igm-model 2.1.0__tar.gz → 2.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {igm-model-2.1.0/igm_model.egg-info → igm-model-2.2.1}/PKG-INFO +12 -8
- {igm-model-2.1.0 → igm-model-2.2.1}/README.md +8 -4
- igm-model-2.2.1/igm/__init__.py +28 -0
- igm-model-2.2.1/igm/common.py +380 -0
- igm-model-2.2.1/igm/igm_run.py +47 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/instructed_oggm.py +12 -4
- {igm-model-2.1.0/igm/modules/preproc → igm-model-2.2.1/igm/modules}/__init__.py +6 -0
- igm-model-2.2.1/igm/modules/postproc/anim_mayavi/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/anim_mayavi}/anim_mayavi.py +8 -13
- igm-model-2.2.1/igm/modules/postproc/anim_plotly/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/anim_plotly}/anim_plotly.py +27 -26
- igm-model-2.2.1/igm/modules/postproc/anim_video/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/anim_video}/anim_video.py +8 -14
- igm-model-2.2.1/igm/modules/postproc/plot2d/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/plot2d}/plot2d.py +6 -13
- igm-model-2.2.1/igm/modules/postproc/print_comp/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/print_comp}/print_comp.py +12 -29
- igm-model-2.2.1/igm/modules/postproc/print_info/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/print_info}/print_info.py +4 -4
- igm-model-2.2.1/igm/modules/postproc/write_ncdf/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/write_ncdf}/write_ncdf.py +10 -22
- igm-model-2.2.1/igm/modules/postproc/write_particles/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/write_particles}/write_particles.py +10 -16
- igm-model-2.2.1/igm/modules/postproc/write_tif/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/write_tif}/write_tif.py +5 -7
- igm-model-2.2.1/igm/modules/postproc/write_ts/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/postproc/write_ts}/write_ts.py +8 -22
- igm-model-2.2.1/igm/modules/preproc/__init__.py +24 -0
- igm-model-2.2.1/igm/modules/preproc/include_icemask/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/preproc → igm-model-2.2.1/igm/modules/preproc/include_icemask}/include_icemask.py +4 -4
- igm-model-2.2.1/igm/modules/preproc/infersmb.py +44 -0
- igm-model-2.2.1/igm/modules/preproc/load_ncdf/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/preproc → igm-model-2.2.1/igm/modules/preproc/load_ncdf}/load_ncdf.py +6 -6
- igm-model-2.2.1/igm/modules/preproc/load_tif/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/preproc → igm-model-2.2.1/igm/modules/preproc/load_tif}/load_tif.py +5 -5
- igm-model-2.2.1/igm/modules/preproc/oggm_shop/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/preproc → igm-model-2.2.1/igm/modules/preproc/oggm_shop}/oggm_shop.py +62 -28
- igm-model-2.2.1/igm/modules/preproc/optimize/__init__.py +8 -0
- {igm-model-2.1.0/igm/modules/preproc → igm-model-2.2.1/igm/modules/preproc/optimize}/optimize.py +186 -114
- igm-model-2.2.1/igm/modules/preproc/optimize_v1/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/preproc → igm-model-2.2.1/igm/modules/preproc/optimize_v1}/optimize_v1.py +12 -6
- igm-model-2.2.1/igm/modules/preproc/pretraining/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/preproc → igm-model-2.2.1/igm/modules/preproc/pretraining}/pretraining.py +22 -22
- {igm-model-2.1.0/igm/modules/postproc → igm-model-2.2.1/igm/modules/process}/__init__.py +2 -0
- igm-model-2.2.1/igm/modules/process/clim_oggm/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/clim_oggm}/clim_oggm.py +7 -6
- igm-model-2.2.1/igm/modules/process/flow_dt_thk/__init__.py +6 -0
- igm-model-2.2.1/igm/modules/process/flow_dt_thk/flow_dt_thk.py +32 -0
- igm-model-2.2.1/igm/modules/process/glerosion/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/glerosion}/glerosion.py +4 -4
- igm-model-2.2.1/igm/modules/process/iceflow/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/iceflow}/iceflow.py +243 -53
- igm-model-2.2.1/igm/modules/process/iceflow_v1/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/iceflow_v1}/iceflow_v1.py +4 -4
- igm-model-2.2.1/igm/modules/process/particles/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/particles}/particles.py +7 -6
- igm-model-2.2.1/igm/modules/process/particles_v1/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/particles_v1}/particles_v1.py +4 -4
- igm-model-2.2.1/igm/modules/process/read_output.py +99 -0
- igm-model-2.2.1/igm/modules/process/rockflow/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/rockflow}/rockflow.py +4 -4
- igm-model-2.2.1/igm/modules/process/smb_oggm/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/smb_oggm}/smb_oggm.py +4 -4
- igm-model-2.2.1/igm/modules/process/smb_simple/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/smb_simple}/smb_simple.py +5 -5
- igm-model-2.2.1/igm/modules/process/thk/__init__.py +6 -0
- igm-model-2.2.1/igm/modules/process/thk/thk.py +73 -0
- igm-model-2.2.1/igm/modules/process/time/__init__.py +6 -0
- {igm-model-2.1.0/igm/modules/process → igm-model-2.2.1/igm/modules/process/time}/time.py +4 -4
- igm-model-2.2.1/igm/modules/process/vert_flow/__init__.py +6 -0
- igm-model-2.2.1/igm/modules/process/vert_flow/vert_flow.py +146 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/modules/utils.py +85 -17
- {igm-model-2.1.0 → igm-model-2.2.1/igm_model.egg-info}/PKG-INFO +12 -8
- igm-model-2.2.1/igm_model.egg-info/SOURCES.txt +125 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm_model.egg-info/requires.txt +2 -2
- igm-model-2.2.1/igm_model.egg-info/top_level.txt +2 -0
- igm-model-2.2.1/setup.py +47 -0
- igm-model-2.2.1/tests/__init__.py +3 -0
- igm-model-2.2.1/tests/test_modules/__init__.py +2 -0
- igm-model-2.2.1/tests/test_modules/invalid_custom_module_folder/__init__.py +6 -0
- igm-model-2.2.1/tests/test_modules/invalid_custom_module_folder/invalid_custom_module.py +27 -0
- igm-model-2.2.1/tests/test_modules/missing_function_custom_module.py +28 -0
- igm-model-2.2.1/tests/test_modules/test_loading_modules.py +24 -0
- igm-model-2.2.1/tests/test_modules/valid_custom_module.py +27 -0
- igm-model-2.2.1/tests/test_modules/valid_custom_module_folder/__init__.py +6 -0
- igm-model-2.2.1/tests/test_modules/valid_custom_module_folder/valid_custom_module.py +27 -0
- igm-model-2.2.1/tests/test_params/__init__.py +0 -0
- igm-model-2.2.1/tests/test_params/test_params.py +183 -0
- igm-model-2.1.0/igm/__init__.py +0 -44
- igm-model-2.1.0/igm/common.py +0 -187
- igm-model-2.1.0/igm/igm_run.py +0 -72
- igm-model-2.1.0/igm/modules/process/__init__.py +0 -4
- igm-model-2.1.0/igm/modules/process/avalanche.py +0 -124
- igm-model-2.1.0/igm/modules/process/enthalpy.py +0 -749
- igm-model-2.1.0/igm/modules/process/flow_dt_thk.py +0 -32
- igm-model-2.1.0/igm/modules/process/gflex.py +0 -80
- igm-model-2.1.0/igm/modules/process/thk.py +0 -55
- igm-model-2.1.0/igm/modules/process/vert_flow.py +0 -77
- igm-model-2.1.0/igm_model.egg-info/SOURCES.txt +0 -85
- igm-model-2.1.0/igm_model.egg-info/top_level.txt +0 -1
- igm-model-2.1.0/setup.py +0 -48
- {igm-model-2.1.0 → igm-model-2.2.1}/LICENSE +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/100/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/100/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/100/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/200/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/200/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/200/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/50/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/50/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/50/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/f15_cfsflow_GJ_22_a/README.md +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_16_3_1/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_16_3_1/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_16_3_1/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_2_0/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_2_0/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_2_0/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_2_1/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_2_1/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_2_1/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_3_0/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_3_0/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_3_0/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_3_1/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_3_1/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_16_32_3_1/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_8_32_2_0/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_8_32_2_0/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_8_32_2_0/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_8_32_2_1/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_8_32_2_1/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_10_4_cnn_8_32_2_1/model.h5 +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_30_4_cnn_12_32_3_1/fieldin.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_30_4_cnn_12_32_3_1/fieldout.dat +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm/emulators/pinnbp_30_4_cnn_12_32_3_1/model.h5 +0 -0
- {igm-model-2.1.0/igm/modules → igm-model-2.2.1/igm/modules/postproc}/__init__.py +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm_model.egg-info/dependency_links.txt +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/igm_model.egg-info/entry_points.txt +0 -0
- {igm-model-2.1.0 → igm-model-2.2.1}/setup.cfg +0 -0
|
@@ -1,44 +1,49 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: igm-model
|
|
3
|
-
Version: 2.1
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: IGM - a glacier evolution model
|
|
5
5
|
Home-page: https://github.com/jouvetg/igm
|
|
6
6
|
Author: Guillaume Jouvet
|
|
7
7
|
Author-email: guillaume.jouvet@unil.ch
|
|
8
8
|
License: gpl-3.0
|
|
9
|
-
Requires-Python: <3.
|
|
9
|
+
Requires-Python: <3.11
|
|
10
10
|
Description-Content-Type: text/markdown
|
|
11
11
|
License-File: LICENSE
|
|
12
|
+
Requires-Dist: tensorflow[and-cuda]==2.14.0
|
|
12
13
|
Requires-Dist: matplotlib
|
|
13
|
-
Requires-Dist: numpy
|
|
14
14
|
Requires-Dist: scipy
|
|
15
|
-
Requires-Dist: tensorflow==2.12.0
|
|
16
15
|
Requires-Dist: netCDF4
|
|
17
16
|
Requires-Dist: xarray
|
|
18
17
|
Requires-Dist: rasterio
|
|
19
18
|
Requires-Dist: pyproj
|
|
20
19
|
Requires-Dist: geopandas
|
|
21
20
|
Requires-Dist: oggm
|
|
21
|
+
Requires-Dist: salem
|
|
22
22
|
Requires-Dist: importlib_resources
|
|
23
23
|
|
|
24
24
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
25
25
|
### <h1 align="center" id="title">The Instructed Glacier Model (IGM) </h1>
|
|
26
|
+
|
|
27
|
+
<div align="center">
|
|
28
|
+
<img src="logo/logo_igm.svg" width="40%" alt="Alt text">
|
|
29
|
+
</div>
|
|
30
|
+
|
|
26
31
|
|
|
27
32
|
# Overview
|
|
28
33
|
|
|
29
34
|
The Instructed Glacier Model (IGM) is an **open-source Python package**, which permits to simulate **3D glacier evolution** accounting for the coupling between ice thermo-dynamics, surface mass balance, and mass conservation. IGM features:
|
|
30
35
|
|
|
31
|
-
- **
|
|
36
|
+
- **Accessibility and modularity:** IGM is implemented in the most popular programming language -- Python -- and takes large benefit of existing tools such as [OGGM](https://oggm.org/). It is organized **module-wise** to facilitate coupling, customization and commmunity development. For simplicity, IGM uses a horizontal regular grid for numerical discretization and therefore deals with **2D gridded input and output data**.
|
|
32
37
|
|
|
33
38
|
- **State-of-the-art physics:** IGM implements mass conservation, **high-order** 3D ice flow mechanics, an **Enthalpy** model for the thermic regime of ice, **melt/accumulation surface mass balance** model, and other glaciological processes.
|
|
34
39
|
|
|
35
|
-
- **Computational
|
|
40
|
+
- **Computational efficiency:** Thanks to the **TensorFlow library**, mathematical operations are **fully-vectorized**. This permits tremendous **speed-ups on GPU**. **Physics-informed deep learning** is used as an alternative to numerical solvers for modelling ice flow physics in a vectorized way. While GPU are highly-recommended for modelling large domain / high resolution, IGM runs fairly well on CPU for individual glaciers.
|
|
36
41
|
|
|
37
42
|
- **Automatic differentiation:** TensorFlow operations are differentiable. Therefore, automatic differentiation strongly facilitates and speeds-up inverse modelling / data assimilation.
|
|
38
43
|
|
|
39
44
|
# Documentation
|
|
40
45
|
|
|
41
|
-
Start with the 10-min [video tutorial](https://vimeo.com/884003820). Then, all the documentation can be found on the dedicated [wiki](https://github.com/jouvetg/igm/wiki) and the the in-progress [
|
|
46
|
+
Start with the 10-min [video tutorial](https://vimeo.com/884003820). Then, all the documentation can be found on the dedicated [wiki](https://github.com/jouvetg/igm/wiki) and the the in-progress and open-to-contributions [technical paper](https://github.com/jouvetg/igm-paper/paper.pdf).
|
|
42
47
|
|
|
43
48
|
# Discord channel
|
|
44
49
|
|
|
@@ -47,4 +52,3 @@ IGM has a [discord channel](https://discord.com/) for quick support, getting lat
|
|
|
47
52
|
# Contact
|
|
48
53
|
|
|
49
54
|
Feel free to drop me an email for any questions, bug reports, or ideas of model extension: guillaume.jouvet at unil.ch
|
|
50
|
-
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
2
2
|
### <h1 align="center" id="title">The Instructed Glacier Model (IGM) </h1>
|
|
3
|
+
|
|
4
|
+
<div align="center">
|
|
5
|
+
<img src="logo/logo_igm.svg" width="40%" alt="Alt text">
|
|
6
|
+
</div>
|
|
7
|
+
|
|
3
8
|
|
|
4
9
|
# Overview
|
|
5
10
|
|
|
6
11
|
The Instructed Glacier Model (IGM) is an **open-source Python package**, which permits to simulate **3D glacier evolution** accounting for the coupling between ice thermo-dynamics, surface mass balance, and mass conservation. IGM features:
|
|
7
12
|
|
|
8
|
-
- **
|
|
13
|
+
- **Accessibility and modularity:** IGM is implemented in the most popular programming language -- Python -- and takes large benefit of existing tools such as [OGGM](https://oggm.org/). It is organized **module-wise** to facilitate coupling, customization and commmunity development. For simplicity, IGM uses a horizontal regular grid for numerical discretization and therefore deals with **2D gridded input and output data**.
|
|
9
14
|
|
|
10
15
|
- **State-of-the-art physics:** IGM implements mass conservation, **high-order** 3D ice flow mechanics, an **Enthalpy** model for the thermic regime of ice, **melt/accumulation surface mass balance** model, and other glaciological processes.
|
|
11
16
|
|
|
12
|
-
- **Computational
|
|
17
|
+
- **Computational efficiency:** Thanks to the **TensorFlow library**, mathematical operations are **fully-vectorized**. This permits tremendous **speed-ups on GPU**. **Physics-informed deep learning** is used as an alternative to numerical solvers for modelling ice flow physics in a vectorized way. While GPU are highly-recommended for modelling large domain / high resolution, IGM runs fairly well on CPU for individual glaciers.
|
|
13
18
|
|
|
14
19
|
- **Automatic differentiation:** TensorFlow operations are differentiable. Therefore, automatic differentiation strongly facilitates and speeds-up inverse modelling / data assimilation.
|
|
15
20
|
|
|
16
21
|
# Documentation
|
|
17
22
|
|
|
18
|
-
Start with the 10-min [video tutorial](https://vimeo.com/884003820). Then, all the documentation can be found on the dedicated [wiki](https://github.com/jouvetg/igm/wiki) and the the in-progress [
|
|
23
|
+
Start with the 10-min [video tutorial](https://vimeo.com/884003820). Then, all the documentation can be found on the dedicated [wiki](https://github.com/jouvetg/igm/wiki) and the the in-progress and open-to-contributions [technical paper](https://github.com/jouvetg/igm-paper/paper.pdf).
|
|
19
24
|
|
|
20
25
|
# Discord channel
|
|
21
26
|
|
|
@@ -24,4 +29,3 @@ IGM has a [discord channel](https://discord.com/) for quick support, getting lat
|
|
|
24
29
|
# Contact
|
|
25
30
|
|
|
26
31
|
Feel free to drop me an email for any questions, bug reports, or ideas of model extension: guillaume.jouvet at unil.ch
|
|
27
|
-
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2021-2023 Guillaume Jouvet <guillaume.jouvet@unil.ch>
|
|
4
|
+
# Published under the GNU GPL (Version 3), check at the LICENSE file
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import os
|
|
8
|
+
sys.path.append(os.getcwd()) # I guess by default sys.path does not have cwd. not sure if this is the convention though...
|
|
9
|
+
|
|
10
|
+
from . import modules, emulators
|
|
11
|
+
|
|
12
|
+
from .common import (
|
|
13
|
+
State,
|
|
14
|
+
params_core,
|
|
15
|
+
load_modules,
|
|
16
|
+
add_logger,
|
|
17
|
+
print_params,
|
|
18
|
+
load_dependent_modules,
|
|
19
|
+
get_modules_list,
|
|
20
|
+
load_user_defined_params,
|
|
21
|
+
run_intializers,
|
|
22
|
+
run_processes,
|
|
23
|
+
run_finalizers,
|
|
24
|
+
setup_igm_modules,
|
|
25
|
+
setup_igm_params,
|
|
26
|
+
add_logger,
|
|
27
|
+
print_gpu_info
|
|
28
|
+
)
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Copyright (C) 2021-2023 Guillaume Jouvet <guillaume.jouvet@unil.ch>
|
|
5
|
+
Published under the GNU GPL (Version 3), check at the LICENSE file
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os, json
|
|
9
|
+
from json import JSONDecodeError
|
|
10
|
+
import importlib
|
|
11
|
+
import argparse
|
|
12
|
+
from argparse import ArgumentParser, Namespace
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from functools import partial
|
|
15
|
+
from typing import List, Any, Dict, Tuple
|
|
16
|
+
from types import ModuleType
|
|
17
|
+
import logging
|
|
18
|
+
import warnings
|
|
19
|
+
|
|
20
|
+
import tensorflow as tf
|
|
21
|
+
|
|
22
|
+
import igm
|
|
23
|
+
|
|
24
|
+
IGM_DESCRIPTION = r"""
|
|
25
|
+
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
|
|
26
|
+
│ Welcome to IGM! The Iceflow Glacier Model (IGM) is a modular, open-source, and user-friendly glacier model. │
|
|
27
|
+
│ It is designed to be used in a variety of applications, including glacier evolution, ice flow, and ice │
|
|
28
|
+
│ dynamics. │
|
|
29
|
+
│ │
|
|
30
|
+
│ __/\\\\\\\\\\\_____/\\\\\\\\\\\\__/\\\\____________/\\\\_ │
|
|
31
|
+
│ _\/////\\\///____/\\\//////////__\/\\\\\\________/\\\\\\_ │
|
|
32
|
+
│ _____\/\\\______/\\\_____________\/\\\//\\\____/\\\//\\\_ │
|
|
33
|
+
│ _____\/\\\_____\/\\\____/\\\\\\\_\/\\\\///\\\/\\\/_\/\\\_ │
|
|
34
|
+
│ _____\/\\\_____\/\\\___\/////\\\_\/\\\__\///\\\/___\/\\\_ │
|
|
35
|
+
│ _____\/\\\_____\/\\\_______\/\\\_\/\\\____\///_____\/\\\_ │
|
|
36
|
+
│ _____\/\\\_____\/\\\_______\/\\\_\/\\\_____________\/\\\_ │
|
|
37
|
+
│ __/\\\\\\\\\\\_\//\\\\\\\\\\\\/__\/\\\_____________\/\\\_ │
|
|
38
|
+
│ _\///////////___\////////////____\///______________\///__ │
|
|
39
|
+
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class State:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# this create core parameters for any IGM run
|
|
48
|
+
def params_core() -> argparse.ArgumentParser:
|
|
49
|
+
parser = ArgumentParser(
|
|
50
|
+
description=IGM_DESCRIPTION,
|
|
51
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
52
|
+
conflict_handler="resolve",
|
|
53
|
+
) # automatically overrides repeated/older parameters! Valid solution?
|
|
54
|
+
|
|
55
|
+
parser.add_argument(
|
|
56
|
+
"--param_file",
|
|
57
|
+
type=str,
|
|
58
|
+
default="params.json",
|
|
59
|
+
help="Path for the JSON parameter file. (default: %(default)s)",
|
|
60
|
+
)
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
"--modules_preproc",
|
|
63
|
+
type=list,
|
|
64
|
+
default=["oggm_shop"],
|
|
65
|
+
help="List of pre-processing modules (default: %(default)s)",
|
|
66
|
+
)
|
|
67
|
+
parser.add_argument(
|
|
68
|
+
"--modules_process",
|
|
69
|
+
type=list,
|
|
70
|
+
default=["iceflow", "time", "thk"],
|
|
71
|
+
help="List of processing modules (default: %(default)s)",
|
|
72
|
+
)
|
|
73
|
+
parser.add_argument(
|
|
74
|
+
"--modules_postproc",
|
|
75
|
+
type=list,
|
|
76
|
+
default=["write_ncdf", "plot2d", "print_info"],
|
|
77
|
+
help="List of post-processing modules (default: %(default)s)",
|
|
78
|
+
)
|
|
79
|
+
parser.add_argument(
|
|
80
|
+
"--logging",
|
|
81
|
+
action="store_true",
|
|
82
|
+
default=False,
|
|
83
|
+
help="Activates the logging (default: %(default)s)",
|
|
84
|
+
)
|
|
85
|
+
parser.add_argument(
|
|
86
|
+
"--logging_level",
|
|
87
|
+
default=30,
|
|
88
|
+
type=int,
|
|
89
|
+
help="Determine logging level used for logger (default: %(default)s)",
|
|
90
|
+
)
|
|
91
|
+
parser.add_argument(
|
|
92
|
+
"--logging_file",
|
|
93
|
+
type=str,
|
|
94
|
+
default="",
|
|
95
|
+
help="Logging file name, if empty it prints in the screen (default: %(default)s)",
|
|
96
|
+
)
|
|
97
|
+
parser.add_argument(
|
|
98
|
+
"--print_params",
|
|
99
|
+
action="store_false",
|
|
100
|
+
default=True,
|
|
101
|
+
help="Print definitive parameters in a file for record (default: %(default)s)",
|
|
102
|
+
)
|
|
103
|
+
parser.add_argument(
|
|
104
|
+
"--gpu_info",
|
|
105
|
+
action="store_true",
|
|
106
|
+
default=False,
|
|
107
|
+
help="Print CUDA and GPU information to the screen (default: %(default)s)",
|
|
108
|
+
)
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"--gpu_id",
|
|
111
|
+
type=int,
|
|
112
|
+
default=0,
|
|
113
|
+
help="Id of the GPU to use (default: %(default)s)",
|
|
114
|
+
)
|
|
115
|
+
parser.add_argument(
|
|
116
|
+
"--saved_params_filename",
|
|
117
|
+
type=str,
|
|
118
|
+
default="params_saved",
|
|
119
|
+
help="Name of the file to store the parameters used in the run (default: %(default)s)",
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
return parser
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def setup_igm_modules(params: Namespace) -> List[ModuleType]:
|
|
126
|
+
|
|
127
|
+
modules_dict = get_modules_list(params.param_file)
|
|
128
|
+
imported_modules = load_modules(modules_dict)
|
|
129
|
+
imported_modules = load_dependent_modules(imported_modules)
|
|
130
|
+
|
|
131
|
+
return imported_modules
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def setup_igm_params(
|
|
135
|
+
parser: ArgumentParser, imported_modules: List[ModuleType]
|
|
136
|
+
) -> Namespace:
|
|
137
|
+
for module in imported_modules:
|
|
138
|
+
module.params(parser)
|
|
139
|
+
|
|
140
|
+
core_and_module_params = parser.parse_args()
|
|
141
|
+
params = load_user_defined_params(
|
|
142
|
+
param_file=core_and_module_params.param_file,
|
|
143
|
+
params_dict=vars(core_and_module_params),
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
parser.set_defaults(**params)
|
|
147
|
+
params = parser.parse_args()
|
|
148
|
+
|
|
149
|
+
return params
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def run_intializers(modules: List, params: Any, state: State) -> None:
|
|
153
|
+
for module in modules:
|
|
154
|
+
module.initialize(params, state)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def run_processes(modules: List, params: Any, state: State) -> None:
|
|
158
|
+
if hasattr(state, "t"):
|
|
159
|
+
while state.t < params.time_end:
|
|
160
|
+
for module in modules:
|
|
161
|
+
module.update(params, state)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def run_finalizers(modules: List, params: Any, state: State) -> None:
|
|
165
|
+
for module in modules:
|
|
166
|
+
module.finalize(params, state)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def add_logger(params, state) -> None:
|
|
170
|
+
if params.logging_file == "":
|
|
171
|
+
pathf = ""
|
|
172
|
+
else:
|
|
173
|
+
pathf = params.logging_file
|
|
174
|
+
|
|
175
|
+
logging.basicConfig(
|
|
176
|
+
filename=pathf,
|
|
177
|
+
encoding="utf-8",
|
|
178
|
+
filemode="w",
|
|
179
|
+
level=params.logging_level,
|
|
180
|
+
format="%(asctime)s - %(levelname)s - %(message)s",
|
|
181
|
+
)
|
|
182
|
+
logging.root.setLevel(params.logging_level)
|
|
183
|
+
|
|
184
|
+
state.logger = logging.getLogger("igm_logger")
|
|
185
|
+
if not pathf == "":
|
|
186
|
+
os.system("echo rm " + pathf + " >> clean.sh")
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def remove_comments(json_str) -> str:
|
|
190
|
+
lines = json_str.split("\n")
|
|
191
|
+
cleaned_lines = [
|
|
192
|
+
line for line in lines if not line.strip().startswith(("//", "#"))
|
|
193
|
+
] # ! TODO: Add blocks comments...
|
|
194
|
+
cleaned_text = "\n".join(cleaned_lines)
|
|
195
|
+
return cleaned_text
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def load_json_file(
|
|
199
|
+
param_file: str, remove_param_comments: bool = True
|
|
200
|
+
) -> Dict[str, Any]:
|
|
201
|
+
with open(param_file, "r") as json_file:
|
|
202
|
+
json_text = json_file.read()
|
|
203
|
+
|
|
204
|
+
if remove_param_comments:
|
|
205
|
+
json_text = remove_comments(json_text)
|
|
206
|
+
|
|
207
|
+
dic_params = json.loads(json_text)
|
|
208
|
+
return dic_params
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def get_modules_list(params_path: str) -> dict[str, List[str]]:
|
|
212
|
+
try:
|
|
213
|
+
with open(params_path) as f:
|
|
214
|
+
# params_dict = json.load(f) #re-instate if you want to enforce no comments in the json file(remove all the lines that load the clean json in this case...)
|
|
215
|
+
json_text = f.read()
|
|
216
|
+
json_cleaned = remove_comments(json_text)
|
|
217
|
+
params_dict = json.loads(json_cleaned)
|
|
218
|
+
module_dict = {
|
|
219
|
+
"modules_preproc": params_dict["modules_preproc"],
|
|
220
|
+
"modules_process": params_dict["modules_process"],
|
|
221
|
+
"modules_postproc": params_dict["modules_postproc"],
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return module_dict
|
|
225
|
+
except JSONDecodeError as e:
|
|
226
|
+
raise JSONDecodeError(
|
|
227
|
+
msg="For the following line, please check the 1) JSON file structure and/or 2) make sure there are no comments (//, #, etc.)",
|
|
228
|
+
doc=e.doc,
|
|
229
|
+
pos=e.pos,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def load_user_defined_params(param_file: str, params_dict: dict[str, Any]):
|
|
234
|
+
try:
|
|
235
|
+
json_defined_params = load_json_file(param_file=param_file)
|
|
236
|
+
except JSONDecodeError as e:
|
|
237
|
+
raise JSONDecodeError(
|
|
238
|
+
msg=f"Error decoding JSON: Please make sure your file path is correct or your json is properly formatted.",
|
|
239
|
+
doc=e.doc,
|
|
240
|
+
pos=e.pos,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
unrecognized_json_arguments = {
|
|
244
|
+
k: v for k, v in json_defined_params.items() if k not in params_dict
|
|
245
|
+
}
|
|
246
|
+
params_dict.update(json_defined_params)
|
|
247
|
+
|
|
248
|
+
for key in unrecognized_json_arguments.keys():
|
|
249
|
+
raise ValueError(
|
|
250
|
+
f"The following argument specified in the JSON file does not exist among the core arguments nor the modules you have chosen: {key}"
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
return params_dict
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def load_modules(modules_dict: Dict) -> List[ModuleType]:
|
|
257
|
+
"""Returns a list of actionable modules to then apply the update, initialize, finalize functions on for IGM."""
|
|
258
|
+
|
|
259
|
+
imported_preproc_modules = load_modules_from_directory(
|
|
260
|
+
modules_list=modules_dict["modules_preproc"], module_folder="preproc"
|
|
261
|
+
)
|
|
262
|
+
imported_process_modules = load_modules_from_directory(
|
|
263
|
+
modules_list=modules_dict["modules_process"], module_folder="process"
|
|
264
|
+
)
|
|
265
|
+
imported_postproc_modules = load_modules_from_directory(
|
|
266
|
+
modules_list=modules_dict["modules_postproc"], module_folder="postproc"
|
|
267
|
+
)
|
|
268
|
+
# ? Should we have custom modules in a seperate folder?
|
|
269
|
+
# imported_custom_modules = load_modules_from_directory(
|
|
270
|
+
# modules_list=modules_dict.modules_custom, module_folder=params.modules_custom_folder
|
|
271
|
+
# )
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
imported_preproc_modules
|
|
275
|
+
+ imported_process_modules
|
|
276
|
+
+ imported_postproc_modules # + imported_custom_modules
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def validate_module(module) -> None:
|
|
281
|
+
"""Validates that a module has the required functions to be used in IGM."""
|
|
282
|
+
required_functions = ["params", "initialize", "finalize", "update"]
|
|
283
|
+
for function in required_functions:
|
|
284
|
+
if not hasattr(module, function):
|
|
285
|
+
raise AttributeError(
|
|
286
|
+
f"Module {module} is missing the required function ({function}). If it is a custom python package, make sure to include the 4 required functions: ['params', 'initialize', 'finalize', 'update'].",
|
|
287
|
+
f"Please see https://github.com/jouvetg/igm/wiki/5.-Custom-modules-(coding) for more information on how to construct custom modules.",
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def load_modules_from_directory(
|
|
292
|
+
modules_list: List[str], module_folder: str
|
|
293
|
+
) -> List[ModuleType]:
|
|
294
|
+
imported_modules = []
|
|
295
|
+
for module_name in modules_list:
|
|
296
|
+
module_path = f"igm.modules.{module_folder}.{module_name}"
|
|
297
|
+
try:
|
|
298
|
+
module = importlib.import_module(module_path)
|
|
299
|
+
except ModuleNotFoundError:
|
|
300
|
+
logging.info(
|
|
301
|
+
f"Error importing module: {module_path}, checking for custom package in current working directory."
|
|
302
|
+
)
|
|
303
|
+
try:
|
|
304
|
+
logging.info(
|
|
305
|
+
f"Trying to import custom module from current working directory (folder or .py): {module_name}"
|
|
306
|
+
)
|
|
307
|
+
module = importlib.import_module(module_name)
|
|
308
|
+
except ModuleNotFoundError:
|
|
309
|
+
raise ModuleNotFoundError(
|
|
310
|
+
f"Can not find module {module_name}. Make sure it is either in the 1) {Path(igm.__file__).parent}/modules/{module_folder} directory or 2) in your current working directory."
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
validate_module(module)
|
|
314
|
+
imported_modules.append(module)
|
|
315
|
+
|
|
316
|
+
return imported_modules
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def has_dependencies(module: Any) -> bool:
|
|
320
|
+
if hasattr(module, "dependencies"):
|
|
321
|
+
return True
|
|
322
|
+
return False
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def load_dependent_modules(imported_modules: List) -> List[ModuleType]:
|
|
326
|
+
imported_dependencies = set()
|
|
327
|
+
for module in imported_modules:
|
|
328
|
+
if has_dependencies(module):
|
|
329
|
+
module_dependencies = module.dependencies
|
|
330
|
+
directories_to_search = [
|
|
331
|
+
"preproc",
|
|
332
|
+
"process",
|
|
333
|
+
"postproc",
|
|
334
|
+
] # will also check current working directory if any of them fail
|
|
335
|
+
load_modules_partial = partial(
|
|
336
|
+
load_modules_from_directory, module_dependencies
|
|
337
|
+
)
|
|
338
|
+
for directory in directories_to_search:
|
|
339
|
+
try:
|
|
340
|
+
dependent_module = load_modules_partial(module_folder=directory)
|
|
341
|
+
imported_dependencies.add(
|
|
342
|
+
dependent_module[0]
|
|
343
|
+
) # [0] because it returns a singleton list
|
|
344
|
+
logging.info(
|
|
345
|
+
f"Found dependencies in directory {directory} or current working directory. Checking next module for dependencies."
|
|
346
|
+
)
|
|
347
|
+
break
|
|
348
|
+
except ModuleNotFoundError:
|
|
349
|
+
logging.info(
|
|
350
|
+
f"Could not find dependencies in directory {directory} or current working directory. Checking next IGM directory."
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
return imported_modules + list(imported_dependencies)
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def print_gpu_info() -> None:
|
|
357
|
+
gpus = tf.config.experimental.list_physical_devices("GPU")
|
|
358
|
+
print(f"{'CUDA Enviroment':-^150}")
|
|
359
|
+
tf.sysconfig.get_build_info().pop("cuda_compute_capabilities", None)
|
|
360
|
+
print(f"{json.dumps(tf.sysconfig.get_build_info(), indent=2, default=str)}")
|
|
361
|
+
print(f"{'Available GPU Devices':-^150}")
|
|
362
|
+
for gpu in gpus:
|
|
363
|
+
gpu_info = {"gpu_id": gpu.name, "device_type": gpu.device_type}
|
|
364
|
+
device_details = tf.config.experimental.get_device_details(gpu)
|
|
365
|
+
gpu_info.update(device_details)
|
|
366
|
+
|
|
367
|
+
print(f"{json.dumps(gpu_info, indent=2, default=str)}")
|
|
368
|
+
print(f"{'':-^150}")
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
# Print parameters in screen and a dedicated file
|
|
372
|
+
def print_params(params: Namespace) -> None:
|
|
373
|
+
param_file = params.saved_params_filename
|
|
374
|
+
param_file = param_file + ".json"
|
|
375
|
+
|
|
376
|
+
# load the given parameters
|
|
377
|
+
with open(param_file, "w") as json_file:
|
|
378
|
+
json.dump(params.__dict__, json_file, indent=2)
|
|
379
|
+
|
|
380
|
+
os.system("echo rm " + param_file + " >> clean.sh")
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
# Copyright (C) 2021-2023 Guillaume Jouvet <guillaume.jouvet@unil.ch>
|
|
4
|
+
# Published under the GNU GPL (Version 3), check at the LICENSE file
|
|
5
|
+
|
|
6
|
+
import tensorflow as tf
|
|
7
|
+
from igm import (
|
|
8
|
+
State,
|
|
9
|
+
params_core,
|
|
10
|
+
print_params,
|
|
11
|
+
run_intializers,
|
|
12
|
+
run_processes,
|
|
13
|
+
run_finalizers,
|
|
14
|
+
setup_igm_modules,
|
|
15
|
+
setup_igm_params,
|
|
16
|
+
print_gpu_info,
|
|
17
|
+
add_logger
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def main() -> None:
|
|
22
|
+
state = State() # class acting as a dictionary
|
|
23
|
+
parser = params_core()
|
|
24
|
+
params, _ = parser.parse_known_args()
|
|
25
|
+
|
|
26
|
+
if params.gpu_info:
|
|
27
|
+
print_gpu_info()
|
|
28
|
+
|
|
29
|
+
if params.logging:
|
|
30
|
+
add_logger(params=params, state=state)
|
|
31
|
+
tf.get_logger().setLevel(params.logging_level)
|
|
32
|
+
|
|
33
|
+
imported_modules = setup_igm_modules(params)
|
|
34
|
+
params = setup_igm_params(parser, imported_modules)
|
|
35
|
+
|
|
36
|
+
if params.print_params:
|
|
37
|
+
print_params(params=params)
|
|
38
|
+
|
|
39
|
+
# Place the computation on your device GPU ('/GPU:0') or CPU ('/CPU:0')
|
|
40
|
+
with tf.device(f"/GPU:{params.gpu_id}"): # type: ignore for linting checks
|
|
41
|
+
run_intializers(imported_modules, params, state)
|
|
42
|
+
run_processes(imported_modules, params, state)
|
|
43
|
+
run_finalizers(imported_modules, params, state)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
if __name__ == "__main__":
|
|
47
|
+
main()
|
|
@@ -76,8 +76,16 @@ class IGM_Model2D(Model2D):
|
|
|
76
76
|
|
|
77
77
|
"""
|
|
78
78
|
|
|
79
|
-
parser = argparse.ArgumentParser(description="IGM")
|
|
80
|
-
igm.
|
|
79
|
+
# parser = argparse.ArgumentParser(description="IGM")
|
|
80
|
+
parser = igm.params_core()
|
|
81
|
+
|
|
82
|
+
params, __ = parser.parse_known_args() # args=[] add this for jupyter notebook
|
|
83
|
+
|
|
84
|
+
imported_modules = igm.load_modules(params)
|
|
85
|
+
|
|
86
|
+
for module in imported_modules:
|
|
87
|
+
module.params(parser)
|
|
88
|
+
|
|
81
89
|
self.params = parser.parse_args(args=[])
|
|
82
90
|
|
|
83
91
|
self.state = igm.State()
|
|
@@ -111,7 +119,7 @@ class IGM_Model2D(Model2D):
|
|
|
111
119
|
|
|
112
120
|
self.icemask = mb_filter
|
|
113
121
|
|
|
114
|
-
igm.
|
|
122
|
+
igm.modules.process.iceflow.initialize(self.params, self.state)
|
|
115
123
|
|
|
116
124
|
def step(self, dt):
|
|
117
125
|
# recast glacier variables into igm-like variables
|
|
@@ -120,7 +128,7 @@ class IGM_Model2D(Model2D):
|
|
|
120
128
|
self.state.usurf.assign(self.surface_h)
|
|
121
129
|
|
|
122
130
|
# compute ubar and vbar
|
|
123
|
-
igm.
|
|
131
|
+
igm.modules.process.iceflow.update(self.params, self.state)
|
|
124
132
|
|
|
125
133
|
# retrurn the divergence of the flux using upwind fluxes
|
|
126
134
|
divflux = (
|
|
@@ -3,26 +3,23 @@
|
|
|
3
3
|
# Copyright (C) 2021-2023 Guillaume Jouvet <guillaume.jouvet@unil.ch>
|
|
4
4
|
# Published under the GNU GPL (Version 3), check at the LICENSE file
|
|
5
5
|
|
|
6
|
-
import numpy as np
|
|
7
|
-
import os, sys, shutil
|
|
8
|
-
import time
|
|
9
6
|
import tensorflow as tf
|
|
10
7
|
import matplotlib.pyplot as plt
|
|
11
8
|
|
|
12
9
|
|
|
13
|
-
def
|
|
10
|
+
def params(parser):
|
|
14
11
|
pass
|
|
15
12
|
|
|
16
13
|
|
|
17
|
-
def
|
|
14
|
+
def initialize(params, state):
|
|
18
15
|
pass
|
|
19
16
|
|
|
20
17
|
|
|
21
|
-
def
|
|
18
|
+
def update(params, state):
|
|
22
19
|
pass
|
|
23
20
|
|
|
24
21
|
|
|
25
|
-
def
|
|
22
|
+
def finalize(params, state):
|
|
26
23
|
from mayavi import mlab
|
|
27
24
|
import xarray as xr
|
|
28
25
|
import numpy as np
|
|
@@ -30,9 +27,7 @@ def finalize_anim_mayavi(params, state):
|
|
|
30
27
|
|
|
31
28
|
plt.close("all")
|
|
32
29
|
|
|
33
|
-
ds = xr.open_dataset(
|
|
34
|
-
os.path.join(params.working_dir, "output.nc"), engine="netcdf4"
|
|
35
|
-
)
|
|
30
|
+
ds = xr.open_dataset("output.nc", engine="netcdf4")
|
|
36
31
|
|
|
37
32
|
X, Y = np.meshgrid(ds.x, ds.y)
|
|
38
33
|
|
|
@@ -57,7 +52,7 @@ def finalize_anim_mayavi(params, state):
|
|
|
57
52
|
|
|
58
53
|
VEC = hasattr(ds, "uvelsurf") & hasattr(ds, "vvelsurf") & hasattr(ds, "wvelsurf")
|
|
59
54
|
|
|
60
|
-
PAR = os.path.isdir(
|
|
55
|
+
PAR = os.path.isdir("trajectories")
|
|
61
56
|
|
|
62
57
|
if VEC:
|
|
63
58
|
quiv = mlab.quiver3d(
|
|
@@ -70,7 +65,7 @@ def finalize_anim_mayavi(params, state):
|
|
|
70
65
|
)
|
|
71
66
|
|
|
72
67
|
# if PAR:
|
|
73
|
-
# f = os.path.join(
|
|
68
|
+
# f = os.path.join("trajectories",'traj-'+"{:06.0f}".format(TIME[0])+".csv")
|
|
74
69
|
# XYZ = np.loadtxt(f,skiprows=1,delimiter=',')
|
|
75
70
|
# pt3d = mlab.points3d(XYZ[:,1], XYZ[:,2], XYZ[:,3], colormap="RdBu",mode='point')
|
|
76
71
|
# pt3d.actor.property.point_size = 5
|
|
@@ -87,7 +82,7 @@ def finalize_anim_mayavi(params, state):
|
|
|
87
82
|
quiv.mlab_source.v = np.array(tf.expand_dims(ds.vvelsurf[i], axis=0))
|
|
88
83
|
quiv.mlab_source.w = np.array(tf.expand_dims(ds.wvelsurf[i], axis=0))
|
|
89
84
|
# if PAR:
|
|
90
|
-
# f = os.path.join(
|
|
85
|
+
# f = os.path.join("trajectories",'traj-'+"{:06.0f}".format(TIME[i])+".csv")
|
|
91
86
|
# XYZ = np.loadtxt(f,skiprows=1,delimiter=',')
|
|
92
87
|
# pt3d.mlab_source.x = XYZ[:,1]
|
|
93
88
|
# pt3d.mlab_source.y = XYZ[:,2]
|