Transitioning IGM from v2 to v3: Guideline
In short
This is a major structural update, and we are starting a new versioning series with IGM 3.0.0. Below are the main changes and improvements you can expect:
-
Hydra integration (game changer!): The most important update is the integration of the Hydra library for handling parameters. This allows you to run large multi-ensemble simulations (poss on multiple GPUs) from a single command line, with full traceability and reproducibility. No more manually managing complex parameter files—Hydra does it for you, and does it extremely well. This alone is a compelling reason to switch to IGM3!
-
YAML-based parameters with hierarchical structure: All parameters are now defined in YAML (instead of JSON), offering a more powerful and flexible configuration format. Especially, parameters are now organized hierarchically, making it much easier to manage large configurations. This comes with renamed parameters, but don’t worry—we provide a tool to convert old JSON files to the new YAML format, along with a conversion table.
-
New documentation website: A freshly built documentation website now automatically collects all parameter definitions, along with their default values, descriptions, and units.
-
Clean folder structure: The working directory is now properly organized into subfolders for parameters, data, user modules, and output.
-
Improved code readability: Key modules like iceflow and data_assimilation (formerly optimize) have been split into sub-files to improve readability, maintainability, and customization.
Here are the important new links:
-
The pre-release is on the usual https://github.com/instructed-glacier-model/igm , but you need to checkout the feature/hydra branch.
-
The new documentation website is here : https://instructed-glacier-model.github.io/igm-doc/
-
The separate repo containing examples : https://github.com/instructed-glacier-model/igm-examples
-
The repo with the current technical paper re-shaped for IGM 3.0.0 : https://github.com/instructed-glacier-model/igm-paper
In more details (for users)
Parameter handling
hydra library replaces parser, and YAML file
Parameters previously managed with the parser library are now handled using the hydra library. The parameter file, which was formerly a JSON file (params.json), has been transitioned to a YAML file (experiment/params.yaml) adhering to the YAML standard. This shift to hydra has significantly simplified the core IGM code. Running IGM now involves executing commands like:
where parameters can be changed within the params.yaml file, or overridden directly in the command line. For example:
From a user perspective, migrating to IGM 3 essentially involves converting the former parameter file params.json into the new experiment/params.yaml format. To facilitate this transition, we provide a utility script named json_to_yaml.py (in the root of IGM repo) that automates the conversion process (you may have to adjust manually, check it afterwards!).
Parameter Naming Changes, and hierarchical construction
Parameter names have been slightly modified. Previously, all parameters included a prefix like iflo to indicate they were associated with the iceflow module. Now, parameters are organized hierarchically by attributes, making the prefix redundant and therefore removed. For example: time_start is now accessible as processes.time.start.
In the iceflow module, parameters have been significantly reorganized to follow a hierarchical structure. To assist with the transition, we provide a script named json_to_yaml.py, and correspondence table to help convert old JSON files into the new YAML format. Also, IGM now raises an error if a parameter contains a typo, and suggests parameters to pick.
Example of new parameter file
Here is what the new parameter file looks like:
# @package _global_
core:
url_data: "https://www.dropbox.com/scl/fo/8ixpy27i67s04bp7uixoq/h?rlkey=0ye7rd4zkcqfhvzx7suunw3bk&dl=0"
defaults:
- override /inputs: [local]
- override /processes: [smb_simple, iceflow, time, thk]
- override /outputs: [local, plot2d]
inputs:
local:
input_file: input.nc
processes:
iceflow:
physics:
init_slidingco: 0.0595
time:
start: 1880.0
end: 2020.0
save: 5.0
outputs:
plot2d:
live: true
The above file will be read by Hydra in IGM and has the following structure:
core: Includes all parameters specific to the core IGM run, such as logging, downloading data prior to the run, GPU-related settings, etc.defaults: Lists the input, process, and output modules to be used.inputs: Contains parameters to override the defaults for input modules.processes: Contains parameters to override the defaults for process modules.outputs: Contains parameters to override the defaults for output modules.
Note: The former module types preprocess, process, and postprocess have been renamed to input, modules, and output, respectively.
Running multiple runs
A great advantage of Hydra is the possibility it provides for running ensemble simulations. For example, the following command sequentially runs two simulations with two different sets of parameters:
Alternatively, if you supply two parameter files (params1 and params2), you can execute:
You can also perform a grid search over multiple parameters. For instance, the following command runs simulations for a 3x2 parameter grid:
In such cases, the output folder will be named multirun instead of output.
New structure of working folder
The working folder is structured as follows:
experiment: Contains the parameter files.data: Stores input data, if any.user: Contains user-defined/custom Python functions or modules.outputormultirun: Contains the results of the IGM runs.
The folder structure looks like this:
├── experiment
│ └── params.yaml
├── data
│ ├── ...
├── user
│ ├── code
│ │ └── processes
│ │ └── mymodule.py
│ └── conf
│ └── processes
│ └── mymodule.yaml
└── output
├── 2025-03-06
│ └── 15-43-37
│ └── 15-44-07
│ └── output.nc
│ └── ...
Integration and Exclusion of Former Modules
-
Splitting of
iceflowmodules intodata_assimilationandpretraining: Theiceflowmodule has been split into two dedicated modules:data_assimilation(formerlyoptimize) andpretraining. This change was made to improve code organization and maintainability, as theiceflowmodule had grown too large. Previously,data_assimilationandpretrainingwere separate but had dependency issues withiceflow. With the new structure, both modules remain dependent oniceflow, but these dependencies are now handled seamlessly. When usingdata_assimilationorpretraining, ensure that theiceflowmodule is also included in your configuration. The order of inclusion does not matter. -
The modules
anim_mayavi,anim_plotly, andanim_videohave been externalized from IGM and moved toutils. These modules were purely for postprocessing and were executed at the very end. To simplify the core structure, they were externalized. -
Modules such as
print_compandprint_infohave been integrated into the core functionality of IGM. -
The
write_particlesfunctionality is now integrated into theparticulemodule.
New local module merging netcdf and tif
A new I/O module, local, has been introduced to replace the load_XXX and write_XXX modules. The local module leverages the xarray library, which is more powerful and supports loading both NetCDF (.nc) and GeoTIFF (.tif) files.
oggm_shop requires coupling with load_ncdf or local
The oggm_shop module now exclusively handles downloading data (e.g., RGIXXXX folders) using OGGM and converting it into a NetCDF file (input.nc) that adheres to IGM's naming conventions. However, it no longer performs the task of loading this data into IGM. To process the downloaded data, you must pair oggm_shop with either the load_ncdf or local modules.
For example, if you use oggm_shop, you must include load_ncdf or local as additional inputs modules in your configuration.
oggm_shop
The oggm_shop module has been substantially re-organized.
Parameters RGI_version and RGI_product were removed since there are directly deduced from the RGI ID
utils re-structuring
The former utils.py file has been re-structured forlder-wise for clarity, this means that some import like
from ..utils import getmag
must be changed to
from igm.utils.math.getmag import getmag
Default Parameter Value Changes (Upcoming Release)
In the upcoming release, several default parameter values will be updated to improve performance and usability. These changes are not applied yet but will be included in the next version:
-
retrain_freq(current default: 10): The current default retrains the ice flow CNN every 10 time steps. This frequency has been found insufficient in many cases. The next release will increase the retraining frequency to every 3 time steps. -
smooth_anisotropy_factor(current default: 0.2): The current value of 0.2 for anisotropic smoothing has been observed to cause chessboard effects in ice thickness. To address this, the next release will safely deactivate anisotropic smoothing by setting this parameter to 1.0. -
convexity_weight(current default: unknown): The current convexity weight, which is particularly useful in the absence of data, has been found to be highly empirical and non-intuitive. As a result, it will be deactivated in the next release by setting its value to 0. -
fix_opti_normalization_issue(current default: false): A normalization issue has been identified in the current cost function for data assimilation, where some terms use sums while others use means. This inconsistency has been compensated for by adjusting regularization parameters. The next release will address this issue by setting this parameter totrue, ensuring consistent use of means throughout. Consequently, users will need to significantly increase the regularization parameters (approximately \(10^3\) for thickness and \(10^{10}\) for sliding coefficients). -
log_slidingco(current default: false): In the next release, the optimization will handle the square root ofslidingco(scaled) instead ofslidingcodirectly. This approach ensures thatslidingcoremains positive without explicitly enforcing positivity. Note that this change will affect the scaling ofslidingco(approximately \(10^{-6}\)) when this option is set totrue. -
`lr_init`` (current default: 0.0001): In the next release, it will be reduced to 0.001 to make the training more agressive.
In more details (for developpers)
Hierachical and separated parameters and code
In IGM source code, the parameters and the code are now hierarchically organized. Default parameters are stored in the igm/igm/conf folder, which is separate from the code located in the igm/igm folder. This separation ensures a clean organization of configuration files and source code. Parameters are grouped into logical categories and subcategories within the YAML files. This structure mirrors the organization of the modules and processes in IGM. For example, the folder structure for default parameters looks like this:
igm/igm/conf
├── inputs
│ └── local.yaml
│ └── ...
├── processes
│ └── iceflow.yaml
│ └── ...
└── outputs
└── plot2d.yaml
└── ...
In the code, all parameters are accessible through the object cfg. For example, cfg.processes.enthalpy.ref_temp refers to a parameter associated with the enthalpy processes module.
On the other hand the structure for the code looks very similar:
igm/igm
├── inputs
│ └── local
│ └── ...
├── processes
│ └── iceflow
│ └── avalanche
└── outputs
└── plot2d
└── ...
Custom modules (now called "user")
User modules are very useful when customizing applications. They can be used to tailor input, process, or output methods. To create such a user module, you need to create (or update) the user folder located at the root of your working directory, ensuring the following hierarchy is respected:
└── user
├── code
│ └── inputs
│ │ └── my_inputs_module
│ │ └── my_inputs_module.py
│ └── processes
│ │ └── my_processes_module
│ │ └── my_processes_module.py
│ └── outputs
│ └── my_outputs_module
│ └── my_outputs_module.py
└── conf
└── inputs
└── my_inputs_module.yaml
└── processes
└── my_processes_module.yaml
└── outputs
└── my_outputs_module.yaml
where my_processes_module.py has the following structure (and requires the definitions of functions initialize, update, and finalize):
def initialize(cfg,state):
...
def update(cfg,state):
cfg.processes.clim_aletsch.time_resolution
...
def finalize(cfg,state):
pass
Note that my_inputs_module.py and my_outputs_module.py only require a single function called run (with the addition of an initialize function for output), defined in the same way as the three functions above.
Parameter files located in conf/inputs, conf/processes, and conf/outputs look like
It is important to note that user modules take precedence over official modules. If a user module shares the same name as an official module, the user module will override the official one, and the official module will be ignored.
How to transition your own user modules?
-
Parameter changes: Update your user module code to replace each parameter reference (e.g.,
params.iflo_exp_glen) with the new naming convention (e.g.,cfg.processes.iceflow.physics.exp_glen) as outlined in the parameter change tables below. -
Function updates: Modify the function argument for
initialize,update, andfinalizeto acceptcfgas an argument instead ofparams. Thestateargument remains unchanged. -
Own parameter: Remove the
params(parser)function that previously defined your parameter list. Instead, transfer your parameter definitions into the appropriate YAML files within theconffolder, following the structure described in the "Custom modules (now called 'user')" section.
Complex modules made more readables, and more customizable
Key modules like iceflow and data_assimilation (formerly optimize) have been split into sub-files to improve readability, maintainability, and customization. Sometimes, you may need to modify an existing built-in module, e.g. to test a new feature in the iceflow emulator/solver, or new cost in the data assimilation. This can be achieved by creating a user module that overrides the built-in functionality. Check at the page on user modules in the documentation.
Parameter changes
Parameter name change table for iceflow module
| Formerly | New name |
|---|---|
| iflo_type | iceflow.method |
| iflo_force_max_velbar | iceflow.force_max_velbar |
| iflo_gravity_cst | iceflow.physics.gravity_cst |
| iflo_ice_density | iceflow.physics.ice_density |
| iflo_init_slidingco | iceflow.physics.init_slidingco |
| iflo_init_arrhenius | iceflow.physics.init_arrhenius |
| iflo_enhancement_factor | iceflow.physics.enhancement_factor |
| iflo_exp_glen | iceflow.physics.exp_glen |
| iflo_exp_weertman | iceflow.physics.exp_weertman |
| iflo_regu_glen | iceflow.physics.regu_glen |
| iflo_regu_weertman | iceflow.physics.regu_weertman |
| iflo_new_friction_param | REMOVED |
| iflo_dim_arrhenius | iceflow.physics.dim_arrhenius |
| iflo_regu | REMOVED |
| iflo_thr_ice_thk | iceflow.physics.thr_ice_thk |
| iflo_min_sr | iceflow.physics.min_sr |
| iflo_max_sr | iceflow.physics.max_sr |
| iflo_force_negative_gravitational_energy | iceflow.physics.force_negative_gravitational_energy |
| iflo_cf_eswn | iceflow.physics.cf_eswn |
| iflo_cf_cond | iceflow.physics.cf_cond |
| iflo_Nz | iceflow.numerics.Nz |
| iflo_vert_spacing | iceflow.numerics.vert_spacing |
| iflo_solve_step_size | iceflow.solver.step_size |
| iflo_solve_nbitmax | iceflow.solver.nbitmax |
| iflo_solve_stop_if_no_decrease | iceflow.solver.stop_if_no_decrease |
| iflo_optimizer_solver | iceflow.solver.optimizer |
| iflo_optimizer_lbfgs | iceflow.solver.lbfgs |
| iflo_save_cost_solver | iceflow.solver.save_cost |
| iflo_fieldin | iceflow.emulator.fieldin |
| iflo_retrain_emulator_freq | iceflow.emulator.retrain_freq |
| iflo_retrain_emulator_lr | iceflow.emulator.lr |
| iflo_retrain_emulator_lr_init | iceflow.emulator.lr_init |
| iflo_retrain_warm_up_it | iceflow.emulator.warm_up_it |
| iflo_retrain_emulator_nbit_init | iceflow.emulator.nbit_init |
| iflo_retrain_emulator_nbit | iceflow.emulator.nbit |
| iflo_retrain_emulator_framesizemax | iceflow.emulator.framesizemax |
| iflo_pretrained_emulator | iceflow.emulator.pretrained |
| iflo_emulator | iceflow.emulator.name |
| iflo_save_model | iceflow.emulator.save_model |
| iflo_exclude_borders | iceflow.emulator.exclude_borders |
| iflo_optimizer_emulator | iceflow.emulator.optimizer |
| iflo_optimizer_emulator_clipnorm | iceflow.emulator.optimizer_clipnorm |
| iflo_optimizer_emulator_epsilon | iceflow.emulator.optimizer_epsilon |
| iflo_save_cost_emulator | iceflow.emulator.save_cost |
| iflo_output_directory | iceflow.emulator.output_directory |
| iflo_network | iceflow.emulator.network.architecture |
| iflo_multiple_window_size | iceflow.emulator.network.multiple_window_size |
| iflo_activation | iceflow.emulator.network.activation |
| iflo_nb_layers | iceflow.emulator.network.nb_layers |
| iflo_nb_blocks | iceflow.emulator.network.nb_blocks |
| iflo_nb_out_filter | iceflow.emulator.network.nb_out_filter |
| iflo_conv_ker_size | iceflow.emulator.network.conv_ker_size |
| iflo_dropout_rate | iceflow.emulator.network.dropout_rate |
| iflo_weight_initialization | iceflow.emulator.network.weight_initialization |
Parameter name change table for optimize (data_assimilation) module
| Formerly | New name |
|---|---|
| opti_control | data_assimilation.control_list |
| opti_cost | data_assimilation.cost_list |
| opti_nbitmin | data_assimilation.optimization.nbitmin |
| opti_nbitmax | data_assimilation.optimization.nbitmax |
| opti_step_size | data_assimilation.optimization.step_size |
| opti_step_size_decay | data_assimilation.optimization.step_size_decay |
| opti_init_zero_thk | data_assimilation.optimization.init_zero_thk |
| opti_sole_mask | data_assimilation.optimization.sole_mask |
| opti_retrain_iceflow_model | data_assimilation.optimization.retrain_iceflow_model |
| opti_fix_opti_normalization_issue | data_assimilation.optimization.fix_opti_normalization_issue |
| opti_regu_param_thk | data_assimilation.regularization.thk |
| opti_regu_param_slidingco | data_assimilation.regularization.slidingco |
| opti_regu_param_arrhenius | data_assimilation.regularization.arrhenius |
| opti_regu_param_div | data_assimilation.regularization.divflux |
| opti_smooth_anisotropy_factor | data_assimilation.regularization.smooth_anisotropy_factor |
| opti_smooth_anisotropy_factor_sl | data_assimilation.regularization.smooth_anisotropy_factor_sl |
| opti_convexity_weight | data_assimilation.regularization.convexity_weight |
| opti_convexity_power | data_assimilation.regularization.convexity_power |
| opti_to_regularize | data_assimilation.regularization.to_regularize |
| opti_usurfobs_std | data_assimilation.fitting.usurfobs_std |
| opti_velsurfobs_std | data_assimilation.fitting.velsurfobs_std |
| opti_thkobs_std | data_assimilation.fitting.thkobs_std |
| opti_divfluxobs_std | data_assimilation.fitting.divfluxobs_std |
| opti_uniformize_thkobs | data_assimilation.fitting.uniformize_thkobs |
| opti_include_low_speed_term | data_assimilation.fitting.include_low_speed_term |
| opti_velsurfobs_thr | data_assimilation.fitting.velsurfobs_thr |
| opti_log_slidingco | data_assimilation.fitting.log_slidingco |
| opti_divflux_method | data_assimilation.divflux.method |
| opti_force_zero_sum_divflux | data_assimilation.divflux.force_zero_sum |
| opti_scaling_thk | data_assimilation.scaling.thk |
| opti_scaling_usurf | data_assimilation.scaling.usurf |
| opti_scaling_slidingco | data_assimilation.scaling.slidingco |
| opti_scaling_arrhenius | data_assimilation.scaling.arrhenius |
| opti_output_freq | data_assimilation.output.freq |
| opti_plot2d_live | data_assimilation.output.plot2d_live |
| opti_plot2d | data_assimilation.output.plot2d |
| opti_save_result_in_ncdf | data_assimilation.output.save_result_in_ncdf |
| opti_save_iterat_in_ncdf | data_assimilation.output.save_iterat_in_ncdf |
| opti_editor_plot2d | data_assimilation.output.editor_plot2d |
| opti_vars_to_save | data_assimilation.output.vars_to_save |
| opti_infer_params | data_assimilation.cook.infer_params |
| opti_tidewater_glacier | data_assimilation.cook.tidewater_glacier |
| opti_vol_std | data_assimilation.cook.vol_std |