Skip to content

Commit 3c3dce3

Browse files
Add log-uniform sampling method
1 parent fba3b5c commit 3c3dce3

4 files changed

Lines changed: 64 additions & 48 deletions

File tree

compass/landice/tests/ensemble_generator/ensemble_templates/default/spinup/ensemble_generator.cfg

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,26 @@ ensemble_template = default
1111
# Additional runs can be added and run to an existing ensemble
1212
# without affecting existing runs, but trying to set up a run
1313
# that already exists will generate a warning and skip that run.
14-
# If using uniform sampling, start_run should be 0 and end_run should be
15-
# equal to (max_samples - 1), otherwise unexpected behavior may result.
14+
# If using uniform or log-uniform sampling, start_run should be 0 and
15+
# end_run should be equal to (max_samples - 1), otherwise unexpected
16+
# behavior may result.
1617
# These values do not affect viz/analysis, which will include any
1718
# runs it finds.
1819
start_run = 0
1920
end_run = 3
2021

21-
# sampling_method can be either 'sobol' for a space-filling Sobol sequence
22-
# or 'uniform' for uniform sampling. Uniform sampling is most appropriate
23-
# for a single parameter sensitivity study. It will sample uniformly across
24-
# all dimensions simultaneously, thus sampling only a small fraction of
25-
# parameter space
22+
# sampling_method can be 'sobol' for a space-filling Sobol sequence,
23+
# 'uniform' for linear sampling, or 'log-uniform' for logarithmic sampling.
24+
# Uniform and log-uniform are most appropriate for a single-parameter
25+
# sensitivity study because they sample each active parameter using the
26+
# same rank ordering, thus sampling only a small fraction of parameter space
27+
# in higher dimensions.
2628
sampling_method = sobol
2729

2830
# maximum number of samples to be considered.
2931
# max_samples needs to be greater or equal to (end_run + 1)
30-
# When using uniform sampling, max_samples should equal (end_run + 1).
32+
# When using uniform or log-uniform sampling, max_samples should equal
33+
# (end_run + 1).
3134
# When using Sobol sequence, max_samples ought to be a power of 2.
3235
# max_samples should not be changed after the first set of ensemble.
3336
# So, when using Sobol sequence, max_samples might be set larger than

compass/landice/tests/ensemble_generator/spinup_ensemble/__init__.py

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,10 @@ def configure(self):
9393
if max_samples < self.end_run:
9494
sys.exit("ERROR: max_samples is exceeded by end_run")
9595
sampling_method = section.get('sampling_method')
96-
param_unit_values = _sample_parameter_unit_values(
97-
sampling_method=sampling_method, n_params=n_params,
98-
max_samples=max_samples)
99-
10096
parameter_specs = _populate_parameter_vectors(
101-
parameter_specs, param_unit_values)
97+
parameter_specs=parameter_specs,
98+
sampling_method=sampling_method,
99+
max_samples=max_samples)
102100

103101
spec_by_name = {spec['name']: spec for spec in parameter_specs}
104102

@@ -181,45 +179,51 @@ def _get_parameter_specs(section):
181179
return specs
182180

183181

184-
def _sample_parameter_unit_values(sampling_method, n_params, max_samples):
185-
"""Create an ``(max_samples, n_params)`` array in unit space.
182+
def _populate_parameter_vectors(parameter_specs, sampling_method,
183+
max_samples):
184+
"""Generate and scale samples to each parameter range.
186185
187-
The returned values are in the range ``[0, 1]`` and are later scaled to
188-
each parameter's configured min/max bounds.
186+
This function updates each ``spec['vec']`` in ``parameter_specs`` and
187+
returns the same list for explicit readability at call site.
188+
``sobol`` creates a space-filling sequence in unit space,
189+
``uniform`` creates linearly spaced samples, and ``log-uniform`` samples
190+
linearly in log10 space (requiring strictly positive bounds).
189191
190192
Returns
191193
-------
192-
numpy.ndarray
193-
Unit-space samples with shape ``(max_samples, n_params)``.
194+
list of dict
195+
The same ``parameter_specs`` list with each ``spec['vec']`` populated.
194196
"""
197+
n_params = len(parameter_specs)
195198
if sampling_method == 'sobol':
196199
print(f"Generating Sobol sequence for {n_params} parameter(s)")
197200
sampler = qmc.Sobol(d=n_params, scramble=True, seed=4)
198-
return sampler.random(n=max_samples)
199-
200-
if sampling_method == 'uniform':
201-
print(f"Generating uniform sampling for {n_params} parameter(s)")
201+
param_unit_values = sampler.random(n=max_samples)
202+
elif sampling_method in {'uniform', 'log-uniform'}:
203+
print(f"Generating {sampling_method} sampling for "
204+
f"{n_params} parameter(s)")
202205
samples = np.linspace(0.0, 1.0, max_samples).reshape(-1, 1)
203-
return np.tile(samples, (1, n_params))
204-
205-
sys.exit("ERROR: Unsupported sampling method specified.")
206-
206+
param_unit_values = np.tile(samples, (1, n_params))
207+
else:
208+
sys.exit("ERROR: Unsupported sampling method specified.")
207209

208-
def _populate_parameter_vectors(parameter_specs, param_unit_values):
209-
"""Scale unit samples to configured parameter ranges.
210+
if sampling_method == 'log-uniform':
211+
for spec in parameter_specs:
212+
if spec['min'] <= 0.0 or spec['max'] <= 0.0:
213+
sys.exit(
214+
"ERROR: log-uniform sampling requires positive min/max "
215+
f"for parameter '{spec['name']}'.")
210216

211-
This function updates each ``spec['vec']`` in ``parameter_specs`` and
212-
returns the same list for explicit readability at call site.
213-
214-
Returns
215-
-------
216-
list of dict
217-
The same ``parameter_specs`` list with each ``spec['vec']`` populated.
218-
"""
219217
for idx, spec in enumerate(parameter_specs):
220218
print('Including parameter ' + spec['name'])
221-
spec['vec'] = param_unit_values[:, idx] * \
222-
(spec['max'] - spec['min']) + spec['min']
219+
if sampling_method == 'log-uniform':
220+
log_min = np.log10(spec['min'])
221+
log_max = np.log10(spec['max'])
222+
spec['vec'] = 10.0 ** (param_unit_values[:, idx] *
223+
(log_max - log_min) + log_min)
224+
else:
225+
spec['vec'] = param_unit_values[:, idx] * \
226+
(spec['max'] - spec['min']) + spec['min']
223227
return parameter_specs
224228

225229

docs/developers_guide/landice/test_groups/ensemble_generator.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ Spinup run-control options (for example, ``start_run``, ``end_run``,
125125
are read from ``[ensemble_generator]``, while spinup resource paths and
126126
related values (for example ``input_file_path`` and ``iceshelf_area_obs``)
127127
are read from ``[spinup_ensemble]``.
128+
Supported sampling methods are ``sobol``, ``uniform``, and ``log-uniform``.
128129
The values for each parameter are
129130
passed to the ``EnsembleMember`` constructor to define each run.
130131

docs/users_guide/landice/test_groups/ensemble_generator.rst

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ ensemble_generator
66
The ``landice/ensemble_generator`` test group creates ensembles of MALI
77
simulations with different parameter values. The ensemble framework
88
sets up a user-defined number of simulations with parameter values selected
9-
from either uniform sampling or a space-filling Sobol sequence.
9+
from uniform sampling, log-uniform sampling, or a space-filling Sobol
10+
sequence.
1011

1112
A test case in this test group consists of a number of ensemble members,
1213
and one ensemble manager.
@@ -157,23 +158,27 @@ The template-specific spinup config options (from
157158
# Additional runs can be added and run to an existing ensemble
158159
# without affecting existing runs, but trying to set up a run
159160
# that already exists will generate a warning and skip that run.
160-
# If using uniform sampling, start_run should be 0 and end_run should be
161-
# equal to (max_samples - 1), otherwise unexpected behavior may result.
161+
# If using uniform or log-uniform sampling, start_run should be 0 and
162+
# end_run should be equal to (max_samples - 1), otherwise unexpected
163+
# behavior may result.
162164
# These values do not affect viz/analysis, which will include any
163165
# runs it finds.
164166
start_run = 0
165167
end_run = 3
166168
167-
# sampling_method can be either 'sobol' for a space-filling Sobol sequence
168-
# or 'uniform' for uniform sampling. Uniform sampling is most appropriate
169-
# for a single parameter sensitivity study. It will sample uniformly across
170-
# all dimensions simultaneously, thus sampling only a small fraction of
171-
# parameter space
169+
# sampling_method can be 'sobol' for a space-filling Sobol sequence,
170+
# 'uniform' for linear sampling, or 'log-uniform' for logarithmic
171+
# sampling between min and max parameter bounds.
172+
# Uniform and log-uniform are most appropriate for a single-parameter
173+
# sensitivity study because they sample each active parameter using the
174+
# same rank ordering, thus sampling only a small fraction of parameter
175+
# space in higher dimensions.
172176
sampling_method = sobol
173177
174178
# maximum number of samples to be considered.
175179
# max_samples needs to be greater or equal to (end_run + 1)
176-
# When using uniform sampling, max_samples should equal (end_run + 1).
180+
# When using uniform or log-uniform sampling, max_samples should equal
181+
# (end_run + 1).
177182
# When using Sobol sequence, max_samples ought to be a power of 2.
178183
# max_samples should not be changed after the first set of ensemble.
179184
# So, when using Sobol sequence, max_samples might be set larger than
@@ -238,6 +243,9 @@ The parameter sampling definitions live in a separate section,
238243
dimension ordering, special parameters are unprefixed, and namelist
239244
parameters use the ``nl.`` prefix with a companion ``.option_name``.
240245

246+
For ``log-uniform`` sampling, each parameter bound must be strictly
247+
positive because sampling is performed in log space.
248+
241249
.. code-block:: cfg
242250
243251
[ensemble.parameters]

0 commit comments

Comments
 (0)