├── .github
└── workflows
│ └── CI.yml
├── .gitignore
├── .gitmodules
├── MOM_diags.txt
├── README.md
├── accessom.yml
├── doc
└── static
│ └── ACCESSOM2_System_Architecture.png
├── hashexe-public.sh
├── hashexe.sh
├── install.sh
├── libcheck.sh
├── test
├── checksums
│ ├── 1deg_jra55_iaf-access-om2.out
│ ├── cm_1440x1080-test.txt
│ ├── cm_360x300-test.txt
│ └── om_1440x1080-test.txt
├── dump_field.F90
├── exp_test_helper.py
├── load_dump.py
├── requirements_test.txt
├── test_bit_reproducibility.py
├── test_build.py
├── test_coupling_fields.py
├── test_grids_match.py
├── test_remapping_weights.py
├── test_run.py
├── test_startup.py
├── test_valgrind.py
├── util.py
└── valgrind_suppressions.txt
└── tools
├── .pylintrc
├── README.md
├── add_core2_time_bounds.py
├── calc_input_checksum.py
├── contrib
├── build_esmf_on_raijin.sh
└── build_esmf_on_ubuntu.sh
├── make_cice_grid.py
├── make_remap_weights.py
├── make_remap_weights.sh
├── make_salt_sfc_restore.py
└── release.py
/.github/workflows/CI.yml:
--------------------------------------------------------------------------------
1 | # Run CI tests
2 | name: CI
3 |
4 | # Controls when the action will run.
5 | on:
6 | # Triggers the workflow on push or pull request events but only for the master branch
7 | push:
8 | branches: [ master ]
9 | pull_request:
10 | branches: [ master ]
11 |
12 | # Allows you to run this workflow manually from the Actions tab
13 | workflow_dispatch:
14 |
15 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
16 | jobs:
17 | build:
18 | runs-on: ubuntu-latest
19 |
20 | # Run the job for different versions of python
21 | strategy:
22 | matrix:
23 | python-version: [3.7, 3.8, 3.9]
24 |
25 | # Steps represent a sequence of tasks that will be executed as part of the job
26 | steps:
27 |
28 | # Checks-out repository code
29 | - name: Checkout code
30 | uses: actions/checkout@v2
31 | with:
32 | submodules: recursive
33 |
34 | - name: Set up Python ${{ matrix.python-version }}
35 | uses: actions/setup-python@v2
36 | with:
37 | python-version: ${{ matrix.python-version }}
38 |
39 | - name: Install dependencies
40 | run: pip install -r test/requirements_test.txt
41 |
42 | - name: Lint test
43 | working-directory: ./test
44 | run: pylint --extension-pkg-whitelist=netCDF4 --errors-only --ignore=test_coupling_fields.py,test_grids_match.py,test_valgrind.py *.py
45 |
46 | - name: Lint tools
47 | working-directory: ./tools
48 | run: pylint --extension-pkg-whitelist=netCDF4 -v --errors-only --rcfile=.pylintrc *.py
49 |
50 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #
2 |
3 | archive
4 | bin
5 | work
6 | access-om2.err
7 | access-om2.out
8 | pbs_logs
9 |
10 | tools/PET*
11 | tools/*.nc
12 | tools/contrib/esmf
13 | tools/contrib/bin
14 |
15 | *.swp
16 | input_*.tar.gz
17 | input
18 |
19 | .cache
20 |
21 | # Byte-compiled / optimized / DLL files
22 | __pycache__/
23 | *.py[cod]
24 |
25 | # C extensions
26 | *.so
27 |
28 | payu-experiments
29 |
30 | ._*
31 |
32 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "src/mom"]
2 | path = src/mom
3 | url = https://github.com/mom-ocean/MOM5.git
4 | [submodule "src/cice5"]
5 | path = src/cice5
6 | url = https://github.com/COSIMA/cice5.git
7 | [submodule "control/1deg_jra55_ryf"]
8 | path = control/1deg_jra55_ryf
9 | url = https://github.com/COSIMA/1deg_jra55_ryf.git
10 | [submodule "control/01deg_jra55_ryf"]
11 | path = control/01deg_jra55_ryf
12 | url = https://github.com/COSIMA/01deg_jra55_ryf.git
13 | [submodule "control/025deg_jra55_ryf"]
14 | path = control/025deg_jra55_ryf
15 | url = https://github.com/COSIMA/025deg_jra55_ryf.git
16 | [submodule "tools/esmgrids"]
17 | path = tools/esmgrids
18 | url = https://github.com/DoublePrecision/esmgrids.git
19 | [submodule "src/libaccessom2"]
20 | path = src/libaccessom2
21 | url = https://github.com/COSIMA/libaccessom2.git
22 | [submodule "control/1deg_jra55_iaf"]
23 | path = control/1deg_jra55_iaf
24 | url = https://github.com/COSIMA/1deg_jra55_iaf.git
25 | [submodule "control/01deg_jra55_iaf"]
26 | path = control/01deg_jra55_iaf
27 | url = https://github.com/COSIMA/01deg_jra55_iaf.git
28 | [submodule "control/025deg_jra55_iaf"]
29 | path = control/025deg_jra55_iaf
30 | url = https://github.com/COSIMA/025deg_jra55_iaf.git
31 | [submodule "tools/initial_conditions_access-om2"]
32 | path = tools/initial_conditions_access-om2
33 | url = https://github.com/COSIMA/initial_conditions_access-om2.git
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ----------
5 | # _DEPRECATION NOTICE_
6 |
7 | _[ACCESS-NRI](https://www.access-nri.org.au/) has taken on responsibility for ongoing support of ACCESS-OM2, so this repository is not being updated and will eventually be archived._
8 |
9 | _**New ACCESS-OM2 experiments and code development should use the latest code release from [ACCESS-NRI/ACCESS-OM2](https://github.com/ACCESS-NRI/ACCESS-OM2) and configurations from [ACCESS-NRI/access-om2-configs](https://github.com/ACCESS-NRI/access-om2-configs), and all new issues should be posted on one of those repositories.**_
10 |
11 | -----------
12 |
13 | # ACCESS-OM2
14 |
15 | ACCESS-OM2 is a global coupled ocean - sea ice model being developed by [COSIMA](http://www.cosima.org.au).
16 |
17 | ACCESS-OM2 consists of the [MOM 5.1](https://mom-ocean.github.io) ocean model, [CICE 5.1.2](https://github.com/CICE-Consortium/CICE-svn-trunk/tree/cice-5.1.2) sea ice model, and a file-based atmosphere called [YATM](https://github.com/COSIMA/libaccessom2) coupled together using [OASIS3-MCT v2.0](https://portal.enes.org/oasis). ACCESS-OM2 builds on the ACCESS-OM ([Bi et al., 2013](http://www.bom.gov.au/jshess/docs/2013/bi2_hres.pdf)) and AusCOM ([Roberts et al., 2007](https://50years.acs.org.au/content/dam/acs/50-years/journals/jrpit/JRPIT39.2.137.pdf); [Bi and Marsland, 2010](https://www.cawcr.gov.au/technical-reports/CTR_027.pdf)) models originally developed at [CSIRO](http://www.csiro.au).
18 |
19 | ACCESS-OM2 comes with a number of standard configurations in the [control](https://github.com/COSIMA/access-om2/tree/master/control) directory. These include sea ice and ocean at a nominal 1.0, 0.25 and 0.1 degree horizontal grid spacing, forced by [JRA55-do](https://doi.org/10.1016/j.ocemod.2018.07.002) atmospheric reanalyses.
20 |
21 | ACCESS-OM2 is being used for a growing number of research projects. A partial list of publications using the model is given [here](https://scholar.google.com/citations?hl=en&view_op=list_works&gmla=AJsN-F5gp3-wpXzF8odo9cFy-9ajlgIeqwrOq_7DvPS1rkETzqmPk1Sfx-gAmIs9kFfRflOR3HqNV_85pJ2j4LljHks1wQtONqiuOVgii-UICb9q2fmTp_w&user=inVqu_4AAAAJ).
22 |
23 | # Downloading
24 |
25 | This repository contains many submodules, so you will need to clone it with the `--recursive` flag:
26 | ```
27 | git clone --recursive https://github.com/COSIMA/access-om2.git
28 | ```
29 |
30 | To update a previous clone of this repository to the latest version, you will need to do
31 | ```
32 | git pull
33 | ```
34 | followed by
35 | ```
36 | git submodule update --init --recursive
37 | ```
38 | to update all the submodules.
39 |
40 | # Where to find information
41 |
42 | The v1.0 model code, configurations and performance were described in [Kiss et al. (2020)](https://doi.org/10.5194/gmd-13-401-2020), with further details in the draft [ACCESS-OM2 technical report](https://github.com/COSIMA/ACCESS-OM2-1-025-010deg-report). The current code and configurations differ from v1.0 in a number of ways (biogeochemistry, updated forcing, improvements and bug fixes), as described by [Solodoch et al. (2022)](https://doi.org/10.1029/2021GL097211), [Hayashida et al. (2023)](https://dx.doi.org/10.1029/2023JC019697), [Menviel et al. (2023)](https://doi.org/10.5194/egusphere-2023-390) and [Wang et al. (2023)](https://doi.org/10.5194/gmd-2023-123).
43 |
44 | Model output can be accessed by [NCI](http://nci.org.au) users via the [COSIMA Cookbook](https://github.com/COSIMA/cosima-cookbook).
45 |
46 | For information on downloading, building and running the model, see the [ACCESS-OM2 wiki](https://github.com/COSIMA/access-om2/wiki).
47 |
48 | **NOTE:** All ACCESS-OM2 model components and configurations are undergoing continual improvement. We strongly recommend that you "watch" this repo (see button at top of screen; ask to be notified of all conversations) and also watch all the [component models](https://github.com/COSIMA/access-om2/tree/master/src), whichever [configuration(s)](https://github.com/COSIMA/access-om2/tree/master/control) you are using, and [`payu`](https://github.com/payu-org/payu) to be kept informed of updates, problems and bug fixes as they arise.
49 |
50 | Requests for help and other issues associated with the model, tools or configurations can be registered as [ACCESS-OM2 issues](https://github.com/COSIMA/access-om2/issues).
51 |
52 | ## Conditions of use
53 |
54 | We request that users of this or other ACCESS-OM2 model code:
55 | 1. consider citing Kiss et al. (2020) ([http://doi.org/10.5194/gmd-13-401-2020](http://doi.org/10.5194/gmd-13-401-2020)), and also the other [papers above](https://github.com/COSIMA/access-om2#where-to-find-information) detailing more recent improvements to the model
56 | 2. include an acknowledgement such as the following:
57 |
58 | *The authors thank the Consortium for Ocean-Sea Ice Modelling in Australia (COSIMA; [http://www.cosima.org.au](http://www.cosima.org.au)) for making the ACCESS-OM2 suite of models available at [https://github.com/COSIMA/access-om2](https://github.com/COSIMA/access-om2).*
59 | 3. let us know of any publications which use these models or data so we can add them to [our list](https://scholar.google.com/citations?hl=en&user=inVqu_4AAAAJ).
60 |
--------------------------------------------------------------------------------
/accessom.yml:
--------------------------------------------------------------------------------
1 | name: accessom
2 | channels:
3 | - conda-forge
4 | - defaults
5 | dependencies:
6 | - asn1crypto=0.22.0=py36_0
7 | - cffi=1.11.2=py36_0
8 | - chardet=3.0.4=py36_0
9 | - ckanapi=4.1=py_0
10 | - cryptography=2.0.3=py36_0
11 | - docopt=0.6.2=py36_0
12 | - idna=2.6=py36_1
13 | - pycparser=2.18=py36_0
14 | - pyopenssl=17.4.0=py36_0
15 | - pysocks=1.6.7=py36_0
16 | - requests=2.18.4=py36_1
17 | - simplejson=3.11.1=py36_0
18 | - six=1.11.0=py36_1
19 | - urllib3=1.22=py36_0
20 | - ca-certificates=2017.08.26=h1d4fec5_0
21 | - certifi=2017.11.5=py36hf29ccca_0
22 | - libedit=3.1=heed3624_0
23 | - libffi=3.2.1=hd88cf55_4
24 | - libgcc-ng=7.2.0=h7cc24e2_2
25 | - libstdcxx-ng=7.2.0=h7a57d05_2
26 | - ncurses=6.0=h9df7e31_2
27 | - openssl=1.0.2m=h26d622b_1
28 | - pip=9.0.1=py36h6c6f9ce_4
29 | - python=3.6.3=h6c0c0dc_5
30 | - readline=7.0=ha6073c6_4
31 | - setuptools=36.5.0=py36he42e2e1_0
32 | - sqlite=3.20.1=hb898158_2
33 | - tk=8.6.7=hc745277_3
34 | - wheel=0.30.0=py36hfd4bba0_1
35 | - xz=5.2.3=h55aa19d_2
36 | - zlib=1.2.11=ha838bed_2
37 | - pip:
38 | - apipkg==1.4
39 | - attrs==17.3.0
40 | - execnet==1.5.0
41 | - llvmlite==0.20.0
42 | - netcdf4==1.3.1
43 | - nose==1.3.7
44 | - numba==0.35.0
45 | - numpy==1.13.3
46 | - pep8==1.7.1
47 | - pluggy==0.6.0
48 | - py==1.5.2
49 | - pyproj==1.9.5.1
50 | - pytest==3.3.0
51 | - pytest-cache==1.0
52 | - pytest-pep8==1.0.6
53 | - pyyaml==3.12
54 | - scipy==1.0.0
55 | - sh==1.12.14
56 | - shapely==1.6.2.post1
57 | prefix: /short/ir04/ap4626/anaconda3/envs/accessom
58 |
59 |
--------------------------------------------------------------------------------
/doc/static/ACCESSOM2_System_Architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/COSIMA/access-om2/c35ebfaaaf287041b42998f1a9a40191cef9b79b/doc/static/ACCESSOM2_System_Architecture.png
--------------------------------------------------------------------------------
/hashexe-public.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # Copy ACCESS-OM2 executables to bin with githash in name, and config.yaml to match.
4 | # All changes to config.yaml are reported.
5 | # This is basically the same as hashexe.sh but copies to a public bin dir (using non-clobbering copy for safety).
6 | #
7 | # Andrew Kiss https://github.com/aekiss
8 |
9 | set -e
10 |
11 | if [[ -z "${ACCESS_OM_DIR}" ]]; then
12 | export ACCESS_OM_DIR=$(pwd)
13 | fi
14 |
15 | if [[ -z "${public}" ]]; then
16 | public=/g/data/ik11/inputs/access-om2/bin # if not called from update-commit-push.sh
17 | fi
18 |
19 | if [ -w $public ]; then
20 | bindir=$public
21 | else
22 | echo "You don't have write access to $public. Exiting."
23 | exit 1
24 | fi
25 |
26 | if [[ -z "${mom_type}" ]]; then
27 | echo "FATAL ERROR: mom_type not set. Need to do whichever of these is appropriate"
28 | echo " export mom_type=ACCESS-OM"
29 | echo "or"
30 | echo " export mom_type=ACCESS-OM-BGC"
31 | echo "taking into account the branches the control dirs are on:"
32 | for d in control/*; do cd $d; echo $d; git status | grep "On branch"; cd -; done
33 | exit 1
34 | fi
35 |
36 | yatmpath=${ACCESS_OM_DIR}/src/libaccessom2/build/bin/yatm.exe
37 | fmspath=${ACCESS_OM_DIR}/src/mom/exec/nci/${mom_type}/fms_${mom_type}.x
38 | cice1path=${ACCESS_OM_DIR}/src/cice5/build_auscom_360x300_24p/cice_auscom_360x300_24p.exe
39 | cice025path=${ACCESS_OM_DIR}/src/cice5/build_auscom_1440x1080_480p/cice_auscom_1440x1080_480p.exe
40 | cice010path=${ACCESS_OM_DIR}/src/cice5/build_auscom_3600x2700_722p/cice_auscom_3600x2700_722p.exe
41 | cice010path_18x15=${ACCESS_OM_DIR}/src/cice5/build_auscom_18x15.3600x2700_1682p/cice_auscom_18x15.3600x2700_1682p.exe
42 | mppnccombinepath=${ACCESS_OM_DIR}/src/mom/bin/mppnccombine.nci
43 |
44 | config1ryfpath=${ACCESS_OM_DIR}/control/1deg_jra55_ryf/config.yaml
45 | config025ryfpath=${ACCESS_OM_DIR}/control/025deg_jra55_ryf/config.yaml
46 | config010ryfpath=${ACCESS_OM_DIR}/control/01deg_jra55_ryf/config.yaml
47 |
48 | config1iafpath=${ACCESS_OM_DIR}/control/1deg_jra55_iaf/config.yaml
49 | config025iafpath=${ACCESS_OM_DIR}/control/025deg_jra55_iaf/config.yaml
50 | config010iafpath=${ACCESS_OM_DIR}/control/01deg_jra55_iaf/config.yaml
51 |
52 | echo "Getting executable hashes..."
53 |
54 | cd $(dirname "${yatmpath}") && yatmhash=`git rev-parse --short=7 HEAD`
55 | test -z "$(git status --porcelain)" || yatmhash=${yatmhash}-modified # uncommitted changes or untracked files
56 | cd $(dirname "${fmspath}") && fmshash=`git rev-parse --short=7 HEAD`
57 | test -z "$(git status --porcelain)" || fmshash=${fmshash}-modified # uncommitted changes or untracked files
58 | fmshash=${fmshash}_libaccessom2_${yatmhash} # also track libaccessom2
59 | cd $(dirname "${cice1path}") && cicehash=`git rev-parse --short=7 HEAD` # NB only one hash for all three cice builds
60 | test -z "$(git status --porcelain)" || cicehash=${cicehash}-modified # uncommitted changes or untracked files
61 | cicehash=${cicehash}_libaccessom2_${yatmhash} # also track libaccessom2
62 |
63 | echo "Copying executables to "${bindir}" with hashes added to names..."
64 |
65 | yatmbn=$(basename "${yatmpath}")
66 | yatmhashexe="${yatmbn%.*}"_${yatmhash}."${yatmpath##*.}"
67 | echo " cp -n ${yatmpath} ${bindir}/${yatmhashexe}"
68 | cp -n ${yatmpath} ${bindir}/${yatmhashexe}
69 | chmod o+x ${bindir}/${yatmhashexe} || true
70 | chgrp ik11 ${bindir}/${yatmhashexe} || true
71 |
72 | fmsbn=$(basename "${fmspath}")
73 | fmshashexe="${fmsbn%.*}"_${fmshash}."${fmspath##*.}"
74 | echo " cp -n ${fmspath} ${bindir}/${fmshashexe}"
75 | cp -n ${fmspath} ${bindir}/${fmshashexe}
76 | chmod o+x ${bindir}/${fmshashexe} || true
77 | chgrp ik11 ${bindir}/${fmshashexe} || true
78 |
79 | cice1bn=$(basename "${cice1path}")
80 | cice1hashexe="${cice1bn%.*}"_${cicehash}."${cice1path##*.}"
81 | echo " cp -n ${cice1path} ${bindir}/${cice1hashexe}"
82 | cp -n ${cice1path} ${bindir}/${cice1hashexe}
83 | chmod o+x ${bindir}/${cice1hashexe} || true
84 | chgrp ik11 ${bindir}/${cice1hashexe} || true
85 |
86 | cice025bn=$(basename "${cice025path}")
87 | cice025hashexe="${cice025bn%.*}"_${cicehash}."${cice025path##*.}"
88 | echo " cp -n ${cice025path} ${bindir}/${cice025hashexe}"
89 | cp -n ${cice025path} ${bindir}/${cice025hashexe}
90 | chmod o+x ${bindir}/${cice025hashexe} || true
91 | chgrp ik11 ${bindir}/${cice025hashexe} || true
92 |
93 | cice010bn=$(basename "${cice010path}")
94 | cice010hashexe="${cice010bn%.*}"_${cicehash}."${cice010path##*.}"
95 | echo " cp -n ${cice010path} ${bindir}/${cice010hashexe}"
96 | cp -n ${cice010path} ${bindir}/${cice010hashexe}
97 | chmod o+x ${bindir}/${cice010hashexe} || true
98 | chgrp ik11 ${bindir}/${cice010hashexe} || true
99 |
100 | cice010bn_18x15=$(basename "${cice010path_18x15}")
101 | cice010hashexe_18x15="${cice010bn_18x15%.*}"_${cicehash}."${cice010path_18x15##*.}"
102 | echo " cp -n ${cice010path_18x15} ${bindir}/${cice010hashexe_18x15}"
103 | cp -n ${cice010path_18x15} ${bindir}/${cice010hashexe_18x15}
104 | chmod o+x ${bindir}/${cice010hashexe_18x15} || true
105 | chgrp ik11 ${bindir}/${cice010hashexe_18x15} || true
106 |
107 | echo " cp -n ${mppnccombinepath} ${bindir}/mppnccombine"
108 | cp -n ${mppnccombinepath} ${bindir}/mppnccombine # no hash for mppnccombine
109 | chmod o+x ${bindir}/mppnccombine || true # no hash for mppnccombine
110 | chgrp ik11 ${bindir}/mppnccombine || true # no hash for mppnccombine
111 |
112 | echo "Fixing exe in "${config1ryfpath}" to match executable names..."
113 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config1ryfpath} > ${config1ryfpath}-tmp
114 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config1ryfpath}-tmp > ${config1ryfpath}-tmp2
115 | sed "s|exe:.*${cice1bn%.*}_.*|exe: ${bindir}/${cice1hashexe}|g" < ${config1ryfpath}-tmp2 > ${config1ryfpath}-tmp3
116 | diff ${config1ryfpath} ${config1ryfpath}-tmp3 || true
117 | mv ${config1ryfpath}-tmp3 ${config1ryfpath}
118 | rm ${config1ryfpath}-tmp*
119 |
120 | echo "Fixing exe in "${config025ryfpath}" to match executable names..."
121 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config025ryfpath} > ${config025ryfpath}-tmp
122 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config025ryfpath}-tmp > ${config025ryfpath}-tmp2
123 | sed "s|exe:.*${cice025bn%.*}_.*|exe: ${bindir}/${cice025hashexe}|g" < ${config025ryfpath}-tmp2 > ${config025ryfpath}-tmp3
124 | diff ${config025ryfpath} ${config025ryfpath}-tmp3 || true
125 | mv ${config025ryfpath}-tmp3 ${config025ryfpath}
126 | rm ${config025ryfpath}-tmp*
127 |
128 | echo "Fixing exe in "${config010ryfpath}" to match executable names..."
129 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config010ryfpath} > ${config010ryfpath}-tmp
130 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config010ryfpath}-tmp > ${config010ryfpath}-tmp2
131 | sed "s|exe:.*${cice010bn%.*}_.*|exe: ${bindir}/${cice010hashexe}|g" < ${config010ryfpath}-tmp2 > ${config010ryfpath}-tmp3
132 | diff ${config010ryfpath} ${config010ryfpath}-tmp3 || true
133 | mv ${config010ryfpath}-tmp3 ${config010ryfpath}
134 | rm ${config010ryfpath}-tmp*
135 |
136 | echo "Fixing exe in "${config1iafpath}" to match executable names..."
137 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config1iafpath} > ${config1iafpath}-tmp
138 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config1iafpath}-tmp > ${config1iafpath}-tmp2
139 | sed "s|exe:.*${cice1bn%.*}_.*|exe: ${bindir}/${cice1hashexe}|g" < ${config1iafpath}-tmp2 > ${config1iafpath}-tmp3
140 | diff ${config1iafpath} ${config1iafpath}-tmp3 || true
141 | mv ${config1iafpath}-tmp3 ${config1iafpath}
142 | rm ${config1iafpath}-tmp*
143 |
144 | echo "Fixing exe in "${config025iafpath}" to match executable names..."
145 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config025iafpath} > ${config025iafpath}-tmp
146 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config025iafpath}-tmp > ${config025iafpath}-tmp2
147 | sed "s|exe:.*${cice025bn%.*}_.*|exe: ${bindir}/${cice025hashexe}|g" < ${config025iafpath}-tmp2 > ${config025iafpath}-tmp3
148 | diff ${config025iafpath} ${config025iafpath}-tmp3 || true
149 | mv ${config025iafpath}-tmp3 ${config025iafpath}
150 | rm ${config025iafpath}-tmp*
151 |
152 | echo "Fixing exe in "${config010iafpath}" to match executable names..."
153 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config010iafpath} > ${config010iafpath}-tmp
154 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config010iafpath}-tmp > ${config010iafpath}-tmp2
155 | sed "s|exe:.*${cice010bn%.*}_.*|exe: ${bindir}/${cice010hashexe}|g" < ${config010iafpath}-tmp2 > ${config010iafpath}-tmp3
156 | diff ${config010iafpath} ${config010iafpath}-tmp3 || true
157 | mv ${config010iafpath}-tmp3 ${config010iafpath}
158 | rm ${config010iafpath}-tmp*
159 |
160 | # TODO: fix sed script to handle changes of mom_type
161 | echo
162 | echo "WARNING: if your previous exe mom_type was not ${mom_type} it will need to be manually updated in the config.yaml file"
163 | echo
164 | sleep 1
165 |
166 | echo "$(basename $BASH_SOURCE) completed."
167 |
168 |
--------------------------------------------------------------------------------
/hashexe.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # Copy ACCESS-OM2 executables to bin with githash in name, and config.yaml to match.
4 | # All changes to config.yaml are reported.
5 | # Andrew Kiss https://github.com/aekiss
6 |
7 | set -e
8 |
9 | if [[ -z "${ACCESS_OM_DIR}" ]]; then
10 | export ACCESS_OM_DIR=$(pwd)
11 | fi
12 |
13 | if [[ -z "${mom_type}" ]]; then
14 | echo "FATAL ERROR: mom_type not set. Need to do whichever of these is appropriate"
15 | echo " export mom_type=ACCESS-OM"
16 | echo "or"
17 | echo " export mom_type=ACCESS-OM-BGC"
18 | echo "taking into account the branches the control dirs are on:"
19 | for d in control/*; do cd $d; echo $d; git status | grep "On branch"; cd -; done
20 | exit 1
21 | fi
22 |
23 | yatmpath=${ACCESS_OM_DIR}/src/libaccessom2/build/bin/yatm.exe
24 | fmspath=${ACCESS_OM_DIR}/src/mom/exec/nci/${mom_type}/fms_${mom_type}.x
25 | cice1path=${ACCESS_OM_DIR}/src/cice5/build_auscom_360x300_24p/cice_auscom_360x300_24p.exe
26 | cice025path=${ACCESS_OM_DIR}/src/cice5/build_auscom_1440x1080_480p/cice_auscom_1440x1080_480p.exe
27 | cice010path=${ACCESS_OM_DIR}/src/cice5/build_auscom_3600x2700_722p/cice_auscom_3600x2700_722p.exe
28 | cice010path_18x15=${ACCESS_OM_DIR}/src/cice5/build_auscom_18x15.3600x2700_1682p/cice_auscom_18x15.3600x2700_1682p.exe
29 | mppnccombinepath=${ACCESS_OM_DIR}/src/mom/bin/mppnccombine.nci
30 |
31 | config1ryfpath=${ACCESS_OM_DIR}/control/1deg_jra55_ryf/config.yaml
32 | config025ryfpath=${ACCESS_OM_DIR}/control/025deg_jra55_ryf/config.yaml
33 | config010ryfpath=${ACCESS_OM_DIR}/control/01deg_jra55_ryf/config.yaml
34 |
35 | config1iafpath=${ACCESS_OM_DIR}/control/1deg_jra55_iaf/config.yaml
36 | config025iafpath=${ACCESS_OM_DIR}/control/025deg_jra55_iaf/config.yaml
37 | config010iafpath=${ACCESS_OM_DIR}/control/01deg_jra55_iaf/config.yaml
38 |
39 | bindir=${ACCESS_OM_DIR}/bin
40 |
41 | mkdir -p ${bindir}
42 |
43 | echo "Getting executable hashes..."
44 |
45 | cd $(dirname "${yatmpath}") && yatmhash=`git rev-parse --short=7 HEAD`
46 | test -z "$(git status --porcelain)" || yatmhash=${yatmhash}-modified # uncommitted changes or untracked files
47 | cd $(dirname "${fmspath}") && fmshash=`git rev-parse --short=7 HEAD`
48 | test -z "$(git status --porcelain)" || fmshash=${fmshash}-modified # uncommitted changes or untracked files
49 | fmshash=${fmshash}_libaccessom2_${yatmhash} # also track libaccessom2
50 | cd $(dirname "${cice1path}") && cicehash=`git rev-parse --short=7 HEAD` # NB only one hash for all three cice builds
51 | test -z "$(git status --porcelain)" || cicehash=${cicehash}-modified # uncommitted changes or untracked files
52 | cicehash=${cicehash}_libaccessom2_${yatmhash} # also track libaccessom2
53 |
54 | echo "Copying executables to "${bindir}" with hashes added to names..."
55 |
56 | yatmbn=$(basename "${yatmpath}")
57 | yatmhashexe="${yatmbn%.*}"_${yatmhash}."${yatmpath##*.}"
58 | echo " cp ${yatmpath} ${bindir}/${yatmhashexe}"
59 | cp ${yatmpath} ${bindir}/${yatmhashexe}
60 |
61 | fmsbn=$(basename "${fmspath}")
62 | fmshashexe="${fmsbn%.*}"_${fmshash}."${fmspath##*.}"
63 | echo " cp ${fmspath} ${bindir}/${fmshashexe}"
64 | cp ${fmspath} ${bindir}/${fmshashexe}
65 |
66 | cice1bn=$(basename "${cice1path}")
67 | cice1hashexe="${cice1bn%.*}"_${cicehash}."${cice1path##*.}"
68 | echo " cp ${cice1path} ${bindir}/${cice1hashexe}"
69 | cp ${cice1path} ${bindir}/${cice1hashexe}
70 |
71 | cice025bn=$(basename "${cice025path}")
72 | cice025hashexe="${cice025bn%.*}"_${cicehash}."${cice025path##*.}"
73 | echo " cp ${cice025path} ${bindir}/${cice025hashexe}"
74 | cp ${cice025path} ${bindir}/${cice025hashexe}
75 |
76 | cice010bn=$(basename "${cice010path}")
77 | cice010hashexe="${cice010bn%.*}"_${cicehash}."${cice010path##*.}"
78 | echo " cp ${cice010path} ${bindir}/${cice010hashexe}"
79 | cp ${cice010path} ${bindir}/${cice010hashexe}
80 |
81 | cice010bn_18x15=$(basename "${cice010path_18x15}")
82 | cice010hashexe_18x15="${cice010bn_18x15%.*}"_${cicehash}."${cice010path_18x15##*.}"
83 | echo " cp ${cice010path_18x15} ${bindir}/${cice010hashexe_18x15}"
84 | cp ${cice010path_18x15} ${bindir}/${cice010hashexe_18x15}
85 |
86 | echo " cp ${mppnccombinepath} ${bindir}/mppnccombine"
87 | cp ${mppnccombinepath} ${bindir}/mppnccombine # no hash for mppnccombine
88 |
89 | echo "Fixing exe in "${config1ryfpath}" to match executable names..."
90 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config1ryfpath} > ${config1ryfpath}-tmp
91 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config1ryfpath}-tmp > ${config1ryfpath}-tmp2
92 | sed "s|exe:.*${cice1bn%.*}_.*|exe: ${bindir}/${cice1hashexe}|g" < ${config1ryfpath}-tmp2 > ${config1ryfpath}-tmp3
93 | diff ${config1ryfpath} ${config1ryfpath}-tmp3 || true
94 | mv ${config1ryfpath}-tmp3 ${config1ryfpath}
95 | rm ${config1ryfpath}-tmp*
96 |
97 | echo "Fixing exe in "${config025ryfpath}" to match executable names..."
98 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config025ryfpath} > ${config025ryfpath}-tmp
99 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config025ryfpath}-tmp > ${config025ryfpath}-tmp2
100 | sed "s|exe:.*${cice025bn%.*}_.*|exe: ${bindir}/${cice025hashexe}|g" < ${config025ryfpath}-tmp2 > ${config025ryfpath}-tmp3
101 | diff ${config025ryfpath} ${config025ryfpath}-tmp3 || true
102 | mv ${config025ryfpath}-tmp3 ${config025ryfpath}
103 | rm ${config025ryfpath}-tmp*
104 |
105 | echo "Fixing exe in "${config010ryfpath}" to match executable names..."
106 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config010ryfpath} > ${config010ryfpath}-tmp
107 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config010ryfpath}-tmp > ${config010ryfpath}-tmp2
108 | sed "s|exe:.*${cice010bn%.*}_.*|exe: ${bindir}/${cice010hashexe}|g" < ${config010ryfpath}-tmp2 > ${config010ryfpath}-tmp3
109 | diff ${config010ryfpath} ${config010ryfpath}-tmp3 || true
110 | mv ${config010ryfpath}-tmp3 ${config010ryfpath}
111 | rm ${config010ryfpath}-tmp*
112 |
113 | echo "Fixing exe in "${config1iafpath}" to match executable names..."
114 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config1iafpath} > ${config1iafpath}-tmp
115 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config1iafpath}-tmp > ${config1iafpath}-tmp2
116 | sed "s|exe:.*${cice1bn%.*}_.*|exe: ${bindir}/${cice1hashexe}|g" < ${config1iafpath}-tmp2 > ${config1iafpath}-tmp3
117 | diff ${config1iafpath} ${config1iafpath}-tmp3 || true
118 | mv ${config1iafpath}-tmp3 ${config1iafpath}
119 | rm ${config1iafpath}-tmp*
120 |
121 | echo "Fixing exe in "${config025iafpath}" to match executable names..."
122 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config025iafpath} > ${config025iafpath}-tmp
123 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config025iafpath}-tmp > ${config025iafpath}-tmp2
124 | sed "s|exe:.*${cice025bn%.*}_.*|exe: ${bindir}/${cice025hashexe}|g" < ${config025iafpath}-tmp2 > ${config025iafpath}-tmp3
125 | diff ${config025iafpath} ${config025iafpath}-tmp3 || true
126 | mv ${config025iafpath}-tmp3 ${config025iafpath}
127 | rm ${config025iafpath}-tmp*
128 |
129 | echo "Fixing exe in "${config010iafpath}" to match executable names..."
130 | sed "s|exe:.*${yatmbn%.*}_.*|exe: ${bindir}/${yatmhashexe}|g" < ${config010iafpath} > ${config010iafpath}-tmp
131 | sed "s|exe:.*${fmsbn%.*}_.*|exe: ${bindir}/${fmshashexe}|g" < ${config010iafpath}-tmp > ${config010iafpath}-tmp2
132 | sed "s|exe:.*${cice010bn%.*}_.*|exe: ${bindir}/${cice010hashexe}|g" < ${config010iafpath}-tmp2 > ${config010iafpath}-tmp3
133 | diff ${config010iafpath} ${config010iafpath}-tmp3 || true
134 | mv ${config010iafpath}-tmp3 ${config010iafpath}
135 | rm ${config010iafpath}-tmp*
136 |
137 | # TODO: fix sed script to handle changes of mom_type
138 | echo
139 | echo "WARNING: if your previous exe mom_type was not ${mom_type} it will need to be manually updated in the config.yaml file"
140 | echo
141 | sleep 1
142 |
143 | echo "$(basename $BASH_SOURCE) completed."
144 |
145 |
--------------------------------------------------------------------------------
/install.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # Compile ACCESS-OM2 at 1, 1/4 and 1/10 degree resolution with JRA-55-do forcing
4 | # Andrew Kiss https://github.com/aekiss
5 |
6 | set -e
7 |
8 | #Type of MOM installation
9 |
10 | export mom_type=ACCESS-OM
11 | #export mom_type=ACCESS-OM-BGC
12 |
13 | echo "MOM5 build is of type mom_type=${mom_type}"
14 | sleep 1
15 |
16 | # Disable user gitconfig
17 | export GIT_CONFIG_NOGLOBAL=yes
18 |
19 | if [[ -z "${ACCESS_OM_DIR}" ]]; then
20 | echo "Installing ACCESS-OM2 in $(pwd)"
21 | export ACCESS_OM_DIR=$(pwd)
22 | fi
23 | export LIBACCESSOM2_ROOT=$ACCESS_OM_DIR/src/libaccessom2
24 |
25 | declare -a exepaths=(${ACCESS_OM_DIR}/src/mom/exec/nci/${mom_type}/fms_${mom_type}.x ${LIBACCESSOM2_ROOT}/build/bin/yatm.exe ${ACCESS_OM_DIR}/src/cice5/build_auscom_360x300_24p/cice_auscom_360x300_24p.exe ${ACCESS_OM_DIR}/src/cice5/build_auscom_1440x1080_480p/cice_auscom_1440x1080_480p.exe ${ACCESS_OM_DIR}/src/cice5/build_auscom_3600x2700_722p/cice_auscom_3600x2700_722p.exe ${ACCESS_OM_DIR}/src/cice5/build_auscom_18x15.3600x2700_1682p/cice_auscom_18x15.3600x2700_1682p.exe ${ACCESS_OM_DIR}/src/mom/bin/mppnccombine.nci)
26 | # ${ACCESS_OM_DIR}/src/matm/build_nt62/matm_nt62.exe
27 | # ${ACCESS_OM_DIR}/src/matm/build_jra55/matm_jra55.exe
28 |
29 | cd ${ACCESS_OM_DIR}
30 |
31 | # echo "Downloading experiment input data and creating directories..."
32 | # ${ACCESS_OM_DIR}/get_input_data.py
33 |
34 | echo
35 | echo "Removing previous executables (if any)..."
36 | for p in "${exepaths[@]}"
37 | do
38 | rm ${p} && echo "rm ${p}"
39 | done
40 |
41 | echo
42 | echo "Compiling YATM file-based atmosphere and libaccessom2... "
43 | cd ${LIBACCESSOM2_ROOT}
44 | source ./build_on_gadi.sh
45 |
46 | echo
47 | echo "Compiling MOM5.1..."
48 | cd ${ACCESS_OM_DIR}/src/mom/exp
49 | ./MOM_compile.csh --type $mom_type --platform nci
50 |
51 | cd ${ACCESS_OM_DIR}/src/cice5
52 | echo
53 | echo "Compiling CICE5.1 at 1 degree..."
54 | make # 1 degree
55 | echo
56 | echo "Compiling CICE5.1 at 1/4 degree..."
57 | make 025deg
58 | echo
59 | echo "Compiling CICE5.1 at 1/10 degree..."
60 | make 01deg
61 | echo
62 | echo "Compiling CICE5.1 at 1/10 degree with more blocks..."
63 | make 01deg_18x15
64 |
65 | echo
66 | echo "Checking all executables have been built..."
67 | for p in "${exepaths[@]}"
68 | do
69 | ls ${p} || { echo "Build failed!"; exit 1; }
70 | done
71 |
72 | echo
73 | source ${ACCESS_OM_DIR}/hashexe.sh
74 |
75 | cd ${ACCESS_OM_DIR}
76 | echo
77 | echo "Executables were built using these library versions:"
78 | source ${ACCESS_OM_DIR}/libcheck.sh
79 |
80 | echo
81 | echo "$(basename "$0") completed."
82 | echo
83 |
84 | # exit 0
85 |
86 |
--------------------------------------------------------------------------------
/libcheck.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # Report library versions used in model components of ACCESS-OM2
4 | # Andrew Kiss https://github.com/aekiss
5 | # mom_type= ACCESS-OM for default or ACCESS-OM-BGC for WOMBAT :RASF
6 |
7 | if [[ -z "${ACCESS_OM_DIR}" ]]; then
8 | export ACCESS_OM_DIR=$(pwd)
9 | fi
10 | if [[ -z "${LIBACCESSOM2_ROOT}" ]]; then
11 | export LIBACCESSOM2_ROOT=$ACCESS_OM_DIR/src/libaccessom2
12 | fi
13 | if [[ -z "${mom_type}" ]]; then
14 | export mom_type=ACCESS-OM-BGC
15 | fi
16 |
17 | declare -a libs=(openmpi netcdf)
18 |
19 | declare -a paths=(${ACCESS_OM_DIR}/src/mom/bin/environs.nci ${ACCESS_OM_DIR}/src/cice5/bld/config.nci.auscom.360x300 ${ACCESS_OM_DIR}/src/cice5/bld/config.nci.auscom.1440x1080 ${ACCESS_OM_DIR}/src/cice5/bld/config.nci.auscom.3600x2700 ${ACCESS_OM_DIR}/src/cice5/bld/config.nci.auscom.18x15.3600x2700 ${LIBACCESSOM2_ROOT}/build_on_gadi.sh ${LIBACCESSOM2_ROOT}/oasis3-mct/util/make_dir/config.gadi)
20 |
21 | declare -a exepaths=(${ACCESS_OM_DIR}/src/mom/exec/nci/${mom_type}/fms_${mom_type}.x ${ACCESS_OM_DIR}/src/cice5/build_auscom_360x300_24p/cice_auscom_360x300_24p.exe ${ACCESS_OM_DIR}/src/cice5/build_auscom_1440x1080_480p/cice_auscom_1440x1080_480p.exe ${ACCESS_OM_DIR}/src/cice5/build_auscom_3600x2700_722p/cice_auscom_3600x2700_722p.exe ${ACCESS_OM_DIR}/src/cice5/build_auscom_18x15.3600x2700_1682p/cice_auscom_18x15.3600x2700_1682p.exe ${LIBACCESSOM2_ROOT}/build/bin/yatm.exe ${ACCESS_OM_DIR}/src/mom/bin/mppnccombine.nci)
22 |
23 | for l in "${libs[@]}"
24 | do
25 | echo $l library versions used:
26 | echo " in build scripts:"
27 | for p in "${paths[@]}"
28 | do
29 | echo -n " "
30 | grep -H $l $p
31 | done
32 | echo " in executables:"
33 | for p in "${exepaths[@]}"
34 | do
35 | echo " $p: "
36 | ldd $p | grep $l || true
37 | done
38 | done
39 |
40 |
--------------------------------------------------------------------------------
/test/checksums/cm_1440x1080-test.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/COSIMA/access-om2/c35ebfaaaf287041b42998f1a9a40191cef9b79b/test/checksums/cm_1440x1080-test.txt
--------------------------------------------------------------------------------
/test/checksums/cm_360x300-test.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/COSIMA/access-om2/c35ebfaaaf287041b42998f1a9a40191cef9b79b/test/checksums/cm_360x300-test.txt
--------------------------------------------------------------------------------
/test/checksums/om_1440x1080-test.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/COSIMA/access-om2/c35ebfaaaf287041b42998f1a9a40191cef9b79b/test/checksums/om_1440x1080-test.txt
--------------------------------------------------------------------------------
/test/dump_field.F90:
--------------------------------------------------------------------------------
1 |
2 | module dump_field
3 |
4 | ! Dump a field. Subsequent calls with the same field name and proc will a new
5 | ! time point to the same file. See the test program below for use.
6 |
7 | use netcdf
8 | implicit none
9 |
10 | private
11 | public dump_field_2d, dump_field_close
12 |
13 | type field_info_type
14 | integer :: count
15 | integer :: ncid
16 | integer :: varid
17 | integer :: min_varid
18 | integer :: max_varid
19 | integer :: mean_varid
20 | character(len=256) :: field_name
21 | end type field_info_type
22 |
23 | ! Array containing list of field names and associated data, e.g. ncid.
24 | integer, parameter :: MAX_FIELDS = 256
25 | type (field_info_type), dimension(MAX_FIELDS) :: field_info
26 | integer :: field_num = 1
27 |
28 | contains
29 |
30 | subroutine setup_2d(field_name, proc_num, nx, ny, do_full_dump)
31 |
32 | character(len=*), intent(in) :: field_name
33 | integer, intent(in) :: nx, ny, proc_num
34 | logical, intent(in) :: do_full_dump
35 |
36 | integer :: ncid, varid, min_varid, max_varid, mean_varid, x_dimid, y_dimid, t_dimid
37 | character(len=6) :: proc_str
38 |
39 | if (proc_num > 999999) then
40 | stop 'Error: dump_field::setup_2d(), proc_num too high.'
41 | endif
42 |
43 | write(proc_str, '(I6.6)') proc_num
44 |
45 | ! Open a file, set up a meta-data needed to save the field.
46 | call check(nf90_create(field_name//'.'//proc_str//'.nc', NF90_CLOBBER, ncid))
47 | call check(nf90_def_dim(ncid, 't', NF90_UNLIMITED, t_dimid))
48 | if (do_full_dump) then
49 | call check(nf90_def_dim(ncid, 'x', nx, x_dimid))
50 | call check(nf90_def_dim(ncid, 'y', ny, y_dimid))
51 | call check(nf90_def_var(ncid, field_name, NF90_REAL, (/ x_dimid, y_dimid, t_dimid /), varid))
52 | field_info(field_num)%varid = varid
53 | endif
54 | call check(nf90_def_var(ncid, field_name//'_min', NF90_REAL, (/ t_dimid /), min_varid))
55 | call check(nf90_def_var(ncid, field_name//'_max', NF90_REAL, (/ t_dimid /), max_varid))
56 | call check(nf90_def_var(ncid, field_name//'_mean', NF90_REAL, (/ t_dimid /), mean_varid))
57 | call check(nf90_enddef(ncid))
58 |
59 | field_info(field_num)%field_name = field_name
60 | field_info(field_num)%ncid = ncid
61 | field_info(field_num)%min_varid = min_varid
62 | field_info(field_num)%max_varid = max_varid
63 | field_info(field_num)%mean_varid = mean_varid
64 | field_info(field_num)%count = 1
65 |
66 | field_num = field_num + 1
67 | if (field_num > MAX_FIELDS) then
68 | stop 'Error: dump_field::setup_2d(), too many fields.'
69 | endif
70 |
71 | end subroutine
72 |
73 | subroutine dump_field_2d(field_name, proc_num, field_data, do_full_dump)
74 | ! Search through field names and find appropriate file handle.
75 | ! Save to file.
76 |
77 | character(len=*), intent(in) :: field_name
78 | integer, intent(in) :: proc_num
79 | real, dimension(:,:), intent(in) :: field_data
80 | logical, intent(in), optional :: do_full_dump
81 |
82 | real :: mean
83 | integer :: start(3), data_size(3), idx
84 | logical :: found, dump
85 |
86 | found = .false.
87 | dump = .false.
88 |
89 | if (present(do_full_dump)) then
90 | dump = do_full_dump
91 | end if
92 |
93 | call get_index(field_name, idx, found)
94 | if (.not. found) then
95 | call setup_2d(field_name, proc_num, size(field_data, 1), size(field_data, 2), dump)
96 | end if
97 |
98 | call get_index(field_name, idx, found)
99 | if (.not. found) then
100 | stop 'save_field_mod::field_write'
101 | end if
102 |
103 | data_size = (/ size(field_data, 1), size(field_data, 2), 1 /)
104 | start = (/ 1, 1, field_info(idx)%count /)
105 |
106 | ! Dump data
107 | if (dump) then
108 | call check(nf90_put_var(field_info(idx)%ncid, field_info(idx)%varid, field_data, start=start, count=data_size))
109 | end if
110 |
111 | ! Write out some stats.
112 | call check(nf90_put_var(field_info(idx)%ncid, field_info(idx)%max_varid, (/ maxval(field_data) /), &
113 | start=(/ field_info(idx)%count /), count=(/ 1 /)))
114 | call check(nf90_put_var(field_info(idx)%ncid, field_info(idx)%min_varid, (/ minval(field_data) /), &
115 | start=(/ field_info(idx)%count /), count=(/ 1 /)))
116 | mean = sum(field_data) / (size(field_data, 1) * size(field_data, 2))
117 | call check(nf90_put_var(field_info(idx)%ncid, field_info(idx)%mean_varid, (/ mean /), &
118 | start=(/ field_info(idx)%count /), count=(/ 1 /)))
119 |
120 | call check(nf90_sync(field_info(idx)%ncid))
121 |
122 | field_info(idx)%count = field_info(idx)%count + 1
123 |
124 | end subroutine
125 |
126 | subroutine dump_field_close(field_name)
127 |
128 | character(len=*), intent(in) :: field_name
129 |
130 | integer :: idx
131 | logical :: found
132 |
133 | call get_index(field_name, idx, found)
134 | if (.not. found) then
135 | stop 'save_field_mod::field_close()'
136 | end if
137 |
138 | call check(nf90_close(field_info(idx)%ncid))
139 |
140 | end subroutine
141 |
142 | subroutine get_index(field_name, idx, found)
143 |
144 | character(len=*), intent(in) :: field_name
145 | integer, intent(out) :: idx
146 | logical, intent(out) :: found
147 |
148 | found = .false.
149 | do idx=1, field_num
150 | if (field_name == field_info(idx)%field_name) then
151 | found = .true.
152 | return
153 | end if
154 | end do
155 |
156 | end subroutine get_index
157 |
158 | subroutine check(status)
159 | integer, intent ( in) :: status
160 |
161 | if(status /= nf90_noerr) then
162 | print *, trim(nf90_strerror(status))
163 | stop 'save_field_mod::check()'
164 | end if
165 | end subroutine check
166 |
167 | end module
168 |
169 | program test_dump_field
170 |
171 | use dump_field
172 |
173 | real, dimension(3, 3) :: array
174 |
175 | array = reshape((/ 12.0, 32.0, 1.23123, 55.0, 3322.0, 65.0, 0.123, 99.0, 10.0 /), shape(array))
176 | call dump_field_2d('sst', 4, array, .true.)
177 |
178 | array = reshape((/ 3099.0, 554343.0, 0.3221, 405.0, 23.0, 56.0, 123.0, 89.0, 0.000002 /), shape(array))
179 | call dump_field_2d('sst', 4, array, .true.)
180 |
181 | call dump_field_close('sst')
182 |
183 | end program
184 |
185 |
--------------------------------------------------------------------------------
/test/exp_test_helper.py:
--------------------------------------------------------------------------------
1 |
2 | from __future__ import print_function
3 |
4 | import subprocess as sp
5 | import sys
6 | import stat
7 | import shutil
8 | import re
9 | import os
10 | import sys
11 | import glob
12 | import time
13 | import yaml
14 |
15 | from util import wait_for_qsub, get_git_hash
16 |
17 | class ExpTestHelper(object):
18 |
19 | def __init__(self, exp_name, bin_path=None):
20 |
21 | self.exp_name = exp_name
22 | self.res = exp_name.split('deg')[0].split('_')[-1] + 'deg'
23 |
24 | self.my_path = os.path.dirname(os.path.realpath(__file__))
25 | self.lab_path = os.path.realpath(os.path.join(self.my_path, '../'))
26 | if not bin_path:
27 | self.bin_path = os.path.join(self.lab_path, 'bin')
28 | else:
29 | self.bin_path = bin_path
30 | self.control_path = os.path.join(self.lab_path, 'control')
31 | self.exp_path = os.path.join(self.control_path, exp_name)
32 | self.payu_config = os.path.join(self.exp_path, 'config.yaml')
33 | self.accessom2_config = os.path.join(self.exp_path, 'accessom2.nml')
34 | self.ocean_config = os.path.join(self.exp_path, 'ocean', 'input.nml')
35 | self.archive = os.path.join(self.lab_path, 'archive', exp_name)
36 | self.output000 = os.path.join(self.archive, 'output000')
37 | self.output001 = os.path.join(self.archive, 'output001')
38 | self.accessom2_out_000 = os.path.join(self.output000, 'access-om2.out')
39 | self.accessom2_out_001 = os.path.join(self.output001, 'access-om2.out')
40 |
41 | self.src = os.path.join(self.lab_path, 'src')
42 |
43 | self.libaccessom2_src = os.path.join(self.src, 'libaccessom2')
44 | self.mom_src = os.path.join(self.src, 'mom')
45 | self.cice_src = os.path.join(self.src, 'cice5')
46 | self.yatm_exe = None
47 | self.mom_exe = None
48 | self.cice_exe = None
49 | self.input_path = '/short/public/access-om2/input_rc'
50 |
51 | self.mom_input = os.path.join(self.input_path, 'mom_' + self.res)
52 | self.cice_input = os.path.join(self.input_path, 'cice_' + self.res)
53 |
54 | if not os.path.exists(self.bin_path):
55 | os.mkdir(self.bin_path)
56 |
57 | def has_run(self):
58 | """
59 | See wether this experiment has been run.
60 | """
61 |
62 | return os.path.exists(os.path.join(self.output000, 'access-om2.out'))
63 |
64 | def make_paths(self, exp_name, run_num=0):
65 | paths = {}
66 | run_num = str(run_num).zfill(3)
67 |
68 | paths['archive_link'] = os.path.join(paths['exp'], 'archive')
69 | paths['output'] = os.path.join(paths['archive'], 'output' + run_num)
70 | paths['restart'] = os.path.join(paths['archive'], 'restart' + run_num)
71 | paths['stdout'] = os.path.join(paths['output'], 'access.out')
72 | paths['stderr'] = os.path.join(paths['output'], 'access.err')
73 |
74 | paths['stdout_runtime'] = os.path.join(paths['exp'], 'access.out')
75 | paths['stderr_runtime'] = os.path.join(paths['exp'], 'access.err')
76 |
77 | return paths
78 |
79 | def print_output(self, files):
80 |
81 | for file in files:
82 | if file is not None:
83 | if os.path.exists(file):
84 | with open(file, 'r') as f:
85 | print(f.read())
86 |
87 | def get_most_recent_run_num(self, archive_path):
88 | """
89 | Look in the archive directory to find which build this is.
90 | """
91 |
92 | dirs = glob.glob(archive_path + '/output*')
93 | dirs.sort()
94 |
95 | return int(dirs[-1][-3:])
96 |
97 | def setup_for_programmatic_run(self, exes):
98 | """
99 | Various config.yaml settings need to be modified in order to run in the
100 | test environment.
101 | """
102 |
103 | yatm_exe, cice_exe, mom_exe = exes
104 |
105 | with open(self.payu_config) as f:
106 | doc = yaml.safe_load(f)
107 |
108 | doc['submodels'][0]['exe'] = yatm_exe
109 | doc['submodels'][1]['exe'] = mom_exe
110 | doc['submodels'][2]['exe'] = cice_exe
111 | doc['runlog'] = False
112 |
113 | with open(self.payu_config, 'w') as f:
114 | yaml.dump(doc, f)
115 |
116 | def do_basic_access_run(self, exp, model='cm'):
117 | paths = self.make_paths(exp)
118 | ret, qso, qse, qsub_files = self.run()
119 | if ret != 0:
120 | self.print_output([qso, qse,
121 | paths['stdout_runtime'],
122 | paths['stderr_runtime']])
123 | fstring = 'Run {} failed with code {}.'
124 | print(fstring.format(exp, ret), file=sys.stderr)
125 | assert(ret == 0)
126 |
127 | run_num = self.get_most_recent_run_num(paths['archive'])
128 | paths = self.make_paths(exp, run_num)
129 |
130 | # Model output should exist.
131 | assert(os.path.exists(paths['output']))
132 | assert(os.path.exists(paths['restart']))
133 | assert(os.path.exists(paths['stdout']))
134 | assert(os.path.exists(paths['stderr']))
135 |
136 | with open(paths['stdout'], 'r') as f:
137 | s = f.read()
138 | assert('MOM4: --- completed ---' in s)
139 | if model == 'om':
140 | assert('********** End of MATM **********' in s)
141 |
142 | def copy_to_bin(self, src_dir, wildcard, libaccessom2_src=None):
143 | exes = glob.glob(wildcard)
144 | if len(exes) != 1:
145 | print("Error: copy_to_bin can't find one {}".format(wildcard), file=sys.stderr)
146 | return None, 1
147 | exe = exes[0]
148 |
149 | ghash = get_git_hash(src_dir)
150 | if libaccessom2_src:
151 | libaccessom2_hash = get_git_hash(libaccessom2_src)
152 | else:
153 | libaccessom2_hash = None
154 |
155 | eb = os.path.basename(exe)
156 | if libaccessom2_hash:
157 | new_name = '{}_{}_libaccessom2_{}.{}'.format(eb.split('.')[0], ghash,
158 | libaccessom2_hash, eb.split('.')[1])
159 | else:
160 | new_name = '{}_{}.{}'.format(eb.split('.')[0], ghash,
161 | eb.split('.')[1])
162 | dest = os.path.join(self.bin_path, new_name)
163 | if os.path.exists(dest):
164 | os.remove(dest)
165 |
166 | shutil.copy(exe, dest)
167 | shutil.chown(dest, group='ik11')
168 | perms = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IXUSR \
169 | | stat.S_IXGRP | stat.S_IXOTH
170 | os.chmod(dest, perms)
171 |
172 | return dest, 0
173 |
174 |
175 | def build_libaccessom2(self, clean=False):
176 | """
177 | Note: the 'clean' arg does nothing.
178 | """
179 |
180 | r1 = sp.call([os.path.join(self.libaccessom2_src, 'build_on_gadi.sh')])
181 | exename, r2 = self.copy_to_bin(self.libaccessom2_src,
182 | self.libaccessom2_src + '/build/bin/yatm.exe')
183 | return exename, r1 + r2
184 |
185 | def build_cice(self, clean=False):
186 | os.environ['ACCESS_OM_DIR'] = os.path.join(self.lab_path)
187 | os.environ['LIBACCESSOM2_ROOT'] = os.path.join(self.libaccessom2_src)
188 | if clean:
189 | r1 = sp.call(['make', '-C', self.cice_src, 'clean'])
190 | r1 = sp.call(['make', '-C', self.cice_src, self.res])
191 |
192 | if self.res == '025deg':
193 | exe_res = '1440x1080'
194 | elif self.res == '01deg':
195 | exe_res = '3600x2700'
196 | elif self.res == '1deg':
197 | exe_res = '360x300'
198 | else:
199 | assert False
200 |
201 | build_dir_wildcard = self.cice_src + '/build_*_' + exe_res + '_*p/*.exe'
202 | exename, r2 = self.copy_to_bin(self.cice_src, build_dir_wildcard,
203 | self.libaccessom2_src)
204 |
205 | return exename, r1 + r2
206 |
207 | def build_mom(self, clean=False):
208 | """
209 | Note: the 'clean' arg does nothing.
210 | """
211 |
212 | os.environ['ACCESS_OM_DIR'] = os.path.join(self.lab_path)
213 | os.environ['LIBACCESSOM2_ROOT'] = os.path.join(self.libaccessom2_src)
214 |
215 | mydir = os.getcwd()
216 | os.chdir(os.path.join(self.mom_src, 'exp'))
217 | r1 = sp.call(['./MOM_compile.csh', '--type', 'ACCESS-OM',
218 | '--platform', 'nci', '--repro'])
219 | os.chdir(mydir)
220 |
221 | exename, r2 = self.copy_to_bin(self.mom_src,
222 | self.mom_src + '/exec/nci/ACCESS-OM/*.x',
223 | self.libaccessom2_src)
224 | return exename, r1 + r2
225 |
226 | def build(self, clean=False):
227 |
228 | self.yatm_exe, r1 = self.build_libaccessom2(clean)
229 | if r1 != 0:
230 | print('YATM build failed for exp {}'.format(self.exp_name),
231 | file=sys.stderr)
232 | return r1
233 | self.cice_exe, r2 = self.build_cice(clean)
234 | if r2 != 0:
235 | print('CICE build failed for exp {}'.format(self.exp_name),
236 | file=sys.stderr)
237 |
238 | self.mom_exe, r3 = self.build_mom(clean)
239 | if r3 != 0:
240 | print('MOM build failed for exp {}'.format(self.exp_name),
241 | file=sys.stderr)
242 |
243 | return [self.yatm_exe, self.cice_exe, self.mom_exe], r1 + r2 + r3
244 |
245 | def run(self):
246 | """
247 | Run the experiment using payu and check output.
248 |
249 | Don't do any work if it has already run.
250 | """
251 |
252 | if self.has_run():
253 | return 0, None, None, None
254 | else:
255 | return self.force_run()
256 |
257 | def force_qsub_run(self):
258 | """
259 | Run using qsub
260 | """
261 |
262 | # Change to experiment directory and run.
263 | try:
264 | os.chdir(self.exp_path)
265 | sp.check_output(['payu', 'sweep', '--lab', self.lab_path])
266 | run_id = sp.check_output(['payu', 'run', '--lab', self.lab_path])
267 | run_id = run_id.decode().splitlines()[0]
268 | os.chdir(self.my_path)
269 | except sp.CalledProcessError as err:
270 | os.chdir(self.my_path)
271 | print('Error: call to payu run failed.', file=sys.stderr)
272 | return 1, None, None, None
273 |
274 | wait_for_qsub(run_id)
275 | run_id = run_id.split('.')[0]
276 |
277 | output_files = []
278 | # Read qsub stdout file
279 | stdout_filename = glob.glob(os.path.join(self.exp_path,
280 | '*.o{}'.format(run_id)))
281 | if len(stdout_filename) != 1:
282 | print('Error: there are too many stdout files.', file=sys.stderr)
283 | return 2, None, None, None
284 |
285 | stdout_filename = stdout_filename[0]
286 | output_files.append(stdout_filename)
287 | stdout = ''
288 | with open(stdout_filename, 'r') as f:
289 | stdout = f.read()
290 |
291 | # Read qsub stderr file
292 | stderr_filename = glob.glob(os.path.join(self.exp_path,
293 | '*.e{}'.format(run_id)))
294 | stderr = ''
295 | if len(stderr_filename) == 1:
296 | stderr_filename = stderr_filename[0]
297 | output_files.append(stderr_filename)
298 | with open(stderr_filename, 'r') as f:
299 | stderr = f.read()
300 |
301 | # Read the qsub id of the collate job from the stdout.
302 | # Payu puts this here.
303 | m = re.search(r'(\d+.gadi-pbs)\n', stdout)
304 | if m is None:
305 | print('Error: qsub id of collate job.', file=sys.stderr)
306 | return 3, stdout, stderr, output_files
307 |
308 | # Wait for the collate to complete.
309 | run_id = m.group(1)
310 | wait_for_qsub(run_id)
311 |
312 | # Return files created by qsub so caller can read or delete.
313 | collate_files = os.path.join(self.exp_path, '*.[oe]{}'.format(run_id))
314 | output_files += glob.glob(collate_files)
315 |
316 | return 0, stdout, stderr, output_files
317 |
318 | def force_interactive_run(self):
319 | """
320 | Already in a PBS session, run interactively
321 | """
322 |
323 | # Change to experiment directory and run.
324 | try:
325 | os.chdir(self.exp_path)
326 | sp.check_output(['payu', 'sweep', '--lab', self.lab_path])
327 | sp.check_output(['payu-run', '--lab', self.lab_path])
328 | except sp.CalledProcessError as err:
329 | os.chdir(self.my_path)
330 | print('Error: call to payu run failed.', file=sys.stderr)
331 | return 1, None, None, None
332 |
333 | return 0, None, None, None
334 |
335 | def force_run(self):
336 | """
337 | Always try to run.
338 | """
339 |
340 | try:
341 | dont_care = os.environ['PBS_NODEFILE']
342 | is_interactive = True
343 | except:
344 | is_interactive = False
345 |
346 | # Check whether this is an interactive PBS session.
347 | if is_interactive:
348 | ret, stdout, stderr, output_files = self.force_interactive_run()
349 | else:
350 | ret, stdout, stderr, output_files = self.force_qsub_run()
351 |
352 | return ret, stdout, stderr, output_files
353 |
354 |
355 | def build_and_run(self):
356 |
357 | exes, ret = self.build()
358 | assert ret == 0
359 | self.setup_for_programmatic_run(exes)
360 | self.force_run()
361 |
362 |
363 | def setup_exp_from_base(base_exp_name, new_exp_name):
364 | """
365 | Create a new exp by copying the base config
366 | """
367 |
368 | base_exp = ExpTestHelper(base_exp_name)
369 |
370 | new_exp_path = os.path.join(base_exp.control_path, new_exp_name)
371 | if os.path.exists(new_exp_path):
372 | shutil.rmtree(new_exp_path)
373 | shutil.copytree(base_exp.exp_path, new_exp_path, symlinks=True)
374 |
375 | new_exp = ExpTestHelper(new_exp_name)
376 | if os.path.exists(new_exp.archive):
377 | shutil.rmtree(new_exp.archive)
378 |
379 | try:
380 | os.remove(os.path.join(new_exp.control_path, 'archive'))
381 | except OSError:
382 | pass
383 | try:
384 | os.remove(os.path.join(new_exp.control_path, 'work'))
385 | except OSError:
386 | pass
387 |
388 | return new_exp
389 |
390 |
391 | def run_exp(exp_name, force=False):
392 | my_path = os.path.dirname(os.path.realpath(__file__))
393 |
394 | helper = ExpTestHelper(exp_name)
395 | exes, ret = helper.build()
396 | assert ret == 0
397 | helper.setup_for_programmatic_run(exes)
398 |
399 | if force:
400 | ret, qso, qse, qsub_files = helper.force_run()
401 | else:
402 | ret, qso, qse, qsub_files = helper.run()
403 |
404 | assert ret == 0
405 |
406 | return helper
407 |
--------------------------------------------------------------------------------
/test/load_dump.py:
--------------------------------------------------------------------------------
1 |
2 | import netCDF4 as nc
3 |
4 |
5 | def load(exp, routine, input_names, output_names):
6 | """
7 | Load the input and output data for a particular unit test.
8 | """
9 |
10 | inputs = {}
11 | outputs = {}
12 |
13 | for i in input_names:
14 | with nc.Dataset(routine + '-' + i) as f:
15 | inputs[i] = f.variables[i].data
16 |
17 | for o in output_names:
18 | with nc.Dataset(routine + '-' + o) as f:
19 | outputs[o] = f.variables[o].data
20 |
21 | return inputs, outputs
22 |
23 |
24 | def load_coupling_fields(exp, field_names):
25 | """
26 |
27 | """
28 |
--------------------------------------------------------------------------------
/test/requirements_test.txt:
--------------------------------------------------------------------------------
1 | pytest
2 | pylint
3 | numpy
4 | f90nml
5 | netCDF4
6 | nose
7 | numba
8 | numpy
9 | pyyaml
10 | GitPython
11 | scipy
12 |
--------------------------------------------------------------------------------
/test/test_bit_reproducibility.py:
--------------------------------------------------------------------------------
1 |
2 | from exp_test_helper import ExpTestHelper, setup_exp_from_base
3 |
4 | import pytest
5 | import f90nml
6 | import shutil
7 | import os
8 | import sys
9 | import re
10 |
11 | class TestBitReproducibility():
12 |
13 | def checksums_to_list(self, filename):
14 | """
15 | Look at each line an make a list of checksums
16 | """
17 |
18 | regex_a = re.compile(r'\[chksum\]\s+.*\s+-?[0-9]+$')
19 | regex_b = re.compile(r'\[chksum\] Ice_ocean_boundary.*\s+-?[0-9]+$')
20 | l = []
21 | with open(filename) as f:
22 | for line in f:
23 | m = regex_a.match(line)
24 | if m:
25 | l.append(line)
26 | else:
27 | m = regex_b.match(line)
28 | if m:
29 | l.append(line)
30 | return l
31 |
32 | @pytest.mark.slow
33 | def test_bit_repro_repeat(self):
34 | """
35 | Test that a run reproduces saved checksums.
36 | """
37 |
38 | exp_bit_repo1 = setup_exp_from_base('1deg_jra55_iaf', '1deg_jra55_iaf_bit_repo1')
39 | exp_bit_repo2 = setup_exp_from_base('1deg_jra55_iaf', '1deg_jra55_iaf_bit_repo2')
40 |
41 | # Reconfigure to a 1 day and do run
42 | for exp in [exp_bit_repo1, exp_bit_repo2]:
43 | with open(exp.accessom2_config) as f:
44 | nml = f90nml.read(f)
45 |
46 | nml['date_manager_nml']['restart_period'] = [0, 0, 86400]
47 | nml.write(exp.accessom2_config, force=True)
48 | exp.build_and_run()
49 |
50 | # Compare expected to produced.
51 | assert os.path.exists(exp_bit_repo1.accessom2_out_000)
52 | expected = self.checksums_to_list(exp_bit_repo1.accessom2_out_000)
53 | expected.sort()
54 |
55 | assert os.path.exists(exp_bit_repo2.accessom2_out_000)
56 | produced = self.checksums_to_list(exp_bit_repo2.accessom2_out_000)
57 | produced.sort()
58 |
59 | if produced != expected:
60 | with open('checksums-produced-test_bit_repo.txt', 'w') as f:
61 | f.write('\n'.join(produced))
62 | with open('checksums-expected-test_bit_repo.txt', 'w') as f:
63 | f.write('\n'.join(expected))
64 |
65 | assert len(produced) > 0
66 | assert len(produced) == len(expected)
67 | assert produced == expected
68 |
69 | @pytest.mark.slow
70 | def test_bit_repro_historical(self):
71 | """
72 | Test that a run reproduces saved checksums.
73 | """
74 |
75 | exp_bit_repo = setup_exp_from_base('1deg_jra55_iaf', '1deg_jra55_iaf_bit_repo')
76 |
77 | # Reconfigure to a 1 day and do run
78 | with open(exp_bit_repo.accessom2_config) as f:
79 | nml = f90nml.read(f)
80 |
81 | nml['date_manager_nml']['restart_period'] = [0, 0, 86400]
82 | nml.write(exp_bit_repo.accessom2_config, force=True)
83 | exp_bit_repo.build_and_run()
84 |
85 | assert os.path.exists(exp_bit_repo.accessom2_out_000)
86 | produced = self.checksums_to_list(exp_bit_repo.accessom2_out_000)
87 |
88 | # Compare expected to produced.
89 | test_stdout = os.path.join('checksums', '1deg_jra55_iaf-access-om2.out')
90 | assert os.path.exists(test_stdout)
91 | expected = self.checksums_to_list(test_stdout)
92 |
93 | wrong = 0
94 | assert len(produced) > 0
95 | for line in produced:
96 | if line not in expected:
97 | wrong = wrong + 1
98 | with open('checksums-produced-test_bit_repo.txt', 'w') as f:
99 | f.write('\n'.join(produced))
100 | with open('checksums-expected-test_bit_repo.txt', 'w') as f:
101 | f.write('\n'.join(expected))
102 |
103 | assert wrong == 0
104 |
105 | @pytest.mark.fast
106 | def test_restart_repro(self):
107 | """
108 | Test that a run reproduces across restarts.
109 | """
110 |
111 | # First do two short (1 day) runs.
112 | exp_2x1day = setup_exp_from_base('1deg_jra55_iaf', '1deg_jra55_iaf_2x1day')
113 |
114 | # Reconfigure to a 1 day run.
115 | with open(exp_2x1day.accessom2_config) as f:
116 | nml = f90nml.read(f)
117 |
118 | nml['date_manager_nml']['restart_period'] = [0, 0, 86400]
119 | nml.write(exp_2x1day.accessom2_config, force=True)
120 |
121 | # Don't use Redsea fix - this breaks reproducibility
122 | # https://github.com/COSIMA/access-om2/issues/124
123 | with open(exp_2x1day.ocean_config) as f:
124 | nml = f90nml.read(f)
125 |
126 | nml['auscom_ice_nml']['redsea_gulfbay_sfix'] = False
127 | nml.write(exp_2x1day.ocean_config, force=True)
128 |
129 | # Now run twice.
130 | exp_2x1day.build_and_run()
131 | exp_2x1day.force_run()
132 |
133 | # Now do a single 2 day run
134 | exp_2day = setup_exp_from_base('1deg_jra55_iaf', '1deg_jra55_iaf_2day')
135 | # Reconfigure
136 | with open(exp_2day.accessom2_config) as f:
137 | nml = f90nml.read(f)
138 |
139 | nml['date_manager_nml']['restart_period'] = [0, 0, 172800]
140 | nml.write(exp_2day.accessom2_config, force=True)
141 |
142 | # Don't use Redsea fix - this breaks reproducibility
143 | # https://github.com/COSIMA/access-om2/issues/124
144 | with open(exp_2day.ocean_config) as f:
145 | nml = f90nml.read(f)
146 |
147 | nml['auscom_ice_nml']['redsea_gulfbay_sfix'] = False
148 | nml.write(exp_2day.ocean_config, force=True)
149 |
150 | # Run once.
151 | exp_2day.build_and_run()
152 |
153 | # Now compare the output between our two short and one long run.
154 | two_shrt = self.checksums_to_list(exp_2x1day.accessom2_out_000)
155 | two_shrt = two_shrt + self.checksums_to_list(exp_2x1day.accessom2_out_001)
156 |
157 | one_long = self.checksums_to_list(exp_2day.accessom2_out_000)
158 |
159 | assert len(one_long) > 0
160 | for line in one_long:
161 | if line not in two_shrt:
162 | with open('checksums-two_short-test_restart_repo.txt', 'w') as f:
163 | f.write('\n'.join(two_shrt))
164 | with open('checksums-one_long-test_restart_repo.txt', 'w') as f:
165 | f.write('\n'.join(one_long))
166 | assert line in two_shrt
167 |
168 | # Additionally check that the temp and salt fields of the final restart
169 | # are identical
170 |
--------------------------------------------------------------------------------
/test/test_build.py:
--------------------------------------------------------------------------------
1 |
2 | from exp_test_helper import ExpTestHelper
3 |
4 | class TestBuild():
5 |
6 | def test_build_libaccessom2(self):
7 | helper = ExpTestHelper('1deg_jra55_ryf')
8 | exe, ret = helper.build_libaccessom2()
9 | assert ret == 0
10 |
11 | def test_build_1deg_cice(self):
12 | helper = ExpTestHelper('1deg_jra55_ryf')
13 | exe, ret = helper.build_cice()
14 | assert ret == 0
15 |
16 | def test_build_025deg_cice(self):
17 | helper = ExpTestHelper('025deg_jra55_ryf')
18 | exe, ret = helper.build_cice()
19 | assert ret == 0
20 |
21 | def test_build_01deg_cice(self):
22 | helper = ExpTestHelper('01deg_jra55_ryf')
23 | exe, ret = helper.build_cice()
24 | assert ret == 0
25 |
26 | def test_build_mom(self):
27 | helper = ExpTestHelper('1deg_jra55_ryf')
28 | exe, ret = helper.build_mom()
29 | assert ret == 0
30 |
--------------------------------------------------------------------------------
/test/test_coupling_fields.py:
--------------------------------------------------------------------------------
1 |
2 | from __future__ import print_function
3 |
4 | import os
5 | import netCDF4 as nc
6 |
7 | from exp_test_helper import ExpTestHelper
8 |
9 |
10 | class TestCouplingFields(ExpTestHelper):
11 |
12 | def __init__(self):
13 | super(TestCouplingFields, self).__init__()
14 |
15 | def test_swflx(self):
16 | """
17 | Compare short wave flux over a geographic area between low and hi res
18 | models.
19 | """
20 |
21 | hi_paths = self.make_paths('cm_1440x1080-test')
22 | lo_paths = self.make_paths('cm_360x300-test')
23 |
24 | hi_fields = os.path.join(hi_paths['output'], 'ice',
25 | 'fields_a2i_in_ice.nc')
26 | lo_fields = os.path.join(lo_paths['output'], 'ice',
27 | 'fields_a2i_in_ice.nc')
28 | f_hi = nc.Dataset(hi_fields)
29 | f_hi.close()
30 | f_lo = nc.Dataset(lo_fields)
31 | f_lo.close()
32 |
--------------------------------------------------------------------------------
/test/test_grids_match.py:
--------------------------------------------------------------------------------
1 |
2 | from exp_test_helper import ExpTestHelper
3 | import os
4 | import glob
5 | import netCDF4 as nc
6 | import numpy as np
7 | import pytest
8 |
9 | def find_nearest_index(array, value):
10 | return (np.abs(array - value)).argmin()
11 |
12 | class TestGridMatch():
13 | """
14 | Test that MOM and CICE grids match
15 | """
16 |
17 | @pytest.mark.fast
18 | def test_mom_and_cice_output_grids(self):
19 | """
20 | Compare mom output grid to cice output grid
21 | """
22 |
23 | helper = ExpTestHelper('minimal_01deg_jra55_ryf_control')
24 | fo = nc.Dataset(os.path.join(helper.output000, 'ocean', 'ocean_grid.nc'))
25 | iceh = glob.glob(os.path.join(helper.archive, 'output*', 'ice',
26 | 'OUTPUT', 'iceh.*.nc'))
27 | fi = nc.Dataset(iceh[0])
28 |
29 | fo_tmp = nc.Dataset(os.path.join(helper.mom_input, 'ocean_hgrid.nc'))
30 | fi_tmp = nc.Dataset(os.path.join(helper.cice_input, 'grid.nc'))
31 |
32 | xtmp = fo_tmp.variables['x'][:]
33 | ytmp = fo_tmp.variables['y'][:]
34 |
35 | xo_t = fo.variables['geolon_t'][:]
36 | xo_t[np.where(xo_t < 0)] += 360.0
37 | yo_t = fo.variables['geolat_t'][:]
38 | xo_u = fo.variables['geolon_c'][:]
39 | xo_u[np.where(xo_u < 0)] += 360.0
40 | yo_u = fo.variables['geolat_c'][:]
41 |
42 | xi_t = fi.variables['TLON'][:].astype('f')
43 | yi_t = fi.variables['TLAT'][:].astype('f')
44 | xi_u = fi.variables['ULON'][:].astype('f')
45 | yi_u = fi.variables['ULAT'][:].astype('f')
46 |
47 | mask = np.logical_or(xo_t.mask, xi_t.mask)
48 | assert np.ma.allclose(np.ma.array(xo_t, mask=mask), np.ma.array(xi_t, mask=mask), atol=0, rtol=1e-6)
49 | assert np.ma.allclose(np.ma.array(yo_t, mask=mask), np.ma.array(yi_t, mask=mask), atol=0, rtol=1e-6)
50 | #assert np.ma.allclose(np.ma.array(xo_u, mask=mask), np.ma.array(xi_u, mask=mask), atol=0, rtol=1e-6)
51 | #assert np.ma.allclose(np.ma.array(yo_u, mask=mask), np.ma.array(yi_u, mask=mask), atol=0, rtol=1e-6)
52 |
53 | dxo_t = fo.variables['dxt'][:]
54 | dyo_t = fo.variables['dyt'][:]
55 | dxo_u = fo.variables['dxu'][:]
56 | dyo_u = fo.variables['dyu'][:]
57 |
58 | dxi_t = fi.variables['dxt'][:]
59 | dyi_t = fi.variables['dyt'][:]
60 | dxi_u = fi.variables['dxu'][:]
61 | dyi_u = fi.variables['dyu'][:]
62 |
63 | mask = np.logical_or(dxo_t.mask, dxi_t.mask)
64 | assert np.ma.allclose(np.ma.array(dxo_t, mask=mask), np.ma.array(dxi_t, mask=mask), atol=0, rtol=1e-6)
65 | #assert np.ma.allclose(np.ma.array(dyo_t, mask=mask), np.ma.array(dyi_t, mask=mask), atol=0, rtol=1e-6)
66 | assert np.ma.allclose(np.ma.array(dxo_u, mask=mask), np.ma.array(dxi_u, mask=mask), atol=0, rtol=1e-6)
67 | #assert np.ma.allclose(np.ma.array(dyo_u, mask=mask), np.ma.array(dyi_u, mask=mask), atol=0, rtol=1e-6)
68 |
69 | areao_tmp = fo_tmp.variables['area'][:]
70 |
71 | areao_t = fo.variables['area_t'][:]
72 | areao_u = fo.variables['area_u'][:]
73 |
74 | areai_t = fi.variables['tarea'][:].astype('f')
75 | areai_u = fi.variables['uarea'][:].astype('f')
76 |
77 | # Area is difficult to compare because MOM uses dx*dy not the area from
78 | # ocean_hgrid.nc. We compare cells south of 65N.
79 | idx = find_nearest_index(yo_t[:, 0], 65.0)
80 |
81 | mask = np.logical_or(areao_t.mask, areai_t.mask)
82 | assert np.ma.allclose(np.ma.array(areao_t, mask=mask)[:idx, :], np.ma.array(areai_t, mask=mask)[:idx, :])
83 | #assert np.ma.allclose(np.ma.array(areao_u, mask=mask)[:idx, :], np.ma.array(areai_u, mask=mask)[:idx, :])
84 |
85 | import pdb
86 | pdb.set_trace()
87 |
88 | fo.close()
89 | fi.close()
90 |
91 | @pytest.mark.slow
92 | def test_mom_and_cice_input_grids(self):
93 | """
94 | Test that the input grids match
95 | """
96 |
97 | helper = ExpTestHelper('minimal_01deg_jra55_ryf_control')
98 | fo = nc.Dataset(os.path.join(helper.mom_input, 'ocean_hgrid.nc'))
99 | fi = nc.Dataset(os.path.join(helper.cice_input, 'grid.nc'))
100 | with nc.Dataset(os.path.join(helper.mom_input, 'ocean_mask.nc')) as f:
101 | mask = 1 - f.variables['mask'][:]
102 |
103 | x = fo.variables['x'][:, :]
104 | y = fo.variables['y'][:, :]
105 |
106 | # t-cell centres
107 | xo_t = x[1::2, 1::2]
108 | yo_t = y[1::2, 1::2]
109 |
110 | xi_t = np.rad2deg(fi.variables['tlon'][:])
111 | yi_t = np.rad2deg(fi.variables['tlat'][:])
112 |
113 | assert np.allclose(xi_t, xo_t, atol=0, rtol=1e-15)
114 | assert np.allclose(yi_t, yo_t, atol=0, rtol=1e-15)
115 |
116 | # u-cell centres
117 | xo_u = x[2::2, 2::2]
118 | yo_u = y[2::2, 2::2]
119 |
120 | xi_u = np.rad2deg(fi.variables['ulon'][:])
121 | yi_u = np.rad2deg(fi.variables['ulat'][:])
122 |
123 | #assert np.allclose(xi_u, xo_u, atol=0, rtol=1e-15)
124 | #assert np.allclose(yi_u, yo_u, atol=0, rtol=1e-15)
125 |
126 | #del x, y, xo_t, yo_t, xi_t, yi_t, xo_u, yo_u, xi_u, yi_u
127 |
128 | # cell area
129 | # Add up areas, going clockwise from bottom left.
130 | area = fo.variables['area'][:]
131 | areao_t = area[0::2, 0::2] + area[1::2, 0::2] + area[1::2, 1::2] + area[0::2, 1::2]
132 |
133 | # These need to wrap around the globe. Copy ocn_area and
134 | # add an extra column at the end.
135 | area_ext = np.append(area[:], area[:, 0:1], axis=1)
136 | areao_u = area_ext[0::2, 1::2] + area_ext[1::2, 1::2] + area_ext[1::2, 2::2] + area_ext[0::2, 2::2]
137 |
138 | areai_t = fi.variables['tarea'][:]
139 | areai_u = fi.variables['uarea'][:]
140 |
141 | assert np.array_equal(areao_t, areai_t)
142 | assert np.array_equal(areao_u, areai_u)
143 |
144 | # cell edge length
145 | # Grab the Northern and Eastern edge distances, not the centre distance,
146 | # this is what cice should be using.
147 | dx = fo.variables['dx'][:]
148 | dy = fo.variables['dy'][:]
149 | dxo_t = dx[2::2, ::2] + dx[2::2, 1::2]
150 | dyo_t = dy[::2, 2::2] + dy[1::2, 2::2]
151 |
152 | dxi_t = fi.variables['htn'][:] / 100
153 | dyi_t = fi.variables['hte'][:] / 100
154 |
155 | assert np.allclose(dxi_t, dxo_t, atol=0, rtol=1e-15)
156 | assert np.allclose(dyi_t, dyo_t, atol=0, rtol=1e-15)
157 |
158 | import pdb
159 | pdb.set_trace()
160 |
161 | # angle wrt East
162 | angleo_t = fo.variables['angle_dx'][1::2, 1::2]
163 | angleo_u = np.ma.array(fo.variables['angle_dx'][2::2, 2::2], mask=mask)
164 |
165 | anglei_t = np.rad2deg(fi.variables['angleT'][:])
166 | anglei_u = np.ma.array(np.rad2deg(fi.variables['angle'][:]), mask=mask)
167 |
168 | #import pdb
169 | #pdb.set_trace()
170 |
171 | assert np.allclose(anglei_t, angleo_t, atol=0, rtol=1e-15)
172 | # Compare U using the land mask because MOM sets some land only longitudes to zero.
173 | assert np.ma.allclose(anglei_u, angleo_u, atol=0, rtol=1e-15)
174 |
175 | fo.close()
176 | fi.close()
177 |
178 | def test_mom_and_cice_mask(self):
179 |
180 | helper = ExpTestHelper('minimal_01deg_jra55_ryf_control')
181 |
182 | with nc.Dataset(os.path.join(helper.mom_input, 'ocean_mask.nc')) as f:
183 | omask = f.variables['mask'][:]
184 |
185 | with nc.Dataset(os.path.join(helper.cice_input, 'kmt.nc')) as f:
186 | imask = f.variables['mask'][:]
187 |
188 | import pdb
189 | pdb.set_trace()
190 |
191 |
--------------------------------------------------------------------------------
/test/test_remapping_weights.py:
--------------------------------------------------------------------------------
1 |
2 | from __future__ import print_function
3 |
4 | from exp_test_helper import ExpTestHelper
5 | import os
6 | import numpy as np
7 | import numba
8 | import netCDF4 as nc
9 | import subprocess as sp
10 | import multiprocessing as mp
11 |
12 | EARTH_RADIUS = 6370997.0
13 |
14 | def calc_regridding_err(weights, src, dest):
15 | """
16 | Calculate the regirdding error.
17 | """
18 |
19 | with nc.Dataset(weights) as f:
20 | try:
21 | area_a = f.variables['area_a'][:]
22 | except KeyError as e:
23 | area_a = f.variables['src_grid_area'][:]
24 | area_a = area_a.reshape(src.shape[0], src.shape[1])
25 | area_a = area_a*EARTH_RADIUS**2
26 |
27 | try:
28 | area_b = f.variables['area_b'][:]
29 | except KeyError as e:
30 | area_b = f.variables['dst_grid_area'][:]
31 | area_b = area_b.reshape(dest.shape[0], dest.shape[1])
32 | area_b = area_b*EARTH_RADIUS**2
33 |
34 | try:
35 | frac_a = f.variables['frac_a'][:]
36 | except KeyError as e:
37 | frac_a = f.variables['src_grid_frac'][:]
38 | frac_a = frac_a.reshape(src.shape[0], src.shape[1])
39 |
40 | try:
41 | frac_b = f.variables['frac_b'][:]
42 | except KeyError as e:
43 | frac_b = f.variables['dst_grid_frac'][:]
44 | frac_b = frac_b.reshape(dest.shape[0], dest.shape[1])
45 |
46 | # Calculation of totals here.
47 | # http://www.earthsystemmodeling.org/esmf_releases/non_public/ESMF_5_3_0/ESMC_crefdoc/node3.html
48 | src_tot = np.sum(src[:, :] * area_a[:, :] * frac_a[:, :])
49 | dest_tot = np.sum(dest[:, :] * area_b[:, :])
50 | rel_err = abs(src_tot - dest_tot) / dest_tot
51 |
52 | return rel_err
53 |
54 |
55 | @numba.jit
56 | def apply_weights(src, dest_shape, n_s, n_b, row, col, s):
57 | """
58 | Apply ESMF regirdding weights.
59 | """
60 |
61 | dest = np.ndarray(dest_shape).flatten()
62 | dest[:] = 0.0
63 | src = src.flatten()
64 |
65 | for i in range(n_s):
66 | dest[row[i]-1] = dest[row[i]-1] + s[i]*src[col[i]-1]
67 |
68 | print('src.shape: {}'.format(src.shape))
69 | print('n_s, n_b: {} {}'.format(n_s, n_b))
70 | fstring = 'sum(row[:]) = {}, sum(col[:]) = {}, sum(S[:]) = {}'
71 | print(fstring.format(np.sum(row[:]), np.sum(col[:]), np.sum(s[:])))
72 |
73 | return dest.reshape(dest_shape)
74 |
75 |
76 | def remap(src_data, weights, dest_shape):
77 | """
78 | Regrid a 2d field and see how it looks.
79 | """
80 |
81 | dest_data = np.ndarray(dest_shape)
82 |
83 | with nc.Dataset(weights) as wf:
84 | try:
85 | n_s = wf.dimensions['n_s'].size
86 | except KeyError as e:
87 | n_s = wf.dimensions['num_links'].size
88 | try:
89 | n_b = wf.dimensions['n_b'].size
90 | except KeyError as e:
91 | n_b = wf.dimensions['dst_grid_size'].size
92 | try:
93 | row = wf.variables['row'][:]
94 | except KeyError as e:
95 | row = wf.variables['dst_address'][:]
96 | try:
97 | col = wf.variables['col'][:]
98 | except KeyError as e:
99 | col = wf.variables['src_address'][:]
100 |
101 | s = wf.variables['S'][:]
102 |
103 | dest_data[:, :] = apply_weights(src_data[:, :], dest_data.shape,
104 | n_s, n_b, row, col, s)
105 | return dest_data
106 |
107 |
108 | class TestRemap():
109 | def test_jra55_to_01deg(self):
110 |
111 | helper = ExpTestHelper('01deg_jra55_ryf')
112 | weights = os.path.join(helper.input_path, 'yatm_01deg',
113 | 'rmp_jrar_to_cict_CONSERV.nc')
114 | src = np.random.rand(1440, 720)
115 | dest = remap(src, weights, (3600, 2700))
116 |
117 | rel_err = calc_regridding_err(weights, src, dest)
118 | print('relative error {}'.format(rel_err))
119 |
120 | assert rel_err < 1e-14
121 |
122 | def test_jra55_to_1deg(self):
123 | pass
124 |
125 | def test_jra55_to_025deg(self):
126 | pass
127 |
128 |
129 | class TestCreateWeights():
130 | """
131 | Create weights and compare to existing.
132 | """
133 |
134 | def test_build_esmf(self):
135 | """
136 | Build ESMF
137 | """
138 |
139 | helper = ExpTestHelper('01deg_jra55_ryf')
140 |
141 | contrib_dir = os.path.join(helper.lab_path, 'tools', 'contrib')
142 | os.chdir(contrib_dir)
143 | ret = sp.call('./build_esmf_on_raijin.sh')
144 | os.chdir(helper.lab_path)
145 |
146 | assert ret == 0
147 | assert os.path.exists(os.path.join(contrib_dir, 'bin', 'ESMF_RegridWeightGen'))
148 |
149 | def test_create_weights(self):
150 | """
151 | Create weights
152 | """
153 |
154 | helper = ExpTestHelper('01deg_jra55_ryf')
155 |
156 | # Build ESMF_RegridWeightGen if it doesn't already exist
157 | contrib_dir = os.path.join(helper.lab_path, 'tools', 'contrib')
158 | bpath = os.path.join(contrib_dir, 'bin', 'ESMF_RegridWeightGen')
159 | if not os.path.exists(bpath):
160 | self.test_build_esmf()
161 |
162 | cmd = os.path.join(os.getcwd(), 'tools', 'make_remap_weights.py')
163 | jra55_dir = '/g/data/ua8/JRA55-do/RYF/v1-3/'
164 | core_dir = os.path.join(helper.input_path, 'yatm_1deg')
165 |
166 | # Change to contrib bin dir to use ESMF_RegridWeightGen
167 | bin_dir = os.path.join(contrib_dir, 'bin')
168 | os.chdir(bin_dir)
169 |
170 | # We don't always test the more expensive weight creation.
171 | if (mp.cpu_count() // 2) < 8:
172 | ret = sp.call([cmd, helper.input_path, jra55_dir, core_dir,
173 | '--ocean', 'MOM1'])
174 | os.chdir(helper.lab_path)
175 | assert ret == 0
176 | ocn = ['MOM1']
177 | else:
178 | ret = sp.call([cmd, helper.input_path, jra55_dir, core_dir])
179 | os.chdir(helper.lab_path)
180 | assert ret == 0
181 | ocn = ['MOM1', 'MOM025', 'MOM01']
182 |
183 | atm = ['JRA55', 'JRA55_runoff', 'CORE2', 'Daitren_runoff']
184 | method = ['patch', 'conserve2nd']
185 |
186 | for o in ocn:
187 | for a in atm:
188 | for m in method:
189 | filename = '{}_{}_{}.nc'.format(a, o, m)
190 | assert os.path.exists(os.path.join(bin_dir, filename))
191 |
--------------------------------------------------------------------------------
/test/test_run.py:
--------------------------------------------------------------------------------
1 |
2 | from exp_test_helper import run_exp
3 |
4 | import pytest
5 |
6 |
7 | class TestRun():
8 | """
9 | Run and check return code.
10 | """
11 |
12 | @pytest.mark.fast
13 | def test_1deg_jra55_ryf_run(self):
14 | run_exp('1deg_jra55_ryf')
15 |
16 | @pytest.mark.slow
17 | def test_1deg_jra55_iaf_run(self):
18 | run_exp('1deg_jra55_iaf')
19 |
20 | @pytest.mark.slow
21 | def test_slow_run(self):
22 | run_exp('025deg_jra55_ryf')
23 |
24 | @pytest.mark.slow
25 | def test_slow_run_iaf(self):
26 | run_exp('025deg_jra55_iaf')
27 |
--------------------------------------------------------------------------------
/test/test_startup.py:
--------------------------------------------------------------------------------
1 |
2 | from __future__ import print_function
3 |
4 | import netCDF4 as nc
5 | import os
6 | import filecmp
7 | from nose.plugins.attrib import attr
8 |
9 | from exp_test_helper import ExpTestHelper
10 |
11 |
12 | class TestStartUp(ExpTestHelper):
13 |
14 | def test_coupling_restarts_change(self):
15 | """
16 | Check that the coupling restarts change between subsequent runs. If not
17 | they're not being regenerated properly.
18 | """
19 |
20 | exps = ['cm_360x300-test', 'om_360x300-test']
21 | cpl_restarts = ['a2i.nc', 'i2a.nc', 'o2i.nc', 'i2o.nc']
22 | for e in exps:
23 | for r in cpl_restarts:
24 | run0_paths = self.make_paths(e, 0)
25 | run1_paths = self.make_paths(e, 1)
26 |
27 | self.get_most_recent_run_num(run0_paths['archive'])
28 |
29 | file0 = os.path.join(run0_paths['restart'], 'coupler', r)
30 | file1 = os.path.join(run1_paths['restart'], 'coupler', r)
31 |
32 | assert(not filecmp.cmp(file0, file1))
33 |
34 | def test_coupling_restarts_loaded(self):
35 | """
36 | Check that the fields on the first timestep are
37 | the same as the OASIS restarts.
38 | """
39 |
40 | pass
41 |
--------------------------------------------------------------------------------
/test/test_valgrind.py:
--------------------------------------------------------------------------------
1 |
2 | from __future__ import print_function
3 |
4 | import shutil
5 | import os
6 |
7 | from exp_test_helper import ExpTestHelper
8 |
9 | tests = {'om_360x300-valgrind': ('om'),
10 | 'om_1440x1080-valgrind': ('om')}
11 |
12 |
13 | class TestValgrind(ExpTestHelper):
14 | """
15 | Run the model in valgrind.
16 | """
17 |
18 | def __init__(self):
19 | super(TestValgrind, self).__init__()
20 |
21 | def pre_run_cleanup(self, exp):
22 |
23 | paths = self.make_paths(exp)
24 |
25 | try:
26 | shutil.rmtree(paths['archive'])
27 | os.remove(paths['archive_link'])
28 | except OSError as e:
29 | if not e.strerror == 'No such file or directory':
30 | raise e
31 |
32 | def check_run(self, key):
33 |
34 | print('############ Running {} ############'.format(key))
35 | self.pre_run_cleanup(key)
36 | self.do_basic_access_run(key, model=tests[key][0])
37 |
38 | # FIXME: check that valgrind does not find any problems.
39 |
40 | def test_runs(self):
41 | for k in tests.keys():
42 | yield self.check_run, k
43 |
--------------------------------------------------------------------------------
/test/util.py:
--------------------------------------------------------------------------------
1 |
2 | import os
3 | import time
4 | import subprocess as sp
5 |
6 | def wait_for_qsub(run_id):
7 | """
8 | Wait for the qsub job to terminate.
9 | """
10 |
11 | while True:
12 | time.sleep(10*60)
13 | try:
14 | qsub_out = sp.check_output(['qstat', run_id], stderr=sp.STDOUT)
15 | except sp.CalledProcessError as err:
16 | qsub_out = err.output
17 |
18 | qsub_out = qsub_out.decode()
19 |
20 | if 'Job has finished' in qsub_out:
21 | break
22 |
23 |
24 | def get_git_hash(src_dir):
25 | """
26 | Get the git hash of src_dir.
27 | """
28 | mydir = os.getcwd()
29 | os.chdir(src_dir)
30 | ghash = sp.check_output(['git', 'rev-parse', 'HEAD'])[:8]
31 | os.chdir(mydir)
32 |
33 | return ghash.decode('utf-8')
34 |
--------------------------------------------------------------------------------
/test/valgrind_suppressions.txt:
--------------------------------------------------------------------------------
1 | {
2 |
3 | Memcheck:Cond
4 | fun:__intel_sse2_strcpy
5 | fun:for__open_proc
6 | fun:for__open_default
7 | fun:for_write_seq_fmt
8 | fun:ocean_momentum_source_mod_mp_rayleigh_damp_table_init_
9 | fun:ocean_momentum_source_mod_mp_ocean_momentum_source_init_
10 | fun:ocean_model_mod_mp_ocean_model_init_
11 | fun:MAIN__
12 | fun:main
13 | }
14 | {
15 |
16 | Memcheck:Cond
17 | fun:__intel_sse2_strcpy
18 | fun:for__open_proc
19 | fun:for__open_default
20 | fun:for_write_seq_fmt
21 | fun:sf_exch_
22 | fun:sf_expl_
23 | fun:bdy_layr_
24 | fun:bl_intct_
25 | fun:ni_bl_ctl_
26 | fun:atmos_physics2_
27 | fun:atm_step_
28 | fun:u_model_
29 | }
30 | {
31 |
32 | Memcheck:Cond
33 | fun:cvt_integer64_to_text
34 | fun:for__format_value
35 | fun:for_write_seq_fmt_xmit
36 | fun:for_write_seq_fmt
37 | fun:wrtwblog_
38 | fun:routedbl_
39 | fun:riv_rout_
40 | fun:riv_intctl_
41 | fun:atmos_physics2_
42 | fun:atm_step_
43 | fun:u_model_
44 | fun:um_shell_
45 | }
46 | {
47 |
48 | Memcheck:Cond
49 | fun:cvt_integer64_to_text
50 | fun:for__format_value
51 | fun:for_write_seq_fmt_xmit
52 | fun:wrtwblog_
53 | fun:routedbl_
54 | fun:riv_rout_
55 | fun:riv_intctl_
56 | fun:atmos_physics2_
57 | fun:atm_step_
58 | fun:u_model_
59 | fun:um_shell_
60 | fun:MAIN__
61 | }
62 | {
63 |
64 | Memcheck:Addr16
65 | fun:kill_trailing
66 | fun:nf_inq_varid_
67 | fun:ice_read_write_mp_ice_read_nc_
68 | fun:ice_grid_mp_popgrid_nc_
69 | fun:ice_grid_mp_init_grid2_
70 | fun:cice_initmod_mp_cice_init_
71 | fun:cice_initmod_mp_cice_initialize_
72 | fun:MAIN__
73 | fun:main
74 | }
75 | {
76 |
77 | Memcheck:Addr16
78 | fun:__intel_sse2_strlen
79 | fun:kill_trailing
80 | fun:nf_inq_dim_
81 | fun:netcdf_mp_nf90_inquire_dimension_
82 | fun:ice_read_write_mp_ice_read_nc_
83 | fun:ice_grid_mp_popgrid_nc_
84 | fun:ice_grid_mp_init_grid2_
85 | fun:cice_initmod_mp_cice_init_
86 | fun:cice_initmod_mp_cice_initialize_
87 | fun:MAIN__
88 | fun:main
89 | }
90 | {
91 |
92 | Memcheck:Addr16
93 | fun:kill_trailing
94 | fun:nf_inq_varid_
95 | fun:ice_read_write_mp_ice_read_global_nc_
96 | fun:ice_grid_mp_popgrid_nc_
97 | fun:ice_grid_mp_init_grid2_
98 | fun:cice_initmod_mp_cice_init_
99 | fun:cice_initmod_mp_cice_initialize_
100 | fun:MAIN__
101 | fun:main
102 | }
103 | {
104 |
105 | Memcheck:Addr16
106 | fun:kill_trailing
107 | fun:nf_inq_varid_
108 | fun:ice_read_write_mp_ice_read_nc_
109 | fun:cpl_forcing_handler_mp_get_time0_sstsss_
110 | fun:cice_initmod_mp_cice_init_
111 | fun:cice_initmod_mp_cice_initialize_
112 | fun:MAIN__
113 | fun:main
114 | }
115 | {
116 |
117 | Memcheck:Addr16
118 | fun:kill_trailing
119 | fun:nf_open_
120 | fun:netcdf_mp_nf90_open_
121 | fun:ice_read_write_mp_ice_open_nc_
122 | fun:cpl_forcing_handler_mp_get_restart_o2i_
123 | fun:cice_initmod_mp_cice_init_
124 | fun:cice_initmod_mp_cice_initialize_
125 | fun:MAIN__
126 | fun:main
127 | }
128 | {
129 |
130 | Memcheck:Addr16
131 | fun:kill_trailing
132 | fun:nf_inq_varid_
133 | fun:ice_read_write_mp_ice_read_nc_
134 | fun:cpl_forcing_handler_mp_get_restart_o2i_
135 | fun:cice_initmod_mp_cice_init_
136 | fun:cice_initmod_mp_cice_initialize_
137 | fun:MAIN__
138 | fun:main
139 | }
140 | {
141 |
142 | Memcheck:Addr16
143 | fun:__intel_sse2_strlen
144 | fun:kill_trailing
145 | fun:nf_create_
146 | fun:netcdf_mp_nf90_create_
147 | fun:dump_field_mp_setup_2d_
148 | fun:dump_field_mp_dump_field_2d_
149 | fun:cpl_interface_mp_from_atm_
150 | fun:cice_runmod_mp_cice_run_
151 | fun:MAIN__
152 | fun:main
153 | }
154 | {
155 |
156 | Memcheck:Addr16
157 | fun:kill_trailing
158 | fun:nf_def_dim_
159 | fun:dump_field_mp_setup_2d_
160 | fun:dump_field_mp_dump_field_2d_
161 | fun:cpl_interface_mp_from_atm_
162 | fun:cice_runmod_mp_cice_run_
163 | fun:MAIN__
164 | fun:main
165 | }
166 | {
167 |
168 | Memcheck:Addr16
169 | fun:__intel_sse2_strlen
170 | fun:kill_trailing
171 | fun:nf_def_var_
172 | fun:netcdf_mp_nf90_def_var_manydims_
173 | fun:dump_field_mp_setup_2d_
174 | fun:dump_field_mp_dump_field_2d_
175 | fun:cpl_interface_mp_from_atm_
176 | fun:cice_runmod_mp_cice_run_
177 | fun:MAIN__
178 | fun:main
179 | }
180 | {
181 |
182 | Memcheck:Addr16
183 | fun:kill_trailing
184 | fun:nf_open_
185 | fun:netcdf_mp_nf90_open_
186 | fun:ice_read_write_mp_ice_open_nc_
187 | fun:cpl_forcing_handler_mp_get_restart_i2o_
188 | fun:cice_runmod_mp_cice_run_
189 | fun:MAIN__
190 | fun:main
191 | }
192 | {
193 |
194 | Memcheck:Addr16
195 | fun:kill_trailing
196 | fun:nf_inq_varid_
197 | fun:ice_read_write_mp_ice_read_nc_
198 | fun:cpl_forcing_handler_mp_get_restart_i2o_
199 | fun:cice_runmod_mp_cice_run_
200 | fun:MAIN__
201 | fun:main
202 | }
203 | {
204 |
205 | Memcheck:Cond
206 | fun:__intel_sse2_strcpy
207 | fun:for__open_proc
208 | fun:for__open_default
209 | fun:for_write_seq_lis
210 | fun:cpl_interface_mp_prism_init_
211 | fun:cice_initmod_mp_cice_init_
212 | fun:cice_initmod_mp_cice_initialize_
213 | fun:MAIN__
214 | fun:main
215 | }
216 | {
217 |
218 | Memcheck:Cond
219 | fun:__intel_sse2_strcpy
220 | fun:for__add_to_lf_table
221 | fun:for__open_proc
222 | fun:for__open_default
223 | fun:for_write_seq_lis
224 | fun:cpl_interface_mp_prism_init_
225 | fun:cice_initmod_mp_cice_init_
226 | fun:cice_initmod_mp_cice_initialize_
227 | fun:MAIN__
228 | fun:main
229 | }
230 | {
231 |
232 | Memcheck:Addr16
233 | fun:__intel_sse2_strlen
234 | fun:for__add_to_lf_table
235 | fun:for__open_proc
236 | fun:for__open_default
237 | fun:for_write_seq_fmt
238 | fun:mod_oasis_method_mp_oasis_init_comp_
239 | fun:oasis3_atmos_init_mp_oasis3_um_init_
240 | fun:um_shell_
241 | fun:MAIN__
242 | fun:main
243 | }
244 | {
245 |
246 | Memcheck:Addr16
247 | fun:__intel_sse2_strcpy
248 | fun:for__add_to_lf_table
249 | fun:for__open_proc
250 | fun:for__open_default
251 | fun:for_write_seq_fmt
252 | fun:mod_oasis_method_mp_oasis_init_comp_
253 | fun:oasis3_atmos_init_mp_oasis3_um_init_
254 | fun:um_shell_
255 | fun:MAIN__
256 | fun:main
257 | }
258 | {
259 |
260 | Memcheck:Param
261 | write(buf)
262 | obj:/lib64/libpthread-2.12.so
263 | fun:send_bytes
264 | fun:mca_oob_tcp_send_handler
265 | fun:opal_libevent2021_event_base_loop
266 | fun:orte_progress_thread_engine
267 | fun:start_thread
268 | fun:clone
269 | }
270 | {
271 |
272 | Memcheck:Value8
273 | obj:/plush/dugong/usr/lib64/libmlx4-rdmav2.so
274 | fun:udcm_process_messages
275 | fun:udcm_cq_event_dispatch
276 | fun:service_thread_start
277 | fun:start_thread
278 | fun:clone
279 | }
280 | {
281 |
282 | Memcheck:Cond
283 | obj:/plush/dugong/usr/lib64/libmlx4-rdmav2.so
284 | fun:udcm_process_messages
285 | fun:udcm_cq_event_dispatch
286 | fun:service_thread_start
287 | fun:start_thread
288 | fun:clone
289 | }
290 | {
291 |
292 | Memcheck:Value8
293 | obj:/plush/dugong/usr/lib64/libmlx4-rdmav2.so
294 | obj:/plush/dugong/usr/lib64/libmlx4-rdmav2.so
295 | fun:udcm_process_messages
296 | fun:udcm_cq_event_dispatch
297 | fun:service_thread_start
298 | fun:start_thread
299 | fun:clone
300 | }
301 | {
302 |
303 | Memcheck:Cond
304 | fun:ibv_create_ah
305 | fun:udcm_process_messages
306 | fun:udcm_cq_event_dispatch
307 | fun:service_thread_start
308 | fun:start_thread
309 | fun:clone
310 | }
311 | {
312 |
313 | Memcheck:Cond
314 | obj:/plush/dugong/usr/lib64/libmlx4-rdmav2.so
315 | fun:ibv_create_ah
316 | fun:udcm_process_messages
317 | fun:udcm_cq_event_dispatch
318 | fun:service_thread_start
319 | fun:start_thread
320 | fun:clone
321 | }
322 | {
323 |
324 | Memcheck:Cond
325 | obj:/plush/dugong/usr/lib64/libmlx4-rdmav2.so
326 | fun:udcm_post_send.clone.2
327 | fun:udcm_process_messages
328 | fun:udcm_cq_event_dispatch
329 | fun:service_thread_start
330 | fun:start_thread
331 | fun:clone
332 | }
333 | {
334 |
335 | Memcheck:Value8
336 | obj:/plush/dugong/usr/lib64/libmlx4-rdmav2.so
337 | fun:udcm_post_send.clone.2
338 | fun:udcm_process_messages
339 | fun:udcm_cq_event_dispatch
340 | fun:service_thread_start
341 | fun:start_thread
342 | fun:clone
343 | }
344 | {
345 |
346 | Memcheck:Value8
347 | obj:/plush/dugong/usr/lib64/libmlx4-rdmav2.so
348 | obj:/plush/dugong/usr/lib64/libmlx4-rdmav2.so
349 | fun:udcm_post_send.clone.2
350 | fun:udcm_process_messages
351 | fun:udcm_cq_event_dispatch
352 | fun:service_thread_start
353 | fun:start_thread
354 | fun:clone
355 | }
356 | {
357 |
358 | Memcheck:Cond
359 | fun:__intel_sse2_strcpy
360 | fun:for__open_proc
361 | fun:for__open_default
362 | fun:for_write_seq_lis
363 | fun:mod_oasis_sys_mp_oasis_unitget_
364 | fun:mod_oasis_method_mp_oasis_init_comp_
365 | fun:oasis3_atmos_init_mp_oasis3_um_init_
366 | fun:um_shell_
367 | fun:MAIN__
368 | fun:main
369 | }
370 | {
371 |
372 | Memcheck:Cond
373 | fun:__intel_sse2_strcpy
374 | fun:for__add_to_lf_table
375 | fun:for__open_proc
376 | fun:for__open_default
377 | fun:for_write_seq_lis
378 | fun:mod_oasis_sys_mp_oasis_unitget_
379 | fun:mod_oasis_method_mp_oasis_init_comp_
380 | fun:oasis3_atmos_init_mp_oasis3_um_init_
381 | fun:um_shell_
382 | fun:MAIN__
383 | fun:main
384 | }
385 | {
386 |
387 | Memcheck:Addr16
388 | fun:__intel_sse2_strlen
389 | fun:for__add_to_lf_table
390 | fun:for__open_proc
391 | fun:for_open
392 | fun:mod_oasis_method_mp_oasis_init_comp_
393 | fun:oasis3_atmos_init_mp_oasis3_um_init_
394 | fun:um_shell_
395 | fun:MAIN__
396 | fun:main
397 | }
398 | {
399 |
400 | Memcheck:Addr16
401 | fun:__intel_sse2_strcpy
402 | fun:for__add_to_lf_table
403 | fun:for__open_proc
404 | fun:for_open
405 | fun:mod_oasis_method_mp_oasis_init_comp_
406 | fun:oasis3_atmos_init_mp_oasis3_um_init_
407 | fun:um_shell_
408 | fun:MAIN__
409 | fun:main
410 | }
411 | {
412 |
413 | Memcheck:Cond
414 | fun:__intel_sse2_strcpy
415 | fun:for__open_proc
416 | fun:for_open
417 | fun:um_shell_
418 | fun:MAIN__
419 | fun:main
420 | }
421 | {
422 |
423 | Memcheck:Cond
424 | fun:__intel_sse2_strcpy
425 | fun:for__add_to_lf_table
426 | fun:for__open_proc
427 | fun:for_open
428 | fun:um_shell_
429 | fun:MAIN__
430 | fun:main
431 | }
432 | {
433 |
434 | Memcheck:Addr16
435 | fun:__intel_sse2_strlen
436 | fun:for__io_return
437 | fun:for_read_seq_nml
438 | fun:fms_mod_mp_nml_error_init_
439 | fun:fms_mod_mp_fms_init_
440 | fun:MAIN__
441 | fun:main
442 | }
443 | {
444 |
445 | Memcheck:Addr16
446 | fun:__intel_sse2_strlen
447 | fun:for__add_to_lf_table
448 | fun:for__open_proc
449 | fun:for__open_default
450 | fun:for_write_seq_fmt
451 | fun:mod_oasis_method_mp_oasis_init_comp_
452 | fun:mom_oasis3_interface_mod_mp_mom_prism_init_
453 | fun:main_IP_external_coupler_mpi_init_
454 | fun:MAIN__
455 | fun:main
456 | }
457 | {
458 |
459 | Memcheck:Addr16
460 | fun:__intel_sse2_strcpy
461 | fun:for__add_to_lf_table
462 | fun:for__open_proc
463 | fun:for__open_default
464 | fun:for_write_seq_fmt
465 | fun:mod_oasis_method_mp_oasis_init_comp_
466 | fun:mom_oasis3_interface_mod_mp_mom_prism_init_
467 | fun:main_IP_external_coupler_mpi_init_
468 | fun:MAIN__
469 | fun:main
470 | }
471 | {
472 |
473 | Memcheck:Addr16
474 | fun:__intel_sse2_strlen
475 | fun:for__add_to_lf_table
476 | fun:for__open_proc
477 | fun:for_open
478 | fun:mod_oasis_namcouple_mp_oasis_namcouple_init_
479 | fun:mod_oasis_method_mp_oasis_init_comp_
480 | fun:mom_oasis3_interface_mod_mp_mom_prism_init_
481 | fun:main_IP_external_coupler_mpi_init_
482 | fun:MAIN__
483 | fun:main
484 | }
485 | {
486 |
487 | Memcheck:Addr16
488 | fun:__intel_sse2_strcpy
489 | fun:for__add_to_lf_table
490 | fun:for__open_proc
491 | fun:for_open
492 | fun:mod_oasis_namcouple_mp_oasis_namcouple_init_
493 | fun:mod_oasis_method_mp_oasis_init_comp_
494 | fun:mom_oasis3_interface_mod_mp_mom_prism_init_
495 | fun:main_IP_external_coupler_mpi_init_
496 | fun:MAIN__
497 | fun:main
498 | }
499 | {
500 |
501 | Memcheck:Addr16
502 | fun:__intel_sse2_strlen
503 | fun:for__io_return
504 | fun:for_read_seq_fmt
505 | fun:mod_oasis_namcouple_mp_inipar_alloc_
506 | fun:mod_oasis_namcouple_mp_oasis_namcouple_init_
507 | fun:mod_oasis_method_mp_oasis_init_comp_
508 | fun:mom_oasis3_interface_mod_mp_mom_prism_init_
509 | fun:main_IP_external_coupler_mpi_init_
510 | fun:MAIN__
511 | fun:main
512 | }
513 | {
514 |
515 | Memcheck:Addr16
516 | fun:__intel_sse2_strlen
517 | fun:for__io_return
518 | fun:for_read_seq_fmt
519 | fun:mod_oasis_namcouple_mp_inipar_
520 | fun:mod_oasis_namcouple_mp_oasis_namcouple_init_
521 | fun:mod_oasis_method_mp_oasis_init_comp_
522 | fun:mom_oasis3_interface_mod_mp_mom_prism_init_
523 | fun:main_IP_external_coupler_mpi_init_
524 | fun:MAIN__
525 | fun:main
526 | }
527 | {
528 |
529 | Memcheck:Addr16
530 | fun:__intel_sse2_strlen
531 | fun:for__add_to_lf_table
532 | fun:for__open_proc
533 | fun:for_open
534 | fun:mod_oasis_namcouple_mp_oasis_namcouple_init_
535 | fun:mod_oasis_method_mp_oasis_init_comp_
536 | fun:cpl_interface_mp_prism_init_
537 | fun:cice_initmod_mp_cice_init_
538 | fun:cice_initmod_mp_cice_initialize_
539 | fun:MAIN__
540 | fun:main
541 | }
542 | {
543 |
544 | Memcheck:Addr16
545 | fun:__intel_sse2_strcpy
546 | fun:for__add_to_lf_table
547 | fun:for__open_proc
548 | fun:for_open
549 | fun:mod_oasis_namcouple_mp_oasis_namcouple_init_
550 | fun:mod_oasis_method_mp_oasis_init_comp_
551 | fun:cpl_interface_mp_prism_init_
552 | fun:cice_initmod_mp_cice_init_
553 | fun:cice_initmod_mp_cice_initialize_
554 | fun:MAIN__
555 | fun:main
556 | }
557 | {
558 |
559 | Memcheck:Addr16
560 | fun:__intel_sse2_strlen
561 | fun:for__io_return
562 | fun:for_read_seq_fmt
563 | fun:mod_oasis_namcouple_mp_inipar_alloc_
564 | fun:mod_oasis_namcouple_mp_oasis_namcouple_init_
565 | fun:mod_oasis_method_mp_oasis_init_comp_
566 | fun:cpl_interface_mp_prism_init_
567 | fun:cice_initmod_mp_cice_init_
568 | fun:cice_initmod_mp_cice_initialize_
569 | fun:MAIN__
570 | fun:main
571 | }
572 | {
573 |
574 | Memcheck:Addr16
575 | fun:__intel_sse2_strlen
576 | fun:for__io_return
577 | fun:for_read_seq_fmt
578 | fun:mod_oasis_namcouple_mp_inipar_
579 | fun:mod_oasis_namcouple_mp_oasis_namcouple_init_
580 | fun:mod_oasis_method_mp_oasis_init_comp_
581 | fun:cpl_interface_mp_prism_init_
582 | fun:cice_initmod_mp_cice_init_
583 | fun:cice_initmod_mp_cice_initialize_
584 | fun:MAIN__
585 | fun:main
586 | }
587 | {
588 |
589 | Memcheck:Cond
590 | fun:__intel_sse2_strcpy
591 | fun:for__open_proc
592 | fun:for__open_default
593 | fun:for_write_seq_lis
594 | fun:mod_oasis_sys_mp_oasis_unitget_
595 | fun:mod_oasis_method_mp_oasis_init_comp_
596 | fun:mom_oasis3_interface_mod_mp_mom_prism_init_
597 | fun:main_IP_external_coupler_mpi_init_
598 | fun:MAIN__
599 | fun:main
600 | }
601 | {
602 |
603 | Memcheck:Cond
604 | fun:__intel_sse2_strcpy
605 | fun:for__add_to_lf_table
606 | fun:for__open_proc
607 | fun:for__open_default
608 | fun:for_write_seq_lis
609 | fun:mod_oasis_sys_mp_oasis_unitget_
610 | fun:mod_oasis_method_mp_oasis_init_comp_
611 | fun:mom_oasis3_interface_mod_mp_mom_prism_init_
612 | fun:main_IP_external_coupler_mpi_init_
613 | fun:MAIN__
614 | fun:main
615 | }
616 | {
617 |
618 | Memcheck:Cond
619 | fun:__intel_sse2_strcpy
620 | fun:for__open_proc
621 | fun:for__open_default
622 | fun:for_write_seq_lis
623 | fun:mod_oasis_sys_mp_oasis_unitget_
624 | fun:mod_oasis_method_mp_oasis_init_comp_
625 | fun:cpl_interface_mp_prism_init_
626 | fun:cice_initmod_mp_cice_init_
627 | fun:cice_initmod_mp_cice_initialize_
628 | fun:MAIN__
629 | fun:main
630 | }
631 | {
632 |
633 | Memcheck:Cond
634 | fun:__intel_sse2_strcpy
635 | fun:for__add_to_lf_table
636 | fun:for__open_proc
637 | fun:for__open_default
638 | fun:for_write_seq_lis
639 | fun:mod_oasis_sys_mp_oasis_unitget_
640 | fun:mod_oasis_method_mp_oasis_init_comp_
641 | fun:cpl_interface_mp_prism_init_
642 | fun:cice_initmod_mp_cice_init_
643 | fun:cice_initmod_mp_cice_initialize_
644 | fun:MAIN__
645 | fun:main
646 | }
647 | {
648 |
649 | Memcheck:Addr16
650 | fun:__intel_sse2_strlen
651 | fun:for__io_return
652 | fun:for_read_seq_fmt
653 | fun:mpp_mod_mp_get_ascii_file_num_lines_
654 | fun:mpp_mod_mp_read_input_nml_
655 | fun:mpp_mod_mp_mpp_init_
656 | fun:fms_mod_mp_fms_init_
657 | fun:MAIN__
658 | fun:main
659 | }
660 | {
661 |
662 | Memcheck:Addr16
663 | fun:__intel_sse2_strlen
664 | fun:for__io_return
665 | fun:for_read_seq_fmt
666 | fun:mpp_mod_mp_read_ascii_file_
667 | fun:mpp_mod_mp_read_input_nml_
668 | fun:mpp_mod_mp_mpp_init_
669 | fun:fms_mod_mp_fms_init_
670 | fun:MAIN__
671 | fun:main
672 | }
673 | {
674 |
675 | Memcheck:Addr16
676 | fun:__intel_sse2_strlen
677 | fun:for__io_return
678 | fun:for_read_seq_nml
679 | fun:mpp_mod_mp_mpp_init_
680 | fun:fms_mod_mp_fms_init_
681 | fun:MAIN__
682 | fun:main
683 | }
684 | {
685 |
686 | Memcheck:Cond
687 | fun:__intel_sse2_strcpy
688 | fun:for__open_proc
689 | fun:for_open
690 | fun:mpp_mod_mp_mpp_init_
691 | fun:fms_mod_mp_fms_init_
692 | fun:MAIN__
693 | fun:main
694 | }
695 | {
696 |
697 | Memcheck:Cond
698 | fun:__intel_sse2_strcpy
699 | fun:for__add_to_lf_table
700 | fun:for__open_proc
701 | fun:for_open
702 | fun:mpp_mod_mp_mpp_init_
703 | fun:fms_mod_mp_fms_init_
704 | fun:MAIN__
705 | fun:main
706 | }
707 | {
708 |
709 | Memcheck:Addr16
710 | fun:__intel_sse2_strlen
711 | fun:for__io_return
712 | fun:for_read_seq_nml
713 | fun:ice_init_mp_input_data_
714 | fun:cice_initmod_mp_cice_init_
715 | fun:cice_initmod_mp_cice_initialize_
716 | fun:MAIN__
717 | fun:main
718 | }
719 | {
720 |
721 | Memcheck:Addr16
722 | fun:__intel_sse2_strlen
723 | fun:for__io_return
724 | fun:for_read_seq_nml
725 | fun:mpp_domains_mod_mp_mpp_domains_init_
726 | fun:fms_mod_mp_fms_init_
727 | fun:MAIN__
728 | fun:main
729 | }
730 | {
731 |
732 | Memcheck:Addr16
733 | fun:__intel_sse2_strlen
734 | fun:for__io_return
735 | fun:for_read_seq_nml
736 | fun:mpp_io_mod_mp_mpp_io_init_
737 | fun:fms_io_mod_mp_fms_io_init_
738 | fun:fms_mod_mp_fms_init_
739 | fun:MAIN__
740 | fun:main
741 | }
742 | {
743 |
744 | Memcheck:Addr16
745 | fun:__intel_sse2_strlen
746 | fun:kill_trailing
747 | fun:nf__open_
748 | fun:mpp_io_mod_mp_mpp_open_
749 | fun:fms_io_mod_mp_get_file_unit_
750 | fun:fms_io_mod_mp_field_exist_
751 | fun:fms_io_mod_mp_fms_io_init_
752 | fun:fms_mod_mp_fms_init_
753 | fun:MAIN__
754 | fun:main
755 | }
756 | {
757 |
758 | Memcheck:Addr16
759 | fun:kill_trailing
760 | fun:nf_inq_att_
761 | fun:mpp_io_mod_mp_mpp_read_meta_
762 | fun:mpp_io_mod_mp_mpp_open_
763 | fun:fms_io_mod_mp_get_file_unit_
764 | fun:fms_io_mod_mp_field_exist_
765 | fun:fms_io_mod_mp_fms_io_init_
766 | fun:fms_mod_mp_fms_init_
767 | fun:MAIN__
768 | fun:main
769 | }
770 | {
771 |
772 | Memcheck:Addr16
773 | fun:__intel_sse2_strlen
774 | fun:kill_trailing
775 | fun:nf_get_att_text_
776 | fun:mpp_io_mod_mp_mpp_read_meta_
777 | fun:mpp_io_mod_mp_mpp_open_
778 | fun:fms_io_mod_mp_get_file_unit_
779 | fun:fms_io_mod_mp_field_exist_
780 | fun:fms_io_mod_mp_fms_io_init_
781 | fun:fms_mod_mp_fms_init_
782 | fun:MAIN__
783 | fun:main
784 | }
785 | {
786 |
787 | Memcheck:Addr16
788 | fun:__intel_sse2_strlen
789 | fun:kill_trailing
790 | fun:nf_inq_attname_
791 | fun:mpp_io_mod_mp_mpp_read_meta_
792 | fun:mpp_io_mod_mp_mpp_open_
793 | fun:fms_io_mod_mp_get_file_unit_
794 | fun:fms_io_mod_mp_field_exist_
795 | fun:fms_io_mod_mp_fms_io_init_
796 | fun:fms_mod_mp_fms_init_
797 | fun:MAIN__
798 | fun:main
799 | }
800 | {
801 |
802 | Memcheck:Addr16
803 | fun:__intel_sse2_strlen
804 | fun:kill_trailing
805 | fun:nf_inq_att_
806 | fun:mpp_io_mod_mp_mpp_read_meta_
807 | fun:mpp_io_mod_mp_mpp_open_
808 | fun:fms_io_mod_mp_get_file_unit_
809 | fun:fms_io_mod_mp_field_exist_
810 | fun:fms_io_mod_mp_fms_io_init_
811 | fun:fms_mod_mp_fms_init_
812 | fun:MAIN__
813 | fun:main
814 | }
815 | {
816 |
817 | Memcheck:Addr16
818 | fun:__intel_sse2_strlen
819 | fun:kill_trailing
820 | fun:nf_get_att_real_
821 | fun:mpp_io_mod_mp_mpp_read_meta_
822 | fun:mpp_io_mod_mp_mpp_open_
823 | fun:fms_io_mod_mp_get_file_unit_
824 | fun:fms_io_mod_mp_field_exist_
825 | fun:fms_io_mod_mp_fms_io_init_
826 | fun:fms_mod_mp_fms_init_
827 | fun:MAIN__
828 | fun:main
829 | }
830 | {
831 |
832 | Memcheck:Addr16
833 | fun:__intel_sse2_strlen
834 | fun:kill_trailing
835 | fun:nf_inq_dim_
836 | fun:mpp_io_mod_mp_mpp_read_meta_
837 | fun:mpp_io_mod_mp_mpp_open_
838 | fun:fms_io_mod_mp_get_file_unit_
839 | fun:fms_io_mod_mp_field_exist_
840 | fun:fms_io_mod_mp_fms_io_init_
841 | fun:fms_mod_mp_fms_init_
842 | fun:MAIN__
843 | fun:main
844 | }
845 | {
846 |
847 | Memcheck:Addr16
848 | fun:__intel_sse2_strlen
849 | fun:kill_trailing
850 | fun:nf_inq_var_
851 | fun:mpp_io_mod_mp_mpp_read_meta_
852 | fun:mpp_io_mod_mp_mpp_open_
853 | fun:fms_io_mod_mp_get_file_unit_
854 | fun:fms_io_mod_mp_field_exist_
855 | fun:fms_io_mod_mp_fms_io_init_
856 | fun:fms_mod_mp_fms_init_
857 | fun:MAIN__
858 | fun:main
859 | }
860 | {
861 |
862 | Memcheck:Addr16
863 | fun:__intel_sse2_strlen
864 | fun:kill_trailing
865 | fun:nf_inq_dimid_
866 | fun:mpp_io_mod_mp_mpp_read_meta_
867 | fun:mpp_io_mod_mp_mpp_open_
868 | fun:fms_io_mod_mp_get_file_unit_
869 | fun:fms_io_mod_mp_field_exist_
870 | fun:fms_io_mod_mp_fms_io_init_
871 | fun:fms_mod_mp_fms_init_
872 | fun:MAIN__
873 | fun:main
874 | }
875 | {
876 |
877 | Memcheck:Addr16
878 | fun:kill_trailing
879 | fun:nf_get_att_text_
880 | fun:mpp_io_mod_mp_mpp_read_meta_
881 | fun:mpp_io_mod_mp_mpp_open_
882 | fun:fms_io_mod_mp_get_file_unit_
883 | fun:fms_io_mod_mp_field_exist_
884 | fun:fms_io_mod_mp_fms_io_init_
885 | fun:fms_mod_mp_fms_init_
886 | fun:MAIN__
887 | fun:main
888 | }
889 | {
890 |
891 | Memcheck:Addr16
892 | fun:__intel_sse2_strlen
893 | fun:kill_trailing
894 | fun:nf_open_
895 | fun:netcdf_mp_nf90_open_
896 | fun:ice_read_write_mp_ice_open_nc_
897 | fun:ice_grid_mp_init_grid1_
898 | fun:cice_initmod_mp_cice_init_
899 | fun:cice_initmod_mp_cice_initialize_
900 | fun:MAIN__
901 | fun:main
902 | }
903 | {
904 |
905 | Memcheck:Addr16
906 | fun:kill_trailing
907 | fun:nf_inq_varid_
908 | fun:ice_read_write_mp_ice_read_global_nc_
909 | fun:ice_grid_mp_init_grid1_
910 | fun:cice_initmod_mp_cice_init_
911 | fun:cice_initmod_mp_cice_initialize_
912 | fun:MAIN__
913 | fun:main
914 | }
915 | {
916 |
917 | Memcheck:Addr16
918 | fun:__intel_sse2_strlen
919 | fun:kill_trailing
920 | fun:nf_inq_dim_
921 | fun:netcdf_mp_nf90_inquire_dimension_
922 | fun:ice_read_write_mp_ice_read_global_nc_
923 | fun:ice_grid_mp_init_grid1_
924 | fun:cice_initmod_mp_cice_init_
925 | fun:cice_initmod_mp_cice_initialize_
926 | fun:MAIN__
927 | fun:main
928 | }
929 | {
930 |
931 | Memcheck:Addr16
932 | fun:__intel_sse2_strlen
933 | fun:for__io_return
934 | fun:for_read_seq_nml
935 | fun:time_interp_external_mod_mp_time_interp_external_init_
936 | fun:MAIN__
937 | fun:main
938 | }
939 | {
940 |
941 | Memcheck:Addr16
942 | fun:__intel_sse2_strlen
943 | fun:for__io_return
944 | fun:for_read_seq_nml
945 | fun:time_interp_mod_mp_time_interp_init_
946 | fun:time_interp_external_mod_mp_time_interp_external_init_
947 | fun:MAIN__
948 | fun:main
949 | }
950 | {
951 |
952 | Memcheck:Addr16
953 | fun:__intel_sse2_strlen
954 | fun:for__io_return
955 | fun:for_read_seq_nml
956 | fun:ocean_parameters_mod_mp_ocean_parameters_init_
957 | fun:ocean_model_mod_mp_ocean_model_init_
958 | fun:MAIN__
959 | fun:main
960 | }
961 | {
962 |
963 | Memcheck:Addr16
964 | fun:__intel_sse2_strlen
965 | fun:kill_trailing
966 | fun:nf__open_
967 | fun:mpp_io_mod_mp_mpp_open_
968 | fun:fms_io_mod_mp_get_global_att_value_text_
969 | fun:ocean_grids_mod_mp_set_ocean_grid_size_
970 | fun:ocean_model_mod_mp_ocean_model_init_
971 | fun:MAIN__
972 | fun:main
973 | }
974 | {
975 |
976 | Memcheck:Addr16
977 | fun:kill_trailing
978 | fun:nf_inq_att_
979 | fun:mpp_io_mod_mp_mpp_read_meta_
980 | fun:mpp_io_mod_mp_mpp_open_
981 | fun:fms_io_mod_mp_get_global_att_value_text_
982 | fun:ocean_grids_mod_mp_set_ocean_grid_size_
983 | fun:ocean_model_mod_mp_ocean_model_init_
984 | fun:MAIN__
985 | fun:main
986 | }
987 | {
988 |
989 | Memcheck:Addr16
990 | fun:kill_trailing
991 | fun:nf_get_att_text_
992 | fun:mpp_io_mod_mp_mpp_read_meta_
993 | fun:mpp_io_mod_mp_mpp_open_
994 | fun:fms_io_mod_mp_get_global_att_value_text_
995 | fun:ocean_grids_mod_mp_set_ocean_grid_size_
996 | fun:ocean_model_mod_mp_ocean_model_init_
997 | fun:MAIN__
998 | fun:main
999 | }
1000 | {
1001 |
1002 | Memcheck:Addr16
1003 | fun:__intel_sse2_strlen
1004 | fun:kill_trailing
1005 | fun:nf__open_
1006 | fun:mpp_io_mod_mp_mpp_open_
1007 | fun:fms_io_mod_mp_get_global_att_value_real_
1008 | fun:ocean_grids_mod_mp_set_ocean_grid_size_
1009 | fun:ocean_model_mod_mp_ocean_model_init_
1010 | fun:MAIN__
1011 | fun:main
1012 | }
1013 | {
1014 |
1015 | Memcheck:Addr16
1016 | fun:kill_trailing
1017 | fun:nf_inq_att_
1018 | fun:mpp_io_mod_mp_mpp_read_meta_
1019 | fun:mpp_io_mod_mp_mpp_open_
1020 | fun:fms_io_mod_mp_get_global_att_value_real_
1021 | fun:ocean_grids_mod_mp_set_ocean_grid_size_
1022 | fun:ocean_model_mod_mp_ocean_model_init_
1023 | fun:MAIN__
1024 | fun:main
1025 | }
1026 | {
1027 |
1028 | Memcheck:Addr16
1029 | fun:kill_trailing
1030 | fun:nf_get_att_text_
1031 | fun:mpp_io_mod_mp_mpp_read_meta_
1032 | fun:mpp_io_mod_mp_mpp_open_
1033 | fun:fms_io_mod_mp_get_global_att_value_real_
1034 | fun:ocean_grids_mod_mp_set_ocean_grid_size_
1035 | fun:ocean_model_mod_mp_ocean_model_init_
1036 | fun:MAIN__
1037 | fun:main
1038 | }
1039 | {
1040 |
1041 | Memcheck:Addr16
1042 | fun:__intel_sse2_strlen
1043 | fun:for__io_return
1044 | fun:for_read_seq_nml
1045 | fun:ocean_tracer_util_mod_mp_ocean_tracer_util_init_
1046 | fun:ocean_model_mod_mp_ocean_model_init_
1047 | fun:MAIN__
1048 | fun:main
1049 | }
1050 | {
1051 |
1052 | Memcheck:Addr16
1053 | fun:__intel_sse2_strlen
1054 | fun:for__io_return
1055 | fun:for_read_seq_nml
1056 | fun:ocean_operators_mod_mp_ocean_operators_init_
1057 | fun:ocean_model_mod_mp_ocean_model_init_
1058 | fun:MAIN__
1059 | fun:main
1060 | }
1061 | {
1062 |
1063 | Memcheck:Addr16
1064 | fun:__intel_sse2_strlen
1065 | fun:kill_trailing
1066 | fun:nf_inq_varid_
1067 | fun:mpp_io_mod_mp_mpp_read_meta_
1068 | fun:mpp_io_mod_mp_mpp_open_
1069 | fun:fms_io_mod_mp_get_file_unit_
1070 | fun:fms_io_mod_mp_field_exist_
1071 | fun:ocean_tracer_mod_mp_ocean_prog_tracer_init_
1072 | fun:ocean_model_mod_mp_ocean_model_init_
1073 | fun:MAIN__
1074 | fun:main
1075 | }
1076 | {
1077 |
1078 | Memcheck:Addr16
1079 | fun:kill_trailing
1080 | fun:nf_get_att_double_
1081 | fun:mpp_io_mod_mp_mpp_read_meta_
1082 | fun:mpp_io_mod_mp_mpp_open_
1083 | fun:fms_io_mod_mp_get_file_unit_
1084 | fun:fms_io_mod_mp_field_exist_
1085 | fun:ocean_tracer_mod_mp_ocean_prog_tracer_init_
1086 | fun:ocean_model_mod_mp_ocean_model_init_
1087 | fun:MAIN__
1088 | fun:main
1089 | }
1090 | {
1091 |
1092 | Memcheck:Addr16
1093 | fun:kill_trailing
1094 | fun:nf_get_att_real_
1095 | fun:mpp_io_mod_mp_mpp_read_meta_
1096 | fun:mpp_io_mod_mp_mpp_open_
1097 | fun:fms_io_mod_mp_get_file_unit_
1098 | fun:fms_io_mod_mp_field_exist_
1099 | fun:ocean_tracer_mod_mp_ocean_prog_tracer_init_
1100 | fun:ocean_model_mod_mp_ocean_model_init_
1101 | fun:MAIN__
1102 | fun:main
1103 | }
1104 | {
1105 |
1106 | Memcheck:Addr16
1107 | fun:__intel_sse2_strlen
1108 | fun:kill_trailing
1109 | fun:nf__open_
1110 | fun:mpp_io_mod_mp_mpp_open_
1111 | fun:fms_io_mod_mp_restore_state_one_field_
1112 | fun:ocean_tracer_mod_mp_ocean_prog_tracer_init_
1113 | fun:ocean_model_mod_mp_ocean_model_init_
1114 | fun:MAIN__
1115 | fun:main
1116 | }
1117 | {
1118 |
1119 | Memcheck:Addr16
1120 | fun:__intel_sse2_strlen
1121 | fun:kill_trailing
1122 | fun:nf_inq_dim_
1123 | fun:mpp_io_mod_mp_mpp_read_meta_
1124 | fun:mpp_io_mod_mp_mpp_open_
1125 | fun:fms_io_mod_mp_restore_state_one_field_
1126 | fun:ocean_tracer_mod_mp_ocean_prog_tracer_init_
1127 | fun:ocean_model_mod_mp_ocean_model_init_
1128 | fun:MAIN__
1129 | fun:main
1130 | }
1131 | {
1132 |
1133 | Memcheck:Addr16
1134 | fun:kill_trailing
1135 | fun:nf_inq_att_
1136 | fun:mpp_io_mod_mp_mpp_read_meta_
1137 | fun:mpp_io_mod_mp_mpp_open_
1138 | fun:fms_io_mod_mp_restore_state_one_field_
1139 | fun:ocean_tracer_mod_mp_ocean_prog_tracer_init_
1140 | fun:ocean_model_mod_mp_ocean_model_init_
1141 | fun:MAIN__
1142 | fun:main
1143 | }
1144 | {
1145 |
1146 | Memcheck:Addr16
1147 | fun:kill_trailing
1148 | fun:nf_get_att_text_
1149 | fun:mpp_io_mod_mp_mpp_read_meta_
1150 | fun:mpp_io_mod_mp_mpp_open_
1151 | fun:fms_io_mod_mp_restore_state_one_field_
1152 | fun:ocean_tracer_mod_mp_ocean_prog_tracer_init_
1153 | fun:ocean_model_mod_mp_ocean_model_init_
1154 | fun:MAIN__
1155 | fun:main
1156 | }
1157 | {
1158 |
1159 | Memcheck:Addr16
1160 | fun:kill_trailing
1161 | fun:nf_get_att_double_
1162 | fun:mpp_io_mod_mp_mpp_read_meta_
1163 | fun:mpp_io_mod_mp_mpp_open_
1164 | fun:fms_io_mod_mp_restore_state_one_field_
1165 | fun:ocean_tracer_mod_mp_ocean_prog_tracer_init_
1166 | fun:ocean_model_mod_mp_ocean_model_init_
1167 | fun:MAIN__
1168 | fun:main
1169 | }
1170 | {
1171 |
1172 | Memcheck:Addr16
1173 | fun:kill_trailing
1174 | fun:nf_get_att_real_
1175 | fun:mpp_io_mod_mp_mpp_read_meta_
1176 | fun:mpp_io_mod_mp_mpp_open_
1177 | fun:fms_io_mod_mp_restore_state_one_field_
1178 | fun:ocean_tracer_mod_mp_ocean_prog_tracer_init_
1179 | fun:ocean_model_mod_mp_ocean_model_init_
1180 | fun:MAIN__
1181 | fun:main
1182 | }
1183 | {
1184 |
1185 | Memcheck:Addr16
1186 | fun:__intel_sse2_strlen
1187 | fun:for__io_return
1188 | fun:for_read_seq_nml
1189 | fun:ocean_blob_mod_mp_ocean_blob_init_
1190 | fun:ocean_model_mod_mp_ocean_model_init_
1191 | fun:MAIN__
1192 | fun:main
1193 | }
1194 | {
1195 |
1196 | Memcheck:Addr16
1197 | fun:__intel_sse2_strlen
1198 | fun:for__io_return
1199 | fun:for_read_seq_nml
1200 | fun:ocean_vert_util_mod_mp_ocean_vert_util_init_
1201 | fun:ocean_vert_mix_mod_mp_ocean_vert_mix_init_
1202 | fun:ocean_model_mod_mp_ocean_model_init_
1203 | fun:MAIN__
1204 | fun:main
1205 | }
1206 | {
1207 |
1208 | Memcheck:Addr16
1209 | fun:kill_trailing
1210 | fun:nf_get_att_double_
1211 | fun:mpp_io_mod_mp_mpp_read_meta_
1212 | fun:mpp_io_mod_mp_mpp_open_
1213 | fun:fms_io_mod_mp_get_file_unit_
1214 | fun:fms_io_mod_mp_read_data_3d_new_
1215 | fun:fms_io_mod_mp_read_data_2d_new_
1216 | fun:ocean_vert_tidal_mod_mp_ocean_vert_tidal_init_
1217 | fun:ocean_vert_mix_mod_mp_ocean_vert_mix_init_
1218 | fun:ocean_model_mod_mp_ocean_model_init_
1219 | fun:MAIN__
1220 | fun:main
1221 | }
1222 | {
1223 |
1224 | Memcheck:Addr16
1225 | fun:__intel_sse2_strlen
1226 | fun:for__io_return
1227 | fun:for_read_seq_nml
1228 | fun:ocean_vert_kpp_mom4p1_mod_mp_ocean_vert_kpp_mom4p1_init_
1229 | fun:ocean_vert_mix_mod_mp_ocean_vert_mix_init_
1230 | fun:ocean_model_mod_mp_ocean_model_init_
1231 | fun:MAIN__
1232 | fun:main
1233 | }
1234 | {
1235 |
1236 | Memcheck:Addr16
1237 | fun:__intel_sse2_strlen
1238 | fun:for__io_return
1239 | fun:for_read_seq_nml
1240 | fun:ocean_nphysics_new_mod_mp_ocean_nphysics_new_init_
1241 | fun:ocean_model_mod_mp_ocean_model_init_
1242 | fun:MAIN__
1243 | fun:main
1244 | }
1245 | {
1246 |
1247 | Memcheck:Addr16
1248 | fun:__intel_sse2_strlen
1249 | fun:for__io_return
1250 | fun:for_read_seq_nml
1251 | fun:ocean_nphysics_util_new_mod_mp_ocean_nphysics_util_new_init_
1252 | fun:ocean_nphysics_new_mod_mp_ocean_nphysics_new_init_
1253 | fun:ocean_model_mod_mp_ocean_model_init_
1254 | fun:MAIN__
1255 | fun:main
1256 | }
1257 | {
1258 |
1259 | Memcheck:Addr16
1260 | fun:__intel_sse2_strlen
1261 | fun:kill_trailing
1262 | fun:nf__open_
1263 | fun:mpp_io_mod_mp_mpp_open_
1264 | fun:time_interp_external_mod_mp_init_external_field_
1265 | fun:ocean_sbc_mod_mp_ocean_sbc_init_
1266 | fun:ocean_model_mod_mp_ocean_model_init_
1267 | fun:MAIN__
1268 | fun:main
1269 | }
1270 | {
1271 |
1272 | Memcheck:Addr16
1273 | fun:kill_trailing
1274 | fun:nf_inq_att_
1275 | fun:mpp_io_mod_mp_mpp_read_meta_
1276 | fun:mpp_io_mod_mp_mpp_open_
1277 | fun:time_interp_external_mod_mp_init_external_field_
1278 | fun:ocean_sbc_mod_mp_ocean_sbc_init_
1279 | fun:ocean_model_mod_mp_ocean_model_init_
1280 | fun:MAIN__
1281 | fun:main
1282 | }
1283 | {
1284 |
1285 | Memcheck:Addr16
1286 | fun:kill_trailing
1287 | fun:nf_get_att_text_
1288 | fun:mpp_io_mod_mp_mpp_read_meta_
1289 | fun:mpp_io_mod_mp_mpp_open_
1290 | fun:time_interp_external_mod_mp_init_external_field_
1291 | fun:ocean_sbc_mod_mp_ocean_sbc_init_
1292 | fun:ocean_model_mod_mp_ocean_model_init_
1293 | fun:MAIN__
1294 | fun:main
1295 | }
1296 | {
1297 |
1298 | Memcheck:Addr16
1299 | fun:kill_trailing
1300 | fun:nf_get_att_double_
1301 | fun:mpp_io_mod_mp_mpp_read_meta_
1302 | fun:mpp_io_mod_mp_mpp_open_
1303 | fun:time_interp_external_mod_mp_init_external_field_
1304 | fun:ocean_sbc_mod_mp_ocean_sbc_init_
1305 | fun:ocean_model_mod_mp_ocean_model_init_
1306 | fun:MAIN__
1307 | fun:main
1308 | }
1309 | {
1310 |
1311 | Memcheck:Addr16
1312 | fun:__intel_sse2_strlen
1313 | fun:kill_trailing
1314 | fun:nf_get_att_text_
1315 | fun:mpp_io_mod_mp_mpp_read_meta_
1316 | fun:mpp_io_mod_mp_mpp_open_
1317 | fun:time_interp_external_mod_mp_init_external_field_
1318 | fun:ocean_sbc_mod_mp_ocean_sbc_init_
1319 | fun:ocean_model_mod_mp_ocean_model_init_
1320 | fun:MAIN__
1321 | fun:main
1322 | }
1323 | {
1324 |
1325 | Memcheck:Addr16
1326 | fun:__intel_sse2_strlen
1327 | fun:for__io_return
1328 | fun:for_read_seq_nml
1329 | fun:get_cal_time_mod_mp_get_cal_time_
1330 | fun:time_interp_external_mod_mp_init_external_field_
1331 | fun:ocean_sbc_mod_mp_ocean_sbc_init_
1332 | fun:ocean_model_mod_mp_ocean_model_init_
1333 | fun:MAIN__
1334 | fun:main
1335 | }
1336 | {
1337 |
1338 | Memcheck:Addr16
1339 | fun:__intel_sse2_strlen
1340 | fun:for__io_return
1341 | fun:for_read_seq_nml
1342 | fun:ocean_wave_mod_mp_ocean_wave_init_
1343 | fun:ocean_model_mod_mp_ocean_model_init_
1344 | fun:MAIN__
1345 | fun:main
1346 | }
1347 | {
1348 |
1349 | Memcheck:Addr16
1350 | fun:__intel_sse2_strlen
1351 | fun:for__io_return
1352 | fun:for_read_seq_nml
1353 | fun:horiz_interp_mod_mp_horiz_interp_init_
1354 | fun:data_override_mod_mp_data_override_init_
1355 | fun:MAIN__
1356 | fun:main
1357 | }
1358 | {
1359 |
1360 | Memcheck:Addr16
1361 | fun:__intel_sse2_strlen
1362 | fun:for__io_return
1363 | fun:for_read_seq_nml
1364 | fun:horiz_interp_spherical_mod_mp_horiz_interp_spherical_init_
1365 | fun:horiz_interp_mod_mp_horiz_interp_init_
1366 | fun:data_override_mod_mp_data_override_init_
1367 | fun:MAIN__
1368 | fun:main
1369 | }
1370 | {
1371 |
1372 | Memcheck:Addr16
1373 | fun:__intel_sse2_strlen
1374 | fun:kill_trailing
1375 | fun:nf_open_
1376 | fun:netcdf_mp_nf90_open_
1377 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1378 | fun:mod_oasis_method_mp_oasis_enddef_
1379 | fun:cpl_interface_mp_init_cpl_
1380 | fun:cice_initmod_mp_cice_init_
1381 | fun:cice_initmod_mp_cice_initialize_
1382 | fun:MAIN__
1383 | fun:main
1384 | }
1385 | {
1386 |
1387 | Memcheck:Addr16
1388 | fun:kill_trailing
1389 | fun:nf_inq_dimid_
1390 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1391 | fun:mod_oasis_method_mp_oasis_enddef_
1392 | fun:cpl_interface_mp_init_cpl_
1393 | fun:cice_initmod_mp_cice_init_
1394 | fun:cice_initmod_mp_cice_initialize_
1395 | fun:MAIN__
1396 | fun:main
1397 | }
1398 | {
1399 |
1400 | Memcheck:Addr16
1401 | fun:__intel_sse2_strlen
1402 | fun:kill_trailing
1403 | fun:nf_inq_dim_
1404 | fun:netcdf_mp_nf90_inquire_dimension_
1405 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1406 | fun:mod_oasis_method_mp_oasis_enddef_
1407 | fun:cpl_interface_mp_init_cpl_
1408 | fun:cice_initmod_mp_cice_init_
1409 | fun:cice_initmod_mp_cice_initialize_
1410 | fun:MAIN__
1411 | fun:main
1412 | }
1413 | {
1414 |
1415 | Memcheck:Addr16
1416 | fun:__intel_sse2_strlen
1417 | fun:kill_trailing
1418 | fun:nf_open_
1419 | fun:netcdf_mp_nf90_open_
1420 | fun:mod_oasis_coupler_mp_oasis_coupler_smatreaddnc_
1421 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1422 | fun:mod_oasis_method_mp_oasis_enddef_
1423 | fun:cpl_interface_mp_init_cpl_
1424 | fun:cice_initmod_mp_cice_init_
1425 | fun:cice_initmod_mp_cice_initialize_
1426 | fun:MAIN__
1427 | fun:main
1428 | }
1429 | {
1430 |
1431 | Memcheck:Addr16
1432 | fun:kill_trailing
1433 | fun:nf_inq_dimid_
1434 | fun:mod_oasis_coupler_mp_oasis_coupler_smatreaddnc_
1435 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1436 | fun:mod_oasis_method_mp_oasis_enddef_
1437 | fun:cpl_interface_mp_init_cpl_
1438 | fun:cice_initmod_mp_cice_init_
1439 | fun:cice_initmod_mp_cice_initialize_
1440 | fun:MAIN__
1441 | fun:main
1442 | }
1443 | {
1444 |
1445 | Memcheck:Addr16
1446 | fun:__intel_sse2_strlen
1447 | fun:kill_trailing
1448 | fun:nf_inq_dim_
1449 | fun:netcdf_mp_nf90_inquire_dimension_
1450 | fun:mod_oasis_coupler_mp_oasis_coupler_smatreaddnc_
1451 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1452 | fun:mod_oasis_method_mp_oasis_enddef_
1453 | fun:cpl_interface_mp_init_cpl_
1454 | fun:cice_initmod_mp_cice_init_
1455 | fun:cice_initmod_mp_cice_initialize_
1456 | fun:MAIN__
1457 | fun:main
1458 | }
1459 | {
1460 |
1461 | Memcheck:Addr16
1462 | fun:kill_trailing
1463 | fun:nf_inq_varid_
1464 | fun:mod_oasis_coupler_mp_oasis_coupler_smatreaddnc_
1465 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1466 | fun:mod_oasis_method_mp_oasis_enddef_
1467 | fun:cpl_interface_mp_init_cpl_
1468 | fun:cice_initmod_mp_cice_init_
1469 | fun:cice_initmod_mp_cice_initialize_
1470 | fun:MAIN__
1471 | fun:main
1472 | }
1473 | {
1474 |
1475 | Memcheck:Addr16
1476 | fun:__intel_sse2_strlen
1477 | fun:kill_trailing
1478 | fun:nf_open_
1479 | fun:netcdf_mp_nf90_open_
1480 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1481 | fun:mod_oasis_method_mp_oasis_enddef_
1482 | fun:cpl_interfaces_mp_init_cpl_
1483 | fun:MAIN__
1484 | fun:main
1485 | }
1486 | {
1487 |
1488 | Memcheck:Addr16
1489 | fun:kill_trailing
1490 | fun:nf_inq_dimid_
1491 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1492 | fun:mod_oasis_method_mp_oasis_enddef_
1493 | fun:cpl_interfaces_mp_init_cpl_
1494 | fun:MAIN__
1495 | fun:main
1496 | }
1497 | {
1498 |
1499 | Memcheck:Addr16
1500 | fun:__intel_sse2_strlen
1501 | fun:kill_trailing
1502 | fun:nf_open_
1503 | fun:netcdf_mp_nf90_open_
1504 | fun:mod_oasis_coupler_mp_oasis_coupler_smatreaddnc_
1505 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1506 | fun:mod_oasis_method_mp_oasis_enddef_
1507 | fun:cpl_interfaces_mp_init_cpl_
1508 | fun:MAIN__
1509 | fun:main
1510 | }
1511 | {
1512 |
1513 | Memcheck:Addr16
1514 | fun:kill_trailing
1515 | fun:nf_inq_dimid_
1516 | fun:mod_oasis_coupler_mp_oasis_coupler_smatreaddnc_
1517 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1518 | fun:mod_oasis_method_mp_oasis_enddef_
1519 | fun:cpl_interfaces_mp_init_cpl_
1520 | fun:MAIN__
1521 | fun:main
1522 | }
1523 | {
1524 |
1525 | Memcheck:Addr16
1526 | fun:__intel_sse2_strlen
1527 | fun:kill_trailing
1528 | fun:nf_inq_dim_
1529 | fun:netcdf_mp_nf90_inquire_dimension_
1530 | fun:mod_oasis_coupler_mp_oasis_coupler_smatreaddnc_
1531 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1532 | fun:mod_oasis_method_mp_oasis_enddef_
1533 | fun:cpl_interfaces_mp_init_cpl_
1534 | fun:MAIN__
1535 | fun:main
1536 | }
1537 | {
1538 |
1539 | Memcheck:Addr16
1540 | fun:kill_trailing
1541 | fun:nf_inq_varid_
1542 | fun:mod_oasis_coupler_mp_oasis_coupler_smatreaddnc_
1543 | fun:mod_oasis_coupler_mp_oasis_coupler_setup_
1544 | fun:mod_oasis_method_mp_oasis_enddef_
1545 | fun:cpl_interfaces_mp_init_cpl_
1546 | fun:MAIN__
1547 | fun:main
1548 | }
1549 | {
1550 |
1551 | Memcheck:Addr16
1552 | fun:kill_trailing
1553 | fun:nf_open_
1554 | fun:netcdf_mp_nf90_open_
1555 | fun:mod_oasis_io_mp_oasis_io_read_avfile_
1556 | fun:mod_oasis_advance_mp_oasis_advance_run_
1557 | fun:mod_oasis_advance_mp_oasis_advance_init_
1558 | fun:mod_oasis_method_mp_oasis_enddef_
1559 | fun:cpl_interfaces_mp_init_cpl_
1560 | fun:MAIN__
1561 | fun:main
1562 | }
1563 | {
1564 |
1565 | Memcheck:Addr16
1566 | fun:kill_trailing
1567 | fun:nf_inq_varid_
1568 | fun:mod_oasis_io_mp_oasis_io_read_avfile_
1569 | fun:mod_oasis_advance_mp_oasis_advance_run_
1570 | fun:mod_oasis_advance_mp_oasis_advance_init_
1571 | fun:mod_oasis_method_mp_oasis_enddef_
1572 | fun:cpl_interfaces_mp_init_cpl_
1573 | fun:MAIN__
1574 | fun:main
1575 | }
1576 | {
1577 |
1578 | Memcheck:Addr16
1579 | fun:__intel_sse2_strlen
1580 | fun:kill_trailing
1581 | fun:nf_inq_var_
1582 | fun:netcdf_mp_nf90_inquire_variable_
1583 | fun:mod_oasis_io_mp_oasis_io_read_avfile_
1584 | fun:mod_oasis_advance_mp_oasis_advance_run_
1585 | fun:mod_oasis_advance_mp_oasis_advance_init_
1586 | fun:mod_oasis_method_mp_oasis_enddef_
1587 | fun:cpl_interfaces_mp_init_cpl_
1588 | fun:MAIN__
1589 | fun:main
1590 | }
1591 | {
1592 |
1593 | Memcheck:Addr16
1594 | fun:__intel_sse2_strlen
1595 | fun:kill_trailing
1596 | fun:nf_inq_dim_
1597 | fun:netcdf_mp_nf90_inquire_dimension_
1598 | fun:mod_oasis_io_mp_oasis_io_read_avfile_
1599 | fun:mod_oasis_advance_mp_oasis_advance_run_
1600 | fun:mod_oasis_advance_mp_oasis_advance_init_
1601 | fun:mod_oasis_method_mp_oasis_enddef_
1602 | fun:cpl_interfaces_mp_init_cpl_
1603 | fun:MAIN__
1604 | fun:main
1605 | }
1606 | {
1607 |
1608 | Memcheck:Addr16
1609 | fun:kill_trailing
1610 | fun:nf_open_
1611 | fun:netcdf_mp_nf90_open_
1612 | fun:mod_oasis_io_mp_oasis_io_read_avfile_
1613 | fun:mod_oasis_advance_mp_oasis_advance_run_
1614 | fun:mod_oasis_advance_mp_oasis_advance_init_
1615 | fun:mod_oasis_method_mp_oasis_enddef_
1616 | fun:cpl_interface_mp_init_cpl_
1617 | fun:cice_initmod_mp_cice_init_
1618 | fun:cice_initmod_mp_cice_initialize_
1619 | fun:MAIN__
1620 | fun:main
1621 | }
1622 | {
1623 |
1624 | Memcheck:Addr16
1625 | fun:kill_trailing
1626 | fun:nf_inq_varid_
1627 | fun:mod_oasis_io_mp_oasis_io_read_avfile_
1628 | fun:mod_oasis_advance_mp_oasis_advance_run_
1629 | fun:mod_oasis_advance_mp_oasis_advance_init_
1630 | fun:mod_oasis_method_mp_oasis_enddef_
1631 | fun:cpl_interface_mp_init_cpl_
1632 | fun:cice_initmod_mp_cice_init_
1633 | fun:cice_initmod_mp_cice_initialize_
1634 | fun:MAIN__
1635 | fun:main
1636 | }
1637 | {
1638 |
1639 | Memcheck:Addr16
1640 | fun:__intel_sse2_strlen
1641 | fun:kill_trailing
1642 | fun:nf_inq_var_
1643 | fun:netcdf_mp_nf90_inquire_variable_
1644 | fun:mod_oasis_io_mp_oasis_io_read_avfile_
1645 | fun:mod_oasis_advance_mp_oasis_advance_run_
1646 | fun:mod_oasis_advance_mp_oasis_advance_init_
1647 | fun:mod_oasis_method_mp_oasis_enddef_
1648 | fun:cpl_interface_mp_init_cpl_
1649 | fun:cice_initmod_mp_cice_init_
1650 | fun:cice_initmod_mp_cice_initialize_
1651 | fun:MAIN__
1652 | fun:main
1653 | }
1654 | {
1655 |
1656 | Memcheck:Addr16
1657 | fun:__intel_sse2_strlen
1658 | fun:kill_trailing
1659 | fun:nf_inq_dim_
1660 | fun:netcdf_mp_nf90_inquire_dimension_
1661 | fun:mod_oasis_io_mp_oasis_io_read_avfile_
1662 | fun:mod_oasis_advance_mp_oasis_advance_run_
1663 | fun:mod_oasis_advance_mp_oasis_advance_init_
1664 | fun:mod_oasis_method_mp_oasis_enddef_
1665 | fun:cpl_interface_mp_init_cpl_
1666 | fun:cice_initmod_mp_cice_init_
1667 | fun:cice_initmod_mp_cice_initialize_
1668 | fun:MAIN__
1669 | fun:main
1670 | }
1671 | {
1672 |
1673 | Memcheck:Addr16
1674 | fun:__intel_sse2_strlen
1675 | fun:for__add_to_lf_table
1676 | fun:for__open_proc
1677 | fun:for_open
1678 | fun:mod_oasis_method_mp_oasis_init_comp_
1679 | fun:cpl_interfaces_mp_prism_init_
1680 | fun:MAIN__
1681 | fun:main
1682 | }
1683 | {
1684 |
1685 | Memcheck:Addr16
1686 | fun:__intel_sse2_strcpy
1687 | fun:for__add_to_lf_table
1688 | fun:for__open_proc
1689 | fun:for_open
1690 | fun:mod_oasis_method_mp_oasis_init_comp_
1691 | fun:cpl_interfaces_mp_prism_init_
1692 | fun:MAIN__
1693 | fun:main
1694 | }
1695 |
--------------------------------------------------------------------------------
/tools/.pylintrc:
--------------------------------------------------------------------------------
1 | [MASTER]
2 | init-hook='import sys; sys.path.extend(["esmgrids","../test"])'
3 |
--------------------------------------------------------------------------------
/tools/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Tools
3 |
4 | This directory contains a collection of tools which are used to make model input files.
5 |
6 |
7 | ## make\_remap\_weights.py
8 |
9 | This tool read the atmosphere and ice/ocean grid definitions and creates remapping weights files. These are used by the coupler to interpolate the fields between the model grids. The tool needs to be invoked once for each pair of grids and by default will create two weights files - one for conservative interpolation and one for patch interpolation.
10 |
11 | For example to create 1 deg JRA55 weights on a Gadi (NCI.org.au) head node:
12 |
13 | ```
14 | module use /g/data3/hh5/public/modules
15 | module load conda/analysis27-18.10
16 | module load nco
17 | module load openmpi
18 | python ./make_remap_weights.py --help
19 | ```
20 |
21 | Now to create the atmosphere to ice/ocean weights:
22 |
23 | ```
24 | python ./make_remap_weights.py /g/data/qv56/replicas/input4MIPs/CMIP6/OMIP/MRI/MRI-JRA55-do-1-4-0/atmos/3hr/rsds/gr/v20190429/rsds/rsds_input4MIPs_atmosphericState_OMIP_MRI-JRA55-do-1-4-0_gr_195801010130-195812312230.nc JRA55 /g/data/ik11/inputs/access-om2/input_rc/mom_1deg/ MOM1
25 | ```
26 |
27 | The above should result in two files in the currect directory: `JRA55_MOM1_conserve.nc` and `JRA55_MOM1_patch.nc`
28 |
29 | The following will create the weights needed for river runoff:
30 |
31 | ```
32 | python ./make_remap_weights.py /g/data/qv56/replicas/input4MIPs/CMIP6/OMIP/MRI/MRI-JRA55-do-1-4-0/land/day/friver/gr/v20190429/friver_input4MIPs_atmosphericState_OMIP_MRI-JRA55-do-1-4-0_gr_19580101-19581231.nc JRA55_runoff /g/data/ik11/inputs/access-om2/input_rc/mom_1deg/ MOM1
33 | ```
34 |
35 | The 0.25 deg weights can also be created on the head nodes - this ususally takes a few minutes:
36 |
37 | ```
38 | python ./make_remap_weights.py /g/data/qv56/replicas/input4MIPs/CMIP6/OMIP/MRI/MRI-JRA55-do-1-4-0/atmos/3hr/rsds/gr/v20190429/rsds_input4MIPs_atmosphericState_OMIP_MRI-JRA55-do-1-4-0_gr_195801010130-195812312230.nc JRA55 /g/data/ik11/inputs/access-om2/input_rc/mom_025deg/ MOM025
39 | python ./make_remap_weights.py /g/data/qv56/replicas/input4MIPs/CMIP6/OMIP/MRI/MRI-JRA55-do-1-4-0/land/day/friver/gr/v20190429/friver_input4MIPs_atmosphericState_OMIP_MRI-JRA55-do-1-4-0_gr_19580101-19581231.nc JRA55_runoff /g/data/ik11/inputs/access-om2/input_rc/mom_025deg/ MOM025
40 | ```
41 |
42 | To make the 0.1 deg weights we need to use more PEs and memory, first get an interactive job with lots of memory:
43 |
44 | ```
45 | qsub -I -P v45 -q normal -lncpus=96 -lmem=348Gb -lwalltime=3:00:00 -lstorage=gdata/ua8+gdata/qv56+gdata/hh5+gdata/ik11
46 | ```
47 |
48 | Then run the following commands, note the use of `--npes 96`.
49 |
50 | ```
51 | cd access-om2/tools
52 | module use /g/data3/hh5/public/modules
53 | module load conda/analysis27-18.10
54 | module load nco
55 | module load openmpi
56 | time python ./make_remap_weights.py /g/data/qv56/replicas/input4MIPs/CMIP6/OMIP/MRI/MRI-JRA55-do-1-4-0/atmos/3hr/rsds/gr/v20190429/rsds_input4MIPs_atmosphericState_OMIP_MRI-JRA55-do-1-4-0_gr_195801010130-195812312230.nc JRA55 /g/data/ik11/inputs/access-om2/input_rc/mom_01deg/ MOM01 --npes 96
57 |
58 | ```
59 |
60 |
61 |
--------------------------------------------------------------------------------
/tools/add_core2_time_bounds.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from __future__ import print_function
4 |
5 | """
6 | The CORE2 forcing files have an ambiguous time dimension. For example in
7 | ncar_precip.0001.nc:
8 |
9 | TIME:units = "days since 1900-01-01 00:00:00" ;
10 | TIME = 15.5, 45, 74.5, 105, 135.5, 166, 196.5, 227.5, 258, 288.5, 319, 349.5 ;
11 |
12 | For a human this probably means that each time point refers to a month, however
13 | for a computer that is trying to index on the basis of a date and time it is
14 | ambiguous. For example which time point should be used for Jan 31? If an
15 | algorithm tries to find the 'closest' time point it will choose the second one,
16 | which is probably not the intention of the dataset.
17 |
18 | This script corrects this ambiguity by adding a time_bounds variable to define
19 | the time range than each point covers.
20 |
21 | Example invocation:
22 |
23 | python ./add_core2_time_bounds.py ../input/yatm_1deg/ncar_precip.0001.nc
24 | """
25 |
26 | import sys
27 | import os
28 | import git
29 | import argparse
30 | import datetime
31 | import netCDF4 as nc
32 |
33 | def get_history_record(repo_dir):
34 | """Create a new history record."""
35 |
36 | time_stamp = datetime.datetime.now().isoformat()
37 | exe = sys.executable
38 | args = " ".join(sys.argv)
39 | repo = git.Repo(repo_dir)
40 | git_url = str(list(repo.remote().urls)[0])
41 | git_hash = str(repo.heads[0].commit)[0:7]
42 |
43 | entry = "{}: {} {} (Git URL: {}, Git hash: {})".format(time_stamp, exe, args, git_url, git_hash)
44 |
45 | return entry
46 |
47 |
48 | def main():
49 |
50 | parser = argparse.ArgumentParser()
51 | parser.add_argument('input', help="Input CORE file without time_bounds variable.")
52 | args = parser.parse_args()
53 |
54 | with nc.Dataset(args.input, 'r+') as f:
55 | try:
56 | time = f.variables['TIME']
57 | time_name = 'TIME'
58 | except KeyError as e:
59 | time = f.variables['Time']
60 | time_name = 'Time'
61 | time.bounds = 'time_bnds'
62 | if os.path.basename(args.input) == 'runoff.daitren.clim.10FEB2011.nc':
63 | assert time.units == "days since 0001-01-01 00:00:00"
64 | time.units = "days since 1900-01-01 00:00:00"
65 |
66 | # Create extra dimension for time_bnds variable
67 | f.createDimension('time_bnds_dim', 2)
68 | time_bnds = f.createVariable('time_bnds', 'f8', (time_name, 'time_bnds_dim'))
69 |
70 | if len(time) == 12:
71 | # Assume this is monthly data and use hard-coded time_bounds. This
72 | # is necessary because ncar_precip and runoff have different dimensions
73 | # despite both being monthly.
74 | time_bnds[:, :] = [[0, 31], [31, 59], [59, 90], [90, 120],
75 | [120, 151], [151, 181], [181, 212], [212, 243],
76 | [243, 273], [273, 304], [304, 334], [334, 365]]
77 | else:
78 | # Calculate time bounds.
79 | for i, t in enumerate(time[:]):
80 | if i == 0:
81 | time_bnds[i, 0] = 0
82 | time_bnds[i, 1] = t*2
83 | else:
84 | time_bnds[i, 0] = time_bnds[i-1, 1]
85 | time_bnds[i, 1] = time_bnds[i, 0] + (time[i] - time_bnds[i-1, 1])*2
86 |
87 | # Update the file history.
88 | my_dir = dir_path = os.path.dirname(os.path.realpath(__file__))
89 | history = get_history_record(os.path.join(my_dir, '../'))
90 | if hasattr(f, 'history'):
91 | f.history = '{} \n {}'.format(f.history, history)
92 | else:
93 | f.history = history
94 |
95 | if __name__ == "__main__":
96 | sys.exit(main())
97 |
--------------------------------------------------------------------------------
/tools/calc_input_checksum.py:
--------------------------------------------------------------------------------
1 |
2 | import sys
3 | import os
4 | import tempfile
5 | import tarfile
6 | import hashlib
7 | import argparse
8 |
9 | def calc_checksum(dirname):
10 | """
11 | Calculate the checksum of a whole directory.
12 |
13 | This is done but tarring the directory first to make sure that file names
14 | and other metadata are included in the checksum.
15 |
16 | FIXME: this doesn't work, subsequent invokations of the function do not
17 | give the same value. This may be because the tmp file name is different
18 | each time.
19 | """
20 |
21 | _, tmp = tempfile.mkstemp(suffix='.tar')
22 | with tarfile.open(tmp, "w") as tar:
23 | tar.add(dirname)
24 |
25 | h = hashlib.md5()
26 |
27 | with open(tmp, "rb") as f:
28 | for chunk in iter(lambda: f.read(4096), b""):
29 | h.update(chunk)
30 |
31 | # Delete tarball now that hash has been calculated.
32 | os.remove(tmp)
33 |
34 | return h.hexdigest()[:8]
35 |
36 |
37 | def main():
38 |
39 | parser = argparse.ArgumentParser()
40 | parser.add_argument('dirpath', help='Path of directory whose checksum to return.')
41 |
42 | args = parser.parse_args()
43 |
44 | checksum = calc_checksum(args.dirpath)
45 | print(checksum)
46 |
47 |
48 | if __name__ == '__main__':
49 | sys.exit(main())
50 |
--------------------------------------------------------------------------------
/tools/contrib/build_esmf_on_raijin.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | git archive --remote=git://git.code.sf.net/p/esmf/esmf --format=tar --prefix=esmf/ ESMF_7_1_0r | tar xf -
4 | module load netcdf/4.4.1.1
5 | module load intel-fc/17.0.1.132
6 | mkdir -p bin
7 | cd esmf
8 | export ESMF_DIR=$(pwd)
9 | export ESMF_F90COMPILER=ifort
10 | export ESMF_F90LINKER=ifort
11 | export ESMF_NETCDF="split"
12 | export ESMF_NETCDF_INCLUDE=$NETCDF_ROOT/include
13 | export ESMF_NETCDF_LIBPATH=$NETCDF_ROOT/lib
14 | export ESMF_NETCDF_LIBS="-lnetcdff -lnetcdf"
15 | make
16 | cd src/apps/ESMF_RegridWeightGen
17 | make
18 | cd ../../../../
19 | cp esmf/apps/appsO/*/ESMF_RegridWeightGen bin/
20 | export PATH=$(pwd)/bin:$PATH
21 |
--------------------------------------------------------------------------------
/tools/contrib/build_esmf_on_ubuntu.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | mkdir bin
4 | sudo apt-get install libnetcdf-dev libnetcdff-dev
5 | wget http://s3-ap-southeast-2.amazonaws.com/dp-drop/ocean-regrid/contrib/esmf_7_0_0_src.tar.gz
6 | tar zxvf esmf_7_0_0_src.tar.gz
7 | cd esmf
8 | export ESMF_DIR=$(pwd)
9 | export ESMF_NETCDF="split"
10 | export ESMF_NETCDF_INCLUDE=/usr/include/
11 | export ESMF_NETCDF_LIBPATH=/usr/lib/x86_64-linux-gnu/
12 | export ESMF_NETCDF_LIBS="-lnetcdff -lnetcdf"
13 | make
14 | cd src/apps/ESMF_RegridWeightGen
15 | make
16 | cd ../../../../
17 | cp esmf/apps/appsO/*/ESMF_RegridWeightGen bin/
18 | export PATH=$(pwd)/bin:$PATH
19 |
--------------------------------------------------------------------------------
/tools/make_cice_grid.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sys
4 | import os
5 | import argparse
6 |
7 | my_dir = os.path.dirname(os.path.realpath(__file__))
8 | sys.path.append(os.path.join(my_dir, 'esmgrids'))
9 |
10 | from esmgrids.mom_grid import MomGrid # noqa
11 | from esmgrids.cice_grid import CiceGrid # noqa
12 |
13 | """
14 | Create CICE grid.nc and kmt.nc from MOM ocean_hgrid.nc and ocean_mask.nc
15 | """
16 |
17 | def main():
18 |
19 | parser = argparse.ArgumentParser()
20 | parser.add_argument('ocean_hgrid', help='ocean_mask.nc file')
21 | parser.add_argument('ocean_mask', help='ocean_hgrid.nc file')
22 |
23 | args = parser.parse_args()
24 |
25 | mom = MomGrid.fromfile(args.ocean_hgrid, mask_file=args.ocean_mask)
26 |
27 | # FIXME:
28 | # MOM dx is at the cell centre while HTN is on the Northern boundary
29 | # MOM dy is at the cell centre while HTE is on the Eastern boundary
30 | cice = CiceGrid.fromgrid(mom)
31 |
32 | grid_file = os.path.join('grid.nc')
33 | mask_file = os.path.join('kmt.nc')
34 | cice.write(grid_file, mask_file)
35 |
36 | if __name__ == '__main__':
37 | sys.exit(main())
38 |
--------------------------------------------------------------------------------
/tools/make_remap_weights.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | from __future__ import print_function
4 |
5 | import sys
6 | import os
7 | import shutil
8 | import shlex
9 | import argparse
10 | import netCDF4 as nc
11 | import numpy as np
12 | import tempfile
13 | import subprocess as sp
14 | import multiprocessing as mp
15 |
16 | my_dir = os.path.dirname(os.path.realpath(__file__))
17 | sys.path.append(os.path.join(my_dir, './esmgrids'))
18 |
19 | from esmgrids.mom_grid import MomGrid # noqa
20 | from esmgrids.core2_grid import Core2Grid # noqa
21 | from esmgrids.jra55_grid import Jra55Grid # noqa
22 | from esmgrids.jra55_river_grid import Jra55RiverGrid # noqa
23 | from esmgrids.daitren_runoff_grid import DaitrenRunoffGrid # noqa
24 |
25 | """
26 | This script makes all of the remapping weights for ACCESS-OM2.
27 |
28 | Run example:
29 |
30 | ./make_remap_weights.py /short/x77/nah599/access-om2/input/ \
31 | /g/data/ua8/JRA55-do/RYF/v1-3/
32 | """
33 |
34 | def convert_to_scrip_output(weights):
35 |
36 | my_dir = os.path.dirname(os.path.realpath(__file__))
37 |
38 | _, new_weights = tempfile.mkstemp(suffix='.nc', dir=my_dir)
39 | # So that ncrename doesn't prompt for overwrite.
40 | os.remove(new_weights)
41 |
42 | cmdstring = ('ncrename -d n_a,src_grid_size -d n_b,dst_grid_size -d n_s,'
43 | 'num_links -d nv_a,src_grid_corners -d nv_b,dst_grid_corner'
44 | 's -v yc_a,src_grid_center_lat -v yc_b,dst_grid_center_lat '
45 | '-v xc_a,src_grid_center_lon -v xc_b,dst_grid_center_lon -v'
46 | ' yv_a,src_grid_corner_lat -v xv_a,src_grid_corner_lon -v y'
47 | 'v_b,dst_grid_corner_lat -v xv_b,dst_grid_corner_lon -v mas'
48 | 'k_a,src_grid_imask -v mask_b,dst_grid_imask -v area_a,src_'
49 | 'grid_area -v area_b,dst_grid_area -v frac_a,src_grid_frac '
50 | '-v frac_b,dst_grid_frac -v col,src_address -v row,dst_addr'
51 | 'ess {} {}')
52 | cmd = cmdstring.format(weights, new_weights)
53 |
54 | try:
55 | sp.check_output(shlex.split(cmd))
56 | except sp.CalledProcessError as e:
57 | print(cmd, file=sys.stderr)
58 | print(e.output, file=sys.stderr)
59 | return None
60 |
61 | # Fix the dimension of the remap_matrix.
62 | with nc.Dataset(weights) as f_old, nc.Dataset(new_weights, 'r+') as f_new:
63 | remap_matrix = f_new.createVariable('remap_matrix',
64 | 'f8', ('num_links', 'num_wgts'))
65 | remap_matrix[:, 0] = f_old.variables['S'][:]
66 |
67 | os.remove(weights)
68 |
69 | return new_weights
70 |
71 |
72 | def create_weights(src_grid, dest_grid, npes, method,
73 | ignore_unmapped=False,
74 | unmasked_src=True, unmasked_dest=False):
75 |
76 | my_dir = os.path.dirname(os.path.realpath(__file__))
77 |
78 | _, src_grid_scrip = tempfile.mkstemp(suffix='.nc', dir=my_dir)
79 | _, dest_grid_scrip = tempfile.mkstemp(suffix='.nc', dir=my_dir)
80 | _, regrid_weights = tempfile.mkstemp(suffix='.nc', dir=my_dir)
81 |
82 | if unmasked_src:
83 | src_grid.write_scrip(src_grid_scrip, write_test_scrip=False,
84 | mask=np.zeros_like(src_grid.mask_t, dtype=int))
85 | else:
86 | src_grid.write_scrip(src_grid_scrip, write_test_scrip=False)
87 |
88 | if unmasked_dest:
89 | dest_grid.write_scrip(dest_grid_scrip, write_test_scrip=False,
90 | mask=np.zeros_like(dest_grid.mask_t, dtype=int))
91 | else:
92 | dest_grid.write_scrip(dest_grid_scrip, write_test_scrip=False)
93 |
94 | if ignore_unmapped:
95 | ignore_unmapped = ['--ignore_unmapped']
96 | else:
97 | ignore_unmapped = []
98 |
99 | try:
100 | cmd = ['mpirun', '-np', str(npes), 'ESMF_RegridWeightGen'] + \
101 | ['--netcdf4',
102 | '-s', src_grid_scrip,
103 | '-d', dest_grid_scrip, '-m', method,
104 | '-w', regrid_weights] + ignore_unmapped
105 | print(cmd)
106 | sp.check_output(cmd)
107 | except sp.CalledProcessError as e:
108 | print("Error: ESMF_RegridWeightGen failed ret {}".format(e.returncode),
109 | file=sys.stderr)
110 | print(e.output, file=sys.stderr)
111 | log = 'PET0.RegridWeightGen.Log'
112 | if os.path.exists(log):
113 | print('Contents of {}:'.format(log), file=sys.stderr)
114 | with open(log) as f:
115 | print(f.read(), file=sys.stderr)
116 | return None
117 |
118 | os.remove(src_grid_scrip)
119 | os.remove(dest_grid_scrip)
120 |
121 | return regrid_weights
122 |
123 |
124 | def find_grid_defs(input_dir, jra55_input, core_input):
125 | """
126 | Return a dictionary containing the grid definition files.
127 | """
128 |
129 | d = {}
130 | d['MOM1'] = (os.path.join(input_dir, 'mom_1deg', 'ocean_hgrid.nc'),
131 | os.path.join(input_dir, 'mom_1deg', 'ocean_mask.nc'))
132 | d['MOM025'] = (os.path.join(input_dir, 'mom_025deg', 'ocean_hgrid.nc'),
133 | os.path.join(input_dir, 'mom_025deg', 'ocean_mask.nc'))
134 | d['MOM01'] = (os.path.join(input_dir, 'mom_01deg', 'ocean_hgrid.nc'),
135 | os.path.join(input_dir, 'mom_01deg', 'ocean_mask.nc'))
136 | d['CORE2'] = os.path.join(core_input, 't_10.0001.nc')
137 | d['JRA55'] = os.path.join(jra55_input, 'RYF.tas.1990_1991.nc')
138 | d['JRA55_runoff'] = os.path.join(jra55_input,
139 | 'RYF.runoff_all.1990_1991.nc')
140 | d['Daitren_runoff'] = os.path.join(core_input, 'runoff.daitren.clim.10FEB2011.nc')
141 |
142 | return d
143 |
144 |
145 | def main():
146 |
147 | parser = argparse.ArgumentParser()
148 | parser.add_argument('input_dir', help="""
149 | The ACCESS-OM2 input directory.""")
150 | parser.add_argument('jra55_input', help="""
151 | The JRA55 input directory.""")
152 | parser.add_argument('core_input', help="""
153 | The CORE input directory.""")
154 | parser.add_argument('--atm', default=None, help="""
155 | Atmosphere grid to regrid from, can be one of:
156 | CORE2, JRA55, JRA55_runoff, Daitren_runoff""")
157 | parser.add_argument('--ocean', default=None, help="""
158 | Ocean grid to regrid to, can be one of:
159 | MOM1, MOM01, MOM025""")
160 | parser.add_argument('--method', default=None, help="""
161 | The interpolation method to use, can be patch, conserve or conserve2nd""")
162 | parser.add_argument('--npes', default=None, help="""
163 | The number of PEs to use.""")
164 | parser.add_argument('--unmask_dest',
165 | action='store_true',
166 | help='Ignore destination grid mask')
167 |
168 | args = parser.parse_args()
169 | atm_options = ['JRA55', 'JRA55_runoff', 'CORE2', 'Daitren_runoff']
170 | ocean_options = ['MOM1', 'MOM025', 'MOM01']
171 | method_options = ['patch', 'conserve', 'conserve2nd']
172 |
173 | if args.atm is None:
174 | args.atm = atm_options
175 | else:
176 | if args.atm not in atm_options:
177 | print("Error: bad atm grid.", file=sys.stderr)
178 | parser.print_help()
179 | return 1
180 | args.atm = [args.atm]
181 |
182 | if args.ocean is None:
183 | args.ocean = ocean_options
184 | else:
185 | if args.ocean not in ocean_options:
186 | print("Error: bad atm grid.", file=sys.stderr)
187 | parser.print_help()
188 | return 1
189 | args.ocean = [args.ocean]
190 |
191 | if args.method is None:
192 | args.method = method_options
193 | else:
194 | args.method = [args.method]
195 |
196 | if args.npes is None:
197 | import multiprocessing as mp
198 | args.npes = mp.cpu_count() // 2
199 |
200 | grid_file_dict = find_grid_defs(args.input_dir, args.jra55_input, args.core_input)
201 |
202 | for ocean in args.ocean:
203 | umask_file = grid_file_dict[ocean][1]
204 | dest_grid = MomGrid.fromfile(grid_file_dict[ocean][0],
205 | mask_file=umask_file)
206 | for atm in args.atm:
207 |
208 | if atm == 'CORE2':
209 | src_grid = Core2Grid(grid_file_dict[atm])
210 | elif atm == 'Daitren_runoff':
211 | src_grid = DaitrenRunoffGrid(grid_file_dict[atm])
212 | elif atm == 'JRA55':
213 | src_grid = Jra55Grid(grid_file_dict[atm])
214 | elif atm == 'JRA55_runoff':
215 | src_grid = Jra55RiverGrid(grid_file_dict[atm], calc_areas=False)
216 | else:
217 | print('Unrecognised atmosphere grid: {}'.format(atm))
218 | return 1
219 |
220 | for method in args.method:
221 |
222 | weights = create_weights(src_grid, dest_grid, args.npes,
223 | method, unmasked_dest=args.unmask_dest)
224 | if not weights:
225 | return 1
226 | weights = convert_to_scrip_output(weights)
227 | if not weights:
228 | return 1
229 |
230 | shutil.move(weights, '{}_{}_{}.nc'.format(atm, ocean, method))
231 |
232 | return 0
233 |
234 | if __name__ == "__main__":
235 | sys.exit(main())
236 |
--------------------------------------------------------------------------------
/tools/make_remap_weights.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #PBS -P x77
3 | #PBS -q normal
4 | #PBS -l ncpus=256,mem=512GB,walltime=05:00:00,jobfs=100GB
5 | #PBS -l storage=gdata/hh5+gdata/ik11
6 | #PBS -l wd
7 |
8 | module purge
9 | module load openmpi
10 | module load nco
11 | module load esmf/8.1.0
12 | module use /g/data/hh5/public/modules
13 | module load conda/analysis3
14 |
15 | # Make all 1 deg weights.
16 | time ./make_remap_weights.py /short/x77/nah599/access-om2/input/ /g/data/ua8/JRA55-do/RYF/v1-3/ /short/x77/nah599/access-om2/input/yatm_1deg/ --ocean MOM1 --npes 256
17 |
18 | # Make all 0.25 deg weights.
19 | time ./make_remap_weights.py /short/x77/nah599/access-om2/input/ /g/data/ua8/JRA55-do/RYF/v1-3/ /short/x77/nah599/access-om2/input/yatm_1deg/ --ocean MOM025 --npes 256
20 |
21 | # Make all 0.1 deg weights.
22 | time ./make_remap_weights.py /short/x77/nah599/access-om2/input/ /g/data/ua8/JRA55-do/RYF/v1-3/ /short/x77/nah599/access-om2/input/yatm_1deg/ --ocean MOM01 --npes 256
23 |
--------------------------------------------------------------------------------
/tools/make_salt_sfc_restore.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import numpy as np
4 | import sys
5 | import numba
6 | import os
7 | import argparse
8 | import netCDF4 as nc
9 | import shutil
10 | from scipy.ndimage.filters import uniform_filter
11 | from make_remap_weights import create_weights
12 |
13 | from esmgrids.mom_grid import MomGrid # noqa
14 | from esmgrids.woa_grid import WoaGrid # noqa
15 |
16 | """
17 | Create MOM salt_sfc_restore.nc file from WOA
18 | """
19 |
20 | def calc_regridding_err(weights, src, dest):
21 | """
22 | Calculate the regridding error.
23 | """
24 |
25 | EARTH_RADIUS = 6370997.0
26 |
27 | with nc.Dataset(weights) as f:
28 | try:
29 | area_a = f.variables['area_a'][:]
30 | except KeyError as e:
31 | area_a = f.variables['src_grid_area'][:]
32 | area_a = area_a.reshape(src.shape[0], src.shape[1])
33 | area_a = area_a*EARTH_RADIUS**2
34 |
35 | try:
36 | area_b = f.variables['area_b'][:]
37 | except KeyError as e:
38 | area_b = f.variables['dst_grid_area'][:]
39 | area_b = area_b.reshape(dest.shape[0], dest.shape[1])
40 | area_b = area_b*EARTH_RADIUS**2
41 |
42 | try:
43 | frac_a = f.variables['frac_a'][:]
44 | except KeyError as e:
45 | frac_a = f.variables['src_grid_frac'][:]
46 | frac_a = frac_a.reshape(src.shape[0], src.shape[1])
47 |
48 | try:
49 | frac_b = f.variables['frac_b'][:]
50 | except KeyError as e:
51 | frac_b = f.variables['dst_grid_frac'][:]
52 | frac_b = frac_b.reshape(dest.shape[0], dest.shape[1])
53 |
54 | # Calculation of totals here.
55 | # http://www.earthsystemmodeling.org/esmf_releases/non_public/ESMF_5_3_0/ESMC_crefdoc/node3.html
56 | src_tot = np.sum(src[:, :] * area_a[:, :] * frac_a[:, :])
57 | dest_tot = np.sum(dest[:, :] * area_b[:, :])
58 | rel_err = abs(src_tot - dest_tot) / dest_tot
59 |
60 | return rel_err
61 |
62 | @numba.jit
63 | def apply_weights(src, dest_shape, n_s, n_b, row, col, s):
64 | """
65 | Apply ESMF regirdding weights.
66 | """
67 |
68 | dest = np.ndarray(dest_shape).flatten()
69 | dest[:] = 0.0
70 | src = src.flatten()
71 |
72 | for i in range(n_s):
73 | dest[row[i]-1] = dest[row[i]-1] + s[i]*src[col[i]-1]
74 |
75 | return dest.reshape(dest_shape)
76 |
77 |
78 | def remap(src_data, weights, dest_shape):
79 | """
80 | Regrid a 2d field and see how it looks.
81 | """
82 |
83 | dest_data = np.ndarray(dest_shape)
84 |
85 | with nc.Dataset(weights) as wf:
86 | try:
87 | n_s = wf.dimensions['n_s'].size
88 | except KeyError as e:
89 | n_s = wf.dimensions['num_links'].size
90 | try:
91 | n_b = wf.dimensions['n_b'].size
92 | except KeyError as e:
93 | n_b = wf.dimensions['dst_grid_size'].size
94 | try:
95 | row = wf.variables['row'][:]
96 | except KeyError as e:
97 | row = wf.variables['dst_address'][:]
98 | try:
99 | col = wf.variables['col'][:]
100 | except KeyError as e:
101 | col = wf.variables['src_address'][:]
102 |
103 | s = wf.variables['S'][:]
104 |
105 | dest_data[:, :] = apply_weights(src_data[:, :], dest_data.shape,
106 | n_s, n_b, row, col, s)
107 | return dest_data
108 |
109 |
110 | def smooth2d(src):
111 |
112 | tmp_src = np.ndarray((src.shape[0] + 6, src.shape[1]))
113 |
114 | # Window size
115 | ws = 3
116 |
117 | tmp_src[ws:-ws, :] = src[:, :]
118 | tmp_src[:ws, :] = src[-ws:, :]
119 | tmp_src[-ws:, :] = src[:3, :]
120 |
121 | dest = uniform_filter(tmp_src, size=ws, mode='nearest')
122 | return dest[ws:-ws, :]
123 |
124 |
125 | def main():
126 |
127 | parser = argparse.ArgumentParser()
128 | parser.add_argument('woa_input', help='The WOA input file.')
129 | parser.add_argument('ocean_hgrid',
130 | help='The horizontal MOM grid definition to remap to')
131 | parser.add_argument('old_salt_sfc_restore',
132 | help='The old salt sfc restoring file. Needed for metadata.')
133 | parser.add_argument('output', help='salt_sfc_restore.nc file for MOM5')
134 | parser.add_argument('--interpolation_weights', default=None,
135 | help='Interpolation weights, file if not given this will be created.')
136 | parser.add_argument('--method', default='patch', help="""
137 | Interpolation method, passed to ESMF_RegridWeightGen.""")
138 | parser.add_argument('--npes', default=None, help="""
139 | The number of PEs to use. Default is 1/2 of available.""")
140 |
141 |
142 | args = parser.parse_args()
143 |
144 | if args.npes is None:
145 | import multiprocessing as mp
146 | args.npes = mp.cpu_count() // 2
147 |
148 | src_grid = WoaGrid(args.woa_input, calc_areas=False)
149 | dest_grid = MomGrid.fromfile(args.ocean_hgrid, calc_areas=False)
150 | dest_res = (dest_grid.num_lat_points, dest_grid.num_lon_points)
151 |
152 | if args.interpolation_weights is None:
153 | weights = create_weights(src_grid, dest_grid, args.npes, args.method)
154 | else:
155 | weights = args.interpolation_weights
156 |
157 | with nc.Dataset(args.woa_input) as f:
158 | src = f.variables['so'][:]
159 |
160 | dest = np.zeros((src.shape[0], dest_res[0], dest_res[1]))
161 |
162 | for t in range(src.shape[0]):
163 | smooth_src = smooth2d(src[t, :, :])
164 | dest[t, :, :] = remap(smooth_src, weights, dest_res)
165 |
166 | if 'conserve' in args.method:
167 | rel_err = calc_regridding_err(weights, smooth_src, dest[t, :, :])
168 | print('relative error {}'.format(rel_err))
169 | assert rel_err < 1e-14
170 |
171 | shutil.copyfile(args.old_salt_sfc_restore, args.output)
172 | with nc.Dataset(args.output, 'r+') as f:
173 | f.variables['salt'][:] = dest
174 |
175 | if __name__ == '__main__':
176 | sys.exit(main())
177 |
--------------------------------------------------------------------------------
/tools/release.py:
--------------------------------------------------------------------------------
1 |
2 | from __future__ import print_function
3 |
4 | import os
5 | import sys
6 | import re
7 | import shutil
8 | import stat
9 | import argparse
10 | import distutils.dir_util
11 | import tempfile
12 | from calc_input_checksum import calc_checksum
13 |
14 | my_path = os.path.dirname(os.path.realpath(__file__))
15 | sys.path.append(os.path.join(my_path, '../', 'test'))
16 | from exp_test_helper import ExpTestHelper
17 |
18 | EXP_NAMES = ['01deg_jra55_ryf', '01deg_jra55_iaf',
19 | '1deg_jra55_ryf', '1deg_jra55_iaf',
20 | '025deg_jra55_ryf', '025deg_jra55_iaf']
21 |
22 | def update_payu_config(exp_name, res, payu_config, yatm_exe, cice_exe, mom_exe, input_dir=None):
23 | """
24 | Set the new input_dirs and exes in payu config.yaml
25 | """
26 |
27 | _, tmp = tempfile.mkstemp()
28 |
29 | with open(payu_config) as fs, open(tmp, 'r+') as fd:
30 | cur_model = None
31 | for line in fs:
32 | m = re.search('^[\s-]*name:\s+(\S+)', line)
33 | if m:
34 | cur_model = m.group(1)
35 |
36 | if re.search('collate', line):
37 | cur_model = 'collate'
38 |
39 | m_exe = re.search('^\s*exe:\s+\S+', line)
40 | if input_dir:
41 | m_input = re.search('^\s*input:\s+\S+', line)
42 | else:
43 | m_input = None
44 |
45 | if m_exe:
46 | assert cur_model
47 | if cur_model == 'atmosphere':
48 | print(' exe: {}'.format(yatm_exe), file=fd)
49 | elif cur_model == 'ocean':
50 | print(' exe: {}'.format(mom_exe), file=fd)
51 | elif cur_model == 'ice':
52 | print(' exe: {}'.format(cice_exe), file=fd)
53 | else:
54 | print(line, file=fd, end='')
55 | elif m_input:
56 | assert cur_model
57 | if cur_model == 'common':
58 | if 'jra55' in exp_name:
59 | common_input = os.path.join(input_dir, 'common_{}_{}'.format(res, 'jra55'))
60 | else:
61 | common_input = os.path.join(input_dir, 'common_{}_{}'.format(res, 'core'))
62 | print('input: {}'.format(common_input), file=fd)
63 | elif cur_model == 'atmosphere':
64 | yatm_input = os.path.join(input_dir, 'yatm_{}'.format(res))
65 | print(' input: {}'.format(yatm_input), file=fd)
66 | elif cur_model == 'ocean':
67 | mom_input = os.path.join(input_dir, 'mom_{}'.format(res))
68 | print(' input: {}'.format(mom_input), file=fd)
69 | elif cur_model == 'ice':
70 | cice_input = os.path.join(input_dir, 'cice_{}'.format(res))
71 | print(' input: {}'.format(cice_input), file=fd)
72 | else:
73 | print(line, file=fd, end='')
74 | else:
75 | print(line, file=fd, end='')
76 |
77 | shutil.copy(tmp, payu_config)
78 |
79 |
80 | def set_input_perms_recursively(path):
81 |
82 | dirperms = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IXUSR \
83 | | stat.S_IXGRP | stat.S_IXOTH
84 | shutil.chown(path, group='v45')
85 | os.chmod(path, dirperms)
86 |
87 | for root, dirs, files in os.walk(path):
88 | for d in dirs:
89 | dirname = os.path.join(root, d)
90 | shutil.chown(dirname, group='ik11')
91 | os.chmod(dirname, dirperms)
92 | for f in files:
93 | fname = os.path.join(root, f)
94 | shutil.chown(fname, group='ik11')
95 | perms = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH
96 | os.chmod(fname, perms)
97 |
98 |
99 | def update_input_data():
100 |
101 | input_template = '/g/data/ik11/inputs/access-om2/input_{}'
102 | input_rc = input_template.format('rc')
103 |
104 | checksum = calc_checksum(input_rc)
105 | input_chksum = input_template.format(checksum)
106 |
107 | # Copy release candidate (rc) to dirctory with checksum
108 | if not os.path.exists(input_chksum):
109 | # For some reason shutil.copytree() doesn't work here.
110 | distutils.dir_util.copy_tree(input_rc, input_chksum, preserve_symlinks=True)
111 |
112 | # Fix up permissions.
113 | set_input_perms_recursively(input_chksum)
114 |
115 | return input_chksum
116 |
117 |
118 | def do_release(update_input_data=False):
119 |
120 | if update_input_data:
121 | input_dir = update_input_data()
122 | else:
123 | input_dir = None
124 |
125 | for exp_name in EXP_NAMES:
126 |
127 | # Build new exes.
128 | exp = ExpTestHelper(exp_name, bin_path='/g/data/ik11/inputs/access-om2/bin/')
129 | (yatm_exe, cice_exe, mom_exe), ret = exp.build()
130 | if ret != 0:
131 | print('Build failed for exp {}'.format(exp_name), file=sys.stderr)
132 | assert ret == 0
133 |
134 | update_payu_config(exp.exp_name, exp.res, exp.payu_config, yatm_exe, cice_exe, mom_exe, input_dir)
135 |
136 | def main():
137 |
138 | parser = argparse.ArgumentParser()
139 | parser.add_argument('--update_input', default=False, action='store_true',
140 | help='Update experiment input directories as well.')
141 |
142 | args = parser.parse_args()
143 |
144 | do_release(update_input_data=args.update_input)
145 |
146 |
147 | if __name__ == '__main__':
148 | sys.exit(main())
149 |
150 |
151 |
--------------------------------------------------------------------------------