@@ -8,7 +8,11 @@ import EnsembleKalmanProcesses.TOMLInterface as TI
88
99export get_prior, initialize, update_ensemble, save_G_ensemble
1010export path_to_ensemble_member,
11- path_to_model_log, path_to_iteration, parameter_path, load_latest_ekp
11+ path_to_model_log,
12+ path_to_iteration,
13+ parameter_path,
14+ load_latest_ekp,
15+ run_initial_ensemble
1216
1317"""
1418 load_ekp_struct(output_dir, iteration)
@@ -308,6 +312,88 @@ function save_eki_and_parameters(eki, output_dir, iteration, prior)
308312 JLD2. save_object (ekp_path (output_dir, iteration), eki)
309313end
310314
315+ """
316+ run_initial_ensemble(
317+ backend::AbstractBackend,
318+ process::EKP.Process,
319+ prior::PD.ParameterDistribution,
320+ output_dir;
321+ ensemble_size = 0,
322+ rng = MersenneTwister(1234),
323+ run_forward_models_kwargs = (),
324+ )
325+
326+ Run the initial ensemble without needing the `EKP.EnsembleKalmanProcess`
327+ object and return the unconstrained parameters of the ensemble.
328+
329+ This is useful if the observations depend on the grid resolution of the
330+ simulation data as the first ensemble can be ran, the observations can be
331+ generated, and the `EKP.EnsembleKalmanProcess` object can be created afterward.
332+
333+ Depending on the `process`, the ensemble size will automatically be determined
334+ (e.g. `EKP.Unscented` or `EKP.TransformUnscented`).
335+
336+ !!! warning "Passing initial ensemble to EKP constructor"
337+ If the process is `EKP.Unscented` or `EKP.TransformUnscented`, you should
338+ not pass it to the `EnsembleKalmanProcess` constructor. Otherwise, you
339+ should pass the initial ensemble to the `EnsembleKalmanProcess` constructor.
340+ If you do not, the calibration results may be incorrect.
341+ """
342+ function run_initial_ensemble ( # TODO : Maybe move this to backends?
343+ backend,
344+ process:: EKP.Process ,
345+ prior:: PD.ParameterDistribution ,
346+ output_dir;
347+ ensemble_size = 0 ,
348+ rng = Random. MersenneTwister (1234 ),
349+ run_forward_models_kwargs = (),
350+ )
351+ # Cannot use last_completed_iteration because the JLD2 files storing the
352+ # G ensemble object and the ekp objects will never exist when calling this
353+ # function
354+ iter0_path = joinpath (output_dir, " iteration_000" )
355+ if isdir (iter0_path)
356+ @info " Detected first iteration. Not running the initial ensemble. If this is not the case, then delete the directory $iter0_path ."
357+ end
358+
359+ initial_ensemble = _construct_intial_unconstrained_ensemble (
360+ process,
361+ prior,
362+ ensemble_size = ensemble_size,
363+ rng = rng,
364+ )
365+
366+ # The size of initial_ensemble is (number of parameters, ensemble members)
367+ # For some processes, the ensemble_size is ignored
368+ ensemble_size = last (size (initial_ensemble))
369+
370+ param_dict = get_param_dict (prior)
371+ TI. save_parameter_ensemble (
372+ initial_ensemble,
373+ prior,
374+ param_dict,
375+ output_dir,
376+ DEFAULT_PARAMETER_FILE,
377+ 0 ,
378+ )
379+
380+ # Cannot save eki object because the goal of this function is to be able
381+ # to run the first ensemble without the eki object
382+ JLD2. save_object (
383+ joinpath (path_to_iteration (output_dir, 0 ), " prior.jld2" ),
384+ prior,
385+ )
386+
387+ run_forward_models (
388+ backend,
389+ 0 ,
390+ ensemble_size;
391+ output_dir = output_dir,
392+ run_forward_models_kwargs... ,
393+ )
394+ return initial_ensemble
395+ end
396+
311397"""
312398 _construct_intial_unconstrained_ensemble(
313399 process::EKP.Process,
0 commit comments