diff --git a/.github/workflows/ubuntu-basic.yml b/.github/workflows/ubuntu-basic.yml index 831e3bbaf..c5836ea08 100644 --- a/.github/workflows/ubuntu-basic.yml +++ b/.github/workflows/ubuntu-basic.yml @@ -55,11 +55,9 @@ jobs: --with-scalapack-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-mumps-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" + --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" ext_pkg_build_command: | cd $ISSM_DIR/externalpackages/triangle && ./install-linux.sh - cd $ISSM_DIR/externalpackages/m1qn3 && ./install-linux.sh cd $ISSM_DIR/externalpackages/petsc && ./install-3.22-linux.sh cd $ISSM_DIR/externalpackages/semic && ./install.sh test_cases: '["101:399", "401:899"]' diff --git a/.github/workflows/ubuntu-codipack.yml b/.github/workflows/ubuntu-codipack.yml index 0a1fdae22..e8995a6c5 100644 --- a/.github/workflows/ubuntu-codipack.yml +++ b/.github/workflows/ubuntu-codipack.yml @@ -59,12 +59,10 @@ jobs: --with-mumps-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ --with-gsl-dir="${ISSM_DIR}/externalpackages/gsl/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ --with-medipack-dir="${ISSM_DIR}/externalpackages/medipack/install" \ --with-codipack-dir="${ISSM_DIR}/externalpackages/codipack/install" ext_pkg_build_command: | cd $ISSM_DIR/externalpackages/triangle && ./install-linux.sh - cd $ISSM_DIR/externalpackages/m1qn3 && ./install-linux.sh cd $ISSM_DIR/externalpackages/petsc && ./install-3.22-linux.sh cd $ISSM_DIR/externalpackages/gsl && ./install.sh cd $ISSM_DIR/externalpackages/codipack && ./install.sh diff --git a/.github/workflows/ubuntu-python.yml b/.github/workflows/ubuntu-python.yml index e68758489..fc3ecb564 100644 --- a/.github/workflows/ubuntu-python.yml +++ b/.github/workflows/ubuntu-python.yml @@ -59,11 +59,9 @@ jobs: --with-scalapack-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-mumps-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" + --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" ext_pkg_build_command: | cd $ISSM_DIR/externalpackages/triangle && ./install-linux.sh - cd $ISSM_DIR/externalpackages/m1qn3 && ./install-linux.sh cd $ISSM_DIR/externalpackages/petsc && ./install-3.22-linux.sh cd $ISSM_DIR/externalpackages/semic && ./install.sh test_cases: '["101:399", "401:899"]' diff --git a/.gitignore b/.gitignore index 7f7b47c91..3299ccbda 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ config.h.in~ config.log config.status configure +configure~ configure.sh libtool stamp-h1 @@ -96,3 +97,5 @@ examples/Data/*.txt examples/Data/*.zip examples/Data/Jakobshavn_2008_2011_Composite examples/Helheim/Models +examples/Inversion/*.mat +examples/Inversion/*.tar.gz diff --git a/CLAUDE.md b/CLAUDE.md index f2daf625d..17a22de19 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,7 +21,6 @@ External packages must be installed before configuring ISSM. The minimum require ```sh cd $ISSM_DIR/externalpackages/triangle && ./install-linux.sh # or install-mac.sh -cd $ISSM_DIR/externalpackages/m1qn3 && ./install-linux.sh cd $ISSM_DIR/externalpackages/petsc && ./install-3.22-linux.sh ``` @@ -35,7 +34,7 @@ make -j$(nproc) make install ``` -Key `configure` flags: `--prefix=$ISSM_DIR`, `--with-matlab-dir`, `--with-python`, `--with-petsc-dir`, `--with-triangle-dir`, `--with-m1qn3-dir`, `--enable-debugging`. +Key `configure` flags: `--prefix=$ISSM_DIR`, `--with-matlab-dir`, `--with-python`, `--with-petsc-dir`, `--with-triangle-dir`, `--enable-debugging`. ## Running Tests @@ -49,7 +48,9 @@ cd $ISSM_DIR/test/NightlyRun ./runme.py # run all nightly tests ./runme.py -i 101 102 # run specific tests by ID ./runme.py -i SquareShelf # run by (partial) name -./runme.py --benchmark nightly # benchmark filter +./runme.py -b nightly # benchmark filter (-b/--benchmark: all/nightly/ismip/eismint/thermal/mesh/slc/qmu/...) +./runme.py -e Dakota # exclude tests by ID or name (-e/--exclude) +./runme.py -p update # update reference archive (-p/--procedure: check/update) ``` **MATLAB** (from within MATLAB): @@ -61,7 +62,7 @@ runme('id', [101 102]) % run specific tests runme('id', 102, 'procedure', 'update') % update reference archive (developers only) ``` -To update a test's reference archive (after an intentional result change), use `procedure='update'` (MATLAB) or `--procedure update` (Python). +To update a test's reference archive (after an intentional result change), use `procedure='update'` (MATLAB) or `-p update` (Python). ## Code Architecture @@ -69,10 +70,12 @@ To update a test's reference archive (after an intentional result change), use ` ISSM has two layers that work together: -1. **High-level interfaces** (`src/m/`) — MATLAB (`.m`), Python (`.py`), and JavaScript (`.js`) code for building and parameterizing models, running simulations, and post-processing results. The key object is `model` (defined in `src/m/classes/model.m` / `model.py`), which holds all simulation fields as properties (mesh, geometry, materials, boundary conditions, solver settings, results, etc.). +1. **High-level interfaces** (`src/m/`) — MATLAB (`.m`), Python (`.py`), and JavaScript (`.js`) code for building and parameterizing models, running simulations, and post-processing results. The key object is `model` (defined in `src/m/classes/model.m` / `model.py` / `model.js`), which holds all simulation fields as properties (mesh, geometry, materials, boundary conditions, solver settings, results, etc.). 2. **C++ computational core** (`src/c/`) — compiled finite-element parallel engine that does the actual solving. +3. **JavaScript interface** (`src/m/js/`, `src/m/classes/model.js`) — browser/WebAssembly interface built via Emscripten, with wrappers in `src/wrappers/javascript/`. + The high-level interface generates input files (`.bin`, `.queue`, and `.toolkits`) that are read by the computational core. In turn, the results from the simulation are saved in an `.outbin` file that is read by the High-level interface and added to the model (saved in `md.results`) ### Typical model workflow @@ -81,7 +84,7 @@ The high-level interface generates input files (`.bin`, `.queue`, and `.toolkits triangle/mesh → setmask → parameterize → setflowequation → solve → results ``` -Each step corresponds to functions in `src/m/parameterization/` and `src/m/solve/`. `parameterize()` runs a user-supplied `.par` file that fills the `model` object fields. `solve()` marshals model data to binary, calls the C++ executable (`bin/issm.exe`), and loads results back into `md.results`. +Each step corresponds to functions in `src/m/parameterization/` and `src/m/solve/`. `parameterize()` runs a user-supplied `.par` file that fills the `model` object fields. `solve()` marshals model data to binary, calls the C++ executable (`bin/issm.exe` for ice dynamics, `bin/issm_slc.exe` for sea-level change), and loads results back into `md.results`. ### C++ core layout (`src/c/`) @@ -92,21 +95,29 @@ Each step corresponds to functions in `src/m/parameterization/` and `src/m/solve - **`modules/`** — Compiled callable modules exposed as MEX/Python wrappers (e.g., mesh generation, interpolation, partitioning). - **`toolkits/`** — Abstraction layer over PETSc, MPI, MUMPS, METIS for linear algebra and distributed computing. - **`datastructures/`** — `DataSet` container and `Object` base class used throughout the core. +- **`shared/`** — Shared utilities (I/O helpers, exceptions, enum definitions, math routines) used across the core. +- **`bamg/`** — BAMG anisotropic mesh generator (alternative to Triangle). +- **`main/`** — Entry-point source files for the compiled executables (`issm.cpp`, `issm_slc.cpp`, `kriging.cpp`). ### Wrappers (`src/wrappers/`) -Glue code that compiles C++ modules as shared libraries loadable from MATLAB (`*_matlab.la`) and Python (`*_python.la`). The `io/` subdirectory handles binary serialization of the `model` object (marshalling) for communication between the interface and the executable. +Glue code that compiles C++ modules as shared libraries loadable from MATLAB (`*_matlab.la`), Python (`*_python.la`), and JavaScript (`javascript/` via Emscripten/WebAssembly). The `io/` subdirectory handles binary serialization of the `model` object (marshalling) for communication between the interface and the executable. ### External packages (`externalpackages/`) Each subdirectory has its own `install-linux.sh` / `install-mac.sh` / etc. ISSM only needs a handful of external packages installed depending on the desired configuration. The key dependencies are: - **PETSc** (includes MPI/MPICH, BLAS/LAPACK, MUMPS, METIS/ParMETIS, ScaLAPACK) - **Triangle** (mesh generation), -- **m1qn3** (L-BFGS optimizer for inversions). -Some optional that can be useful depending on the application: -- **Dakota** (UQ/sampling), -- **CoDiPack** (automatic differentiation) +Some optional packages that can be useful depending on the application: +- **Dakota** (UQ/sampling) +- **CoDiPack** / **ADOL-C** (automatic differentiation) +- **GDAL** / **PROJ** (geospatial data I/O and coordinate transforms) +- **NetCDF** / **HDF5** (scientific data file formats) +- **Boost** (C++ utilities) +- **GSL** (GNU Scientific Library) +- **Gmsh** (alternative mesh generation) +- **ESMF** (Earth System Modeling Framework coupling) ### Path setup for interfaces diff --git a/LICENSE b/LICENSE index 8733a8125..f944d104f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ Ice-sheet and Sea-level System Model (ISSM) is a California Institute of Technology Copyright, distributed under BSD 3-Clause License. -Copyright (c) 2002-2024, California Institute of Technology. All rights +Copyright (c) 2002-2026, California Institute of Technology. All rights reserved. Based on Government Sponsored Research under contracts NAS7-1407 and/or NAS7-03001. diff --git a/configure.ac b/configure.ac index 2e64d6d98..19148628a 100644 --- a/configure.ac +++ b/configure.ac @@ -10,6 +10,11 @@ AC_MSG_NOTICE(================================================================== AC_MSG_NOTICE(= AC_PACKAGE_NAME AC_PACKAGE_VERSION configuration =) AC_MSG_NOTICE(============================================================================) +#Make sure options were provided +AS_IF([test "x$prefix" = "xNONE"],[AC_MSG_ERROR([--prefix is not provided. + Did you run ./configure without any option? + Maybe you meant to run ./configure.sh?])]) + #Determine System type and OS AC_CANONICAL_TARGET diff --git a/examples/Greenland/runme.py b/examples/Greenland/runme.py index 15234d4ea..88cc6bffb 100755 --- a/examples/Greenland/runme.py +++ b/examples/Greenland/runme.py @@ -17,6 +17,8 @@ from BamgTriangulate import BamgTriangulate from InterpFromMeshToMesh2d import InterpFromMeshToMesh2d from scipy.interpolate import griddata +import matplotlib.pyplot as plt +import numpy as np steps = [1] @@ -152,7 +154,7 @@ 'title', 'Surface (m)') #Line Plots - figure + plt.figure #Plot surface mass balance, velocity and volume surfmb = [] @@ -190,7 +192,7 @@ t = np.arange(years_of_simulation[0], years_of_simulation[-1] + 11 / 12, 1 / 12) #Area of grid for 5km box area_of_grid = 5000 * 5000 - totalsmb = reshape(np.nansum(smbbox / 1000, axis=(-2, -1)), (len(t), 1)) * area_of_grid + totalsmb = np.reshape(np.nansum(smbbox / 1000, axis=(-2, -1)), (len(t), 1)) * area_of_grid #save surface mass balance mat dataset smbmean = np.nanmean(smbbox, axis=(0, 1)) diff --git a/externalpackages/autotools/install-mac.sh b/externalpackages/autotools/install-mac.sh index fa7ec10da..11f013838 100755 --- a/externalpackages/autotools/install-mac.sh +++ b/externalpackages/autotools/install-mac.sh @@ -4,10 +4,10 @@ set -eu ## Constants # -AUTOCONF_VER="2.69" -AUTOMAKE_VER="1.16.1" -LIBTOOL_VER="2.4.6" -M4_VER="1.4.19" +AUTOCONF_VER="2.73" +AUTOMAKE_VER="1.18.1" +LIBTOOL_VER="2.5.4" +M4_VER="1.4.21" PREFIX="${ISSM_DIR}/externalpackages/autotools/install" # Set to location where external package should be installed diff --git a/externalpackages/m1qn3/configs/linux/configure.make b/externalpackages/m1qn3/configs/linux/configure.make deleted file mode 100644 index 7e876a511..000000000 --- a/externalpackages/m1qn3/configs/linux/configure.make +++ /dev/null @@ -1,2 +0,0 @@ -STATIC_LIB_EXT=a -SHARED_LIB_EXT=so diff --git a/externalpackages/m1qn3/configs/mac/configure.make b/externalpackages/m1qn3/configs/mac/configure.make deleted file mode 100644 index 100505b93..000000000 --- a/externalpackages/m1qn3/configs/mac/configure.make +++ /dev/null @@ -1,2 +0,0 @@ -STATIC_LIB_EXT=a -SHARED_LIB_EXT=dylib diff --git a/externalpackages/m1qn3/configs/makefile b/externalpackages/m1qn3/configs/makefile deleted file mode 100644 index f817bd472..000000000 --- a/externalpackages/m1qn3/configs/makefile +++ /dev/null @@ -1,37 +0,0 @@ -include ./configure.make - -ifeq "$(origin AR)" "undefined" - AR = ar -endif - -ifeq "$(origin RANLIB)" "undefined" - RANLIB = ranlib -endif - -OBJECTS=${LIBNAME}.o -SOURCES=${LIBNAME}.f - -objects: $(OBJECTS) - -shared: lib${LIBNAME}.$(SHARED_LIB_EXT) - -static: lib${LIBNAME}.$(STATIC_LIB_EXT) - -${LIBNAME}.o: $(SOURCES) - ${FC} ${FFLAGS} -fpic -c $< -o $@ - -lib${LIBNAME}.a: $(OBJECTS) - $(AR) -cr $@ $(OBJECTS) - $(RANLIB) $@ - -lib${LIBNAME}.dll: $(OBJECTS) - ${FC} ${FFLAGS} -shared -c $(SOURCES) -o $@ - -lib${LIBNAME}.dylib: $(OBJECTS) - ${FC} ${FFLAGS} -dynamiclib -install_name ${PREFIX}/lib/$@ -c $(SOURCES) -o $@ - -lib${LIBNAME}.so: $(OBJECTS) - ${FC} ${FFLAGS} -shared -c $(SOURCES) -o $@ - -clean: - rm -rf *.o *.$(SHARED_LIB_EXT) *.$(STATIC_LIB_EXT) diff --git a/externalpackages/m1qn3/configs/win/msys2/mingw64/configure.make b/externalpackages/m1qn3/configs/win/msys2/mingw64/configure.make deleted file mode 100644 index bd875ec43..000000000 --- a/externalpackages/m1qn3/configs/win/msys2/mingw64/configure.make +++ /dev/null @@ -1,2 +0,0 @@ -STATIC_LIB_EXT=a -SHARED_LIB_EXT=dll diff --git a/externalpackages/m1qn3/install-linux-static.sh b/externalpackages/m1qn3/install-linux-static.sh deleted file mode 100755 index 6e3aeb7f5..000000000 --- a/externalpackages/m1qn3/install-linux-static.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash -set -eu - -## Constants -# -VER=3.3 - -PREFIX="${ISSM_DIR}/externalpackages/m1qn3/install" # Set to location where external package should be installed - -# Cleanup -rm -rf ${PREFIX} src -mkdir -p ${PREFIX} src - -# Download source -$ISSM_DIR/scripts/DownloadExternalPackage.sh "https://github.com/ISSMteam/ExternalPackages/raw/refs/heads/main/m1qn3-${VER}-distrib.tgz" "m1qn3-${VER}-distrib.tgz" - -# Unpack source -tar -xzf m1qn3-${VER}-distrib.tgz - -# Move source to 'src' directory -mv m1qn3-${VER}-distrib/* src -rm -rf m1qn3-${VER}-distrib - -# Apply patches to src -patch src/src/m1qn3.f patch/m1qn3.f.patch -patch src/blas/ddot.f patch/ddot.f.patch - -# Compile and install -if which ifort 2>/dev/null; then - export FC="ifort" - export FFLAGS="-traceback -check all" # -O2 is default -else - export FC="gfortran" - if [ `uname` == "Darwin" ]; then - FFLAGS="-arch $(uname -m)" - else - FFLAGS="" - fi - - export FFLAGS -fi - -cd src/src -cp ../../configs/makefile . -cp ../../configs/linux/configure.make . -export LIBNAME="m1qn3" -make static -cp lib${LIBNAME}.* ${PREFIX} - -cd ../blas -cp ../../configs/makefile . -cp ../../configs/linux/configure.make . -export LIBNAME="ddot" -make static -cp lib${LIBNAME}.* ${PREFIX} diff --git a/externalpackages/m1qn3/install-linux.sh b/externalpackages/m1qn3/install-linux.sh deleted file mode 100755 index 0736691af..000000000 --- a/externalpackages/m1qn3/install-linux.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash -set -eu - -## Constants -# -VER=3.3 - -PREFIX="${ISSM_DIR}/externalpackages/m1qn3/install" # Set to location where external package should be installed - -# Cleanup -rm -rf ${PREFIX} src -mkdir -p ${PREFIX} src - -# Download source -$ISSM_DIR/scripts/DownloadExternalPackage.sh "https://github.com/ISSMteam/ExternalPackages/raw/refs/heads/main/m1qn3-${VER}-distrib.tgz" "m1qn3-${VER}-distrib.tgz" - -# Unpack source -tar -xzf m1qn3-${VER}-distrib.tgz - -# Move source to 'src' directory -mv m1qn3-${VER}-distrib/* src -rm -rf m1qn3-${VER}-distrib - -# Apply patches to src -patch src/src/m1qn3.f patch/m1qn3.f.patch -patch src/blas/ddot.f patch/ddot.f.patch - -# Compile and install -if which mpifort 2>/dev/null; then - export FC="mpifort" -else - if which ifort 2>/dev/null; then - export FC="ifort" - else - export FC="gfortran" - fi -fi -export FFLAGS="-fPIC" # -O2 is default - -cd src/src -cp ../../configs/makefile . -cp ../../configs/linux/configure.make . -export LIBNAME="m1qn3" -make shared -cp lib${LIBNAME}.* ${PREFIX} - -cd ../blas -cp ../../configs/makefile . -cp ../../configs/linux/configure.make . -export LIBNAME="ddot" -make shared -cp lib${LIBNAME}.* ${PREFIX} diff --git a/externalpackages/m1qn3/install-mac-static.sh b/externalpackages/m1qn3/install-mac-static.sh deleted file mode 100755 index ff30d3a0a..000000000 --- a/externalpackages/m1qn3/install-mac-static.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash -set -eu - -## Constants -# -VER=3.3 - -PREFIX="${ISSM_DIR}/externalpackages/m1qn3/install" # Set to location where external package should be installed - -# Cleanup -rm -rf ${PREFIX} src -mkdir -p ${PREFIX} src - -# Download source -$ISSM_DIR/scripts/DownloadExternalPackage.sh "https://github.com/ISSMteam/ExternalPackages/raw/refs/heads/main/m1qn3-${VER}-distrib.tgz" "m1qn3-${VER}-distrib.tgz" - -# Unpack source -tar -xzf m1qn3-${VER}-distrib.tgz - -# Move source to 'src' directory -mv m1qn3-${VER}-distrib/* src -rm -rf m1qn3-${VER}-distrib - -# Apply patches to src -patch src/src/m1qn3.f patch/m1qn3.f.patch -patch src/blas/ddot.f patch/ddot.f.patch - -# Compile and install -if which ifort 2>/dev/null; then - export FC="ifort" - export FFLAGS="-traceback -check all" # -O2 is default -else - export FC="gfortran" - if [ `uname` == "Darwin" ]; then - FFLAGS="-arch $(uname -m)" - else - FFLAGS="" - fi - - export FFLAGS -fi - -cd src/src -cp ../../configs/makefile . -cp ../../configs/mac/configure.make . -export LIBNAME="m1qn3" -make static -cp lib${LIBNAME}.* ${PREFIX} - -cd ../blas -cp ../../configs/makefile . -cp ../../configs/mac/configure.make . -export LIBNAME="ddot" -make static -cp lib${LIBNAME}.* ${PREFIX} diff --git a/externalpackages/m1qn3/install-mac.sh b/externalpackages/m1qn3/install-mac.sh deleted file mode 100755 index 32cf7e226..000000000 --- a/externalpackages/m1qn3/install-mac.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -set -eu - - -## Constants -# -VER=3.3 - -PREFIX="${ISSM_DIR}/externalpackages/m1qn3/install" # Set to location where external package should be installed - -# Cleanup -rm -rf ${PREFIX} src -mkdir -p ${PREFIX} src - -# Download source -$ISSM_DIR/scripts/DownloadExternalPackage.sh "https://github.com/ISSMteam/ExternalPackages/raw/refs/heads/main/m1qn3-${VER}-distrib.tgz" "m1qn3-${VER}-distrib.tgz" - -# Unpack source -tar -xzf m1qn3-${VER}-distrib.tgz - -# Move source to 'src' directory -mv m1qn3-${VER}-distrib/* src -rm -rf m1qn3-${VER}-distrib - -# Apply patches to src -patch src/src/m1qn3.f patch/m1qn3.f.patch -patch src/blas/ddot.f patch/ddot.f.patch - -# Compile and install -if which ifort 2>/dev/null; then - export FC="ifort" - export FFLAGS="-traceback -check all" # -O2 is default -else - export FC="gfortran" - if [ `uname` == "Darwin" ]; then - FFLAGS="-arch $(uname -m)" - else - FFLAGS="" - fi - - export FFLAGS -fi - -cd src/src -cp ../../configs/makefile . -cp ../../configs/mac/configure.make . -export LIBNAME="m1qn3" -make shared -cp lib${LIBNAME}.* ${PREFIX} - -cd ../blas -cp ../../configs/makefile . -cp ../../configs/mac/configure.make . -export LIBNAME="ddot" -make shared -cp lib${LIBNAME}.* ${PREFIX} diff --git a/externalpackages/m1qn3/install-win-msys2-mingw-static.sh b/externalpackages/m1qn3/install-win-msys2-mingw-static.sh deleted file mode 100755 index e9a564f13..000000000 --- a/externalpackages/m1qn3/install-win-msys2-mingw-static.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash -set -eu - -## Constants -# -VER=3.3 - -PREFIX="${ISSM_DIR}/externalpackages/m1qn3/install" # Set to location where external package should be installed - -# Cleanup -rm -rf ${PREFIX} src -mkdir -p ${PREFIX} src - -# Download source -$ISSM_DIR/scripts/DownloadExternalPackage.sh "https://github.com/ISSMteam/ExternalPackages/raw/refs/heads/main/m1qn3-${VER}-distrib.tgz" "m1qn3-${VER}-distrib.tgz" - -# Unpack source -tar -xzf m1qn3-${VER}-distrib.tgz - -# Move source to 'src' directory -mv m1qn3-${VER}-distrib/* src -rm -rf m1qn3-${VER}-distrib - -# Apply patches to src -patch src/src/m1qn3.f patch/m1qn3.f.patch -patch src/blas/ddot.f patch/ddot.f.patch - -# Compile and install -if which ifort 2>/dev/null; then - export FC="ifort" - export FFLAGS="-traceback -check all" # -O2 is default -else - export FC="gfortran" - if [ `uname` == "Darwin" ]; then - FFLAGS="-arch $(uname -m)" - else - FFLAGS="" - fi - - export FFLAGS -fi - -cd src/src -cp ../../configs/makefile . -cp ../../configs/win/msys2/mingw64/configure.make . -export LIBNAME="m1qn3" -make static -cp lib${LIBNAME}.* ${PREFIX} - -cd ../blas -cp ../../configs/makefile . -cp ../../configs/win/msys2/mingw64/configure.make . -export LIBNAME="ddot" -make static -cp lib${LIBNAME}.* ${PREFIX} diff --git a/externalpackages/m1qn3/install-win-msys2-mingw.sh b/externalpackages/m1qn3/install-win-msys2-mingw.sh deleted file mode 100755 index 3a0676f41..000000000 --- a/externalpackages/m1qn3/install-win-msys2-mingw.sh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/bash -set -eu - -## Constants -# -VER=3.3 - -PREFIX="${ISSM_DIR}/externalpackages/m1qn3/install" # Set to location where external package should be installed - -# Cleanup -rm -rf ${PREFIX} src -mkdir -p ${PREFIX} src - -# Download source -$ISSM_DIR/scripts/DownloadExternalPackage.sh "https://github.com/ISSMteam/ExternalPackages/raw/refs/heads/main/m1qn3-${VER}-distrib.tgz" "m1qn3-${VER}-distrib.tgz" - -# Unpack source -tar -xzf m1qn3-${VER}-distrib.tgz - -# Move source to 'src' directory -mv m1qn3-${VER}-distrib/* src -rm -rf m1qn3-${VER}-distrib - -# Apply patches to src -patch src/src/m1qn3.f patch/m1qn3.f.patch -patch src/blas/ddot.f patch/ddot.f.patch - -# Compile and install -if which ifort 2>/dev/null; then - export FC="ifort" - export FFLAGS="-traceback -check all" # -O2 is default -else - export FC="gfortran" - if [ `uname` == "Darwin" ]; then - FFLAGS="-arch $(uname -m)" - else - FFLAGS="" - fi - - export FFLAGS -fi - -cd src/src -cp ../../configs/makefile . -cp ../../configs/win/msys2/mingw64/configure.make . -export LIBNAME="m1qn3" -make shared -cp lib${LIBNAME}.* ${PREFIX} - -cd ../blas -cp ../../configs/makefile . -cp ../../configs/win/msys2/mingw64/configure.make . -export LIBNAME="ddot" -make shared -cp lib${LIBNAME}.* ${PREFIX} diff --git a/externalpackages/m1qn3/patch/ddot.f.patch b/externalpackages/m1qn3/patch/ddot.f.patch deleted file mode 100644 index 4dcb84088..000000000 --- a/externalpackages/m1qn3/patch/ddot.f.patch +++ /dev/null @@ -1,8 +0,0 @@ ---- src/blas/ddot.f 2009-10-20 06:39:35.000000000 -0400 -+++ ddot.f 2024-05-28 16:21:01.271069359 -0400 -@@ -1,4 +1,4 @@ -- double precision function ddot(n,dx,incx,dy,incy) -+ double precision function ddot_m1qn3(n,dx,incx,dy,incy) - c - c forms the dot product of two vectors. - c uses unrolled loops for increments equal to one. diff --git a/externalpackages/m1qn3/patch/m1qn3.f.patch b/externalpackages/m1qn3/patch/m1qn3.f.patch deleted file mode 100644 index 172b9ca3b..000000000 --- a/externalpackages/m1qn3/patch/m1qn3.f.patch +++ /dev/null @@ -1,76 +0,0 @@ ---- src/src/m1qn3.f 2009-10-20 03:39:35 -+++ m1qn3.f 2024-05-29 11:49:22 -@@ -124,7 +124,7 @@ - c - c --- function - c -- double precision ddot,dnrmi -+ double precision ddot_m1qn3,dnrmi - c - c --- stop if reverse < 0 (m1qn3 should not be called with reverse < 0) - c -@@ -373,7 +373,7 @@ - & /5x,"number of simulations: ",i13 - & /5x,"realized relative precision on g: ",1pd9.2) - if (normtype.eq.'two') then -- gnorm = sqrt(ddot(n,g,1,g,1)) -+ gnorm = sqrt(ddot_m1qn3(n,g,1,g,1)) - elseif (normtype.eq.'sup') then - gnorm = dnrmi(n,g) - elseif (normtype.eq.'dfn') then -@@ -432,7 +432,7 @@ - c - c function - c -- double precision ddot,dnrmi -+ double precision ddot_m1qn3,dnrmi - c - c --- possible jumps - c 9998: call of the simulator in m1qn3a with indic = 1 -@@ -462,7 +462,7 @@ - call prosca (n,g,g,ps,izs,rzs,dzs) - gnorm = dsqrt(ps) - if (normtype.eq.'two') then -- gnorms = sqrt(ddot(n,g,1,g,1)) -+ gnorms = sqrt(ddot_m1qn3(n,g,1,g,1)) - elseif (normtype.eq.'sup') then - gnorms = dnrmi(n,g) - elseif (normtype.eq.'dfn') then -@@ -789,7 +789,7 @@ - c - call prosca(n,g,g,ps,izs,rzs,dzs) - if (normtype.eq.'two') then -- gnorm = sqrt(ddot(n,g,1,g,1)) -+ gnorm = sqrt(ddot_m1qn3(n,g,1,g,1)) - elseif (normtype.eq.'sup') then - gnorm = dnrmi(n,g) - elseif (normtype.eq.'dfn') then -@@ -802,7 +802,7 @@ - & " iter simul stepsize f |g|", - & " |g|/|g0|" - write(io, -- & '(1x,i5,2x,i5,2x,1pd8.2,2x,d21.14,2x,d11.5,2x,d10.4)') -+ & '(1x,i5,2x,i5,2x,1pd9.2,2x,d21.14,2x,d12.5,2x,d11.4)') - & niter, isim, t, f, gnorm, eps1 - endif - if (impres.ge.5) write (io,940) eps1 -@@ -1355,7 +1355,8 @@ - if (tg.eq.0.d0) go to 940 - fn=fg - do 930 i=1,n -- 930 xn(i)=xn(i)+tg*d(i) -+ xn(i)=xn(i)+tg*d(i) -+ 930 end do - 940 if (imp.le.3) go to 999 - write (io,1001) - write (io,1005) tg,fg,fpg -@@ -1366,7 +1367,8 @@ - c recopiage de x et boucle - c - 950 do 960 i=1,n -- 960 x(i)=xn(i)+t*d(i) -+ x(i)=xn(i)+t*d(i) -+ 960 end do - go to 100 - c --- linesearch finished, no skip at next entry in mlis3 - 999 if (reverse.ne.0) reentry = 0 diff --git a/externalpackages/petsc/install-3.22-gadi-gpu.sh b/externalpackages/petsc/install-3.22-gadi-gpu.sh new file mode 100644 index 000000000..8bbf28b68 --- /dev/null +++ b/externalpackages/petsc/install-3.22-gadi-gpu.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# PETSc 3.22 with CUDA support for NCI Gadi GPU nodes (V100 / A100). +# +# Before running, load the CUDA module and set ISSM_DIR, e.g.: +# module load cuda/12.3.2 +# export ISSM_DIR=/g/data1b/au88/jh7060/ISSM +# bash install-3.22-gadi-gpu.sh +# +# The GPU-enabled PETSc is installed to a separate prefix so it can +# coexist with the CPU-only install. +set -eu + +## Constants +VER="3.22.3" + +PETSC_DIR="${ISSM_DIR}/externalpackages/petsc/src-gpu" # DO NOT CHANGE THIS +PREFIX="${ISSM_DIR}/externalpackages/petsc/install-gpu" # separate from CPU install + +# Require CUDA_HOME / CUDA_ROOT to be set by the module system +CUDA_DIR="${CUDA_HOME:-${CUDA_ROOT:-/usr/local/cuda}}" +if [ ! -d "${CUDA_DIR}" ]; then + echo "ERROR: CUDA directory not found at ${CUDA_DIR}." + echo " Load the CUDA module first: module load cuda/12.3.2" + exit 1 +fi + +# Environment +if [ -z ${LDFLAGS+x} ]; then + LDFLAGS="" +fi + +# Download source +${ISSM_DIR}/scripts/DownloadExternalPackage.sh \ + "https://web.cels.anl.gov/projects/petsc/download/release-snapshots/petsc-${VER}.tar.gz" \ + "petsc-${VER}.tar.gz" + +# Unpack source +tar -zxvf petsc-${VER}.tar.gz + +# Cleanup +rm -rf ${PREFIX} ${PETSC_DIR} +mkdir -p ${PETSC_DIR} + +# Move source to $PETSC_DIR +mv petsc-${VER}/* ${PETSC_DIR} +rm -rf petsc-${VER} + +# Configure +cd ${PETSC_DIR} +./configure \ + --prefix="${PREFIX}" \ + --PETSC_DIR="${PETSC_DIR}" \ + --LDFLAGS="${LDFLAGS}" \ + --with-debugging=0 \ + --with-valgrind=0 \ + --with-x=0 \ + --with-ssl=0 \ + --with-pic=1 \ + --download-fblaslapack=1 \ + --download-metis=1 \ + --download-mpich=1 \ + --download-mumps=1 \ + --download-parmetis=1 \ + --download-scalapack=1 \ + --download-zlib=1 \ + --with-cuda=1 \ + --with-cuda-dir="${CUDA_DIR}" \ + --with-cudac="${CUDA_DIR}/bin/nvcc" + +# Compile and install +make +make install diff --git a/externalpackages/petsc/install-3.25-mac.sh b/externalpackages/petsc/install-3.25-mac.sh new file mode 100755 index 000000000..08c9439c8 --- /dev/null +++ b/externalpackages/petsc/install-3.25-mac.sh @@ -0,0 +1,44 @@ +#!/bin/bash +set -eu + +## Constants +# +VER="3.25.1" + +PETSC_DIR="${ISSM_DIR}/externalpackages/petsc/src" # DO NOT CHANGE THIS +PREFIX="${ISSM_DIR}/externalpackages/petsc/install" # Set to location where external package should be installed + +# Download source +${ISSM_DIR}/scripts/DownloadExternalPackage.sh "https://web.cels.anl.gov/projects/petsc/download/release-snapshots/petsc-${VER}.tar.gz" "petsc-${VER}.tar.gz" + +# Unpack source +tar -zxvf petsc-${VER}.tar.gz + +# Cleanup +rm -rf ${PREFIX} ${PETSC_DIR} +mkdir -p ${PETSC_DIR} + +# Move source to $PETSC_DIR +mv petsc-${VER}/* ${PETSC_DIR} +rm -rf petsc-${VER} + +# Configure +cd ${PETSC_DIR} +./configure \ + --prefix="${PREFIX}" \ + --PETSC_DIR="${PETSC_DIR}" \ + --with-debugging=1 \ + --with-valgrind=0 \ + --with-x=0 \ + --with-ssl=0 \ + --with-pic=1 \ + --download-metis=1 \ + --download-mpich=1 \ + --download-mumps=1 \ + --download-parmetis=1 \ + --download-scalapack=1 \ + --download-zlib=1 + +# Compile and install +make +make install diff --git a/jenkins/aws-amazon_linux-solid_earth b/jenkins/aws-amazon_linux-solid_earth index 13597706d..0e81141d0 100755 --- a/jenkins/aws-amazon_linux-solid_earth +++ b/jenkins/aws-amazon_linux-solid_earth @@ -26,7 +26,6 @@ ISSM_CONFIG='\ --with-boost-dir=${ISSM_DIR}/externalpackages/boost/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -46,8 +45,6 @@ EXTERNALPACKAGES=" gmt install-6-linux.sh gmsh install-4-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/aws-ubuntu-tljh b/jenkins/aws-ubuntu-tljh new file mode 100644 index 000000000..9d090ddb1 --- /dev/null +++ b/jenkins/aws-ubuntu-tljh @@ -0,0 +1,80 @@ +# NOTE: This configuration adds solid earth and Dakota capabilities to the +# basic build. + +MATLAB_PATH="/usr/local/MATLAB/R2025a" + +#--------------------# +# ISSM Configuration # +#--------------------# + +ISSM_CONFIG='\ + --prefix=${ISSM_DIR} \ + --disable-static \ + --enable-debugging \ + --with-numthreads=4 \ + --with-matlab-dir=${MATLAB_PATH} \ + --with-python-version=3.9 \ + --with-python-dir=/opt/tljh/user \ + --with-python-numpy-dir="/opt/tljh/user/lib/python3.9/site-packages/numpy" \ + --with-fortran-lib="-L/usr/lib/x86_64-linux-gnu -lgfortran" \ + --with-mpi-include="${ISSM_DIR}/externalpackages/petsc/install/include" \ + --with-mpi-libflags="-L${ISSM_DIR}/externalpackages/petsc/install/lib -lmpi -lmpicxx -lmpifort" \ + --with-blas-lapack-dir="${ISSM_DIR}/externalpackages/petsc/install" \ + --with-metis-dir="${ISSM_DIR}/externalpackages/petsc/install" \ + --with-parmetis-dir="${ISSM_DIR}/externalpackages/petsc/install" \ + --with-scalapack-dir="${ISSM_DIR}/externalpackages/petsc/install" \ + --with-mumps-dir="${ISSM_DIR}/externalpackages/petsc/install" \ + --with-hdf5-dir="${ISSM_DIR}/externalpackages/hdf5/install" \ + --with-petsc-dir="${ISSM_DIR}/externalpackages/petsc/install" \ + --with-boost-dir="${ISSM_DIR}/externalpackages/boost/install" \ + --with-dakota-dir="${ISSM_DIR}/externalpackages/dakota/install" \ + --with-chaco-dir="${ISSM_DIR}/externalpackages/chaco/install" \ + --with-proj-dir="${ISSM_DIR}/externalpackages/proj/install" \ + --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ +' + +#-------------------# +# External Packages # +#-------------------# + +EXTERNALPACKAGES=" + autotools install-linux.sh + cmake install.sh + petsc install-3.23-linux.sh + boost install-1.7-linux.sh + dakota install-6.2-linux.sh + chaco install-linux.sh + curl install-7-linux.sh + hdf5 install-1.sh + netcdf install-4.sh + proj install-6.sh + gdal install-3-linux-python.sh + gshhg install.sh + gmt install-6-linux.sh + gmsh install-4-linux.sh + triangle install-linux.sh +" + +#---------# +# Testing # +#---------# + +# Test suites +MATLAB_TEST=0 +PYTHON_TEST=0 +JAVASCRIPT_TEST=0 +EXAMPLES_TEST=0 + +# Number of CPUs used in ISSM compilation +# +# NOTE: One is usually safer as some packages are very sensitive to parallel +# compilation +# +NUMCPUS_INSTALL=8 + +# Number of CPUs used in the nightly runs +NUMCPUS_RUN=1 + +# Nightly run options +MATLAB_NROPTIONS="" +PYTHON_NROPTIONS="" diff --git a/jenkins/ghub-workspace_10 b/jenkins/ghub-workspace_10 index 92006ff69..eb5e4e35a 100755 --- a/jenkins/ghub-workspace_10 +++ b/jenkins/ghub-workspace_10 @@ -32,8 +32,6 @@ ISSM_CONFIG='\ --with-chaco-dir="${ISSM_EXT_DIR}/chaco/install" \ --with-proj-dir="${ISSM_EXT_DIR}/proj/install" \ --with-triangle-dir="${ISSM_EXT_DIR}/triangle/install" \ - --with-m1qn3-dir="${ISSM_EXT_DIR}/m1qn3/install" \ - --with-semic-dir=${ISSM_EXT_DIR}/semic/install \ ' #-------------------# @@ -55,8 +53,6 @@ EXTERNALPACKAGES=" gmt install-6-linux.sh gmsh install-4-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/github-linux-basic-codeql b/jenkins/github-linux-basic-codeql index 55f99476a..cd713dda3 100755 --- a/jenkins/github-linux-basic-codeql +++ b/jenkins/github-linux-basic-codeql @@ -19,8 +19,6 @@ ISSM_CONFIG='\ --with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -32,8 +30,6 @@ EXTERNALPACKAGES=" cmake install.sh petsc install-3.23-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/github_linux_basic b/jenkins/github_linux_basic index 2f89712e7..cb03059b8 100644 --- a/jenkins/github_linux_basic +++ b/jenkins/github_linux_basic @@ -20,8 +20,6 @@ ISSM_CONFIG='\ --with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -33,8 +31,6 @@ EXTERNALPACKAGES=" cmake install.sh petsc install-3.23-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/linux64_caladan b/jenkins/linux64_caladan index a82af98a0..f77a4dae3 100755 --- a/jenkins/linux64_caladan +++ b/jenkins/linux64_caladan @@ -22,7 +22,6 @@ ISSM_CONFIG='\ --with-dakota-dir=$ISSM_DIR/externalpackages/dakota/install \ --with-boost-dir=$ISSM_DIR/externalpackages/boost/install/ \ --with-fortran-lib="-L/usr/lib/gcc/x86_64-linux-gnu/4.9/ -lgfortran" \ - --with-m1qn3-dir=$ISSM_DIR/externalpackages/m1qn3/install \ --with-numthreads=4 \ --enable-development \ --enable-debugging ' @@ -40,7 +39,6 @@ EXTERNALPACKAGES=" boost install-1.7-linux.sh dakota install-6.2-linux64.sh chaco install-linux.sh - m1qn3 install-linux.sh shell2junit install.sh " diff --git a/jenkins/mac-intel-basic b/jenkins/mac-intel-basic index a2aad63d2..0ebd5ad4b 100755 --- a/jenkins/mac-intel-basic +++ b/jenkins/mac-intel-basic @@ -21,8 +21,6 @@ ISSM_CONFIG='\ --with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -34,8 +32,6 @@ EXTERNALPACKAGES=" cmake install.sh petsc install-3.23-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-intel-binaries-matlab b/jenkins/mac-intel-binaries-matlab index 33cfc78c6..373d425c2 100755 --- a/jenkins/mac-intel-binaries-matlab +++ b/jenkins/mac-intel-binaries-matlab @@ -36,8 +36,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -60,8 +58,6 @@ EXTERNALPACKAGES=" gmt install-6-mac-static.sh gmsh install-4-mac-static.sh triangle install-mac-static.sh - m1qn3 install-mac-static.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-intel-binaries-python-3 b/jenkins/mac-intel-binaries-python-3 index 6f573cbba..4596bee9e 100755 --- a/jenkins/mac-intel-binaries-python-3 +++ b/jenkins/mac-intel-binaries-python-3 @@ -36,8 +36,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -60,8 +58,6 @@ EXTERNALPACKAGES=" gmt install-6-mac-static.sh gmsh install-4-mac-static.sh triangle install-mac-static.sh - m1qn3 install-mac-static.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-intel-dakota b/jenkins/mac-intel-dakota index 9bac5d5c5..35e731e0b 100755 --- a/jenkins/mac-intel-dakota +++ b/jenkins/mac-intel-dakota @@ -32,8 +32,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -56,8 +54,6 @@ EXTERNALPACKAGES=" gmt install-6-mac.sh gmsh install-4-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-intel-examples b/jenkins/mac-intel-examples index 05338c9de..9e37db636 100755 --- a/jenkins/mac-intel-examples +++ b/jenkins/mac-intel-examples @@ -34,8 +34,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -58,8 +56,6 @@ EXTERNALPACKAGES=" gmt install-6-mac.sh gmsh install-4-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-intel-full b/jenkins/mac-intel-full index eb189e70c..b799e417d 100755 --- a/jenkins/mac-intel-full +++ b/jenkins/mac-intel-full @@ -36,8 +36,6 @@ ISSM_CONFIG='\ --with-chaco-dir="${ISSM_DIR}/externalpackages/chaco/install" \ --with-proj-dir="${ISSM_DIR}/externalpackages/proj/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ - --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" \ ' #-------------------# @@ -60,8 +58,6 @@ EXTERNALPACKAGES=" gmt install-6-mac.sh gmsh install-4-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-intel-solid_earth b/jenkins/mac-intel-solid_earth index ed61cbe70..94f36b47e 100755 --- a/jenkins/mac-intel-solid_earth +++ b/jenkins/mac-intel-solid_earth @@ -35,8 +35,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -60,8 +58,6 @@ EXTERNALPACKAGES=" gmt install-6-mac.sh gmsh install-4-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-silicon-basic b/jenkins/mac-silicon-basic index fa98b033d..778c42d55 100755 --- a/jenkins/mac-silicon-basic +++ b/jenkins/mac-silicon-basic @@ -21,8 +21,6 @@ ISSM_CONFIG='\ --with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -34,8 +32,6 @@ EXTERNALPACKAGES=" cmake install.sh petsc install-3.23-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " @@ -64,9 +60,8 @@ NUMCPUS_RUN=2 # See documentation in test/NightlyRun/runme.* for more information # # NOTE: -# - Tests 124, 703 are excluded because of an outright crash # - Tests 216, 274, 362, 430, 435, 441:442, 456, 470:476, 517 are excluded because of large errors -# - Tests 119, 423, 433, 448, 462:464, 508, 544, 546, 550, 808 are excluded because of failure "Arrays have incompatible sizes for this operation." +# - Tests 423, 433, 448, 462:464, 508, 544, 546, 550, 808 are excluded because of failure "Arrays have incompatible sizes for this operation." # -MATLAB_NROPTIONS="'exclude',[IdFromString('Dakota'),119,124,216,274,362,423,430,433,435,441:442,448,456,462:464,470:476,508,517,544,546,550,703,808]" +MATLAB_NROPTIONS="'exclude',[IdFromString('Dakota'),216,274,362,423,430,433,435,441:442,448,456,462:464,470:476,508,517,544,546,550,808]" PYTHON_NROPTIONS="" diff --git a/jenkins/mac-silicon-binaries-matlab b/jenkins/mac-silicon-binaries-matlab index 65787a9dd..adab3dbc8 100755 --- a/jenkins/mac-silicon-binaries-matlab +++ b/jenkins/mac-silicon-binaries-matlab @@ -36,8 +36,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -60,8 +58,6 @@ EXTERNALPACKAGES=" gmt install-6-mac-static.sh gmsh install-4-mac-static.sh triangle install-mac-static.sh - m1qn3 install-mac-static.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-silicon-binaries-python-3 b/jenkins/mac-silicon-binaries-python-3 index 26bde6e0d..74c67ee91 100755 --- a/jenkins/mac-silicon-binaries-python-3 +++ b/jenkins/mac-silicon-binaries-python-3 @@ -35,8 +35,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -59,8 +57,6 @@ EXTERNALPACKAGES=" gmt install-6-mac-static.sh gmsh install-4-mac-static.sh triangle install-mac-static.sh - m1qn3 install-mac-static.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-silicon-dakota b/jenkins/mac-silicon-dakota index 686157be3..5e17ccdf4 100755 --- a/jenkins/mac-silicon-dakota +++ b/jenkins/mac-silicon-dakota @@ -27,8 +27,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -51,8 +49,6 @@ EXTERNALPACKAGES=" gmt install-6-mac.sh gmsh install-4-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-silicon-examples b/jenkins/mac-silicon-examples index 6498f0314..6197effe3 100755 --- a/jenkins/mac-silicon-examples +++ b/jenkins/mac-silicon-examples @@ -26,8 +26,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -50,8 +48,6 @@ EXTERNALPACKAGES=" gmt install-6-mac.sh gmsh install-4-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-silicon-full b/jenkins/mac-silicon-full index 27ade7c4c..634e6dcd1 100755 --- a/jenkins/mac-silicon-full +++ b/jenkins/mac-silicon-full @@ -27,8 +27,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -51,8 +49,6 @@ EXTERNALPACKAGES=" gmt install-6-mac.sh gmsh install-4-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/mac-silicon-python b/jenkins/mac-silicon-python index 5ccd76565..68a479e42 100755 --- a/jenkins/mac-silicon-python +++ b/jenkins/mac-silicon-python @@ -19,8 +19,6 @@ ISSM_CONFIG='\ --with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -32,8 +30,6 @@ EXTERNALPACKAGES=" cmake install.sh petsc install-3.23-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " @@ -62,10 +58,8 @@ NUMCPUS_RUN=2 # See documentation in test/NightlyRun/runme.* for more information # NOTE: -# - Tests 124, 703 are excluded because of an outright crash # - Tests 216, 274, 362, 430, 435, 441:442 517 are excluded because of large errors -# - Tests 119, 423, 433, 448, 462:464, 508, 544, 546, 702, 808 are excluded because of failure "Arrays have incompatible sizes for this operation." +# - Tests 423, 433, 448, 462:464, 508, 544, 546, 702, 703, 808 are excluded because of failure "Arrays have incompatible sizes for this operation." # MATLAB_NROPTIONS="" -PYTHON_NROPTIONS="--exclude Dakota 119 124 216 274 362 423 430 433 435 441:442 448 462:464 508 517 544 546 702:703 808" - +PYTHON_NROPTIONS="--exclude Dakota 216 274 362 423 430 433 435 441:442 448 462:464 508 517 544 546 702 703 808" diff --git a/jenkins/mac-silicon-solid_earth b/jenkins/mac-silicon-solid_earth index 81a415a47..d21b5ada2 100755 --- a/jenkins/mac-silicon-solid_earth +++ b/jenkins/mac-silicon-solid_earth @@ -27,8 +27,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -51,8 +49,6 @@ EXTERNALPACKAGES=" gmt install-6-mac.sh gmsh install-4-mac.sh triangle install-mac.sh - m1qn3 install-mac.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/pleiades-basic b/jenkins/pleiades-basic index 45c7202e0..d31561388 100755 --- a/jenkins/pleiades-basic +++ b/jenkins/pleiades-basic @@ -25,8 +25,6 @@ ISSM_CONFIG='\ --with-mumps-dir="${PETSC_DIR}" \ --with-petsc-dir="${PETSC_DIR}" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ - --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" \ ' #-------------------# @@ -36,8 +34,6 @@ ISSM_CONFIG='\ EXTERNALPACKAGES=" autotools install-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh " #---------# diff --git a/jenkins/pleiades-dakota b/jenkins/pleiades-dakota index c1fc973a0..bd1d7b6cc 100755 --- a/jenkins/pleiades-dakota +++ b/jenkins/pleiades-dakota @@ -28,8 +28,6 @@ ISSM_CONFIG='\ --with-dakota-dir="${ISSM_DIR}/externalpackages/dakota/install" \ --with-chaco-dir="${ISSM_DIR}/externalpackages/chaco/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ - --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" \ ' #-------------------# @@ -41,9 +39,7 @@ EXTERNALPACKAGES=" boost install-1.7-linux.sh dakota install-6.2-pleiades.sh chaco install-linux.sh - triangle install-linux.shwhic - m1qn3 install-linux.sh - semic install.sh + triangle install-linux.sh " #---------# diff --git a/jenkins/pleiades-solid_earth b/jenkins/pleiades-solid_earth index f7e66d9e8..805c7a711 100755 --- a/jenkins/pleiades-solid_earth +++ b/jenkins/pleiades-solid_earth @@ -30,8 +30,6 @@ ISSM_CONFIG='\ --with-chaco-dir="${ISSM_DIR}/externalpackages/chaco/install" \ --with-proj-dir="${ISSM_DIR}/externalpackages/proj/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ - --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" \ ' #-------------------# @@ -53,8 +51,6 @@ EXTERNALPACKAGES=" gmt install-6-pleiades.sh gmsh install-4-pleiades.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh " #---------# diff --git a/jenkins/ross-debian_linux-adolc-ampioff b/jenkins/ross-debian_linux-adolc-ampioff index 139cd24cf..5c9eb8a20 100755 --- a/jenkins/ross-debian_linux-adolc-ampioff +++ b/jenkins/ross-debian_linux-adolc-ampioff @@ -29,7 +29,6 @@ ISSM_CONFIG='\ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ --with-gsl-dir=${ISSM_DIR}/externalpackages/gsl/install \ --with-adolc-dir=${ISSM_DIR}/externalpackages/adolc/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -47,7 +46,6 @@ EXTERNALPACKAGES=" gsl install.sh triangle install-linux.sh adolc install.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-adolc-ampion b/jenkins/ross-debian_linux-adolc-ampion index b484642b3..3453b1596 100755 --- a/jenkins/ross-debian_linux-adolc-ampion +++ b/jenkins/ross-debian_linux-adolc-ampion @@ -29,7 +29,6 @@ ISSM_CONFIG='\ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ --with-gsl-dir=${ISSM_DIR}/externalpackages/gsl/install \ --with-adolc-dir=${ISSM_DIR}/externalpackages/adolc/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -48,7 +47,6 @@ EXTERNALPACKAGES=" triangle install-linux.sh adjoinablempi install-linux.sh adolc install-with_ampi.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-basic b/jenkins/ross-debian_linux-basic index 3b55f6e78..84ad12301 100755 --- a/jenkins/ross-debian_linux-basic +++ b/jenkins/ross-debian_linux-basic @@ -21,8 +21,6 @@ ISSM_CONFIG='\ --with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -34,8 +32,6 @@ EXTERNALPACKAGES=" cmake install.sh petsc install-3.23-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-binaries-matlab b/jenkins/ross-debian_linux-binaries-matlab index 073af6800..2948822c9 100755 --- a/jenkins/ross-debian_linux-binaries-matlab +++ b/jenkins/ross-debian_linux-binaries-matlab @@ -34,8 +34,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# # External Packages # @@ -57,8 +55,6 @@ EXTERNALPACKAGES=" gmt install-6-linux-static.sh gmsh install-4-linux-static.sh triangle install-linux-static.sh - m1qn3 install-linux-static.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-binaries-python-3 b/jenkins/ross-debian_linux-binaries-python-3 index e56127bf7..e9c26ad03 100755 --- a/jenkins/ross-debian_linux-binaries-python-3 +++ b/jenkins/ross-debian_linux-binaries-python-3 @@ -32,8 +32,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# # External Packages # @@ -55,8 +53,6 @@ EXTERNALPACKAGES=" gmt install-6-linux-static.sh gmsh install-4-linux-static.sh triangle install-linux-static.sh - m1qn3 install-linux-static.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-codipack b/jenkins/ross-debian_linux-codipack index d17890f35..3e8cbfc5e 100755 --- a/jenkins/ross-debian_linux-codipack +++ b/jenkins/ross-debian_linux-codipack @@ -25,10 +25,8 @@ ISSM_CONFIG='\ --with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-gsl-dir=${ISSM_DIR}/externalpackages/gsl/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ --with-medipack-dir="${ISSM_DIR}/externalpackages/medipack/install" \ --with-codipack-dir="${ISSM_DIR}/externalpackages/codipack/install" \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -41,10 +39,8 @@ EXTERNALPACKAGES=" petsc install-3.23-linux.sh gsl install.sh triangle install-linux.sh - m1qn3 install-linux.sh medipack install.sh codipack install.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-dakota b/jenkins/ross-debian_linux-dakota index 2f0a6121d..20108cc33 100755 --- a/jenkins/ross-debian_linux-dakota +++ b/jenkins/ross-debian_linux-dakota @@ -28,8 +28,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -52,8 +50,6 @@ EXTERNALPACKAGES=" gmt install-6-linux.sh gmsh install-4-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-full b/jenkins/ross-debian_linux-full index 74d2d3932..2c716d29c 100755 --- a/jenkins/ross-debian_linux-full +++ b/jenkins/ross-debian_linux-full @@ -30,8 +30,6 @@ ISSM_CONFIG='\ --with-chaco-dir="${ISSM_DIR}/externalpackages/chaco/install" \ --with-proj-dir="${ISSM_DIR}/externalpackages/proj/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -54,8 +52,6 @@ EXTERNALPACKAGES=" gmt install-6-linux.sh gmsh install-4-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-full-mplapack b/jenkins/ross-debian_linux-full-mplapack index f7be08e92..e2960b213 100755 --- a/jenkins/ross-debian_linux-full-mplapack +++ b/jenkins/ross-debian_linux-full-mplapack @@ -28,8 +28,6 @@ ISSM_CONFIG='\ --with-chaco-dir="${ISSM_DIR}/externalpackages/chaco/install" \ --with-proj-dir="${ISSM_DIR}/externalpackages/proj/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -53,8 +51,6 @@ EXTERNALPACKAGES=" gmt install-6-linux.sh gmsh install-4-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-full-valgrind b/jenkins/ross-debian_linux-full-valgrind index 724a44a8b..257307cfb 100755 --- a/jenkins/ross-debian_linux-full-valgrind +++ b/jenkins/ross-debian_linux-full-valgrind @@ -30,8 +30,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -54,8 +52,6 @@ EXTERNALPACKAGES=" gmt install-6-linux.sh gmsh install-4-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh valgrind install-linux.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-iceocean b/jenkins/ross-debian_linux-iceocean index af74ac665..601ef0271 100755 --- a/jenkins/ross-debian_linux-iceocean +++ b/jenkins/ross-debian_linux-iceocean @@ -22,8 +22,6 @@ ISSM_CONFIG='\ --with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -35,8 +33,6 @@ EXTERNALPACKAGES=" cmake install.sh petsc install-3.23-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-python b/jenkins/ross-debian_linux-python index 76f3efaf6..b13501edd 100755 --- a/jenkins/ross-debian_linux-python +++ b/jenkins/ross-debian_linux-python @@ -19,8 +19,6 @@ ISSM_CONFIG='\ --with-mumps-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-petsc-dir=${ISSM_DIR}/externalpackages/petsc/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -32,8 +30,6 @@ EXTERNALPACKAGES=" cmake install.sh petsc install-3.23-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-debian_linux-solid_earth b/jenkins/ross-debian_linux-solid_earth index cec1eaff2..0131a68a2 100755 --- a/jenkins/ross-debian_linux-solid_earth +++ b/jenkins/ross-debian_linux-solid_earth @@ -27,8 +27,6 @@ ISSM_CONFIG='\ --with-chaco-dir=${ISSM_DIR}/externalpackages/chaco/install \ --with-proj-dir=${ISSM_DIR}/externalpackages/proj/install \ --with-triangle-dir=${ISSM_DIR}/externalpackages/triangle/install \ - --with-m1qn3-dir=${ISSM_DIR}/externalpackages/m1qn3/install \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -51,8 +49,6 @@ EXTERNALPACKAGES=" gmt install-6-linux.sh gmsh install-4-linux.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ross-win-msys2-mingw-msmpi-basic b/jenkins/ross-win-msys2-mingw-msmpi-basic index b6e472eef..2826db846 100644 --- a/jenkins/ross-win-msys2-mingw-msmpi-basic +++ b/jenkins/ross-win-msys2-mingw-msmpi-basic @@ -21,8 +21,6 @@ ISSM_CONFIG='\ --with-mumps-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-petsc-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ - --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" \ ' #-------------------# @@ -33,8 +31,6 @@ EXTERNALPACKAGES=" msmpi install.sh petsc install-3.14-win-msys2-mingw-msmpi.sh triangle install-win-msys2-mingw.sh - m1qn3 install-win-msys2-mingw-static.sh - semic install.sh shell2junit install.sh " @@ -63,9 +59,8 @@ NUMCPUS_RUN=2 # See documentation in test/NightlyRun/runme.* for more information # # NOTE: -# - Tests 125, 126, and 129 are skipped because restart is not yet implemented -# for Windows (under MSYS2) -# - test701 is skipped because it uses full Stokes equations +# - Tests 125, 126, and 129 are skipped because restart is not yet implemented for Windows (under MSYS2) +# - test701:703 is skipped because it uses full Stokes equations # MATLAB_NROPTIONS="'exclude',[IdFromString('Dakota'),125,126,129,435,701,702,703]" PYTHON_NROPTIONS="" diff --git a/jenkins/ross-win-msys2-mingw-msmpi-binaries-matlab b/jenkins/ross-win-msys2-mingw-msmpi-binaries-matlab index 25d49c883..f7ccb5d50 100644 --- a/jenkins/ross-win-msys2-mingw-msmpi-binaries-matlab +++ b/jenkins/ross-win-msys2-mingw-msmpi-binaries-matlab @@ -22,8 +22,6 @@ ISSM_CONFIG='\ --with-mumps-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-petsc-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ - --with-semic-dir=${ISSM_DIR}/externalpackages/semic/install \ ' #-------------------# @@ -34,8 +32,6 @@ EXTERNALPACKAGES=" msmpi install-static.sh petsc install-3.14-win-msys2-mingw-msmpi-static.sh triangle install-win-msys2-mingw-static.sh - m1qn3 install-win-msys2-mingw-static.sh - semic install.sh shell2junit install.sh " diff --git a/jenkins/ub-ccr b/jenkins/ub-ccr index 81fd45a6d..f4e3332aa 100644 --- a/jenkins/ub-ccr +++ b/jenkins/ub-ccr @@ -21,8 +21,6 @@ ISSM_CONFIG='\ --with-petsc-dir="${ISSM_DIR}/externalpackages/petsc/install" \ --with-proj-dir="${ISSM_DIR}/externalpackages/proj/install" \ --with-triangle-dir="${ISSM_DIR}/externalpackages/triangle/install" \ - --with-m1qn3-dir="${ISSM_DIR}/externalpackages/m1qn3/install" \ - --with-semic-dir="${ISSM_DIR}/externalpackages/semic/install" \ ' #-------------------# @@ -36,8 +34,6 @@ EXTERNALPACKAGES=" proj install-6.sh gdal install-3-linux-python.sh triangle install-linux.sh - m1qn3 install-linux.sh - semic install.sh shell2junit install.sh " diff --git a/m4/issm_options.m4 b/m4/issm_options.m4 index 984c98995..7b67b3f08 100644 --- a/m4/issm_options.m4 +++ b/m4/issm_options.m4 @@ -40,9 +40,9 @@ AC_DEFUN([ISSM_OPTIONS],[ user_name="$USER" else if test -n "$LOGNAME"; then - user_name ="$LOGNAME" + user_name="$LOGNAME" else - user_name =`(whoami) 2>/dev/null` || user_name=unknown + user_name=`(whoami) 2>/dev/null` || user_name=unknown fi fi AC_DEFINE_UNQUOTED([USER_NAME], "${user_name}", [user name]) @@ -237,7 +237,7 @@ AC_DEFUN([ISSM_OPTIONS],[ export OSLIBS="-Wl,-L/c/msys64/mingw64/lib -Wl,-lstdc++ -Wl,-lmingw32 -Wl,-lgcc_s -Wl,-lmoldname -Wl,-lmingwex -Wl,-lmsvcrt -Wl,-lm -Wl,-lpthread -Wl,-lshell32 -Wl,-luser32 -Wl,-lgdi32 -Wl,-luser32 -Wl,-ladvapi32 -Wl,-lkernel32 -Wl,-lgcc" ;; *) - AC_MSG_ERROR([unsupported operating system type)]) + AC_MSG_ERROR([unsupported operating system type]) ;; esac @@ -523,7 +523,7 @@ AC_DEFUN([ISSM_OPTIONS],[ else DAKOTA_VERSION_OUTPUT=`${DAKOTA_ROOT}/bin/dakota -v` if test -n "${DAKOTA_VERSION_OUTPUT}"; then - DAKOTA_VERSION=`echo ${DAKOTA_VERSION_OUTPUT} grep "Dakota version" | sed 's/Dakota version //' | sed 's/ .*//'` + DAKOTA_VERSION=`echo ${DAKOTA_VERSION_OUTPUT} | grep "Dakota version" | sed 's/Dakota version //' | sed 's/ .*//'` elif test -f "${DAKOTA_ROOT}/../src/src/CommandLineHandler.C"; then DAKOTA_VERSION=`cat ${DAKOTA_ROOT}/../src/src/CommandLineHandler.C | grep 'DAKOTA version' | grep 'release' | grep -v // | sed 's/.*DAKOTA version //' | sed 's/ .*//' ` elif test -f "${DAKOTA_ROOT}/../src/src/CommandLineHandler.cpp"; then @@ -608,7 +608,7 @@ AC_DEFUN([ISSM_OPTIONS],[ DAKOTAFLAGS="-DDISABLE_DAKOTA_CONFIG_H -DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DDAKOTA_PLUGIN -DBOOST_DISABLE_ASSERTS -DDAKOTA_HAVE_BOOST_FS -DHAVE_UNISTD_H -DHAVE_SYSTEM -DHAVE_WORKING_FORK -DHAVE_WORKING_VFORK -DHAVE_SYS_WAIT_H -DHAVE_USLEEP -DDAKOTA_F90 -DDAKOTA_HAVE_MPI -DHAVE_PECOS -DHAVE_SURFPACK -DDAKOTA_UTILIB -DHAVE_ADAPTIVE_SAMPLING -DHAVE_CONMIN -DDAKOTA_DDACE -DHAVE_FSUDACE -DDAKOTA_HOPS -DHAVE_NCSU -DHAVE_NL2SOL -DHAVE_OPTPP -DDAKOTA_OPTPP -DHAVE_PSUADE -DHAVE_AMPL" DAKOTALIB="-L${DAKOTA_ROOT}/lib -ldakota_src -ldream -lfsudace -lddace -lnomad -lpecos_src -llhs -llhs_mods -loptpp -lsurfpack -lconmin -ldakota_src_fortran -llhs_mod -lncsuopt -lsurfpack_fortran -lteuchos -lamplsolver -lcport -ldfftpack -lfsudace -lhopspack -lnidr -lpecos -lpsuade -lsparsegrid -L$BOOST_ROOT/lib -lboost_serialization -lboost_signals -lboost_regex -lboost_filesystem -lboost_system ${BLASLAPACKLIB}" elif test "${BOOST_VERSION_MINOR}" == "72"; then - DAKOTAFLAGS="-DHAVE_CONFIG_H -DHAVE_CONFIG_H -DDISABLE_DAKOTA_CONFIG_H -DBOOST_DISABLE_ASSERTS -DHAVE_UNISTD_H -DHAVE_SYSTEM -DHAVE_WORKING_FORK -DHAVE_WORKING_VFORK -DHAVE_SYS_WAIT_H -DHAVE_USLEEP -DDAKOTA_F90 -DDAKOTA_HAVE_MPI -DHAVE_PECOS -DHAVE_SURFPACK -DHAVE_ADAPTIVE_SAMPLING -DHAVE_ESM -DHAVE_CONMIN -DHAVE_DDACE -DHAVE_DREAM -DHAVE_FSUDACE -DDAKOTA_HOPS -DHAVE_NCSU -DHAVE_NL2SOL -DHAVE_NOMAD -DHAVE_OPTPP -DDAKOTA_OPTPP -DHAVE_PSUADE -DHAVE_AMPL" + DAKOTAFLAGS="-DHAVE_CONFIG_H -DDISABLE_DAKOTA_CONFIG_H -DBOOST_DISABLE_ASSERTS -DHAVE_UNISTD_H -DHAVE_SYSTEM -DHAVE_WORKING_FORK -DHAVE_WORKING_VFORK -DHAVE_SYS_WAIT_H -DHAVE_USLEEP -DDAKOTA_F90 -DDAKOTA_HAVE_MPI -DHAVE_PECOS -DHAVE_SURFPACK -DHAVE_ADAPTIVE_SAMPLING -DHAVE_ESM -DHAVE_CONMIN -DHAVE_DDACE -DHAVE_DREAM -DHAVE_FSUDACE -DDAKOTA_HOPS -DHAVE_NCSU -DHAVE_NL2SOL -DHAVE_NOMAD -DHAVE_OPTPP -DDAKOTA_OPTPP -DHAVE_PSUADE -DHAVE_AMPL" DAKOTALIB="-L${DAKOTA_ROOT}/lib -ldakota_src -ldakota_src_fortran -lnidr -lteuchosremainder -lteuchosnumerics -lteuchoscomm -lteuchosparameterlist -lteuchosparser -lteuchoscore -lpecos_util -lpecos_src -llhs -llhs_mods -llhs_mod -ldfftpack -lsparsegrid -lsurfpack -lsurfpack -lsurfpack_fortran -lapproxnn -lconmin -lddace -ldream -lfsudace -lhopspack -lncsuopt -lcport -lnomad -loptpp -lpsuade -lamplsolver -L${BOOST_ROOT}/lib -lboost_filesystem -lboost_program_options -lboost_regex -lboost_serialization -lboost_system ${BLASLAPACKLIB}" fi fi @@ -650,7 +650,7 @@ AC_DEFUN([ISSM_OPTIONS],[ AC_SUBST([DAKOTAFLAGS]) AC_SUBST([DAKOTALIB]) fi - AM_CONDITIONAL([ISSM_DAKOTA], [test "x${DAKOTA_MAJOR}" == "x6"]) + AM_CONDITIONAL([ISSM_DAKOTA], [test "x${HAVE_DAKOTA}" == "xyes" && test "x${DAKOTA_MAJOR}" == "x6"]) dnl }}} dnl Python{{{ AC_MSG_CHECKING([for Python]) @@ -689,7 +689,7 @@ AC_DEFUN([ISSM_OPTIONS],[ AC_MSG_CHECKING([for Python include directory]) PYTHONINCL=$(${PYTHON_PATH} -c "import sys; import sysconfig; sys.stdout.write(sysconfig.get_config_var('INCLUDEPY'))") if ! test -f "${PYTHONINCL}/Python.h"; then - PYTHONINCL=$(${PYTHON_PATH} -c "from sysconfig import get_paths as gp; print(gp()[['include']])") + PYTHONINCL=$(${PYTHON_PATH} -c "from sysconfig import get_paths as gp; print(gp().get('include'))") if ! test -f "${PYTHONINCL}/Python.h"; then AC_MSG_ERROR([Python.h not found! Please locate this file and contact ISSM developers via forum or email.]); fi @@ -704,7 +704,7 @@ AC_DEFUN([ISSM_OPTIONS],[ elif ls ${PYTHONLIBDIR}/libpython${PYTHON_VERSION}.* 1> /dev/null 2>&1; then PYTHONLIB="-L${PYTHONLIBDIR} -lpython${PYTHON_VERSION}" else - PYTHONLIBDIR=$(${PYTHON_PATH} -c "from sysconfig import get_paths as gp; print(gp()[['stdlib']])") + PYTHONLIBDIR=$(${PYTHON_PATH} -c "from sysconfig import get_paths as gp; print(gp().get('stdlib'))") if ls ${PYTHONLIBDIR}/../libpython${PYTHON_VERSION}m.* 1> /dev/null 2>&1; then PYTHONLIB="-L${PYTHONLIBDIR}/.. -lpython${PYTHON_VERSION}m" elif ls ${PYTHONLIBDIR}/../libpython${PYTHON_VERSION}.* 1> /dev/null 2>&1; then @@ -744,7 +744,7 @@ AC_DEFUN([ISSM_OPTIONS],[ AC_DEFINE([_HAVE_PYTHON_NUMPY_], [1], [with NumPy in ISSM src]) AC_SUBST([PYTHON_NUMPYINCL]) fi - AM_CONDITIONAL([PYTHON3], [test "xyes" == "xyes"]) + AM_CONDITIONAL([PYTHON3], [test "x${PYTHON_MAJOR}" == "x3"]) dnl }}} dnl Python-OLD{{{ if test "x${HAVE_PYTHON}" != "xyes"; then @@ -995,7 +995,7 @@ AC_DEFUN([ISSM_OPTIONS],[ AC_SUBST([CODIPACKINCL]) fi AM_CONDITIONAL([CODIPACK], [test "x${HAVE_CODIPACK}" == "xyes"]) - AM_COND_IF(CODIPACK, [CXXFLAGS+=" -std=c++17"]) + AM_COND_IF(CODIPACK, [CXXFLAGS="${CXXFLAGS} -std=c++17"]) dnl }}} dnl Tape Allocation {{{ AC_MSG_CHECKING(for tape allocation) @@ -1039,7 +1039,7 @@ AC_DEFUN([ISSM_OPTIONS],[ AC_SUBST([ADOLCLIB]) fi AM_CONDITIONAL([ADOLC], [test "x${HAVE_ADOLC}" == "xyes"]) - AM_COND_IF(ADOLC, [CXXFLAGS+=" -std=c++11"]) + AM_COND_IF(ADOLC, [CXXFLAGS="${CXXFLAGS} -std=c++11"]) dnl }}} dnl ADOL-C version{{{ AC_MSG_CHECKING(for ADOL-C version) @@ -1575,35 +1575,6 @@ AC_DEFUN([ISSM_OPTIONS],[ fi fi dnl }}} - dnl M1QN3{{{ - AC_MSG_CHECKING([for M1QN3]) - AC_ARG_WITH( - [m1qn3-dir], - AS_HELP_STRING([--with-m1qn3-dir=DIR], [M1QN3 root directory]), - [M1QN3_ROOT=${withval}], - [M1QN3_ROOT="no"] - ) - if test "x${M1QN3_ROOT}" == "xno"; then - HAVE_M1QN3=no - else - HAVE_M1QN3=yes - if ! test -d "${M1QN3_ROOT}"; then - AC_MSG_ERROR([M1QN3 directory provided (${M1QN3_ROOT}) does not exist!]); - fi - fi - AC_MSG_RESULT([${HAVE_M1QN3}]) - - dnl M1QN3 libraries and header files - if test "x${HAVE_M1QN3}" == "xyes"; then - if test "x${IS_MSYS2}" == "xyes"; then - M1QN3LIB="-Wl,-L${M1QN3_ROOT} -Wl,-lm1qn3 -Wl,-lddot" - else - M1QN3LIB="-L${M1QN3_ROOT} -lm1qn3 -lddot" - fi - AC_DEFINE([_HAVE_M1QN3_], [1], [with M1QN3 in ISSM src]) - AC_SUBST([M1QN3LIB]) - fi - dnl }}} dnl PROJ{{{ AC_MSG_CHECKING([for PROJ]) AC_ARG_WITH( @@ -2006,38 +1977,6 @@ AC_DEFUN([ISSM_OPTIONS],[ AC_SUBST([PROMETHEUSLIB]) fi dnl }}} - dnl SEMIC{{{ - AC_MSG_CHECKING([for SEMIC]) - AC_ARG_WITH( - [semic-dir], - AS_HELP_STRING([--with-semic-dir=DIR], [SEMIC root directory]), - [SEMIC_ROOT=${withval}], - [SEMIC_ROOT="no"] - ) - if test "x${SEMIC_ROOT}" == "xno"; then - HAVE_SEMIC=no - else - HAVE_SEMIC=yes - if ! test -d "${SEMIC_ROOT}"; then - AC_MSG_ERROR([SEMIC directory provided (${SEMIC_ROOT}) does not exist!]); - fi - fi - AC_MSG_RESULT([${HAVE_SEMIC}]) - - dnl SEMIC libraries and header files - if test "x${HAVE_SEMIC}" == "xyes"; then - SEMICINCL="-I${SEMIC_ROOT}" - if test "x${IS_MSYS2}" == "xyes"; then - SEMICLIB="-Wl,-L${SEMIC_ROOT}/lib -Wl,-lsurface_physics -Wl,-lutils" - else - SEMICLIB="-L${SEMIC_ROOT}/lib -lsurface_physics -lutils" - fi - AC_DEFINE([_HAVE_SEMIC_], [1], [with SEMIC in ISSM src]) - AC_SUBST([SEMICLIB]) - AC_SUBST([SEMICINCL]) - fi - AM_CONDITIONAL([SEMIC], [test "x${HAVE_SEMIC}" == "xyes"]) - dnl }}} dnl SPAI{{{ AC_MSG_CHECKING([for SPAI]) AC_ARG_WITH( @@ -2341,6 +2280,32 @@ AC_DEFUN([ISSM_OPTIONS],[ AC_MSG_RESULT([${GMSH_VERSION_MAJOR}]) AC_DEFINE_UNQUOTED([_GMSH_VERSION_MAJOR_], ${GMSH_VERSION_MAJOR}, [Gmsh major version]) fi + dnl }}} + dnl PyBind11{{{ + AC_MSG_CHECKING([for pybind11]) + AC_ARG_WITH( + [pybind11-include], + AS_HELP_STRING([--with-pybind11-include=DIR], [PyBind11 include directory, necessary for emulator integration]), + [PyBind11INCL=${withval}], + [PyBind11INCL=""] + ) + AC_ARG_WITH( + [pybind11-libflags], + AS_HELP_STRING([--with-pybind11-libflags=LIBS], [PyBind11 libraries to be used, necessary for emulator integration]), + [PyBind11LIB=${withval}], + [PyBind11LIB=""] + ) + if test -z "${PyBind11INCL}"; then + HAVE_PyBind11=no + else + HAVE_PyBind11=yes + + AC_DEFINE([_HAVE_PyBind11_], [1], [with PyBind11 in ISSM src]) + AC_SUBST([PyBind11INCL]) + AC_SUBST([PyBind11LIB]) + fi + AM_CONDITIONAL([PyBind11], [test "x${HAVE_PyBind11}" == "xyes"]) + AC_MSG_RESULT([${HAVE_PyBind11}]) dnl }}} dnl Capabilities dnl with-bamg{{{ @@ -2427,7 +2392,7 @@ AC_DEFUN([ISSM_OPTIONS],[ AC_MSG_ERROR([Number of threads must be at least 1!]); fi MULTITHREADING=no - MULTITHREADINLIB="" + MULTITHREADINGLIB="" if test "x${NUMTHREADS_VALUE}" != "x1"; then MULTITHREADINGLIB="-lpthread -lrt" case "${host_os}" in @@ -2474,12 +2439,12 @@ AC_DEFUN([ISSM_OPTIONS],[ fi dnl Check that we have MATLAB and/or Python support if we compile the modules - if test "x${MODULES_VALUE}" == "xyes" && test "${HAVE_MATLAB}" == "xno" && test "${HAVE_PYTHON}" == "xno"; then + if test "x${MODULES_VALUE}" == "xyes" && test "x${HAVE_MATLAB}" == "xno" && test "x${HAVE_PYTHON}" == "xno"; then AC_MSG_ERROR([need at least MATLAB and/or Python support to compile modules! (or use --with-modules=no)]); fi dnl Check that Fortran is provided if Gia is on - if test "x${HAVE_GIA}" == "xyes" && test "${HAVE_FORTRAN}" == "xno"; then + if test "x${HAVE_GIA}" == "xyes" && test "x${HAVE_FORTRAN}" == "xno"; then AC_MSG_ERROR([need Fortran compiler to compile Gia! (or use --without-Gia)]); fi @@ -2494,7 +2459,7 @@ AC_DEFUN([ISSM_OPTIONS],[ fi dnl Check that if we run ADOL-C, we don't compile kriging.exe - if test "x${HAVE_ADOLC}" == "xyes" && test "${HAVE_KRIGING}" == "xyes"; then + if test "x${HAVE_ADOLC}" == "xyes" && test "x${HAVE_KRIGING}" == "xyes"; then AC_MSG_ERROR([cannot compile kriging.exe under ADOL-C conditions!]); fi @@ -2541,22 +2506,15 @@ dnl ISSM_ENABLE_AD – Automatic-Differentiation (CoDiPack + MediPack) dnl ===================================================================== AC_DEFUN([ISSM_ENABLE_AD], [ # --- command-line switches ------------------------------------------ + dnl NOTE: --with-codipack-dir and --with-medipack-dir are already declared + dnl in ISSM_OPTIONS above; do not re-declare them here to avoid duplicate + dnl AC_ARG_WITH warnings from autoconf. AC_ARG_ENABLE([ad], AS_HELP_STRING([--enable-ad], [Build ISSM with CoDiPack+MediPack automatic differentiation (disables PETSc)]), [enable_ad=$enableval], [enable_ad=no]) - AC_ARG_WITH([codipack-dir], - AS_HELP_STRING([--with-codipack-dir=DIR], - [Prefix of CoDiPack install]), - [CODIPACK_ROOT=$withval], [CODIPACK_ROOT=]) - - AC_ARG_WITH([medipack-dir], - AS_HELP_STRING([--with-medipack-dir=DIR], - [Prefix of MediPack install]), - [MEDIPACK_ROOT=$withval], [MEDIPACK_ROOT=]) - # --- validation & flag injection ------------------------------------ if test "x$enable_ad" = "xyes"; then if test -z "$CODIPACK_ROOT" || test -z "$MEDIPACK_ROOT"; then diff --git a/packagers/linux/package-issm-linux-binaries-matlab.sh b/packagers/linux/package-issm-linux-binaries-matlab.sh index 13402a1b0..ae004c43e 100755 --- a/packagers/linux/package-issm-linux-binaries-matlab.sh +++ b/packagers/linux/package-issm-linux-binaries-matlab.sh @@ -78,9 +78,6 @@ mkdir ${PKG} # Add required binaries and libraries to package and modify them where needed cd ${ISSM_DIR}/bin -echo "Modify generic" -cat generic_static.m | sed -e "s/generic_static/generic/g" > generic.m - echo "Moving certain shared libraries to lib/" cp ${LIBGCC} ${LIBGCC_DIST} 2>/dev/null cp ${LIBGFORTRAN} ${LIBGFORTRAN_DIST} 2>/dev/null @@ -192,7 +189,6 @@ echo "Copying assets to package: ${PKG}" cp -rf bin examples lib scripts share test ${PKG} mkdir ${PKG}/execution echo "Cleaning up unneeded/unwanted files" -rm -f ${PKG}/bin/generic_static.* # Remove static versions of generic cluster classes rm -f ${PKG}/lib/*.a # Remove static libraries from package rm -f ${PKG}/lib/*.la # Remove libtool libraries from package rm -rf ${PKG}/test/SandBox # Remove testing sandbox from package diff --git a/packagers/linux/package-issm-linux-binaries-python-3.sh b/packagers/linux/package-issm-linux-binaries-python-3.sh index 048c4fae3..54d0bf1e9 100755 --- a/packagers/linux/package-issm-linux-binaries-python-3.sh +++ b/packagers/linux/package-issm-linux-binaries-python-3.sh @@ -71,9 +71,6 @@ mkdir ${PKG} # Add required binaries and libraries to package and modify them where needed cd ${ISSM_DIR}/bin -echo "Modify generic" -cat generic_static.py | sed -e "s/generic_static/generic/g" > generic.py - echo "Moving certain shared libraries to lib/" cp ${LIBGCC} ${LIBGCC_DIST} 2>/dev/null cp ${LIBGFORTRAN} ${LIBGFORTRAN_DIST} 2>/dev/null diff --git a/packagers/mac/package-issm-mac-binaries-matlab.sh b/packagers/mac/package-issm-mac-binaries-matlab.sh index 40c6c6805..8929090e2 100755 --- a/packagers/mac/package-issm-mac-binaries-matlab.sh +++ b/packagers/mac/package-issm-mac-binaries-matlab.sh @@ -73,9 +73,6 @@ mkdir ${PKG} # Add required binaries and libraries to package and modify them where needed cd ${ISSM_DIR}/bin -echo "Modify generic" -cat generic_static.m | sed -e "s/generic_static/generic/g" > generic.m - echo "Moving certain shared libraries to lib/" cp ${LIBGMT} ${LIBGMT_DIST} 2>/dev/null cp ${LIBPSL} ${LIBPSL_DIST} 2>/dev/null @@ -184,7 +181,6 @@ cp -rf bin examples lib scripts share test ${PKG} mkdir ${PKG}/execution cp packagers/mac/issm-executable_entitlements.plist ${PKG}/bin/entitlements.plist echo "Cleaning up unneeded/unwanted files" -rm -f ${PKG}/bin/generic_static.* # Remove static versions of generic cluster classes rm -f ${PKG}/lib/*.a # Remove static libraries from package rm -f ${PKG}/lib/*.la # Remove libtool libraries from package rm -rf ${PKG}/test/SandBox # Remove testing sandbox from package diff --git a/packagers/mac/package-issm-mac-binaries-python-3.sh b/packagers/mac/package-issm-mac-binaries-python-3.sh index 9c6e33214..360183ec1 100755 --- a/packagers/mac/package-issm-mac-binaries-python-3.sh +++ b/packagers/mac/package-issm-mac-binaries-python-3.sh @@ -66,9 +66,6 @@ mkdir ${PKG} # Add required binaries and libraries to package and modify them where needed cd ${ISSM_DIR}/bin -echo "Modify generic" -cat generic_static.py | sed -e "s/generic_static/generic/g" > generic.py - echo "Moving certain shared libraries to lib/" cp ${LIBGMT} ${LIBGMT_DIST} 2>/dev/null cp ${LIBPSL} ${LIBPSL_DIST} 2>/dev/null diff --git a/packagers/win/package-issm-win-binaries-matlab.sh b/packagers/win/package-issm-win-binaries-matlab.sh index 6e9738f4d..4e3e0d569 100644 --- a/packagers/win/package-issm-win-binaries-matlab.sh +++ b/packagers/win/package-issm-win-binaries-matlab.sh @@ -69,9 +69,6 @@ mkdir ${PKG} # Add required binaries and libraries to package and modify them where needed cd ${ISSM_DIR}/bin -echo "Modify generic" -cat generic_static.m | sed -e "s/generic_static/generic/g" > generic.m - echo "Moving system and MinGW libraries to bin/" cp /c/msys64/mingw64/bin/libgcc_s_seh-1.dll . cp /c/msys64/mingw64/bin/libstdc++-6.dll . @@ -234,7 +231,6 @@ cp -rf bin examples scripts share test ${PKG} mkdir ${PKG}/execution echo "Cleaning up unneeded/unwanted files" -rm -f ${PKG}/bin/generic_static.* # Remove static versions of generic cluster classes rm -rf ${PKG}/test/SandBox # Remove testing sandbox from package # Compress package diff --git a/src/c/Makefile.am b/src/c/Makefile.am index 96e3fb43f..cb7be17ae 100644 --- a/src/c/Makefile.am +++ b/src/c/Makefile.am @@ -1,5 +1,5 @@ -AM_CPPFLAGS = @NEOPZINCL@ @DAKOTAINCL@ @TRIANGLEINCL@ @PETSCINCL@ @AMPIINCL@ @MEDIPACKINCL@ @MPIINCL@ @PARMETISINCL@ @METISINCL@ @CHACOINCL@ @PLAPACKINCL@ @MKLINCL@ @MUMPSINCL@ @SPAIINCL@ @HYPREINCL@ @PROMETHEUSINCL@ @SUPERLUINCL@ @SPOOLESINCL@ @PASTIXINCL@ @MLINCL@ @TAOINCL@ @ADOLCINCL@ @CODIPACKINCL@ @ADJOINTPETSCINCL@ @GSLINCL@ @BOOSTINCL@ @ESMFINCL@ @PROJINCL@ @MPLAPACKINCL@ -AM_FCFLAGS = @SEMICINCL@ +AM_CPPFLAGS = @NEOPZINCL@ @DAKOTAINCL@ @TRIANGLEINCL@ @PETSCINCL@ @AMPIINCL@ @MEDIPACKINCL@ @MPIINCL@ @PARMETISINCL@ @METISINCL@ @CHACOINCL@ @PLAPACKINCL@ @MKLINCL@ @MUMPSINCL@ @SPAIINCL@ @HYPREINCL@ @PROMETHEUSINCL@ @SUPERLUINCL@ @SPOOLESINCL@ @PASTIXINCL@ @MLINCL@ @TAOINCL@ @ADOLCINCL@ @CODIPACKINCL@ @ADJOINTPETSCINCL@ @GSLINCL@ @BOOSTINCL@ @ESMFINCL@ @PROJINCL@ @MPLAPACKINCL@ @PyBind11INCL@ +AM_FCFLAGS = AUTOMAKE_OPTIONS = subdir-objects @@ -170,6 +170,7 @@ issm_sources += \ ./shared/Numerics/Interpolation.cpp \ ./shared/Exceptions/Exceptions.cpp \ ./shared/Sorting/binary_search.cpp \ + ./shared/Semic/Semic.cpp \ ./shared/Elements/Cuffey.cpp \ ./shared/Elements/BuddJacka.cpp \ ./shared/Elements/CuffeyTemperate.cpp \ @@ -305,10 +306,12 @@ issm_sources += \ ./modules/RheologyBbarAbsGradientx/RheologyBbarAbsGradientx.cpp \ ./modules/RheologyBAbsGradientx/RheologyBAbsGradientx.cpp \ ./shared/Numerics/BrentSearch.cpp \ + ./shared/m1qn3/m1qn3.cpp \ ./cores/control_core.cpp \ ./cores/controltao_core.cpp \ ./cores/controlm1qn3_core.cpp \ ./cores/controladm1qn3_core.cpp \ + ./cores/controlnudging_core.cpp \ ./cores/controlvalidation_core.cpp \ ./cores/adjointstressbalance_core.cpp \ ./cores/adjointbalancethickness_core.cpp \ @@ -585,6 +588,12 @@ if OCEAN issm_sources += ./modules/OceanExchangeDatax/OceanExchangeDatax.cpp endif #}}} +# PyBind11{{{ +if PyBind11 +issm_sources += ./classes/Params/EmulatorParam.cpp +issm_sources += ./modules/StressBalanceEmulatorx/StressBalanceEmulatorx.cpp +endif +#}}} # Sampling sources {{{ if SAMPLING issm_sources += \ @@ -626,14 +635,6 @@ if ESMF issm_sources += ./main/esmfbinders.cpp endif #}}} -# SEMIC sources {{{ -if SEMIC -if FORTRAN -issm_sources += ./modules/SurfaceMassBalancex/run_semic.f90 -issm_sources += ./modules/SurfaceMassBalancex/run_semic_transient.f90 -endif -endif -#}}} # Wrapper sources # NEOPZ sources {{{ neopz_sources = ./classes/AmrNeopz.cpp @@ -708,7 +709,7 @@ endif libISSMCore_la_SOURCES = $(issm_sources) libISSMCore_la_CXXFLAGS = $(ALL_CXXFLAGS) libISSMCore_la_FFLAGS = $(AM_FFLAGS) -libISSMCore_LIB_ADD = $(CHACOLIB) $(DAKOTALIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(TAOLIB) $(M1QN3LIB) $(SEMICLIB) $(PLAPACKLIB) $(MPLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(BLACSLIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MPILIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(ADOLCLIB) $(AMPILIB) $(PROJLIB) $(ADJOINTPETSCLIB) +libISSMCore_LIB_ADD = $(CHACOLIB) $(DAKOTALIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(TAOLIB) $(PLAPACKLIB) $(MPLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(BLACSLIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MPILIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(ADOLCLIB) $(AMPILIB) $(PROJLIB) $(ADJOINTPETSCLIB) if FORTRAN libISSMCore_LIB_ADD += $(FLIBS) $(FORTRANLIB) endif @@ -854,7 +855,7 @@ LDADD += ./libISSMModules.la $(TRIANGLELIB) endif # External packages -LDADD += $(DAKOTALIB) $(SEMICLIB) $(M1QN3LIB) $(CHACOLIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(NEOPZLIB) $(TAOLIB) $(PLAPACKLIB) $(MPLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(BLACSLIB) $(HDF5LIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(AMPILIB) $(ADOLCLIB) $(MPILIB) $(ESMFLIB) +LDADD += $(DAKOTALIB) $(CHACOLIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(NEOPZLIB) $(TAOLIB) $(PLAPACKLIB) $(MPLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(BLACSLIB) $(HDF5LIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(AMPILIB) $(ADOLCLIB) $(MPILIB) $(ESMFLIB) if FORTRAN LDADD += $(FLIBS) $(FORTRANLIB) diff --git a/src/c/analyses/FreeSurfaceBaseAnalysis.cpp b/src/c/analyses/FreeSurfaceBaseAnalysis.cpp index 6d527a034..cf28a4d82 100644 --- a/src/c/analyses/FreeSurfaceBaseAnalysis.cpp +++ b/src/c/analyses/FreeSurfaceBaseAnalysis.cpp @@ -396,6 +396,7 @@ ElementVector* FreeSurfaceBaseAnalysis::CreatePVector(Element* element){/*{{{*/ /*Retrieve all inputs and parameters*/ basalelement->FindParam(&dt,TimesteppingTimeStepEnum); basalelement->FindParam(&melt_style,GroundinglineMeltInterpolationEnum); + basalelement->FindParam(&stabilization,MasstransportStabilizationEnum); //basalelement->FindParam(&intrusiondist,GroundinglineIntrusionDistanceEnum); Input* groundedice_input = basalelement->GetInput(MaskOceanLevelsetEnum); _assert_(groundedice_input); @@ -406,9 +407,6 @@ ElementVector* FreeSurfaceBaseAnalysis::CreatePVector(Element* element){/*{{{*/ Input* vz_input = NULL; Input* vx_input = NULL; Input* vy_input = NULL; - //Input* gldistance_input = basalelement->GetInput(DistanceToGroundinglineEnum); _assert_(gldistance_input); - Input* intrusiondist_input = basalelement->GetInput(GroundinglineIntrusionDistanceEnum); _assert_(intrusiondist_input); - switch(dim){ case 1: vx_input=basalelement->GetInput(VxEnum); _assert_(vx_input); @@ -429,13 +427,14 @@ ElementVector* FreeSurfaceBaseAnalysis::CreatePVector(Element* element){/*{{{*/ Gauss* gauss = NULL; if(melt_style==SubelementMelt2Enum){ basalelement->GetGroundedPart(&point1,&fraction1,&fraction2,&mainlyfloating,MaskOceanLevelsetEnum,0); - gauss = basalelement->NewGauss(point1,fraction1,fraction2,3); + gauss = basalelement->NewGauss(point1,fraction1,fraction2,mainlyfloating,3); } - if(melt_style==IntrusionMeltEnum){ + else if(melt_style==IntrusionMeltEnum){ /* Calculate here the average intrusion distance value over the element to pass to GetGroundedPart*/ + Input* intrusiondist_input = basalelement->GetInput(GroundinglineIntrusionDistanceEnum); _assert_(intrusiondist_input); intrusiondist_input->GetInputAverage(&intrusiondist_avg); basalelement->GetGroundedPart(&point1,&fraction1,&fraction2,&mainlyfloating,DistanceToGroundinglineEnum,intrusiondist_avg); - gauss = basalelement->NewGauss(point1,fraction1,fraction2,3); + gauss = basalelement->NewGauss(point1,fraction1,fraction2,mainlyfloating,3); } else{ gauss = basalelement->NewGauss(3); diff --git a/src/c/analyses/FreeSurfaceTopAnalysis.cpp b/src/c/analyses/FreeSurfaceTopAnalysis.cpp index c3ac7d247..58305d81f 100644 --- a/src/c/analyses/FreeSurfaceTopAnalysis.cpp +++ b/src/c/analyses/FreeSurfaceTopAnalysis.cpp @@ -347,6 +347,7 @@ ElementVector* FreeSurfaceTopAnalysis::CreatePVector(Element* element){/*{{{*/ /*Retrieve all inputs and parameters*/ topelement->GetVerticesCoordinates(&xyz_list); topelement->FindParam(&dt,TimesteppingTimeStepEnum); + topelement->FindParam(&stabilization,MasstransportStabilizationEnum); Input *ms_input = topelement->GetInput(SmbMassBalanceEnum); _assert_(ms_input); Input *surface_input = topelement->GetInput(SurfaceEnum); _assert_(surface_input); Input *vz_input = NULL; @@ -380,23 +381,23 @@ ElementVector* FreeSurfaceTopAnalysis::CreatePVector(Element* element){/*{{{*/ factor = Jdet*gauss->weight*(surface + dt*ms + dt*vz); for(int i=0;ivalues[i]+=factor*basis[i]; - } - if(stabilization==5){ - /*SUPG*/ - topelement->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); - if(dim==1){ - vx_input->GetInputAverage(&vx); - tau=h/(2.*fabs(vx)+1e-10); - factor = Jdet*gauss->weight*(dt*ms+dt*vz)*tau; - for(int i=0;ivalues[i]+=factor*(vx*dbasis[0*numnodes+i]); - } - else{ - vx_input->GetInputAverage(&vx); - vy_input->GetInputAverage(&vy); - tau=h/(2.*pow(vx*vx+vy*vy,0.5)+1e-10); - factor = Jdet*gauss->weight*(dt*ms+dt*vz)*tau; - for(int i=0;ivalues[i]+=factor*(vx*dbasis[0*numnodes+i]+vy*dbasis[1*numnodes+i]); + if(stabilization==5){ + /*SUPG*/ + topelement->NodalFunctionsDerivatives(dbasis,xyz_list,gauss); + if(dim==1){ + vx_input->GetInputAverage(&vx); + tau=h/(2.*fabs(vx)+1e-10); + factor = Jdet*gauss->weight*(dt*ms+dt*vz)*tau; + for(int i=0;ivalues[i]+=factor*(vx*dbasis[0*numnodes+i]); + } + else{ + vx_input->GetInputAverage(&vx); + vy_input->GetInputAverage(&vy); + tau=h/(2.*pow(vx*vx+vy*vy,0.5)+1e-10); + factor = Jdet*gauss->weight*(dt*ms+dt*vz)*tau; + for(int i=0;ivalues[i]+=factor*(vx*dbasis[0*numnodes+i]+vy*dbasis[1*numnodes+i]); + } } } diff --git a/src/c/analyses/MasstransportAnalysis.cpp b/src/c/analyses/MasstransportAnalysis.cpp index 0266cf39b..b22336034 100644 --- a/src/c/analyses/MasstransportAnalysis.cpp +++ b/src/c/analyses/MasstransportAnalysis.cpp @@ -241,6 +241,7 @@ void MasstransportAnalysis::UpdateElements(Elements* elements,Inputs* inputs,IoM break; case BasalforcingsIsmip7Enum:{ /*TODO: Update for ISMIP7*/ + iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.basin_id",BasalforcingsIsmip7BasinIdEnum); iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.coriolis_f",BasalforcingsCoriolisFEnum); /*Deal with tf...*/ @@ -908,15 +909,23 @@ ElementVector* MasstransportAnalysis::CreatePVectorDG(Element* element){/*{{{*/ else if(melt_style==IntrusionMeltEnum){ Input* gldistance_input = element->GetInput(DistanceToGroundinglineEnum); _assert_(gldistance_input); gldistance_input->GetInputValue(&gldistance,gauss); - if (intrusiondist_avg==0) - if(gllevelset>0.) mb=gmb; - else mb=fmb; - else if(gldistance>intrusiondist_avg) + if(intrusiondist_avg==0){ + if(gllevelset>0.){ + mb=gmb; + } + else{ + mb=fmb; + } + } + else if(gldistance>intrusiondist_avg){ mb=gmb; - else if(gldistance<=intrusiondist_avg && gldistance>0) + } + else if(gldistance<=intrusiondist_avg && gldistance>0) { mb=fmb*(1-gldistance/intrusiondist_avg); - else + } + else{ mb=fmb; + } } else _error_("melt interpolation "<AddBasalInput(ThicknessEnum,newthickness,element->GetElementType()); element->AddBasalInput(ThicknessResidualEnum,thicknessresidual,element->GetElementType()); - xDelete(doflist); xDelete(newthickness); xDelete(thicknessresidual); @@ -1056,7 +1064,6 @@ void MasstransportAnalysis::InputUpdateFromSolution(IssmDouble* soluti xDelete(phi); xDelete(sealevel); xDelete(bed); - xDelete(doflist); if(basalelement->IsSpawnedElement()){basalelement->DeleteMaterials(); delete basalelement;}; }/*}}}*/ void MasstransportAnalysis::UpdateConstraints(FemModel* femmodel){/*{{{*/ @@ -1083,7 +1090,6 @@ ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/ ElementMatrix* Ke = element->NewElementMatrix(); IssmDouble* basis = xNew(numnodes); IssmDouble* dbasis = xNew(dim*numnodes); - IssmDouble* D = xNewZeroInit(dim*dim); /*Retrieve all inputs and parameters*/ element->GetVerticesCoordinates(&xyz_list); @@ -1117,7 +1123,6 @@ ElementMatrix* MasstransportAnalysis::CreateFctKMatrix(Element* element){/*{{{*/ /*Clean up and return*/ xDelete(xyz_list); - xDelete(D); xDelete(basis); xDelete(dbasis); delete gauss; @@ -1192,7 +1197,6 @@ ElementVector* MasstransportAnalysis::CreateFctPVector(Element* element){/*{{{*/ /*Initialize Element vector and other vectors*/ ElementVector* pe = element->NewElementVector(); IssmDouble* basis = xNew(numnodes); - IssmDouble* dbasis= xNew(dim*numnodes); /*Retrieve all inputs and parameters*/ element->GetVerticesCoordinates(&xyz_list); @@ -1252,7 +1256,6 @@ ElementVector* MasstransportAnalysis::CreateFctPVector(Element* element){/*{{{*/ /*Clean up and return*/ xDelete(xyz_list); xDelete(basis); - xDelete(dbasis); delete gauss; return pe; }/*}}}*/ diff --git a/src/c/analyses/SealevelchangeAnalysis.cpp b/src/c/analyses/SealevelchangeAnalysis.cpp index 6387aca3b..c1f6b2c83 100644 --- a/src/c/analyses/SealevelchangeAnalysis.cpp +++ b/src/c/analyses/SealevelchangeAnalysis.cpp @@ -129,6 +129,10 @@ void SealevelchangeAnalysis::UpdateParameters(Parameters* parameters,IoModel* io bool istime=true; IssmDouble start_time,final_time; int nt,precomputednt; + int i, j, k, n, viscoussampling; + int* viscoussamplingindex =NULL; + IssmDouble* viscoustimes=NULL; + IssmDouble* viscouspolarmotion=NULL; int numoutputs; char** requestedoutputs = NULL; @@ -301,25 +305,61 @@ void SealevelchangeAnalysis::UpdateParameters(Parameters* parameters,IoModel* io // AD performance is sensitive to calls to ensurecontiguous. // // Providing "t" will cause ensurecontiguous to be called. - if(viscous){ - IssmDouble* viscoustimes=NULL; - ntimesteps=precomputednt; - nt=reCast((final_time-start_time)/timeacc)+1; + if(viscous){ /*Initialize viscous stack times:*/ + ntimesteps=precomputednt; + iomodel->FetchData(&viscoussampling,"md.solidearth.settings.viscoussampling"); + + parameters->AddObject(new IntParam(SealevelchangeViscousSamplingEnum,viscoussampling)); + parameters->AddObject(new IntParam(SealevelchangeViscousIndexEnum,0)); + + /*Compute time indices to be used in the convolution:{{{*/ + /* These samples are spaced by intervals that double into the future. + * This captures fast evolving rates right after loading, then the + * slower relaxation times. */ + nt=reCast((final_time-start_time)/timeacc)+1; /*initial estimate, we may have to go further*/ + int* viscoussamplingindex2=NULL; + if(viscoussampling>=nt){ + n=nt; + viscoussamplingindex2=xNewZeroInit(n); + for(i=0;i(nt+1); + viscoussamplingindex[0]=0; + while (k(n); + for (i=0;iAddObject(new IntParam(SealevelchangeViscousSamplingLengthEnum,n)); + parameters->AddObject(new IntVecParam(SealevelchangeViscousSamplingIndexEnum,viscoussamplingindex2,n)); + + xDelete(viscoussamplingindex2); + /*}}}*/ - parameters->AddObject(new IntParam(SealevelchangeViscousNumStepsEnum,nt)); - /*Initialize viscous stack times:*/ viscoustimes=xNew(nt); for(int t=0;tAddObject(new IntParam(SealevelchangeViscousNumStepsEnum,nt)); parameters->AddObject(new DoubleVecParam(SealevelchangeViscousTimesEnum,viscoustimes,nt)); - parameters->AddObject(new IntParam(SealevelchangeViscousIndexEnum,0)); - xDelete(viscoustimes); if (rotation){ - IssmDouble* viscouspolarmotion=NULL; viscouspolarmotion=xNewZeroInit(3*nt); parameters->AddObject(new DoubleMatParam(SealevelchangeViscousPolarMotionEnum,viscouspolarmotion,3,nt)); - xDelete(viscouspolarmotion); } } #ifdef _HAVE_AD_ @@ -463,7 +503,6 @@ void SealevelchangeAnalysis::UpdateParameters(Parameters* parameters,IoModel* io /*Reinterpolate viscoelastic green kernels onto a regular gridded time *with steps equal to timeacc:*/ if(viscous){ - nt=reCast((final_time-start_time)/timeacc)+1; #ifdef _HAVE_AD_ G_viscoelastic_interpolated=xNew(M*nt,"t"); U_viscoelastic_interpolated=xNew(M*nt,"t"); @@ -628,6 +667,11 @@ void SealevelchangeAnalysis::UpdateParameters(Parameters* parameters,IoModel* io xDelete(Love_th2_interpolated); if (horiz) xDelete(Love_tl2_interpolated); } + if (viscous){ + xDelete(viscoussamplingindex); + xDelete(viscoustimes); + if (rotation) xDelete(viscouspolarmotion); + } } } /*}}}*/ diff --git a/src/c/analyses/SmbAnalysis.cpp b/src/c/analyses/SmbAnalysis.cpp index d1ab5b074..ef5c13d3e 100644 --- a/src/c/analyses/SmbAnalysis.cpp +++ b/src/c/analyses/SmbAnalysis.cpp @@ -24,7 +24,7 @@ void SmbAnalysis::UpdateElements(Elements* elements,Inputs* inputs,IoModel* iomo int smb_model; bool isdelta18o,ismungsm,isd18opd,issetpddfac,isprecipscaled,istemperaturescaled,isfirnwarming,isstochastic; - bool ismappedforcing,isprecipforcingremapped; + bool ismappedforcing,isprecipforcingremapped,ismappingusingneighbors; /*Update elements: */ int counter=0; @@ -51,6 +51,7 @@ void SmbAnalysis::UpdateElements(Elements* elements,Inputs* inputs,IoModel* iomo case SMBgembEnum: iomodel->FindConstant(&ismappedforcing,"md.smb.ismappedforcing"); iomodel->FindConstant(&isprecipforcingremapped,"md.smb.isprecipforcingremapped"); + iomodel->FindConstant(&ismappingusingneighbors,"md.smb.ismappingusingneighbors"); if (!ismappedforcing){ iomodel->FetchDataToInput(inputs,elements,"md.smb.Ta",SmbTaEnum); iomodel->FetchDataToInput(inputs,elements,"md.smb.V",SmbVEnum); @@ -67,6 +68,9 @@ void SmbAnalysis::UpdateElements(Elements* elements,Inputs* inputs,IoModel* iomo iomodel->FetchDataToInput(inputs,elements,"md.smb.Vz",SmbVzEnum); } else { iomodel->FetchDataToInput(inputs,elements,"md.smb.mappedforcingpoint",SmbMappedforcingpointEnum); + if(ismappingusingneighbors){ + iomodel->FetchDataToInput(inputs,elements,"md.smb.mappedforcingneighbors",SmbMappedforcingneighborsEnum); + } if(isprecipforcingremapped){ iomodel->FetchDataToInput(inputs,elements,"md.smb.mappedforcingprecipscaling",SmbMappedforcingprecipscalingEnum); } @@ -284,6 +288,21 @@ void SmbAnalysis::UpdateElements(Elements* elements,Inputs* inputs,IoModel* iomo iomodel->FetchDataToInput(inputs,elements,"md.smb.windspeed_anomaly",SmbWindspeedAnomalyEnum); iomodel->FetchDataToInput(inputs,elements,"md.smb.airhumidity_anomaly",SmbAirhumidityAnomalyEnum); break; + #ifdef _HAVE_PyBind11_ + case SMBmariaEnum: + iomodel->FetchDataToInput(inputs,elements,"md.smb.mass_balance",MariaSmbEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.elev",MariaElevEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.al",MariaAlEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.st",MariaStEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.tt",MariaTtEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.swd",MariaSwdEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.lwd",MariaLwdEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.swu",MariaSwuEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.lwu",MariaLwuEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.shf",MariaShfEnum); + iomodel->FetchDataToInput(inputs,elements,"md.smb.lhf",MariaLhfEnum); + break; + #endif default: _error_("Surface mass balance model "<AddObject(iomodel->CopyConstantObject("md.smb.aIce",SmbAIceEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.smb.aSnow",SmbASnowEnum)); iomodel->FindConstant(&ismappedforcing,"md.smb.ismappedforcing"); + iomodel->FindConstant(&ismappingusingneighbors,"md.smb.ismappingusingneighbors"); + iomodel->FindConstant(&ismappingneighborxy,"md.smb.ismappingneighborxy"); + if (ismappedforcing){ iomodel->FetchData(&temp,&M,&N,"md.smb.Ta"); _assert_(M>=1 && N>=1); parameters->AddObject(new TransientArrayParam(SmbTaParamEnum,temp,&temp[N*(M-1)],interp,cycle,N,M)); @@ -433,6 +456,26 @@ void SmbAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int s parameters->AddObject(new DoubleVecParam(SmbLapsedlwrfValueEnum,&temp[0],M)); iomodel->DeleteData(temp,"md.smb.lapsedlwrfValue"); + if (ismappingusingneighbors){ + + if (ismappingneighborxy){ + iomodel->FetchData(&temp,&M,&N,"md.smb.x_mappedforcing"); _assert_(N==1); + parameters->AddObject(new DoubleVecParam(SmbXMappedforcingEnum,&temp[0],M)); + iomodel->DeleteData(temp,"md.smb.x_mappedforcing"); + iomodel->FetchData(&temp,&M,&N,"md.smb.y_mappedforcing"); _assert_(N==1); + parameters->AddObject(new DoubleVecParam(SmbYMappedforcingEnum,&temp[0],M)); + iomodel->DeleteData(temp,"md.smb.y_mappedforcing"); + } + else{ + iomodel->FetchData(&temp,&M,&N,"md.smb.lat_mappedforcing"); _assert_(N==1); + parameters->AddObject(new DoubleVecParam(SmbLatMappedforcingEnum,&temp[0],M)); + iomodel->DeleteData(temp,"md.smb.lat_mappedforcing"); + iomodel->FetchData(&temp,&M,&N,"md.smb.lon_mappedforcing"); _assert_(N==1); + parameters->AddObject(new DoubleVecParam(SmbLonMappedforcingEnum,&temp[0],M)); + iomodel->DeleteData(temp,"md.smb.lon_mappedforcing"); + } + } + } parameters->AddObject(iomodel->CopyConstantObject("md.smb.aIdx",SmbAIdxEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.smb.eIdx",SmbEIdxEnum)); @@ -458,11 +501,14 @@ void SmbAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int s parameters->AddObject(iomodel->CopyConstantObject("md.smb.isconstrainsurfaceT",SmbIsconstrainsurfaceTEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.smb.isdeltaLWup",SmbIsdeltaLWupEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.smb.ismappedforcing",SmbIsmappedforcingEnum)); + parameters->AddObject(iomodel->CopyConstantObject("md.smb.ismappingusingneighbors",SmbIsmappingusingneighborsEnum)); + parameters->AddObject(iomodel->CopyConstantObject("md.smb.ismappingneighborxy",SmbIsmappingneighborxyEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.smb.isprecipforcingremapped",SmbIsprecipforcingremappedEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.smb.InitDensityScaling",SmbInitDensityScalingEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.smb.ThermoDeltaTScaling",SmbThermoDeltaTScalingEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.smb.adThresh",SmbAdThreshEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.smb.teThresh",SmbTeThreshEnum)); + parameters->AddObject(iomodel->CopyConstantObject("md.smb.teDefault",SmbTeDefaultEnum)); break; case SMBpddEnum: parameters->AddObject(iomodel->CopyConstantObject("md.smb.desfac",SmbDesfacEnum)); @@ -651,6 +697,27 @@ void SmbAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int s } /*Nothing to add to parameters*/ break; + #ifdef _HAVE_PyBind11_ + case SMBmariaEnum:{ + char* module_dir = NULL; + char* pt_name = NULL; + char* py_name = NULL; + + iomodel->FetchData(&module_dir,"md.smb.module_dir"); + iomodel->FetchData(&pt_name,"md.smb.pt_name"); + iomodel->FetchData(&py_name,"md.smb.py_name"); + + if(parameters->Exist(SmbEmulatorEnum)){ + _error_("SmbEmulatorEnum already exists in this process; EmulatorParam is process-local and must only be created once"); + } + parameters->AddObject(new EmulatorParam(SmbEmulatorEnum,module_dir,pt_name,py_name)); + + xDelete(module_dir); + xDelete(pt_name); + xDelete(py_name); + break; + } + #endif default: _error_("Surface mass balance model "<parameters->FindParam(&ismethod,SmbSemicMethodEnum); - SmbSemicx(femmodel,ismethod); - #else - _error_("SEMIC not installed"); - #endif //_HAVE_SEMIC_ + { + int ismethod; + femmodel->parameters->FindParam(&ismethod,SmbSemicMethodEnum); + SmbSemicx(femmodel,ismethod); + } break; case SMBdebrisEvattEnum: if(VerboseSolution())_printf0_(" call smb Evatt debris module\n"); SmbDebrisEvattx(femmodel); break; + #ifdef _HAVE_PyBind11_ + case SMBmariaEnum: + if(VerboseSolution()) _printf0_(" call smb emulator module\n"); + SmbEmulatorx(femmodel); + break; + #endif default: _error_("Surface mass balance model "<(timesx); xDelete(timesy); xDelete(timesz); - xDelete(values); - }/*}}}*/ void StressbalanceAnalysis::CreateLoads(Loads* loads, IoModel* iomodel){/*{{{*/ @@ -846,6 +847,7 @@ void StressbalanceAnalysis::UpdateElements(Elements* elements,Inputs* inputs,IoM iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.deepwater_elevation",BasalforcingsSpatialDeepwaterElevationEnum); iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.upperwater_melting_rate",BasalforcingsSpatialUpperwaterMeltingRateEnum); iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.upperwater_elevation",BasalforcingsSpatialUpperwaterElevationEnum); + iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.perturbation_melting_rate",BasalforcingsPerturbationMeltingRateEnum,0.); if(isstochastic){ iomodel->FetchDataToInput(inputs,elements,"md.stochasticforcing.default_id",StochasticForcingDefaultIdEnum); iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.deepwater_melting_rate",BaselineBasalforcingsSpatialDeepwaterMeltingRateEnum); @@ -890,6 +892,45 @@ void StressbalanceAnalysis::UpdateElements(Elements* elements,Inputs* inputs,IoM }/*}}}*/ void StressbalanceAnalysis::UpdateParameters(Parameters* parameters,IoModel* iomodel,int solution_enum,int analysis_enum){/*{{{*/ + #ifdef _HAVE_PyBind11_ + int isEmulator; + parameters->AddObject(iomodel->CopyConstantObject("md.stressbalance.isemulator",StressbalanceIsemulatorEnum)); + iomodel->FetchData(&isEmulator,"md.stressbalance.isemulator"); + if(isEmulator){ + char* module_dir = NULL; + char* pt_name = NULL; + char* py_name = NULL; + int* edge_src = NULL; + int* edge_dst = NULL; + int nsrc = 0; + int ndst = 0; + int nedges = 0; + int rank = IssmComm::GetRank(); + + iomodel->FetchData(&module_dir,"md.stressbalance.module_dir"); + iomodel->FetchData(&pt_name,"md.stressbalance.pt_name"); + iomodel->FetchData(&py_name,"md.stressbalance.py_name"); + if(rank==0){ + parameters->FindParam(&nedges,EdgesNumberEnum); + parameters->FindParam(&edge_src,&nsrc,EdgesSrcEnum); + parameters->FindParam(&edge_dst,&ndst,EdgesDstEnum); + if(nsrc!=nedges || ndst!=nedges){ + _error_("Stressbalance emulator edge arrays do not match EdgesNumberEnum"); + } + } + if(parameters->Exist(StressbalanceEmulatorEnum)){ + _error_("StressbalanceEmulatorEnum already exists in this process; EmulatorParam is process-local and must only be created once"); + } + parameters->AddObject(new EmulatorParam(StressbalanceEmulatorEnum,module_dir,pt_name,py_name,edge_src,nsrc,edge_dst,ndst,iomodel->numberofvertices)); + + xDelete(edge_src); + xDelete(edge_dst); + xDelete(module_dir); + xDelete(pt_name); + xDelete(py_name); + } + #endif + /*Intermediaries*/ int fe_FS; int numoutputs; @@ -945,6 +986,16 @@ void StressbalanceAnalysis::UpdateParameters(Parameters* parameters,IoModel* iom /*Finite Element Analysis*/ void StressbalanceAnalysis::Core(FemModel* femmodel){/*{{{*/ + /*Emulator*/ + #ifdef _HAVE_PyBind11_ + int isEmulator; + femmodel->parameters->FindParam(&isEmulator,StressbalanceIsemulatorEnum); + if(isEmulator==1){ + StressBalanceEmulatorx(femmodel); + return; + } + #endif + /*Intermediaries*/ bool isSSA,isL1L2,isMOLHO,isHO,isFS; bool conserve_loads = true; @@ -2188,8 +2239,8 @@ void StressbalanceAnalysis::ComputeHydrologySlope(IssmDouble* hydrologyslope,Gau } switch(point1){//{{{ case 0: - Hl_f1=H[0]+(Hl[1]-Hl[0])*fraction1; - Hl_f2=H[0]+(Hl[2]-Hl[0])*fraction2; + Hl_f1=Hl[0]+(Hl[1]-Hl[0])*fraction1; + Hl_f2=Hl[0]+(Hl[2]-Hl[0])*fraction2; break; case 1: Hl_f1=Hl[1]+(Hl[2]-Hl[1])*fraction1; @@ -2282,7 +2333,6 @@ void StressbalanceAnalysis::ComputeHydrologySlope(IssmDouble* hydrologyslope,Gau xDelete(h); xDelete(Hl); xDelete(h_r); - xDelete(Sl_subelem); }/*}}}*/ void StressbalanceAnalysis::NodalFunctionsDerivativesRGB(IssmDouble* dbasis_subelem,Gauss* gauss_DG,Gauss* gauss_CG,int point1,IssmDouble fraction1,IssmDouble fraction2,int ig,int dim,Element* element){/*{{{*/ @@ -3651,7 +3701,7 @@ ElementVector* StressbalanceAnalysis::CreatePVectorHO(Element* element){/*{{{*/ forcex=fx(x_coord,y_coord,z_coord,FSANALYTICAL); forcey=fy(x_coord,y_coord,z_coord,FSANALYTICAL); - IssmDouble Jdet*gauss->weight; + IssmDouble factor = Jdet*gauss->weight; for(int i=0;ivalues[i*(dim-1)+0]+=forcex*factor*basis[i]; pe->values[i*(dim-1)+1]+=forcey*factor*basis[i]; @@ -4772,7 +4822,7 @@ ElementMatrix* StressbalanceAnalysis::CreateKMatrixFSViscousXTH(Element* element element->FindParam(&FSreconditioning,StressbalanceFSreconditioningEnum); Input* vx_input=element->GetInput(VxEnum); _assert_(vx_input); Input* vy_input=element->GetInput(VyEnum); _assert_(vy_input); - Input* vz_input; + Input* vz_input=NULL; if(dim==3){vz_input=element->GetInput(VzEnum); _assert_(vz_input);} /* Start looping on the number of gaussian points: */ @@ -4886,7 +4936,6 @@ ElementVector* StressbalanceAnalysis::CreatePVectorFS(Element* element){/*{{{*/ ElementVector* pe1=CreatePVectorFSViscous(element); ElementVector* pe2=CreatePVectorFSFriction(element); - ElementVector* pe3=CreatePVectorFSStress(element); pe =new ElementVector(pe1,pe2,pe3); delete pe1; delete pe2; @@ -4948,65 +4997,6 @@ ElementVector* StressbalanceAnalysis::CreatePVectorFSFriction(Element* element){ xDelete(vbasis); return pe; }/*}}}*/ -ElementVector* StressbalanceAnalysis::CreatePVectorFSStress(Element* element){/*{{{*/ - - /*Skipping for now*/ - return NULL; - if(!element->IsOnBase()) return NULL; - - /*Intermediaries*/ - int dim; - IssmDouble sigmann,sigmant,Jdet,bedslope,beta; - IssmDouble *xyz_list_base = NULL; - Gauss* gauss = NULL; - - /*Get problem dimension*/ - element->FindParam(&dim,DomainDimensionEnum); - - /*Fetch number of nodes and dof for this finite element*/ - int vnumnodes = element->NumberofNodesVelocity(); - - /*Initialize Element matrix and vectors*/ - ElementVector* pe = element->NewElementVector(FSvelocityEnum); - IssmDouble* vbasis = xNew(vnumnodes); - - /*Retrieve all inputs and parameters*/ - element->GetVerticesCoordinatesBase(&xyz_list_base); - Input* sigmann_input=element->GetInput(VzEnum); _assert_(sigmann_input); - Input* sigmant_input=element->GetInput(TemperatureEnum); _assert_(sigmant_input); - Input* bedslope_input=element->GetInput(BedSlopeXEnum); _assert_(bedslope_input); - - /* Start looping on the number of gaussian points: */ - gauss=element->NewGaussBase(3); - while(gauss->next()){ - - sigmann_input->GetInputValue(&sigmann, gauss); - sigmant_input->GetInputValue(&sigmant, gauss); - bedslope_input->GetInputValue(&bedslope, gauss); - element->JacobianDeterminantBase(&Jdet,xyz_list_base,gauss); - element->NodalFunctionsVelocity(vbasis,gauss); - - beta=sqrt(1+bedslope*bedslope); - IssmDouble factor = - (1./beta)*gauss->weight*Jdet; - for(int i=0;ivalues[i*dim+0] += factor*(-bedslope*sigmann + sigmant)*vbasis[i]; - pe->values[i*dim+1] += factor*(sigmann + bedslope*sigmant)*vbasis[i]; - if(dim==3){ - //pe->values[i*dim+2]+= alpha2*gauss->weight*Jdet*vbasis[i]; - _error_("3d not supported yet"); - } - } - - } - - /*DO NOT Transform Coordinate System: this stiffness matrix is already expressed in tangential coordinates*/ - - /*Clean up and return*/ - delete gauss; - xDelete(xyz_list_base); - xDelete(vbasis); - return pe; -}/*}}}*/ ElementVector* StressbalanceAnalysis::CreatePVectorFSViscous(Element* element){/*{{{*/ int i,dim,fe_FS; @@ -6484,7 +6474,7 @@ void StressbalanceAnalysis::InitializeXTH(Elements* elements,Parameter element->GetVerticesCoordinates(&xyz_list); Input* vx_input=element->GetInput(VxEnum); _assert_(vx_input); Input* vy_input=element->GetInput(VyEnum); _assert_(vy_input); - Input* vz_input; + Input* vz_input=NULL; if(dim==3){vz_input=element->GetInput(VzEnum); _assert_(vz_input);} /*Allocate new inputs*/ diff --git a/src/c/analyses/StressbalanceVerticalAnalysis.cpp b/src/c/analyses/StressbalanceVerticalAnalysis.cpp index e28b24014..9600dc0c1 100644 --- a/src/c/analyses/StressbalanceVerticalAnalysis.cpp +++ b/src/c/analyses/StressbalanceVerticalAnalysis.cpp @@ -145,6 +145,7 @@ void StressbalanceVerticalAnalysis::UpdateElements(Elements* elements,Inputs* in iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.deepwater_elevation",BasalforcingsSpatialDeepwaterElevationEnum); iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.upperwater_melting_rate",BasalforcingsSpatialUpperwaterMeltingRateEnum); iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.upperwater_elevation",BasalforcingsSpatialUpperwaterElevationEnum); + iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.perturbation_melting_rate",BasalforcingsPerturbationMeltingRateEnum,0.); if(isstochastic){ iomodel->FetchDataToInput(inputs,elements,"md.stochasticforcing.default_id",StochasticForcingDefaultIdEnum); iomodel->FetchDataToInput(inputs,elements,"md.basalforcings.deepwater_melting_rate",BaselineBasalforcingsSpatialDeepwaterMeltingRateEnum); diff --git a/src/c/bamg/Triangle.cpp b/src/c/bamg/Triangle.cpp index 2552274e5..6534f995e 100644 --- a/src/c/bamg/Triangle.cpp +++ b/src/c/bamg/Triangle.cpp @@ -271,14 +271,17 @@ namespace bamg { x2a = s2->i.x - sa->i.x, yba = sb->i.y - sa->i.y, y2a = s2->i.y - sa->i.y; - double - cosb12 = double(xb1*x21 + yb1*y21), - cosba2 = double(xba*x2a + yba*y2a) , - sinb12 = double(det2), - sinba2 = double(t2->det); + long long cosb12_ll = xb1*x21 + yb1*y21; + long long cosba2_ll = xba*x2a + yba*y2a; + long long sinb12_ll = det2; + long long sinba2_ll = t2->det; // angle b12 > angle ba2 => cotg(angle b12) < cotg(angle ba2) - OnSwap = ((double) cosb12 * (double) sinba2) < ((double) cosba2 * (double) sinb12); + // Use exact 128-bit integer arithmetic to avoid platform-dependent + // floating-point rounding in the cross-multiplication: + __int128 lhs = (__int128)cosb12_ll * (__int128)sinba2_ll; + __int128 rhs = (__int128)cosba2_ll * (__int128)sinb12_ll; + OnSwap = lhs < rhs; break; } else { @@ -320,17 +323,30 @@ namespace bamg { } else {kopt=1;continue;} } - OnSwap = som < 2; + // When som is within machine epsilon of 2, the anisotropic criterion + // is ambiguous (co-circular in metric space). Fall back to the exact + // isotropic criterion (integer arithmetic, fully deterministic). + if(som >= 2*(1-4e-15) && som <= 2*(1+4e-15)) { + long long xb1_ = sb->i.x - s1->i.x, x21_ = s2->i.x - s1->i.x, + yb1_ = sb->i.y - s1->i.y, y21_ = s2->i.y - s1->i.y, + xba_ = sb->i.x - sa->i.x, x2a_ = s2->i.x - sa->i.x, + yba_ = sb->i.y - sa->i.y, y2a_ = s2->i.y - sa->i.y; + __int128 lhs_ = (__int128)(xb1_*x21_ + yb1_*y21_) * (__int128)det2; + __int128 rhs_ = (__int128)(xba_*x2a_ + yba_*y2a_) * (__int128)(t2->det); + OnSwap = lhs_ < rhs_; + } else { + OnSwap = som < 2; + } break; } } // OnSwap } // (! OnSwap &&(det1 > 0) && (det2 > 0) ) } - if( OnSwap ) + if( OnSwap ) bamg::swap(t1,a1,t2,a2,s1,s2,det1,det2); else { - t1->SetMarkUnSwap(a1); + t1->SetMarkUnSwap(a1); } return OnSwap; } diff --git a/src/c/classes/BarystaticContributions.cpp b/src/c/classes/BarystaticContributions.cpp index 6cbd5a2d4..63875d3fa 100644 --- a/src/c/classes/BarystaticContributions.cpp +++ b/src/c/classes/BarystaticContributions.cpp @@ -17,38 +17,52 @@ /*Constructors and destructors:*/ BarystaticContributions::BarystaticContributions(IoModel* iomodel ){ /*{{{*/ - int nel; + /*Intermediaries*/ + int nel; - iomodel->FetchData(&nice,"md.solidearth.npartice"); - if(nice){ - iomodel->FetchData(&pice,&nel,NULL,"md.solidearth.partitionice"); - ice=new Vector(nice); - cumice=new Vector(nice); cumice->Set(0); cumice->Assemble(); + /*Allocate all pointers to NULL*/ + this->ice = NULL; //contributions to every ice partition (size nice x 1) + this->cumice = NULL; //cumulated contributions to every ice partition + this->pice = NULL; //ice partition (nel) + + this->hydro = NULL; //contributions to every hydro partition (size nhydro x 1) + this->cumhydro = NULL; //cumulated contributions to every hydro partition + this->phydro = NULL; //hydro partition (nel) + + this->ocean = NULL; //contributions to every ocean partition (size nocean x 1) + this->cumocean = NULL; //cumulated contributions to every ocean partition + this->pocean = NULL; //ocean partition (nel) + + iomodel->FetchData(&this->nice,"md.solidearth.npartice"); + if(this->nice){ + iomodel->FetchData(&this->pice,&nel,NULL,"md.solidearth.partitionice"); + this->ice=new Vector(nice); + this->cumice=new Vector(nice); this->cumice->Set(0); this->cumice->Assemble(); } else{ - ice=new Vector(1); - cumice=new Vector(1); + this->ice=new Vector(1); + this->cumice=new Vector(1); } - iomodel->FetchData(&nhydro,"md.solidearth.nparthydro"); - if(nhydro){ - iomodel->FetchData(&phydro,&nel,NULL,"md.solidearth.partitionhydro"); - hydro=new Vector(nhydro); - cumhydro=new Vector(nhydro); cumhydro->Set(0); cumhydro->Assemble(); + iomodel->FetchData(&this->nhydro,"md.solidearth.nparthydro"); + if(this->nhydro){ + iomodel->FetchData(&this->phydro,&nel,NULL,"md.solidearth.partitionhydro"); + this->hydro=new Vector(this->nhydro); + this->cumhydro=new Vector(this->nhydro); this->cumhydro->Set(0); this->cumhydro->Assemble(); } else{ - hydro=new Vector(1); - cumhydro=new Vector(1); + this->hydro=new Vector(1); + this->cumhydro=new Vector(1); } - iomodel->FetchData(&nocean,"md.solidearth.npartocean"); - if(nocean){ - iomodel->FetchData(&pocean,&nel,NULL,"md.solidearth.partitionocean"); - ocean=new Vector(nocean); - cumocean=new Vector(nocean); cumocean->Set(0); cumocean->Assemble(); + iomodel->FetchData(&this->nocean,"md.solidearth.npartocean"); + if(this->nocean){ + iomodel->FetchData(&this->pocean,&nel,NULL,"md.solidearth.partitionocean"); + this->ocean=new Vector(this->nocean); + this->cumocean=new Vector(this->nocean); this->cumocean->Set(0); this->cumocean->Assemble(); } else{ - ocean=new Vector(1); - cumocean=new Vector(1); + this->ocean=new Vector(1); + this->cumocean=new Vector(1); } } /*}}}*/ @@ -62,14 +76,24 @@ BarystaticContributions::~BarystaticContributions(){ /*{{{*/ }; /*}}}*/ /*Support routines:*/ -IssmDouble BarystaticContributions::Total(){ /*{{{*/ - - IssmDouble sumice,sumhydro,sumocean; +void BarystaticContributions::Assemble(){ /*{{{*/ ice->Assemble(); hydro->Assemble(); ocean->Assemble(); +} /*}}}*/ +void BarystaticContributions::CumAssemble(){ /*{{{*/ + + cumice->Assemble(); + cumhydro->Assemble(); + cumocean->Assemble(); + +} /*}}}*/ +IssmDouble BarystaticContributions::Total(){ /*{{{*/ + + IssmDouble sumice,sumhydro,sumocean; + ice->Sum(&sumice); hydro->Sum(&sumhydro); ocean->Sum(&sumocean); @@ -81,10 +105,6 @@ IssmDouble BarystaticContributions::CumTotal(){ /*{{{*/ IssmDouble sumice,sumhydro,sumocean; - cumice->Assemble(); - cumhydro->Assemble(); - cumocean->Assemble(); - cumice->Sum(&sumice); cumhydro->Sum(&sumhydro); cumocean->Sum(&sumocean); @@ -161,37 +181,37 @@ void BarystaticContributions::Save(Results* results, Parameters* parameters, Iss parameters->FindParam(&rho_water,MaterialsRhoSeawaterEnum); ice->Sum(&sumice); hydro->Sum(&sumhydro); ocean->Sum(&sumocean); - results->AddResult(new GenericExternalResult(results->Size()+1,BslcEnum,this->Total()/oceanarea/rho_water,step,time)); + results->AddResult(new GenericExternalResult(results->Size()+1,BslcEnum,(sumice+sumhydro+sumocean)/oceanarea/rho_water,step,time)); results->AddResult(new GenericExternalResult(results->Size()+1,BslcIceEnum,sumice/oceanarea/rho_water,step,time)); - results->AddResult(new GenericExternalResult(results->Size()+1,BslcHydroEnum,sumice/oceanarea/rho_water,step,time)); + results->AddResult(new GenericExternalResult(results->Size()+1,BslcHydroEnum,sumhydro/oceanarea/rho_water,step,time)); results->AddResult(new GenericExternalResult(results->Size()+1,BslcOceanEnum,sumocean/oceanarea/rho_water,step,time)); cumice->Sum(&sumice); cumhydro->Sum(&sumhydro); cumocean->Sum(&sumocean); - results->AddResult(new GenericExternalResult(results->Size()+1,CumBslcEnum,this->CumTotal()/oceanarea/rho_water,step,time)); + results->AddResult(new GenericExternalResult(results->Size()+1,CumBslcEnum,(sumice+sumhydro+sumocean)/oceanarea/rho_water,step,time)); results->AddResult(new GenericExternalResult(results->Size()+1,CumBslcIceEnum,sumice/oceanarea/rho_water,step,time)); results->AddResult(new GenericExternalResult(results->Size()+1,CumBslcHydroEnum,sumhydro/oceanarea/rho_water,step,time)); results->AddResult(new GenericExternalResult(results->Size()+1,CumBslcOceanEnum,sumocean/oceanarea/rho_water,step,time)); if(nice){ cumice_serial=this->cumice->ToMPISerial0(); - if(IssmComm::GetRank()==0){ - for (int i=0;iAddResult(new GenericExternalResult(results->Size()+1,CumBslcIcePartitionEnum,cumice_serial,nice,1,step,time)); - } + if(IssmComm::GetRank()==0){ + for (int i=0;iAddResult(new GenericExternalResult(results->Size()+1,CumBslcIcePartitionEnum,cumice_serial,nice,1,step,time)); + } } if(nhydro){ cumhydro_serial=this->cumhydro->ToMPISerial0(); - if(IssmComm::GetRank()==0){ - for (int i=0;iAddResult(new GenericExternalResult(results->Size()+1,CumBslcHydroPartitionEnum,cumhydro_serial,nhydro,1,step,time)); - } + if(IssmComm::GetRank()==0){ + for (int i=0;iAddResult(new GenericExternalResult(results->Size()+1,CumBslcHydroPartitionEnum,cumhydro_serial,nhydro,1,step,time)); + } } if(nocean){ - cumocean_serial=this->cumocean->ToMPISerial0(); - if(IssmComm::GetRank()==0){ - for (int i=0;iAddResult(new GenericExternalResult(results->Size()+1,CumBslcOceanPartitionEnum,cumocean_serial,nocean,1,step,time)); - } + cumocean_serial=this->cumocean->ToMPISerial0(); + if(IssmComm::GetRank()==0){ + for (int i=0;iAddResult(new GenericExternalResult(results->Size()+1,CumBslcOceanPartitionEnum,cumocean_serial,nocean,1,step,time)); + } } if(IssmComm::GetRank()==0){ diff --git a/src/c/classes/BarystaticContributions.h b/src/c/classes/BarystaticContributions.h index a29e13015..3a4fa1180 100644 --- a/src/c/classes/BarystaticContributions.h +++ b/src/c/classes/BarystaticContributions.h @@ -36,6 +36,8 @@ class BarystaticContributions { ~BarystaticContributions(); /*routines:*/ + void Assemble(); + void CumAssemble(); IssmDouble Total(); IssmDouble CumTotal(); void Cumulate(Parameters* parameters); diff --git a/src/c/classes/Elements/Element.cpp b/src/c/classes/Elements/Element.cpp index 5002ff42f..0b3b0d5f0 100644 --- a/src/c/classes/Elements/Element.cpp +++ b/src/c/classes/Elements/Element.cpp @@ -25,26 +25,6 @@ /*}}}*/ #define MAXVERTICES 6 /*Maximum number of vertices per element, currently Penta, to avoid dynamic mem allocation*/ -#ifdef _HAVE_SEMIC_ -/* SEMIC prototype {{{*/ -extern "C" void run_semic_(IssmDouble *sf_in, IssmDouble *rf_in, IssmDouble *swd_in, IssmDouble *lwd_in, IssmDouble *wind_in, IssmDouble *sp_in, IssmDouble *rhoa_in, - IssmDouble *qq_in, IssmDouble *tt_in, IssmDouble *tsurf_out, IssmDouble *smb_out, IssmDouble *saccu_out, IssmDouble *smelt_out); - -extern "C" void run_semic_transient_(int *nx, int *ntime, int *nloop, - IssmDouble *sf_in, IssmDouble *rf_in, IssmDouble *swd_in, - IssmDouble *lwd_in, IssmDouble *wind_in, IssmDouble *sp_in, IssmDouble *rhoa_in, - IssmDouble *qq_in, IssmDouble *tt_in, IssmDouble *tsurf_in, IssmDouble *qmr_in, - IssmDouble *tstic, - IssmDouble *hcrit, IssmDouble *rcrit, - IssmDouble *mask, IssmDouble *hice, IssmDouble *hsnow, - IssmDouble *albedo_in, IssmDouble *albedo_snow_in, - int *alb_scheme, IssmDouble *alb_smax, IssmDouble *alb_smin, IssmDouble *albi, IssmDouble *albl, - IssmDouble *Tamp, - IssmDouble *tmin, IssmDouble *tmax, IssmDouble *tmid, IssmDouble *mcrit, IssmDouble *wcrit, IssmDouble *tau_a, IssmDouble* tau_f, IssmDouble *afac, bool *verbose, - IssmDouble *tsurf_out, IssmDouble *smb_out, IssmDouble *smbi_out, IssmDouble *smbs_out, IssmDouble *saccu_out, IssmDouble *smelt_out, IssmDouble *refr_out, IssmDouble *albedo_out, IssmDouble *albedo_snow_out, IssmDouble *hsnow_out, IssmDouble *hice_out, IssmDouble *qmr_out, IssmDouble *runoff_out, IssmDouble *subl_out); -#endif -// _HAVE_SEMIC_ -/*}}}*/ /*Constructors/destructor/copy*/ Element::Element(){/*{{{*/ this->id = -1; @@ -2508,6 +2488,7 @@ void Element::Ismip7FloatingiceMeltingRate(){/*{{{*/ if(!this->IsIceInElement() || !this->IsAllFloating() || !this->IsOnBase()) return; int basinid,num_basins,M,N; + IssmDouble delta_t_basin; IssmDouble* xyz_list; IssmDouble tf,gamma0; @@ -2515,6 +2496,7 @@ void Element::Ismip7FloatingiceMeltingRate(){/*{{{*/ IssmDouble coriolis; /*Coriolis parameter*/ IssmDouble dbase[2]; /*derivative of z_b*/ IssmDouble theta, slope; + IssmDouble* delta_t = NULL; IssmDouble* depths = NULL; @@ -2533,12 +2515,17 @@ void Element::Ismip7FloatingiceMeltingRate(){/*{{{*/ IssmDouble g = this->FindParam(ConstantsGEnum); /* Get parameters and inputs */ + this->GetInputValue(&basinid,BasalforcingsIsmip7BasinIdEnum); + this->parameters->FindParam(&num_basins,BasalforcingsIsmip7NumBasinsEnum); + this->parameters->FindParam(&delta_t,&M,BasalforcingsIsmip7DeltaTEnum); _assert_(M==num_basins); this->parameters->FindParam(&gamma0,BasalforcingsIsmip7GammaEnum); Input* base_input = this->GetInput(BaseEnum); _assert_(base_input); Input* tf_input = this->GetInput(BasalforcingsIsmip7TfShelfEnum); _assert_(tf_input); Input* salinity_input = this->GetInput(BasalforcingsIsmip7SalinityShelfEnum); _assert_(salinity_input); Input* coriolis_input = this->GetInput(BasalforcingsCoriolisFEnum); _assert_(coriolis_input); + + delta_t_basin = delta_t[basinid]; /*Compute melt rate for Local and Nonlocal parameterizations*/ Gauss* gauss=this->NewGauss(); @@ -2553,7 +2540,7 @@ void Element::Ismip7FloatingiceMeltingRate(){/*{{{*/ slope = sqrt(pow(dbase[0],2)+pow(dbase[1],2)); theta = atan(slope); - basalmeltrate[i] = gamma0*sin(theta)*(rhow/rhoi)*pow(cp/lf,2)*betaS*salinity*g/2.0/fabs(coriolis)*fabs(tf)*tf; + basalmeltrate[i] = gamma0*sin(theta)*(rhow/rhoi)*pow(cp/lf,2)*betaS*salinity*g/2.0/fabs(coriolis)*fabs(tf+delta_t_basin)*(tf+delta_t_basin); } /*Return basal melt rate*/ @@ -2562,7 +2549,7 @@ void Element::Ismip7FloatingiceMeltingRate(){/*{{{*/ /*Cleanup and return*/ delete gauss; xDelete(depths); - + xDelete(delta_t); }/*}}}*/ void Element::LapseRateBasinSMB(int numelevbins, IssmDouble* lapserates, IssmDouble* elevbins,IssmDouble* refelevation){/*{{{*/ @@ -4901,7 +4888,6 @@ void Element::SetwiseNodeConnectivity(int* pd_nz,int* po_nz,Node* node,boo *po_nz=o_nz; } /*}}}*/ -#ifdef _HAVE_SEMIC_ void Element::SmbSemic(){/*{{{*/ /*only compute SMB at the surface: */ @@ -4996,10 +4982,10 @@ void Element::SmbSemic(){/*{{{*/ } for (int iv = 0; ivObjectEnum()){ @@ -5260,20 +5246,21 @@ void Element::SmbSemicTransient(){/*{{{*/ _printf0_("smb core: assign qmr :" << qmr_in[0] << "\n"); } - if(isverbose && this->Sid()==0)_printf0_("smb core: call run_semic_transient module.\n"); - /* call semic */ + if(isverbose && this->Sid()==0)_printf0_("smb core: call RunSemicTransient (C++).\n"); + /* call semic (C++ implementation) */ int nx=NUM_VERTICES, ntime=1, nloop=1; bool semic_verbose=false; //VerboseSmb(); - run_semic_transient_(&nx, &ntime, &nloop, + RunSemicTransient(nx, ntime, nloop, dailysnowfall, dailyrainfall, dailydsradiation, dailydlradiation, - dailywindspeed, dailypressure, dailyairdensity, dailyairhumidity, dailytemperature, tsurf_in, qmr_in, - &dt, - &hcrit, &rcrit, - mask_in, hice_in, hsnow_in, + dailywindspeed, dailypressure, dailyairdensity, dailyairhumidity, dailytemperature, tsurf_in, qmr_in, + dt, + hcrit, rcrit, + mask_in, hice_in, hsnow_in, albedo_in, albedo_snow_in, - &alb_scheme, &alb_smax, &alb_smin, &albi, &albl, + alb_scheme, alb_smax, alb_smin, albi, albl, Tamp_in, - &tmin, &tmax, &tmid, &mcrit, &wcrit, &tau_a, &tau_f, &afac, &semic_verbose, + tmin, tmax, tmid, mcrit, wcrit, tau_a, tau_f, afac, + semic_verbose, tsurf_out, smb_out, smbi_out, smbs_out, saccu_out, smelt_out, refr_out, albedo_out, albedo_snow_out, hsnow_out, hice_out, qmr_out, runoff_out, subl_out); for (int iv = 0; ivsid; @@ -5426,6 +5412,7 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ int dsnowIdx=0; int swIdx=0; int N=0; + int N2=0; IssmDouble cldFrac,t0wet, t0dry, K; IssmDouble lhf=0.0; IssmDouble shf=0.0; @@ -5455,13 +5442,15 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ IssmDouble accsumEC=0.0; IssmDouble accsumP=0.0; IssmDouble accsumRa=0.0; - bool isgraingrowth,isalbedo,isshortwave,isthermal,isaccumulation,ismelt,isdensification,isturbulentflux,ismappedforcing; + bool isgraingrowth,isalbedo,isshortwave,isthermal,isaccumulation,ismelt,isdensification,isturbulentflux; + bool ismappedforcing, ismappingusingneighbors, ismappingneighborxy; bool isconstrainsurfaceT=false; bool isdeltaLWup=false; IssmDouble init_scaling=0.0; IssmDouble thermo_scaling=1.0; IssmDouble adThresh=1023.0; IssmDouble teThresh=10; + IssmDouble teDefault=1; IssmDouble tlapse=0.0; IssmDouble dlwlapse=0.0; /*}}}*/ @@ -5516,6 +5505,11 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ IssmDouble* Radsub=NULL; IssmDouble* Pdsub=NULL; int m=0; + int mpQ11=0; + int mpQ21=0; + int mpQ12=0; + int mpQ22=0; + IssmDouble minx, maxx, miny, maxy, lat, lon; /*}}}*/ /*Retrieve material properties and parameters:{{{ */ @@ -5551,7 +5545,10 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ parameters->FindParam(&thermo_scaling,SmbThermoDeltaTScalingEnum); parameters->FindParam(&adThresh,SmbAdThreshEnum); parameters->FindParam(&teThresh,SmbTeThreshEnum); + parameters->FindParam(&teDefault,SmbTeDefaultEnum); parameters->FindParam(&ismappedforcing,SmbIsmappedforcingEnum); + parameters->FindParam(&ismappingusingneighbors,SmbIsmappingusingneighborsEnum); + parameters->FindParam(&ismappingneighborxy,SmbIsmappingneighborxyEnum); /*}}}*/ /*Retrieve inputs: {{{*/ Input *zTop_input = this->GetInput(SmbZTopEnum); _assert_(zTop_input); @@ -5573,6 +5570,8 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ zMin_input->GetInputValue(&zMin,gauss); zY_input->GetInputValue(&zY,gauss); + int* Qinterp=NULL; + if (!ismappedforcing) { Input *Tmean_input = this->GetInput(SmbTmeanEnum); _assert_(Tmean_input); Input *Vmean_input = this->GetInput(SmbVmeanEnum); _assert_(Vmean_input); @@ -5589,29 +5588,196 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ } else { this->GetInputValue(&Mappedpoint,SmbMappedforcingpointEnum); - IssmDouble* tmean = NULL; - IssmDouble* vmean = NULL; - IssmDouble* cmean = NULL; + IssmDouble* tmeane = NULL; + IssmDouble* vmeane = NULL; + IssmDouble* cmeane = NULL; IssmDouble* tzval = NULL; IssmDouble* vzval = NULL; - parameters->FindParam(&tmean,&N,SmbTmeanParamEnum); - parameters->FindParam(&vmean,&N,SmbVmeanParamEnum); - parameters->FindParam(&cmean,&N,SmbCParamEnum); parameters->FindParam(&tzval,&N,SmbTzParamEnum); parameters->FindParam(&vzval,&N,SmbVzParamEnum); + parameters->FindParam(&tmeane,&N,SmbTmeanParamEnum); + parameters->FindParam(&vmeane,&N,SmbVmeanParamEnum); + parameters->FindParam(&cmeane,&N,SmbCParamEnum); - Tmean = tmean[Mappedpoint-1]; - Vmean = vmean[Mappedpoint-1]; - C = cmean[Mappedpoint-1]; Tz = tzval[Mappedpoint-1]; Vz = vzval[Mappedpoint-1]; - xDelete(tmean); - xDelete(vmean); - xDelete(cmean); + if (ismappingusingneighbors){ + + if (!isinitialized){ + + IssmDouble* lat_mappingpoint=NULL; + IssmDouble* lon_mappingpoint=NULL; + int* mappedforcingneighbors=NULL; + + if (ismappingneighborxy) { + parameters->FindParam(&lon_mappingpoint,&N,SmbXMappedforcingEnum); + parameters->FindParam(&lat_mappingpoint,&N,SmbYMappedforcingEnum); + }else{ + parameters->FindParam(&lon_mappingpoint,&N,SmbLonMappedforcingEnum); + parameters->FindParam(&lat_mappingpoint,&N,SmbLatMappedforcingEnum); + } + + this->inputs->GetIntArray(SmbMappedforcingneighborsEnum,this->lid,&mappedforcingneighbors,&N2); _assert_(N2==3); + + Qinterp = xNew(4); + IssmDouble* xinterp = xNew(4); + IssmDouble* yinterp = xNew(4); + int* mappedforcingpoints = xNew(4); + double* xelem = xNew(1); + double* yelem = xNew(1); + double* latelem = xNew(1); + double* lonelem = xNew(1); + + /*Allocate all arrays*/ + IssmDouble* xyz_list = NULL; + this->GetVerticesCoordinates(&xyz_list); + xelem[0]=reCast(this->GetXcoord(xyz_list,gauss)); + yelem[0]=reCast(this->GetYcoord(xyz_list,gauss)); + + //Figure out which points are Q11, Q12, Q21, and Q22 + int neighbor1,neighbor2,neighbor3; + + if (mappedforcingneighbors[0] < 0 || mappedforcingneighbors[1] < 0 || mappedforcingneighbors[2] < 0){ + neighbor1 = Mappedpoint; + neighbor2 = Mappedpoint; + neighbor3 = Mappedpoint; + } + else{ + neighbor1 = mappedforcingneighbors[0]; + neighbor2 = mappedforcingneighbors[1]; + neighbor3 = mappedforcingneighbors[2]; + } + + mappedforcingpoints[0]=Mappedpoint; + mappedforcingpoints[1]=neighbor1; + mappedforcingpoints[2]=neighbor2; + mappedforcingpoints[3]=neighbor3; + xinterp[0]=lon_mappingpoint[mappedforcingpoints[0]-1]; + xinterp[1]=lon_mappingpoint[mappedforcingpoints[1]-1]; + xinterp[2]=lon_mappingpoint[mappedforcingpoints[2]-1]; + xinterp[3]=lon_mappingpoint[mappedforcingpoints[3]-1]; + yinterp[0]=lat_mappingpoint[mappedforcingpoints[0]-1]; + yinterp[1]=lat_mappingpoint[mappedforcingpoints[1]-1]; + yinterp[2]=lat_mappingpoint[mappedforcingpoints[2]-1]; + yinterp[3]=lat_mappingpoint[mappedforcingpoints[3]-1]; + + if (ismappingneighborxy){ + lat = yelem[0]; + lon = xelem[0]; + } + else{ + if(xinterp[0]>180) xinterp[0]=xinterp[0]-360; + if(xinterp[1]>180) xinterp[1]=xinterp[1]-360; + if(xinterp[2]>180) xinterp[2]=xinterp[2]-360; + if(xinterp[3]>180) xinterp[3]=xinterp[3]-360; + + int latlon = 0; + int signlat = 1; + if (yinterp[0]<0) signlat = -1; + latlon = Xy2llx(latelem, lonelem, xelem, yelem, 1, signlat); _assert_(latlon>0); + lat = latelem[0]; + lon = lonelem[0]; + if(lon>180) lon=lon-360; + } + + minx=fmin(fmin(xinterp[0],xinterp[1]),fmin(xinterp[2],xinterp[3])); + maxx=fmax(fmax(xinterp[0],xinterp[1]),fmax(xinterp[2],xinterp[3])); + miny=fmin(fmin(yinterp[0],yinterp[1]),fmin(yinterp[2],yinterp[3])); + maxy=fmax(fmax(yinterp[0],yinterp[1]),fmax(yinterp[2],yinterp[3])); + + for(int ni=0;ni<=N2;ni++) { + if(minx==xinterp[ni] && miny==yinterp[ni]) mpQ11=mappedforcingpoints[ni]; + else if(minx==xinterp[ni] && maxy==yinterp[ni]) mpQ12=mappedforcingpoints[ni]; + else if(maxx==xinterp[ni] && miny==yinterp[ni]) mpQ21=mappedforcingpoints[ni]; + else if(maxx==xinterp[ni] && maxy==yinterp[ni]) mpQ22=mappedforcingpoints[ni]; + else _error_("Gemb mapping neighbor points were not assignee properly. Check that they represent a uniform grid box of lat/lon."); + } + + //Calculate Q order and set in Qinterp for this element, set mpQ12, mpQ21, mpQ11, mpQ22 locally + Tmean=bilinearinterp(minx, maxx, miny, maxy, tmeane[mpQ11-1], tmeane[mpQ12-1], tmeane[mpQ21-1], tmeane[mpQ22-1], lon, lat); + Vmean=bilinearinterp(minx, maxx, miny, maxy, vmeane[mpQ11-1], vmeane[mpQ12-1], vmeane[mpQ21-1], vmeane[mpQ22-1], lon, lat); + C=bilinearinterp(minx, maxx, miny, maxy, cmeane[mpQ11-1], cmeane[mpQ12-1], cmeane[mpQ21-1], cmeane[mpQ22-1], lon, lat); + + //Set these all as element inputs + Qinterp[0]=mpQ11; + Qinterp[1]=mpQ12; + Qinterp[2]=mpQ21; + Qinterp[3]=mpQ22; + + this->SetElementInput(SmbTmeanEnum,Tmean); + this->SetElementInput(SmbVmeanEnum,Vmean); + this->SetElementInput(SmbCEnum,C); + + this->SetElementInput(SmbMinXEnum,minx); + this->SetElementInput(SmbMaxXEnum,maxx); + this->SetElementInput(SmbMinYEnum,miny); + this->SetElementInput(SmbMaxYEnum,maxy); + this->SetElementInput(SmbLatEnum,lat); + this->SetElementInput(SmbLonEnum,lon); + this->inputs->SetIntArrayInput(SmbQinterpEnum,this->lid,Qinterp,4); + xDelete(xyz_list); + xDelete(xinterp); + xDelete(yinterp); + xDelete(mappedforcingpoints); + xDelete(xelem); + xDelete(yelem); + xDelete(latelem); + xDelete(lonelem); + xDelete(lat_mappingpoint); + xDelete(lon_mappingpoint); + xDelete(mappedforcingneighbors); + + } else { + // Get Qinterp for this element, set Q12, Q21, Q11, Q22 locally + this->inputs->GetIntArray(SmbQinterpEnum,this->lid,&Qinterp,&N); + mpQ11=Qinterp[0]; + mpQ12=Qinterp[1]; + mpQ21=Qinterp[2]; + mpQ22=Qinterp[3]; + + // Get input values for this location already calculated before + Input *MinX_input = this->GetInput(SmbMinXEnum); _assert_(MinX_input); + Input *MinY_input = this->GetInput(SmbMinYEnum); _assert_(MinY_input); + Input *MaxX_input = this->GetInput(SmbMaxXEnum); _assert_(MaxX_input); + Input *MaxY_input = this->GetInput(SmbMaxYEnum); _assert_(MaxY_input); + + MinX_input->GetInputAverage(&minx); + MinY_input->GetInputAverage(&miny); + MaxX_input->GetInputAverage(&maxx); + MaxY_input->GetInputAverage(&maxy); + + Input *Lat_input = this->GetInput(SmbLatEnum); _assert_(Lat_input); + Input *Lon_input = this->GetInput(SmbLonEnum); _assert_(Lon_input); + + Lat_input->GetInputAverage(&lat); + Lon_input->GetInputAverage(&lon); + + // Get input values for this location already calculated before + Input *Tmean_input = this->GetInput(SmbTmeanEnum); _assert_(Tmean_input); + Input *Vmean_input = this->GetInput(SmbVmeanEnum); _assert_(Vmean_input); + Input *C_input = this->GetInput(SmbCEnum); _assert_(C_input); + + Tmean_input->GetInputAverage(&Tmean); + Vmean_input->GetInputAverage(&Vmean); + C_input->GetInputAverage(&C); + } + + } else { + + Tmean = tmeane[Mappedpoint-1]; + Vmean = vmeane[Mappedpoint-1]; + C = cmeane[Mappedpoint-1]; + + } + xDelete(tzval); xDelete(vzval); + xDelete(tmeane); + xDelete(vmeane); + xDelete(cmeane); + } /*}}}*/ @@ -5872,6 +6038,8 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ bool isprecipmap=true; parameters->FindParam(&isprecipmap,SmbIsprecipforcingremappedEnum); + IssmDouble tlapsem, dlwlapsem, elevationm; + IssmDouble* tlapse = NULL; parameters->FindParam(&tlapse,&N,SmbLapseTaValueEnum); _assert_(tlapse); @@ -5882,22 +6050,83 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ parameters->FindParam(&elevation,&N,SmbMappedforcingelevationEnum); _assert_(elevation); //Variables for downscaling - IssmDouble taparam, dlwrfparam, rhparam, eaparam, pparam, prparam; - parameters->FindParam(&taparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbTaParamEnum); - parameters->FindParam(&dlwrfparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbDlwrfParamEnum); - parameters->FindParam(&eaparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbEAirParamEnum); - parameters->FindParam(&pparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbPAirParamEnum); - parameters->FindParam(&prparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbPParamEnum); - - //Variables not downscaled - parameters->FindParam(&V, Mappedpoint-1, timeinputs, timestepping, dt, SmbVParamEnum); - parameters->FindParam(&dsw, Mappedpoint-1, timeinputs, timestepping, dt, SmbDswrfParamEnum); - parameters->FindParam(&dswdiff, Mappedpoint-1, timeinputs, timestepping, dt, SmbDswdiffrfParamEnum); - - Ta = taparam + (currentsurface - elevation[Mappedpoint-1])*tlapse[Mappedpoint-1]; - Tmean = Tmean + (currentsurface - elevation[Mappedpoint-1])*tlapse[Mappedpoint-1]; - if (fabs(dlwlapse[Mappedpoint-1]) > Dtol){ - dlw = fmax(dlwrfparam + (currentsurface - elevation[Mappedpoint-1])*dlwlapse[Mappedpoint-1],0.0); + IssmDouble taparam, dlwrfparam, rhparam, eaparam, pparam, prparam, Q11param, Q12param, Q21param, Q22param; + if (ismappingusingneighbors){ + + //Calculate interpolated fields + tlapsem=bilinearinterp(minx, maxx, miny, maxy, tlapse[mpQ11-1], tlapse[mpQ12-1], tlapse[mpQ21-1], tlapse[mpQ22-1], lon, lat); + dlwlapsem=bilinearinterp(minx, maxx, miny, maxy, dlwlapse[mpQ11-1], dlwlapse[mpQ12-1], dlwlapse[mpQ21-1], dlwlapse[mpQ22-1], lon, lat); + elevationm=bilinearinterp(minx, maxx, miny, maxy, elevation[mpQ11-1], elevation[mpQ12-1], elevation[mpQ21-1], elevation[mpQ22-1], lon, lat); + + parameters->FindParam(&Q11param, mpQ11-1, timeinputs, timestepping, dt, SmbTaParamEnum); + parameters->FindParam(&Q12param, mpQ12-1, timeinputs, timestepping, dt, SmbTaParamEnum); + parameters->FindParam(&Q21param, mpQ21-1, timeinputs, timestepping, dt, SmbTaParamEnum); + parameters->FindParam(&Q22param, mpQ22-1, timeinputs, timestepping, dt, SmbTaParamEnum); + taparam=bilinearinterp(minx, maxx, miny, maxy, Q11param, Q12param, Q21param, Q22param, lon, lat); + + parameters->FindParam(&Q11param, mpQ11-1, timeinputs, timestepping, dt, SmbDlwrfParamEnum); + parameters->FindParam(&Q12param, mpQ12-1, timeinputs, timestepping, dt, SmbDlwrfParamEnum); + parameters->FindParam(&Q21param, mpQ21-1, timeinputs, timestepping, dt, SmbDlwrfParamEnum); + parameters->FindParam(&Q22param, mpQ22-1, timeinputs, timestepping, dt, SmbDlwrfParamEnum); + dlwrfparam=bilinearinterp(minx, maxx, miny, maxy, Q11param, Q12param, Q21param, Q22param, lon, lat); + + parameters->FindParam(&Q11param, mpQ11-1, timeinputs, timestepping, dt, SmbEAirParamEnum); + parameters->FindParam(&Q12param, mpQ12-1, timeinputs, timestepping, dt, SmbEAirParamEnum); + parameters->FindParam(&Q21param, mpQ21-1, timeinputs, timestepping, dt, SmbEAirParamEnum); + parameters->FindParam(&Q22param, mpQ22-1, timeinputs, timestepping, dt, SmbEAirParamEnum); + eaparam=bilinearinterp(minx, maxx, miny, maxy, Q11param, Q12param, Q21param, Q22param, lon, lat); + + parameters->FindParam(&Q11param, mpQ11-1, timeinputs, timestepping, dt, SmbPAirParamEnum); + parameters->FindParam(&Q12param, mpQ12-1, timeinputs, timestepping, dt, SmbPAirParamEnum); + parameters->FindParam(&Q21param, mpQ21-1, timeinputs, timestepping, dt, SmbPAirParamEnum); + parameters->FindParam(&Q22param, mpQ22-1, timeinputs, timestepping, dt, SmbPAirParamEnum); + pparam=bilinearinterp(minx, maxx, miny, maxy, Q11param, Q12param, Q21param, Q22param, lon, lat); + + parameters->FindParam(&Q11param, mpQ11-1, timeinputs, timestepping, dt, SmbPParamEnum); + parameters->FindParam(&Q12param, mpQ12-1, timeinputs, timestepping, dt, SmbPParamEnum); + parameters->FindParam(&Q21param, mpQ21-1, timeinputs, timestepping, dt, SmbPParamEnum); + parameters->FindParam(&Q22param, mpQ22-1, timeinputs, timestepping, dt, SmbPParamEnum); + prparam=bilinearinterp(minx, maxx, miny, maxy, Q11param, Q12param, Q21param, Q22param, lon, lat); + + parameters->FindParam(&Q11param, mpQ11-1, timeinputs, timestepping, dt, SmbVParamEnum); + parameters->FindParam(&Q12param, mpQ12-1, timeinputs, timestepping, dt, SmbVParamEnum); + parameters->FindParam(&Q21param, mpQ21-1, timeinputs, timestepping, dt, SmbVParamEnum); + parameters->FindParam(&Q22param, mpQ22-1, timeinputs, timestepping, dt, SmbVParamEnum); + V=bilinearinterp(minx, maxx, miny, maxy, Q11param, Q12param, Q21param, Q22param, lon, lat); + + parameters->FindParam(&Q11param, mpQ11-1, timeinputs, timestepping, dt, SmbDswrfParamEnum); + parameters->FindParam(&Q12param, mpQ12-1, timeinputs, timestepping, dt, SmbDswrfParamEnum); + parameters->FindParam(&Q21param, mpQ21-1, timeinputs, timestepping, dt, SmbDswrfParamEnum); + parameters->FindParam(&Q22param, mpQ22-1, timeinputs, timestepping, dt, SmbDswrfParamEnum); + dsw=bilinearinterp(minx, maxx, miny, maxy, Q11param, Q12param, Q21param, Q22param, lon, lat); + + parameters->FindParam(&Q11param, mpQ11-1, timeinputs, timestepping, dt, SmbDswdiffrfParamEnum); + parameters->FindParam(&Q12param, mpQ12-1, timeinputs, timestepping, dt, SmbDswdiffrfParamEnum); + parameters->FindParam(&Q21param, mpQ21-1, timeinputs, timestepping, dt, SmbDswdiffrfParamEnum); + parameters->FindParam(&Q22param, mpQ22-1, timeinputs, timestepping, dt, SmbDswdiffrfParamEnum); + dswdiff=bilinearinterp(minx, maxx, miny, maxy, Q11param, Q12param, Q21param, Q22param, lon, lat); + + } else { + tlapsem=tlapse[Mappedpoint-1]; + dlwlapsem=dlwlapse[Mappedpoint-1]; + elevationm=elevation[Mappedpoint-1]; + + parameters->FindParam(&taparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbTaParamEnum); + parameters->FindParam(&dlwrfparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbDlwrfParamEnum); + parameters->FindParam(&eaparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbEAirParamEnum); + parameters->FindParam(&pparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbPAirParamEnum); + parameters->FindParam(&prparam, Mappedpoint-1, timeinputs, timestepping, dt, SmbPParamEnum); + + //Variables not downscaled + parameters->FindParam(&V, Mappedpoint-1, timeinputs, timestepping, dt, SmbVParamEnum); + parameters->FindParam(&dsw, Mappedpoint-1, timeinputs, timestepping, dt, SmbDswrfParamEnum); + parameters->FindParam(&dswdiff, Mappedpoint-1, timeinputs, timestepping, dt, SmbDswdiffrfParamEnum); + } + + Ta = taparam + (currentsurface - elevationm)*tlapsem; + Tmean = Tmean + (currentsurface - elevationm)*tlapsem; + if (fabs(dlwlapsem) > Dtol){ + dlw = fmax(dlwrfparam + (currentsurface - elevationm)*dlwlapsem,0.0); }else{ //adjust downward longwave, holding emissivity equal (Glover et al, 1999) IssmDouble SB = 5.67e-8; // Stefan-Boltzmann constant (W m-2 K-4) @@ -5906,23 +6135,23 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ dlw = fmax(effe*SB*pow(Ta,4.0),0.0); } - if ( (fabs(dlwlapse[Mappedpoint-1]) > Dtol) || (fabs(tlapse[Mappedpoint-1]) > Dtol)){ + if ( (fabs(dlwlapsem) > Dtol) || (fabs(tlapsem) > Dtol)){ + // IssmDouble pscale = -8400; + // pAir=pparam*exp((currentsurface - elevationm)/pscale); IssmDouble Rg = 8.314; // gas constant (J mol-1 K-1) IssmDouble dAir = 0.0; // calculated air density [kg/m3] // dAir = 0.029 * pAir /(R * Ta); - dAir=0.029 * pparam /(Rg * Ta); - pAir=pparam-gravity*dAir*(currentsurface - elevation[Mappedpoint-1]); + dAir=0.029 * pparam /(Rg * taparam); + pAir=pparam-gravity*dAir*(currentsurface - elevationm); } else pAir=pparam; - //Hold relative humidity constant, calculte new saturation vapor pressure, - // and new saturation specific humidity to scale precipitation + //Hold relative humidity constant and calculte new saturation vapor pressure //https://cran.r-project.org/web/packages/humidity/vignettes/humidity-measures.html //es over ice calculation //Ding et al., 2019 after Bolton, 1980 //ea37 = rh37*100*6.112.*exp((17.67*(t237-273.15))./(t237-29.65)); - //ea37s (hPa) = 6.1121*exp(22.587*(t-273.15)/(t-273.15+273.86)); (with respect to ice) IssmDouble esparam, es, qsparam, qs; esparam=6.112*exp((17.67*(taparam-273.15))/(taparam-29.65)); es=6.112*exp((17.67*(Ta-273.15))/(Ta-29.65)); @@ -5931,7 +6160,7 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ qs=fmax(0.622*es/(pAir/100 - 0.378*es),0); qsparam=fmax(0.622*esparam/(pparam/100 - 0.378*esparam),0); - if ((isprecipmap) && (qsparam>0)){ + if ((isprecipmap) && (qsparam>0)){ IssmDouble precipscaling = 1.0; Input *pscaling_input = NULL; pscaling_input = this->GetInput(SmbMappedforcingprecipscalingEnum); _assert_(pscaling_input); @@ -5964,7 +6193,7 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ if (m>1) T[1]=Ta; } /*Thermal profile computation:*/ - if(isthermal)thermo(&shf, &lhf, &EC, &T, &ulw, re, dz, d, swf, dlw, Ta, V, eAir, pAir, tcIdx, eIdx, teValue, dulwrfValue, teThresh, W[0], smb_dt, dzMin, m, Vz, Tz, thermo_scaling,rho_ice,this->Sid(),isconstrainsurfaceT,isdeltaLWup); + if(isthermal)thermo(&shf, &lhf, &EC, &T, &ulw, re, dz, d, swf, dlw, Ta, V, eAir, pAir, tcIdx, eIdx, teValue, teDefault, dulwrfValue, teThresh, W[0], smb_dt, dzMin, m, Vz, Tz, thermo_scaling,rho_ice,this->Sid(),isconstrainsurfaceT,isdeltaLWup); /*Change in thickness of top cell due to evaporation/condensation assuming same density as top cell. * need to fix this in case all or more of cell evaporates */ @@ -6185,6 +6414,8 @@ void Element::SmbGemb(IssmDouble timeinputs, int count, int steps){/*{{{*/ if(Radsub) xDelete(Radsub); if(Pdsub) xDelete(Pdsub); + if(Qinterp) xDelete(Qinterp); + delete gauss; /*}}}*/ } diff --git a/src/c/classes/Elements/Element.h b/src/c/classes/Elements/Element.h index 2507d72d9..9adca52a5 100644 --- a/src/c/classes/Elements/Element.h +++ b/src/c/classes/Elements/Element.h @@ -323,7 +323,6 @@ class Element: public Object{ virtual void InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type)=0; virtual void InputScaleFromDakota(IssmDouble* distributed_values, IssmDouble* partition, int npart, int nt, int name)=0; #endif - virtual void InputUpdateFromIoModel(int index, IoModel* iomodel)=0; virtual void InputUpdateFromVector(IssmDouble* vector, int name, int type)=0; virtual bool IsFaceOnBoundary(void)=0; virtual bool IsIcefront(void)=0; diff --git a/src/c/classes/Elements/Penta.cpp b/src/c/classes/Elements/Penta.cpp index 26cc2b4fa..e8ebec508 100644 --- a/src/c/classes/Elements/Penta.cpp +++ b/src/c/classes/Elements/Penta.cpp @@ -2444,9 +2444,6 @@ void Penta::ControlInputExtrude(int enum_type,int start){/*{{{*/ ElementInput* input = this->inputs->GetControlInputData(enum_type,"value"); if(input->ObjectEnum()!=PentaInputEnum) _error_("not supported yet"); PentaInput* pentainput = xDynamicCast(input); - ElementInput* input2 = this->inputs->GetControlInputData(enum_type,"savedvalues"); - if(input->ObjectEnum()!=PentaInputEnum) _error_("not supported yet"); - PentaInput* pentainput2= xDynamicCast(input2); /*FIXME: this should not be necessary*/ ElementInput* input3 = this->inputs->GetControlInputData(enum_type,"gradient"); if(input->ObjectEnum()!=PentaInputEnum) _error_("not supported yet"); @@ -2455,29 +2452,24 @@ void Penta::ControlInputExtrude(int enum_type,int start){/*{{{*/ int lidlist[NUMVERTICES]; this->GetVerticesLidList(&lidlist[0]); pentainput->Serve(NUMVERTICES,&lidlist[0]); - pentainput2->Serve(NUMVERTICES,&lidlist[0]); pentainput3->Serve(NUMVERTICES,&lidlist[0]); if(pentainput->GetInterpolation()==P1Enum){ /*Extrude values first*/ IssmDouble extrudedvalues[NUMVERTICES]; - IssmDouble extrudedvalues2[NUMVERTICES]; IssmDouble extrudedvalues3[NUMVERTICES]; this->GetInputListOnVertices(&extrudedvalues[0],pentainput,0.); - this->GetInputListOnVertices(&extrudedvalues2[0],pentainput2,0.); this->GetInputListOnVertices(&extrudedvalues3[0],pentainput3,0.); if(start==-1){ for(int i=0;iGetVerticesLidList(&vertexlids[0]); pentainput->SetInput(P1Enum,NUMVERTICES,&vertexlids[0],&extrudedvalues[0]); - pentainput2->SetInput(P1Enum,NUMVERTICES,&vertexlids[0],&extrudedvalues2[0]); if(start==-1 && !penta->IsOnBase()){ pentainput3->SetInput(P1Enum,NUMVERTICES,&vertexlids[0],&extrudedvalues3[0]); } @@ -2560,33 +2551,6 @@ void Penta::InputExtrude(int enum_type,int start){/*{{{*/ } } /*}}}*/ -void Penta::InputUpdateFromIoModel(int index,IoModel* iomodel){ /*{{{*/ - - /*Intermediaries*/ - int i,j; - int penta_vertex_ids[NUMVERTICES]; - IssmDouble nodeinputs[NUMVERTICES]; - IssmDouble cmmininputs[NUMVERTICES]; - IssmDouble cmmaxinputs[NUMVERTICES]; - - IssmDouble yts; - bool control_analysis; - char** controls = NULL; - int num_control_type,num_responses; - - /*Fetch parameters: */ - iomodel->FindConstant(&yts,"md.constants.yts"); - iomodel->FindConstant(&control_analysis,"md.inversion.iscontrol"); - if(control_analysis) iomodel->FindConstant(&num_control_type,"md.inversion.num_control_parameters"); - if(control_analysis) iomodel->FindConstant(&num_responses,"md.inversion.num_cost_functions"); - - /*Recover vertices ids needed to initialize inputs*/ - _assert_(iomodel->elements); - for(i=0;ielements[NUMVERTICES*index+i]; //ids for vertices are in the elements array from Matlab - } -} -/*}}}*/ void Penta::InputUpdateFromSolutionOneDof(IssmDouble* solution,int enum_type){/*{{{*/ /*Intermediary*/ diff --git a/src/c/classes/Elements/Penta.h b/src/c/classes/Elements/Penta.h index 3b0976692..1211822e7 100644 --- a/src/c/classes/Elements/Penta.h +++ b/src/c/classes/Elements/Penta.h @@ -121,7 +121,6 @@ class Penta: public Element,public ElementHook,public PentaRef{ IssmDouble IceVolumeAboveFloatation(bool scaled); void InputDepthAverageAtBase(int enum_type,int average_enum_type); void InputExtrude(int enum_type,int start); - void InputUpdateFromIoModel(int index, IoModel* iomodel); void InputUpdateFromSolutionOneDof(IssmDouble* solutiong,int enum_type); void InputUpdateFromSolutionOneDofCollapsed(IssmDouble* solutiong,int enum_type); void InputUpdateFromVector(IssmDouble* vector, int name, int type); diff --git a/src/c/classes/Elements/Seg.h b/src/c/classes/Elements/Seg.h index 2cb305628..1d4899624 100644 --- a/src/c/classes/Elements/Seg.h +++ b/src/c/classes/Elements/Seg.h @@ -88,7 +88,6 @@ class Seg: public Element,public ElementHook,public SegRef{ IssmDouble IceVolumeAboveFloatation(bool scaled){_error_("not implemented yet");}; void InputDepthAverageAtBase(int enum_type,int average_enum_type){_error_("not implemented yet");}; void InputExtrude(int enum_type,int start){_error_("not implemented"); /*For penta only*/}; - void InputUpdateFromIoModel(int index, IoModel* iomodel){_error_("not implemented yet");}; void InputUpdateFromSolutionOneDof(IssmDouble* solution,int inputenum){_error_("not implemented yet");}; void InputUpdateFromSolutionOneDofCollapsed(IssmDouble* solution,int inputenum){_error_("not implemented yet");}; void InputUpdateFromVector(IssmDouble* vector, int name, int type){_error_("not implemented yet");}; diff --git a/src/c/classes/Elements/Tetra.cpp b/src/c/classes/Elements/Tetra.cpp index 138c23062..5187c1cf2 100644 --- a/src/c/classes/Elements/Tetra.cpp +++ b/src/c/classes/Elements/Tetra.cpp @@ -396,33 +396,6 @@ bool Tetra::HasFaceOnSurface(){/*{{{*/ } } /*}}}*/ -void Tetra::InputUpdateFromIoModel(int index,IoModel* iomodel){ /*{{{*/ - - /*Intermediaries*/ - int i,j; - int tetra_vertex_ids[NUMVERTICES]; - IssmDouble nodeinputs[NUMVERTICES]; - IssmDouble cmmininputs[NUMVERTICES]; - IssmDouble cmmaxinputs[NUMVERTICES]; - - IssmDouble yts; - bool control_analysis; - char** controls = NULL; - int num_control_type,num_responses; - - /*Fetch parameters: */ - iomodel->FindConstant(&yts,"md.constants.yts"); - iomodel->FindConstant(&control_analysis,"md.inversion.iscontrol"); - if(control_analysis) iomodel->FindConstant(&num_control_type,"md.inversion.num_control_parameters"); - if(control_analysis) iomodel->FindConstant(&num_responses,"md.inversion.num_cost_functions"); - - /*Recover vertices ids needed to initialize inputs*/ - _assert_(iomodel->elements); - for(i=0;ielements[NUMVERTICES*index+i]; //ids for vertices are in the elements array from Matlab - } -} -/*}}}*/ void Tetra::InputUpdateFromSolutionOneDof(IssmDouble* solution,int enum_type){/*{{{*/ /*Intermediary*/ @@ -888,9 +861,6 @@ void Tetra::Update(Inputs* inputs,int index,IoModel* iomodel,int analysis_co /*hooks: */ this->SetHookNodes(tetra_node_ids,numnodes,analysis_counter); this->nodes=NULL; xDelete(tetra_node_ids); - - /*Fill with IoModel*/ - this->InputUpdateFromIoModel(index,iomodel); } /*}}}*/ void Tetra::ValueP1OnGauss(IssmDouble* pvalue,IssmDouble* values,Gauss* gauss){/*{{{*/ diff --git a/src/c/classes/Elements/Tetra.h b/src/c/classes/Elements/Tetra.h index 8090686f8..074efe755 100644 --- a/src/c/classes/Elements/Tetra.h +++ b/src/c/classes/Elements/Tetra.h @@ -99,7 +99,6 @@ class Tetra: public Element,public ElementHook,public TetraRef{ bool IsZeroLevelset(int levelset_enum){_error_("not implemented");}; void InputDepthAverageAtBase(int enum_type,int average_enum_type){_error_("not implemented yet");}; void InputExtrude(int enum_type,int start){_error_("not implemented"); /*For penta only*/}; - void InputUpdateFromIoModel(int index, IoModel* iomodel); void InputUpdateFromSolutionOneDof(IssmDouble* solution,int inputenum); void InputUpdateFromSolutionOneDofCollapsed(IssmDouble* solution,int inputenum){_error_("not implemented yet");}; void InputUpdateFromVector(IssmDouble* vector, int name, int type){_error_("not implemented yet");}; diff --git a/src/c/classes/Elements/Tria.cpp b/src/c/classes/Elements/Tria.cpp index 0fd8272fd..51f4b3268 100644 --- a/src/c/classes/Elements/Tria.cpp +++ b/src/c/classes/Elements/Tria.cpp @@ -4311,34 +4311,6 @@ void Tria::InputDepthAverageAtBase(int enum_type,int average_enum_type){/* _error_("not implemented"); } /*}}}*/ -void Tria::InputUpdateFromIoModel(int index, IoModel* iomodel){ //i is the element index/*{{{*/ - - /*Intermediaries*/ - int i,j; - int tria_vertex_ids[3]; - IssmDouble nodeinputs[3]; - IssmDouble cmmininputs[3]; - IssmDouble cmmaxinputs[3]; - bool control_analysis,ad_analysis = false; - int num_control_type,num_responses; - char** controls = NULL; - IssmDouble yts; - - /*Get parameters: */ - iomodel->FindConstant(&yts,"md.constants.yts"); - iomodel->FindConstant(&control_analysis,"md.inversion.iscontrol"); - iomodel->FindConstant(&ad_analysis, "md.autodiff.isautodiff"); - if(control_analysis && !ad_analysis) iomodel->FindConstant(&num_control_type,"md.inversion.num_control_parameters"); - if(control_analysis && !ad_analysis) iomodel->FindConstant(&num_responses,"md.inversion.num_cost_functions"); - if(control_analysis && ad_analysis) iomodel->FindConstant(&num_control_type,"md.autodiff.num_independent_objects"); - if(control_analysis && ad_analysis) iomodel->FindConstant(&num_responses,"md.autodiff.num_dependent_objects"); - - /*Recover vertices ids needed to initialize inputs*/ - for(i=0;i<3;i++){ - tria_vertex_ids[i]=reCast(iomodel->elements[3*index+i]); //ids for vertices are in the elements array from Matlab - } -} -/*}}}*/ void Tria::InputUpdateFromSolutionOneDof(IssmDouble* solution,int enum_type){/*{{{*/ /*Intermediary*/ @@ -7108,6 +7080,7 @@ void Tria::SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, IssmDouble timeacc=0.; IssmDouble start_time,final_time; int nt,precomputednt; + int viscousnumsteps=1; int grd, grdmodel; /*Rotational:*/ @@ -7194,6 +7167,7 @@ void Tria::SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, this->parameters->FindParam(&timeacc,SolidearthSettingsTimeAccEnum); this->parameters->FindParam(&start_time,TimesteppingStartTimeEnum); this->parameters->FindParam(&final_time,TimesteppingFinalTimeEnum); + this->parameters->FindParam(&viscousnumsteps,SealevelchangeViscousNumStepsEnum); nt=reCast((final_time-start_time)/timeacc)+1; } else{ @@ -7250,22 +7224,24 @@ void Tria::SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, /*}}}*/ /*Compute rotation kernel:{{{*/ if(computerotation){ + int ntrot = computeviscous ? viscousnumsteps : nt; + //initialization - LoveRotRSL = xNewZeroInit(nt); - LoveRotU = xNewZeroInit(nt); - if(horiz)LoveRothoriz= xNewZeroInit(nt); - Grot = xNewZeroInit(3*3*nt); //3 polar motion components * 3 vertices * number of time steps - GUrot = xNewZeroInit(3*3*nt); + LoveRotRSL = xNewZeroInit(ntrot); + LoveRotU = xNewZeroInit(ntrot); + if(horiz)LoveRothoriz= xNewZeroInit(ntrot); + Grot = xNewZeroInit(3*3*ntrot); //3 polar motion components * 3 vertices * number of time steps + GUrot = xNewZeroInit(3*3*ntrot); if (horiz){ - GErot=xNewZeroInit(3*3*nt); - GNrot=xNewZeroInit(3*3*nt); + GErot=xNewZeroInit(3*3*ntrot); + GNrot=xNewZeroInit(3*3*ntrot); } /*What is the gravity at planet's surface: */ g=4.0/3.0*M_PI*rho_earth*NewtonG*planetradius; cent_scaling=pow(omega*planetradius,2.0); //centrifugal potential dimensioning constant - for(int t=0;tinputs->SetArrayInput(SealevelchangeGrotEnum,this->lid,Grot,3*3*nt); + this->inputs->SetArrayInput(SealevelchangeGrotEnum,this->lid,Grot,3*3*ntrot); if (computeelastic){ - this->inputs->SetArrayInput(SealevelchangeGUrotEnum,this->lid,GUrot,3*3*nt); + this->inputs->SetArrayInput(SealevelchangeGUrotEnum,this->lid,GUrot,3*3*ntrot); if(horiz){ - this->inputs->SetArrayInput(SealevelchangeGNrotEnum,this->lid,GNrot,3*3*nt); - this->inputs->SetArrayInput(SealevelchangeGErotEnum,this->lid,GErot,3*3*nt); + this->inputs->SetArrayInput(SealevelchangeGNrotEnum,this->lid,GNrot,3*3*ntrot); + this->inputs->SetArrayInput(SealevelchangeGErotEnum,this->lid,GErot,3*3*ntrot); } } /*Free resources:*/ @@ -7347,17 +7323,17 @@ void Tria::SealevelchangeGeometryInitial(IssmDouble* xxe, IssmDouble* yye, /*}}}*/ /*Initialize viscous stacks: {{{*/ if(computeviscous){ - viscousRSL=xNewZeroInit(3*nt); - viscousU=xNewZeroInit(3*nt); + viscousRSL=xNewZeroInit(3*viscousnumsteps); + viscousU=xNewZeroInit(3*viscousnumsteps); - this->inputs->SetArrayInput(SealevelchangeViscousRSLEnum,this->lid,viscousRSL,3*nt); - this->inputs->SetArrayInput(SealevelchangeViscousUEnum,this->lid,viscousU,3*nt); + this->inputs->SetArrayInput(SealevelchangeViscousRSLEnum,this->lid,viscousRSL,3*viscousnumsteps); + this->inputs->SetArrayInput(SealevelchangeViscousUEnum,this->lid,viscousU,3*viscousnumsteps); this->parameters->SetParam(0,SealevelchangeViscousIndexEnum); if(horiz){ - viscousN=xNewZeroInit(3*nt); - viscousE=xNewZeroInit(3*nt); - this->inputs->SetArrayInput(SealevelchangeViscousNEnum,this->lid,viscousN,3*nt); - this->inputs->SetArrayInput(SealevelchangeViscousEEnum,this->lid,viscousE,3*nt); + viscousN=xNewZeroInit(3*viscousnumsteps); + viscousE=xNewZeroInit(3*viscousnumsteps); + this->inputs->SetArrayInput(SealevelchangeViscousNEnum,this->lid,viscousN,3*viscousnumsteps); + this->inputs->SetArrayInput(SealevelchangeViscousEEnum,this->lid,viscousE,3*viscousnumsteps); } } /*}}}*/ @@ -8146,7 +8122,7 @@ IssmDouble* Tria::SealevelchangeGxL(IssmDouble* G, IssmDouble* Grot, GrdLo int* AlphaIndexsub[SLGEOM_NUMLOADS]; int* activevertices=NULL; IssmDouble* grdfield=NULL; - int i,e,l,t,a, index, nbar, size, av,ae,b,c; + int i,e,l,t,it,a, index, nbar, size, av,ae,b,c; bool rotation=false; int nt=1; //important, ensures there is a defined value if computeviscous is false int n_activevertices=0; @@ -8155,6 +8131,10 @@ IssmDouble* Tria::SealevelchangeGxL(IssmDouble* G, IssmDouble* Grot, GrdLo bool computeviscous=false; int viscousindex=0; //important int viscousnumsteps=1; //important + int viscoussamplinglength=1; + int* viscoussamplingindex=NULL; + IssmDouble* viscoustimes=NULL; + IssmDouble final_time; this->parameters->FindParam(&computeviscous,SolidearthSettingsViscousEnum); this->parameters->FindParam(&rotation,SolidearthSettingsRotationEnum); @@ -8167,17 +8147,31 @@ IssmDouble* Tria::SealevelchangeGxL(IssmDouble* G, IssmDouble* Grot, GrdLo if(computeviscous){ this->parameters->FindParam(&viscousnumsteps,SealevelchangeViscousNumStepsEnum); this->parameters->FindParam(&viscousindex,SealevelchangeViscousIndexEnum); + this->parameters->FindParam(&viscoussamplinglength,SealevelchangeViscousSamplingLengthEnum); + this->parameters->FindParam(&viscoussamplingindex,NULL,SealevelchangeViscousSamplingIndexEnum); if(computefuture) { - nt=viscousnumsteps-viscousindex+2; //number of time steps remaining to reach final_time, +1 is sufficient with no adaptative time stepping, +2 necessary otherwise; we assume the safe choice here for the sake of simplicity - if (nt>viscousnumsteps) nt=viscousnumsteps; + this->parameters->FindParam(&viscoustimes,NULL,SealevelchangeViscousTimesEnum); + this->parameters->FindParam(&final_time,TimesteppingFinalTimeEnum); + nt=1; + while (nt(1); + } + //allocate grdfield=xNewZeroInit(3*nt); //early return - if (n_activevertices==0) return grdfield; + if (n_activevertices==0){ + xDelete(viscoussamplingindex); + if(computeviscous){ + if(computefuture) xDelete(viscoustimes); + } + return grdfield; + } if(rotation){ //add rotational feedback for(av=0;avlids[this->vertices[i]->lid]!=this->lid)continue; b=i*nt; for (int m=0;m<3;m++){ //polar motion components - for(t=0;tnactiveloads;ae++){ e=loads->combined_loads_index[ae]; a=AlphaIndex[c+e]*viscousnumsteps; - for(t=0;tcombined_loads[ae]; + for(it=0;itcombined_loads[ae]; } } for(l=0;lnactivesubloads[l];ae++){ e=loads->combined_subloads_index[l][ae]; a=AlphaIndexsub[l][c+e]*viscousnumsteps; - for(t=0;tcombined_subloads[l][ae]; + for(it=0;itcombined_subloads[l][ae]; } } } //av+=1; } /*}}}*/ + xDelete(viscoussamplingindex); + if(computeviscous){ + if(computefuture) xDelete(viscoustimes); + } + return grdfield; } /*}}}*/ @@ -8232,7 +8234,7 @@ IssmDouble* Tria::SealevelchangeHorizGxL(int spatial_component, IssmDouble int* AzimIndexsub[SLGEOM_NUMLOADS]; int* activevertices = NULL; IssmDouble* grdfield=NULL; - int i,e,l,t,a,b,c, index, nbar, av, ae,n_activevertices, size; + int i,e,l,t,it,a,b,c, index, nbar, av, ae,n_activevertices, size; bool rotation=false; IssmDouble* projected_loads=NULL; IssmDouble* projected_subloads[SLGEOM_NUMLOADS]; @@ -8244,6 +8246,10 @@ IssmDouble* Tria::SealevelchangeHorizGxL(int spatial_component, IssmDouble bool computeviscous=false; int viscousindex=0; //important int viscousnumsteps=1; //important + int viscoussamplinglength=1; + int* viscoussamplingindex=NULL; + IssmDouble* viscoustimes=NULL; + IssmDouble final_time; //Get green functions indexing & geometry this->inputs->GetIntArrayPtr(SealevelchangeConvolutionVerticesEnum,this->lid,&activevertices,&n_activevertices); @@ -8258,24 +8264,38 @@ IssmDouble* Tria::SealevelchangeHorizGxL(int spatial_component, IssmDouble if(computeviscous){ this->parameters->FindParam(&viscousnumsteps,SealevelchangeViscousNumStepsEnum); this->parameters->FindParam(&viscousindex,SealevelchangeViscousIndexEnum); + this->parameters->FindParam(&viscoussamplinglength,SealevelchangeViscousSamplingLengthEnum); + this->parameters->FindParam(&viscoussamplingindex,NULL,SealevelchangeViscousSamplingIndexEnum); if(computefuture) { - nt=viscousnumsteps-viscousindex+2; //number of time steps remaining to reach final_time, +1 is sufficient with no adaptative time stepping, +2 necessary otherwise; we assume the safe choice here for the sake of simplicity - if (nt>viscousnumsteps) nt=viscousnumsteps; + this->parameters->FindParam(&viscoustimes,NULL,SealevelchangeViscousTimesEnum); + this->parameters->FindParam(&final_time,TimesteppingFinalTimeEnum); + nt=1; + while (nt(1); + } //allocate grdfield=xNewZeroInit(3*nt); - if (n_activevertices==0) return grdfield; + if (n_activevertices==0){ + xDelete(viscoussamplingindex); + if(computeviscous){ + if(computefuture) xDelete(viscoustimes); + } + return grdfield; + } if(rotation){ //add rotational feedback for(av=0;avlids[this->vertices[i]->lid]!=this->lid)continue; for (int m=0;m<3;m++){ //polar motion components - for(t=0;tnactiveloads;ae++){ e=loads->combined_loads_index[ae]; a=AlphaIndex[c+e]*viscousnumsteps; - for(t=0;tnactivesubloads[l];ae++){ e=loads->combined_subloads_index[l][ae]; a=AlphaIndexsub[l][c+e]*viscousnumsteps; - for(t=0;t(horiz_projection); xDelete(projected_loads); + xDelete(viscoussamplingindex); + if(computeviscous){ + if(computefuture) xDelete(viscoustimes); + } for(l=0;l(projected_subloads[l]); xDelete(horiz_projectionsub[l]); @@ -8384,13 +8410,15 @@ void Tria::SealevelchangeCollectGrdfield(IssmDouble* grdfieldout, IssmDoub bool computeviscous=false; int viscousindex=0; //important int viscousnumsteps=1; //important + int viscousfieldsize=0; + int viscoussamplinglength=1; int* activevertices = NULL; IssmDouble* viscousfield=NULL; IssmDouble* grdfieldinterp=NULL; IssmDouble* viscoustimes=NULL; IssmDouble final_time; IssmDouble lincoeff; - IssmDouble timeacc; + int* viscoussamplingindex=NULL; //parameters & initialization this->parameters->FindParam(&computeviscous,SolidearthSettingsViscousEnum); @@ -8399,13 +8427,15 @@ void Tria::SealevelchangeCollectGrdfield(IssmDouble* grdfieldout, IssmDoub if(computeviscous){ this->parameters->FindParam(&viscousnumsteps,SealevelchangeViscousNumStepsEnum); this->parameters->FindParam(&viscousindex,SealevelchangeViscousIndexEnum); + this->parameters->FindParam(&viscoussamplinglength,SealevelchangeViscousSamplingLengthEnum); this->parameters->FindParam(&viscoustimes,NULL,SealevelchangeViscousTimesEnum); this->parameters->FindParam(&final_time,TimesteppingFinalTimeEnum); - this->parameters->FindParam(&timeacc,SolidearthSettingsTimeAccEnum); - this->inputs->GetArrayPtr(viscousenum,this->lid,&viscousfield,NULL); + this->inputs->GetArrayPtr(viscousenum,this->lid,&viscousfield,&viscousfieldsize); + _assert_(viscousfieldsize==3*viscousnumsteps); + this->parameters->FindParam(&viscoussamplingindex,NULL,SealevelchangeViscousSamplingIndexEnum); if(computefuture) { - nt=viscousnumsteps-viscousindex+2; //number of time steps remaining to reach final_time, +1 is sufficient with no adaptative time stepping, +2 necessary otherwise; we assume the safe choice here for the sake of simplicity - if (nt>viscousnumsteps) nt=viscousnumsteps; + nt=1; + while (nt(3*viscousnumsteps); } else nt=1; @@ -8452,16 +8482,25 @@ void Tria::SealevelchangeCollectGrdfield(IssmDouble* grdfieldout, IssmDoub } if(viscoustimes[viscousindex]lids[this->vertices[i]->lid]!=this->lid)continue; - int i_time1= i*nt-viscousindex; + int i_time1= i*nt; int i_time2= i*viscousnumsteps; + int itB=0; for(int t=viscousindex+1;t(grdfield); xDelete(viscoustimes); + xDelete(viscoussamplingindex); if (computefuture){ xDelete(grdfieldinterp); } diff --git a/src/c/classes/Elements/Tria.h b/src/c/classes/Elements/Tria.h index 7d4862069..0022904e8 100644 --- a/src/c/classes/Elements/Tria.h +++ b/src/c/classes/Elements/Tria.h @@ -48,7 +48,6 @@ class Tria: public Element,public ElementHook,public TriaRef{ void InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type); void InputScaleFromDakota(IssmDouble* distributed_values, IssmDouble* partition, int npart, int nt, int name); #endif - void InputUpdateFromIoModel(int index, IoModel* iomodel); void InputUpdateFromVector(IssmDouble* vector, int name, int type); /*}}}*/ /*Element virtual functions definitions: {{{*/ diff --git a/src/c/classes/FemModel.cpp b/src/c/classes/FemModel.cpp index 976ec7206..a064044fd 100644 --- a/src/c/classes/FemModel.cpp +++ b/src/c/classes/FemModel.cpp @@ -979,7 +979,7 @@ void FemModel::Solve(void){/*{{{*/ int solution_type; void (*solutioncore)(FemModel*)=NULL; //core solution function pointer - _printf0_("call computational core:\n"); + if(VerboseSolution()) _printf0_("call computational core:\n"); /*Retrieve solution_type from parameters: */ parameters->FindParam(&solution_type,SolutionTypeEnum); diff --git a/src/c/classes/GrdLoads.cpp b/src/c/classes/GrdLoads.cpp index 48efa4b3c..854d6a910 100644 --- a/src/c/classes/GrdLoads.cpp +++ b/src/c/classes/GrdLoads.cpp @@ -158,7 +158,7 @@ void GrdLoads::SHDegree2Coefficients(IssmDouble* deg2coeff, FemModel* femmodel, }; /*}}}*/ void GrdLoads::Combineloads(int nel,SealevelGeometry* slgeom){ /*{{{*/ - int e,l, nbar, ae; + int e, l, nbar, ae; //Determine loads /*{{{*/ nactiveloads=0; @@ -225,7 +225,7 @@ void GrdLoads::Combineloads(int nel,SealevelGeometry* slgeom){ /*{{{*/ ae=0; if(subsealevelloads && l==SLGEOM_OCEAN){ for (e=0;evalues){ for(int i=0;inumberofelements_local;i++) if(this->values[i]) xDelete(this->values[i]); - xDelete(this->values); + xDelete(this->values); } if(this->N) xDelete(this->N); } diff --git a/src/c/classes/Inputs/ControlInput.cpp b/src/c/classes/Inputs/ControlInput.cpp index a0e7bdb35..f5717bd15 100644 --- a/src/c/classes/Inputs/ControlInput.cpp +++ b/src/c/classes/Inputs/ControlInput.cpp @@ -19,7 +19,6 @@ ControlInput::ControlInput(){/*{{{*/ control_id = 0; values = NULL; - savedvalues = NULL; minvalues = NULL; maxvalues = NULL; gradient = NULL; @@ -33,14 +32,12 @@ ControlInput::ControlInput(int nbe, int nbv,int input_layout_enum,int interp,int switch(this->layout_enum){ case TriaInputEnum: this->values =new TriaInput(nbe,nbv,interp); - this->savedvalues=new TriaInput(nbe,nbv,interp); this->minvalues =new TriaInput(nbe,nbv,interp); this->maxvalues =new TriaInput(nbe,nbv,interp); this->gradient =new TriaInput(nbe,nbv,interp); break; case PentaInputEnum: this->values =new PentaInput(nbe,nbv,interp); - this->savedvalues=new PentaInput(nbe,nbv,interp); this->minvalues =new PentaInput(nbe,nbv,interp); this->maxvalues =new PentaInput(nbe,nbv,interp); this->gradient =new PentaInput(nbe,nbv,interp); @@ -57,7 +54,6 @@ ControlInput::ControlInput(int enum_in,int nbe, int nbv,int id,IssmDouble* times this->layout_enum = TransientInputEnum; /*Tria or Penta?*/ this->values =new TransientInput(enum_in,nbe,nbv,times,numtimes); - this->savedvalues=new TransientInput(enum_in,nbe,nbv,times,numtimes); this->minvalues =new TransientInput(enum_in,nbe,nbv,times,numtimes); this->maxvalues =new TransientInput(enum_in,nbe,nbv,times,numtimes); this->gradient =new TransientInput(enum_in,nbe,nbv,times,numtimes); @@ -65,7 +61,6 @@ ControlInput::ControlInput(int enum_in,int nbe, int nbv,int id,IssmDouble* times /*}}}*/ ControlInput::~ControlInput(){/*{{{*/ delete values; - delete savedvalues; delete minvalues; delete maxvalues; delete gradient; @@ -83,7 +78,6 @@ Input* ControlInput::copy() {/*{{{*/ output->layout_enum = this->layout_enum; if(values) output->values = this->values->copy(); - if(savedvalues) output->savedvalues = this->savedvalues->copy(); if(minvalues) output->minvalues = this->minvalues->copy(); if(maxvalues) output->maxvalues = this->maxvalues->copy(); if(gradient) output->gradient = this->gradient->copy(); @@ -93,7 +87,6 @@ Input* ControlInput::copy() {/*{{{*/ /*}}}*/ void ControlInput::Configure(Parameters* params){/*{{{*/ this->values->Configure(params); - this->savedvalues->Configure(params); this->minvalues->Configure(params); this->maxvalues->Configure(params); this->gradient->Configure(params); @@ -105,7 +98,6 @@ void ControlInput::DeepEcho(void){/*{{{*/ _printf_(setw(15)<<" ControlInput "<enum_type)<<"\n"); _printf_(setw(15)<<" Layout "<layout_enum)<<"\n"); _printf_("---values: \n"); if (values) values->Echo(); - _printf_("---savedvalues: \n");if (savedvalues) savedvalues->Echo(); _printf_("---minvalues: \n"); if (minvalues) minvalues->Echo(); _printf_("---maxvalues: \n"); if (maxvalues) maxvalues->Echo(); _printf_("---gradient: \n"); if (gradient){ gradient->Echo();} else{_printf_(" Not set yet\n");} @@ -131,21 +123,18 @@ void ControlInput::Marshall(MarshallHandle* marshallhandle){ /*{{{*/ switch(this->layout_enum){ case TriaInputEnum: this->values =new TriaInput(); - this->savedvalues=new TriaInput(); this->minvalues =new TriaInput(); this->maxvalues =new TriaInput(); this->gradient =new TriaInput(); break; case PentaInputEnum: this->values =new PentaInput(); - this->savedvalues=new PentaInput(); this->minvalues =new PentaInput(); this->maxvalues =new PentaInput(); this->gradient =new PentaInput(); break; case TransientInputEnum: this->values =new TransientInput(); - this->savedvalues=new TransientInput(); this->minvalues =new TransientInput(); this->maxvalues =new TransientInput(); this->gradient =new TransientInput(); @@ -156,7 +145,6 @@ void ControlInput::Marshall(MarshallHandle* marshallhandle){ /*{{{*/ } this->values->Marshall(marshallhandle); - this->savedvalues->Marshall(marshallhandle); this->minvalues->Marshall(marshallhandle); this->maxvalues->Marshall(marshallhandle); this->gradient->Marshall(marshallhandle); @@ -243,10 +231,6 @@ ElementInput* ControlInput::GetInput(const char* data){/*{{{*/ _assert_(values); return xDynamicCast(values); } - else if(strcmp(data,"savedvalues")==0){ - _assert_(savedvalues); - return xDynamicCast(values); - } else if (strcmp(data,"lowerbound")==0){ _assert_(minvalues); return xDynamicCast(minvalues); @@ -277,10 +261,6 @@ TransientInput* ControlInput::GetTransientInput(const char* data){/*{{{*/ _assert_(values); return xDynamicCast(values); } - else if(strcmp(data,"savedvalues")==0){ - _assert_(savedvalues); - return xDynamicCast(values); - } else if (strcmp(data,"lowerbound")==0){ _assert_(minvalues); return xDynamicCast(minvalues); diff --git a/src/c/classes/Inputs/ControlInput.h b/src/c/classes/Inputs/ControlInput.h index fa0dd0125..ffda7560b 100644 --- a/src/c/classes/Inputs/ControlInput.h +++ b/src/c/classes/Inputs/ControlInput.h @@ -20,7 +20,6 @@ class ControlInput: public Input{ Input *gradient; Input *maxvalues; Input *minvalues; - Input *savedvalues; Input *values; /*ControlInput constructors, destructors: {{{*/ diff --git a/src/c/classes/Inputs/DatasetInput.cpp b/src/c/classes/Inputs/DatasetInput.cpp index 2bc1ae00e..413b01ff3 100644 --- a/src/c/classes/Inputs/DatasetInput.cpp +++ b/src/c/classes/Inputs/DatasetInput.cpp @@ -54,6 +54,8 @@ Input* DatasetInput::copy() {/*{{{*/ output->inputs[i] = this->inputs[i]->copy(); } } + output->numberofelements_local = this->numberofelements_local; + output->numberofvertices_local = this->numberofvertices_local; return output; } diff --git a/src/c/classes/Inputs/IntArrayInput.cpp b/src/c/classes/Inputs/IntArrayInput.cpp index be274a3ab..7edc1e95d 100644 --- a/src/c/classes/Inputs/IntArrayInput.cpp +++ b/src/c/classes/Inputs/IntArrayInput.cpp @@ -32,7 +32,7 @@ IntArrayInput::IntArrayInput(int nbe_in){/*{{{*/ IntArrayInput::~IntArrayInput(){/*{{{*/ if(this->values){ for(int i=0;inumberofelements_local;i++) if(this->values[i]) xDelete(this->values[i]); - xDelete(this->values); + xDelete(this->values); } if(this->N) xDelete(this->N); } @@ -78,18 +78,40 @@ void IntArrayInput::Marshall(MarshallHandle* marshallhandle){ /*{{{*/ int object_enum = IntArrayInputEnum; marshallhandle->call(object_enum); marshallhandle->call(this->numberofelements_local); + + /*Allocate memory if reading restart file*/ + if(marshallhandle->OperationNumber() == MARSHALLING_LOAD){ + _assert_(this->numberofelements_local>0); + _assert_(this->numberofelements_local<1e11); + if(this->numberofelements_local){ + this->N = xNewZeroInit(this->numberofelements_local); + this->values = xNewZeroInit(this->numberofelements_local); + } + else{ + this->N = NULL; + this->values = NULL; + } + } + /*Marshall N*/ if(this->numberofelements_local){ marshallhandle->call(this->N,this->numberofelements_local); + } + + /*Marshall individual arrays*/ + if(this->numberofelements_local){ + for(int i=0;inumberofelements_local;i++){ - if(this->values[i]){ + if(this->N[i]){ + + /*Allocate if reading restart*/ + if(marshallhandle->OperationNumber() == MARSHALLING_LOAD){ + this->values[i] = xNew(this->N[i]); + } + _assert_(this->values[i]); marshallhandle->call(this->values[i],this->N[i]); } } } - else{ - this->N = NULL; - this->values = NULL; - } } /*}}}*/ diff --git a/src/c/classes/Inputs/TransientFileInput.cpp b/src/c/classes/Inputs/TransientFileInput.cpp index 0efec1064..c1d6e7e31 100644 --- a/src/c/classes/Inputs/TransientFileInput.cpp +++ b/src/c/classes/Inputs/TransientFileInput.cpp @@ -211,7 +211,7 @@ bool TransientFileInput::IsFileInputUpdate(IssmDouble time){/*{{{*/ /*Check if we are less than */ _assert_(this->timesteps); _assert_(this->loading_period>0.); - if(time - this->timesteps[this->numtimesteps-1] < this->loading_period){ + if(this->timesteps[this->numtimesteps-1] - time< this->loading_period){ return true; } diff --git a/src/c/classes/Inputs/TransientInput.cpp b/src/c/classes/Inputs/TransientInput.cpp index de4a50b9c..ede9174cc 100644 --- a/src/c/classes/Inputs/TransientInput.cpp +++ b/src/c/classes/Inputs/TransientInput.cpp @@ -588,6 +588,7 @@ void TransientInput::SetAverageAsCurrentTimeInput(IssmDouble start_time,IssmDoub stepinput->Pow(-1); this->current_input->AXPY(stepinput,dt); } + break; default: _error_("averaging method is not recognised"); } diff --git a/src/c/classes/Inputs/TriaInput.cpp b/src/c/classes/Inputs/TriaInput.cpp index 191107874..7cb3bafba 100644 --- a/src/c/classes/Inputs/TriaInput.cpp +++ b/src/c/classes/Inputs/TriaInput.cpp @@ -103,7 +103,8 @@ void TriaInput::Echo(void){/*{{{*/ if(isserved){ _printf_(" current values: "); _printf_("[ "); - for(int i=0;iinterpolation);i++) _printf_(" "<element_values[i]); + int numnodes = TriaRef::NumberofNodes(this->interpolation); + for(int i=0;ielement_values[i]); _printf_("] ("<interpolation)<<")\n"); } } @@ -361,14 +362,17 @@ int TriaInput::GetResultNumberOfNodes(void){/*{{{*/ /*}}}*/ void TriaInput::Scale(IssmDouble alpha){/*{{{*/ + int numnodes = TriaRef::NumberofNodes(this->interpolation); + for(int i=0;iM*this->N;i++) this->values[i] = alpha*this->values[i]; - for(int i=0;iinterpolation);i++) this->element_values[i] = alpha*this->element_values[i]; + for(int i=0;ielement_values[i] = alpha*this->element_values[i]; } /*}}}*/ void TriaInput::Pow(IssmDouble alpha){/*{{{*/ + int numnodes = TriaRef::NumberofNodes(this->interpolation); for(int i=0;iM*this->N;i++) this->values[i] = pow(this->values[i],alpha); - for(int i=0;iinterpolation);i++) this->element_values[i] = pow(this->element_values[i],alpha); + for(int i=0;ielement_values[i] = pow(this->element_values[i],alpha); } /*}}}*/ void TriaInput::AXPY(Input* xinput,IssmDouble alpha){/*{{{*/ @@ -379,15 +383,17 @@ void TriaInput::AXPY(Input* xinput,IssmDouble alpha){/*{{{*/ if(xtriainput->GetInterpolation()!=this->interpolation) _error_("Operation not permitted because xinput is of type " << EnumToStringx(xinput->ObjectEnum())); /*Carry out the AXPY operation depending on type:*/ + int numnodes = TriaRef::NumberofNodes(this->interpolation); for(int i=0;iM*this->N;i++) this->values[i] = alpha*xtriainput->values[i] + this->values[i]; - for(int i=0;iinterpolation);i++) this->element_values[i] = alpha*xtriainput->element_values[i] + this->element_values[i]; + for(int i=0;ielement_values[i] = alpha*xtriainput->element_values[i] + this->element_values[i]; } /*}}}*/ void TriaInput::Shift(IssmDouble alpha){/*{{{*/ /*Carry out the shift operation:*/ + int numnodes = TriaRef::NumberofNodes(this->interpolation); for(int i=0;iM*this->N;i++) this->values[i] +=alpha; - for(int i=0;iinterpolation);i++) this->element_values[i] += alpha; + for(int i=0;ielement_values[i] += alpha; } /*}}}*/ void TriaInput::PointWiseMult(Input* xinput){/*{{{*/ @@ -401,8 +407,9 @@ void TriaInput::PointWiseMult(Input* xinput){/*{{{*/ if(xtriainput->M!=this->M||xtriainput->N!=this->N) _error_("Operation not permitted because the inputs have different sizes"); /*Carry out the AXPY operation depending on type:*/ + int numnodes = TriaRef::NumberofNodes(this->interpolation); for(int i=0;iM*this->N;i++) this->values[i] = xtriainput->values[i] * this->values[i]; - for(int i=0;iinterpolation);i++) this->element_values[i] = xtriainput->element_values[i] * this->element_values[i]; + for(int i=0;ielement_values[i] = xtriainput->element_values[i] * this->element_values[i]; } /*}}}*/ void TriaInput::AverageAndReplace(void){/*{{{*/ diff --git a/src/c/classes/Loads/Channel.h b/src/c/classes/Loads/Channel.h index 9a019e3e7..14462d6d1 100644 --- a/src/c/classes/Loads/Channel.h +++ b/src/c/classes/Loads/Channel.h @@ -58,7 +58,6 @@ class Channel: public Load { void InputUpdateFromConstant(IssmDouble constant, int name){/*Do nothing*/}; void InputUpdateFromConstant(int constant, int name){/*Do nothing*/}; void InputUpdateFromConstant(bool constant, int name){_error_("Not implemented yet!");} - void InputUpdateFromIoModel(int index, IoModel* iomodel){_error_("not implemented yet");}; void InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){/*Do nothing*/} void InputUpdateFromVector(IssmDouble* vector, int name, int type){/*Do nothing*/} void InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){/*Do nothing*/} diff --git a/src/c/classes/Loads/Friction.cpp b/src/c/classes/Loads/Friction.cpp index 76f8f8587..8091aa0af 100644 --- a/src/c/classes/Loads/Friction.cpp +++ b/src/c/classes/Loads/Friction.cpp @@ -13,6 +13,10 @@ #include "../classes.h" #include "shared/shared.h" #include "../../modules/InputUpdateFromConstantx/InputUpdateFromConstantx.h" +#ifdef _HAVE_PyBind11_ + #include + namespace py=pybind11; +#endif /*}}}*/ /*Constructors/destructors*/ @@ -27,6 +31,9 @@ Friction::Friction(){/*{{{*/ this->vz_input=NULL; this->alpha2_list=NULL; this->alpha2_complement_list=NULL; + #ifdef _HAVE_PyBind11_ + this->emulator=NULL; + #endif } /*}}}*/ Friction::Friction(Element* element_in){/*{{{*/ @@ -38,6 +45,9 @@ Friction::Friction(Element* element_in){/*{{{*/ this->element=element_in; this->linearize = 0; + #ifdef _HAVE_PyBind11_ + this->emulator=NULL; + #endif /* Load necessary parameters */ element_in->FindParam(&this->law,FrictionLawEnum); @@ -97,6 +107,15 @@ Friction::Friction(Element* element_in){/*{{{*/ _error_("not supported yet"); } } + + #ifdef _HAVE_PyBind11_ + if(this->law==20){ + Param* emulator_param = element_in->parameters->FindParamObject(FrictionEmulatorEnum); + if(emulator_param->ObjectEnum()!=EmulatorParamEnum) _error_("Paramerer should be EmulatorParam"); + this->emulator = (EmulatorParam*)emulator_param; + } + #endif + } /*}}}*/ Friction::Friction(Element* element_in,int dim) : Friction(element_in) {/*{{{*/ @@ -108,7 +127,7 @@ Friction::Friction(Element* element_in,IssmPDouble dim) : Friction(element_in) { } /*}}}*/ Friction::~Friction(){/*{{{*/ - if(this->linearize){ + if(this->linearize!=0){ xDelete(this->alpha2_list); xDelete(this->alpha2_complement_list); } @@ -437,6 +456,11 @@ void Friction::GetAlpha2(IssmDouble* palpha2, Gauss* gauss){/*{{{*/ case 15: GetAlpha2RegCoulomb2(palpha2,gauss); break; + #ifdef _HAVE_PyBind11_ + case 20: + GetAlpha2Emulator(palpha2, gauss); + break; + #endif default: _error_("Friction law "<< this->law <<" not supported"); } @@ -1084,6 +1108,42 @@ void Friction::GetAlpha2RegCoulomb2(IssmDouble* palpha2, Gauss* gauss){/*{{{*/ /*Assign output pointers:*/ *palpha2=alpha2; }/*}}}*/ +#if _HAVE_PyBind11_ +void Friction::GetAlpha2Emulator(IssmDouble* palpha2, Gauss* gauss){/*{{{*/ + IssmDouble C; + IssmDouble alpha2; + + element->GetInputValue(&C,gauss,FrictionCEnum); + IssmDouble vmag = VelMag(gauss); + + /*Check to prevent dividing by zero if vmag==0*/ + if(vmag==0.) { + alpha2=0.; + } + else { + try { + py::array_t feats({1, 2}); + auto feats_mut = feats.mutable_unchecked<2>(); + feats_mut(0, 0) = static_cast(C * C); + feats_mut(0, 1) = static_cast(vmag); + + py::object pred_obj = this->emulator->mod.attr("predict_alpha2_np")(feats, py::arg("dtype") = "float64"); + py::array_t pred(pred_obj); + auto pred_view = pred.unchecked<2>(); + alpha2 = static_cast(pred_view(0, 0)); + } + catch (const py::error_already_set& e) { + _error_(std::string("Python friction inference failed: ") + e.what()); + } + catch (const std::exception& e) { + _error_(std::string("Friction emulator inference failed: ") + e.what()); + } + } + + /*Assign output pointers:*/ + *palpha2=alpha2; +}/*}}}*/ +#endif IssmDouble Friction::EffectivePressure(Gauss* gauss){/*{{{*/ /*Get effective pressure as a function of flag */ @@ -1374,6 +1434,11 @@ void FrictionUpdateInputs(Elements* elements,Inputs* inputs,IoModel* iomodel){/* iomodel->FetchDataToInput(inputs,elements,"md.friction.m",FrictionMEnum); iomodel->FetchDataToInput(inputs,elements,"md.friction.K",FrictionKEnum); break; + #ifdef _HAVE_PyBind11_ + case 20: + iomodel->FetchDataToInput(inputs,elements,"md.friction.C",FrictionCEnum); + break; + #endif default: _error_("friction law "<< frictionlaw <<" not supported"); } @@ -1451,6 +1516,25 @@ void FrictionUpdateParameters(Parameters* parameters,IoModel* iomodel){/*{{{*/ parameters->AddObject(new IntParam(FrictionCouplingEnum,2)); parameters->AddObject(iomodel->CopyConstantObject("md.friction.effective_pressure_limit",FrictionEffectivePressureLimitEnum)); break; + #ifdef _HAVE_PyBind11_ + case 20:{ + /*Get path from iomodel*/ + char* module_dir = NULL; + char* pt_name = NULL; + char* py_name = NULL; + iomodel->FetchData(&module_dir, "md.friction.module_dir"); + iomodel->FetchData(&pt_name, "md.friction.pt_name"); + iomodel->FetchData(&py_name, "md.friction.py_name"); + if(parameters->Exist(FrictionEmulatorEnum)){ + _error_("FrictionEmulatorEnum already exists in this process; EmulatorParam is process-local and must only be created once"); + } + parameters->AddObject(new EmulatorParam(FrictionEmulatorEnum, module_dir,pt_name, py_name)); + xDelete(module_dir); + xDelete(pt_name); + xDelete(py_name); + break; + } + #endif default: _error_("Friction law "< +#else +#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!" +#endif + /*Headers:*/ class Inputs; class Elements; @@ -12,6 +18,9 @@ class Parameters; class IoModel; class GaussPenta; class GaussTria; +#ifdef _HAVE_PyBind11_ +class EmulatorParam; +#endif class Friction{ @@ -26,6 +35,9 @@ class Friction{ Input *vz_input; IssmDouble *alpha2_list; IssmDouble *alpha2_complement_list; + #ifdef _HAVE_PyBind11_ + EmulatorParam* emulator; + #endif /*methods: */ Friction(); @@ -59,6 +71,9 @@ class Friction{ void GetAlpha2RegCoulomb(IssmDouble* palpha2,Gauss* gauss); void GetAlpha2RegCoulomb2(IssmDouble* palpha2,Gauss* gauss); void GetAlpha2Tsai(IssmDouble* palpha2,Gauss* gauss); + #if _HAVE_PyBind11_ + void GetAlpha2Emulator(IssmDouble* palpha2, Gauss* gauss); + #endif IssmDouble EffectivePressure(Gauss* gauss); IssmDouble IcePressure(Gauss* gauss); diff --git a/src/c/classes/Loads/Moulin.h b/src/c/classes/Loads/Moulin.h index 9f85a2f5c..7b4b83a8e 100644 --- a/src/c/classes/Loads/Moulin.h +++ b/src/c/classes/Loads/Moulin.h @@ -55,7 +55,6 @@ class Moulin: public Load{ void InputUpdateFromConstant(IssmDouble constant, int name); void InputUpdateFromConstant(int constant, int name); void InputUpdateFromConstant(bool constant, int name); - void InputUpdateFromIoModel(int index, IoModel* iomodel){_error_("not implemented yet");}; void InputUpdateFromMatrixDakota(IssmDouble* matrix ,int nrows, int ncols, int name, int type); void InputUpdateFromVector(IssmDouble* vector, int name, int type); void InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type); diff --git a/src/c/classes/Loads/Neumannflux.h b/src/c/classes/Loads/Neumannflux.h index 74b06e496..36f9025ab 100644 --- a/src/c/classes/Loads/Neumannflux.h +++ b/src/c/classes/Loads/Neumannflux.h @@ -48,7 +48,6 @@ class Neumannflux: public Load { void InputUpdateFromConstant(IssmDouble constant, int name){/*Do nothing*/}; void InputUpdateFromConstant(int constant, int name){/*Do nothing*/}; void InputUpdateFromConstant(bool constant, int name){/*Do nothing*/}; - void InputUpdateFromIoModel(int index, IoModel* iomodel){_error_("not implemented yet");}; void InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){/*Do nothing*/} void InputUpdateFromVector(IssmDouble* vector, int name, int type){/*Do nothing*/} void InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){/*Do nothing*/} diff --git a/src/c/classes/Loads/Numericalflux.h b/src/c/classes/Loads/Numericalflux.h index 767e12ea0..63607adf9 100644 --- a/src/c/classes/Loads/Numericalflux.h +++ b/src/c/classes/Loads/Numericalflux.h @@ -50,7 +50,6 @@ class Numericalflux: public Load { void InputUpdateFromConstant(IssmDouble constant, int name){/*Do nothing*/}; void InputUpdateFromConstant(int constant, int name){/*Do nothing*/}; void InputUpdateFromConstant(bool constant, int name){_error_("Not implemented yet!");} - void InputUpdateFromIoModel(int index, IoModel* iomodel){_error_("not implemented yet");}; void InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){/*Do nothing*/} void InputUpdateFromVector(IssmDouble* vector, int name, int type){/*Do nothing*/} void InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){/*Do nothing*/} diff --git a/src/c/classes/Loads/Penpair.h b/src/c/classes/Loads/Penpair.h index 0b09b2c50..f42e95d90 100644 --- a/src/c/classes/Loads/Penpair.h +++ b/src/c/classes/Loads/Penpair.h @@ -40,7 +40,6 @@ class Penpair: public Load{ void InputUpdateFromConstant(IssmDouble constant, int name); void InputUpdateFromConstant(int constant, int name); void InputUpdateFromConstant(bool constant, int name); - void InputUpdateFromIoModel(int index, IoModel* iomodel){_error_("not implemented yet");}; void InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrow, int ncols,int name, int type){_error_("Not implemented yet!");} void InputUpdateFromVector(IssmDouble* vector, int name, int type); void InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){_error_("Not implemented yet!");} diff --git a/src/c/classes/Loads/Riftfront.h b/src/c/classes/Loads/Riftfront.h index 9a3a2d286..2ec40f7e0 100644 --- a/src/c/classes/Loads/Riftfront.h +++ b/src/c/classes/Loads/Riftfront.h @@ -66,7 +66,6 @@ class Riftfront: public Load { void InputUpdateFromConstant(IssmDouble constant, int name); void InputUpdateFromConstant(int constant, int name){_error_("Not implemented yet!");} void InputUpdateFromConstant(bool constant, int name); - void InputUpdateFromIoModel(int index, IoModel* iomodel){_error_("not implemented yet");}; void InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows,int ncols, int name, int type){_error_("Not implemented yet!");} void InputUpdateFromVector(IssmDouble* vector, int name, int type); void InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){_error_("Not implemented yet!");} diff --git a/src/c/classes/Misfit.cpp b/src/c/classes/Misfit.cpp index 03545c2c6..9afff1786 100644 --- a/src/c/classes/Misfit.cpp +++ b/src/c/classes/Misfit.cpp @@ -205,7 +205,6 @@ IssmDouble Misfit::Response(FemModel* femmodel){/*{{{*/ misfit_t += pow(model[i]-observation[i],2)*weights[i]; if (weights[i]!=0)count++; } - misfit=sqrt(misfit_t/count); /*Add this time's contribution to curent misfit: */ misfit=sqrt(misfit_t)/count; diff --git a/src/c/classes/Node.cpp b/src/c/classes/Node.cpp index 174e2fb39..5cbf3d442 100644 --- a/src/c/classes/Node.cpp +++ b/src/c/classes/Node.cpp @@ -385,17 +385,17 @@ int Node::GetDof(int dofindex,int setenum){/*{{{*/ } /*}}}*/ void Node::GetDofList(int* outdoflist,int approximation_enum,int setenum,bool hideclones){/*{{{*/ + _assert_(!this->indexingupdate); - int i; int* doflistpointer = NULL; - if(setenum==GsetEnum) doflistpointer = gdoflist; - else if(setenum==FsetEnum)for(i=0;igsize;i++) doflistpointer = fdoflist; - else if(setenum==SsetEnum)for(i=0;igsize;i++) doflistpointer = sdoflist; + if(setenum==GsetEnum) doflistpointer = gdoflist; + else if(setenum==FsetEnum) doflistpointer = fdoflist; + else if(setenum==SsetEnum) doflistpointer = sdoflist; else _error_("not supported"); if(approximation_enum==NoneApproximationEnum){ - for(i=0;igsize;i++){ + for(int i=0;igsize;i++){ if(hideclones && this->IsClone()){ outdoflist[i]=-1; } @@ -407,14 +407,14 @@ void Node::GetDofList(int* outdoflist,int approximation_enum,int setenum,bool hi else{ if(doftype){ int count = 0; - for(i=0;igsize;i++){ + for(int i=0;igsize;i++){ if(doftype[i]==approximation_enum){ outdoflist[count++]=doflistpointer[i]; } } } else{ - for(i=0;igsize;i++){ + for(int i=0;igsize;i++){ if(hideclones && this->IsClone()){ outdoflist[i]=-1; } diff --git a/src/c/classes/Params/ControlParam.cpp b/src/c/classes/Params/ControlParam.cpp index a4c6e4d0c..dc454c914 100644 --- a/src/c/classes/Params/ControlParam.cpp +++ b/src/c/classes/Params/ControlParam.cpp @@ -13,6 +13,10 @@ /*ControlParam constructors and destructor*/ ControlParam::ControlParam(){/*{{{*/ + this->value = NULL; + this->minvalue = NULL; + this->maxvalue = NULL; + this->gradient = NULL; return; } /*}}}*/ diff --git a/src/c/classes/Params/DataSetParam.cpp b/src/c/classes/Params/DataSetParam.cpp index 69062c760..46d7f2c2b 100644 --- a/src/c/classes/Params/DataSetParam.cpp +++ b/src/c/classes/Params/DataSetParam.cpp @@ -16,18 +16,18 @@ /*DataSetParam constructors and destructor*/ DataSetParam::DataSetParam(){/*{{{*/ - value=NULL; + this->value = NULL; return; } /*}}}*/ DataSetParam::DataSetParam(int in_enum_type,DataSet* in_value){/*{{{*/ - enum_type=in_enum_type; - value=in_value->Copy(); + this->enum_type=in_enum_type; + this->value=in_value->Copy(); } /*}}}*/ DataSetParam::~DataSetParam(){/*{{{*/ - delete value; + delete this->value; } /*}}}*/ @@ -75,6 +75,11 @@ void DataSetParam::GetParameterValue(DataSet** pdataset){/*{{{*/ } /*}}}*/ void DataSetParam::SetValue(DataSet* dataset){/*{{{*/ + + /*Delete existing dataset*/ + delete this->value; + + /*Replace by what's provided*/ this->value=dataset; } /*}}}*/ diff --git a/src/c/classes/Params/DoubleMatArrayParam.cpp b/src/c/classes/Params/DoubleMatArrayParam.cpp index fd223dca2..93b43bd48 100644 --- a/src/c/classes/Params/DoubleMatArrayParam.cpp +++ b/src/c/classes/Params/DoubleMatArrayParam.cpp @@ -16,6 +16,9 @@ /*DoubleMatArrayParam constructors and destructor*/ DoubleMatArrayParam::DoubleMatArrayParam(){/*{{{*/ + this->array = NULL; + this->mdim_array = NULL; + this->ndim_array = NULL; return; } /*}}}*/ @@ -204,7 +207,7 @@ void DoubleMatArrayParam::SetValue(IssmDouble** in_array, int in_M, int* in_mdi /*avoid leak: */ xDelete(mdim_array); xDelete(ndim_array); - for(i=0;iM;i++){ matrix=array[i]; xDelete(matrix); } @@ -229,6 +232,4 @@ void DoubleMatArrayParam::SetValue(IssmDouble** in_array, int in_M, int* in_mdi this->array[i]=matrix; } - -} -/*}}}*/ +}/*}}}*/ diff --git a/src/c/classes/Params/DoubleMatParam.cpp b/src/c/classes/Params/DoubleMatParam.cpp index 9c9722bf4..12f9c7621 100644 --- a/src/c/classes/Params/DoubleMatParam.cpp +++ b/src/c/classes/Params/DoubleMatParam.cpp @@ -16,6 +16,7 @@ /*DoubleMatParam constructors and destructor*/ DoubleMatParam::DoubleMatParam(){/*{{{*/ + this->value = NULL; return; } /*}}}*/ diff --git a/src/c/classes/Params/DoubleVecParam.cpp b/src/c/classes/Params/DoubleVecParam.cpp index f1635762d..5b74c8c0c 100644 --- a/src/c/classes/Params/DoubleVecParam.cpp +++ b/src/c/classes/Params/DoubleVecParam.cpp @@ -16,6 +16,7 @@ /*DoubleVecParam constructors and destructor*/ DoubleVecParam::DoubleVecParam(){/*{{{*/ + this->values = NULL; return; } /*}}}*/ @@ -87,8 +88,11 @@ void DoubleVecParam::GetParameterValue(IssmDouble** poutput,int* pM){/*{{{*/ /*}}}*/ void DoubleVecParam::GetParameterValue(IssmDouble** poutput,int* pM,int* pN){/*{{{*/ - IssmDouble* output=xNew(this->M); - xMemCpy(output,values,M); + IssmDouble* output = NULL; + if(this->M){ + output=xNew(this->M); + xMemCpy(output,values,M); + } /*Assign output pointers:*/ if(pM) *pM=this->M; diff --git a/src/c/classes/Params/EmulatorParam.cpp b/src/c/classes/Params/EmulatorParam.cpp new file mode 100644 index 000000000..5c0d41588 --- /dev/null +++ b/src/c/classes/Params/EmulatorParam.cpp @@ -0,0 +1,176 @@ +/*!\file EmulatorParam.c + * \brief: implementation of the EmulatorParam object + */ + +/*header files: */ +/*{{{*/ +#ifdef HAVE_CONFIG_H + #include +#else +#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!" +#endif + +#include "../classes.h" +#include "shared/shared.h" +/*}}}*/ +#include +namespace py = pybind11; +using namespace py::literals; + +/*EmulatorParam constructors and destructor*/ +EmulatorParam::EmulatorParam(){/*{{{*/ + this->module_dir = NULL; + this->pt_name = NULL; + this->py_name = NULL; + return; +} +/*}}}*/ +EmulatorParam::EmulatorParam(int in_enum_type, char* module_dir_in, char* pt_name_in, char* py_name_in){/*{{{*/ + + this->enum_type=in_enum_type; + + /*Copy path to emulator*/ + this->module_dir = xNew(strlen(module_dir_in)+1); + xMemCpy(this->module_dir, module_dir_in,(strlen(module_dir_in)+1)); + this->pt_name = xNew(strlen(pt_name_in)+1); + xMemCpy(this->pt_name, pt_name_in,(strlen(pt_name_in)+1)); + this->py_name = xNew(strlen(py_name_in)+1); + xMemCpy(this->py_name, py_name_in,(strlen(py_name_in)+1)); + + /*Activate interpretor*/ + this->guard = NULL; + try{ + /*What if multi-emulator are activated?*/ + this->guard = new py::scoped_interpreter(); + + py::module_ sys = py::module_::import("sys"); + sys.attr("path").attr("append")(this->module_dir); + std::string pt_path(this->module_dir); + if(!pt_path.empty() && pt_path.back() != '/'){ + pt_path += "/"; + } + pt_path += this->pt_name; + std::string py_module_name(this->py_name); + std::size_t dot = py_module_name.rfind('.'); + if(dot != std::string::npos){ + py_module_name = py_module_name.substr(0,dot); + } + + this->mod = py::module_::import(py_module_name.c_str()); + this->mod.attr("init_model")(pt_path.c_str(), "auto"); + } + catch(const py::error_already_set& e){ + _printf_("EmulatorParam: Python exception in constructor\n"); + _printf_(" " << e.what() << "\n"); + this->mod = py::module_(); + delete this->guard; + this->guard = NULL; + throw; + } +} +/*}}}*/ +EmulatorParam::EmulatorParam(int in_enum_type, char* module_dir_in, char* pt_name_in, char* py_name_in, int* edge_src, int nsrc, int* edge_dst, int ndst, int num_nodes){/*{{{*/ + /*This constructor is for GNN only.*/ + + this->enum_type=in_enum_type; + + /*Copy path to emulator*/ + this->module_dir = xNew(strlen(module_dir_in)+1); + xMemCpy(this->module_dir, module_dir_in,(strlen(module_dir_in)+1)); + this->pt_name = xNew(strlen(pt_name_in)+1); + xMemCpy(this->pt_name, pt_name_in,(strlen(pt_name_in)+1)); + this->py_name = xNew(strlen(py_name_in)+1); + xMemCpy(this->py_name, py_name_in,(strlen(py_name_in)+1)); + + /*Activate interpretor*/ + this->guard = NULL; + if(IssmComm::GetRank()!=0) return; + + if(nsrc!=ndst) _error_("EmulatorParam graph constructor received edge_src and edge_dst arrays with different lengths"); + if(nsrc<0) _error_("EmulatorParam graph constructor received a negative edge count"); + if(num_nodes<0) _error_("EmulatorParam graph constructor received a negative node count"); + if(nsrc>0 && (!edge_src || !edge_dst)) _error_("EmulatorParam graph constructor received NULL edge arrays"); + + try{ + this->guard = new py::scoped_interpreter(); + + py::module_::import("numpy"); + py::module_ sys = py::module_::import("sys"); + sys.attr("path").attr("insert")(0,this->module_dir); + std::string pt_path(this->module_dir); + if(!pt_path.empty() && pt_path.back() != '/'){ + pt_path += "/"; + } + pt_path += this->pt_name; + std::string py_module_name(this->py_name); + std::size_t dot = py_module_name.rfind('.'); + if(dot != std::string::npos){ + py_module_name = py_module_name.substr(0,dot); + } + + this->mod = py::module_::import(py_module_name.c_str()); + + py::array_t edge_src_np(nsrc, edge_src); + py::array_t edge_dst_np(ndst, edge_dst); + this->mod.attr("init_model")( + pt_path.c_str(), + "auto", + "edge_src"_a = edge_src_np, + "edge_dst"_a = edge_dst_np, + "num_nodes"_a = num_nodes + ); + } + catch(const py::error_already_set& e){ + _printf_("EmulatorParam: Python exception in graph constructor\n"); + _printf_(" " << e.what() << "\n"); + this->mod = py::module_(); + delete this->guard; + this->guard = NULL; + throw; + } +} +/*}}}*/ +EmulatorParam::~EmulatorParam(){/*{{{*/ + xDelete(this->module_dir); + xDelete(this->pt_name); + xDelete(this->py_name); + + this->mod = py::module_(); + delete this->guard; + this->guard = NULL; +} +/*}}}*/ + +/*Object virtual functions definitions:*/ +Param* EmulatorParam::copy() {/*{{{*/ + + _error_("not implemented"); + +} +/*}}}*/ +void EmulatorParam::DeepEcho(void){/*{{{*/ + + _error_("not implemented"); + +} +/*}}}*/ +void EmulatorParam::Echo(void){/*{{{*/ + this->DeepEcho(); +} +/*}}}*/ +int EmulatorParam::Id(void){ return -1; }/*{{{*/ +/*}}}*/ +void EmulatorParam::Marshall(MarshallHandle* marshallhandle){ /*{{{*/ + + _error_("Not implemented yet"); + +} +/*}}}*/ +int EmulatorParam::ObjectEnum(void){/*{{{*/ + + return EmulatorParamEnum; + +} +/*}}}*/ + +/*EmulatorParam virtual functions definitions: */ diff --git a/src/c/classes/Params/EmulatorParam.h b/src/c/classes/Params/EmulatorParam.h new file mode 100644 index 000000000..ef2da5daf --- /dev/null +++ b/src/c/classes/Params/EmulatorParam.h @@ -0,0 +1,85 @@ +/*! \file EmulatorParam.h + * \brief: header file for triavertexinput object + */ + +#ifndef _EMULATORPARAM_H_ +#define _EMULATORPARAM_H_ + +/*Headers:*/ +/*{{{*/ +#ifdef HAVE_CONFIG_H + #include +#else +#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!" +#endif +#include "./Param.h" +#include "../../shared/shared.h" +/*}}}*/ +#include +namespace py = pybind11; +class EmulatorParam: public Param{ + + private: + int enum_type; + + public: + char* module_dir; + char* pt_name; + char* py_name; + py::scoped_interpreter* guard; + py::module_ mod; + + /*EmulatorParam constructors, destructors: {{{*/ + EmulatorParam(); + EmulatorParam(int enum_type, char* module_dir_in, char* pt_name_in, char* py_name_in); + EmulatorParam(int enum_type, char* module_dir_in, char* pt_name_in, char* py_name_in, int* edge_src, int nsrc, int* edge_dst, int ndst, int num_nodes); + ~EmulatorParam(); + /*}}}*/ + /*Object virtual functions definitions:{{{ */ + Param* copy(); + void DeepEcho(); + void Echo(); + int Id(); + void Marshall(MarshallHandle* marshallhandle); + int ObjectEnum(); + /*}}}*/ + /*Param virtual function definitions: {{{*/ + void GetParameterValue(bool* pbool){ _error_("Param "<< EnumToStringx(enum_type) << " cannot return a bool");} + void GetParameterValue(int* pinteger){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble");} + void GetParameterValue(int** pintarray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble");} + void GetParameterValue(int** pintarray,int* pM,int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble");} + void GetParameterValue(IssmDouble* pIssmDouble){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble");} + void GetParameterValue(IssmDouble* pdouble,IssmDouble time){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble for a given time");} + void GetParameterValue(IssmDouble* pdouble,IssmDouble time, int timestepping, IssmDouble dt){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble for a given time");} + void GetParameterValue(FILE** pfile){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a file pointer");} + void GetParameterValue(char** pstring){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a string");} + void GetParameterValue(char*** pstringarray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a string array");} + void GetParameterValue(IssmDouble** pIssmDoublearray,int* pM){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");} + void GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, int* pN){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");} + void GetParameterValue(IssmDouble** pIssmDoublearray,int* pM, const char* data){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a IssmDouble array");} + void GetParameterValue(IssmDouble*** parray, int* pM,int** pmdims, int** pndims){_error_("DataSet param of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot return a matrix array");} + void GetParameterValue(Vector** pvec){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Vec");} + void GetParameterValue(Matrix** pmat){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Mat");} + void GetParameterValue(DataSet** pdataset){_error_("Param "<< EnumToStringx(enum_type) << " cannot return a Dataset");} + int InstanceEnum(){return enum_type;} + + void SetEnum(int enum_in){this->enum_type = enum_in;}; + void SetValue(bool boolean){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");} + void SetValue(int integer){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");} + void SetValue(IssmDouble scalar){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");} + void SetValue(char* string){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string");} + void SetValue(FILE* fid){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a file pointer");} + void SetValue(char** stringarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a string array");} + void SetValue(IssmDouble* IssmDoublearray){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");} + void SetValue(IssmDouble* IssmDoublearray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");} + void SetValue(IssmDouble* pIssmDoublearray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a IssmDouble array");} + void SetValue(int* intarray,int M){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a int array");} + void SetValue(int* pintarray,int M,int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a int array");} + void SetValue(Vector* vec){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a Vec");} + void SetValue(Matrix* mat){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a Mat");} + void SetValue(DataSet* dataset){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold a Dataset");} + void SetValue(IssmDouble** array, int M, int* mdim_array, int* ndim_array){_error_("DataSet param of enum " << enum_type << " (" << EnumToStringx(enum_type) << ") cannot hold an array of matrices");} + void SetGradient(IssmDouble* poutput, int M, int N){_error_("Param "<< EnumToStringx(enum_type) << " cannot hold an IssmDouble");}; + /*}}}*/ +}; +#endif diff --git a/src/c/classes/Params/FileParam.cpp b/src/c/classes/Params/FileParam.cpp index 53d9593a7..24dfa0192 100644 --- a/src/c/classes/Params/FileParam.cpp +++ b/src/c/classes/Params/FileParam.cpp @@ -16,6 +16,7 @@ /*FileParam constructors and destructor*/ FileParam::FileParam(){/*{{{*/ + this->value = NULL; return; } /*}}}*/ diff --git a/src/c/classes/Params/IntMatParam.cpp b/src/c/classes/Params/IntMatParam.cpp index 668d104a2..cba1b2cf9 100644 --- a/src/c/classes/Params/IntMatParam.cpp +++ b/src/c/classes/Params/IntMatParam.cpp @@ -16,16 +16,16 @@ /*IntMatParam constructors and destructor*/ IntMatParam::IntMatParam(){/*{{{*/ + this->value = NULL; return; } /*}}}*/ IntMatParam::IntMatParam(int in_enum_type,int* in_value, int in_M,int in_N){/*{{{*/ - enum_type=in_enum_type; - M=in_M; - N=in_N; - - value=xNew(M*N); + this->enum_type=in_enum_type; + this->M=in_M; + this->N=in_N; + this->value=xNew(M*N); xMemCpy(value,in_value,M*N); } /*}}}*/ diff --git a/src/c/classes/Params/IntVecParam.cpp b/src/c/classes/Params/IntVecParam.cpp index 57f866864..5e905375a 100644 --- a/src/c/classes/Params/IntVecParam.cpp +++ b/src/c/classes/Params/IntVecParam.cpp @@ -16,6 +16,7 @@ /*IntVecParam constructors and destructor*/ IntVecParam::IntVecParam(){/*{{{*/ + this->values = NULL; return; } /*}}}*/ diff --git a/src/c/classes/Params/MatrixParam.cpp b/src/c/classes/Params/MatrixParam.cpp index f88571bdb..5df032188 100644 --- a/src/c/classes/Params/MatrixParam.cpp +++ b/src/c/classes/Params/MatrixParam.cpp @@ -16,6 +16,7 @@ /*MatrixParam constructors and destructor*/ MatrixParam::MatrixParam(){/*{{{*/ + this->value = NULL; return; } /*}}}*/ diff --git a/src/c/classes/Params/StringArrayParam.cpp b/src/c/classes/Params/StringArrayParam.cpp index 39c566fdf..1b0df5d3e 100644 --- a/src/c/classes/Params/StringArrayParam.cpp +++ b/src/c/classes/Params/StringArrayParam.cpp @@ -16,6 +16,7 @@ /*StringArrayParam constructors and destructor*/ StringArrayParam::StringArrayParam(){/*{{{*/ + this->value = NULL; return; } /*}}}*/ @@ -41,10 +42,8 @@ StringArrayParam::StringArrayParam(int in_enum_type,char** in_values, int in_num /*}}}*/ StringArrayParam::~StringArrayParam(){/*{{{*/ - int i; - char* string=NULL; - for(i=0;inumstrings;i++){ + for(int i=0;inumstrings;i++){ string=value[i]; xDelete(string); } diff --git a/src/c/classes/Params/StringParam.cpp b/src/c/classes/Params/StringParam.cpp index 29fb9bc92..a0e951280 100644 --- a/src/c/classes/Params/StringParam.cpp +++ b/src/c/classes/Params/StringParam.cpp @@ -16,6 +16,7 @@ /*StringParam constructors and destructor*/ StringParam::StringParam(){/*{{{*/ + this->value = NULL; return; } /*}}}*/ diff --git a/src/c/classes/Params/TransientArrayParam.cpp b/src/c/classes/Params/TransientArrayParam.cpp index 08747274e..3e2d303d5 100644 --- a/src/c/classes/Params/TransientArrayParam.cpp +++ b/src/c/classes/Params/TransientArrayParam.cpp @@ -16,6 +16,10 @@ /*TransientArrayParam constructors and destructor*/ TransientArrayParam::TransientArrayParam(){/*{{{*/ + this->M = 0; + this->N = 0; + this->values = NULL; + this->timesteps = NULL; return; } /*}}}*/ @@ -101,7 +105,7 @@ int TransientArrayParam::ObjectEnum(void){/*{{{*/ void TransientArrayParam::GetParameterValue(IssmDouble* pdouble,int row,IssmDouble time){/*{{{*/ IssmDouble output; - bool found; + bool found = false; _assert_(row>=0 && rowM); if(this->cycle) _error_("not implemented yet"); diff --git a/src/c/classes/Params/TransientGriddedFieldParam.cpp b/src/c/classes/Params/TransientGriddedFieldParam.cpp index d9ead7caa..c733e5863 100644 --- a/src/c/classes/Params/TransientGriddedFieldParam.cpp +++ b/src/c/classes/Params/TransientGriddedFieldParam.cpp @@ -16,6 +16,8 @@ /*TransientGriddedFieldParam constructors and destructor*/ TransientGriddedFieldParam::TransientGriddedFieldParam(){/*{{{*/ + this->values = NULL; + this->timesteps = NULL; return; } /*}}}*/ @@ -112,8 +114,8 @@ void TransientGriddedFieldParam::GetParameterValue(IssmDouble* pdouble,int row, void TransientGriddedFieldParam::GetParameterValue(IssmDouble* pdouble,int* index,int row,int column,IssmDouble time){/*{{{*/ IssmDouble output; - int output_id; - bool found; + int output_id; + bool found = false; _assert_(row>=0 && rowM); _assert_(column>=0 && columnN); diff --git a/src/c/classes/Params/TransientParam.cpp b/src/c/classes/Params/TransientParam.cpp index 284599962..082763350 100644 --- a/src/c/classes/Params/TransientParam.cpp +++ b/src/c/classes/Params/TransientParam.cpp @@ -16,6 +16,8 @@ /*TransientParam constructors and destructor*/ TransientParam::TransientParam(){/*{{{*/ + this->values = NULL; + this->timesteps = NULL; return; } /*}}}*/ @@ -97,7 +99,7 @@ int TransientParam::ObjectEnum(void){/*{{{*/ void TransientParam::GetParameterValue(IssmDouble* pdouble,IssmDouble time){/*{{{*/ IssmDouble output; - bool found; + bool found = false; if(this->cycle) _error_("not implemented yet"); diff --git a/src/c/classes/Params/VectorParam.cpp b/src/c/classes/Params/VectorParam.cpp index 6a686744a..984067037 100644 --- a/src/c/classes/Params/VectorParam.cpp +++ b/src/c/classes/Params/VectorParam.cpp @@ -16,6 +16,7 @@ /*VectorParam constructors and destructor*/ VectorParam::VectorParam(){/*{{{*/ + this->value = NULL; return; } /*}}}*/ diff --git a/src/c/classes/SealevelGeometry.cpp b/src/c/classes/SealevelGeometry.cpp index c4ab84127..93f151908 100644 --- a/src/c/classes/SealevelGeometry.cpp +++ b/src/c/classes/SealevelGeometry.cpp @@ -17,32 +17,30 @@ using namespace std; /*Object constructors and destructor*/ SealevelGeometry::SealevelGeometry(int localnelin,int localnodsin){ /*{{{*/ - localnel=localnelin; - for(int i=0;i(localnel); + LoadWeigths[i][j]=xNewZeroInit(localnel); } - vlatbarycentre[i] = NULL; //we don't know yet - vlongbarycentre[i] = NULL; - vareae_subel[i] = NULL; - latbarycentre[i] = NULL; //we don't know yet - longbarycentre[i] = NULL; - area_subel[i] = NULL; - - LoadArea[i] = xNewZeroInit(localnel); - issubelement[i] = xNewZeroInit(localnel); - Ylm_subel[i] = xNewZeroInit(localnel*9); - subelementmapping[i] = NULL; - nsubel[i] = 0; - nbar[i] = 0; + vlatbarycentre[i]=NULL; //we don't know yet + vlongbarycentre[i]=NULL; + vareae_subel[i]=NULL; + latbarycentre[i]=NULL; //we don't know yet + longbarycentre[i]=NULL; + area_subel[i]=NULL; + + LoadArea[i]=xNewZeroInit(localnel); + issubelement[i]=xNewZeroInit(localnel); + subelementmapping[i]=NULL; + nsubel[i]=0; + nbar[i]=0; + Ylm_subel[i]= xNewZeroInit(localnel*9); } - late = xNew(localnel); - longe = xNew(localnel); - isoceanin = xNew(localnel); - lids = xNew(localnodsin); - Ylm = xNewZeroInit(localnel*9); // (degmax+1)^2 terms, degmax = 2 + late=xNew(localnel); + longe=xNew(localnel); + isoceanin=xNew(localnel); + lids=xNew(localnodsin); + Ylm=xNewZeroInit(localnel*9); // (degmax+1)^2 terms, degmax=2 }; /*}}}*/ SealevelGeometry::~SealevelGeometry(){ /*{{{*/ @@ -79,7 +77,7 @@ void SealevelGeometry::InitializeMappingsAndBarycentres(void){ /*{{{*/ #ifdef _HAVE_MPI_ GetOwnershipBoundariesFromRange(&lower_row,&dummy,nsubel[i],IssmComm::GetComm()); #else - _error_("not supported without MIP "); + _error_("not supported without MPI "); #endif int count=0; @@ -152,20 +150,21 @@ void SealevelGeometry::BuildSphericalHarmonics(){ /*{{{*/ //YlmNormalization: N^2=(2*l+1)/4/pi * factorial(l-m)/factorial(l+m) if m==0 // : 2*N^2 if m>0 // such that integral(Ylm * Ylm *YlmNorm dS) = 1 on the unit sphere. - YlmNorm[0] = (0.25/M_PI); // Y00 - YlmNorm[1] = (0.75/M_PI); // Y10 - YlmNorm[2] = (0.75/M_PI); // Y11c - YlmNorm[3] = YlmNorm[2]; // Y11s - YlmNorm[4] = (1.25/M_PI); // Y20 - YlmNorm[5] = (1.25/3./M_PI); // Y21c - YlmNorm[6] = YlmNorm[5]; // Y21s - YlmNorm[7] = (1.25/12./M_PI); // Y22c - YlmNorm[8] = YlmNorm[7]; // Y22s + YlmNorm[0]=(0.25/M_PI); //Y00 + YlmNorm[1]=(0.75/M_PI); //Y10 + YlmNorm[2]=(0.75/M_PI); //Y11c + YlmNorm[3]=YlmNorm[2]; //Y11s + YlmNorm[4]=(1.25/M_PI); //Y20 + YlmNorm[5]=(1.25/3./M_PI); //Y21c + YlmNorm[6]=YlmNorm[5]; //Y21s + YlmNorm[7]=(1.25/12./M_PI); //Y22c + YlmNorm[8]=YlmNorm[7]; //Y22s for (int e=0;e +#else + #error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!" +#endif + /*Objects: */ #include "./Contour.h" #include "./Vertices.h" @@ -111,6 +117,9 @@ #include "./Params/TransientArrayParam.h" #include "./Params/TransientGriddedFieldParam.h" #include "./Params/DataSetParam.h" +#ifdef _HAVE_PyBind11_ +#include "./Params/EmulatorParam.h" +#endif /*matrix: */ #include "./matrix/matrixobjects.h" diff --git a/src/c/cores/WrapperCorePointerFromSolutionEnum.cpp b/src/c/cores/WrapperCorePointerFromSolutionEnum.cpp index 1b463c40a..fdee58e90 100644 --- a/src/c/cores/WrapperCorePointerFromSolutionEnum.cpp +++ b/src/c/cores/WrapperCorePointerFromSolutionEnum.cpp @@ -47,6 +47,7 @@ void WrapperCorePointerFromSolutionEnum(void (**psolutioncore)(FemModel*),Parame case 2: solutioncore=controlm1qn3_core; break; case 3: solutioncore=controlvalidation_core; break; case 4: solutioncore=controladm1qn3_core; break; + case 5: solutioncore=controlnudging_core; break; default: _error_("control type not supported"); } } diff --git a/src/c/cores/bedslope_core.cpp b/src/c/cores/bedslope_core.cpp index 3665ad7a2..430b89472 100644 --- a/src/c/cores/bedslope_core.cpp +++ b/src/c/cores/bedslope_core.cpp @@ -19,7 +19,7 @@ void bedslope_core(FemModel* femmodel){ femmodel->parameters->FindParam(&save_results,SaveResultsEnum); femmodel->parameters->FindParam(&domaintype,DomainTypeEnum); - if(VerboseSolution()) _printf0_(" computing slope\n"); + if(VerboseSolution()) _printf0_(" computing bed slopes\n"); /*Call on core computations: */ femmodel->SetCurrentConfiguration(L2ProjectionBaseAnalysisEnum); diff --git a/src/c/cores/controladm1qn3_core.cpp b/src/c/cores/controladm1qn3_core.cpp index 4c6869752..7f6102d92 100644 --- a/src/c/cores/controladm1qn3_core.cpp +++ b/src/c/cores/controladm1qn3_core.cpp @@ -16,17 +16,9 @@ double transient_ad(FemModel* femmodel, double* G,double* Jlist); #endif -#if defined (_HAVE_M1QN3_) && defined(_HAVE_AD_) +#if defined(_HAVE_AD_) /*m1qn3 prototypes {{{*/ -extern "C" void *ctonbe_; // DIS mode : Conversion -extern "C" void *ctcabe_; // DIS mode : Conversion -extern "C" void *euclid_; // Scalar product typedef void (*SimulFunc) (long* indic,long* n, double* x,double* pf,double* g,long [],float [],void* dzs); -extern "C" void m1qn3_ (void f(long* indic,long* n, double* x,double* pf,double* g,long [],float [],void* dzs), - void **, void **, void **, - long *, double [],double *, double[], double*, double *, - double *, char [], long *, long *, long *, long *, long *, long *, long [],double [], long *, - long *, long *, long [], float [],void* ); /*Use struct to provide arguments*/ typedef struct{ @@ -435,15 +427,11 @@ void controladm1qn3_core(FemModel* femmodel){/*{{{*/ /*Initialize M1QN3 parameters*/ if(VerboseControl())_printf0_(" Initialize M1QN3 parameters\n"); SimulFunc simul_ptr = &simul_ad; /*Cost function address*/ - void** prosca = &euclid_; /*Dot product function (euclid is the default)*/ - char normtype[] = "dfn"; /*Norm type: dfn = scalar product defined by prosca*/ long izs[5]; /*Arrays used by m1qn3 subroutines*/ long iz[5]; /*Integer m1qn3 working array of size 5*/ float rzs[1]; /*Arrays used by m1qn3 subroutines*/ long impres = 0; /*verbosity level*/ - long imode[3] = {0}; /*scaling and starting mode, 0 by default*/ long indic = 4; /*compute f and g*/ - long reverse = 0; /*reverse or direct mode*/ long io = 6; /*Channel number for the output*/ /*Optimization criterions*/ @@ -489,11 +477,12 @@ void controladm1qn3_core(FemModel* femmodel){/*{{{*/ if(dfmin_frac==0.) dfmin_frac=1.; double df1=dfmin_frac*f; - /*Call M1QN3 solver*/ - m1qn3_(simul_ptr,prosca,&ctonbe_,&ctcabe_, + /*Call M1QN3 solver (C++ implementation)*/ + m1qn3_cpp(simul_ptr, &n,X,&f,G,&dxmin,&df1, - >tol,normtype,&impres,&io,imode,&omode,&niter,&nsim,iz,dz,&ndz, - &reverse,&indic,izs,rzs,(void*)&mystruct); + >tol,&impres,&io,&omode,&niter,&nsim,iz,dz,&ndz, + izs,rzs,(void*)&mystruct, + true); /*return_best: always restore the iterate with the lowest f*/ /*Print exit flag*/ InversionStatsFooter(num_cost_functions); @@ -597,5 +586,5 @@ void controladm1qn3_core(FemModel* femmodel){/*{{{*/ }/*}}}*/ #else -void controladm1qn3_core(FemModel* femmodel){_error_("M1QN3 or ADOLC/CoDiPack not installed");} -#endif //_HAVE_M1QN3_ +void controladm1qn3_core(FemModel* femmodel){_error_("ADOLC/CoDiPack not installed");} +#endif //_HAVE_AD_ diff --git a/src/c/cores/controlm1qn3_core.cpp b/src/c/cores/controlm1qn3_core.cpp index 847792dd0..1692c8f72 100644 --- a/src/c/cores/controlm1qn3_core.cpp +++ b/src/c/cores/controlm1qn3_core.cpp @@ -10,17 +10,8 @@ #include "../modules/modules.h" #include "../solutionsequences/solutionsequences.h" -#if defined (_HAVE_M1QN3_) /*m1qn3 prototypes {{{*/ -extern "C" void *ctonbe_; // DIS mode : Conversion -extern "C" void *ctcabe_; // DIS mode : Conversion -extern "C" void *euclid_; // Scalar product typedef void (*SimulFunc) (long* indic,long* n, double* x, double* pf,double* g,long [],float [],void* dzs); -extern "C" void m1qn3_ (void f(long* indic,long* n, double* x, double* pf,double* g,long [],float [],void* dzs), - void **, void **, void **, - long *, double [], double *, double [], double*, double *, - double *, char [], long *, long *, long *, long *, long *, long *, long [], double [], long *, - long *, long *, long [], float [],void* ); /*Cost function prototype*/ void simul(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float rzs[1],void* dzs); @@ -67,15 +58,11 @@ void controlm1qn3_core(FemModel* femmodel){/*{{{*/ /*Initialize M1QN3 parameters*/ if(VerboseControl())_printf0_(" Initialize M1QN3 parameters\n"); SimulFunc costfuncion = &simul; /*Cost function address*/ - void** prosca = &euclid_; /*Dot product function (euclid is the default)*/ - char normtype[] = "dfn"; /*Norm type: dfn = scalar product defined by prosca*/ long izs[5]; /*Arrays used by m1qn3 subroutines*/ long iz[5]; /*Integer m1qn3 working array of size 5*/ float rzs[1]; /*Arrays used by m1qn3 subroutines*/ long impres = 0; /*verbosity level*/ - long imode[3] = {0}; /*scaling and starting mode, 0 by default*/ long indic = 4; /*compute f and g*/ - long reverse = 0; /*reverse or direct mode*/ long io = 6; /*Channel number for the output*/ /*Optimization criterions (need to be cast to long for m1qn3)*/ @@ -123,11 +110,12 @@ void controlm1qn3_core(FemModel* femmodel){/*{{{*/ if(dfmin_frac==0.) dfmin_frac=1.; double df1=dfmin_frac*f; - /*Call M1QN3 solver*/ - m1qn3_(costfuncion,prosca,&ctonbe_,&ctcabe_, + /*Call M1QN3 solver (C++ implementation)*/ + m1qn3_cpp(costfuncion, &n,X,&f,G,&dxmin,&df1, - >tol,normtype,&impres,&io,imode,&omode,&niter,&nsim,iz,dz,&ndz, - &reverse,&indic,izs,rzs,(void*)&mystruct); + >tol,&impres,&io,&omode,&niter,&nsim,iz,dz,&ndz, + izs,rzs,(void*)&mystruct, + true); /*return_best: always restore the iterate with the lowest f*/ /*Print exit flag*/ InversionStatsFooter(num_cost_functions); @@ -316,7 +304,3 @@ void simul(long* indic,long* n,double* X,double* pf,double* G,long izs[1],float xDelete(XL); xDelete(scaling_factors); }/*}}}*/ - -#else -void controlm1qn3_core(FemModel* femmodel){_error_("M1QN3 not installed");} -#endif //_HAVE_M1QN3_ diff --git a/src/c/cores/controlnudging_core.cpp b/src/c/cores/controlnudging_core.cpp new file mode 100644 index 000000000..3116ff410 --- /dev/null +++ b/src/c/cores/controlnudging_core.cpp @@ -0,0 +1,110 @@ +/*!\file: controlnudging_core.cpp + * \brief: core of the control solution + */ + +#include "./cores.h" +#include "../toolkits/toolkits.h" +#include "../classes/classes.h" +#include "../shared/shared.h" +#include "../modules/modules.h" + +void controlnudging_core(FemModel* femmodel){ + + /*Intermediaries*/ + IssmDouble dCdt1, dCdt2, dCdt3, dHdt; + int numvertices=femmodel->vertices->NumberOfVertices(); + + /*Hard-coded nudging parameters*/ + IssmDouble timeadjust = 1/6; // yr per nudging step (2 months) + IssmDouble H0 = 100; // m — thickness error scale (smaller = more sensitive), 100 m used in van den Akker et al (2025) + IssmDouble r = 0.4; // relaxation strength toward C_inv (0 = none, 1 = strong) , 0.5 used in van den Akker et al (2025) + int nsteps = 12000; // number of nudging steps + + /*User-defined nudging parameters*/ + IssmDouble tau_C = femmodel->parameters->FindParam(InversionTauCEnum); + IssmDouble yts = femmodel->parameters->FindParam(ConstantsYtsEnum); + IssmDouble tmax = femmodel->parameters->FindParam(TimesteppingFinalTimeEnum); + IssmDouble tmin = femmodel->parameters->FindParam(TimesteppingStartTimeEnum); + IssmDouble deltat = (tmax - tmin)*yts; // convert to years + + /*Fields before/after*/ + IssmDouble* C0 = NULL; + IssmDouble* C = NULL; + IssmDouble* Hobs = NULL; + IssmDouble* H = NULL; + IssmDouble* V = NULL; + IssmDouble* O_ls = NULL; + + /*Get Fields once and for all*/ + GetVectorFromInputsx(&C0, femmodel, FrictionCoefficientEnum, VertexSIdEnum); + GetVectorFromInputsx(&Hobs, femmodel, ThicknessEnum, VertexSIdEnum); + + femmodel->parameters->SetParam(false,SaveResultsEnum); + for(int m=0;mcopy(); + + /*Solve another transient simulation*/ + transient_core(femmodel); + + /*Extract results*/ + GetVectorFromInputsx(&H, femmodel, ThicknessEnum, VertexSIdEnum); + GetVectorFromInputsx(&C, femmodel, FrictionCoefficientEnum, VertexSIdEnum); + GetVectorFromInputsx(&V, femmodel, VelEnum, VertexSIdEnum); + GetVectorFromInputsx(&O_ls, femmodel, MaskOceanLevelsetEnum, VertexSIdEnum); + + /*Update friction coefficient accordingly*/ + for(int i=0;i H_obs (too thick), decrease C (less friction → faster ice → larger flux, lower H)*/ + dCdt1 = -1*((H[i] - Hobs[i])/ H0) / tau_C; + + /*2. : tendency — damp ongoing thinning/thickening + * Sign: if dH/dt > 0 (thickening), if it is thickening and already too thick, decrease c faster. + * If it is thinning and the thickness is already to large, the ice is already moving in the correct + * direction, so make C decrease a little bit less */ + dHdt = (H[i] - Hobs[i])/deltat; + dCdt2 = -1*(dHdt/H0) /tau_C; + + /*3. Relaxation term*/ + IssmDouble C_loginv = log10(max(C[i], 1.)); + IssmDouble C_loginv0 = log10(max(C0[i], 1.)); + dCdt3 = 1*(r / tau_C)*(C_loginv-C_loginv0); + + /* Do not nudge C where velocity ratio is very low AND ice is too thin + * These cells need upstream replenishment, not local friction changes*/ + if(V[i]<15./yts && dHdt<-50/yts && O_ls[i]>0.) { + dCdt2 = 0.; + dCdt3 = 0.; + } + + /*Compute total dC in log space*/ + IssmDouble dC_log = deltat*(dCdt1 + dCdt2 + dCdt3); + + /*Correction: prevent C from decreasing where ice is too thin and + * still thinning — the model needs more friction here, not less*/ + if( ((H[i] - Hobs[i])< -20.) && (dHdt<-1.) ){ + dC_log = max(dC_log, 0.); + } + + /*Update friction coefficient now*/ + C[i] = pow(10., C_loginv + dC_log); + } + + InputUpdateFromVectorx(femmodel, C, FrictionCoefficientEnum, VertexSIdEnum); + _error_("not implemented yet"); + + xDelete(H); + xDelete(C); + xDelete(O_ls); + xDelete(V); + delete femmodel_temp; + } + + /*Clean up and return*/ + xDelete(C0); + xDelete(Hobs); +} diff --git a/src/c/cores/cores.h b/src/c/cores/cores.h index 61fa13449..23f872d8a 100644 --- a/src/c/cores/cores.h +++ b/src/c/cores/cores.h @@ -33,6 +33,7 @@ void controltao_core(FemModel* femmodel); void controlm1qn3_core(FemModel* femmodel); void controladm1qn3_core(FemModel* femmodel); void controlvalidation_core(FemModel* femmodel); +void controlnudging_core(FemModel* femmodel); void masstransport_core(FemModel* femmodel); void mmemasstransport_core(FemModel* femmodel); void oceantransport_core(FemModel* femmodel); diff --git a/src/c/cores/sealevelchange_core.cpp b/src/c/cores/sealevelchange_core.cpp index e508549bb..acf1846d8 100644 --- a/src/c/cores/sealevelchange_core.cpp +++ b/src/c/cores/sealevelchange_core.cpp @@ -166,6 +166,7 @@ void couplerinput_core(FemModel* femmodel){ /*{{{*/ /*retrieve more parameters:*/ femmodel->parameters->FindParam(&iscoupling,IsSlcCouplingEnum); + femmodel->parameters->FindParam(&horiz,SolidearthSettingsHorizEnum); femmodel->parameters->FindParam(&frequency,SolidearthSettingsRunFrequencyEnum); femmodel->parameters->FindParam(&count,SealevelchangeRunCountEnum); @@ -222,7 +223,7 @@ void couplerinput_core(FemModel* femmodel){ /*{{{*/ }; /*}}}*/ void grd_core(FemModel* femmodel, SealevelGeometry* slgeom) { /*{{{*/ - /*variables:{{{*/ + /*variables:*/ int nel; BarystaticContributions* barycontrib=NULL; GenericParam* barycontribparam=NULL; @@ -234,6 +235,7 @@ void grd_core(FemModel* femmodel, SealevelGeometry* slgeom) { /*{{{ IssmDouble totaloceanarea; Vector* subelementoceanareas=NULL; IssmDouble oceanaverage; + IssmDouble barystatictotal; bool scaleoceanarea=false; IssmDouble rho_water; @@ -250,16 +252,14 @@ void grd_core(FemModel* femmodel, SealevelGeometry* slgeom) { /*{{{ int grd=0; int grdmodel; int sealevelloading=0; - bool sal=false; - bool viscous=false; - bool rotation=false; - bool planethasocean=false; - bool computefuture=false; - IssmDouble* sealevelpercpu=NULL; + bool sal = false; + bool viscous = false; + bool rotation = false; + bool planethasocean = false; + bool computefuture = false; + IssmDouble *sealevelpercpu = NULL; - /*}}}*/ - - /*retrieve parameters:{{{*/ + /*retrieve parameters:*/ femmodel->parameters->FindParam(&grd,SolidearthSettingsGRDEnum); femmodel->parameters->FindParam(&grdmodel,GrdModelEnum); femmodel->parameters->FindParam(&frequency,SolidearthSettingsRunFrequencyEnum); @@ -271,7 +271,6 @@ void grd_core(FemModel* femmodel, SealevelGeometry* slgeom) { /*{{{ femmodel->parameters->FindParam(&viscous,SolidearthSettingsViscousEnum); femmodel->parameters->FindParam(&rotation,SolidearthSettingsRotationEnum); femmodel->parameters->FindParam(&planethasocean,SolidearthSettingsGrdOceanEnum); - /*}}}*/ /*only run if grd was requested, if we are the earth, and we have reached * the necessary number of time steps dictated by :*/ @@ -292,7 +291,7 @@ void grd_core(FemModel* femmodel, SealevelGeometry* slgeom) { /*{{{ /*Verbose: */ if(VerboseSolution()) _printf0_(" computing GRD patterns\n"); - /*retrieve parameters: {{{*/ + /*retrieve parameters:*/ femmodel->parameters->FindParam(&scaleoceanarea,SolidearthSettingsOceanAreaScalingEnum); barycontribparam = xDynamicCast*>(femmodel->parameters->FindParamObject(BarystaticContributionsEnum)); barycontrib=barycontribparam->GetParameterValue(); @@ -301,7 +300,6 @@ void grd_core(FemModel* femmodel, SealevelGeometry* slgeom) { /*{{{ femmodel->parameters->FindParam(&eps_abs,SolidearthSettingsAbstolEnum); femmodel->parameters->FindParam(&horiz,SolidearthSettingsHorizEnum); femmodel->parameters->FindParam(&sal,SolidearthSettingsSelfAttractionEnum); - /*}}}*/ /*initialize loads and sea level loads:*/ femmodel->parameters->FindParam(&nel,MeshNumberofelementsEnum); @@ -321,6 +319,8 @@ void grd_core(FemModel* femmodel, SealevelGeometry* slgeom) { /*{{{ Element* element = xDynamicCast(object); element->SealevelchangeBarystaticLoads(loads, barycontrib,slgeom); } + barycontrib->Assemble(); + barystatictotal=barycontrib->Total(); //broadcast loads loads->BroadcastLoads(); @@ -330,69 +330,70 @@ void grd_core(FemModel* femmodel, SealevelGeometry* slgeom) { /*{{{ loads->sealevelloads=xNewZeroInit(nel); loads->subsealevelloads=xNewZeroInit(slgeom->nbar[SLGEOM_OCEAN]); PolarMotion(&polarmotionvector[0],femmodel,loads, slgeom, computefuture=true); - goto deformation; } + else{ + if(VerboseSolution()) _printf0_(" converging GRD convolutions\n"); + for(;;){ - if(VerboseSolution()) _printf0_(" converging GRD convolutions\n"); - for(;;){ + //compute polar motion: + PolarMotion(&polarmotionvector[0],femmodel,loads,slgeom,computefuture=false); - //compute polar motion: - PolarMotion(&polarmotionvector[0],femmodel,loads,slgeom,computefuture=false); + oldsealevelloads=xNewZeroInit(nel); + if(loads->sealevelloads){ + xMemCpy(oldsealevelloads,loads->sealevelloads,nel); + } - oldsealevelloads=xNewZeroInit(nel); - if (loads->sealevelloads){ - xMemCpy(oldsealevelloads,loads->sealevelloads,nel); - } + /*convolve load and sealevel loads on oceans:*/ + loads->Combineloads(nel,slgeom); //This combines loads and sealevelloads into a single vector + for(Object* & object : femmodel->elements->objects){ + Element* element = xDynamicCast(object); + element->SealevelchangeConvolution(sealevelpercpu, loads, polarmotionvector,slgeom); + } - /*convolve load and sealevel loads on oceans:*/ - loads->Combineloads(nel,slgeom); //This combines loads and sealevelloads into a single vector - for(Object* & object : femmodel->elements->objects){ - Element* element = xDynamicCast(object); - element->SealevelchangeConvolution(sealevelpercpu, loads, polarmotionvector,slgeom); - } + /*retrieve sea level average and ocean area:*/ + for(Object* & object : femmodel->elements->objects){ + Element* element = xDynamicCast(object); + element->SealevelchangeOceanAverage(loads, oceanareas, subelementoceanareas, sealevelpercpu, slgeom); + } - /*retrieve sea level average and ocean area:*/ - for(Object* & object : femmodel->elements->objects){ - Element* element = xDynamicCast(object); - element->SealevelchangeOceanAverage(loads, oceanareas, subelementoceanareas, sealevelpercpu, slgeom); - } + loads->AssembleSealevelLoads(); - loads->AssembleSealevelLoads(); + /*compute ocean areas:*/ + if(!loads->sealevelloads){ //first time in the loop + oceanareas->Assemble(); + subelementoceanareas->Assemble(); + oceanareas->Sum(&totaloceanarea); _assert_(totaloceanarea>0.); + if(scaleoceanarea) totaloceanarea=3.619e+14; // use true ocean area, m^2 + } - /*compute ocean areas:*/ - if(!loads->sealevelloads){ //first time in the loop - oceanareas->Assemble(); - subelementoceanareas->Assemble(); - oceanareas->Sum(&totaloceanarea); _assert_(totaloceanarea>0.); - if(scaleoceanarea) totaloceanarea=3.619e+14; // use true ocean area, m^2 - } + //Conserve ocean mass: + oceanaverage=SealevelloadsOceanAverage(loads, oceanareas,subelementoceanareas, totaloceanarea); + ConserveOceanMass(femmodel,loads,barystatictotal/totaloceanarea -oceanaverage,slgeom); - //Conserve ocean mass: - oceanaverage=SealevelloadsOceanAverage(loads, oceanareas,subelementoceanareas, totaloceanarea); - ConserveOceanMass(femmodel,loads,barycontrib->Total()/totaloceanarea -oceanaverage,slgeom); + //broadcast sea level loads + loads->BroadcastSealevelLoads(); - //broadcast sea level loads - loads->BroadcastSealevelLoads(); + if(!sal){ + xDelete(oldsealevelloads); break; + } - if (!sal) {xDelete(oldsealevelloads); break;} + //convergence? + if(slcconvergence(loads->sealevelloads,oldsealevelloads,eps_rel,eps_abs,totaloceanarea,femmodel)){ + xDelete(oldsealevelloads); break; + } - //convergence? - if(slcconvergence(loads->sealevelloads,oldsealevelloads,eps_rel,eps_abs,totaloceanarea,femmodel)){ - xDelete(oldsealevelloads); break; - } + xDelete(oldsealevelloads); - //early return? - if(iterations>=max_nonlinear_iterations){ - xDelete(oldsealevelloads); break; + //early return? + iterations++; //slc_geometry_cleanup(slgeom, femmodel); + if(iterations>=max_nonlinear_iterations){ + break; + } } - iterations++; - xDelete(oldsealevelloads); - } - - //recompute polar motion one final time, this time updating viscous stacks for future time steps - if (viscous) PolarMotion(&polarmotionvector[0],femmodel,loads, slgeom, computefuture=true); - deformation: + /*recompute polar motion one final time, this time updating viscous stacks for future time steps*/ + if (viscous) PolarMotion(&polarmotionvector[0],femmodel,loads, slgeom, computefuture=true); + } if(VerboseSolution()) _printf0_(" deformation GRD convolutions\n"); @@ -424,13 +425,15 @@ void grd_core(FemModel* femmodel, SealevelGeometry* slgeom) { /*{{{ //Conserve ocean mass //Note that here we create sea-level loads but they will not generate GRD as we have already run all the convolutions oceanaverage=SealevelloadsOceanAverage(loads, oceanareas,subelementoceanareas, totaloceanarea); - ConserveOceanMass(femmodel,loads,barycontrib->Total()/totaloceanarea - oceanaverage,slgeom); + ConserveOceanMass(femmodel,loads,barystatictotal/totaloceanarea - oceanaverage,slgeom); } + //slc_geometry_cleanup(slgeom, femmodel); - femmodel->inputs->Shift(SealevelGRDEnum,barycontrib->Total()/rho_water/totaloceanarea- oceanaverage/rho_water); + femmodel->inputs->Shift(SealevelGRDEnum,barystatictotal/rho_water/totaloceanarea- oceanaverage/rho_water); //cumulate barystatic contributions and save to results: barycontrib->Cumulate(femmodel->parameters); + barycontrib->CumAssemble(); barycontrib->Save(femmodel->results,femmodel->parameters,totaloceanarea); barycontrib->Reset(); } @@ -465,6 +468,7 @@ void dynstr_core(FemModel* femmodel){ /*{{{*/ /*parameters: */ int step; + int gsize; bool isocean=false; IssmDouble time; @@ -493,7 +497,9 @@ void dynstr_core(FemModel* femmodel){ /*{{{*/ femmodel->parameters->FindParam(&cumgmtslc,CumGmtslcEnum); femmodel->parameters->FindParam(&cumbslc,CumBslcEnum); - gmtslc=deltastr->Norm(NORM_TWO); + deltastr->Sum(&gmtslc); + deltastr->GetSize(&gsize); + gmtslc/=reCast(gsize); cumgmtslc+=gmtslc; cumgmslc=cumbslc+cumgmtslc; @@ -582,7 +588,6 @@ void ivins_deformation_core(FemModel* femmodel){ /*{{{*/ } /*Assemble parallel vector:*/ - beduprate->Assemble(); bedup->Assemble(); /*Save results:*/ @@ -609,19 +614,11 @@ void sealevelchange_initialgeometry(FemModel* femmodel) { /*{{{*/ int* lids=NULL; int* n_activevertices=NULL; int grdmodel=0; - bool geometrydone; /*retrieve parameters:*/ femmodel->parameters->FindParam(&grdmodel,GrdModelEnum); nel=femmodel->elements->NumberOfElements(); - /*did we already do this? if so, skip :*/ - femmodel->parameters->FindParam(&geometrydone,SealevelchangeGeometryDoneEnum); - if (geometrydone){ - if(VerboseSolution()) _printf0_(" initial sea level geometrical already computed, skipping.\n"); - return; - } - /*early return?:*/ if(grdmodel!=ElasticEnum) return; @@ -634,13 +631,14 @@ void sealevelchange_initialgeometry(FemModel* femmodel) { /*{{{*/ /*Compute element ids, used to speed up computations in convolution phase:{{{*/ lids=xNew(femmodel->vertices->Size()); n_activevertices = xNew(nel); - //initialize lids to -1, vertex count to 3 + //initialize lids to -1, vertex count to 0 for (int v=0; vvertices->Size();v++) lids[v]=-1; - for (int e=0; eelements->objects){ Element* element=xDynamicCast(object); - for(int i=0;i<3;i++){ + n_activevertices[element->lid]=element->GetNumberOfVertices(); + for(int i=0;iGetNumberOfVertices();i++){ // if lids where we are looking points to an element id (.i.e. not -1) then we are about to claim that element's vertex // and need to lower the number of vertices it is in charge of if (lids[element->vertices[i]->lid] !=-1){ @@ -669,9 +667,6 @@ void sealevelchange_initialgeometry(FemModel* femmodel) { /*{{{*/ femmodel->results->AddResult(new GenericExternalResult(femmodel->results->Size()+1,ZzeEnum,zze,nel,1,1,1)); femmodel->results->AddResult(new GenericExternalResult(femmodel->results->Size()+1,AreaeEnum,areae,nel,1,1,1)); #endif - - geometrydone=true; - femmodel->parameters->SetParam(geometrydone,SealevelchangeGeometryDoneEnum); xDelete(xxe); xDelete(yye); @@ -695,7 +690,7 @@ SealevelGeometry* sealevelchange_geometry(FemModel* femmodel) { /*{{{*/ IssmDouble* areae = NULL; int nel; - int grdmodel=0; + int grdmodel=0; int isgrd=0; int count, frequency; SealevelGeometry* slgeom=NULL; @@ -706,7 +701,7 @@ SealevelGeometry* sealevelchange_geometry(FemModel* femmodel) { /*{{{*/ femmodel->parameters->FindParam(&count,SealevelchangeRunCountEnum); femmodel->parameters->FindParam(&frequency,SolidearthSettingsRunFrequencyEnum); if(grdmodel!=ElasticEnum || !isgrd) return NULL; - if(count!=frequency) return NULL; + if(count!=frequency)return NULL; /*retrieve parameters:*/ femmodel->parameters->FindParam(&xxe,&nel,XxeEnum); @@ -747,11 +742,6 @@ SealevelGeometry* sealevelchange_geometry(FemModel* femmodel) { /*{{{*/ /*Compute spherical harmonic functions for spatial integrations of the loads*/ slgeom->BuildSphericalHarmonics(); - femmodel->parameters->AddObject(new DoubleVecParam(XxeEnum,xxe,nel)); - femmodel->parameters->AddObject(new DoubleVecParam(YyeEnum,yye,nel)); - femmodel->parameters->AddObject(new DoubleVecParam(ZzeEnum,zze,nel)); - femmodel->parameters->AddObject(new DoubleVecParam(AreaeEnum,areae,nel)); - /*Free resources:*/ xDelete(xxe); xDelete(yye); @@ -762,43 +752,52 @@ SealevelGeometry* sealevelchange_geometry(FemModel* femmodel) { /*{{{*/ }/*}}}*/ void sealevelchange_finalize(FemModel* femmodel) { /*{{{*/ - bool isuq=false; - + BarystaticContributions* barycontrib=NULL; GenericParam* barycontribparam=NULL; - + femmodel->parameters->FindParam(&isuq,QmuIsdakotaEnum); + barycontribparam=xDynamicCast*>( + femmodel->parameters->FindParamObject(BarystaticContributionsEnum) + ); + if(!barycontribparam) return; + + barycontrib=barycontribparam->GetParameterValue(); + if(!barycontrib) return; + if(isuq){ - //reset barycontrib object: - barycontribparam = xDynamicCast*>(femmodel->parameters->FindParamObject(BarystaticContributionsEnum)); - barycontrib=barycontribparam->GetParameterValue(); barycontrib->Finalize(); } - else { - /*Erase barycontrib object: */ - barycontribparam = xDynamicCast*>(femmodel->parameters->FindParamObject(BarystaticContributionsEnum)); - barycontrib=barycontribparam->GetParameterValue(); + else{ + femmodel->parameters->AddObject( + new GenericParam((BarystaticContributions*)NULL,BarystaticContributionsEnum) + ); delete barycontrib; } - - return; - }/*}}}*/ void slc_geometry_cleanup(SealevelGeometry* slgeom, FemModel* femmodel){ /*{{{*/ + int grdmodel=0; + int isgrd=0; + int horiz=0; + int count, frequency; /*early return?:*/ - if(slgeom==NULL) return; - - int horiz; + femmodel->parameters->FindParam(&grdmodel,GrdModelEnum); + femmodel->parameters->FindParam(&isgrd,SolidearthSettingsGRDEnum); femmodel->parameters->FindParam(&horiz,SolidearthSettingsHorizEnum); + femmodel->parameters->FindParam(&count,SealevelchangeRunCountEnum); + femmodel->parameters->FindParam(&frequency,SolidearthSettingsRunFrequencyEnum); + if(grdmodel!=ElasticEnum || !isgrd) return; + if(count!=frequency)return; + for (int l=0;linputs->DeleteInput(slgeom->AlphaIndexEnum(l)); - if(horiz) femmodel->inputs->DeleteInput(slgeom->AzimuthIndexEnum(l)); + if (horiz) femmodel->inputs->DeleteInput(slgeom->AzimuthIndexEnum(l)); } - delete slgeom; + if (slgeom) delete slgeom; } /*}}}*/ /*subroutines:*/ @@ -806,19 +805,17 @@ bool slcconvergence(IssmDouble* RSLg,IssmDouble* RSLg_old,IssmDouble eps_r int nel; bool converged=true; - IssmDouble ndS,nS, nS_old; - IssmDouble* dRSLg = NULL; - IssmDouble rho_water =0; + IssmDouble rho_water; femmodel->parameters->FindParam(&nel,MeshNumberofelementsEnum); femmodel->parameters->FindParam(&rho_water,MaterialsRhoSeawaterEnum); //compute norm(du) and norm(u) if requested - dRSLg=xNewZeroInit(nel); + IssmDouble* dRSLg=xNewZeroInit(nel); - ndS=0; - nS=0; - nS_old=0; + IssmDouble ndS=0; + IssmDouble nS=0; + IssmDouble nS_old=0; for (int e=0;e(eps_rel)){ - if((ndS/nS) " << eps_rel*100 << " %\n"); + converged=false; + } + } + else if((ndS/nS) beginning of the simulation - if(t==viscousindex){ - m1interp[t]= m1[0]; - m2interp[t]= m2[0]; - m3interp[t]= m3[0]; - } - else{ //we reinterpolate PM on viscoustimes, so we can handle the case where we are running with adaptative/uneven time steps - int tprime=t-viscousindex-1; - m1interp[t]= (1.0-lincoeff)*m1[tprime]+lincoeff*m1[tprime+1]; - m2interp[t]= (1.0-lincoeff)*m2[tprime]+lincoeff*m2[tprime+1]; - m3interp[t]= (1.0-lincoeff)*m3[tprime]+lincoeff*m3[tprime+1]; - } + m1interp[viscousindex]=m1[0]; + m2interp[viscousindex]=m2[0]; + m3interp[viscousindex]=m3[0]; + int t; + for(t=viscousindex+1;t beginning of the simulation + IssmDouble elapsedtime=viscoustimes[t]-viscoustimes[viscousindex]; + int tprime=reCast(elapsedtime/timeacc); + if(tprime>=nt-1) break; + lincoeff=(elapsedtime-timeacc*tprime)/timeacc; + m1interp[t]= (1.0-lincoeff)*m1[tprime]+lincoeff*m1[tprime+1]; + m2interp[t]= (1.0-lincoeff)*m2[tprime]+lincoeff*m2[tprime+1]; + m3interp[t]= (1.0-lincoeff)*m3[tprime]+lincoeff*m3[tprime+1]; + } + for(;tparameters->FindParam(¤ttime,TimeEnum); if (rotation) femmodel->parameters->FindParam(&viscouspolarmotion,NULL,NULL,SealevelchangeViscousPolarMotionEnum); + if(currenttime=currenttime){ + if (viscoustimes[t]>currenttime){ newindex=t-1; foundtime=true; lincoeff=(currenttime-viscoustimes[newindex])/(viscoustimes[t]-viscoustimes[newindex]); @@ -1088,7 +1102,7 @@ IssmDouble* CombineLoads(IssmDouble* load,IssmDouble* subload,FemModel* femmodel for(int i=0;i* vloadcopy=new Vector(nel); - IssmDouble* loadcopy=xNew(nel); + IssmDouble* loadcopy=NULL; vloadcopy->SetValues(nel,indices,load,INS_VAL); vloadcopy->Assemble(); @@ -1106,6 +1120,9 @@ IssmDouble* CombineLoads(IssmDouble* load,IssmDouble* subload,FemModel* femmodel vloadcopy->Assemble(); loadcopy=vloadcopy->ToMPISerial(); + xDelete(indices); + delete vloadcopy; + return loadcopy; } /*}}}*/ @@ -1119,7 +1136,6 @@ void TransferForcing(FemModel* femmodel,int forcingenum){ /*{{{*/ Vector* forcingglobal=NULL; IssmDouble* transfercount=NULL; int* nvs=NULL; - int modelid,earthid,nummodels; /*transition vectors:*/ IssmDouble** transitions=NULL; @@ -1130,18 +1146,18 @@ void TransferForcing(FemModel* femmodel,int forcingenum){ /*{{{*/ int existforcing=0; /*communicators:*/ - ISSM_MPI_Comm tocomm; - ISSM_MPI_Comm *fromcomms = NULL; - ISSM_MPI_Status status; - ISSM_MPI_Request send_request_1=ISSM_MPI_REQUEST_NULL; - ISSM_MPI_Request send_request_2=ISSM_MPI_REQUEST_NULL; - ISSM_MPI_Request send_request_3=ISSM_MPI_REQUEST_NULL; + ISSM_MPI_Comm tocomm; + ISSM_MPI_Comm* fromcomms=NULL; + ISSM_MPI_Status status; + int my_rank; + int modelid,earthid; + int nummodels; /*Recover some parameters: */ femmodel->parameters->FindParam(&modelid,ModelIdEnum); femmodel->parameters->FindParam(&earthid,EarthIdEnum); femmodel->parameters->FindParam(&nummodels,NumModelsEnum); - int my_rank=IssmComm::GetRank(); + my_rank=IssmComm::GetRank(); /*retrieve the inter communicators that will be used to send data from each ice cap to the earth: */ if(modelid==earthid){ @@ -1166,7 +1182,7 @@ void TransferForcing(FemModel* femmodel,int forcingenum){ /*{{{*/ } } - /*Send the forcing to the earth model*/ + /*Send the forcing to the earth model:{{{*/ if(my_rank==0){ if(modelid==earthid){ forcings=xNew(nummodels-1); @@ -1185,13 +1201,14 @@ void TransferForcing(FemModel* femmodel,int forcingenum){ /*{{{*/ } else{ - ISSM_MPI_Isend(&existforcing, 1, ISSM_MPI_INT, 0, modelid, tocomm,&send_request_1); + ISSM_MPI_Send(&existforcing, 1, ISSM_MPI_INT, 0, modelid, tocomm); if(existforcing){ - ISSM_MPI_Isend(&nv, 1, ISSM_MPI_INT, 0, modelid, tocomm, &send_request_2); - ISSM_MPI_Isend(forcing, nv, ISSM_MPI_DOUBLE, 0, modelid, tocomm, &send_request_3); + ISSM_MPI_Send(&nv, 1, ISSM_MPI_INT, 0, modelid, tocomm); + ISSM_MPI_Send(forcing, nv, ISSM_MPI_DOUBLE, 0, modelid, tocomm); } } } + /*}}}*/ /*On the earth model, consolidate all the forcings into one, and update the elements dataset accordingly*/ if(modelid==earthid){ @@ -1201,7 +1218,7 @@ void TransferForcing(FemModel* femmodel,int forcingenum){ /*{{{*/ nv=femmodel->vertices->NumberOfVertices(); GetVectorFromInputsx(&forcingglobal,femmodel,forcingenum,VertexSIdEnum); - forcingglobal->Set(0.); + forcingglobal->Set(0.0); /*Retrieve transition vectors, used to plug from each ice cap into the global forcing:*/ femmodel->parameters->FindParam(&transitions,&ntransitions,&transitions_m,&transitions_n,SealevelchangeTransitionsEnum); @@ -1218,7 +1235,7 @@ void TransferForcing(FemModel* femmodel,int forcingenum){ /*{{{*/ int M=transitions_m[i]; /*build index to plug values: */ - int* index=xNew(M); for(int i=0;i(transition[i])-1; //matlab indexing! + int* index=xNew(M); for(int i=0;i(transition[i])-1; //matlab indexing! /*We are going to plug this vector into the earth model, at the right vertices corresponding to this particular * ice cap: */ @@ -1235,21 +1252,17 @@ void TransferForcing(FemModel* femmodel,int forcingenum){ /*{{{*/ /*Plug into elements:*/ InputUpdateFromVectorx(femmodel,forcingglobal,forcingenum,VertexSIdEnum); } + /*}}}*/ - /*Free resources:*/ - if(my_rank==0 && modelid!=earthid){ - ISSM_MPI_Wait(&send_request_1,&status); - if(existforcing){ - ISSM_MPI_Wait(&send_request_2,&status); - ISSM_MPI_Wait(&send_request_3,&status); - } - } + /*Free resources:{{{*/ if(forcings){ - for(int i=0;i(forcings[i]); + for(int i=0;i(temp); + } xDelete(forcings); } if(forcing)xDelete(forcing); - if(transfercount) xDelete(transfercount); if(forcingglobal)delete forcingglobal; if(transitions){ for(int i=0;i(transitions_m); xDelete(transitions_n); } + if(transfercount) xDelete(transfercount); if(nvs)xDelete(nvs); + /*}}}*/ + } /*}}}*/ void TransferSealevel(FemModel* femmodel,int forcingenum){ /*{{{*/ /*forcing being transferred from earth to ice caps: */ + IssmDouble** forcings=NULL; IssmDouble* forcing=NULL; IssmDouble* forcingglobal=NULL; @@ -1273,9 +1290,7 @@ void TransferSealevel(FemModel* femmodel,int forcingenum){ /*{{{*/ int ntransitions; int* transitions_m=NULL; int* transitions_n=NULL; - int nv; - int modelid,earthid,nummodels; - int numcoms; + int nv; /*communicators:*/ ISSM_MPI_Comm fromcomm; @@ -1283,26 +1298,26 @@ void TransferSealevel(FemModel* femmodel,int forcingenum){ /*{{{*/ ISSM_MPI_Status status; ISSM_MPI_Request* send_requests_1=NULL; ISSM_MPI_Request* send_requests_2=NULL; - + int my_rank; + int modelid,earthid; + int nummodels; /*Recover some parameters: */ femmodel->parameters->FindParam(&modelid,ModelIdEnum); femmodel->parameters->FindParam(&earthid,EarthIdEnum); femmodel->parameters->FindParam(&nummodels,NumModelsEnum); - int my_rank=IssmComm::GetRank(); + my_rank=IssmComm::GetRank(); /*retrieve the inter communicators that will be used to send data from earth to ice caps:*/ if(modelid==earthid){ GenericParam* parcoms = dynamic_cast*>(femmodel->parameters->FindParamObject(IcecapToEarthCommEnum)); if(!parcoms)_error_("TransferSealevel error message: could not find IcecapToEarthComm communicator"); tocomms=parcoms->GetParameterValue(); - //femmodel->parameters->FindParam((int**)(&tocomms),&numcoms,IcecapToEarthCommEnum); } else{ GenericParam* parcom = dynamic_cast*>(femmodel->parameters->FindParamObject(IcecapToEarthCommEnum)); if(!parcom)_error_("TransferSealevel error message: could not find IcecapToEarthComm communicator"); fromcomm=parcom->GetParameterValue(); - //femmodel->parameters->FindParam((int*)(&fromcomm), IcecapToEarthCommEnum); } /*Retrieve sea-level on earth model: */ @@ -1318,26 +1333,28 @@ void TransferSealevel(FemModel* femmodel,int forcingenum){ /*{{{*/ /*Retrieve transition vectors, used to figure out global forcing contribution to each ice cap's own elements: */ femmodel->parameters->FindParam(&transitions,&ntransitions,&transitions_m,&transitions_n,SealevelchangeTransitionsEnum); - if(ntransitions!=earthid) _error_("TransferSealevel error message: number of transition vectors is not equal to the number of icecaps!"); - /*Prepare requests*/ - send_requests_1 = xNew(earthid); - send_requests_2 = xNew(earthid); - for(int i=0;i(nummodels-1); + send_requests_1=xNew(nummodels-1); + send_requests_2=xNew(nummodels-1); + for(int i=0;i(nv); + forcings[i]=xNew(nv); IssmDouble* transition=transitions[i]; for(int j=0;j(transition[j])-1]; + forcings[i][j]=forcingglobal[reCast(transition[j])-1]; } - ISSM_MPI_Isend(&nv, 1, ISSM_MPI_INT, 0, i, tocomms[i], &send_requests_1[i]); - ISSM_MPI_Isend(forcing, nv, ISSM_MPI_DOUBLE, 0, i, tocomms[i], &send_requests_2[i]); - xDelete(forcing); + ISSM_MPI_Isend(&transitions_m[i], 1, ISSM_MPI_INT, 0, i, tocomms[i], &send_requests_1[i]); + ISSM_MPI_Isend(forcings[i], nv, ISSM_MPI_DOUBLE, 0, i, tocomms[i], &send_requests_2[i]); } } else{ @@ -1358,14 +1375,16 @@ void TransferSealevel(FemModel* femmodel,int forcingenum){ /*{{{*/ InputUpdateFromVectorx(femmodel,forcing,forcingenum,VertexSIdEnum); } - /*Free resources:*/ + /*Free resources:{{{*/ if(my_rank==0 && modelid==earthid){ - for(int i=0;i(forcings[i]); } xDelete(send_requests_1); xDelete(send_requests_2); + xDelete(forcings); } if(forcingglobal)xDelete(forcingglobal); if(forcing)xDelete(forcing); @@ -1378,5 +1397,6 @@ void TransferSealevel(FemModel* femmodel,int forcingenum){ /*{{{*/ xDelete(transitions_m); xDelete(transitions_n); } + /*}}}*/ } /*}}}*/ diff --git a/src/c/cores/surfaceslope_core.cpp b/src/c/cores/surfaceslope_core.cpp index 3edfd219f..fb9fffaa6 100644 --- a/src/c/cores/surfaceslope_core.cpp +++ b/src/c/cores/surfaceslope_core.cpp @@ -19,7 +19,7 @@ void surfaceslope_core(FemModel* femmodel){ femmodel->parameters->FindParam(&save_results,SaveResultsEnum); femmodel->parameters->FindParam(&domaintype,DomainTypeEnum); - if(VerboseSolution()) _printf0_("computing slope...\n"); + if(VerboseSolution()) _printf0_(" computing surface slopes\n"); /*Call on core computations: */ femmodel->SetCurrentConfiguration(L2ProjectionBaseAnalysisEnum); diff --git a/src/c/main/issm_dakota.cpp b/src/c/main/issm_dakota.cpp index eb83aa9a4..072f1be43 100644 --- a/src/c/main/issm_dakota.cpp +++ b/src/c/main/issm_dakota.cpp @@ -9,6 +9,7 @@ #include "ParallelLibrary.hpp" #include "ProblemDescDB.hpp" #include "LibraryEnvironment.hpp" +#include "OutputManager.hpp" #include "DakotaModel.hpp" #include "DakotaInterface.hpp" #endif @@ -53,6 +54,20 @@ int main(int argc,char **argv){ /*{{{*/ /* Defaults constructs the MPIManager, which assumes COMM_WORLD*/ Dakota::LibraryEnvironment env(opts); + /* Redirect dakota_tabular.dat into the execution directory (same rootpath as outbin), + * so it is written alongside other output files rather than in the process CWD */ + { + Dakota::ProblemDescDB& pdb = env.problem_description_db(); + Dakota::OutputManager& om = pdb.parallel_library().output_manager(); + if (om.tabularDataFlag) { + std::string tabname = om.tabularDataFile.empty() ? "dakota_tabular.dat" : om.tabularDataFile; + /* strip any directory component the user may have put in tabname */ + std::string::size_type slash = tabname.rfind('/'); + if (slash != std::string::npos) tabname = tabname.substr(slash + 1); + om.tabularDataFile = std::string(argv[2]) + "/" + tabname; + } + } + /* get the list of all models matching the specified model, interface, driver:*/ Dakota::ModelList filt_models = env.filtered_model_list("single", "direct", "matlab"); if (filt_models.empty()) { diff --git a/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.cpp b/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.cpp index 3546e0abb..bb494bdee 100644 --- a/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.cpp +++ b/src/c/modules/FloatingiceMeltingRatex/FloatingiceMeltingRatex.cpp @@ -223,10 +223,14 @@ void FloatingiceMeltingRateIsmip7x(FemModel* femmodel){/*{{{*/ IssmDouble g; IssmDouble* tf_depths=NULL; int num_depths; + bool islocal; femmodel->parameters->FindParam(&time,TimeEnum); + //femmodel->parameters->FindParam(&num_basins,BasalforcingsIsmip7NumBasinsEnum); femmodel->parameters->FindParam(&tf_depths,&num_depths,BasalforcingsIsmip7TfDepthsEnum); _assert_(tf_depths); + /* FIXME: What does Ismip7IsLocal value contribute to? */ + femmodel->parameters->FindParam(&islocal,BasalforcingsIsmip7IsLocalEnum); /*Binary search works for vectors that are sorted in increasing order only, make depths positive*/ //if(VerboseSolution())_printf0_(" ismip7: prepare binary search\n"); diff --git a/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dx.cpp b/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dx.cpp index 8d6060ff8..b028d8ce6 100644 --- a/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dx.cpp +++ b/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dx.cpp @@ -19,7 +19,6 @@ int InterpFromMesh2dx(IssmSeqVec** pdata_prime, /*Intermediary*/ int i; int interpolation_type; - bool debug; double xmin,xmax; double ymin,ymax; @@ -31,9 +30,6 @@ int InterpFromMesh2dx(IssmSeqVec** pdata_prime, _error_("nothing to be done according to the mesh given in input"); } - /*Set debug to 1 if there are lots of elements*/ - debug=(bool)((double)nels_data*(double)nods_prime >= pow((double)10,(double)9)); - /*figure out what kind of interpolation is needed*/ if (data_length==nods_data){ interpolation_type=1; @@ -77,7 +73,6 @@ int InterpFromMesh2dx(IssmSeqVec** pdata_prime, /*initialize thread parameters: */ InterpFromMesh2dxThreadStruct gate; gate.interpolation_type = interpolation_type; - gate.debug = debug; gate.nels_data = nels_data; gate.index_data = index_data; gate.x_data = x_data; diff --git a/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dx.h b/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dx.h index 59db2bb63..b7cd52655 100644 --- a/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dx.h +++ b/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dx.h @@ -10,24 +10,21 @@ /*threading: */ typedef struct{ - - int interpolation_type; - bool debug; - int nels_data; - int *index_data; - double *x_data; - double *y_data; - double *data; - double xmin,xmax; - double ymin,ymax; - int nods_prime; + int interpolation_type; + int nels_data; + int *index_data; + double *x_data; + double *y_data; + double *data; + double xmin,xmax; + double ymin,ymax; + int nods_prime; IssmSeqVec *data_prime; - double *x_prime; - double *y_prime; - double *default_values; - int num_default_values; - double *incontour; - + double *x_prime; + double *y_prime; + double *default_values; + int num_default_values; + double *incontour; } InterpFromMesh2dxThreadStruct; int InterpFromMesh2dx(IssmSeqVec** pdata_prime,int* index_data, double* x_data, double* y_data, int nods_data,int nels_data, double* data, int data_length, double* x_prime, double* y_prime, int nods_prime, diff --git a/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dxt.cpp b/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dxt.cpp index 6252b80f6..ebf085fc4 100644 --- a/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dxt.cpp +++ b/src/c/modules/InterpFromMesh2dx/InterpFromMesh2dxt.cpp @@ -20,7 +20,6 @@ void* InterpFromMesh2dxt(void* vpthread_handle){ /*recover parameters :*/ int interpolation_type = gate->interpolation_type; - bool debug = gate->debug; int nels_data = gate->nels_data; int *index_data = gate->index_data; double *x_data = gate->x_data; @@ -44,10 +43,6 @@ void* InterpFromMesh2dxt(void* vpthread_handle){ /*Loop over the elements*/ for(i=i0;ixmax) && (x_data[index_data[3*i+1]-1]>xmax) && (x_data[index_data[3*i+2]-1]>xmax)) continue; @@ -97,7 +92,5 @@ void* InterpFromMesh2dxt(void* vpthread_handle){ } } } - if(debug && my_thread==0) - _printf_("\r interpolation progress: "<(cm_responses); parameters->AddObject(new IntVecParam(InversionCostFunctionsEnum,costfunc_enums,num_costfunc)); xDelete(costfunc_enums); - + } break; - } + case 5:/*Nudging*/ + { + /*Nothing to do here*/ + break; + } default: _error_("not supported"); } @@ -147,7 +151,10 @@ void CreateParametersControl(Parameters* parameters,IoModel* iomodel,int solutio parameters->AddObject(iomodel->CopyConstantObject("md.inversion.gttol",InversionGttolEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.inversion.maxsteps",InversionMaxstepsEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.inversion.maxiter",InversionMaxiterEnum)); - break; + break; + case 5: /*Nudging*/ + parameters->AddObject(iomodel->CopyConstantObject("md.inversion.tau_C",InversionTauCEnum)); + break; default: _error_("not supported"); } diff --git a/src/c/modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp b/src/c/modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp index 735f490fd..5f3a02c19 100644 --- a/src/c/modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp +++ b/src/c/modules/ModelProcessorx/Control/UpdateElementsAndMaterialsControl.cpp @@ -8,8 +8,29 @@ #include "../ModelProcessorx.h" void UpdateElementsAndMaterialsControl(Elements* elements,Parameters* parameters,Inputs* inputs,Materials* materials, IoModel* iomodel){ - /*Intermediary*/ + + /*Return if iscontrol is 0*/ bool control_analysis; + iomodel->FindConstant(&control_analysis,"md.inversion.iscontrol"); + if(!control_analysis) return; + + /*Use dedicated function if AD*/ + bool isautodiff; + iomodel->FindConstant(&isautodiff,"md.autodiff.isautodiff"); + if(isautodiff){ + UpdateElementsAndMaterialsControlAD(elements,parameters,inputs,materials,iomodel); + return; + } + + /*Simple case for nudging*/ + int inversiontype; + iomodel->FindConstant(&inversiontype,"md.inversion.type"); + if(inversiontype==5){ + iomodel->FetchDataToInput(inputs,elements,"md.inversion.dhdt_obs",BalancethicknessThickeningRateEnum); + return; + } + + /*General case*/ int M,N; int control,cost_function,domaintype; int num_controls,num_cost_functions; @@ -24,18 +45,6 @@ void UpdateElementsAndMaterialsControl(Elements* elements,Parameters* parameters IssmDouble *independents_max = NULL; IssmDouble *weights = NULL; - /*Fetch parameters: */ - iomodel->FindConstant(&control_analysis,"md.inversion.iscontrol"); - if(!control_analysis) return; - - /*Fetch parameters: */ - bool isautodiff; - iomodel->FindConstant(&isautodiff,"md.autodiff.isautodiff"); - if(isautodiff){ - UpdateElementsAndMaterialsControlAD(elements,parameters,inputs,materials,iomodel); - return; - } - /*Process controls and convert from string to enums*/ iomodel->FindConstant(&num_controls,"md.inversion.num_control_parameters"); iomodel->FindConstant(&controls,&num_controls,"md.inversion.control_parameters"); diff --git a/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp b/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp index 4e2f4f2d7..e8e6cfb4b 100644 --- a/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp +++ b/src/c/modules/ModelProcessorx/CreateElementsVerticesAndMaterials.cpp @@ -43,7 +43,6 @@ void CreateElements(Elements* elements,IoModel* iomodel,const int nummodels){/*{ _assert_(elements->Size()==0); /*Create elements*/ - if(control_analysis && !adolc_analysis)iomodel->FetchData(2,"md.inversion.min_parameters","md.inversion.max_parameters"); if(iomodel->domaintype==Domain2DverticalEnum || iomodel->domaindim==3) iomodel->FetchData(2,"md.mesh.vertexonbase","md.mesh.vertexonsurface"); int count = 0; @@ -78,7 +77,7 @@ void CreateElements(Elements* elements,IoModel* iomodel,const int nummodels){/*{ } /*Free data: */ - iomodel->DeleteData(6,"md.mesh.upperelements","md.mesh.lowerelements","md.inversion.min_parameters","md.inversion.max_parameters","md.mesh.vertexonbase","md.mesh.vertexonsurface"); + iomodel->DeleteData(4,"md.mesh.upperelements","md.mesh.lowerelements","md.mesh.vertexonbase","md.mesh.vertexonsurface"); }/*}}}*/ void CreateMaterials(Elements* elements,Inputs* inputs,Materials* materials,IoModel* iomodel,const int nummodels){/*{{{*/ @@ -450,12 +449,15 @@ void CreateVertices(Elements* elements,Vertices* vertices,IoModel* iomodel,int s if(solution_type!=LoveSolutionEnum) CreateNumberNodeToElementConnectivity(iomodel); if(!isamr){ int isoceancoupling; + int smb_model; iomodel->FindConstant(&isoceancoupling,"md.transient.isoceancoupling"); + iomodel->FindConstant(&smb_model,"md.smb.model"); //iomodel->FetchData(6,"md.mesh.x","md.mesh.y","md.mesh.z","md.geometry.base","md.geometry.thickness","md.mask.ice_levelset"); iomodel->FetchData(5,"md.mesh.x","md.mesh.y","md.mesh.z","md.geometry.base","md.geometry.thickness"); if (iomodel->domaintype == Domain3DsurfaceEnum) iomodel->FetchData(3,"md.mesh.lat","md.mesh.long","md.mesh.r"); if (isoceancoupling) iomodel->FetchData(2,"md.mesh.lat","md.mesh.long"); + if (smb_model==SMBmariaEnum) iomodel->FetchData(2,"md.mesh.lat","md.mesh.long"); for(int i=0;inumberofvertices;i++){ if(vertices_offsets[i]!=-1){ @@ -469,6 +471,7 @@ void CreateVertices(Elements* elements,Vertices* vertices,IoModel* iomodel,int s iomodel->DeleteData(5,"md.mesh.x","md.mesh.y","md.mesh.z","md.geometry.base","md.geometry.thickness"); if (iomodel->domaintype == Domain3DsurfaceEnum) iomodel->DeleteData(3,"md.mesh.lat","md.mesh.long","md.mesh.r"); if (isoceancoupling) iomodel->DeleteData(2,"md.mesh.lat","md.mesh.long"); + if (smb_model==SMBmariaEnum) iomodel->DeleteData(2,"md.mesh.lat","md.mesh.long"); } else{ for(int i=0;inumberofvertices;i++){ diff --git a/src/c/modules/ModelProcessorx/CreateParameters.cpp b/src/c/modules/ModelProcessorx/CreateParameters.cpp index 66a7f990b..1c77f68a6 100644 --- a/src/c/modules/ModelProcessorx/CreateParameters.cpp +++ b/src/c/modules/ModelProcessorx/CreateParameters.cpp @@ -14,6 +14,68 @@ #include "../ParseToolkitsOptionsx/ParseToolkitsOptionsx.h" #include "./ModelProcessorx.h" +#ifdef _HAVE_PyBind11_ +#include +static void BuildGnnAdjacencyFromElements(IoModel* iomodel, Parameters* parameters) {/*{{{*/ + + int n_points = iomodel->numberofvertices; + int n_elems = iomodel->numberofelements; + int nperelem = 3; + int* elements = iomodel->elements; + + std::vector< std::vector > node_to_elems(n_points); + for (int e = 0; e < n_elems; ++e) { + for (int loc = 0; loc < nperelem; ++loc) { + int v = elements[e*nperelem + loc] - 1; // convert to 0-based + if (v < 0 || v >= n_points) _error_("BuildGnnAdjacencyFromElements: bad vertex index"); + node_to_elems[v].push_back(e); + } + } + + std::vector src; + std::vector dst; + + src.reserve(6 * n_points); + dst.reserve(6 * n_points); + + for (int i0 = 0; i0 < n_points; ++i0) { + std::vector connect; + connect.reserve(16); + const std::vector& elems_for_node = node_to_elems[i0]; + for (int idx = 0; idx < (int)elems_for_node.size(); ++idx) { + int e = elems_for_node[idx]; + for (int loc = 0; loc < nperelem; ++loc) { + int k0 = elements[e*nperelem + loc] - 1; // 0-based + if (k0 == i0) continue; + bool seen = false; + for (int c : connect) { + if (c == k0) { seen = true; break; } + } + if (seen) continue; + connect.push_back(k0); + src.push_back(i0); + dst.push_back(k0); + } + } + } + + int nedges = (int)src.size(); + int* src_arr = xNew(nedges); + int* dst_arr = xNew(nedges); + for (int i = 0; i < nedges; ++i) { + src_arr[i] = src[i]; + dst_arr[i] = dst[i]; + } + + parameters->AddObject(new IntParam(EdgesNumberEnum, nedges)); + parameters->AddObject(new IntVecParam(EdgesSrcEnum, src_arr, nedges)); + parameters->AddObject(new IntVecParam(EdgesDstEnum, dst_arr, nedges)); + + xDelete(src_arr); + xDelete(dst_arr); +}/*}}}*/ +#endif + void CreateParameters(Parameters* parameters,IoModel* iomodel,char* rootpath,FILE* toolkitsoptionsfid,const int solution_type){ int i,j,m,k; @@ -103,6 +165,10 @@ void CreateParameters(Parameters* parameters,IoModel* iomodel,char* rootpath,FIL parameters->AddObject(iomodel->CopyConstantObject("md.stressbalance.abstol",StressbalanceAbstolEnum)); if(iomodel->domaintype==Domain3DEnum) parameters->AddObject(iomodel->CopyConstantObject("md.mesh.numberoflayers",MeshNumberoflayersEnum)); + + #ifdef _HAVE_PyBind11_ + BuildGnnAdjacencyFromElements(iomodel, parameters); + #endif } /*amr properties*/ @@ -289,6 +355,10 @@ void CreateParameters(Parameters* parameters,IoModel* iomodel,char* rootpath,FIL case BasalforcingsIsmip7Enum: parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.num_basins",BasalforcingsIsmip7NumBasinsEnum)); parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.gamma",BasalforcingsIsmip7GammaEnum)); + parameters->AddObject(iomodel->CopyConstantObject("md.basalforcings.islocal",BasalforcingsIsmip7IsLocalEnum)); + iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.delta_t"); + parameters->AddObject(new DoubleVecParam(BasalforcingsIsmip7DeltaTEnum,transparam,N)); + xDelete(transparam); iomodel->FetchData(&transparam,&M,&N,"md.basalforcings.tf_depths"); parameters->AddObject(new DoubleVecParam(BasalforcingsIsmip7TfDepthsEnum,transparam,N)); xDelete(transparam); diff --git a/src/c/modules/StressBalanceEmulatorx/StressBalanceEmulatorx.cpp b/src/c/modules/StressBalanceEmulatorx/StressBalanceEmulatorx.cpp new file mode 100644 index 000000000..6990d88d1 --- /dev/null +++ b/src/c/modules/StressBalanceEmulatorx/StressBalanceEmulatorx.cpp @@ -0,0 +1,128 @@ +/*!\file StressBalanceEmulatorx + * \brief: evaluate stressbalance emulator and update velocity inputs + */ + +#include "./StressBalanceEmulatorx.h" +#include "../../toolkits/toolkits.h" +#include "../modules.h" + +#include +#include +#include +#include + +#include +namespace py = pybind11; + +void StressBalanceEmulatorx(FemModel* femmodel){/*{{{*/ + + if(!femmodel->parameters->Exist(StressbalanceEmulatorEnum)) _error_("StressbalanceEmulatorEnum not found; stressbalance emulator was not initialized"); + Param* emulator_param = femmodel->parameters->FindParamObject(StressbalanceEmulatorEnum); + if(emulator_param->ObjectEnum()!=EmulatorParamEnum) _error_("Parameter should be EmulatorParam"); + EmulatorParam* emulator = xDynamicCast(emulator_param); + + int rank = IssmComm::GetRank(); + int numberofvertices = femmodel->vertices->NumberOfVertices(); + IssmDouble yts; + femmodel->parameters->FindParam(&yts,ConstantsYtsEnum); + + /*Recover geometry and model inputs*/ + IssmDouble* thickness = NULL; + IssmDouble* base = NULL; + IssmDouble* frictionc = NULL; + IssmDouble* mask = NULL; + IssmDouble* vx = NULL; + IssmDouble* vy = NULL; + int thickness_size = 0; + int base_size = 0; + int frictionc_size = 0; + int mask_size = 0; + int vx_size = 0; + int vy_size = 0; + + GetVectorFromInputsx(&thickness,&thickness_size,femmodel,ThicknessEnum); + GetVectorFromInputsx(&base,&base_size,femmodel,BaseEnum); + GetVectorFromInputsx(&frictionc,&frictionc_size,femmodel,FrictionCEnum); + GetVectorFromInputsx(&mask,&mask_size,femmodel,MaskIceLevelsetEnum); + GetVectorFromInputsx(&vx,&vx_size,femmodel,VxEnum); + GetVectorFromInputsx(&vy,&vy_size,femmodel,VyEnum); + + if(thickness_size!=numberofvertices || base_size!=numberofvertices || frictionc_size!=numberofvertices || mask_size!=numberofvertices || vx_size!=numberofvertices || vy_size!=numberofvertices){ + _error_("StressBalanceEmulatorx expects vertex-based Thickness, Base, FrictionC, MaskIceLevelset, Vx, and Vy inputs"); + } + + std::vector vx_all(numberofvertices,0.); + std::vector vy_all(numberofvertices,0.); + std::vector vel_all(numberofvertices,0.); + + /*Evaluate emulator on rank 0*/ + if(rank==0){ + const size_t nvertices = static_cast(numberofvertices); + const size_t nfeatures = 6; + std::vector features(nvertices*nfeatures); + + for(size_t i=0;i(mask[i]/400000.0); + features[i*nfeatures + 1] = static_cast(thickness[i]/5000.0); + features[i*nfeatures + 2] = static_cast((base[i]-1200.0)/5000.0); + features[i*nfeatures + 3] = static_cast(frictionc[i]/12000.0); + features[i*nfeatures + 4] = static_cast(vx[i]*yts/1000.0); + features[i*nfeatures + 5] = static_cast(vy[i]*yts/1000.0); + } + + try{ + std::vector features_shape = {static_cast(nvertices),static_cast(nfeatures)}; + py::array_t features_np(features_shape,features.data()); + py::object output_obj = emulator->mod.attr("predict_logits_np")(features_np); + py::array_t output_array(output_obj); + py::buffer_info output_info = output_array.request(); + + if(output_info.ndim!=2){ + _error_("StressBalanceEmulatorx output is not a 2D array"); + } + size_t rows = static_cast(output_info.shape[0]); + size_t cols = static_cast(output_info.shape[1]); + if(rows!=nvertices || cols!=2){ + std::ostringstream message; + message << "StressBalanceEmulatorx unexpected output shape: (" << rows << ", " << cols << "), expected (" << nvertices << ", 2)"; + _error_(message.str()); + } + + const float* output = static_cast(output_info.ptr); + for(size_t i=0;i(output[i*2 + 0]*1000.0/yts); + vy_all[i] = static_cast(output[i*2 + 1]*1000.0/yts); + } + } + catch(const py::error_already_set& e){ + _error_("StressBalanceEmulatorx Python exception: " << e.what()); + } + } + + xDelete(thickness); + xDelete(base); + xDelete(frictionc); + xDelete(mask); + xDelete(vx); + xDelete(vy); + + /*Broadcast emulator output and update model inputs*/ + if(numberofvertices>0){ + ISSM_MPI_Comm comm = IssmComm::GetComm(); + ISSM_MPI_Bcast(vx_all.data(),numberofvertices,ISSM_MPI_DOUBLE,0,comm); + ISSM_MPI_Bcast(vy_all.data(),numberofvertices,ISSM_MPI_DOUBLE,0,comm); + + for(int i=0;i pressure(numberofvertices,0.); + InputUpdateFromVectorx(femmodel,pressure.data(),PressureEnum,VertexSIdEnum); + } + + return; +}/*}}}*/ diff --git a/src/c/modules/StressBalanceEmulatorx/StressBalanceEmulatorx.h b/src/c/modules/StressBalanceEmulatorx/StressBalanceEmulatorx.h new file mode 100644 index 000000000..0c9144341 --- /dev/null +++ b/src/c/modules/StressBalanceEmulatorx/StressBalanceEmulatorx.h @@ -0,0 +1,10 @@ + +#ifndef _STRESSBALANCE_EMULATOR_ +#define _STRESSBALANCE_EMULATOR_ + +#include "../../classes/classes.h" +#include "../../shared/shared.h" + +void StressBalanceEmulatorx(FemModel* femmodel); + +#endif diff --git a/src/c/modules/SurfaceMassBalancex/Gembx.cpp b/src/c/modules/SurfaceMassBalancex/Gembx.cpp index 184b8774c..0bd0ef96f 100644 --- a/src/c/modules/SurfaceMassBalancex/Gembx.cpp +++ b/src/c/modules/SurfaceMassBalancex/Gembx.cpp @@ -19,7 +19,6 @@ const double Ttol = 1e-10; const double Dtol = 1e-11; const double Gdntol = 1e-10; const double Wtol = 1e-13; -const double Ptol = 1e-6; const double CI = 2102.0; // heat capacity of snow/ice (J kg-1 k-1) const double LF = 0.3345e6; // latent heat of fusion (J kg-1) @@ -710,7 +709,7 @@ void albedo(IssmDouble** pa, IssmDouble** padiff, int aIdx, IssmDouble* re, Issm *padiff=adiff; } /*}}}*/ -void thermo(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble** pT, IssmDouble* pulwrf, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlwrf, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, int tcIdx, int eIdx, IssmDouble teValue, IssmDouble dulwrfValue, IssmDouble teThresh, IssmDouble Ws, IssmDouble dt0, IssmDouble dzMin, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble thermo_scaling, IssmDouble dIce, int sid, bool isconstrainsurfaceT, bool isdeltaLWup) { /*{{{*/ +void thermo(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble** pT, IssmDouble* pulwrf, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlwrf, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, int tcIdx, int eIdx, IssmDouble teValue, IssmDouble teDefault, IssmDouble dulwrfValue, IssmDouble teThresh, IssmDouble Ws, IssmDouble dt0, IssmDouble dzMin, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble thermo_scaling, IssmDouble dIce, int sid, bool isconstrainsurfaceT, bool isdeltaLWup) { /*{{{*/ /* ENGLACIAL THERMODYNAMICS*/ @@ -1179,12 +1178,13 @@ void thermo(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble** pT // upward longwave contribution IssmDouble deltaULW=0.0; - IssmDouble emissivity=1.0; + IssmDouble emissivity=teDefault; //If user wants to set a upward long wave bias if(isdeltaLWup) deltaULW = dulwrfValue; //If user wants to directly set emissivity, or grain radius is larger than the // threshold, or eIdx is 2 and we have wet snow or ice, use prescribed emissivity - if(eIdx==0 || (teThresh - re[0])(0.001+Gdntol))) emissivity = teValue; + // or eIdx is 3 and we have a wet surface, use prescribed emissivity + if(eIdx==0 || (teThresh - re[0])0.001) || (eIdx==3 && Ws >= Wtol)) emissivity = teValue; ulw = - (SB * pow(Ts,4.0)* emissivity + deltaULW) * dt; ulwrf = ulwrf - ulw/dt0; @@ -1558,7 +1558,7 @@ void accumulation(IssmDouble** pT, IssmDouble** pdz, IssmDouble** pd, IssmDouble massinit=0.0; for(int i=0;i 0.0+Ptol){ + if (P > 0.0) { //if (P > 0.0+Dtol){ if (T_air <= CtoK+Ttol){ // if snow @@ -2504,7 +2504,7 @@ void densification(IssmDouble** pd,IssmDouble** pdz, IssmDouble* T, IssmDouble* else d[i] = d[i] + (c2 * (dIce - d[i]) / 365.0 * dt); // do not allow densities to exceed the density of ice - if(d[i] > dIce-Ptol) d[i]=dIce; + if(d[i] > dIce-Dtol) d[i]=dIce; // calculate new grid cell length dz[i] = mass_init[i] / d[i]; diff --git a/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.cpp b/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.cpp index 36944dd52..13cecd809 100644 --- a/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.cpp +++ b/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.cpp @@ -10,6 +10,14 @@ #include "../../classes/Inputs/TransientInput.h" #include "../../shared/Random/random.h" +#ifdef _HAVE_PyBind11_ +#include +#include +#include +#include +namespace py = pybind11; +#endif + void SmbForcingx(FemModel* femmodel){/*{{{*/ // void SmbForcingx(smb,ni){ @@ -415,6 +423,187 @@ void PositiveDegreeDayGCMx(FemModel* femmodel){/*{{{*/ xDelete(annualtemp); xDelete(precepitation); }/*}}}*/ +#ifdef _HAVE_PyBind11_ +void SmbEmulatorx(FemModel* femmodel){/*{{{*/ + + if(!femmodel->parameters->Exist(SmbEmulatorEnum)) _error_("SmbEmulatorEnum not found; SMB emulator was not initialized"); + Param* emulator_param = femmodel->parameters->FindParamObject(SmbEmulatorEnum); + if(emulator_param->ObjectEnum()!=EmulatorParamEnum) _error_("Parameter should be EmulatorParam"); + EmulatorParam* smbemulator = xDynamicCast(emulator_param); + + IssmDouble timeinputs; + femmodel->parameters->FindParam(&timeinputs,TimeEnum); + IssmDouble rho_ice; + femmodel->parameters->FindParam(&rho_ice,MaterialsRhoIceEnum); + const IssmDouble dts = 86400.; + + int numberofvertices_local = femmodel->vertices->NumberOfVerticesLocalAll(); + if(numberofvertices_local==0) return; + + std::vector lid_to_batch(numberofvertices_local,-1); + std::vector batch_lids; + std::vector elev; + std::vector lon; + std::vector lat; + std::vector al; + std::vector st; + std::vector tt; + std::vector swd; + std::vector lwd; + std::vector swu; + std::vector lwu; + std::vector shf; + std::vector lhf; + std::vector maria_elev; + std::vector maria_smb; + batch_lids.reserve(numberofvertices_local); + elev.reserve(numberofvertices_local); + lon.reserve(numberofvertices_local); + lat.reserve(numberofvertices_local); + al.reserve(numberofvertices_local); + st.reserve(numberofvertices_local); + tt.reserve(numberofvertices_local); + swd.reserve(numberofvertices_local); + lwd.reserve(numberofvertices_local); + swu.reserve(numberofvertices_local); + lwu.reserve(numberofvertices_local); + shf.reserve(numberofvertices_local); + lhf.reserve(numberofvertices_local); + maria_elev.reserve(numberofvertices_local); + maria_smb.reserve(numberofvertices_local); + + for(Object* & object : femmodel->elements->objects){ + Element* element=xDynamicCast(object); + const int numvertices = element->GetNumberOfVertices(); + + std::vector elev_e(numvertices); + std::vector al_e(numvertices); + std::vector st_e(numvertices); + std::vector tt_e(numvertices); + std::vector swd_e(numvertices); + std::vector lwd_e(numvertices); + std::vector swu_e(numvertices); + std::vector lwu_e(numvertices); + std::vector shf_e(numvertices); + std::vector lhf_e(numvertices); + std::vector maria_elev_e(numvertices); + std::vector maria_smb_e(numvertices); + + Input* elev_input = element->GetInput(SurfaceEnum); _assert_(elev_input); + Input* maria_elev_input = element->GetInput(MariaElevEnum,timeinputs); _assert_(maria_elev_input); + Input* maria_smb_input = element->GetInput(MariaSmbEnum,timeinputs); _assert_(maria_smb_input); + Input* al_input = element->GetInput(MariaAlEnum,timeinputs); _assert_(al_input); + Input* st_input = element->GetInput(MariaStEnum,timeinputs); _assert_(st_input); + Input* tt_input = element->GetInput(MariaTtEnum,timeinputs); _assert_(tt_input); + Input* swd_input = element->GetInput(MariaSwdEnum,timeinputs); _assert_(swd_input); + Input* lwd_input = element->GetInput(MariaLwdEnum,timeinputs); _assert_(lwd_input); + Input* swu_input = element->GetInput(MariaSwuEnum,timeinputs); _assert_(swu_input); + Input* lwu_input = element->GetInput(MariaLwuEnum,timeinputs); _assert_(lwu_input); + Input* shf_input = element->GetInput(MariaShfEnum,timeinputs); _assert_(shf_input); + Input* lhf_input = element->GetInput(MariaLhfEnum,timeinputs); _assert_(lhf_input); + + element->GetInputListOnVertices(elev_e.data(),elev_input,0.); + element->GetInputListOnVertices(maria_elev_e.data(),maria_elev_input,0.); + element->GetInputListOnVertices(maria_smb_e.data(),maria_smb_input,0.); + element->GetInputListOnVertices(al_e.data(),al_input,0.); + element->GetInputListOnVertices(st_e.data(),st_input,0.); + element->GetInputListOnVertices(tt_e.data(),tt_input,0.); + element->GetInputListOnVertices(swd_e.data(),swd_input,0.); + element->GetInputListOnVertices(lwd_e.data(),lwd_input,0.); + element->GetInputListOnVertices(swu_e.data(),swu_input,0.); + element->GetInputListOnVertices(lwu_e.data(),lwu_input,0.); + element->GetInputListOnVertices(shf_e.data(),shf_input,0.); + element->GetInputListOnVertices(lhf_e.data(),lhf_input,0.); + + for(int iv=0;ivvertices[iv]->Lid(); + if(lid<0 || lid>=numberofvertices_local){ + _error_("SmbEmulatorx vertex local id " << lid << " is outside local vertex range [0," << numberofvertices_local << ")"); + } + if(lid_to_batch[lid]>=0) continue; + + lid_to_batch[lid] = static_cast(batch_lids.size()); + batch_lids.push_back(lid); + elev.push_back(static_cast(elev_e[iv])); + lon.push_back(static_cast(element->vertices[iv]->GetLongitude())); + lat.push_back(static_cast(element->vertices[iv]->GetLatitude())); + al.push_back(static_cast(al_e[iv])); + st.push_back(static_cast(st_e[iv])); + tt.push_back(static_cast(tt_e[iv])); + swd.push_back(static_cast(swd_e[iv])); + lwd.push_back(static_cast(lwd_e[iv])); + swu.push_back(static_cast(swu_e[iv])); + lwu.push_back(static_cast(lwu_e[iv])); + shf.push_back(static_cast(shf_e[iv])); + lhf.push_back(static_cast(lhf_e[iv])); + maria_elev.push_back(static_cast(maria_elev_e[iv])); + maria_smb.push_back(static_cast(maria_smb_e[iv])); + } + } + + int batch_size = static_cast(batch_lids.size()); + if(batch_size==0) return; + + std::vector smb_local(numberofvertices_local,0.); + + try{ + py::gil_scoped_acquire gil; + + py::array_t elev_np(batch_size,elev.data()); + py::array_t lon_np(batch_size,lon.data()); + py::array_t lat_np(batch_size,lat.data()); + py::array_t al_np(batch_size,al.data()); + py::array_t st_np(batch_size,st.data()); + py::array_t tt_np(batch_size,tt.data()); + py::array_t swd_np(batch_size,swd.data()); + py::array_t lwd_np(batch_size,lwd.data()); + py::array_t swu_np(batch_size,swu.data()); + py::array_t lwu_np(batch_size,lwu.data()); + py::array_t shf_np(batch_size,shf.data()); + py::array_t lhf_np(batch_size,lhf.data()); + + py::object pred_obj = smbemulator->mod.attr("predict_smb_np")( + elev_np, lon_np, lat_np, al_np, st_np, tt_np, swd_np, lwd_np, swu_np, lwu_np, shf_np, lhf_np, + py::arg("dtype") = "float64"); + py::array_t pred(pred_obj); + py::buffer_info pred_info = pred.request(); + + if(pred_info.ndim!=1){ + _error_("SmbEmulatorx output is not a 1D array"); + } + if(pred_info.shape[0]!=batch_size){ + std::ostringstream message; + message << "SmbEmulatorx unexpected output length: " << pred_info.shape[0] << ", expected " << batch_size; + _error_(message.str()); + } + + const double* pred_data = static_cast(pred_info.ptr); + for(int i=0;i(pred_data[i])/(rho_ice*dts); + } + if(IssmComm::GetRank()==0){ + int nprint = batch_size<3 ? batch_size : 3; + _printf0_(" SMB emulator diagnostic at time " << timeinputs << ":\n"); + for(int i=0;ielements->objects){ @@ -585,6 +773,3 @@ void SmbSemicx(FemModel* femmodel,int ismethod){/*{{{*/ } }/*}}}*/ -#else -void SmbSemicx(FemModel* femmodel){_error_("SEMIC not installed");} -#endif //_HAVE_SEMIC_ diff --git a/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.h b/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.h index 7a16079fc..869928136 100644 --- a/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.h +++ b/src/c/modules/SurfaceMassBalancex/SurfaceMassBalancex.h @@ -20,6 +20,9 @@ void PositiveDegreeDayx(FemModel* femmodel); void PositiveDegreeDaySicopolisx(FemModel* femmodel); void PositiveDegreeDayFastx(FemModel* femmodel); void PositiveDegreeDayGCMx(FemModel* femmodel); +#ifdef _HAVE_PyBind11_ +void SmbEmulatorx(FemModel* femmodel); +#endif void SmbHenningx(FemModel* femmodel); void SmbComponentsx(FemModel* femmodel); void SmbMeltComponentsx(FemModel* femmodel); @@ -35,7 +38,7 @@ IssmDouble gardnerAlb(IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble void grainGrowth(IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, IssmDouble* T,IssmDouble* dz,IssmDouble* d, IssmDouble* W,IssmDouble smb_dt,int m,int aIdx, int sid); void albedo(IssmDouble** a, IssmDouble** adiff, int aIdx, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble cldFrac, IssmDouble aIce, IssmDouble aSnow, IssmDouble aValue, IssmDouble adThresh, IssmDouble* T, IssmDouble* W, IssmDouble P, IssmDouble EC, IssmDouble Msurf, IssmDouble clabSnow, IssmDouble clabIce, IssmDouble SZA, IssmDouble COT, IssmDouble t0wet, IssmDouble t0dry, IssmDouble K, IssmDouble dt, IssmDouble dIce, int m, int sid); void shortwave(IssmDouble** pswf, int swIdx, int aIdx, IssmDouble dsw, IssmDouble dswdiff, IssmDouble as, IssmDouble asdiff, IssmDouble* d, IssmDouble* dz, IssmDouble* re, IssmDouble dIce, int m, int sid); -void thermo(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble** pT, IssmDouble* pulwrf, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlw, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, int tcIdx, int eIdx, IssmDouble teValue, IssmDouble dulwrfValue, IssmDouble teThresh, IssmDouble Ws, IssmDouble dt0, IssmDouble dzMin, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble thermo_scaling, IssmDouble dIce, int sid, bool isconstrainsurfaceT, bool isdeltaLWup); +void thermo(IssmDouble* pshf, IssmDouble* plhf, IssmDouble* pEC, IssmDouble** pT, IssmDouble* pulwrf, IssmDouble* re, IssmDouble* dz, IssmDouble* d, IssmDouble* swf, IssmDouble dlw, IssmDouble Ta, IssmDouble V, IssmDouble eAir, IssmDouble pAir, int tcIdx, int eIdx, IssmDouble teValue, IssmDouble teDefault, IssmDouble dulwrfValue, IssmDouble teThresh, IssmDouble Ws, IssmDouble dt0, IssmDouble dzMin, int m, IssmDouble Vz, IssmDouble Tz, IssmDouble thermo_scaling, IssmDouble dIce, int sid, bool isconstrainsurfaceT, bool isdeltaLWup); void accumulation(IssmDouble** pT, IssmDouble** pdz, IssmDouble** pd, IssmDouble** pW, IssmDouble** pa, IssmDouble** padiff, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, IssmDouble* pRa, int* pm, int aIdx, int dsnowIdx, IssmDouble Tmean, IssmDouble Ta, IssmDouble P, IssmDouble dzMin, IssmDouble aSnow, IssmDouble C, IssmDouble V, IssmDouble Vmean, IssmDouble dIce, int sid); void melt(IssmDouble* pM, IssmDouble* pMs, IssmDouble* pR, IssmDouble* pF, IssmDouble* pmAdd, IssmDouble* pdz_add, IssmDouble** pT, IssmDouble** pd, IssmDouble** pdz, IssmDouble** pW, IssmDouble** pa, IssmDouble** padiff, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pn, IssmDouble Ra, IssmDouble dzMin, IssmDouble zMax, IssmDouble zMin, IssmDouble zTop, IssmDouble zY, IssmDouble dIce, int sid); void managelayers(IssmDouble* pmAdd, IssmDouble* pdz_add, IssmDouble* paddE, IssmDouble** pm, IssmDouble** pEI, IssmDouble** pEW, IssmDouble** pT, IssmDouble** pd, IssmDouble** pdz, IssmDouble** pW, IssmDouble** pa, IssmDouble** padiff, IssmDouble** pre, IssmDouble** pgdn, IssmDouble** pgsp, int* pn, IssmDouble dzMin, IssmDouble zMax, IssmDouble zMin, IssmDouble zTop, IssmDouble zY); diff --git a/src/c/modules/modules.h b/src/c/modules/modules.h index 61c00f974..06c65e30c 100644 --- a/src/c/modules/modules.h +++ b/src/c/modules/modules.h @@ -104,4 +104,8 @@ #include "./OceanExchangeDatax/OceanExchangeDatax.h" #endif +#ifdef _HAVE_PyBind11_ +#include "./StressBalanceEmulatorx/StressBalanceEmulatorx.h" +#endif + #endif diff --git a/src/c/shared/Enum/Enum.vim b/src/c/shared/Enum/Enum.vim index 3a113e31b..8d5e57e27 100644 --- a/src/c/shared/Enum/Enum.vim +++ b/src/c/shared/Enum/Enum.vim @@ -85,6 +85,8 @@ syn keyword cConstant BasalforcingsIsmip6Gamma0Enum syn keyword cConstant BasalforcingsIsmip6IsLocalEnum syn keyword cConstant BasalforcingsIsmip6NumBasinsEnum syn keyword cConstant BasalforcingsIsmip6TfDepthsEnum +syn keyword cConstant BasalforcingsIsmip7DeltaTEnum +syn keyword cConstant BasalforcingsIsmip7IsLocalEnum syn keyword cConstant BasalforcingsIsmip7TfDepthsEnum syn keyword cConstant BasalforcingsIsmip7NumBasinsEnum syn keyword cConstant BasalforcingsIsmip7GammaEnum @@ -351,6 +353,7 @@ syn keyword cConstant InversionNumControlParametersEnum syn keyword cConstant InversionNumCostFunctionsEnum syn keyword cConstant InversionStepThresholdEnum syn keyword cConstant InversionStopFlagEnum +syn keyword cConstant InversionTauCEnum syn keyword cConstant InversionTypeEnum syn keyword cConstant IoConstantEnum syn keyword cConstant IvinsEnum @@ -488,6 +491,9 @@ syn keyword cConstant SealevelchangeGeometryDoneEnum syn keyword cConstant SealevelchangeViscousNumStepsEnum syn keyword cConstant SealevelchangeViscousTimesEnum syn keyword cConstant SealevelchangeViscousIndexEnum +syn keyword cConstant SealevelchangeViscousSamplingEnum +syn keyword cConstant SealevelchangeViscousSamplingLengthEnum +syn keyword cConstant SealevelchangeViscousSamplingIndexEnum syn keyword cConstant SealevelchangeViscousPolarMotionEnum syn keyword cConstant SealevelchangeRunCountEnum syn keyword cConstant SealevelchangeTransitionsEnum @@ -616,6 +622,8 @@ syn keyword cConstant SmbIsdeltaLWupEnum syn keyword cConstant SmbIsfirnwarmingEnum syn keyword cConstant SmbIsgraingrowthEnum syn keyword cConstant SmbIsmappedforcingEnum +syn keyword cConstant SmbIsmappingusingneighborsEnum +syn keyword cConstant SmbIsmappingneighborxyEnum syn keyword cConstant SmbIsmeltEnum syn keyword cConstant SmbIsmungsmEnum syn keyword cConstant SmbIsprecipforcingremappedEnum @@ -629,6 +637,8 @@ syn keyword cConstant SmbKEnum syn keyword cConstant SmbLapsedlwrfValueEnum syn keyword cConstant SmbLapseRatesEnum syn keyword cConstant SmbLapseTaValueEnum +syn keyword cConstant SmbLatMappedforcingEnum +syn keyword cConstant SmbLonMappedforcingEnum syn keyword cConstant SmbLWgradEnum syn keyword cConstant SmbMappedforcingelevationEnum syn keyword cConstant SmbNumBasinsEnum @@ -668,6 +678,7 @@ syn keyword cConstant SmbT0dryEnum syn keyword cConstant SmbT0wetEnum syn keyword cConstant SmbTaParamEnum syn keyword cConstant SmbTcIdxEnum +syn keyword cConstant SmbTeDefaultEnum syn keyword cConstant SmbTeThreshEnum syn keyword cConstant SmbTdiffEnum syn keyword cConstant SmbThermoDeltaTScalingEnum @@ -679,6 +690,8 @@ syn keyword cConstant SmbVParamEnum syn keyword cConstant SmbVmeanParamEnum syn keyword cConstant SmbVzParamEnum syn keyword cConstant SmbWindspeedgradEnum +syn keyword cConstant SmbXMappedforcingEnum +syn keyword cConstant SmbYMappedforcingEnum syn keyword cConstant SmoothThicknessMultiplierEnum syn keyword cConstant SolutionTypeEnum syn keyword cConstant SteadystateMaxiterEnum @@ -691,6 +704,10 @@ syn keyword cConstant StressbalanceAbstolEnum syn keyword cConstant StressbalanceFSreconditioningEnum syn keyword cConstant StressbalanceIsHydrologyLayerEnum syn keyword cConstant StressbalanceIsnewtonEnum +syn keyword cConstant StressbalanceIsemulatorEnum +syn keyword cConstant EdgesNumberEnum +syn keyword cConstant EdgesSrcEnum +syn keyword cConstant EdgesDstEnum syn keyword cConstant StressbalanceMaxiterEnum syn keyword cConstant StressbalanceNumRequestedOutputsEnum syn keyword cConstant StressbalancePenaltyFactorEnum @@ -755,6 +772,9 @@ syn keyword cConstant YyeEnum syn keyword cConstant ZzeEnum syn keyword cConstant AreaeEnum syn keyword cConstant WorldCommEnum +syn keyword cConstant FrictionEmulatorEnum +syn keyword cConstant SmbEmulatorEnum +syn keyword cConstant StressbalanceEmulatorEnum syn keyword cConstant ParametersENDEnum syn keyword cConstant InputsSTARTEnum syn keyword cConstant AccumulatedDeltaBottomPressureEnum @@ -798,6 +818,7 @@ syn keyword cConstant BasalforcingsIsmip6BasinIdEnum syn keyword cConstant BasalforcingsIsmip6TfEnum syn keyword cConstant BasalforcingsIsmip6TfShelfEnum syn keyword cConstant BasalforcingsIsmip6MeltAnomalyEnum +syn keyword cConstant BasalforcingsIsmip7BasinIdEnum syn keyword cConstant BasalforcingsIsmip7TfEnum syn keyword cConstant BasalforcingsIsmip7TfShelfEnum syn keyword cConstant BasalforcingsIsmip7SalinityEnum @@ -1195,7 +1216,10 @@ syn keyword cConstant SmbHSnowEnum syn keyword cConstant SmbHSnowInitEnum syn keyword cConstant SmbHrefEnum syn keyword cConstant SmbIsInitializedEnum +syn keyword cConstant SmbLatEnum +syn keyword cConstant SmbLonEnum syn keyword cConstant SmbMAddEnum +syn keyword cConstant SmbMappedforcingneighborsEnum syn keyword cConstant SmbMappedforcingpointEnum syn keyword cConstant SmbMappedforcingprecipscalingEnum syn keyword cConstant SmbMassBalanceEnum @@ -1204,12 +1228,16 @@ syn keyword cConstant SmbMassBalanceIceEnum syn keyword cConstant SmbMassBalanceSubstepEnum syn keyword cConstant SmbMassBalanceTransientEnum syn keyword cConstant SmbMaskEnum +syn keyword cConstant SmbMaxXEnum +syn keyword cConstant SmbMaxYEnum syn keyword cConstant SmbMeanLHFEnum syn keyword cConstant SmbMeanSHFEnum syn keyword cConstant SmbMeanULWEnum syn keyword cConstant SmbMeanTemperatureEnum syn keyword cConstant SmbMeltEnum syn keyword cConstant SmbMeltSubstepEnum +syn keyword cConstant SmbMinXEnum +syn keyword cConstant SmbMinYEnum syn keyword cConstant SmbMonthlytemperaturesEnum syn keyword cConstant SmbMonthlydsradiationEnum syn keyword cConstant SmbMonthlydlradiationEnum @@ -1226,6 +1254,7 @@ syn keyword cConstant SmbPddfacSnowEnum syn keyword cConstant SmbPrecipitationEnum syn keyword cConstant SmbPrecipitationSubstepEnum syn keyword cConstant SmbPrecipitationsAnomalyEnum +syn keyword cConstant SmbQinterpEnum syn keyword cConstant SmbDsradiationAnomalyEnum syn keyword cConstant SmbDlradiationAnomalyEnum syn keyword cConstant SmbWindspeedAnomalyEnum @@ -1282,6 +1311,17 @@ syn keyword cConstant SmbZMaxEnum syn keyword cConstant SmbZMinEnum syn keyword cConstant SmbZTopEnum syn keyword cConstant SmbZYEnum +syn keyword cConstant MariaSmbEnum +syn keyword cConstant MariaElevEnum +syn keyword cConstant MariaAlEnum +syn keyword cConstant MariaStEnum +syn keyword cConstant MariaTtEnum +syn keyword cConstant MariaSwdEnum +syn keyword cConstant MariaLwdEnum +syn keyword cConstant MariaSwuEnum +syn keyword cConstant MariaLwuEnum +syn keyword cConstant MariaShfEnum +syn keyword cConstant MariaLhfEnum syn keyword cConstant SolidearthExternalDisplacementEastRateEnum syn keyword cConstant SolidearthExternalDisplacementNorthRateEnum syn keyword cConstant SolidearthExternalDisplacementUpRateEnum @@ -3476,6 +3516,7 @@ syn keyword cConstant DoubleVecParamEnum syn keyword cConstant ElementEnum syn keyword cConstant ElementHookEnum syn keyword cConstant ElementSIdEnum +syn keyword cConstant EmulatorParamEnum syn keyword cConstant EnthalpyAnalysisEnum syn keyword cConstant EsaAnalysisEnum syn keyword cConstant EsaSolutionEnum @@ -3704,6 +3745,7 @@ syn keyword cConstant SMBpddSicopolisEnum syn keyword cConstant SMBpddGCMEnum syn keyword cConstant SMBpddFastEnum syn keyword cConstant SMBsemicEnum +syn keyword cConstant SMBmariaEnum syn keyword cConstant SSAApproximationEnum syn keyword cConstant SSAFSApproximationEnum syn keyword cConstant SSAHOApproximationEnum @@ -3847,6 +3889,7 @@ syn keyword cType ElementInput syn keyword cType ElementMatrix syn keyword cType Elements syn keyword cType ElementVector +syn keyword cType EmulatorParam syn keyword cType ExponentialVariogram syn keyword cType ExternalResult syn keyword cType FemModel diff --git a/src/c/shared/Enum/EnumDefinitions.h b/src/c/shared/Enum/EnumDefinitions.h index 336775e14..e65b65dcd 100644 --- a/src/c/shared/Enum/EnumDefinitions.h +++ b/src/c/shared/Enum/EnumDefinitions.h @@ -79,6 +79,8 @@ enum definitions{ BasalforcingsIsmip6IsLocalEnum, BasalforcingsIsmip6NumBasinsEnum, BasalforcingsIsmip6TfDepthsEnum, + BasalforcingsIsmip7DeltaTEnum, + BasalforcingsIsmip7IsLocalEnum, BasalforcingsIsmip7TfDepthsEnum, BasalforcingsIsmip7NumBasinsEnum, BasalforcingsIsmip7GammaEnum, @@ -345,6 +347,7 @@ enum definitions{ InversionNumCostFunctionsEnum, InversionStepThresholdEnum, InversionStopFlagEnum, + InversionTauCEnum, InversionTypeEnum, IoConstantEnum, IvinsEnum, @@ -482,6 +485,9 @@ enum definitions{ SealevelchangeViscousNumStepsEnum, SealevelchangeViscousTimesEnum, SealevelchangeViscousIndexEnum, + SealevelchangeViscousSamplingEnum, + SealevelchangeViscousSamplingLengthEnum, + SealevelchangeViscousSamplingIndexEnum, SealevelchangeViscousPolarMotionEnum, SealevelchangeRunCountEnum, SealevelchangeTransitionsEnum, @@ -610,6 +616,8 @@ enum definitions{ SmbIsfirnwarmingEnum, SmbIsgraingrowthEnum, SmbIsmappedforcingEnum, + SmbIsmappingusingneighborsEnum, + SmbIsmappingneighborxyEnum, SmbIsmeltEnum, SmbIsmungsmEnum, SmbIsprecipforcingremappedEnum, @@ -623,6 +631,8 @@ enum definitions{ SmbLapsedlwrfValueEnum, SmbLapseRatesEnum, SmbLapseTaValueEnum, + SmbLatMappedforcingEnum, + SmbLonMappedforcingEnum, SmbLWgradEnum, SmbMappedforcingelevationEnum, SmbNumBasinsEnum, @@ -662,6 +672,7 @@ enum definitions{ SmbT0wetEnum, SmbTaParamEnum, SmbTcIdxEnum, + SmbTeDefaultEnum, SmbTeThreshEnum, SmbTdiffEnum, SmbThermoDeltaTScalingEnum, @@ -673,6 +684,8 @@ enum definitions{ SmbVmeanParamEnum, SmbVzParamEnum, SmbWindspeedgradEnum, + SmbXMappedforcingEnum, + SmbYMappedforcingEnum, SmoothThicknessMultiplierEnum, SolutionTypeEnum, SteadystateMaxiterEnum, @@ -685,6 +698,10 @@ enum definitions{ StressbalanceFSreconditioningEnum, StressbalanceIsHydrologyLayerEnum, StressbalanceIsnewtonEnum, + StressbalanceIsemulatorEnum, + EdgesNumberEnum, + EdgesSrcEnum, + EdgesDstEnum, StressbalanceMaxiterEnum, StressbalanceNumRequestedOutputsEnum, StressbalancePenaltyFactorEnum, @@ -749,6 +766,9 @@ enum definitions{ ZzeEnum, AreaeEnum, WorldCommEnum, + FrictionEmulatorEnum, + SmbEmulatorEnum, + StressbalanceEmulatorEnum, /*}}}*/ ParametersENDEnum, InputsSTARTEnum, @@ -794,6 +814,7 @@ enum definitions{ BasalforcingsIsmip6TfEnum, BasalforcingsIsmip6TfShelfEnum, BasalforcingsIsmip6MeltAnomalyEnum, + BasalforcingsIsmip7BasinIdEnum, BasalforcingsIsmip7TfEnum, BasalforcingsIsmip7TfShelfEnum, BasalforcingsIsmip7SalinityEnum, @@ -1191,7 +1212,10 @@ enum definitions{ SmbHSnowInitEnum, SmbHrefEnum, SmbIsInitializedEnum, + SmbLatEnum, + SmbLonEnum, SmbMAddEnum, + SmbMappedforcingneighborsEnum, SmbMappedforcingpointEnum, SmbMappedforcingprecipscalingEnum, SmbMassBalanceEnum, @@ -1200,6 +1224,8 @@ enum definitions{ SmbMassBalanceSubstepEnum, SmbMassBalanceTransientEnum, SmbMaskEnum, + SmbMaxXEnum, + SmbMaxYEnum, SmbMeanLHFEnum, SmbMeanSHFEnum, SmbMeanULWEnum, @@ -1207,6 +1233,8 @@ enum definitions{ SmbMeltEnum, SmbMeltSubstepEnum, SmbMInitnum, + SmbMinXEnum, + SmbMinYEnum, SmbMonthlytemperaturesEnum, SmbMonthlydsradiationEnum, SmbMonthlydlradiationEnum, @@ -1223,6 +1251,7 @@ enum definitions{ SmbPrecipitationEnum, SmbPrecipitationSubstepEnum, SmbPrecipitationsAnomalyEnum, + SmbQinterpEnum, SmbDsradiationAnomalyEnum, SmbDlradiationAnomalyEnum, SmbWindspeedAnomalyEnum, @@ -1279,6 +1308,17 @@ enum definitions{ SmbZMinEnum, SmbZTopEnum, SmbZYEnum, + MariaSmbEnum, + MariaElevEnum, + MariaAlEnum, + MariaStEnum, + MariaTtEnum, + MariaSwdEnum, + MariaLwdEnum, + MariaSwuEnum, + MariaLwuEnum, + MariaShfEnum, + MariaLhfEnum, SolidearthExternalDisplacementEastRateEnum, SolidearthExternalDisplacementNorthRateEnum, SolidearthExternalDisplacementUpRateEnum, @@ -3475,6 +3515,7 @@ enum definitions{ ElementEnum, ElementHookEnum, ElementSIdEnum, + EmulatorParamEnum, EnthalpyAnalysisEnum, EsaAnalysisEnum, EsaSolutionEnum, @@ -3703,6 +3744,7 @@ enum definitions{ SMBpddGCMEnum, SMBpddFastEnum, SMBsemicEnum, + SMBmariaEnum, SSAApproximationEnum, SSAFSApproximationEnum, SSAHOApproximationEnum, diff --git a/src/c/shared/Enum/EnumToStringx.cpp b/src/c/shared/Enum/EnumToStringx.cpp index ce5402157..2e76cfab7 100644 --- a/src/c/shared/Enum/EnumToStringx.cpp +++ b/src/c/shared/Enum/EnumToStringx.cpp @@ -87,6 +87,8 @@ const char* EnumToStringx(int en){ case BasalforcingsIsmip6IsLocalEnum : return "BasalforcingsIsmip6IsLocal"; case BasalforcingsIsmip6NumBasinsEnum : return "BasalforcingsIsmip6NumBasins"; case BasalforcingsIsmip6TfDepthsEnum : return "BasalforcingsIsmip6TfDepths"; + case BasalforcingsIsmip7DeltaTEnum : return "BasalforcingsIsmip7DeltaT"; + case BasalforcingsIsmip7IsLocalEnum : return "BasalforcingsIsmip7IsLocal"; case BasalforcingsIsmip7TfDepthsEnum : return "BasalforcingsIsmip7TfDepths"; case BasalforcingsIsmip7NumBasinsEnum : return "BasalforcingsIsmip7NumBasins"; case BasalforcingsIsmip7GammaEnum : return "BasalforcingsIsmip7Gamma"; @@ -353,6 +355,7 @@ const char* EnumToStringx(int en){ case InversionNumCostFunctionsEnum : return "InversionNumCostFunctions"; case InversionStepThresholdEnum : return "InversionStepThreshold"; case InversionStopFlagEnum : return "InversionStopFlag"; + case InversionTauCEnum : return "InversionTauC"; case InversionTypeEnum : return "InversionType"; case IoConstantEnum : return "IoConstant"; case IvinsEnum : return "Ivins"; @@ -490,6 +493,9 @@ const char* EnumToStringx(int en){ case SealevelchangeViscousNumStepsEnum : return "SealevelchangeViscousNumSteps"; case SealevelchangeViscousTimesEnum : return "SealevelchangeViscousTimes"; case SealevelchangeViscousIndexEnum : return "SealevelchangeViscousIndex"; + case SealevelchangeViscousSamplingEnum : return "SealevelchangeViscousSampling"; + case SealevelchangeViscousSamplingLengthEnum : return "SealevelchangeViscousSamplingLength"; + case SealevelchangeViscousSamplingIndexEnum : return "SealevelchangeViscousSamplingIndex"; case SealevelchangeViscousPolarMotionEnum : return "SealevelchangeViscousPolarMotion"; case SealevelchangeRunCountEnum : return "SealevelchangeRunCount"; case SealevelchangeTransitionsEnum : return "SealevelchangeTransitions"; @@ -618,6 +624,8 @@ const char* EnumToStringx(int en){ case SmbIsfirnwarmingEnum : return "SmbIsfirnwarming"; case SmbIsgraingrowthEnum : return "SmbIsgraingrowth"; case SmbIsmappedforcingEnum : return "SmbIsmappedforcing"; + case SmbIsmappingusingneighborsEnum : return "SmbIsmappingusingneighbors"; + case SmbIsmappingneighborxyEnum : return "SmbIsmappingneighborxy"; case SmbIsmeltEnum : return "SmbIsmelt"; case SmbIsmungsmEnum : return "SmbIsmungsm"; case SmbIsprecipforcingremappedEnum : return "SmbIsprecipforcingremapped"; @@ -631,6 +639,8 @@ const char* EnumToStringx(int en){ case SmbLapsedlwrfValueEnum : return "SmbLapsedlwrfValue"; case SmbLapseRatesEnum : return "SmbLapseRates"; case SmbLapseTaValueEnum : return "SmbLapseTaValue"; + case SmbLatMappedforcingEnum : return "SmbLatMappedforcing"; + case SmbLonMappedforcingEnum : return "SmbLonMappedforcing"; case SmbLWgradEnum : return "SmbLWgrad"; case SmbMappedforcingelevationEnum : return "SmbMappedforcingelevation"; case SmbNumBasinsEnum : return "SmbNumBasins"; @@ -670,6 +680,7 @@ const char* EnumToStringx(int en){ case SmbT0wetEnum : return "SmbT0wet"; case SmbTaParamEnum : return "SmbTaParam"; case SmbTcIdxEnum : return "SmbTcIdx"; + case SmbTeDefaultEnum : return "SmbTeDefault"; case SmbTeThreshEnum : return "SmbTeThresh"; case SmbTdiffEnum : return "SmbTdiff"; case SmbThermoDeltaTScalingEnum : return "SmbThermoDeltaTScaling"; @@ -681,6 +692,8 @@ const char* EnumToStringx(int en){ case SmbVmeanParamEnum : return "SmbVmeanParam"; case SmbVzParamEnum : return "SmbVzParam"; case SmbWindspeedgradEnum : return "SmbWindspeedgrad"; + case SmbXMappedforcingEnum : return "SmbXMappedforcing"; + case SmbYMappedforcingEnum : return "SmbYMappedforcing"; case SmoothThicknessMultiplierEnum : return "SmoothThicknessMultiplier"; case SolutionTypeEnum : return "SolutionType"; case SteadystateMaxiterEnum : return "SteadystateMaxiter"; @@ -693,6 +706,10 @@ const char* EnumToStringx(int en){ case StressbalanceFSreconditioningEnum : return "StressbalanceFSreconditioning"; case StressbalanceIsHydrologyLayerEnum : return "StressbalanceIsHydrologyLayer"; case StressbalanceIsnewtonEnum : return "StressbalanceIsnewton"; + case StressbalanceIsemulatorEnum : return "StressbalanceIsemulator"; + case EdgesNumberEnum : return "EdgesNumber"; + case EdgesSrcEnum : return "EdgesSrc"; + case EdgesDstEnum : return "EdgesDst"; case StressbalanceMaxiterEnum : return "StressbalanceMaxiter"; case StressbalanceNumRequestedOutputsEnum : return "StressbalanceNumRequestedOutputs"; case StressbalancePenaltyFactorEnum : return "StressbalancePenaltyFactor"; @@ -757,6 +774,9 @@ const char* EnumToStringx(int en){ case ZzeEnum : return "Zze"; case AreaeEnum : return "Areae"; case WorldCommEnum : return "WorldComm"; + case FrictionEmulatorEnum : return "FrictionEmulator"; + case SmbEmulatorEnum : return "SmbEmulator"; + case StressbalanceEmulatorEnum : return "StressbalanceEmulator"; case ParametersENDEnum : return "ParametersEND"; case InputsSTARTEnum : return "InputsSTART"; case AccumulatedDeltaBottomPressureEnum : return "AccumulatedDeltaBottomPressure"; @@ -800,6 +820,7 @@ const char* EnumToStringx(int en){ case BasalforcingsIsmip6TfEnum : return "BasalforcingsIsmip6Tf"; case BasalforcingsIsmip6TfShelfEnum : return "BasalforcingsIsmip6TfShelf"; case BasalforcingsIsmip6MeltAnomalyEnum : return "BasalforcingsIsmip6MeltAnomaly"; + case BasalforcingsIsmip7BasinIdEnum : return "BasalforcingsIsmip7BasinId"; case BasalforcingsIsmip7TfEnum : return "BasalforcingsIsmip7Tf"; case BasalforcingsIsmip7TfShelfEnum : return "BasalforcingsIsmip7TfShelf"; case BasalforcingsIsmip7SalinityEnum : return "BasalforcingsIsmip7Salinity"; @@ -1197,7 +1218,10 @@ const char* EnumToStringx(int en){ case SmbHSnowInitEnum : return "SmbHSnowInit"; case SmbHrefEnum : return "SmbHref"; case SmbIsInitializedEnum : return "SmbIsInitialized"; + case SmbLatEnum : return "SmbLat"; + case SmbLonEnum : return "SmbLon"; case SmbMAddEnum : return "SmbMAdd"; + case SmbMappedforcingneighborsEnum : return "SmbMappedforcingneighbors"; case SmbMappedforcingpointEnum : return "SmbMappedforcingpoint"; case SmbMappedforcingprecipscalingEnum : return "SmbMappedforcingprecipscaling"; case SmbMassBalanceEnum : return "SmbMassBalance"; @@ -1206,12 +1230,16 @@ const char* EnumToStringx(int en){ case SmbMassBalanceSubstepEnum : return "SmbMassBalanceSubstep"; case SmbMassBalanceTransientEnum : return "SmbMassBalanceTransient"; case SmbMaskEnum : return "SmbMask"; + case SmbMaxXEnum : return "SmbMaxX"; + case SmbMaxYEnum : return "SmbMaxY"; case SmbMeanLHFEnum : return "SmbMeanLHF"; case SmbMeanSHFEnum : return "SmbMeanSHF"; case SmbMeanULWEnum : return "SmbMeanULW"; case SmbMeanTemperatureEnum : return "SmbMeanTemperature"; case SmbMeltEnum : return "SmbMelt"; case SmbMeltSubstepEnum : return "SmbMeltSubstep"; + case SmbMinXEnum : return "SmbMinX"; + case SmbMinYEnum : return "SmbMinY"; case SmbMonthlytemperaturesEnum : return "SmbMonthlytemperatures"; case SmbMonthlydsradiationEnum : return "SmbMonthlydsradiation"; case SmbMonthlydlradiationEnum : return "SmbMonthlydlradiation"; @@ -1228,6 +1256,7 @@ const char* EnumToStringx(int en){ case SmbPrecipitationEnum : return "SmbPrecipitation"; case SmbPrecipitationSubstepEnum : return "SmbPrecipitationSubstep"; case SmbPrecipitationsAnomalyEnum : return "SmbPrecipitationsAnomaly"; + case SmbQinterpEnum : return "SmbQinterp"; case SmbDsradiationAnomalyEnum : return "SmbDsradiationAnomaly"; case SmbDlradiationAnomalyEnum : return "SmbDlradiationAnomaly"; case SmbWindspeedAnomalyEnum : return "SmbWindspeedAnomaly"; @@ -1284,6 +1313,17 @@ const char* EnumToStringx(int en){ case SmbZMinEnum : return "SmbZMin"; case SmbZTopEnum : return "SmbZTop"; case SmbZYEnum : return "SmbZY"; + case MariaSmbEnum : return "MariaSmb"; + case MariaElevEnum : return "MariaElev"; + case MariaAlEnum : return "MariaAl"; + case MariaStEnum : return "MariaSt"; + case MariaTtEnum : return "MariaTt"; + case MariaSwdEnum : return "MariaSwd"; + case MariaLwdEnum : return "MariaLwd"; + case MariaSwuEnum : return "MariaSwu"; + case MariaLwuEnum : return "MariaLwu"; + case MariaShfEnum : return "MariaShf"; + case MariaLhfEnum : return "MariaLhf"; case SolidearthExternalDisplacementEastRateEnum : return "SolidearthExternalDisplacementEastRate"; case SolidearthExternalDisplacementNorthRateEnum : return "SolidearthExternalDisplacementNorthRate"; case SolidearthExternalDisplacementUpRateEnum : return "SolidearthExternalDisplacementUpRate"; @@ -3478,6 +3518,7 @@ const char* EnumToStringx(int en){ case ElementEnum : return "Element"; case ElementHookEnum : return "ElementHook"; case ElementSIdEnum : return "ElementSId"; + case EmulatorParamEnum : return "EmulatorParam"; case EnthalpyAnalysisEnum : return "EnthalpyAnalysis"; case EsaAnalysisEnum : return "EsaAnalysis"; case EsaSolutionEnum : return "EsaSolution"; @@ -3706,6 +3747,7 @@ const char* EnumToStringx(int en){ case SMBpddGCMEnum : return "SMBpddGCM"; case SMBpddFastEnum : return "SMBpddFast"; case SMBsemicEnum : return "SMBsemic"; + case SMBmariaEnum : return "SMBmaria"; case SSAApproximationEnum : return "SSAApproximation"; case SSAFSApproximationEnum : return "SSAFSApproximation"; case SSAHOApproximationEnum : return "SSAHOApproximation"; diff --git a/src/c/shared/Enum/Enumjl.vim b/src/c/shared/Enum/Enumjl.vim index 4800491ec..5fcf85c64 100644 --- a/src/c/shared/Enum/Enumjl.vim +++ b/src/c/shared/Enum/Enumjl.vim @@ -78,6 +78,8 @@ syn keyword juliaConstC BasalforcingsIsmip6Gamma0Enum syn keyword juliaConstC BasalforcingsIsmip6IsLocalEnum syn keyword juliaConstC BasalforcingsIsmip6NumBasinsEnum syn keyword juliaConstC BasalforcingsIsmip6TfDepthsEnum +syn keyword juliaConstC BasalforcingsIsmip7DeltaTEnum +syn keyword juliaConstC BasalforcingsIsmip7IsLocalEnum syn keyword juliaConstC BasalforcingsIsmip7TfDepthsEnum syn keyword juliaConstC BasalforcingsIsmip7NumBasinsEnum syn keyword juliaConstC BasalforcingsIsmip7GammaEnum @@ -344,6 +346,7 @@ syn keyword juliaConstC InversionNumControlParametersEnum syn keyword juliaConstC InversionNumCostFunctionsEnum syn keyword juliaConstC InversionStepThresholdEnum syn keyword juliaConstC InversionStopFlagEnum +syn keyword juliaConstC InversionTauCEnum syn keyword juliaConstC InversionTypeEnum syn keyword juliaConstC IoConstantEnum syn keyword juliaConstC IvinsEnum @@ -481,6 +484,9 @@ syn keyword juliaConstC SealevelchangeGeometryDoneEnum syn keyword juliaConstC SealevelchangeViscousNumStepsEnum syn keyword juliaConstC SealevelchangeViscousTimesEnum syn keyword juliaConstC SealevelchangeViscousIndexEnum +syn keyword juliaConstC SealevelchangeViscousSamplingEnum +syn keyword juliaConstC SealevelchangeViscousSamplingLengthEnum +syn keyword juliaConstC SealevelchangeViscousSamplingIndexEnum syn keyword juliaConstC SealevelchangeViscousPolarMotionEnum syn keyword juliaConstC SealevelchangeRunCountEnum syn keyword juliaConstC SealevelchangeTransitionsEnum @@ -609,6 +615,8 @@ syn keyword juliaConstC SmbIsdeltaLWupEnum syn keyword juliaConstC SmbIsfirnwarmingEnum syn keyword juliaConstC SmbIsgraingrowthEnum syn keyword juliaConstC SmbIsmappedforcingEnum +syn keyword juliaConstC SmbIsmappingusingneighborsEnum +syn keyword juliaConstC SmbIsmappingneighborxyEnum syn keyword juliaConstC SmbIsmeltEnum syn keyword juliaConstC SmbIsmungsmEnum syn keyword juliaConstC SmbIsprecipforcingremappedEnum @@ -622,6 +630,8 @@ syn keyword juliaConstC SmbKEnum syn keyword juliaConstC SmbLapsedlwrfValueEnum syn keyword juliaConstC SmbLapseRatesEnum syn keyword juliaConstC SmbLapseTaValueEnum +syn keyword juliaConstC SmbLatMappedforcingEnum +syn keyword juliaConstC SmbLonMappedforcingEnum syn keyword juliaConstC SmbLWgradEnum syn keyword juliaConstC SmbMappedforcingelevationEnum syn keyword juliaConstC SmbNumBasinsEnum @@ -661,6 +671,7 @@ syn keyword juliaConstC SmbT0dryEnum syn keyword juliaConstC SmbT0wetEnum syn keyword juliaConstC SmbTaParamEnum syn keyword juliaConstC SmbTcIdxEnum +syn keyword juliaConstC SmbTeDefaultEnum syn keyword juliaConstC SmbTeThreshEnum syn keyword juliaConstC SmbTdiffEnum syn keyword juliaConstC SmbThermoDeltaTScalingEnum @@ -672,6 +683,8 @@ syn keyword juliaConstC SmbVParamEnum syn keyword juliaConstC SmbVmeanParamEnum syn keyword juliaConstC SmbVzParamEnum syn keyword juliaConstC SmbWindspeedgradEnum +syn keyword juliaConstC SmbXMappedforcingEnum +syn keyword juliaConstC SmbYMappedforcingEnum syn keyword juliaConstC SmoothThicknessMultiplierEnum syn keyword juliaConstC SolutionTypeEnum syn keyword juliaConstC SteadystateMaxiterEnum @@ -684,6 +697,10 @@ syn keyword juliaConstC StressbalanceAbstolEnum syn keyword juliaConstC StressbalanceFSreconditioningEnum syn keyword juliaConstC StressbalanceIsHydrologyLayerEnum syn keyword juliaConstC StressbalanceIsnewtonEnum +syn keyword juliaConstC StressbalanceIsemulatorEnum +syn keyword juliaConstC EdgesNumberEnum +syn keyword juliaConstC EdgesSrcEnum +syn keyword juliaConstC EdgesDstEnum syn keyword juliaConstC StressbalanceMaxiterEnum syn keyword juliaConstC StressbalanceNumRequestedOutputsEnum syn keyword juliaConstC StressbalancePenaltyFactorEnum @@ -748,6 +765,9 @@ syn keyword juliaConstC YyeEnum syn keyword juliaConstC ZzeEnum syn keyword juliaConstC AreaeEnum syn keyword juliaConstC WorldCommEnum +syn keyword juliaConstC FrictionEmulatorEnum +syn keyword juliaConstC SmbEmulatorEnum +syn keyword juliaConstC StressbalanceEmulatorEnum syn keyword juliaConstC ParametersENDEnum syn keyword juliaConstC InputsSTARTEnum syn keyword juliaConstC AccumulatedDeltaBottomPressureEnum @@ -791,6 +811,7 @@ syn keyword juliaConstC BasalforcingsIsmip6BasinIdEnum syn keyword juliaConstC BasalforcingsIsmip6TfEnum syn keyword juliaConstC BasalforcingsIsmip6TfShelfEnum syn keyword juliaConstC BasalforcingsIsmip6MeltAnomalyEnum +syn keyword juliaConstC BasalforcingsIsmip7BasinIdEnum syn keyword juliaConstC BasalforcingsIsmip7TfEnum syn keyword juliaConstC BasalforcingsIsmip7TfShelfEnum syn keyword juliaConstC BasalforcingsIsmip7SalinityEnum @@ -1188,7 +1209,10 @@ syn keyword juliaConstC SmbHSnowEnum syn keyword juliaConstC SmbHSnowInitEnum syn keyword juliaConstC SmbHrefEnum syn keyword juliaConstC SmbIsInitializedEnum +syn keyword juliaConstC SmbLatEnum +syn keyword juliaConstC SmbLonEnum syn keyword juliaConstC SmbMAddEnum +syn keyword juliaConstC SmbMappedforcingneighborsEnum syn keyword juliaConstC SmbMappedforcingpointEnum syn keyword juliaConstC SmbMappedforcingprecipscalingEnum syn keyword juliaConstC SmbMassBalanceEnum @@ -1197,12 +1221,16 @@ syn keyword juliaConstC SmbMassBalanceIceEnum syn keyword juliaConstC SmbMassBalanceSubstepEnum syn keyword juliaConstC SmbMassBalanceTransientEnum syn keyword juliaConstC SmbMaskEnum +syn keyword juliaConstC SmbMaxXEnum +syn keyword juliaConstC SmbMaxYEnum syn keyword juliaConstC SmbMeanLHFEnum syn keyword juliaConstC SmbMeanSHFEnum syn keyword juliaConstC SmbMeanULWEnum syn keyword juliaConstC SmbMeanTemperatureEnum syn keyword juliaConstC SmbMeltEnum syn keyword juliaConstC SmbMeltSubstepEnum +syn keyword juliaConstC SmbMinXEnum +syn keyword juliaConstC SmbMinYEnum syn keyword juliaConstC SmbMonthlytemperaturesEnum syn keyword juliaConstC SmbMonthlydsradiationEnum syn keyword juliaConstC SmbMonthlydlradiationEnum @@ -1219,6 +1247,7 @@ syn keyword juliaConstC SmbPddfacSnowEnum syn keyword juliaConstC SmbPrecipitationEnum syn keyword juliaConstC SmbPrecipitationSubstepEnum syn keyword juliaConstC SmbPrecipitationsAnomalyEnum +syn keyword juliaConstC SmbQinterpEnum syn keyword juliaConstC SmbDsradiationAnomalyEnum syn keyword juliaConstC SmbDlradiationAnomalyEnum syn keyword juliaConstC SmbWindspeedAnomalyEnum @@ -1275,6 +1304,17 @@ syn keyword juliaConstC SmbZMaxEnum syn keyword juliaConstC SmbZMinEnum syn keyword juliaConstC SmbZTopEnum syn keyword juliaConstC SmbZYEnum +syn keyword juliaConstC MariaSmbEnum +syn keyword juliaConstC MariaElevEnum +syn keyword juliaConstC MariaAlEnum +syn keyword juliaConstC MariaStEnum +syn keyword juliaConstC MariaTtEnum +syn keyword juliaConstC MariaSwdEnum +syn keyword juliaConstC MariaLwdEnum +syn keyword juliaConstC MariaSwuEnum +syn keyword juliaConstC MariaLwuEnum +syn keyword juliaConstC MariaShfEnum +syn keyword juliaConstC MariaLhfEnum syn keyword juliaConstC SolidearthExternalDisplacementEastRateEnum syn keyword juliaConstC SolidearthExternalDisplacementNorthRateEnum syn keyword juliaConstC SolidearthExternalDisplacementUpRateEnum @@ -3469,6 +3509,7 @@ syn keyword juliaConstC DoubleVecParamEnum syn keyword juliaConstC ElementEnum syn keyword juliaConstC ElementHookEnum syn keyword juliaConstC ElementSIdEnum +syn keyword juliaConstC EmulatorParamEnum syn keyword juliaConstC EnthalpyAnalysisEnum syn keyword juliaConstC EsaAnalysisEnum syn keyword juliaConstC EsaSolutionEnum @@ -3697,6 +3738,7 @@ syn keyword juliaConstC SMBpddSicopolisEnum syn keyword juliaConstC SMBpddGCMEnum syn keyword juliaConstC SMBpddFastEnum syn keyword juliaConstC SMBsemicEnum +syn keyword juliaConstC SMBmariaEnum syn keyword juliaConstC SSAApproximationEnum syn keyword juliaConstC SSAFSApproximationEnum syn keyword juliaConstC SSAHOApproximationEnum diff --git a/src/c/shared/Enum/StringToEnumx.cpp b/src/c/shared/Enum/StringToEnumx.cpp index 8836fb973..92e93b392 100644 --- a/src/c/shared/Enum/StringToEnumx.cpp +++ b/src/c/shared/Enum/StringToEnumx.cpp @@ -87,6 +87,8 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"BasalforcingsIsmip6IsLocal")==0) return BasalforcingsIsmip6IsLocalEnum; else if (strcmp(name,"BasalforcingsIsmip6NumBasins")==0) return BasalforcingsIsmip6NumBasinsEnum; else if (strcmp(name,"BasalforcingsIsmip6TfDepths")==0) return BasalforcingsIsmip6TfDepthsEnum; + else if (strcmp(name,"BasalforcingsIsmip7DeltaT")==0) return BasalforcingsIsmip7DeltaTEnum; + else if (strcmp(name,"BasalforcingsIsmip7IsLocal")==0) return BasalforcingsIsmip7IsLocalEnum; else if (strcmp(name,"BasalforcingsIsmip7TfDepths")==0) return BasalforcingsIsmip7TfDepthsEnum; else if (strcmp(name,"BasalforcingsIsmip7NumBasins")==0) return BasalforcingsIsmip7NumBasinsEnum; else if (strcmp(name,"BasalforcingsIsmip7Gamma")==0) return BasalforcingsIsmip7GammaEnum; @@ -134,12 +136,12 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"CalvingTheta")==0) return CalvingThetaEnum; else if (strcmp(name,"CalvingAlpha")==0) return CalvingAlphaEnum; else if (strcmp(name,"CalvingXoffset")==0) return CalvingXoffsetEnum; - else if (strcmp(name,"CalvingYoffset")==0) return CalvingYoffsetEnum; - else if (strcmp(name,"CalvingVelLowerbound")==0) return CalvingVelLowerboundEnum; else stage=2; } if(stage==2){ - if (strcmp(name,"CalvingVelMax")==0) return CalvingVelMaxEnum; + if (strcmp(name,"CalvingYoffset")==0) return CalvingYoffsetEnum; + else if (strcmp(name,"CalvingVelLowerbound")==0) return CalvingVelLowerboundEnum; + else if (strcmp(name,"CalvingVelMax")==0) return CalvingVelMaxEnum; else if (strcmp(name,"CalvingVelThreshold")==0) return CalvingVelThresholdEnum; else if (strcmp(name,"CalvingVelUpperbound")==0) return CalvingVelUpperboundEnum; else if (strcmp(name,"CalvingRc")==0) return CalvingRcEnum; @@ -257,12 +259,12 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"FrontalForcingsSddatebreaks")==0) return FrontalForcingsSddatebreaksEnum; else if (strcmp(name,"FrontalForcingsSdmalagcoefs")==0) return FrontalForcingsSdmalagcoefsEnum; else if (strcmp(name,"FrontalForcingsSdmaOrder")==0) return FrontalForcingsSdmaOrderEnum; - else if (strcmp(name,"FrontalForcingsSdMonthlyFrac")==0) return FrontalForcingsSdMonthlyFracEnum; - else if (strcmp(name,"FrontalForcingsSdNumberofBreaks")==0) return FrontalForcingsSdNumberofBreaksEnum; else stage=3; } if(stage==3){ - if (strcmp(name,"FrontalForcingsSdNumberofParams")==0) return FrontalForcingsSdNumberofParamsEnum; + if (strcmp(name,"FrontalForcingsSdMonthlyFrac")==0) return FrontalForcingsSdMonthlyFracEnum; + else if (strcmp(name,"FrontalForcingsSdNumberofBreaks")==0) return FrontalForcingsSdNumberofBreaksEnum; + else if (strcmp(name,"FrontalForcingsSdNumberofParams")==0) return FrontalForcingsSdNumberofParamsEnum; else if (strcmp(name,"FrontalForcingsSdpolyparams")==0) return FrontalForcingsSdpolyparamsEnum; else if (strcmp(name,"GrdModel")==0) return GrdModelEnum; else if (strcmp(name,"GroundinglineFrictionInterpolation")==0) return GroundinglineFrictionInterpolationEnum; @@ -359,6 +361,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"InversionNumCostFunctions")==0) return InversionNumCostFunctionsEnum; else if (strcmp(name,"InversionStepThreshold")==0) return InversionStepThresholdEnum; else if (strcmp(name,"InversionStopFlag")==0) return InversionStopFlagEnum; + else if (strcmp(name,"InversionTauC")==0) return InversionTauCEnum; else if (strcmp(name,"InversionType")==0) return InversionTypeEnum; else if (strcmp(name,"IoConstant")==0) return IoConstantEnum; else if (strcmp(name,"Ivins")==0) return IvinsEnum; @@ -379,13 +382,13 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"LoveInnerCoreBoundary")==0) return LoveInnerCoreBoundaryEnum; else if (strcmp(name,"LoveComplexComputation")==0) return LoveComplexComputationEnum; else if (strcmp(name,"LoveQuadPrecision")==0) return LoveQuadPrecisionEnum; - else if (strcmp(name,"LoveIntStepsPerLayer")==0) return LoveIntStepsPerLayerEnum; - else if (strcmp(name,"LoveMinIntegrationSteps")==0) return LoveMinIntegrationStepsEnum; - else if (strcmp(name,"LoveMaxIntegrationdr")==0) return LoveMaxIntegrationdrEnum; else stage=4; } if(stage==4){ - if (strcmp(name,"LoveIntegrationScheme")==0) return LoveIntegrationSchemeEnum; + if (strcmp(name,"LoveIntStepsPerLayer")==0) return LoveIntStepsPerLayerEnum; + else if (strcmp(name,"LoveMinIntegrationSteps")==0) return LoveMinIntegrationStepsEnum; + else if (strcmp(name,"LoveMaxIntegrationdr")==0) return LoveMaxIntegrationdrEnum; + else if (strcmp(name,"LoveIntegrationScheme")==0) return LoveIntegrationSchemeEnum; else if (strcmp(name,"LoveKernels")==0) return LoveKernelsEnum; else if (strcmp(name,"LoveMu0")==0) return LoveMu0Enum; else if (strcmp(name,"LoveNfreq")==0) return LoveNfreqEnum; @@ -499,16 +502,19 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SealevelchangeViscousNumSteps")==0) return SealevelchangeViscousNumStepsEnum; else if (strcmp(name,"SealevelchangeViscousTimes")==0) return SealevelchangeViscousTimesEnum; else if (strcmp(name,"SealevelchangeViscousIndex")==0) return SealevelchangeViscousIndexEnum; - else if (strcmp(name,"SealevelchangeViscousPolarMotion")==0) return SealevelchangeViscousPolarMotionEnum; + else if (strcmp(name,"SealevelchangeViscousSampling")==0) return SealevelchangeViscousSamplingEnum; + else if (strcmp(name,"SealevelchangeViscousSamplingLength")==0) return SealevelchangeViscousSamplingLengthEnum; + else if (strcmp(name,"SealevelchangeViscousSamplingIndex")==0) return SealevelchangeViscousSamplingIndexEnum; + else stage=5; + } + if(stage==5){ + if (strcmp(name,"SealevelchangeViscousPolarMotion")==0) return SealevelchangeViscousPolarMotionEnum; else if (strcmp(name,"SealevelchangeRunCount")==0) return SealevelchangeRunCountEnum; else if (strcmp(name,"SealevelchangeTransitions")==0) return SealevelchangeTransitionsEnum; else if (strcmp(name,"SealevelchangeRequestedOutputs")==0) return SealevelchangeRequestedOutputsEnum; else if (strcmp(name,"RotationalAngularVelocity")==0) return RotationalAngularVelocityEnum; else if (strcmp(name,"RotationalEquatorialMoi")==0) return RotationalEquatorialMoiEnum; - else stage=5; - } - if(stage==5){ - if (strcmp(name,"RotationalPolarMoi")==0) return RotationalPolarMoiEnum; + else if (strcmp(name,"RotationalPolarMoi")==0) return RotationalPolarMoiEnum; else if (strcmp(name,"LovePolarMotionTransferFunctionColinear")==0) return LovePolarMotionTransferFunctionColinearEnum; else if (strcmp(name,"LovePolarMotionTransferFunctionOrthogonal")==0) return LovePolarMotionTransferFunctionOrthogonalEnum; else if (strcmp(name,"TidalLoveH")==0) return TidalLoveHEnum; @@ -622,17 +628,19 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SmbInitDensityScaling")==0) return SmbInitDensityScalingEnum; else if (strcmp(name,"SmbIsaccumulation")==0) return SmbIsaccumulationEnum; else if (strcmp(name,"SmbIsalbedo")==0) return SmbIsalbedoEnum; - else if (strcmp(name,"SmbIsconstrainsurfaceT")==0) return SmbIsconstrainsurfaceTEnum; + else stage=6; + } + if(stage==6){ + if (strcmp(name,"SmbIsconstrainsurfaceT")==0) return SmbIsconstrainsurfaceTEnum; else if (strcmp(name,"SmbIsd18opd")==0) return SmbIsd18opdEnum; else if (strcmp(name,"SmbIsdelta18o")==0) return SmbIsdelta18oEnum; else if (strcmp(name,"SmbIsdensification")==0) return SmbIsdensificationEnum; else if (strcmp(name,"SmbIsdeltaLWup")==0) return SmbIsdeltaLWupEnum; else if (strcmp(name,"SmbIsfirnwarming")==0) return SmbIsfirnwarmingEnum; - else stage=6; - } - if(stage==6){ - if (strcmp(name,"SmbIsgraingrowth")==0) return SmbIsgraingrowthEnum; + else if (strcmp(name,"SmbIsgraingrowth")==0) return SmbIsgraingrowthEnum; else if (strcmp(name,"SmbIsmappedforcing")==0) return SmbIsmappedforcingEnum; + else if (strcmp(name,"SmbIsmappingusingneighbors")==0) return SmbIsmappingusingneighborsEnum; + else if (strcmp(name,"SmbIsmappingneighborxy")==0) return SmbIsmappingneighborxyEnum; else if (strcmp(name,"SmbIsmelt")==0) return SmbIsmeltEnum; else if (strcmp(name,"SmbIsmungsm")==0) return SmbIsmungsmEnum; else if (strcmp(name,"SmbIsprecipforcingremapped")==0) return SmbIsprecipforcingremappedEnum; @@ -646,6 +654,8 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SmbLapsedlwrfValue")==0) return SmbLapsedlwrfValueEnum; else if (strcmp(name,"SmbLapseRates")==0) return SmbLapseRatesEnum; else if (strcmp(name,"SmbLapseTaValue")==0) return SmbLapseTaValueEnum; + else if (strcmp(name,"SmbLatMappedforcing")==0) return SmbLatMappedforcingEnum; + else if (strcmp(name,"SmbLonMappedforcing")==0) return SmbLonMappedforcingEnum; else if (strcmp(name,"SmbLWgrad")==0) return SmbLWgradEnum; else if (strcmp(name,"SmbMappedforcingelevation")==0) return SmbMappedforcingelevationEnum; else if (strcmp(name,"SmbNumBasins")==0) return SmbNumBasinsEnum; @@ -685,6 +695,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SmbT0wet")==0) return SmbT0wetEnum; else if (strcmp(name,"SmbTaParam")==0) return SmbTaParamEnum; else if (strcmp(name,"SmbTcIdx")==0) return SmbTcIdxEnum; + else if (strcmp(name,"SmbTeDefault")==0) return SmbTeDefaultEnum; else if (strcmp(name,"SmbTeThresh")==0) return SmbTeThreshEnum; else if (strcmp(name,"SmbTdiff")==0) return SmbTdiffEnum; else if (strcmp(name,"SmbThermoDeltaTScaling")==0) return SmbThermoDeltaTScalingEnum; @@ -696,6 +707,8 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SmbVmeanParam")==0) return SmbVmeanParamEnum; else if (strcmp(name,"SmbVzParam")==0) return SmbVzParamEnum; else if (strcmp(name,"SmbWindspeedgrad")==0) return SmbWindspeedgradEnum; + else if (strcmp(name,"SmbXMappedforcing")==0) return SmbXMappedforcingEnum; + else if (strcmp(name,"SmbYMappedforcing")==0) return SmbYMappedforcingEnum; else if (strcmp(name,"SmoothThicknessMultiplier")==0) return SmoothThicknessMultiplierEnum; else if (strcmp(name,"SolutionType")==0) return SolutionTypeEnum; else if (strcmp(name,"SteadystateMaxiter")==0) return SteadystateMaxiterEnum; @@ -708,6 +721,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"StressbalanceFSreconditioning")==0) return StressbalanceFSreconditioningEnum; else if (strcmp(name,"StressbalanceIsHydrologyLayer")==0) return StressbalanceIsHydrologyLayerEnum; else if (strcmp(name,"StressbalanceIsnewton")==0) return StressbalanceIsnewtonEnum; + else if (strcmp(name,"StressbalanceIsemulator")==0) return StressbalanceIsemulatorEnum; + else if (strcmp(name,"EdgesNumber")==0) return EdgesNumberEnum; + else if (strcmp(name,"EdgesSrc")==0) return EdgesSrcEnum; + else if (strcmp(name,"EdgesDst")==0) return EdgesDstEnum; else if (strcmp(name,"StressbalanceMaxiter")==0) return StressbalanceMaxiterEnum; else if (strcmp(name,"StressbalanceNumRequestedOutputs")==0) return StressbalanceNumRequestedOutputsEnum; else if (strcmp(name,"StressbalancePenaltyFactor")==0) return StressbalancePenaltyFactorEnum; @@ -734,7 +751,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"TimesteppingCflCoefficient")==0) return TimesteppingCflCoefficientEnum; else if (strcmp(name,"TimesteppingCouplingTime")==0) return TimesteppingCouplingTimeEnum; else if (strcmp(name,"TimesteppingFinalTime")==0) return TimesteppingFinalTimeEnum; - else if (strcmp(name,"TimesteppingInterpForcing")==0) return TimesteppingInterpForcingEnum; + else stage=7; + } + if(stage==7){ + if (strcmp(name,"TimesteppingInterpForcing")==0) return TimesteppingInterpForcingEnum; else if (strcmp(name,"TimesteppingCycleForcing")==0) return TimesteppingCycleForcingEnum; else if (strcmp(name,"TimesteppingStartTime")==0) return TimesteppingStartTimeEnum; else if (strcmp(name,"TimesteppingTimeStep")==0) return TimesteppingTimeStepEnum; @@ -751,10 +771,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"TransientIsdamageevolution")==0) return TransientIsdamageevolutionEnum; else if (strcmp(name,"TransientIsdebris")==0) return TransientIsdebrisEnum; else if (strcmp(name,"TransientIsesa")==0) return TransientIsesaEnum; - else stage=7; - } - if(stage==7){ - if (strcmp(name,"TransientIsgia")==0) return TransientIsgiaEnum; + else if (strcmp(name,"TransientIsgia")==0) return TransientIsgiaEnum; else if (strcmp(name,"TransientIsgroundingline")==0) return TransientIsgroundinglineEnum; else if (strcmp(name,"TransientIshydrology")==0) return TransientIshydrologyEnum; else if (strcmp(name,"TransientIsmasstransport")==0) return TransientIsmasstransportEnum; @@ -775,6 +792,9 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Zze")==0) return ZzeEnum; else if (strcmp(name,"Areae")==0) return AreaeEnum; else if (strcmp(name,"WorldComm")==0) return WorldCommEnum; + else if (strcmp(name,"FrictionEmulator")==0) return FrictionEmulatorEnum; + else if (strcmp(name,"SmbEmulator")==0) return SmbEmulatorEnum; + else if (strcmp(name,"StressbalanceEmulator")==0) return StressbalanceEmulatorEnum; else if (strcmp(name,"ParametersEND")==0) return ParametersENDEnum; else if (strcmp(name,"InputsSTART")==0) return InputsSTARTEnum; else if (strcmp(name,"AccumulatedDeltaBottomPressure")==0) return AccumulatedDeltaBottomPressureEnum; @@ -818,6 +838,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"BasalforcingsIsmip6Tf")==0) return BasalforcingsIsmip6TfEnum; else if (strcmp(name,"BasalforcingsIsmip6TfShelf")==0) return BasalforcingsIsmip6TfShelfEnum; else if (strcmp(name,"BasalforcingsIsmip6MeltAnomaly")==0) return BasalforcingsIsmip6MeltAnomalyEnum; + else if (strcmp(name,"BasalforcingsIsmip7BasinId")==0) return BasalforcingsIsmip7BasinIdEnum; else if (strcmp(name,"BasalforcingsIsmip7Tf")==0) return BasalforcingsIsmip7TfEnum; else if (strcmp(name,"BasalforcingsIsmip7TfShelf")==0) return BasalforcingsIsmip7TfShelfEnum; else if (strcmp(name,"BasalforcingsIsmip7Salinity")==0) return BasalforcingsIsmip7SalinityEnum; @@ -853,7 +874,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"BedSlopeY")==0) return BedSlopeYEnum; else if (strcmp(name,"BottomPressure")==0) return BottomPressureEnum; else if (strcmp(name,"BottomPressureOld")==0) return BottomPressureOldEnum; - else if (strcmp(name,"CalvingBasinId")==0) return CalvingBasinIdEnum; + else stage=8; + } + if(stage==8){ + if (strcmp(name,"CalvingBasinId")==0) return CalvingBasinIdEnum; else if (strcmp(name,"CalvingCalvingrate")==0) return CalvingCalvingrateEnum; else if (strcmp(name,"CalvingHabFraction")==0) return CalvingHabFractionEnum; else if (strcmp(name,"CalvingAblationrate")==0) return CalvingAblationrateEnum; @@ -874,10 +898,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"DamageF")==0) return DamageFEnum; else if (strcmp(name,"DebrisThickness")==0) return DebrisThicknessEnum; else if (strcmp(name,"DegreeOfChannelization")==0) return DegreeOfChannelizationEnum; - else stage=8; - } - if(stage==8){ - if (strcmp(name,"DepthBelowSurface")==0) return DepthBelowSurfaceEnum; + else if (strcmp(name,"DepthBelowSurface")==0) return DepthBelowSurfaceEnum; else if (strcmp(name,"DeltaIceThickness")==0) return DeltaIceThicknessEnum; else if (strcmp(name,"DeltaTws")==0) return DeltaTwsEnum; else if (strcmp(name,"DeltaBottomPressure")==0) return DeltaBottomPressureEnum; @@ -976,7 +997,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"HydrologydcSedimentTransmitivity")==0) return HydrologydcSedimentTransmitivityEnum; else if (strcmp(name,"HydrologyDissipation")==0) return HydrologyDissipationEnum; else if (strcmp(name,"HydrologyDrainageRate")==0) return HydrologyDrainageRateEnum; - else if (strcmp(name,"HydrologyEnglacialInput")==0) return HydrologyEnglacialInputEnum; + else stage=9; + } + if(stage==9){ + if (strcmp(name,"HydrologyEnglacialInput")==0) return HydrologyEnglacialInputEnum; else if (strcmp(name,"HydrologyFrictionHeat")==0) return HydrologyFrictionHeatEnum; else if (strcmp(name,"HydrologyGapHeight")==0) return HydrologyGapHeightEnum; else if (strcmp(name,"HydrologyGapHeightX")==0) return HydrologyGapHeightXEnum; @@ -997,10 +1021,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"HydrologySheetThicknessOld")==0) return HydrologySheetThicknessOldEnum; else if (strcmp(name,"HydrologyStorage")==0) return HydrologyStorageEnum; else if (strcmp(name,"HydrologyTws")==0) return HydrologyTwsEnum; - else stage=9; - } - if(stage==9){ - if (strcmp(name,"HydrologyTwsSpc")==0) return HydrologyTwsSpcEnum; + else if (strcmp(name,"HydrologyTwsSpc")==0) return HydrologyTwsSpcEnum; else if (strcmp(name,"HydrologyTwsAnalysis")==0) return HydrologyTwsAnalysisEnum; else if (strcmp(name,"HydrologyWatercolumnMax")==0) return HydrologyWatercolumnMaxEnum; else if (strcmp(name,"HydrologyWaterVx")==0) return HydrologyWaterVxEnum; @@ -1099,7 +1120,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SealevelBarystaticOceanLatbar")==0) return SealevelBarystaticOceanLatbarEnum; else if (strcmp(name,"SealevelBarystaticOceanLongbar")==0) return SealevelBarystaticOceanLongbarEnum; else if (strcmp(name,"SealevelBarystaticOceanLoad")==0) return SealevelBarystaticOceanLoadEnum; - else if (strcmp(name,"SealevelNEsa")==0) return SealevelNEsaEnum; + else stage=10; + } + if(stage==10){ + if (strcmp(name,"SealevelNEsa")==0) return SealevelNEsaEnum; else if (strcmp(name,"SealevelNEsaRate")==0) return SealevelNEsaRateEnum; else if (strcmp(name,"SealevelRSL")==0) return SealevelRSLEnum; else if (strcmp(name,"Bslc")==0) return BslcEnum; @@ -1120,10 +1144,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SealevelchangeAzimuthIndex")==0) return SealevelchangeAzimuthIndexEnum; else if (strcmp(name,"SealevelchangeGrot")==0) return SealevelchangeGrotEnum; else if (strcmp(name,"SealevelchangeGSatGravirot")==0) return SealevelchangeGSatGravirotEnum; - else stage=10; - } - if(stage==10){ - if (strcmp(name,"SealevelchangeGUrot")==0) return SealevelchangeGUrotEnum; + else if (strcmp(name,"SealevelchangeGUrot")==0) return SealevelchangeGUrotEnum; else if (strcmp(name,"SealevelchangeGNrot")==0) return SealevelchangeGNrotEnum; else if (strcmp(name,"SealevelchangeGErot")==0) return SealevelchangeGErotEnum; else if (strcmp(name,"SealevelchangeAlphaIndexOcean")==0) return SealevelchangeAlphaIndexOceanEnum; @@ -1222,9 +1243,15 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SmbHIceInit")==0) return SmbHIceInitEnum; else if (strcmp(name,"SmbHSnow")==0) return SmbHSnowEnum; else if (strcmp(name,"SmbHSnowInit")==0) return SmbHSnowInitEnum; - else if (strcmp(name,"SmbHref")==0) return SmbHrefEnum; + else stage=11; + } + if(stage==11){ + if (strcmp(name,"SmbHref")==0) return SmbHrefEnum; else if (strcmp(name,"SmbIsInitialized")==0) return SmbIsInitializedEnum; + else if (strcmp(name,"SmbLat")==0) return SmbLatEnum; + else if (strcmp(name,"SmbLon")==0) return SmbLonEnum; else if (strcmp(name,"SmbMAdd")==0) return SmbMAddEnum; + else if (strcmp(name,"SmbMappedforcingneighbors")==0) return SmbMappedforcingneighborsEnum; else if (strcmp(name,"SmbMappedforcingpoint")==0) return SmbMappedforcingpointEnum; else if (strcmp(name,"SmbMappedforcingprecipscaling")==0) return SmbMappedforcingprecipscalingEnum; else if (strcmp(name,"SmbMassBalance")==0) return SmbMassBalanceEnum; @@ -1233,20 +1260,21 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SmbMassBalanceSubstep")==0) return SmbMassBalanceSubstepEnum; else if (strcmp(name,"SmbMassBalanceTransient")==0) return SmbMassBalanceTransientEnum; else if (strcmp(name,"SmbMask")==0) return SmbMaskEnum; + else if (strcmp(name,"SmbMaxX")==0) return SmbMaxXEnum; + else if (strcmp(name,"SmbMaxY")==0) return SmbMaxYEnum; else if (strcmp(name,"SmbMeanLHF")==0) return SmbMeanLHFEnum; else if (strcmp(name,"SmbMeanSHF")==0) return SmbMeanSHFEnum; else if (strcmp(name,"SmbMeanULW")==0) return SmbMeanULWEnum; else if (strcmp(name,"SmbMeanTemperature")==0) return SmbMeanTemperatureEnum; else if (strcmp(name,"SmbMelt")==0) return SmbMeltEnum; else if (strcmp(name,"SmbMeltSubstep")==0) return SmbMeltSubstepEnum; + else if (strcmp(name,"SmbMinX")==0) return SmbMinXEnum; + else if (strcmp(name,"SmbMinY")==0) return SmbMinYEnum; else if (strcmp(name,"SmbMonthlytemperatures")==0) return SmbMonthlytemperaturesEnum; else if (strcmp(name,"SmbMonthlydsradiation")==0) return SmbMonthlydsradiationEnum; else if (strcmp(name,"SmbMonthlydlradiation")==0) return SmbMonthlydlradiationEnum; else if (strcmp(name,"SmbMonthlywindspeed")==0) return SmbMonthlywindspeedEnum; - else stage=11; - } - if(stage==11){ - if (strcmp(name,"SmbMonthlyairhumidity")==0) return SmbMonthlyairhumidityEnum; + else if (strcmp(name,"SmbMonthlyairhumidity")==0) return SmbMonthlyairhumidityEnum; else if (strcmp(name,"SmbMSurf")==0) return SmbMSurfEnum; else if (strcmp(name,"SmbMSurfSum")==0) return SmbMSurfSumEnum; else if (strcmp(name,"SmbNetLW")==0) return SmbNetLWEnum; @@ -1258,6 +1286,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SmbPrecipitation")==0) return SmbPrecipitationEnum; else if (strcmp(name,"SmbPrecipitationSubstep")==0) return SmbPrecipitationSubstepEnum; else if (strcmp(name,"SmbPrecipitationsAnomaly")==0) return SmbPrecipitationsAnomalyEnum; + else if (strcmp(name,"SmbQinterp")==0) return SmbQinterpEnum; else if (strcmp(name,"SmbDsradiationAnomaly")==0) return SmbDsradiationAnomalyEnum; else if (strcmp(name,"SmbDlradiationAnomaly")==0) return SmbDlradiationAnomalyEnum; else if (strcmp(name,"SmbWindspeedAnomaly")==0) return SmbWindspeedAnomalyEnum; @@ -1314,6 +1343,17 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SmbZMin")==0) return SmbZMinEnum; else if (strcmp(name,"SmbZTop")==0) return SmbZTopEnum; else if (strcmp(name,"SmbZY")==0) return SmbZYEnum; + else if (strcmp(name,"MariaSmb")==0) return MariaSmbEnum; + else if (strcmp(name,"MariaElev")==0) return MariaElevEnum; + else if (strcmp(name,"MariaAl")==0) return MariaAlEnum; + else if (strcmp(name,"MariaSt")==0) return MariaStEnum; + else if (strcmp(name,"MariaTt")==0) return MariaTtEnum; + else if (strcmp(name,"MariaSwd")==0) return MariaSwdEnum; + else if (strcmp(name,"MariaLwd")==0) return MariaLwdEnum; + else if (strcmp(name,"MariaSwu")==0) return MariaSwuEnum; + else if (strcmp(name,"MariaLwu")==0) return MariaLwuEnum; + else if (strcmp(name,"MariaShf")==0) return MariaShfEnum; + else if (strcmp(name,"MariaLhf")==0) return MariaLhfEnum; else if (strcmp(name,"SolidearthExternalDisplacementEastRate")==0) return SolidearthExternalDisplacementEastRateEnum; else if (strcmp(name,"SolidearthExternalDisplacementNorthRate")==0) return SolidearthExternalDisplacementNorthRateEnum; else if (strcmp(name,"SolidearthExternalDisplacementUpRate")==0) return SolidearthExternalDisplacementUpRateEnum; @@ -1326,7 +1366,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"StrainRatexy")==0) return StrainRatexyEnum; else if (strcmp(name,"StrainRatexz")==0) return StrainRatexzEnum; else if (strcmp(name,"StrainRateyy")==0) return StrainRateyyEnum; - else if (strcmp(name,"StrainRateyz")==0) return StrainRateyzEnum; + else stage=12; + } + if(stage==12){ + if (strcmp(name,"StrainRateyz")==0) return StrainRateyzEnum; else if (strcmp(name,"StrainRatezz")==0) return StrainRatezzEnum; else if (strcmp(name,"StressMaxPrincipal")==0) return StressMaxPrincipalEnum; else if (strcmp(name,"StressTensorxx")==0) return StressTensorxxEnum; @@ -1366,10 +1409,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"ThicknessAbsGradient")==0) return ThicknessAbsGradientEnum; else if (strcmp(name,"ThicknessAbsMisfit")==0) return ThicknessAbsMisfitEnum; else if (strcmp(name,"ThicknessAcrossGradient")==0) return ThicknessAcrossGradientEnum; - else stage=12; - } - if(stage==12){ - if (strcmp(name,"ThicknessAlongGradient")==0) return ThicknessAlongGradientEnum; + else if (strcmp(name,"ThicknessAlongGradient")==0) return ThicknessAlongGradientEnum; else if (strcmp(name,"Thickness")==0) return ThicknessEnum; else if (strcmp(name,"ThicknessOld")==0) return ThicknessOldEnum; else if (strcmp(name,"ThicknessPositive")==0) return ThicknessPositiveEnum; @@ -1449,7 +1489,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition3")==0) return Outputdefinition3Enum; else if (strcmp(name,"Outputdefinition40")==0) return Outputdefinition40Enum; else if (strcmp(name,"Outputdefinition41")==0) return Outputdefinition41Enum; - else if (strcmp(name,"Outputdefinition42")==0) return Outputdefinition42Enum; + else stage=13; + } + if(stage==13){ + if (strcmp(name,"Outputdefinition42")==0) return Outputdefinition42Enum; else if (strcmp(name,"Outputdefinition43")==0) return Outputdefinition43Enum; else if (strcmp(name,"Outputdefinition44")==0) return Outputdefinition44Enum; else if (strcmp(name,"Outputdefinition45")==0) return Outputdefinition45Enum; @@ -1489,10 +1532,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition76")==0) return Outputdefinition76Enum; else if (strcmp(name,"Outputdefinition77")==0) return Outputdefinition77Enum; else if (strcmp(name,"Outputdefinition78")==0) return Outputdefinition78Enum; - else stage=13; - } - if(stage==13){ - if (strcmp(name,"Outputdefinition79")==0) return Outputdefinition79Enum; + else if (strcmp(name,"Outputdefinition79")==0) return Outputdefinition79Enum; else if (strcmp(name,"Outputdefinition7")==0) return Outputdefinition7Enum; else if (strcmp(name,"Outputdefinition80")==0) return Outputdefinition80Enum; else if (strcmp(name,"Outputdefinition81")==0) return Outputdefinition81Enum; @@ -1572,7 +1612,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition158")==0) return Outputdefinition158Enum; else if (strcmp(name,"Outputdefinition159")==0) return Outputdefinition159Enum; else if (strcmp(name,"Outputdefinition105")==0) return Outputdefinition105Enum; - else if (strcmp(name,"Outputdefinition160")==0) return Outputdefinition160Enum; + else stage=14; + } + if(stage==14){ + if (strcmp(name,"Outputdefinition160")==0) return Outputdefinition160Enum; else if (strcmp(name,"Outputdefinition161")==0) return Outputdefinition161Enum; else if (strcmp(name,"Outputdefinition162")==0) return Outputdefinition162Enum; else if (strcmp(name,"Outputdefinition163")==0) return Outputdefinition163Enum; @@ -1612,10 +1655,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition194")==0) return Outputdefinition194Enum; else if (strcmp(name,"Outputdefinition195")==0) return Outputdefinition195Enum; else if (strcmp(name,"Outputdefinition196")==0) return Outputdefinition196Enum; - else stage=14; - } - if(stage==14){ - if (strcmp(name,"Outputdefinition197")==0) return Outputdefinition197Enum; + else if (strcmp(name,"Outputdefinition197")==0) return Outputdefinition197Enum; else if (strcmp(name,"Outputdefinition198")==0) return Outputdefinition198Enum; else if (strcmp(name,"Outputdefinition199")==0) return Outputdefinition199Enum; else if (strcmp(name,"Outputdefinition109")==0) return Outputdefinition109Enum; @@ -1695,7 +1735,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition276")==0) return Outputdefinition276Enum; else if (strcmp(name,"Outputdefinition277")==0) return Outputdefinition277Enum; else if (strcmp(name,"Outputdefinition278")==0) return Outputdefinition278Enum; - else if (strcmp(name,"Outputdefinition279")==0) return Outputdefinition279Enum; + else stage=15; + } + if(stage==15){ + if (strcmp(name,"Outputdefinition279")==0) return Outputdefinition279Enum; else if (strcmp(name,"Outputdefinition207")==0) return Outputdefinition207Enum; else if (strcmp(name,"Outputdefinition280")==0) return Outputdefinition280Enum; else if (strcmp(name,"Outputdefinition281")==0) return Outputdefinition281Enum; @@ -1735,10 +1778,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition321")==0) return Outputdefinition321Enum; else if (strcmp(name,"Outputdefinition322")==0) return Outputdefinition322Enum; else if (strcmp(name,"Outputdefinition323")==0) return Outputdefinition323Enum; - else stage=15; - } - if(stage==15){ - if (strcmp(name,"Outputdefinition324")==0) return Outputdefinition324Enum; + else if (strcmp(name,"Outputdefinition324")==0) return Outputdefinition324Enum; else if (strcmp(name,"Outputdefinition325")==0) return Outputdefinition325Enum; else if (strcmp(name,"Outputdefinition326")==0) return Outputdefinition326Enum; else if (strcmp(name,"Outputdefinition327")==0) return Outputdefinition327Enum; @@ -1818,7 +1858,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition394")==0) return Outputdefinition394Enum; else if (strcmp(name,"Outputdefinition395")==0) return Outputdefinition395Enum; else if (strcmp(name,"Outputdefinition396")==0) return Outputdefinition396Enum; - else if (strcmp(name,"Outputdefinition397")==0) return Outputdefinition397Enum; + else stage=16; + } + if(stage==16){ + if (strcmp(name,"Outputdefinition397")==0) return Outputdefinition397Enum; else if (strcmp(name,"Outputdefinition398")==0) return Outputdefinition398Enum; else if (strcmp(name,"Outputdefinition399")==0) return Outputdefinition399Enum; else if (strcmp(name,"Outputdefinition309")==0) return Outputdefinition309Enum; @@ -1858,10 +1901,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition403")==0) return Outputdefinition403Enum; else if (strcmp(name,"Outputdefinition440")==0) return Outputdefinition440Enum; else if (strcmp(name,"Outputdefinition441")==0) return Outputdefinition441Enum; - else stage=16; - } - if(stage==16){ - if (strcmp(name,"Outputdefinition442")==0) return Outputdefinition442Enum; + else if (strcmp(name,"Outputdefinition442")==0) return Outputdefinition442Enum; else if (strcmp(name,"Outputdefinition443")==0) return Outputdefinition443Enum; else if (strcmp(name,"Outputdefinition444")==0) return Outputdefinition444Enum; else if (strcmp(name,"Outputdefinition445")==0) return Outputdefinition445Enum; @@ -1941,7 +1981,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition521")==0) return Outputdefinition521Enum; else if (strcmp(name,"Outputdefinition522")==0) return Outputdefinition522Enum; else if (strcmp(name,"Outputdefinition523")==0) return Outputdefinition523Enum; - else if (strcmp(name,"Outputdefinition524")==0) return Outputdefinition524Enum; + else stage=17; + } + if(stage==17){ + if (strcmp(name,"Outputdefinition524")==0) return Outputdefinition524Enum; else if (strcmp(name,"Outputdefinition525")==0) return Outputdefinition525Enum; else if (strcmp(name,"Outputdefinition526")==0) return Outputdefinition526Enum; else if (strcmp(name,"Outputdefinition527")==0) return Outputdefinition527Enum; @@ -1981,10 +2024,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition558")==0) return Outputdefinition558Enum; else if (strcmp(name,"Outputdefinition559")==0) return Outputdefinition559Enum; else if (strcmp(name,"Outputdefinition505")==0) return Outputdefinition505Enum; - else stage=17; - } - if(stage==17){ - if (strcmp(name,"Outputdefinition560")==0) return Outputdefinition560Enum; + else if (strcmp(name,"Outputdefinition560")==0) return Outputdefinition560Enum; else if (strcmp(name,"Outputdefinition561")==0) return Outputdefinition561Enum; else if (strcmp(name,"Outputdefinition562")==0) return Outputdefinition562Enum; else if (strcmp(name,"Outputdefinition563")==0) return Outputdefinition563Enum; @@ -2064,7 +2104,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition603")==0) return Outputdefinition603Enum; else if (strcmp(name,"Outputdefinition640")==0) return Outputdefinition640Enum; else if (strcmp(name,"Outputdefinition641")==0) return Outputdefinition641Enum; - else if (strcmp(name,"Outputdefinition642")==0) return Outputdefinition642Enum; + else stage=18; + } + if(stage==18){ + if (strcmp(name,"Outputdefinition642")==0) return Outputdefinition642Enum; else if (strcmp(name,"Outputdefinition643")==0) return Outputdefinition643Enum; else if (strcmp(name,"Outputdefinition644")==0) return Outputdefinition644Enum; else if (strcmp(name,"Outputdefinition645")==0) return Outputdefinition645Enum; @@ -2104,10 +2147,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition676")==0) return Outputdefinition676Enum; else if (strcmp(name,"Outputdefinition677")==0) return Outputdefinition677Enum; else if (strcmp(name,"Outputdefinition678")==0) return Outputdefinition678Enum; - else stage=18; - } - if(stage==18){ - if (strcmp(name,"Outputdefinition679")==0) return Outputdefinition679Enum; + else if (strcmp(name,"Outputdefinition679")==0) return Outputdefinition679Enum; else if (strcmp(name,"Outputdefinition607")==0) return Outputdefinition607Enum; else if (strcmp(name,"Outputdefinition680")==0) return Outputdefinition680Enum; else if (strcmp(name,"Outputdefinition681")==0) return Outputdefinition681Enum; @@ -2187,7 +2227,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition758")==0) return Outputdefinition758Enum; else if (strcmp(name,"Outputdefinition759")==0) return Outputdefinition759Enum; else if (strcmp(name,"Outputdefinition705")==0) return Outputdefinition705Enum; - else if (strcmp(name,"Outputdefinition760")==0) return Outputdefinition760Enum; + else stage=19; + } + if(stage==19){ + if (strcmp(name,"Outputdefinition760")==0) return Outputdefinition760Enum; else if (strcmp(name,"Outputdefinition761")==0) return Outputdefinition761Enum; else if (strcmp(name,"Outputdefinition762")==0) return Outputdefinition762Enum; else if (strcmp(name,"Outputdefinition763")==0) return Outputdefinition763Enum; @@ -2227,10 +2270,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition794")==0) return Outputdefinition794Enum; else if (strcmp(name,"Outputdefinition795")==0) return Outputdefinition795Enum; else if (strcmp(name,"Outputdefinition796")==0) return Outputdefinition796Enum; - else stage=19; - } - if(stage==19){ - if (strcmp(name,"Outputdefinition797")==0) return Outputdefinition797Enum; + else if (strcmp(name,"Outputdefinition797")==0) return Outputdefinition797Enum; else if (strcmp(name,"Outputdefinition798")==0) return Outputdefinition798Enum; else if (strcmp(name,"Outputdefinition799")==0) return Outputdefinition799Enum; else if (strcmp(name,"Outputdefinition709")==0) return Outputdefinition709Enum; @@ -2310,7 +2350,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition876")==0) return Outputdefinition876Enum; else if (strcmp(name,"Outputdefinition877")==0) return Outputdefinition877Enum; else if (strcmp(name,"Outputdefinition878")==0) return Outputdefinition878Enum; - else if (strcmp(name,"Outputdefinition879")==0) return Outputdefinition879Enum; + else stage=20; + } + if(stage==20){ + if (strcmp(name,"Outputdefinition879")==0) return Outputdefinition879Enum; else if (strcmp(name,"Outputdefinition807")==0) return Outputdefinition807Enum; else if (strcmp(name,"Outputdefinition880")==0) return Outputdefinition880Enum; else if (strcmp(name,"Outputdefinition881")==0) return Outputdefinition881Enum; @@ -2350,10 +2393,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition921")==0) return Outputdefinition921Enum; else if (strcmp(name,"Outputdefinition922")==0) return Outputdefinition922Enum; else if (strcmp(name,"Outputdefinition923")==0) return Outputdefinition923Enum; - else stage=20; - } - if(stage==20){ - if (strcmp(name,"Outputdefinition924")==0) return Outputdefinition924Enum; + else if (strcmp(name,"Outputdefinition924")==0) return Outputdefinition924Enum; else if (strcmp(name,"Outputdefinition925")==0) return Outputdefinition925Enum; else if (strcmp(name,"Outputdefinition926")==0) return Outputdefinition926Enum; else if (strcmp(name,"Outputdefinition927")==0) return Outputdefinition927Enum; @@ -2433,7 +2473,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition994")==0) return Outputdefinition994Enum; else if (strcmp(name,"Outputdefinition995")==0) return Outputdefinition995Enum; else if (strcmp(name,"Outputdefinition996")==0) return Outputdefinition996Enum; - else if (strcmp(name,"Outputdefinition997")==0) return Outputdefinition997Enum; + else stage=21; + } + if(stage==21){ + if (strcmp(name,"Outputdefinition997")==0) return Outputdefinition997Enum; else if (strcmp(name,"Outputdefinition998")==0) return Outputdefinition998Enum; else if (strcmp(name,"Outputdefinition999")==0) return Outputdefinition999Enum; else if (strcmp(name,"Outputdefinition909")==0) return Outputdefinition909Enum; @@ -2473,10 +2516,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1003")==0) return Outputdefinition1003Enum; else if (strcmp(name,"Outputdefinition1040")==0) return Outputdefinition1040Enum; else if (strcmp(name,"Outputdefinition1041")==0) return Outputdefinition1041Enum; - else stage=21; - } - if(stage==21){ - if (strcmp(name,"Outputdefinition1042")==0) return Outputdefinition1042Enum; + else if (strcmp(name,"Outputdefinition1042")==0) return Outputdefinition1042Enum; else if (strcmp(name,"Outputdefinition1043")==0) return Outputdefinition1043Enum; else if (strcmp(name,"Outputdefinition1044")==0) return Outputdefinition1044Enum; else if (strcmp(name,"Outputdefinition1045")==0) return Outputdefinition1045Enum; @@ -2556,7 +2596,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1121")==0) return Outputdefinition1121Enum; else if (strcmp(name,"Outputdefinition1122")==0) return Outputdefinition1122Enum; else if (strcmp(name,"Outputdefinition1123")==0) return Outputdefinition1123Enum; - else if (strcmp(name,"Outputdefinition1124")==0) return Outputdefinition1124Enum; + else stage=22; + } + if(stage==22){ + if (strcmp(name,"Outputdefinition1124")==0) return Outputdefinition1124Enum; else if (strcmp(name,"Outputdefinition1125")==0) return Outputdefinition1125Enum; else if (strcmp(name,"Outputdefinition1126")==0) return Outputdefinition1126Enum; else if (strcmp(name,"Outputdefinition1127")==0) return Outputdefinition1127Enum; @@ -2596,10 +2639,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1158")==0) return Outputdefinition1158Enum; else if (strcmp(name,"Outputdefinition1159")==0) return Outputdefinition1159Enum; else if (strcmp(name,"Outputdefinition1105")==0) return Outputdefinition1105Enum; - else stage=22; - } - if(stage==22){ - if (strcmp(name,"Outputdefinition1160")==0) return Outputdefinition1160Enum; + else if (strcmp(name,"Outputdefinition1160")==0) return Outputdefinition1160Enum; else if (strcmp(name,"Outputdefinition1161")==0) return Outputdefinition1161Enum; else if (strcmp(name,"Outputdefinition1162")==0) return Outputdefinition1162Enum; else if (strcmp(name,"Outputdefinition1163")==0) return Outputdefinition1163Enum; @@ -2679,7 +2719,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1203")==0) return Outputdefinition1203Enum; else if (strcmp(name,"Outputdefinition1240")==0) return Outputdefinition1240Enum; else if (strcmp(name,"Outputdefinition1241")==0) return Outputdefinition1241Enum; - else if (strcmp(name,"Outputdefinition1242")==0) return Outputdefinition1242Enum; + else stage=23; + } + if(stage==23){ + if (strcmp(name,"Outputdefinition1242")==0) return Outputdefinition1242Enum; else if (strcmp(name,"Outputdefinition1243")==0) return Outputdefinition1243Enum; else if (strcmp(name,"Outputdefinition1244")==0) return Outputdefinition1244Enum; else if (strcmp(name,"Outputdefinition1245")==0) return Outputdefinition1245Enum; @@ -2719,10 +2762,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1276")==0) return Outputdefinition1276Enum; else if (strcmp(name,"Outputdefinition1277")==0) return Outputdefinition1277Enum; else if (strcmp(name,"Outputdefinition1278")==0) return Outputdefinition1278Enum; - else stage=23; - } - if(stage==23){ - if (strcmp(name,"Outputdefinition1279")==0) return Outputdefinition1279Enum; + else if (strcmp(name,"Outputdefinition1279")==0) return Outputdefinition1279Enum; else if (strcmp(name,"Outputdefinition1207")==0) return Outputdefinition1207Enum; else if (strcmp(name,"Outputdefinition1280")==0) return Outputdefinition1280Enum; else if (strcmp(name,"Outputdefinition1281")==0) return Outputdefinition1281Enum; @@ -2802,7 +2842,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1358")==0) return Outputdefinition1358Enum; else if (strcmp(name,"Outputdefinition1359")==0) return Outputdefinition1359Enum; else if (strcmp(name,"Outputdefinition1305")==0) return Outputdefinition1305Enum; - else if (strcmp(name,"Outputdefinition1360")==0) return Outputdefinition1360Enum; + else stage=24; + } + if(stage==24){ + if (strcmp(name,"Outputdefinition1360")==0) return Outputdefinition1360Enum; else if (strcmp(name,"Outputdefinition1361")==0) return Outputdefinition1361Enum; else if (strcmp(name,"Outputdefinition1362")==0) return Outputdefinition1362Enum; else if (strcmp(name,"Outputdefinition1363")==0) return Outputdefinition1363Enum; @@ -2842,10 +2885,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1394")==0) return Outputdefinition1394Enum; else if (strcmp(name,"Outputdefinition1395")==0) return Outputdefinition1395Enum; else if (strcmp(name,"Outputdefinition1396")==0) return Outputdefinition1396Enum; - else stage=24; - } - if(stage==24){ - if (strcmp(name,"Outputdefinition1397")==0) return Outputdefinition1397Enum; + else if (strcmp(name,"Outputdefinition1397")==0) return Outputdefinition1397Enum; else if (strcmp(name,"Outputdefinition1398")==0) return Outputdefinition1398Enum; else if (strcmp(name,"Outputdefinition1399")==0) return Outputdefinition1399Enum; else if (strcmp(name,"Outputdefinition1309")==0) return Outputdefinition1309Enum; @@ -2925,7 +2965,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1476")==0) return Outputdefinition1476Enum; else if (strcmp(name,"Outputdefinition1477")==0) return Outputdefinition1477Enum; else if (strcmp(name,"Outputdefinition1478")==0) return Outputdefinition1478Enum; - else if (strcmp(name,"Outputdefinition1479")==0) return Outputdefinition1479Enum; + else stage=25; + } + if(stage==25){ + if (strcmp(name,"Outputdefinition1479")==0) return Outputdefinition1479Enum; else if (strcmp(name,"Outputdefinition1407")==0) return Outputdefinition1407Enum; else if (strcmp(name,"Outputdefinition1480")==0) return Outputdefinition1480Enum; else if (strcmp(name,"Outputdefinition1481")==0) return Outputdefinition1481Enum; @@ -2965,10 +3008,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1521")==0) return Outputdefinition1521Enum; else if (strcmp(name,"Outputdefinition1522")==0) return Outputdefinition1522Enum; else if (strcmp(name,"Outputdefinition1523")==0) return Outputdefinition1523Enum; - else stage=25; - } - if(stage==25){ - if (strcmp(name,"Outputdefinition1524")==0) return Outputdefinition1524Enum; + else if (strcmp(name,"Outputdefinition1524")==0) return Outputdefinition1524Enum; else if (strcmp(name,"Outputdefinition1525")==0) return Outputdefinition1525Enum; else if (strcmp(name,"Outputdefinition1526")==0) return Outputdefinition1526Enum; else if (strcmp(name,"Outputdefinition1527")==0) return Outputdefinition1527Enum; @@ -3048,7 +3088,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1594")==0) return Outputdefinition1594Enum; else if (strcmp(name,"Outputdefinition1595")==0) return Outputdefinition1595Enum; else if (strcmp(name,"Outputdefinition1596")==0) return Outputdefinition1596Enum; - else if (strcmp(name,"Outputdefinition1597")==0) return Outputdefinition1597Enum; + else stage=26; + } + if(stage==26){ + if (strcmp(name,"Outputdefinition1597")==0) return Outputdefinition1597Enum; else if (strcmp(name,"Outputdefinition1598")==0) return Outputdefinition1598Enum; else if (strcmp(name,"Outputdefinition1599")==0) return Outputdefinition1599Enum; else if (strcmp(name,"Outputdefinition1509")==0) return Outputdefinition1509Enum; @@ -3088,10 +3131,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1603")==0) return Outputdefinition1603Enum; else if (strcmp(name,"Outputdefinition1640")==0) return Outputdefinition1640Enum; else if (strcmp(name,"Outputdefinition1641")==0) return Outputdefinition1641Enum; - else stage=26; - } - if(stage==26){ - if (strcmp(name,"Outputdefinition1642")==0) return Outputdefinition1642Enum; + else if (strcmp(name,"Outputdefinition1642")==0) return Outputdefinition1642Enum; else if (strcmp(name,"Outputdefinition1643")==0) return Outputdefinition1643Enum; else if (strcmp(name,"Outputdefinition1644")==0) return Outputdefinition1644Enum; else if (strcmp(name,"Outputdefinition1645")==0) return Outputdefinition1645Enum; @@ -3171,7 +3211,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1721")==0) return Outputdefinition1721Enum; else if (strcmp(name,"Outputdefinition1722")==0) return Outputdefinition1722Enum; else if (strcmp(name,"Outputdefinition1723")==0) return Outputdefinition1723Enum; - else if (strcmp(name,"Outputdefinition1724")==0) return Outputdefinition1724Enum; + else stage=27; + } + if(stage==27){ + if (strcmp(name,"Outputdefinition1724")==0) return Outputdefinition1724Enum; else if (strcmp(name,"Outputdefinition1725")==0) return Outputdefinition1725Enum; else if (strcmp(name,"Outputdefinition1726")==0) return Outputdefinition1726Enum; else if (strcmp(name,"Outputdefinition1727")==0) return Outputdefinition1727Enum; @@ -3211,10 +3254,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1758")==0) return Outputdefinition1758Enum; else if (strcmp(name,"Outputdefinition1759")==0) return Outputdefinition1759Enum; else if (strcmp(name,"Outputdefinition1705")==0) return Outputdefinition1705Enum; - else stage=27; - } - if(stage==27){ - if (strcmp(name,"Outputdefinition1760")==0) return Outputdefinition1760Enum; + else if (strcmp(name,"Outputdefinition1760")==0) return Outputdefinition1760Enum; else if (strcmp(name,"Outputdefinition1761")==0) return Outputdefinition1761Enum; else if (strcmp(name,"Outputdefinition1762")==0) return Outputdefinition1762Enum; else if (strcmp(name,"Outputdefinition1763")==0) return Outputdefinition1763Enum; @@ -3294,7 +3334,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1803")==0) return Outputdefinition1803Enum; else if (strcmp(name,"Outputdefinition1840")==0) return Outputdefinition1840Enum; else if (strcmp(name,"Outputdefinition1841")==0) return Outputdefinition1841Enum; - else if (strcmp(name,"Outputdefinition1842")==0) return Outputdefinition1842Enum; + else stage=28; + } + if(stage==28){ + if (strcmp(name,"Outputdefinition1842")==0) return Outputdefinition1842Enum; else if (strcmp(name,"Outputdefinition1843")==0) return Outputdefinition1843Enum; else if (strcmp(name,"Outputdefinition1844")==0) return Outputdefinition1844Enum; else if (strcmp(name,"Outputdefinition1845")==0) return Outputdefinition1845Enum; @@ -3334,10 +3377,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1876")==0) return Outputdefinition1876Enum; else if (strcmp(name,"Outputdefinition1877")==0) return Outputdefinition1877Enum; else if (strcmp(name,"Outputdefinition1878")==0) return Outputdefinition1878Enum; - else stage=28; - } - if(stage==28){ - if (strcmp(name,"Outputdefinition1879")==0) return Outputdefinition1879Enum; + else if (strcmp(name,"Outputdefinition1879")==0) return Outputdefinition1879Enum; else if (strcmp(name,"Outputdefinition1807")==0) return Outputdefinition1807Enum; else if (strcmp(name,"Outputdefinition1880")==0) return Outputdefinition1880Enum; else if (strcmp(name,"Outputdefinition1881")==0) return Outputdefinition1881Enum; @@ -3417,7 +3457,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1958")==0) return Outputdefinition1958Enum; else if (strcmp(name,"Outputdefinition1959")==0) return Outputdefinition1959Enum; else if (strcmp(name,"Outputdefinition1905")==0) return Outputdefinition1905Enum; - else if (strcmp(name,"Outputdefinition1960")==0) return Outputdefinition1960Enum; + else stage=29; + } + if(stage==29){ + if (strcmp(name,"Outputdefinition1960")==0) return Outputdefinition1960Enum; else if (strcmp(name,"Outputdefinition1961")==0) return Outputdefinition1961Enum; else if (strcmp(name,"Outputdefinition1962")==0) return Outputdefinition1962Enum; else if (strcmp(name,"Outputdefinition1963")==0) return Outputdefinition1963Enum; @@ -3457,10 +3500,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Outputdefinition1994")==0) return Outputdefinition1994Enum; else if (strcmp(name,"Outputdefinition1995")==0) return Outputdefinition1995Enum; else if (strcmp(name,"Outputdefinition1996")==0) return Outputdefinition1996Enum; - else stage=29; - } - if(stage==29){ - if (strcmp(name,"Outputdefinition1997")==0) return Outputdefinition1997Enum; + else if (strcmp(name,"Outputdefinition1997")==0) return Outputdefinition1997Enum; else if (strcmp(name,"Outputdefinition1998")==0) return Outputdefinition1998Enum; else if (strcmp(name,"Outputdefinition1999")==0) return Outputdefinition1999Enum; else if (strcmp(name,"Outputdefinition1909")==0) return Outputdefinition1909Enum; @@ -3540,7 +3580,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"DataSet")==0) return DataSetEnum; else if (strcmp(name,"DataSetParam")==0) return DataSetParamEnum; else if (strcmp(name,"DatasetInput")==0) return DatasetInputEnum; - else if (strcmp(name,"DebrisAnalysis")==0) return DebrisAnalysisEnum; + else stage=30; + } + if(stage==30){ + if (strcmp(name,"DebrisAnalysis")==0) return DebrisAnalysisEnum; else if (strcmp(name,"DebrisSolution")==0) return DebrisSolutionEnum; else if (strcmp(name,"DefaultAnalysis")==0) return DefaultAnalysisEnum; else if (strcmp(name,"DefaultCalving")==0) return DefaultCalvingEnum; @@ -3562,6 +3605,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Element")==0) return ElementEnum; else if (strcmp(name,"ElementHook")==0) return ElementHookEnum; else if (strcmp(name,"ElementSId")==0) return ElementSIdEnum; + else if (strcmp(name,"EmulatorParam")==0) return EmulatorParamEnum; else if (strcmp(name,"EnthalpyAnalysis")==0) return EnthalpyAnalysisEnum; else if (strcmp(name,"EsaAnalysis")==0) return EsaAnalysisEnum; else if (strcmp(name,"EsaSolution")==0) return EsaSolutionEnum; @@ -3580,10 +3624,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"FloatingArea")==0) return FloatingAreaEnum; else if (strcmp(name,"FloatingAreaScaled")==0) return FloatingAreaScaledEnum; else if (strcmp(name,"FloatingMeltRate")==0) return FloatingMeltRateEnum; - else stage=30; - } - if(stage==30){ - if (strcmp(name,"Free")==0) return FreeEnum; + else if (strcmp(name,"Free")==0) return FreeEnum; else if (strcmp(name,"FreeSurfaceBaseAnalysis")==0) return FreeSurfaceBaseAnalysisEnum; else if (strcmp(name,"FreeSurfaceTopAnalysis")==0) return FreeSurfaceTopAnalysisEnum; else if (strcmp(name,"FrontalForcingsDefault")==0) return FrontalForcingsDefaultEnum; @@ -3662,7 +3703,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"LevelsetfunctionPicard")==0) return LevelsetfunctionPicardEnum; else if (strcmp(name,"LinearFloatingMeltRate")==0) return LinearFloatingMeltRateEnum; else if (strcmp(name,"LinearFloatingMeltRatearma")==0) return LinearFloatingMeltRatearmaEnum; - else if (strcmp(name,"LliboutryDuval")==0) return LliboutryDuvalEnum; + else stage=31; + } + if(stage==31){ + if (strcmp(name,"LliboutryDuval")==0) return LliboutryDuvalEnum; else if (strcmp(name,"Loads")==0) return LoadsEnum; else if (strcmp(name,"LoveAnalysis")==0) return LoveAnalysisEnum; else if (strcmp(name,"LoveHf")==0) return LoveHfEnum; @@ -3703,10 +3747,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Matlitho")==0) return MatlithoEnum; else if (strcmp(name,"Mathydro")==0) return MathydroEnum; else if (strcmp(name,"MatrixParam")==0) return MatrixParamEnum; - else stage=31; - } - if(stage==31){ - if (strcmp(name,"MaxAbsVx")==0) return MaxAbsVxEnum; + else if (strcmp(name,"MaxAbsVx")==0) return MaxAbsVxEnum; else if (strcmp(name,"MaxAbsVy")==0) return MaxAbsVyEnum; else if (strcmp(name,"MaxAbsVz")==0) return MaxAbsVzEnum; else if (strcmp(name,"MaxDivergence")==0) return MaxDivergenceEnum; @@ -3785,7 +3826,10 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SMBd18opdd")==0) return SMBd18opddEnum; else if (strcmp(name,"SMBforcing")==0) return SMBforcingEnum; else if (strcmp(name,"SMBgcm")==0) return SMBgcmEnum; - else if (strcmp(name,"SMBgemb")==0) return SMBgembEnum; + else stage=32; + } + if(stage==32){ + if (strcmp(name,"SMBgemb")==0) return SMBgembEnum; else if (strcmp(name,"SMBgradients")==0) return SMBgradientsEnum; else if (strcmp(name,"SMBgradientscomponents")==0) return SMBgradientscomponentsEnum; else if (strcmp(name,"SMBgradientsela")==0) return SMBgradientselaEnum; @@ -3796,6 +3840,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"SMBpddGCM")==0) return SMBpddGCMEnum; else if (strcmp(name,"SMBpddFast")==0) return SMBpddFastEnum; else if (strcmp(name,"SMBsemic")==0) return SMBsemicEnum; + else if (strcmp(name,"SMBmaria")==0) return SMBmariaEnum; else if (strcmp(name,"SSAApproximation")==0) return SSAApproximationEnum; else if (strcmp(name,"SSAFSApproximation")==0) return SSAFSApproximationEnum; else if (strcmp(name,"SSAHOApproximation")==0) return SSAHOApproximationEnum; @@ -3826,10 +3871,7 @@ int StringToEnumx(const char* name,bool notfounderror){ else if (strcmp(name,"Sset")==0) return SsetEnum; else if (strcmp(name,"StatisticsSolution")==0) return StatisticsSolutionEnum; else if (strcmp(name,"SteadystateSolution")==0) return SteadystateSolutionEnum; - else stage=32; - } - if(stage==32){ - if (strcmp(name,"StressIntensityFactor")==0) return StressIntensityFactorEnum; + else if (strcmp(name,"StressIntensityFactor")==0) return StressIntensityFactorEnum; else if (strcmp(name,"StressbalanceAnalysis")==0) return StressbalanceAnalysisEnum; else if (strcmp(name,"StressbalanceConvergenceNumSteps")==0) return StressbalanceConvergenceNumStepsEnum; else if (strcmp(name,"StressbalanceSIAAnalysis")==0) return StressbalanceSIAAnalysisEnum; diff --git a/src/c/shared/Enum/issmenums.jl b/src/c/shared/Enum/issmenums.jl index ac1734b4e..e853df6ba 100644 --- a/src/c/shared/Enum/issmenums.jl +++ b/src/c/shared/Enum/issmenums.jl @@ -74,6 +74,8 @@ BasalforcingsIsmip6IsLocalEnum BasalforcingsIsmip6NumBasinsEnum BasalforcingsIsmip6TfDepthsEnum + BasalforcingsIsmip7DeltaTEnum + BasalforcingsIsmip7IsLocalEnum BasalforcingsIsmip7TfDepthsEnum BasalforcingsIsmip7NumBasinsEnum BasalforcingsIsmip7GammaEnum @@ -340,6 +342,7 @@ InversionNumCostFunctionsEnum InversionStepThresholdEnum InversionStopFlagEnum + InversionTauCEnum InversionTypeEnum IoConstantEnum IvinsEnum @@ -477,6 +480,9 @@ SealevelchangeViscousNumStepsEnum SealevelchangeViscousTimesEnum SealevelchangeViscousIndexEnum + SealevelchangeViscousSamplingEnum + SealevelchangeViscousSamplingLengthEnum + SealevelchangeViscousSamplingIndexEnum SealevelchangeViscousPolarMotionEnum SealevelchangeRunCountEnum SealevelchangeTransitionsEnum @@ -605,6 +611,8 @@ SmbIsfirnwarmingEnum SmbIsgraingrowthEnum SmbIsmappedforcingEnum + SmbIsmappingusingneighborsEnum + SmbIsmappingneighborxyEnum SmbIsmeltEnum SmbIsmungsmEnum SmbIsprecipforcingremappedEnum @@ -618,6 +626,8 @@ SmbLapsedlwrfValueEnum SmbLapseRatesEnum SmbLapseTaValueEnum + SmbLatMappedforcingEnum + SmbLonMappedforcingEnum SmbLWgradEnum SmbMappedforcingelevationEnum SmbNumBasinsEnum @@ -657,6 +667,7 @@ SmbT0wetEnum SmbTaParamEnum SmbTcIdxEnum + SmbTeDefaultEnum SmbTeThreshEnum SmbTdiffEnum SmbThermoDeltaTScalingEnum @@ -668,6 +679,8 @@ SmbVmeanParamEnum SmbVzParamEnum SmbWindspeedgradEnum + SmbXMappedforcingEnum + SmbYMappedforcingEnum SmoothThicknessMultiplierEnum SolutionTypeEnum SteadystateMaxiterEnum @@ -680,6 +693,10 @@ StressbalanceFSreconditioningEnum StressbalanceIsHydrologyLayerEnum StressbalanceIsnewtonEnum + StressbalanceIsemulatorEnum + EdgesNumberEnum + EdgesSrcEnum + EdgesDstEnum StressbalanceMaxiterEnum StressbalanceNumRequestedOutputsEnum StressbalancePenaltyFactorEnum @@ -744,6 +761,9 @@ ZzeEnum AreaeEnum WorldCommEnum + FrictionEmulatorEnum + SmbEmulatorEnum + StressbalanceEmulatorEnum ParametersENDEnum InputsSTARTEnum AccumulatedDeltaBottomPressureEnum @@ -787,6 +807,7 @@ BasalforcingsIsmip6TfEnum BasalforcingsIsmip6TfShelfEnum BasalforcingsIsmip6MeltAnomalyEnum + BasalforcingsIsmip7BasinIdEnum BasalforcingsIsmip7TfEnum BasalforcingsIsmip7TfShelfEnum BasalforcingsIsmip7SalinityEnum @@ -1184,7 +1205,10 @@ SmbHSnowInitEnum SmbHrefEnum SmbIsInitializedEnum + SmbLatEnum + SmbLonEnum SmbMAddEnum + SmbMappedforcingneighborsEnum SmbMappedforcingpointEnum SmbMappedforcingprecipscalingEnum SmbMassBalanceEnum @@ -1193,12 +1217,16 @@ SmbMassBalanceSubstepEnum SmbMassBalanceTransientEnum SmbMaskEnum + SmbMaxXEnum + SmbMaxYEnum SmbMeanLHFEnum SmbMeanSHFEnum SmbMeanULWEnum SmbMeanTemperatureEnum SmbMeltEnum SmbMeltSubstepEnum + SmbMinXEnum + SmbMinYEnum SmbMonthlytemperaturesEnum SmbMonthlydsradiationEnum SmbMonthlydlradiationEnum @@ -1215,6 +1243,7 @@ SmbPrecipitationEnum SmbPrecipitationSubstepEnum SmbPrecipitationsAnomalyEnum + SmbQinterpEnum SmbDsradiationAnomalyEnum SmbDlradiationAnomalyEnum SmbWindspeedAnomalyEnum @@ -1271,6 +1300,17 @@ SmbZMinEnum SmbZTopEnum SmbZYEnum + MariaSmbEnum + MariaElevEnum + MariaAlEnum + MariaStEnum + MariaTtEnum + MariaSwdEnum + MariaLwdEnum + MariaSwuEnum + MariaLwuEnum + MariaShfEnum + MariaLhfEnum SolidearthExternalDisplacementEastRateEnum SolidearthExternalDisplacementNorthRateEnum SolidearthExternalDisplacementUpRateEnum @@ -3465,6 +3505,7 @@ ElementEnum ElementHookEnum ElementSIdEnum + EmulatorParamEnum EnthalpyAnalysisEnum EsaAnalysisEnum EsaSolutionEnum @@ -3693,6 +3734,7 @@ SMBpddGCMEnum SMBpddFastEnum SMBsemicEnum + SMBmariaEnum SSAApproximationEnum SSAFSApproximationEnum SSAHOApproximationEnum @@ -3868,6 +3910,8 @@ function EnumToString(enum::IssmEnum) if(enum==BasalforcingsIsmip6IsLocalEnum) return "BasalforcingsIsmip6IsLocal" end if(enum==BasalforcingsIsmip6NumBasinsEnum) return "BasalforcingsIsmip6NumBasins" end if(enum==BasalforcingsIsmip6TfDepthsEnum) return "BasalforcingsIsmip6TfDepths" end + if(enum==BasalforcingsIsmip7DeltaTEnum) return "BasalforcingsIsmip7DeltaT" end + if(enum==BasalforcingsIsmip7IsLocalEnum) return "BasalforcingsIsmip7IsLocal" end if(enum==BasalforcingsIsmip7TfDepthsEnum) return "BasalforcingsIsmip7TfDepths" end if(enum==BasalforcingsIsmip7NumBasinsEnum) return "BasalforcingsIsmip7NumBasins" end if(enum==BasalforcingsIsmip7GammaEnum) return "BasalforcingsIsmip7Gamma" end @@ -4134,6 +4178,7 @@ function EnumToString(enum::IssmEnum) if(enum==InversionNumCostFunctionsEnum) return "InversionNumCostFunctions" end if(enum==InversionStepThresholdEnum) return "InversionStepThreshold" end if(enum==InversionStopFlagEnum) return "InversionStopFlag" end + if(enum==InversionTauCEnum) return "InversionTauC" end if(enum==InversionTypeEnum) return "InversionType" end if(enum==IoConstantEnum) return "IoConstant" end if(enum==IvinsEnum) return "Ivins" end @@ -4271,6 +4316,9 @@ function EnumToString(enum::IssmEnum) if(enum==SealevelchangeViscousNumStepsEnum) return "SealevelchangeViscousNumSteps" end if(enum==SealevelchangeViscousTimesEnum) return "SealevelchangeViscousTimes" end if(enum==SealevelchangeViscousIndexEnum) return "SealevelchangeViscousIndex" end + if(enum==SealevelchangeViscousSamplingEnum) return "SealevelchangeViscousSampling" end + if(enum==SealevelchangeViscousSamplingLengthEnum) return "SealevelchangeViscousSamplingLength" end + if(enum==SealevelchangeViscousSamplingIndexEnum) return "SealevelchangeViscousSamplingIndex" end if(enum==SealevelchangeViscousPolarMotionEnum) return "SealevelchangeViscousPolarMotion" end if(enum==SealevelchangeRunCountEnum) return "SealevelchangeRunCount" end if(enum==SealevelchangeTransitionsEnum) return "SealevelchangeTransitions" end @@ -4399,6 +4447,8 @@ function EnumToString(enum::IssmEnum) if(enum==SmbIsfirnwarmingEnum) return "SmbIsfirnwarming" end if(enum==SmbIsgraingrowthEnum) return "SmbIsgraingrowth" end if(enum==SmbIsmappedforcingEnum) return "SmbIsmappedforcing" end + if(enum==SmbIsmappingusingneighborsEnum) return "SmbIsmappingusingneighbors" end + if(enum==SmbIsmappingneighborxyEnum) return "SmbIsmappingneighborxy" end if(enum==SmbIsmeltEnum) return "SmbIsmelt" end if(enum==SmbIsmungsmEnum) return "SmbIsmungsm" end if(enum==SmbIsprecipforcingremappedEnum) return "SmbIsprecipforcingremapped" end @@ -4412,6 +4462,8 @@ function EnumToString(enum::IssmEnum) if(enum==SmbLapsedlwrfValueEnum) return "SmbLapsedlwrfValue" end if(enum==SmbLapseRatesEnum) return "SmbLapseRates" end if(enum==SmbLapseTaValueEnum) return "SmbLapseTaValue" end + if(enum==SmbLatMappedforcingEnum) return "SmbLatMappedforcing" end + if(enum==SmbLonMappedforcingEnum) return "SmbLonMappedforcing" end if(enum==SmbLWgradEnum) return "SmbLWgrad" end if(enum==SmbMappedforcingelevationEnum) return "SmbMappedforcingelevation" end if(enum==SmbNumBasinsEnum) return "SmbNumBasins" end @@ -4451,6 +4503,7 @@ function EnumToString(enum::IssmEnum) if(enum==SmbT0wetEnum) return "SmbT0wet" end if(enum==SmbTaParamEnum) return "SmbTaParam" end if(enum==SmbTcIdxEnum) return "SmbTcIdx" end + if(enum==SmbTeDefaultEnum) return "SmbTeDefault" end if(enum==SmbTeThreshEnum) return "SmbTeThresh" end if(enum==SmbTdiffEnum) return "SmbTdiff" end if(enum==SmbThermoDeltaTScalingEnum) return "SmbThermoDeltaTScaling" end @@ -4462,6 +4515,8 @@ function EnumToString(enum::IssmEnum) if(enum==SmbVmeanParamEnum) return "SmbVmeanParam" end if(enum==SmbVzParamEnum) return "SmbVzParam" end if(enum==SmbWindspeedgradEnum) return "SmbWindspeedgrad" end + if(enum==SmbXMappedforcingEnum) return "SmbXMappedforcing" end + if(enum==SmbYMappedforcingEnum) return "SmbYMappedforcing" end if(enum==SmoothThicknessMultiplierEnum) return "SmoothThicknessMultiplier" end if(enum==SolutionTypeEnum) return "SolutionType" end if(enum==SteadystateMaxiterEnum) return "SteadystateMaxiter" end @@ -4474,6 +4529,10 @@ function EnumToString(enum::IssmEnum) if(enum==StressbalanceFSreconditioningEnum) return "StressbalanceFSreconditioning" end if(enum==StressbalanceIsHydrologyLayerEnum) return "StressbalanceIsHydrologyLayer" end if(enum==StressbalanceIsnewtonEnum) return "StressbalanceIsnewton" end + if(enum==StressbalanceIsemulatorEnum) return "StressbalanceIsemulator" end + if(enum==EdgesNumberEnum) return "EdgesNumber" end + if(enum==EdgesSrcEnum) return "EdgesSrc" end + if(enum==EdgesDstEnum) return "EdgesDst" end if(enum==StressbalanceMaxiterEnum) return "StressbalanceMaxiter" end if(enum==StressbalanceNumRequestedOutputsEnum) return "StressbalanceNumRequestedOutputs" end if(enum==StressbalancePenaltyFactorEnum) return "StressbalancePenaltyFactor" end @@ -4538,6 +4597,9 @@ function EnumToString(enum::IssmEnum) if(enum==ZzeEnum) return "Zze" end if(enum==AreaeEnum) return "Areae" end if(enum==WorldCommEnum) return "WorldComm" end + if(enum==FrictionEmulatorEnum) return "FrictionEmulator" end + if(enum==SmbEmulatorEnum) return "SmbEmulator" end + if(enum==StressbalanceEmulatorEnum) return "StressbalanceEmulator" end if(enum==ParametersENDEnum) return "ParametersEND" end if(enum==InputsSTARTEnum) return "InputsSTART" end if(enum==AccumulatedDeltaBottomPressureEnum) return "AccumulatedDeltaBottomPressure" end @@ -4581,6 +4643,7 @@ function EnumToString(enum::IssmEnum) if(enum==BasalforcingsIsmip6TfEnum) return "BasalforcingsIsmip6Tf" end if(enum==BasalforcingsIsmip6TfShelfEnum) return "BasalforcingsIsmip6TfShelf" end if(enum==BasalforcingsIsmip6MeltAnomalyEnum) return "BasalforcingsIsmip6MeltAnomaly" end + if(enum==BasalforcingsIsmip7BasinIdEnum) return "BasalforcingsIsmip7BasinId" end if(enum==BasalforcingsIsmip7TfEnum) return "BasalforcingsIsmip7Tf" end if(enum==BasalforcingsIsmip7TfShelfEnum) return "BasalforcingsIsmip7TfShelf" end if(enum==BasalforcingsIsmip7SalinityEnum) return "BasalforcingsIsmip7Salinity" end @@ -4978,7 +5041,10 @@ function EnumToString(enum::IssmEnum) if(enum==SmbHSnowInitEnum) return "SmbHSnowInit" end if(enum==SmbHrefEnum) return "SmbHref" end if(enum==SmbIsInitializedEnum) return "SmbIsInitialized" end + if(enum==SmbLatEnum) return "SmbLat" end + if(enum==SmbLonEnum) return "SmbLon" end if(enum==SmbMAddEnum) return "SmbMAdd" end + if(enum==SmbMappedforcingneighborsEnum) return "SmbMappedforcingneighbors" end if(enum==SmbMappedforcingpointEnum) return "SmbMappedforcingpoint" end if(enum==SmbMappedforcingprecipscalingEnum) return "SmbMappedforcingprecipscaling" end if(enum==SmbMassBalanceEnum) return "SmbMassBalance" end @@ -4987,12 +5053,16 @@ function EnumToString(enum::IssmEnum) if(enum==SmbMassBalanceSubstepEnum) return "SmbMassBalanceSubstep" end if(enum==SmbMassBalanceTransientEnum) return "SmbMassBalanceTransient" end if(enum==SmbMaskEnum) return "SmbMask" end + if(enum==SmbMaxXEnum) return "SmbMaxX" end + if(enum==SmbMaxYEnum) return "SmbMaxY" end if(enum==SmbMeanLHFEnum) return "SmbMeanLHF" end if(enum==SmbMeanSHFEnum) return "SmbMeanSHF" end if(enum==SmbMeanULWEnum) return "SmbMeanULW" end if(enum==SmbMeanTemperatureEnum) return "SmbMeanTemperature" end if(enum==SmbMeltEnum) return "SmbMelt" end if(enum==SmbMeltSubstepEnum) return "SmbMeltSubstep" end + if(enum==SmbMinXEnum) return "SmbMinX" end + if(enum==SmbMinYEnum) return "SmbMinY" end if(enum==SmbMonthlytemperaturesEnum) return "SmbMonthlytemperatures" end if(enum==SmbMonthlydsradiationEnum) return "SmbMonthlydsradiation" end if(enum==SmbMonthlydlradiationEnum) return "SmbMonthlydlradiation" end @@ -5009,6 +5079,7 @@ function EnumToString(enum::IssmEnum) if(enum==SmbPrecipitationEnum) return "SmbPrecipitation" end if(enum==SmbPrecipitationSubstepEnum) return "SmbPrecipitationSubstep" end if(enum==SmbPrecipitationsAnomalyEnum) return "SmbPrecipitationsAnomaly" end + if(enum==SmbQinterpEnum) return "SmbQinterp" end if(enum==SmbDsradiationAnomalyEnum) return "SmbDsradiationAnomaly" end if(enum==SmbDlradiationAnomalyEnum) return "SmbDlradiationAnomaly" end if(enum==SmbWindspeedAnomalyEnum) return "SmbWindspeedAnomaly" end @@ -5065,6 +5136,17 @@ function EnumToString(enum::IssmEnum) if(enum==SmbZMinEnum) return "SmbZMin" end if(enum==SmbZTopEnum) return "SmbZTop" end if(enum==SmbZYEnum) return "SmbZY" end + if(enum==MariaSmbEnum) return "MariaSmb" end + if(enum==MariaElevEnum) return "MariaElev" end + if(enum==MariaAlEnum) return "MariaAl" end + if(enum==MariaStEnum) return "MariaSt" end + if(enum==MariaTtEnum) return "MariaTt" end + if(enum==MariaSwdEnum) return "MariaSwd" end + if(enum==MariaLwdEnum) return "MariaLwd" end + if(enum==MariaSwuEnum) return "MariaSwu" end + if(enum==MariaLwuEnum) return "MariaLwu" end + if(enum==MariaShfEnum) return "MariaShf" end + if(enum==MariaLhfEnum) return "MariaLhf" end if(enum==SolidearthExternalDisplacementEastRateEnum) return "SolidearthExternalDisplacementEastRate" end if(enum==SolidearthExternalDisplacementNorthRateEnum) return "SolidearthExternalDisplacementNorthRate" end if(enum==SolidearthExternalDisplacementUpRateEnum) return "SolidearthExternalDisplacementUpRate" end @@ -7259,6 +7341,7 @@ function EnumToString(enum::IssmEnum) if(enum==ElementEnum) return "Element" end if(enum==ElementHookEnum) return "ElementHook" end if(enum==ElementSIdEnum) return "ElementSId" end + if(enum==EmulatorParamEnum) return "EmulatorParam" end if(enum==EnthalpyAnalysisEnum) return "EnthalpyAnalysis" end if(enum==EsaAnalysisEnum) return "EsaAnalysis" end if(enum==EsaSolutionEnum) return "EsaSolution" end @@ -7487,6 +7570,7 @@ function EnumToString(enum::IssmEnum) if(enum==SMBpddGCMEnum) return "SMBpddGCM" end if(enum==SMBpddFastEnum) return "SMBpddFast" end if(enum==SMBsemicEnum) return "SMBsemic" end + if(enum==SMBmariaEnum) return "SMBmaria" end if(enum==SSAApproximationEnum) return "SSAApproximation" end if(enum==SSAFSApproximationEnum) return "SSAFSApproximation" end if(enum==SSAHOApproximationEnum) return "SSAHOApproximation" end @@ -7662,6 +7746,8 @@ function StringToEnum(name::String) if(name=="BasalforcingsIsmip6IsLocal") return BasalforcingsIsmip6IsLocalEnum end if(name=="BasalforcingsIsmip6NumBasins") return BasalforcingsIsmip6NumBasinsEnum end if(name=="BasalforcingsIsmip6TfDepths") return BasalforcingsIsmip6TfDepthsEnum end + if(name=="BasalforcingsIsmip7DeltaT") return BasalforcingsIsmip7DeltaTEnum end + if(name=="BasalforcingsIsmip7IsLocal") return BasalforcingsIsmip7IsLocalEnum end if(name=="BasalforcingsIsmip7TfDepths") return BasalforcingsIsmip7TfDepthsEnum end if(name=="BasalforcingsIsmip7NumBasins") return BasalforcingsIsmip7NumBasinsEnum end if(name=="BasalforcingsIsmip7Gamma") return BasalforcingsIsmip7GammaEnum end @@ -7928,6 +8014,7 @@ function StringToEnum(name::String) if(name=="InversionNumCostFunctions") return InversionNumCostFunctionsEnum end if(name=="InversionStepThreshold") return InversionStepThresholdEnum end if(name=="InversionStopFlag") return InversionStopFlagEnum end + if(name=="InversionTauC") return InversionTauCEnum end if(name=="InversionType") return InversionTypeEnum end if(name=="IoConstant") return IoConstantEnum end if(name=="Ivins") return IvinsEnum end @@ -8065,6 +8152,9 @@ function StringToEnum(name::String) if(name=="SealevelchangeViscousNumSteps") return SealevelchangeViscousNumStepsEnum end if(name=="SealevelchangeViscousTimes") return SealevelchangeViscousTimesEnum end if(name=="SealevelchangeViscousIndex") return SealevelchangeViscousIndexEnum end + if(name=="SealevelchangeViscousSampling") return SealevelchangeViscousSamplingEnum end + if(name=="SealevelchangeViscousSamplingLength") return SealevelchangeViscousSamplingLengthEnum end + if(name=="SealevelchangeViscousSamplingIndex") return SealevelchangeViscousSamplingIndexEnum end if(name=="SealevelchangeViscousPolarMotion") return SealevelchangeViscousPolarMotionEnum end if(name=="SealevelchangeRunCount") return SealevelchangeRunCountEnum end if(name=="SealevelchangeTransitions") return SealevelchangeTransitionsEnum end @@ -8193,6 +8283,8 @@ function StringToEnum(name::String) if(name=="SmbIsfirnwarming") return SmbIsfirnwarmingEnum end if(name=="SmbIsgraingrowth") return SmbIsgraingrowthEnum end if(name=="SmbIsmappedforcing") return SmbIsmappedforcingEnum end + if(name=="SmbIsmappingusingneighbors") return SmbIsmappingusingneighborsEnum end + if(name=="SmbIsmappingneighborxy") return SmbIsmappingneighborxyEnum end if(name=="SmbIsmelt") return SmbIsmeltEnum end if(name=="SmbIsmungsm") return SmbIsmungsmEnum end if(name=="SmbIsprecipforcingremapped") return SmbIsprecipforcingremappedEnum end @@ -8206,6 +8298,8 @@ function StringToEnum(name::String) if(name=="SmbLapsedlwrfValue") return SmbLapsedlwrfValueEnum end if(name=="SmbLapseRates") return SmbLapseRatesEnum end if(name=="SmbLapseTaValue") return SmbLapseTaValueEnum end + if(name=="SmbLatMappedforcing") return SmbLatMappedforcingEnum end + if(name=="SmbLonMappedforcing") return SmbLonMappedforcingEnum end if(name=="SmbLWgrad") return SmbLWgradEnum end if(name=="SmbMappedforcingelevation") return SmbMappedforcingelevationEnum end if(name=="SmbNumBasins") return SmbNumBasinsEnum end @@ -8245,6 +8339,7 @@ function StringToEnum(name::String) if(name=="SmbT0wet") return SmbT0wetEnum end if(name=="SmbTaParam") return SmbTaParamEnum end if(name=="SmbTcIdx") return SmbTcIdxEnum end + if(name=="SmbTeDefault") return SmbTeDefaultEnum end if(name=="SmbTeThresh") return SmbTeThreshEnum end if(name=="SmbTdiff") return SmbTdiffEnum end if(name=="SmbThermoDeltaTScaling") return SmbThermoDeltaTScalingEnum end @@ -8256,6 +8351,8 @@ function StringToEnum(name::String) if(name=="SmbVmeanParam") return SmbVmeanParamEnum end if(name=="SmbVzParam") return SmbVzParamEnum end if(name=="SmbWindspeedgrad") return SmbWindspeedgradEnum end + if(name=="SmbXMappedforcing") return SmbXMappedforcingEnum end + if(name=="SmbYMappedforcing") return SmbYMappedforcingEnum end if(name=="SmoothThicknessMultiplier") return SmoothThicknessMultiplierEnum end if(name=="SolutionType") return SolutionTypeEnum end if(name=="SteadystateMaxiter") return SteadystateMaxiterEnum end @@ -8268,6 +8365,10 @@ function StringToEnum(name::String) if(name=="StressbalanceFSreconditioning") return StressbalanceFSreconditioningEnum end if(name=="StressbalanceIsHydrologyLayer") return StressbalanceIsHydrologyLayerEnum end if(name=="StressbalanceIsnewton") return StressbalanceIsnewtonEnum end + if(name=="StressbalanceIsemulator") return StressbalanceIsemulatorEnum end + if(name=="EdgesNumber") return EdgesNumberEnum end + if(name=="EdgesSrc") return EdgesSrcEnum end + if(name=="EdgesDst") return EdgesDstEnum end if(name=="StressbalanceMaxiter") return StressbalanceMaxiterEnum end if(name=="StressbalanceNumRequestedOutputs") return StressbalanceNumRequestedOutputsEnum end if(name=="StressbalancePenaltyFactor") return StressbalancePenaltyFactorEnum end @@ -8332,6 +8433,9 @@ function StringToEnum(name::String) if(name=="Zze") return ZzeEnum end if(name=="Areae") return AreaeEnum end if(name=="WorldComm") return WorldCommEnum end + if(name=="FrictionEmulator") return FrictionEmulatorEnum end + if(name=="SmbEmulator") return SmbEmulatorEnum end + if(name=="StressbalanceEmulator") return StressbalanceEmulatorEnum end if(name=="ParametersEND") return ParametersENDEnum end if(name=="InputsSTART") return InputsSTARTEnum end if(name=="AccumulatedDeltaBottomPressure") return AccumulatedDeltaBottomPressureEnum end @@ -8375,6 +8479,7 @@ function StringToEnum(name::String) if(name=="BasalforcingsIsmip6Tf") return BasalforcingsIsmip6TfEnum end if(name=="BasalforcingsIsmip6TfShelf") return BasalforcingsIsmip6TfShelfEnum end if(name=="BasalforcingsIsmip6MeltAnomaly") return BasalforcingsIsmip6MeltAnomalyEnum end + if(name=="BasalforcingsIsmip7BasinId") return BasalforcingsIsmip7BasinIdEnum end if(name=="BasalforcingsIsmip7Tf") return BasalforcingsIsmip7TfEnum end if(name=="BasalforcingsIsmip7TfShelf") return BasalforcingsIsmip7TfShelfEnum end if(name=="BasalforcingsIsmip7Salinity") return BasalforcingsIsmip7SalinityEnum end @@ -8772,7 +8877,10 @@ function StringToEnum(name::String) if(name=="SmbHSnowInit") return SmbHSnowInitEnum end if(name=="SmbHref") return SmbHrefEnum end if(name=="SmbIsInitialized") return SmbIsInitializedEnum end + if(name=="SmbLat") return SmbLatEnum end + if(name=="SmbLon") return SmbLonEnum end if(name=="SmbMAdd") return SmbMAddEnum end + if(name=="SmbMappedforcingneighbors") return SmbMappedforcingneighborsEnum end if(name=="SmbMappedforcingpoint") return SmbMappedforcingpointEnum end if(name=="SmbMappedforcingprecipscaling") return SmbMappedforcingprecipscalingEnum end if(name=="SmbMassBalance") return SmbMassBalanceEnum end @@ -8781,12 +8889,16 @@ function StringToEnum(name::String) if(name=="SmbMassBalanceSubstep") return SmbMassBalanceSubstepEnum end if(name=="SmbMassBalanceTransient") return SmbMassBalanceTransientEnum end if(name=="SmbMask") return SmbMaskEnum end + if(name=="SmbMaxX") return SmbMaxXEnum end + if(name=="SmbMaxY") return SmbMaxYEnum end if(name=="SmbMeanLHF") return SmbMeanLHFEnum end if(name=="SmbMeanSHF") return SmbMeanSHFEnum end if(name=="SmbMeanULW") return SmbMeanULWEnum end if(name=="SmbMeanTemperature") return SmbMeanTemperatureEnum end if(name=="SmbMelt") return SmbMeltEnum end if(name=="SmbMeltSubstep") return SmbMeltSubstepEnum end + if(name=="SmbMinX") return SmbMinXEnum end + if(name=="SmbMinY") return SmbMinYEnum end if(name=="SmbMonthlytemperatures") return SmbMonthlytemperaturesEnum end if(name=="SmbMonthlydsradiation") return SmbMonthlydsradiationEnum end if(name=="SmbMonthlydlradiation") return SmbMonthlydlradiationEnum end @@ -8803,6 +8915,7 @@ function StringToEnum(name::String) if(name=="SmbPrecipitation") return SmbPrecipitationEnum end if(name=="SmbPrecipitationSubstep") return SmbPrecipitationSubstepEnum end if(name=="SmbPrecipitationsAnomaly") return SmbPrecipitationsAnomalyEnum end + if(name=="SmbQinterp") return SmbQinterpEnum end if(name=="SmbDsradiationAnomaly") return SmbDsradiationAnomalyEnum end if(name=="SmbDlradiationAnomaly") return SmbDlradiationAnomalyEnum end if(name=="SmbWindspeedAnomaly") return SmbWindspeedAnomalyEnum end @@ -8859,6 +8972,17 @@ function StringToEnum(name::String) if(name=="SmbZMin") return SmbZMinEnum end if(name=="SmbZTop") return SmbZTopEnum end if(name=="SmbZY") return SmbZYEnum end + if(name=="MariaSmb") return MariaSmbEnum end + if(name=="MariaElev") return MariaElevEnum end + if(name=="MariaAl") return MariaAlEnum end + if(name=="MariaSt") return MariaStEnum end + if(name=="MariaTt") return MariaTtEnum end + if(name=="MariaSwd") return MariaSwdEnum end + if(name=="MariaLwd") return MariaLwdEnum end + if(name=="MariaSwu") return MariaSwuEnum end + if(name=="MariaLwu") return MariaLwuEnum end + if(name=="MariaShf") return MariaShfEnum end + if(name=="MariaLhf") return MariaLhfEnum end if(name=="SolidearthExternalDisplacementEastRate") return SolidearthExternalDisplacementEastRateEnum end if(name=="SolidearthExternalDisplacementNorthRate") return SolidearthExternalDisplacementNorthRateEnum end if(name=="SolidearthExternalDisplacementUpRate") return SolidearthExternalDisplacementUpRateEnum end @@ -11053,6 +11177,7 @@ function StringToEnum(name::String) if(name=="Element") return ElementEnum end if(name=="ElementHook") return ElementHookEnum end if(name=="ElementSId") return ElementSIdEnum end + if(name=="EmulatorParam") return EmulatorParamEnum end if(name=="EnthalpyAnalysis") return EnthalpyAnalysisEnum end if(name=="EsaAnalysis") return EsaAnalysisEnum end if(name=="EsaSolution") return EsaSolutionEnum end @@ -11281,6 +11406,7 @@ function StringToEnum(name::String) if(name=="SMBpddGCM") return SMBpddGCMEnum end if(name=="SMBpddFast") return SMBpddFastEnum end if(name=="SMBsemic") return SMBsemicEnum end + if(name=="SMBmaria") return SMBmariaEnum end if(name=="SSAApproximation") return SSAApproximationEnum end if(name=="SSAFSApproximation") return SSAFSApproximationEnum end if(name=="SSAHOApproximation") return SSAHOApproximationEnum end diff --git a/src/c/shared/MemOps/MemOps.h b/src/c/shared/MemOps/MemOps.h index fd53a9cc5..088d9f587 100644 --- a/src/c/shared/MemOps/MemOps.h +++ b/src/c/shared/MemOps/MemOps.h @@ -91,7 +91,7 @@ template void xDelete(T**& aT_pp) {/*{{{*/ delete [](*aT_pp); delete [](aT_pp); #else - free((void*)*aT_pp) + free((void*)*aT_pp); free((void**)aT_pp); #endif } diff --git a/src/c/shared/Semic/Semic.cpp b/src/c/shared/Semic/Semic.cpp new file mode 100644 index 000000000..f903b9338 --- /dev/null +++ b/src/c/shared/Semic/Semic.cpp @@ -0,0 +1,731 @@ +/*!\file semic.cpp + * \brief C++ port of the SEMIC surface-physics module. + * + * Original Fortran source: + * externalpackages/semic/src/surface_physics.f90 (Mario Krapp) + * src/c/modules/SurfaceMassBalancex/run_semic.f90 + * src/c/modules/SurfaceMassBalancex/run_semic_transient.f90 + * + * Every subroutine, function, and literal constant is translated verbatim. + * Names follow the Fortran originals as closely as C++ allows. + */ + +#include +#include "./Semic.h" +#include "../io/Print/Print.h" +#include "../Exceptions/exceptions.h" +#include "../Numerics/recast.h" + +#include /* std::min, std::max */ +#include /* exp, log, sqrt, tanh, acos, fabs ... */ +#include /* machine epsilon*/ +#include /* memset */ +#include +#include +#include + +using namespace semic_const; + +/* ======================================================================== */ +/* Helpers – scalar physics (identical to Fortran ELEMENTAL routines) */ +/* ======================================================================== */ + +/* Saturation water-vapour pressure over water (Magnus formula) */ +static inline IssmDouble ew_sat(IssmDouble t) { + return 611.2 * std::exp(17.62 * (t - t0) / (243.12 + t - t0)); +} + +/* Saturation water-vapour pressure over ice */ +static inline IssmDouble ei_sat(IssmDouble t) { + return 611.2 * std::exp(22.46 * (t - t0) / (272.62 + t - t0)); +} + +/* ---------------------------------------------------------------------- */ +IssmDouble semic_sensible_heat_flux(IssmDouble ts, IssmDouble ta, IssmDouble wind, + IssmDouble rhoatm, IssmDouble csh, IssmDouble cap_air) +{ + return csh * cap_air * rhoatm * wind * (ts - ta); +} + +/* ---------------------------------------------------------------------- */ +void semic_latent_heat_flux(IssmDouble ts, IssmDouble wind, IssmDouble shum, IssmDouble sp, + IssmDouble rhoatm, int mask, IssmDouble clh, + IssmDouble& lhf, IssmDouble& subl, IssmDouble& evap) +{ + subl = 0.0; + evap = 0.0; + lhf = 0.0; + if (ts < t0) { + IssmDouble esat_sur = ei_sat(ts); + IssmDouble shum_sat = esat_sur * eps / (esat_sur * (eps - 1.0) + sp); + subl = clh * wind * rhoatm * (shum_sat - shum); + lhf = subl * cls; + } else { + IssmDouble esat_sur = ew_sat(ts); + IssmDouble shum_sat = esat_sur * eps / (esat_sur * (eps - 1.0) + sp); + evap = clh * wind * rhoatm * (shum_sat - shum); + lhf = evap * clv; + } +} + +/* ---------------------------------------------------------------------- */ +IssmDouble semic_longwave_upward(IssmDouble ts) { + return sigm * ts * ts * ts * ts; +} + +/* ---------------------------------------------------------------------- */ +void semic_diurnal_cycle(IssmDouble amp, IssmDouble tmean, IssmDouble& above, IssmDouble& below) +{ + IssmDouble tmp1 = 0.0, tmp2 = 0.0; + if (std::fabs(tmean / amp) < 1.0) { + tmp1 = std::acos(tmean / amp); + tmp2 = std::sqrt(1.0 - tmean * tmean / (amp * amp)); + } + if (tmean + amp < 0.0) { + below = tmean; + above = 0.0; + } else { + above = tmean; + below = 0.0; + if (std::fabs(tmean) < amp) { + above = (-tmean * tmp1 + amp * tmp2 + pi * tmean) / (pi - tmp1); + below = (tmean * tmp1 - amp * tmp2) / tmp1; + } + } +} + +/* ---------------------------------------------------------------------- */ +/* Albedo schemes */ +/* ---------------------------------------------------------------------- */ + +IssmDouble semic_albedo_slater(IssmDouble alb_snow, IssmDouble tsurf, IssmDouble tmin, + IssmDouble tmax, IssmDouble alb_smax, IssmDouble alb_smin) +{ + (void)alb_snow; /* the Fortran subroutine ignores the input alb_snow */ + (void)tmax; /* tmax is not actually used inside the formulation */ + IssmDouble tm = 0.0; + IssmDouble f = 1.0 / (t0 - tmin); + if (tsurf >= tmin && tsurf <= t0) + tm = f * (tsurf - tmin); + if (tsurf > t0) + tm = 1.0; + return alb_smax - (alb_smax - alb_smin) * tm * tm * tm; +} + +IssmDouble semic_albedo_denby(IssmDouble melt, IssmDouble alb_smax, + IssmDouble alb_smin, IssmDouble mcrit) +{ + return alb_smin + (alb_smax - alb_smin) * std::exp(-melt / mcrit); +} + +IssmDouble semic_albedo_isba(IssmDouble alb, IssmDouble sf, IssmDouble melt, IssmDouble tstic, + IssmDouble tau_a, IssmDouble tau_f, IssmDouble w_crit, + IssmDouble mcrit, IssmDouble alb_smin, IssmDouble alb_smax) +{ + /* dry case: linear decline */ + IssmDouble alb_dry = alb - tau_a * tstic / tstic; /* tau [1/day], step [s] */ + /* wet case: exponential decline */ + IssmDouble alb_wet = (alb - alb_smin) * std::exp(-tau_f * tstic / tstic) + alb_smin; + IssmDouble alb_new = sf * tstic / (w_crit / rhow) * (alb_smax - alb_smin); + + IssmDouble w_alb = 0.0; + if (melt > 0.0) w_alb = 1.0 - melt / mcrit; + w_alb = std::min(1.0, std::max(w_alb, 0.0)); + + IssmDouble alb_out = (1.0 - w_alb) * alb_dry + w_alb * alb_wet + alb_new; + return std::min(alb_smax, std::max(alb_out, alb_smin)); +} + +/* ======================================================================== */ +/* SemicParam constructor – default values from run_semic_transient.f90 */ +/* ======================================================================== */ +SemicParam::SemicParam() + : nx(1), n_ksub(3), + ceff(2.0e6), + albi(0.41), albl(0.07), + alb_smax(0.79), alb_smin(0.6), + hcrit(0.028), rcrit(0.85), + amp(3.0), + csh(2.0e-3), clh(5.0e-4), + tmin(-999.0), tmax(273.15), + tstic(86400.0), tsticsub(86400.0 / 3.0), + tau_a(0.008), tau_f(0.24), + w_crit(15.0), mcrit(6.0e-8), + afac(0.0), tmid(273.15), + alb_scheme(SEMIC_ALB_NONE) +{} + +/* ======================================================================== */ +/* SemicBnd constructor */ +/* ======================================================================== */ +SemicBnd::SemicBnd() + : t2m(false), tsurf(false), hsnow(false), alb(false), + melt(false), refr(false), smb(false), acc(false), + lhf(false), shf(false), subl(false), amp(false) +{} + +/* ======================================================================== */ +/* Memory management */ +/* ======================================================================== */ +void semic_alloc(SemicState& s, int npts) { + s.t2m .assign(npts, 0.0); + s.tsurf .assign(npts, 0.0); + s.hsnow .assign(npts, 0.0); + s.hice .assign(npts, 0.0); + s.alb .assign(npts, 0.0); + s.alb_snow .assign(npts, 0.0); + s.melt .assign(npts, 0.0); + s.melted_snow.assign(npts, 0.0); + s.melted_ice .assign(npts, 0.0); + s.refr .assign(npts, 0.0); + s.smb .assign(npts, 0.0); + s.acc .assign(npts, 0.0); + s.lhf .assign(npts, 0.0); + s.shf .assign(npts, 0.0); + s.lwu .assign(npts, 0.0); + s.subl .assign(npts, 0.0); + s.evap .assign(npts, 0.0); + s.smb_snow .assign(npts, 0.0); + s.smb_ice .assign(npts, 0.0); + s.runoff .assign(npts, 0.0); + s.qmr .assign(npts, 0.0); + s.qmr_res .assign(npts, 0.0); + s.amp .assign(npts, 0.0); + /* forcing */ + s.sf .assign(npts, 0.0); + s.rf .assign(npts, 0.0); + s.sp .assign(npts, 0.0); + s.lwd .assign(npts, 0.0); + s.swd .assign(npts, 0.0); + s.wind.assign(npts, 0.0); + s.rhoa.assign(npts, 0.0); + s.qq .assign(npts, 0.0); + s.mask.assign(npts, 0); +} + +void semic_dealloc(SemicState& s) { + /* std::vector destructor handles memory; just clear to release */ + s.t2m .clear(); s.tsurf .clear(); + s.hsnow .clear(); s.hice .clear(); + s.alb .clear(); s.alb_snow .clear(); + s.melt .clear(); s.melted_snow.clear(); + s.melted_ice .clear(); s.refr .clear(); + s.smb .clear(); s.acc .clear(); + s.lhf .clear(); s.shf .clear(); + s.lwu .clear(); s.subl .clear(); + s.evap .clear(); s.smb_snow .clear(); + s.smb_ice .clear(); s.runoff .clear(); + s.qmr .clear(); s.qmr_res .clear(); + s.amp .clear(); + s.sf .clear(); s.rf .clear(); s.sp .clear(); + s.lwd .clear(); s.swd .clear(); s.wind.clear(); + s.rhoa.clear(); s.qq .clear(); s.mask.clear(); +} + +/* ======================================================================== */ +/* Boundary helper */ +/* ======================================================================== */ +void semic_boundary_define(SemicBnd& bnd, const std::vector& names) +{ + bnd = SemicBnd(); /* reset all to false */ + for (const auto& nm : names) { + if (nm == "t2m" ) bnd.t2m = true; + else if (nm == "tsurf") bnd.tsurf = true; + else if (nm == "hsnow") bnd.hsnow = true; + else if (nm == "alb" ) bnd.alb = true; + else if (nm == "melt" ) bnd.melt = true; + else if (nm == "refr" ) bnd.refr = true; + else if (nm == "smb" ) bnd.smb = true; + else if (nm == "acc" ) bnd.acc = true; + else if (nm == "lhf" ) bnd.lhf = true; + else if (nm == "shf" ) bnd.shf = true; + else if (nm == "subl" ) bnd.subl = true; + else if (nm == "amp" ) bnd.amp = true; + /* unknown names are silently ignored (matches Fortran DEFAULT case) */ + } +} + +/* ======================================================================== */ +/* Energy balance */ +/* ======================================================================== */ +void semic_energy_balance(SemicState& now, const SemicParam& par, + const SemicBnd& bnd, int /*day*/, int /*year*/) +{ + const int nx = par.nx; + + /* 1. Sensible heat flux */ + if (!bnd.shf) { + for (int i = 0; i < nx; i++) + now.shf[i] = semic_sensible_heat_flux( + now.tsurf[i], now.t2m[i], now.wind[i], now.rhoa[i], + par.csh, cap); + } + + /* 2. Latent heat flux (sublimation / evaporation) */ + if (!bnd.lhf) { + for (int i = 0; i < nx; i++) { + now.subl[i] = 0.0; + now.evap[i] = 0.0; + now.lhf[i] = 0.0; + semic_latent_heat_flux( + now.tsurf[i], now.wind[i], now.qq[i], now.sp[i], + now.rhoa[i], now.mask[i], par.clh, + now.lhf[i], now.subl[i], now.evap[i]); + } + } + /* sublimation: kg/(s m2) -> m/s */ + for (int i = 0; i < nx; i++) + now.subl[i] /= rhow; + + /* 3. Upwelling longwave radiation */ + for (int i = 0; i < nx; i++) + now.lwu[i] = semic_longwave_upward(now.tsurf[i]); + + /* 4. Surface energy balance */ + std::vector qsb(nx); + for (int i = 0; i < nx; i++) + qsb[i] = (1.0 - now.alb[i]) * now.swd[i] + + now.lwd[i] - now.lwu[i] + - now.shf[i] - now.lhf[i] + - now.qmr_res[i]; + + /* 5. Update surface temperature */ + for (int i = 0; i < nx; i++) + now.qmr[i] = 0.0; + + if (!bnd.tsurf) { + for (int i = 0; i < nx; i++) { + now.tsurf[i] += qsb[i] * par.tsticsub / par.ceff; + /* store residual energy when tsurf > t0 over ice or snow */ + if ((now.mask[i] == 2 || now.hsnow[i] > 0.0) && now.tsurf[i] > t0) { + now.qmr[i] = (now.tsurf[i] - t0) * par.ceff / par.tsticsub; + now.tsurf[i] = t0; + } + } + } + + /* 6. Update 2-m air temperature over ice/snow */ + for (int i = 0; i < nx; i++) { + if (now.mask[i] == 2 || now.hsnow[i] > 0.0) + now.t2m[i] += (now.shf[i] + now.lhf[i]) * par.tsticsub / par.ceff; + } +} + +/* ======================================================================== */ +/* Mass balance */ +/* ======================================================================== */ +void semic_mass_balance(SemicState& now, const SemicParam& par, + const SemicBnd& bnd, int /*day*/, int /*year*/) +{ + const int nx = par.nx; + const IssmDouble epsil = std::numeric_limits::epsilon(); + + /* Temporary work arrays */ + std::vector qmelt(nx, 0.0), qcold(nx, 0.0); + std::vector above(nx, 0.0), below(nx, 0.0); + std::vector f_rz(nx, 0.0), f_alb(nx, 0.0); + std::vector refrozen_rain(nx, 0.0), refrozen_snow(nx, 0.0); + std::vector snow_to_ice(nx, 0.0); + + /* 1. Diurnal cycle amplitude */ + for (int i = 0; i < nx; i++) { + if (!bnd.amp) + now.amp[i] = par.amp; + semic_diurnal_cycle( + now.amp[i], + now.tsurf[i] - t0 + now.qmr[i] / par.ceff * par.tstic, + above[i], below[i]); + now.qmr[i] = 0.0; + } + + /* 2-3. Melt and cold energy where mask >= 1 */ + for (int i = 0; i < nx; i++) { + if (now.mask[i] >= 1) { + qmelt[i] = std::max(0.0, above[i] * par.ceff / par.tstic); + qcold[i] = std::max(0.0, std::fabs(below[i]) * par.ceff / par.tstic); + } + } + + /* 4. Potential melt and split into snow/ice melt */ + if (!bnd.melt) { + for (int i = 0; i < nx; i++) + now.melt[i] = qmelt[i] / (rhow * clm); + } + for (int i = 0; i < nx; i++) { + now.melted_snow[i] = std::min(now.melt[i], now.hsnow[i] / par.tstic); + now.melted_ice[i] = now.melt[i] - now.melted_snow[i]; + } + if (!bnd.melt) { + for (int i = 0; i < nx; i++) { + if (now.mask[i] == 2) { + now.melt[i] = now.melted_snow[i] + now.melted_ice[i]; + } else { + now.melt[i] = now.melted_snow[i]; + now.melted_ice[i] = 0.0; + } + } + } + + /* 5. Refreezing */ + if (!bnd.refr) { + for (int i = 0; i < nx; i++) { + f_rz[i] = par.rcrit; + IssmDouble pot_refr = qcold[i] / (rhow * clm); + refrozen_rain[i] = std::min(pot_refr, now.rf[i]); + refrozen_snow[i] = std::max(pot_refr - refrozen_rain[i], 0.0); + refrozen_snow[i] = std::min(refrozen_snow[i], now.melted_snow[i]); + refrozen_rain[i] = f_rz[i] * std::min(now.hsnow[i] / par.tstic, refrozen_rain[i]); + refrozen_snow[i] = f_rz[i] * std::min(now.hsnow[i] / par.tstic, refrozen_snow[i]); + now.refr[i] = refrozen_rain[i] + refrozen_snow[i]; + /* energy released during refreezing that is not used */ + now.qmr[i] -= (1.0 - f_rz[i]) * now.refr[i] * rhow * clm; + } + } + + /* 6. Runoff */ + for (int i = 0; i < nx; i++) + now.runoff[i] = now.melt[i] + now.rf[i] - refrozen_rain[i]; + + /* 7. Accumulation */ + if (!bnd.acc) { + for (int i = 0; i < nx; i++) + now.acc[i] = now.sf[i] - now.subl[i] + now.refr[i]; + } + + /* 8. SMB of snow */ + if (!bnd.smb) { + for (int i = 0; i < nx; i++) + now.smb_snow[i] = now.sf[i] - now.subl[i] + - now.melted_snow[i] + refrozen_snow[i]; + } + + /* 9. Update snow height */ + for (int i = 0; i < nx; i++) { + if (now.mask[i] == 0) + now.hsnow[i] = 0.0; + else + now.hsnow[i] = std::max(0.0, now.hsnow[i] + now.smb_snow[i] * par.tstic); + } + + /* 10. Cap snow height (excess becomes ice) */ + for (int i = 0; i < nx; i++) { + snow_to_ice[i] = std::max(0.0, now.hsnow[i] - hsmax); + now.hsnow[i] -= snow_to_ice[i]; + now.smb_ice[i] = snow_to_ice[i] / par.tstic + - now.melted_ice[i] + refrozen_rain[i]; + now.hice[i] += now.smb_ice[i] * par.tstic; + } + + /* 11. Total SMB */ + if (!bnd.smb) { + for (int i = 0; i < nx; i++) { + if (now.mask[i] == 2) + now.smb[i] = now.smb_snow[i] + now.smb_ice[i] + - snow_to_ice[i] / par.tstic; + else + now.smb[i] = now.smb_snow[i] + + std::max(0.0, now.smb_ice[i] - snow_to_ice[i] / par.tstic); + } + } + + /* 12. Snow albedo update */ + for (int i = 0; i < nx; i++) + f_alb[i] = 1.0 - std::exp(-now.hsnow[i] / (par.hcrit + epsil)); + + if (!bnd.alb) { + switch (par.alb_scheme) { + case SEMIC_ALB_SLATER: + for (int i = 0; i < nx; i++) + now.alb_snow[i] = semic_albedo_slater( + now.alb_snow[i], now.tsurf[i], + par.tmin, par.tmax, par.alb_smax, par.alb_smin); + break; + case SEMIC_ALB_DENBY: + for (int i = 0; i < nx; i++) + now.alb_snow[i] = semic_albedo_denby( + now.melt[i], par.alb_smax, par.alb_smin, par.mcrit); + break; + case SEMIC_ALB_ISBA: + for (int i = 0; i < nx; i++) + now.alb_snow[i] = semic_albedo_isba( + now.alb_snow[i], now.sf[i], now.melt[i], + par.tstic, par.tau_a, par.tau_f, par.w_crit, par.mcrit, + par.alb_smin, par.alb_smax); + break; + case SEMIC_ALB_NONE: + /* "none" (lowercase): fix alb_snow to the maximum value each step. + * Matches Fortran: trim(par%alb_scheme) .eq. "none" => alb_snow = alb_smax */ + for (int i = 0; i < nx; i++) + now.alb_snow[i] = par.alb_smax; + break; + case SEMIC_ALB_SKIP: + default: + /* "None" (capital, annual driver) or unrecognised: leave alb_snow + * unchanged. Matches Fortran run_semic where par%alb_scheme="None" + * falls through all branches without updating alb_snow. */ + break; + } + + /* Grid-averaged albedo by mask */ + for (int i = 0; i < nx; i++) { + if (now.mask[i] == 2) + now.alb[i] = par.albi + f_alb[i] * (now.alb_snow[i] - par.albi); + else if (now.mask[i] == 1) + now.alb[i] = par.albl + f_alb[i] * (now.alb_snow[i] - par.albl); + else + now.alb[i] = 0.06; + } + + /* "alex" scheme overrides both alb_snow and alb */ + if (par.alb_scheme == SEMIC_ALB_ALEX) { + for (int i = 0; i < nx; i++) { + now.alb_snow[i] = par.alb_smin + + (par.alb_smax - par.alb_smin) + * (0.5 * std::tanh(par.afac * (now.t2m[i] - par.tmid)) + 0.5); + now.alb[i] = now.alb_snow[i]; + } + } + } + + /* Store residual energy */ + for (int i = 0; i < nx; i++) { + if (now.mask[i] == 0) + now.qmr_res[i] = 0.0; + else + now.qmr_res[i] = now.qmr[i]; + } +} + +/* ======================================================================== */ +/* Combined surface energy-and-mass balance step */ +/* ======================================================================== */ +void semic_surface_step(SemicState& now, const SemicParam& par, + const SemicBnd& bnd, int day, int year) +{ + /* quasi-relaxation loop for energy balance (no hsnow update inside) */ + for (int ksub = 0; ksub < par.n_ksub; ksub++) + semic_energy_balance(now, par, bnd, day, year); + semic_mass_balance(now, par, bnd, day, year); +} + +/* ======================================================================== */ +/* RunSemic – annual driver (replaces Fortran run_semic_) */ +/* ======================================================================== */ +void RunSemic(const IssmDouble* sf_in, const IssmDouble* rf_in, + const IssmDouble* swd_in, const IssmDouble* lwd_in, + const IssmDouble* wind_in, const IssmDouble* sp_in, + const IssmDouble* rhoa_in, const IssmDouble* qq_in, + const IssmDouble* tt_in, + IssmDouble& tsurf_out, IssmDouble& smb_out, + IssmDouble& saccu_out, IssmDouble& smelt_out) +{ + const int nloop = 10; + const int nx = 1; + const int ntime = 365; + + SemicParam par; + par.nx = nx; + par.tstic = 86400.0; + par.ceff = 2.0e6; + par.csh = 2.0e-3; + par.clh = 5.0e-4; + par.alb_smax = 0.79; + par.alb_smin = 0.6; + par.albi = 0.41; + par.albl = 0.07; + par.tmin = -999.0; + par.tmax = 273.15; + par.hcrit = 0.028; + par.rcrit = 0.85; + par.amp = 3.0; + /* Fortran run_semic sets par%alb_scheme="None" (capital N). + * The Fortran mass_balance only matches lowercase "none", so alb_snow is + * never updated inside that routine — it keeps its initial value of 0.8. + * Use SEMIC_ALB_SKIP to replicate this fall-through behaviour. */ + par.alb_scheme= SEMIC_ALB_SKIP; + par.tau_a = 0.008; + par.tau_f = 0.24; + par.w_crit = 15.0; + par.mcrit = 6.0e-8; + par.n_ksub = 3; + par.tsticsub = par.tstic / par.n_ksub; + + SemicState now; + semic_alloc(now, nx); + + now.mask [0] = 2; + now.hsnow[0] = 1.0; + now.hice [0] = 0.0; + now.alb [0] = 0.8; + now.tsurf[0] = 260.0; + now.alb_snow[0] = 0.8; + now.qmr_res[0] = 0.0; + + SemicBnd bnd; /* all false */ + std::vector bnames; /* empty */ + semic_boundary_define(bnd, bnames); + + tsurf_out = 0.0; + smb_out = 0.0; + saccu_out = 0.0; + smelt_out = 0.0; + + for (int k = 0; k < nloop; k++) { + for (int i = 0; i < ntime; i++) { + now.sf [0] = sf_in [i]; + now.rf [0] = rf_in [i]; + now.sp [0] = sp_in [i]; + now.lwd [0] = lwd_in [i]; + now.swd [0] = swd_in [i]; + now.wind[0] = wind_in[i]; + now.rhoa[0] = rhoa_in[i]; + now.t2m [0] = tt_in [i]; + now.qq [0] = qq_in [i]; + + semic_surface_step(now, par, bnd, i + 1, 0); + + if (k == nloop - 1) { + tsurf_out += now.tsurf[0] / 365.0; + smb_out += now.smb[0] / 365.0; + saccu_out += now.alb[0] / 365.0; /* matches Fortran labelling */ + smelt_out += now.melt[0] / 365.0; + } + } + } + + semic_dealloc(now); +} + +/* ======================================================================== */ +/* RunSemicTransient – transient driver (replaces Fortran */ +/* run_semic_transient_) */ +/* ======================================================================== */ +void RunSemicTransient(int nx, int ntime, int nloop, + const IssmDouble* sf_in, const IssmDouble* rf_in, + const IssmDouble* swd_in, const IssmDouble* lwd_in, + const IssmDouble* wind_in, const IssmDouble* sp_in, + const IssmDouble* rhoa_in, const IssmDouble* qq_in, + const IssmDouble* tt_in, + const IssmDouble* tsurf_in, const IssmDouble* qmr_in, + IssmDouble tstic, + IssmDouble hcrit, IssmDouble rcrit, + const IssmDouble* mask, const IssmDouble* hice, + const IssmDouble* hsnow, + const IssmDouble* albedo, const IssmDouble* albedo_snow, + int alb_scheme_int, + IssmDouble alb_smax, IssmDouble alb_smin, + IssmDouble albi, IssmDouble albl, + const IssmDouble* Tamp, + IssmDouble tmin, IssmDouble tmax, IssmDouble tmid, + IssmDouble mcrit, IssmDouble wcrit, + IssmDouble tau_a, IssmDouble tau_f, IssmDouble afac, + bool verbose, + IssmDouble* tsurf_out, IssmDouble* smb_out, + IssmDouble* smbi_out, IssmDouble* smbs_out, + IssmDouble* saccu_out, IssmDouble* smelt_out, + IssmDouble* refr_out, IssmDouble* alb_out, + IssmDouble* alb_snow_out, + IssmDouble* hsnow_out, IssmDouble* hice_out, + IssmDouble* qmr_out, + IssmDouble* runoff_out, IssmDouble* subl_out) +{ + if (verbose) { + /* minimal printf – mirrors the Fortran debug prints */ + _printf0_("run_semic_transient: ntime=" << ntime << " nx=" << nx << "\n"); + } + + SemicParam par; + par.nx = nx; + par.tstic = tstic; + par.ceff = 2.0e6; + par.csh = 2.0e-3; + par.clh = 5.0e-4; + par.alb_smax = alb_smax; + par.alb_smin = alb_smin; + par.albi = albi; + par.albl = albl; + par.tmin = tmin; + par.tmax = tmax; + par.hcrit = hcrit; + par.rcrit = rcrit; + par.tau_a = tau_a; + par.tau_f = tau_f; + par.w_crit = wcrit; + par.mcrit = mcrit; + par.afac = afac; + par.tmid = tmid; + par.n_ksub = 3; + par.tsticsub = par.tstic / par.n_ksub; + /* Fortran: surface%par%amp = Tamp (scalar — reads first element only). + * bnd%amp is FALSE so semic_mass_balance uses par.amp, not now.amp[i]. */ + par.amp = Tamp[0]; + + switch (alb_scheme_int) { + case 0: par.alb_scheme = SEMIC_ALB_NONE; break; + case 1: par.alb_scheme = SEMIC_ALB_SLATER; break; + case 2: par.alb_scheme = SEMIC_ALB_DENBY; break; + case 3: par.alb_scheme = SEMIC_ALB_ISBA; break; + case 4: par.alb_scheme = SEMIC_ALB_ALEX; break; + default: + _error_("RunSemicTransient: unknown albedo scheme " << alb_scheme_int); + } + + SemicState now; + semic_alloc(now, nx); + + /* Initialise from inputs */ + for (int i = 0; i < nx; i++) { + now.mask [i] = reCast(mask[i]); + now.hsnow [i] = hsnow [i]; + now.hice [i] = hice [i]; + now.tsurf [i] = tsurf_in[i]; + now.alb [i] = albedo [i]; + now.alb_snow[i] = albedo_snow[i]; + now.qmr_res [i] = qmr_in [i]; + now.amp [i] = Tamp [i]; + } + + SemicBnd bnd; + std::vector bnames; + semic_boundary_define(bnd, bnames); + + for (int k = 0; k < nloop; k++) { + for (int i = 0; i < ntime; i++) { + for (int j = 0; j < nx; j++) { + now.sf [j] = sf_in [j]; + now.rf [j] = rf_in [j]; + now.sp [j] = sp_in [j]; + now.lwd [j] = lwd_in [j]; + now.swd [j] = swd_in [j]; + now.wind[j] = wind_in[j]; + now.rhoa[j] = rhoa_in[j]; + now.t2m [j] = tt_in [j]; + now.qq [j] = qq_in [j]; + now.qmr_res[j] = qmr_in[j]; + } + + semic_surface_step(now, par, bnd, i + 1, 0); + + if (k == nloop - 1) { + for (int j = 0; j < nx; j++) { + tsurf_out [j] = now.tsurf [j]; + smb_out [j] = now.smb [j]; + smbi_out [j] = now.smb_ice [j]; + smbs_out [j] = now.smb_snow[j]; + saccu_out [j] = now.acc [j]; + smelt_out [j] = now.melt [j]; + refr_out [j] = now.refr [j]; + alb_out [j] = now.alb [j]; + alb_snow_out[j]= now.alb_snow[j]; + hsnow_out [j] = now.hsnow [j]; + hice_out [j] = now.hice [j]; + qmr_out [j] = now.qmr_res [j]; + runoff_out [j] = now.runoff [j]; + subl_out [j] = now.subl [j]; + } + } + } + } + + semic_dealloc(now); +} diff --git a/src/c/shared/Semic/Semic.h b/src/c/shared/Semic/Semic.h new file mode 100644 index 000000000..4e8cfc3c3 --- /dev/null +++ b/src/c/shared/Semic/Semic.h @@ -0,0 +1,301 @@ +/*!\file semic.h + * \brief C++ port of the SEMIC (Simple Energy/Mass Balance Ice-sheet and + * Climate model) surface physics originally written in Fortran by + * Mario Krapp. All physics are translated verbatim from + * externalpackages/semic/src/surface_physics.f90 and the two driver + * subroutines run_semic.f90 / run_semic_transient.f90 that live in + * src/c/modules/SurfaceMassBalancex/. + * + * Public API + * ---------- + * SemicParam – physical / numerical parameters (≡ surface_param_class) + * SemicState – prognostic + diagnostic arrays (≡ surface_state_class) + * SemicBnd – boundary-override flags (≡ boundary_opt_class) + * + * semic_alloc / semic_dealloc – allocate / free state arrays + * semic_boundary_define – parse boundary list into SemicBnd flags + * semic_energy_balance – one sub-step of the energy balance + * semic_mass_balance – mass balance (called once per full step) + * semic_surface_step – combined energy+mass (≡ surface_energy_and_mass_balance) + * + * RunSemic – annual driver (replaces Fortran run_semic_) + * RunSemicTransient – transient driver (replaces Fortran run_semic_transient_) + */ + +#ifndef _SEMIC_H_ +#define _SEMIC_H_ + +#include +#include +#include "../Numerics/types.h" + +/* ======================================================================== */ +/* Albedo-scheme integer codes (matches run_semic_transient.f90 convention) */ +/* ======================================================================== */ +enum SemicAlbedoScheme { + SEMIC_ALB_SKIP = -1, /* internal: leave alb_snow unchanged (annual driver "None") */ + SEMIC_ALB_NONE = 0, /* "none" lowercase: set alb_snow = alb_smax each step */ + SEMIC_ALB_SLATER = 1, + SEMIC_ALB_DENBY = 2, + SEMIC_ALB_ISBA = 3, + SEMIC_ALB_ALEX = 4 +}; + +/* ======================================================================== */ +/* Physical constants (≡ module-level parameters in surface_physics.f90) */ +/* ======================================================================== */ +namespace semic_const { + static const IssmDouble pi = 3.141592653589793238462643; + static const IssmDouble t0 = 273.15; /* melting point [K] */ + static const IssmDouble sigm = 5.67e-8; /* Stefan-Boltzmann [W/(m2 K4)] */ + static const IssmDouble eps = 0.62197; /* molar-weight ratio water/dry air */ + static const IssmDouble cls = 2.83e6; /* latent heat sublimation [J/kg] */ + static const IssmDouble clm = 3.30e5; /* latent heat melting [J/kg] */ + static const IssmDouble clv = 2.5e6; /* latent heat condensation [J/kg] */ + static const IssmDouble cap = 1000.0; /* specific heat capacity air [J/(kg K)] */ + static const IssmDouble rhow = 1000.0; /* density of water [kg/m3] */ + static const IssmDouble hsmax= 5.0; /* maximum snow height [m] */ +} + +/* ======================================================================== */ +/* Parameter struct */ +/* ======================================================================== */ +struct SemicParam { + int nx; /* number of grid points */ + int n_ksub; /* number of sub-daily time steps */ + IssmDouble ceff; /* surface heat capacity snow/ice [J/(K m2)] */ + IssmDouble albi; /* bare-ice albedo */ + IssmDouble albl; /* bare-land albedo */ + IssmDouble alb_smax; /* maximum (fresh) snow albedo */ + IssmDouble alb_smin; /* minimum (old/wet) snow albedo */ + IssmDouble hcrit; /* critical snow height for 50 % snow cover [m] */ + IssmDouble rcrit; /* critical snow height for 50 % refreezing [m] */ + IssmDouble amp; /* diurnal cycle amplitude [K] */ + IssmDouble csh; /* sensible heat exchange coefficient */ + IssmDouble clh; /* latent heat exchange coefficient */ + IssmDouble tmin; /* min temperature for Slater albedo decline [K] */ + IssmDouble tmax; /* max temperature for Slater albedo decline [K] */ + IssmDouble tstic; /* time step [s] */ + IssmDouble tsticsub; /* sub-time step [s] (= tstic / n_ksub) */ + IssmDouble tau_a; /* dry albedo decline (ISBA) [1/day] */ + IssmDouble tau_f; /* wet albedo decline (ISBA) [1/day] */ + IssmDouble w_crit; /* critical liquid water (ISBA) [kg/m2] */ + IssmDouble mcrit; /* critical melt rate (ISBA / Denby) [m/s] */ + IssmDouble afac; /* "alex" albedo param */ + IssmDouble tmid; /* "alex" albedo param [K] */ + SemicAlbedoScheme alb_scheme; /* albedo parameterisation to use */ + + SemicParam(); /* constructor sets sensible defaults */ +}; + +/* ======================================================================== */ +/* Boundary-override flag struct */ +/* ======================================================================== */ +struct SemicBnd { + bool t2m; + bool tsurf; + bool hsnow; + bool alb; + bool melt; + bool refr; + bool smb; + bool acc; + bool lhf; + bool shf; + bool subl; + bool amp; + + SemicBnd(); /* constructor – all false */ +}; + +/* ======================================================================== */ +/* State struct */ +/* ======================================================================== */ +struct SemicState { + /* prognostic / diagnostic */ + std::vector t2m; /* 2-m air temperature [K] */ + std::vector tsurf; /* surface temperature [K] */ + std::vector hsnow; /* snow-pack height (water-equiv.) [m] */ + std::vector hice; /* ice thickness (water-equiv.) [m] */ + std::vector alb; /* grid-averaged albedo */ + std::vector alb_snow; /* snow albedo */ + std::vector melt; /* potential surface melt [m/s] */ + std::vector melted_snow; /* actual melted snow [m/s] */ + std::vector melted_ice; /* actual melted ice [m/s] */ + std::vector refr; /* refreezing [m/s] */ + std::vector smb; /* surface mass balance [m/s] */ + std::vector acc; /* accumulation [m/s] */ + std::vector lhf; /* latent heat flux [W/m2] */ + std::vector shf; /* sensible heat flux [W/m2] */ + std::vector lwu; /* upwelling longwave radiation [W/m2] */ + std::vector subl; /* sublimation [m/s] */ + std::vector evap; /* evaporation */ + std::vector smb_snow; /* SMB of snow [m/s] */ + std::vector smb_ice; /* SMB of ice [m/s] */ + std::vector runoff; /* surface runoff [m/s] */ + std::vector qmr; /* heat flux from melt/refreezing [W/m2] */ + std::vector qmr_res; /* residual heat flux [W/m2] */ + std::vector amp; /* diurnal cycle amplitude [K] */ + /* forcing */ + std::vector sf; /* snowfall [m/s] */ + std::vector rf; /* rainfall [m/s] */ + std::vector sp; /* surface pressure [Pa] */ + std::vector lwd; /* downwelling longwave radiation [W/m2] */ + std::vector swd; /* downwelling shortwave radiation [W/m2] */ + std::vector wind; /* surface wind speed [m/s] */ + std::vector rhoa; /* air density [kg/m3] */ + std::vector qq; /* air specific humidity [kg/kg] */ + std::vector mask; /* ocean/land/ice mask 0/1/2 */ +}; + +/* ======================================================================== */ +/* Memory management */ +/* ======================================================================== */ +void semic_alloc(SemicState& s, int npts); +void semic_dealloc(SemicState& s); + +/* ======================================================================== */ +/* Boundary helper */ +/* ======================================================================== */ +/*! Parse a list of variable names and set the corresponding override flags. + * \param bnd output boundary flag struct + * \param names list of variable names (up to 30, empty strings ignored) */ +void semic_boundary_define(SemicBnd& bnd, const std::vector& names); + +/* ======================================================================== */ +/* Core physics routines */ +/* ======================================================================== */ +void semic_energy_balance(SemicState& now, const SemicParam& par, const SemicBnd& bnd, + int day, int year); + +void semic_mass_balance (SemicState& now, const SemicParam& par, const SemicBnd& bnd, + int day, int year); + +/*! Combined energy+mass balance step (≡ surface_energy_and_mass_balance) */ +void semic_surface_step (SemicState& now, const SemicParam& par, const SemicBnd& bnd, + int day, int year); + +/* ======================================================================== */ +/* Elemental physics helpers (scalar, inlined equivalents of Fortran */ +/* ELEMENTAL subroutines — also useful for unit tests) */ +/* ======================================================================== */ +IssmDouble semic_sensible_heat_flux(IssmDouble ts, IssmDouble ta, IssmDouble wind, IssmDouble rhoa, + IssmDouble csh, IssmDouble cap_air); + +void semic_latent_heat_flux (IssmDouble ts, IssmDouble wind, IssmDouble shum, IssmDouble sp, + IssmDouble rhoatm, int mask, IssmDouble clh, + IssmDouble& lhf, IssmDouble& subl, IssmDouble& evap); + +IssmDouble semic_longwave_upward (IssmDouble ts); + +void semic_diurnal_cycle (IssmDouble amp, IssmDouble tmean, IssmDouble& above, IssmDouble& below); + +IssmDouble semic_albedo_slater(IssmDouble alb_snow, IssmDouble tsurf, IssmDouble tmin, IssmDouble tmax, + IssmDouble alb_smax, IssmDouble alb_smin); +IssmDouble semic_albedo_denby (IssmDouble melt, IssmDouble alb_smax, IssmDouble alb_smin, IssmDouble mcrit); +IssmDouble semic_albedo_isba (IssmDouble alb, IssmDouble sf, IssmDouble melt, IssmDouble tstic, + IssmDouble tau_a, IssmDouble tau_f, IssmDouble w_crit, IssmDouble mcrit, + IssmDouble alb_smin, IssmDouble alb_smax); + +/* ======================================================================== */ +/* High-level drivers (replace the two Fortran entry points) */ +/* ======================================================================== */ + +/*! Annual driver: loops 365 days × nloop spinup cycles for a single vertex. + * Input arrays have dimension [365]. + * Used by Element::SmbSemic() (method 0). + * + * \param sf_in snowfall rate [m/s], 365 entries + * \param rf_in rainfall rate [m/s], 365 entries + * \param swd_in downwelling SW radiation [W/m2], 365 entries + * \param lwd_in downwelling LW radiation [W/m2], 365 entries + * \param wind_in surface wind speed [m/s], 365 entries + * \param sp_in surface pressure [Pa], 365 entries + * \param rhoa_in air density [kg/m3], 365 entries + * \param qq_in specific humidity [kg/kg], 365 entries + * \param tt_in 2-m temperature [K], 365 entries + * \param tsurf_out mean annual surface temperature [K] (output) + * \param smb_out mean annual SMB [m/s] (output) + * \param saccu_out mean annual albedo (historically labelled) (output) + * \param smelt_out mean annual melt [m/s] (output) + */ +void RunSemic(const IssmDouble* sf_in, const IssmDouble* rf_in, + const IssmDouble* swd_in, const IssmDouble* lwd_in, + const IssmDouble* wind_in, const IssmDouble* sp_in, + const IssmDouble* rhoa_in, const IssmDouble* qq_in, + const IssmDouble* tt_in, + IssmDouble& tsurf_out, IssmDouble& smb_out, + IssmDouble& saccu_out, IssmDouble& smelt_out); + +/*! Transient driver: advances one time step for nx grid points. + * Used by Element::SmbSemicTransient() (method 1). + * + * Input/output arrays all have dimension [nx]. + * + * \param nx number of grid points + * \param ntime number of sub-time steps within a call (usually 1) + * \param nloop number of spinup repetitions (usually 1) + * \param sf_in snowfall [m/s] + * \param rf_in rainfall [m/s] + * \param swd_in downwelling SW [W/m2] + * \param lwd_in downwelling LW [W/m2] + * \param wind_in wind speed [m/s] + * \param sp_in surface pressure [Pa] + * \param rhoa_in air density [kg/m3] + * \param qq_in specific humidity [kg/kg] + * \param tt_in 2-m temperature [K] + * \param tsurf_in previous surface temperature [K] + * \param qmr_in residual heat flux from previous step [W/m2] + * \param tstic time step [s] + * \param hcrit critical snow height for snow cover [m] + * \param rcrit critical snow height for refreezing [m] + * \param mask ocean/land/ice mask 0/1/2 + * \param hice ice thickness (water-equiv.) [m] (in/out via out arrays) + * \param hsnow snow height (water-equiv.) [m] (in/out via out arrays) + * \param albedo grid-averaged albedo + * \param albedo_snow snow albedo + * \param alb_scheme albedo scheme code (SemicAlbedoScheme) + * \param alb_smax maximum snow albedo + * \param alb_smin minimum snow albedo + * \param albi bare-ice albedo + * \param albl bare-land albedo + * \param Tamp diurnal cycle amplitude [K] + * \param tmin min temperature for Slater scheme [K] + * \param tmax max temperature for Slater scheme [K] + * \param tmid "alex" parameter [K] + * \param mcrit critical melt rate [m/s] + * \param wcrit critical liquid water (ISBA) [kg/m2] + * \param tau_a dry albedo decline (ISBA) + * \param tau_f wet albedo decline (ISBA) + * \param afac "alex" parameter + * \param verbose print debug info + * \param tsurf_out … output arrays (same units as inputs) + */ +void RunSemicTransient(int nx, int ntime, int nloop, + const IssmDouble* sf_in, const IssmDouble* rf_in, + const IssmDouble* swd_in, const IssmDouble* lwd_in, + const IssmDouble* wind_in, const IssmDouble* sp_in, + const IssmDouble* rhoa_in, const IssmDouble* qq_in, + const IssmDouble* tt_in, + const IssmDouble* tsurf_in, const IssmDouble* qmr_in, + IssmDouble tstic, + IssmDouble hcrit, IssmDouble rcrit, + const IssmDouble* mask, const IssmDouble* hice, const IssmDouble* hsnow, + const IssmDouble* albedo, const IssmDouble* albedo_snow, + int alb_scheme, + IssmDouble alb_smax, IssmDouble alb_smin, IssmDouble albi, IssmDouble albl, + const IssmDouble* Tamp, + IssmDouble tmin, IssmDouble tmax, IssmDouble tmid, + IssmDouble mcrit, IssmDouble wcrit, + IssmDouble tau_a, IssmDouble tau_f, IssmDouble afac, + bool verbose, + IssmDouble* tsurf_out, IssmDouble* smb_out, + IssmDouble* smbi_out, IssmDouble* smbs_out, + IssmDouble* saccu_out, IssmDouble* smelt_out, + IssmDouble* refr_out, IssmDouble* alb_out, + IssmDouble* alb_snow_out, + IssmDouble* hsnow_out, IssmDouble* hice_out, + IssmDouble* qmr_out, + IssmDouble* runoff_out, IssmDouble* subl_out); + +#endif /* _SEMIC_H_ */ diff --git a/src/c/shared/io/Marshalling/IoCodeConversions.cpp b/src/c/shared/io/Marshalling/IoCodeConversions.cpp index ae7cb6912..73e46ddda 100644 --- a/src/c/shared/io/Marshalling/IoCodeConversions.cpp +++ b/src/c/shared/io/Marshalling/IoCodeConversions.cpp @@ -269,6 +269,7 @@ int IoCodeToEnumSMB(int enum_in){/*{{{*/ case 14: return SMBdebrisEvattEnum; case 15: return SMBpddGCMEnum; case 16: return SMBpddFastEnum; + case 20: return SMBmariaEnum; default: _error_("Marshalled SMB code \""< C++ 0-based throughout. + * 2-D Fortran arrays ybar(n,m) / sbar(n,m) are stored as flat row-major + * arrays ybar[j*n + i] (j = column/update index, i = component). + */ + +#include +#include +#include + +#include "../io/Print/Print.h" +#include "./m1qn3.h" + +/* ========================================================================= + * Internal helpers + * ========================================================================= */ + +/* Euclidean dot product (replaces Fortran euclid / prosca). */ +static double dot(long n, const double* x, const double* y){ + double ps = 0.0; + for(long i = 0; i < n; ++i) ps += x[i] * y[i]; + return ps; +} + +/* ctonb / ctcab: identity transformation (Euclidean metric). */ +static void ctonb(long n, const double* u, double* v){ + for(long i = 0; i < n; ++i) v[i] = u[i]; +} +static void ctcab(long n, const double* u, double* v){ + for(long i = 0; i < n; ++i) v[i] = u[i]; +} + +/* ========================================================================= + * ecube (Fortran: ecube) + * + * Cubic interpolation: given f and f' at t and ta, compute a new t + * safeguarded to [tlower, tupper]. + * ========================================================================= */ +static void ecube(double& t, double f, double fp, double ta, double fa, double fpa, double tlower, double tupper){ + + double z1 = fp + fpa - 3.0 * (fa - f) / (ta - t); + double b = z1 + fp; + double discri; + + if (fabs(z1) <= 1.0) { + discri = z1 * z1 - fp * fpa; + } + else { + discri = fp / z1; + discri = discri * fpa; + discri = z1 - discri; + + if (z1 >= 0.0 && discri >= 0.0) { + discri = sqrt(z1) * sqrt(discri); + } + else if (z1 <= 0.0 && discri <= 0.0) { + discri = sqrt(-z1) * sqrt(-discri); + } + else { + discri = -1.0; + } + } + + if (discri < 0.0) { + t = (fp < 0.0) ? tupper : tlower; + } + else { + discri = sqrt(discri); + if (t - ta < 0.0) discri = -discri; + + double sign = (t - ta) / fabs(t - ta); + if (b * sign > 0.0) { + t = t + fp * (ta - t) / (b + discri); + } + else { + double den = z1 + b + fpa; + double anum = b - discri; + if (fabs((t - ta) * anum) < (tupper - tlower) * fabs(den)) { + t = t + anum * (ta - t) / den; + } + else { + t = tupper; + } + } + } + + t = fmax(t, tlower); + t = fmin(t, tupper); +} + +/* ========================================================================= + * mupdts (Fortran: mupdts) + * + * Compute m (number of L-BFGS updates) for DIS mode with in-memory storage. + * DIS requires ndz >= 4*n + m*(2*n+1), so m = (ndz - 4*n) / (2*n+1). + * ========================================================================= */ +static long mupdts(long n, long ndz){ + return (ndz - 4 * n) / (2 * n + 1); +} + +/* ========================================================================= + * dd (Fortran: dd) + * + * L-BFGS two-loop recursion: compute H * depl in-place. + * DIS mode (sscale = false). + * + * ybar, sbar: flat arrays of shape [m][n] (update j at offset j*n). + * alpha: scratch array of length m. + * jmin, jmax: 0-based circular buffer pointers (inclusive range in the ring). + * precos: unused here (DIS mode uses diag scaling). + * ========================================================================= */ +static void dd(long n, long m, double* depl, double* aux, long jmin, long jmax, double /*precos*/, double* diag, double* alpha, double* ybar, double* sbar, long izs[], float rzs[], void* dzs){ + /* jfin = jmax, but if the ring has wrapped, jfin = jmax + m */ + long jfin = jmax; + if (jfin < jmin) jfin = jmax + m; + + /* --- descent phase --- */ + for (long j = jfin; j >= jmin; --j) { + long jp = j % m; /* 0-based circular index */ + double ps = dot(n, depl, &sbar[jp * n]); + alpha[jp] = ps; + for (long i = 0; i < n; ++i) + depl[i] -= ps * ybar[jp * n + i]; + } + + /* --- DIS preconditioning: depl = D * ctonb(depl), then ctcab --- */ + ctonb(n, depl, aux); + for (long i = 0; i < n; ++i) aux[i] *= diag[i]; + ctcab(n, aux, depl); + + /* --- ascent phase --- */ + for (long j = jmin; j <= jfin; ++j) { + long jp = j % m; + double ps = dot(n, depl, &ybar[jp * n]); + double r = alpha[jp] - ps; + for (long i = 0; i < n; ++i) + depl[i] += r * sbar[jp * n + i]; + } +} + +/* ========================================================================= + * mlis3 (Fortran: mlis3) + * + * Wolfe-condition line search with cubic interpolation. + * Direct communication mode only. + * + * On exit: logic = + * 0 serious step (both Wolfe conditions satisfied) + * 1 blocked on tmax + * 4 napmax exceeded + * 5 user requested stop (indic = 0) + * 6 stopped on dxmin / inconsistent + * <0 simulator failure + * ========================================================================= */ +static void mlis3(long n, M1qn3SimulFunc simul, double* x, double& f, double& fpn, double& t, double tmin, double tmax, double* d, double* g, double amd, double amf, long impres, int& logic, long& nap, long napmax, double* xn, long izs[], float rzs[], void* dzs){ + /* --- sanity check --- */ + if (!(n > 0 && fpn < 0.0 && t > 0.0 && tmax > 0.0 + && amf > 0.0 && amd > amf && amd < 1.0)) { + logic = 6; + return; + } + + double tesf = amf * fpn; + double tesd = amd * fpn; + + const double barmin = 0.01; + const double barmul = 5.0; + const double barmax = 0.3; + double barr = barmin; + + double td = 0.0, tg = 0.0; + double fn = f, fg = fn, fpg = fpn; + double ta = 0.0, fa = fn, fpa = fpn; + double d2 = dot(n, d, d); + + /* eliminate ridiculously small initial t */ + if (t < tmin) { + t = tmin; + if (t > tmax) tmin = tmax; + } + bool t_increased = false; + while (fn + t * fpn >= fn + 0.9 * t * fpn) { + t_increased = true; + t *= 2.0; + } + + int indica = 1; + logic = 0; + if (t > tmax) { t = tmax; logic = 1; } + + /* trial point */ + for (long i = 0; i < n; ++i) { xn[i] = x[i]; x[i] = xn[i] + t * d[i]; } + + /* ---- main loop ---- */ + bool done = false; + bool napmax_exit = false; /* true when we exit via napmax (no simul called) */ + while (!done) { + nap++; + if (nap > napmax) { + /* napmax exceeded: restore fn/xn to left bracket, but leave x at the + * current trial position (matching Fortran: x is not restored here, + * only xn/fn are updated; the final x = xn assignment below is + * skipped via napmax_exit so that x stays at the last trial point + * where g was evaluated). */ + logic = 4; + fn = fg; + for (long i = 0; i < n; ++i) xn[i] += tg * d[i]; + napmax_exit = true; + break; + } + + /* call simulator: ask for f and g */ + bool need_advance = false; + { + long indic = 4; + simul(&indic, &n, x, &f, g, izs, rzs, dzs); + + if (indic == 0) { + /* user stop */ + logic = 5; + fn = f; + for (long i = 0; i < n; ++i) xn[i] = x[i]; + done = true; + } + else if (indic < 0) { + /* computation failed: shrink interval and re-enter advance. + * Fortran goes to label 905 (skipping fa=f;fpa=fp update). */ + td = t; + logic = 0; + t = tg + 0.1 * (td - tg); + /* indica = indic (goes to 905, NOT 900 — do not update fa/fpa) */ + indica = (int)indic; + need_advance = true; + } + } + + if (!done && !need_advance) { + double fp = dot(n, d, g); + double ffn = f - fn; + + if (ffn > t * tesf) { + /* first Wolfe condition violated → bracket from above, interpolate. + * Fortran: td=t; go to 500; then fa=f; fpa=fp at label 900. + * ecube must be called with the OLD fa/fpa (previous anchor), + * so do NOT overwrite fa/fpa before calling ecube. */ + td = t; + logic = 0; + + /* interpolation (label 500 in Fortran) */ + if (indica <= 0) { + ta = t; + t = 0.9 * tg + 0.1 * td; + } + else { + double test = barr * (td - tg); + double gauche = tg + test; + double droite = td - test; + double taa = t; + ecube(t, f, fp, ta, fa, fpa, gauche, droite); + ta = taa; + if (t > gauche && t < droite) + barr = fmax(barmin, barr / barmul); + else + barr = fmin(barmul * barr, barmax); + } + /* label 900: update anchor AFTER ecube */ + fa = f; fpa = fp; + need_advance = true; + } + else if (fp > tesd) { + /* first Wolfe ok, curvature condition satisfied: serious step → accept. + * Fortran: fp > tesd → logic=0; go to 320 (accept). */ + logic = 0; + fn = f; + for (long i = 0; i < n; ++i) xn[i] = x[i]; + done = true; + } + else { + /* first Wolfe ok, curvature condition NOT satisfied. + * Fortran label 350: tg=t; fg=f; fpg=fp; then extrapolate (td==0) + * or interpolate (td!=0) — regardless of whether logic==0 or logic==1. + * The old "else if (logic==0) accept" branch was WRONG: it caused the + * line search to return a step that doesn't satisfy the strong Wolfe + * curvature condition, corrupting (y,s) pairs and producing <=0. */ + tg = t; fg = f; fpg = fp; + + if (td != 0.0) { + /* interpolation (label 500 in Fortran) */ + if (indica <= 0) { + ta = t; + t = 0.9 * tg + 0.1 * td; + } + else { + double test = barr * (td - tg); + double gauche = tg + test; + double droite = td - test; + double taa = t; + ecube(t, f, fp, ta, fa, fpa, gauche, droite); + ta = taa; + if (t > gauche && t < droite) + barr = fmax(barmin, barr / barmul); + else + barr = fmin(barmul * barr, barmax); + } + /* label 900: update anchor AFTER ecube */ + fa = f; fpa = fp; + need_advance = true; + } + else { + /* extrapolation */ + double taa = t; + double gauche = (1.0 + barmin) * t; + double droite = 10.0 * t; + ecube(t, f, fp, ta, fa, fpa, gauche, droite); + ta = taa; + /* label 900: update anchor AFTER ecube */ + fa = f; fpa = fp; + if (t >= tmax) { + logic = 1; + t = tmax; + } + need_advance = true; + } + } + } + + if (!done && need_advance) { + indica = 1; /* treated as "computed" for next cubic */ + + /* check stopping: td - tg < tmin? */ + if (td != 0.0) { + bool stop_dxmin = false; + if (td - tg < tmin) { + stop_dxmin = true; + } + else { + /* machine-precision guard */ + bool no_change = true; + for (long i = 0; i < n; ++i) { + double z = xn[i] + t * d[i]; + if (z != xn[i] && z != x[i]) { no_change = false; break; } + } + if (no_change) stop_dxmin = true; + } + + if (stop_dxmin) { + logic = 6; + if (tg != 0.0) { + fn = fg; + for (long i = 0; i < n; ++i) xn[i] += tg * d[i]; + } + done = true; + } + } + + if (!done) { + /* update trial point and loop */ + for (long i = 0; i < n; ++i) x[i] = xn[i] + t * d[i]; + } + } + } + + /* restore x = best point found. + * For normal exits (accepted step, dxmin, user-stop): x <- xn (best safe point). + * For napmax exit: leave x as the last trial point where simul was called, + * matching Fortran m1qn3 behaviour (x is not explicitly restored there). */ + f = fn; + if (!napmax_exit) { + for (long i = 0; i < n; ++i) x[i] = xn[i]; + } +} + +/* ========================================================================= + * m1qn3a (Fortran: m1qn3a) + * + * Core L-BFGS minimizer. DIS mode, cold start, direct comms, in-memory. + * ========================================================================= */ +static void m1qn3a(M1qn3SimulFunc simul, + long n, double* x, double& f, double* g, + double dxmin, double df1, double& epsg, + long impres, + long& omode, long& niter, long& nsim, + long m, + long& jmin, long& jmax, + double* d, /* length n */ + double* gg, /* length n */ + double* diag, /* length n */ + double* aux, /* length n */ + double* alpha,/* length m */ + double* ybar, /* length m*n */ + double* sbar, /* length m*n */ + long izs[], float rzs[], void* dzs, + bool return_best = true) +{ + const double rm1 = 0.0001; /* Armijo constant */ + const double rm2 = 0.99; /* curvature constant */ + const double rmin = 1.0e-20; + + /* --- initialisation --- */ + long itmax = niter; + niter = 0; + long isim = 1; /* already called once before entering here */ + double eps1 = 1.0; + + /* initial gradient norm (dfn norm = Euclidean) */ + double gnorm = sqrt(dot(n, g, g)); + double gnorms = gnorm; /* dfn-norm = Euclidean norm */ + + if (impres >= 1) { + _printf0_(" f = " << f << "\n"); + _printf0_(" dfn-norm of g = " << gnorms << "\n"); + } + if (gnorms < rmin) { + omode = 2; + if (impres >= 1) _printf0_(" >>> m1qn3a: initial gradient is too small\n"); + return; + } + + /* best-point tracking: keep the (f,x,g) triplet with the lowest f seen */ + double f_best = f; + double* x_best = new double[n]; + double* g_best = new double[n]; + for(long i = 0; i < n; ++i){ x_best[i] = x[i]; g_best[i] = g[i]; } + + /* cold start: jmin=0, jmax=-1 (empty ring, 0-based) */ + jmin = 0; + jmax = -1; + long jcour = jmax; /* current slot (unused for cold start) */ + + /* Fletcher scaling of first descent direction, initialise diag = 1 */ + double precos = 2.0 * df1 / (gnorm * gnorm); + for (long i = 0; i < n; ++i) { + d[i] = -g[i] * precos; + diag[i] = 1.0; + } + + /* check descent */ + double tmax = 1.0e20; + double hp0 = dot(n, d, g); + if (hp0 >= 0.0) { + omode = 7; + if (impres >= 1) + _printf0_(" >>> m1qn3 (iter 0): search direction is not descent: (g,d)=" << hp0 << "\n"); + goto m1qn3a_exit; + } + + /* ---- main iteration loop ---- */ + for (;;) { + niter++; + + if (impres >= 4) + _printf0_(" m1qn3: iter " << niter << ", simul " << isim + << ", f=" << f << ", h'(0)=" << hp0 << "\n"); + + /* save current gradient */ + for (long i = 0; i < n; ++i) gg[i] = g[i]; + double ff = f; + + /* compute tmin */ + double tmin_ls = 0.0; + for (long i = 0; i < n; ++i) + tmin_ls = fmax(tmin_ls, fabs(d[i])); + tmin_ls = dxmin / tmin_ls; + + double t = 1.0; + double d1 = hp0; + int moderl; + + /* --- line search --- */ + mlis3(n, simul, x, f, d1, t, tmin_ls, tmax, d, g, + rm2, rm1, impres, moderl, isim, nsim, aux, + izs, rzs, dzs); + + /* handle line-search exit codes */ + if (moderl != 0) { + if (moderl < 0) { + omode = moderl; goto m1qn3a_exit; + } + else if (moderl == 4) { + omode = 5; goto m1qn3a_exit; + } + else if (moderl == 5) { + omode = 0; goto m1qn3a_exit; + } + else if (moderl == 6) { + omode = 6; goto m1qn3a_exit; + } + /* moderl == 1 (blocked on tmax): skip L-BFGS update, fall through */ + } + + /* --- L-BFGS matrix update (skipped when blocked on tmax) --- */ + if (moderl != 1 && m > 0) { + /* advance ring pointer */ + jmax = jmax + 1; + if (jmax >= m) jmax -= m; + /* advance jmin only when ring is full (cold start: Fortran niter > m) */ + if (niter > m) { + jmin++; + if (jmin >= m) jmin -= m; + } + jcour = jmax; + + /* y = g_new - g_old, s = t * d */ + for (long i = 0; i < n; ++i) { + sbar[jcour * n + i] = t * d[i]; + ybar[jcour * n + i] = g[i] - gg[i]; + } + + /* ys = (y, s) — must be positive */ + double ys = dot(n, &ybar[jcour * n], &sbar[jcour * n]); + if (ys <= 0.0) { + omode = 7; + if (impres >= 1) + _printf0_(" >>> m1qn3 (iter " << niter + << "): (y,s) = " << ys << " is not positive\n"); + goto m1qn3a_exit; + } + + /* normalise ybar and sbar by 1/sqrt(ys) */ + double inv_sqrt_ys = 1.0 / sqrt(ys); + for (long i = 0; i < n; ++i) { + sbar[jcour * n + i] *= inv_sqrt_ys; + ybar[jcour * n + i] *= inv_sqrt_ys; + } + + /* DIS: update diagonal preconditioner. + * Scale to Rayleigh ellipsoid, then rank-1 update. + * aux = ctonb(ybar_j), then scale by 1/(ybar_j^T D ybar_j) + * then update: D <- D - (D*sbar_j)(D*sbar_j)^T/(sbar_j^T D^{-1} sbar_j) + * + ybar_j ybar_j^T (in orthonormal basis) + * Following the Fortran exactly: + */ + { + /* ctonb(ybar_j) -> aux */ + ctonb(n, &ybar[jcour * n], aux); + double ps = 0.0; + for (long i = 0; i < n; ++i) ps += diag[i] * aux[i] * aux[i]; + double d1_scale = 1.0 / ps; + for (long i = 0; i < n; ++i) diag[i] *= d1_scale; + + /* ctonb(sbar_j) -> gg (used as temp) */ + ctonb(n, &sbar[jcour * n], gg); + ps = 0.0; + for (long i = 0; i < n; ++i) ps += gg[i] * gg[i] / diag[i]; + double den = ps; + for (long i = 0; i < n; ++i) { + diag[i] = 1.0 / (1.0 / diag[i] + aux[i] * aux[i] + - (gg[i] / diag[i]) * (gg[i] / diag[i]) / den); + if (diag[i] <= 0.0) diag[i] = rmin; + } + /* restore gg to current gradient (was overwritten by ctonb) */ + for (long i = 0; i < n; ++i) gg[i] = g[i]; + } + } + + /* --- update best point seen so far (after line search + L-BFGS update) --- */ + if (return_best && f < f_best) { + f_best = f; + for (long i = 0; i < n; ++i) { x_best[i] = x[i]; g_best[i] = g[i]; } + } + + /* --- stopping tests --- */ + gnorm = sqrt(dot(n, g, g)); + eps1 = gnorm / gnorms; + + if (impres >= 3) + _printf0_(" m1qn3: iter " << niter << ", simul " << isim + << ", step=" << t << ", f=" << f + << ", |g|=" << gnorm << ", |g|/|g0|=" << eps1 << "\n"); + + if (eps1 < epsg) { + omode = 1; + epsg = eps1; + nsim = isim; + goto m1qn3a_exit; + } + if (niter == itmax) { + omode = 4; + if (impres >= 1) + _printf0_(" >>> m1qn3 (iter " << niter << "): max iterations reached\n"); + epsg = eps1; nsim = isim; + goto m1qn3a_exit; + } + if (isim > nsim) { + omode = 5; + if (impres >= 1) + _printf0_(" >>> m1qn3 (iter " << niter << "): max simulations reached\n"); + epsg = eps1; nsim = isim; + goto m1qn3a_exit; + } + + /* --- compute new descent direction d = -H * g --- */ + for (long i = 0; i < n; ++i) d[i] = -g[i]; + if (m > 0 && jmax >= 0) { + dd(n, m, d, aux, jmin, jmax, precos, diag, alpha, ybar, sbar, + izs, rzs, dzs); + } + else { + /* m=0 fallback: steepest descent scaled by preco */ + double ps = dot(n, g, g); + double prec = 2.0 * (ff - f) / ps; + for (long i = 0; i < n; ++i) d[i] = -g[i] * prec; + } + + /* check descent */ + hp0 = dot(n, d, g); + if (hp0 >= 0.0) { + omode = 7; + if (impres >= 1) + _printf0_(" >>> m1qn3 (iter " << niter + << "): d is not a descent direction: (g,d)=" << hp0 << "\n"); + epsg = eps1; nsim = isim; + goto m1qn3a_exit; + } + } /* end main loop */ + +m1qn3a_exit: + /* Restore the best (f, x, g) triplet seen during the run */ + if (return_best && f_best < f) { + f = f_best; + for (long i = 0; i < n; ++i){ + x[i] = x_best[i]; + g[i] = g_best[i]; + } + } + delete [] x_best; + delete [] g_best; +} + +/* ========================================================================= + * m1qn3_cpp (public entry point, Fortran: m1qn3) + * ========================================================================= */ +void m1qn3_cpp(M1qn3SimulFunc simul, + long* n_ptr, double* x, double* f_ptr, double* g, + double* dxmin, double* df1, double* epsg, + long* impres, long* /*io*/, + long* omode, long* niter, long* nsim, + long* iz, double* dz, long* ndz, + long izs[], float rzs[], void* dzs, + bool return_best) +{ + long n = *n_ptr; + double f = *f_ptr; + long impres_ = *impres; + + /* --- input checks --- */ + if (n <= 0) { *omode = 2; return; } + if (*niter <= 0) { *omode = 2; return; } + if (*nsim <= 0) { *omode = 2; return; } + if (*dxmin <= 0.0) { *omode = 2; return; } + if (*epsg <= 0.0) { *omode = 2; return; } + if (*epsg >= 1.0) { *omode = 1; *niter = 0; *nsim = 0; return; } + + /* --- compute m (number of L-BFGS updates) --- */ + long m = mupdts(n, *ndz); + if (m < 1) { + *omode = 2; + if (impres_ >= 1) + _printf0_(" >>> m1qn3_cpp: not enough memory (ndz too small)\n"); + return; + } + long ndz_needed = 4 * n + m * (2 * n + 1); + if (*ndz < ndz_needed) { *omode = 2; return; } + + if (impres_ >= 1) { + _printf0_(" m1qn3_cpp (C++ implementation): entry point\n"); + _printf0_(" n=" << n << ", dxmin=" << *dxmin << ", df1=" << *df1 + << ", epsg=" << *epsg << "\n"); + _printf0_(" max iter=" << *niter << ", max sim=" << *nsim << "\n"); + _printf0_(" allocated ndz=" << *ndz << ", used=" << ndz_needed + << ", updates m=" << m << "\n"); + } + + /* --- split working array dz (DIS mode layout): + * + * dz[0 .. n-1] : diag (diagonal preconditioner) + * dz[n .. n+n*m-1] : ybar (m blocks of n: ybar[j*n+i]) + * dz[n+n*m .. n+2*n*m-1] : sbar + * dz[n+2*n*m .. 2*n+2*n*m-1] : d (descent direction) + * dz[2*n+2*n*m .. 3*n+2*n*m-1] : gg (old gradient) + * dz[3*n+2*n*m .. 4*n+2*n*m-1] : aux + * dz[4*n+2*n*m .. 4*n+2*n*m+m-1]: alpha + * + * Total = 4*n + m*(2*n+1) = ndz_needed. + --- */ + double* diag = dz; + double* ybar = diag + n; + double* sbar = ybar + n * m; + double* d_vec = sbar + n * m; + double* gg = d_vec + n; + double* aux = gg + n; + double* alpha = aux + n; + + /* store problem size in iz (for potential warm-restart info) */ + iz[0] = n; + iz[1] = 0; /* DIS */ + iz[2] = m; + + long jmin = 0, jmax = -1; + + /* Call the core optimizer */ + m1qn3a(simul, n, x, f, g, + *dxmin, *df1, *epsg, + impres_, + *omode, *niter, *nsim, + m, jmin, jmax, + d_vec, gg, diag, aux, alpha, ybar, sbar, + izs, rzs, dzs, + return_best); + + /* store final pointers */ + iz[3] = jmin; + iz[4] = jmax; + + *f_ptr = f; + + if(impres_ >= 1){ + _printf0_(" m1qn3_cpp: exit code " << *omode << ", iter=" << *niter << ", sim=" << *nsim << ", |g|/|g0|=" << *epsg << "\n"); + } +} diff --git a/src/c/shared/m1qn3/m1qn3.h b/src/c/shared/m1qn3/m1qn3.h new file mode 100644 index 000000000..578c5d96c --- /dev/null +++ b/src/c/shared/m1qn3/m1qn3.h @@ -0,0 +1,58 @@ +/*!\file: m1qn3.h + * \brief: C++ implementation of the m1qn3 L-BFGS optimizer. + * + * Translated from the Fortran m1qn3 (Version 3.3, October 2009) by + * Jean Charles Gilbert and Claude Lemarechal, INRIA. + * + * This translation covers only the subset used by ISSM: + * - Direct communication mode (reverse = 0) + * - DIS (Diagonal Initial Scaling) mode (imode[0] = 0) + * - Cold start (imode[1] = 0) + * - In-memory (y,s) pair storage + * - "dfn" norm (Euclidean scalar product) + */ + +#ifndef _M1QN3_CPP_H_ +#define _M1QN3_CPP_H_ + +/*! Callback type for the cost function / simulator. + * indic = 4 on entry: compute f and g. + * indic = 0 on return: user requests stop. + * indic < 0 on return: computation failed at this point. + */ +typedef void (*M1qn3SimulFunc)(long* indic, long* n, double* x, double* pf, + double* g, long izs[], float rzs[], void* dzs); + +/*! m1qn3_cpp - L-BFGS minimizer (C++ implementation). + * + * Parameters (matching the Fortran m1qn3_ interface, minus unused args): + * simul [in] cost-function callback (same signature as Fortran simul) + * n [in] problem dimension + * x [in/out] initial guess on entry, solution on exit + * f [in/out] f(x) on entry (already evaluated), final f on exit + * g [in/out] grad f on entry (already evaluated), final grad on exit + * dxmin [in] minimum step-size for line search + * df1 [in] expected decrease in f during the first iteration + * epsg [in/out] relative gradient tolerance on entry; achieved value on exit + * impres [in] verbosity level (0 = silent) + * io [in] (unused, kept for interface compatibility) + * omode [out] exit code (1=converged, 4=max iter, 5=max sim, ...) + * niter [in/out] max iterations on entry; iterations performed on exit + * nsim [in/out] max simulations on entry; simulations performed on exit + * iz [work] integer working array of size 5 + * dz [work] double working array of size ndz + * ndz [in] size of dz; must be >= 4*n + m*(2*n+1) for some m >= 1 + * izs [in] passed through to simul (not used internally) + * rzs [in] passed through to simul (not used internally) + * dzs [in] passed through to simul (user data pointer) + */ +void m1qn3_cpp(M1qn3SimulFunc simul, + long* n, double* x, double* f, double* g, + double* dxmin, double* df1, double* epsg, + long* impres, long* io, + long* omode, long* niter, long* nsim, + long* iz, double* dz, long* ndz, + long izs[], float rzs[], void* dzs, + bool return_best = true); + +#endif /* _M1QN3_CPP_H_ */ diff --git a/src/c/shared/shared.h b/src/c/shared/shared.h index b96159c67..c24480446 100644 --- a/src/c/shared/shared.h +++ b/src/c/shared/shared.h @@ -15,10 +15,12 @@ #include "./Exp/exp.h" #include "./Matrix/matrix.h" #include "./Numerics/numerics.h" +#include "./Semic/Semic.h" #include "./Sorting/sorting.h" #include "./String/sharedstring.h" #include "./Threads/issm_threads.h" #include "./Triangle/triangle.h" #include "./LatLong/latlong.h" +#include "./m1qn3/m1qn3.h" #endif diff --git a/src/m/archive/archdisp.m b/src/m/archive/archdisp.m index b56305d1b..9fdf9bc5c 100644 --- a/src/m/archive/archdisp.m +++ b/src/m/archive/archdisp.m @@ -9,7 +9,7 @@ function archdisp(filename) % {{{ error('Error: Invalid number of arguments, only one file can be displayed at a time'); end - if ~exist(filename,'file'), + if ~exist(filename,'file') error('Error: File does not exist!'); end diff --git a/src/m/archive/archread.m b/src/m/archive/archread.m index 0db46f8b3..b81775f9d 100644 --- a/src/m/archive/archread.m +++ b/src/m/archive/archread.m @@ -48,7 +48,7 @@ % Determine what fields we need (compare to varargin) idx=find(ismember(field_names,varargin)); - if size(idx) == 0, + if size(idx) == 0 fclose(fid); error('Error: No matching variables found in archive.'); end diff --git a/src/m/archive/archwrite.m b/src/m/archive/archwrite.m index a9390aed7..38abf1d9d 100644 --- a/src/m/archive/archwrite.m +++ b/src/m/archive/archwrite.m @@ -14,7 +14,7 @@ function archwrite(filename,varargin) % {{{ error('Error: Invalid number of arguments provided. Please check the usage above.'); end - if ~exist(filename,'file'), + if ~exist(filename,'file') fid=fopen(filename,'wb'); % create new file else fid=fopen(filename,'ab+'); % append to file @@ -22,7 +22,7 @@ function archwrite(filename,varargin) % {{{ numfields=nvarargs/2; % Generate data to write - for i=1:numfields, + for i=1:numfields % write field name name=varargin{2*i-1}; write_field_name(fid,name); diff --git a/src/m/boundaryconditions/PattynSMB.m b/src/m/boundaryconditions/PattynSMB.m index 687b6ef7d..a3b6c4bdc 100644 --- a/src/m/boundaryconditions/PattynSMB.m +++ b/src/m/boundaryconditions/PattynSMB.m @@ -21,12 +21,12 @@ % ABLdot : Surface ablation rate in [m/a] ice equivalent %Double check lat and long exist: - if isnan(md.mesh.lat), + if isnan(md.mesh.lat) error('PattynSMB error message: md.mesh.lat field required'); end %Delta Temperature forcing - if (nargin==1), + if (nargin==1) Tf=0; end diff --git a/src/m/boundaryconditions/SetIceSheetBC.m b/src/m/boundaryconditions/SetIceSheetBC.m index cc6868da5..b4fe9b11b 100644 --- a/src/m/boundaryconditions/SetIceSheetBC.m +++ b/src/m/boundaryconditions/SetIceSheetBC.m @@ -36,7 +36,7 @@ md.dsl = initialize(md.dsl,md); %Deal with other boundary conditions -if isnan(md.balancethickness.thickening_rate), +if isnan(md.balancethickness.thickening_rate) md.balancethickness.thickening_rate=zeros(md.mesh.numberofvertices,1); disp(' no balancethickness.thickening_rate specified: values set as zero'); end @@ -44,13 +44,13 @@ md.balancethickness.spcthickness=NaN*ones(md.mesh.numberofvertices,1); md.damage.spcdamage=NaN*ones(md.mesh.numberofvertices,1); -if (length(md.initialization.temperature)==md.mesh.numberofvertices), +if (length(md.initialization.temperature)==md.mesh.numberofvertices) md.thermal.spctemperature=NaN*ones(md.mesh.numberofvertices,1); if isprop(md.mesh,'vertexonsurface') pos=find(md.mesh.vertexonsurface); md.thermal.spctemperature(pos)=md.initialization.temperature(pos); %impose observed temperature on surface end - if (length(md.basalforcings.geothermalflux)~=md.mesh.numberofvertices), + if (length(md.basalforcings.geothermalflux)~=md.mesh.numberofvertices) md.basalforcings.geothermalflux=50.*10^-3*ones(md.mesh.numberofvertices,1); %50 mW/m^2 end else diff --git a/src/m/boundaryconditions/SetIceShelfBC.m b/src/m/boundaryconditions/SetIceShelfBC.m index 12eed6645..f48740421 100644 --- a/src/m/boundaryconditions/SetIceShelfBC.m +++ b/src/m/boundaryconditions/SetIceShelfBC.m @@ -15,12 +15,12 @@ % See also: SETICESHEETBC, SETMARINEICESHEETBC %node on Dirichlet (boundary and ~icefront) -if nargin==2, +if nargin==2 icefrontfile=varargin{1}; if ~exist(icefrontfile), error(['SetIceShelfBC error message: ice front file ' icefrontfile ' not found']); end nodeinsideicefront=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,icefrontfile,'node',2); nodeonicefront=double(md.mesh.vertexonboundary & nodeinsideicefront); -elseif nargin==1, +elseif nargin==1 nodeonicefront=zeros(md.mesh.numberofvertices,1); else help SetIceShelfBC @@ -37,9 +37,9 @@ md.mask.ice_levelset(find(nodeonicefront))=0; %First find segments that are not completely on the front -if strcmp(elementtype(md.mesh),'Penta'), +if strcmp(elementtype(md.mesh),'Penta') numbernodesfront=4; -elseif strcmp(elementtype(md.mesh),'Tria'), +elseif strcmp(elementtype(md.mesh),'Tria') numbernodesfront=2; else error('mesh type not supported yet'); @@ -66,7 +66,7 @@ md.basalforcings = initialize(md.basalforcings,md); %Deal with other boundary conditions -if isnan(md.balancethickness.thickening_rate), +if isnan(md.balancethickness.thickening_rate) md.balancethickness.thickening_rate=zeros(md.mesh.numberofvertices,1); disp(' no balancethickness.thickening_rate specified: values set as zero'); end @@ -74,13 +74,13 @@ md.balancethickness.spcthickness=NaN*ones(md.mesh.numberofvertices,1); md.damage.spcdamage=NaN*ones(md.mesh.numberofvertices,1); -if (length(md.initialization.temperature)==md.mesh.numberofvertices), +if (length(md.initialization.temperature)==md.mesh.numberofvertices) md.thermal.spctemperature=NaN*ones(md.mesh.numberofvertices,1); - if isprop(md.mesh,'vertexonsurface'), + if isprop(md.mesh,'vertexonsurface') pos=find(md.mesh.vertexonsurface); md.thermal.spctemperature(pos)=md.initialization.temperature(pos); %impose observed temperature on surface end - if (length(md.basalforcings.geothermalflux)~=md.mesh.numberofvertices), + if (length(md.basalforcings.geothermalflux)~=md.mesh.numberofvertices) md.basalforcings.geothermalflux=zeros(md.mesh.numberofvertices,1); end else diff --git a/src/m/boundaryconditions/SetMarineIceSheetBC.m b/src/m/boundaryconditions/SetMarineIceSheetBC.m index 18a6928f6..7b2175933 100644 --- a/src/m/boundaryconditions/SetMarineIceSheetBC.m +++ b/src/m/boundaryconditions/SetMarineIceSheetBC.m @@ -16,16 +16,16 @@ % See also: SETICESHELFBC, SETMARINEICESHEETBC %node on Dirichlet (boundary and ~icefront) -if nargin==2, +if nargin==2 %User provided Front.exp, use it icefrontfile=varargin{1}; if ~exist(icefrontfile) error(['SetMarineIceSheetBC error message: ice front file ' icefrontfile ' not found']); end [path,name,ext]=fileparts(icefrontfile); - if strcmp(ext,'.shp'), + if strcmp(ext,'.shp') contours=shpread(icefrontfile); - elseif strcmp(ext,'.exp'), + elseif strcmp(ext,'.exp') contours=expread(icefrontfile); end incontour=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,contours,'node',2); @@ -38,7 +38,7 @@ vertexonicefront=double(md.mesh.vertexonboundary & vertexonfloatingice); end pos=find(md.mesh.vertexonboundary & ~vertexonicefront); -if isempty(pos), +if isempty(pos) disp('Warning: SetMarineIceSheetBC.m: ice front all around the glacier, no dirichlet applied') end md.stressbalance.spcvx=NaN*ones(md.mesh.numberofvertices,1); @@ -51,9 +51,9 @@ md.mask.ice_levelset(find(vertexonicefront))=0; %First find segments that are not completely on the front -if strcmp(elementtype(md.mesh),'Penta'), +if strcmp(elementtype(md.mesh),'Penta') numbernodesfront=4; -elseif strcmp(elementtype(md.mesh),'Tria'), +elseif strcmp(elementtype(md.mesh),'Tria') numbernodesfront=2; else error('mesh type not supported yet'); @@ -84,7 +84,7 @@ md.basalforcings = initialize(md.basalforcings,md); %Deal with other boundary conditions -if isnan(md.balancethickness.thickening_rate), +if isnan(md.balancethickness.thickening_rate) md.balancethickness.thickening_rate=zeros(md.mesh.numberofvertices,1); disp(' no balancethickness.thickening_rate specified: values set as zero'); end @@ -93,13 +93,13 @@ md.balancethickness.spcthickness=NaN*ones(md.mesh.numberofvertices,1); md.damage.spcdamage=NaN*ones(md.mesh.numberofvertices,1); -if (length(md.initialization.temperature)==md.mesh.numberofvertices), +if (length(md.initialization.temperature)==md.mesh.numberofvertices) md.thermal.spctemperature=NaN*ones(md.mesh.numberofvertices,1); - if isprop(md.mesh,'vertexonsurface'), + if isprop(md.mesh,'vertexonsurface') pos=find(md.mesh.vertexonsurface); md.thermal.spctemperature(pos)=md.initialization.temperature(pos); %impose observed temperature on surface end - if (length(md.basalforcings.geothermalflux)~=md.mesh.numberofvertices), + if (length(md.basalforcings.geothermalflux)~=md.mesh.numberofvertices) md.basalforcings.geothermalflux=zeros(md.mesh.numberofvertices,1); md.basalforcings.geothermalflux(find(md.mask.ocean_levelset>0.))=50.*10.^-3; %50mW/m2 end diff --git a/src/m/boundaryconditions/getlovenumbers.m b/src/m/boundaryconditions/getlovenumbers.m index 6a38dde64..e00bb433a 100644 --- a/src/m/boundaryconditions/getlovenumbers.m +++ b/src/m/boundaryconditions/getlovenumbers.m @@ -10042,31 +10042,31 @@ love_numbers(maxdeg+2:end,:)=[]; %retrive right type: - if strcmpi(type,'loadingverticaldisplacement'), + if strcmpi(type,'loadingverticaldisplacement') series=love_numbers(:,1); - elseif strcmpi(type,'loadinggravitationalpotential'), + elseif strcmpi(type,'loadinggravitationalpotential') series=love_numbers(:,2); - elseif strcmpi(type,'loadinghorizontaldisplacement'), + elseif strcmpi(type,'loadinghorizontaldisplacement') series=love_numbers(:,3); - elseif strcmpi(type,'tidalverticaldisplacement'), + elseif strcmpi(type,'tidalverticaldisplacement') series=love_numbers(:,4); - elseif strcmpi(type,'tidalgravitationalpotential'), + elseif strcmpi(type,'tidalgravitationalpotential') series=love_numbers(:,5); - elseif strcmpi(type,'tidalhorizontaldisplacement'), + elseif strcmpi(type,'tidalhorizontaldisplacement') series=love_numbers(:,6); else error(['love_numbers error message: unknown type:' type]); end % choose degree 1 term for CF reference system - if strcmpi(frame,'CM'), + if strcmpi(frame,'CM') return; elseif strcmpi(frame,'CF'), % from Blewitt, 2003, JGR - if strcmpi(type,'loadingverticaldisplacement'), + if strcmpi(type,'loadingverticaldisplacement') series(2,1) = -0.269; - elseif strcmpi(type,'loadinggravitationalpotential'), + elseif strcmpi(type,'loadinggravitationalpotential') series(2,1) = 0.021; - elseif strcmpi(type,'loadinghorizontaldisplacement'), + elseif strcmpi(type,'loadinghorizontaldisplacement') series(2,1) = 0.134; end else diff --git a/src/m/boundaryconditions/love_numbers.m b/src/m/boundaryconditions/love_numbers.m index fabc44061..214f414c5 100644 --- a/src/m/boundaryconditions/love_numbers.m +++ b/src/m/boundaryconditions/love_numbers.m @@ -10041,31 +10041,31 @@ love_numbers(maxdeg+2:end,:)=[]; %retrive right type: - if strcmpi(type,'loadingverticaldisplacement'), + if strcmpi(type,'loadingverticaldisplacement') series=love_numbers(:,1); - elseif strcmpi(type,'loadinggravitationalpotential'), + elseif strcmpi(type,'loadinggravitationalpotential') series=love_numbers(:,2); - elseif strcmpi(type,'loadinghorizontaldisplacement'), + elseif strcmpi(type,'loadinghorizontaldisplacement') series=love_numbers(:,3); - elseif strcmpi(type,'tidalverticaldisplacement'), + elseif strcmpi(type,'tidalverticaldisplacement') series=love_numbers(:,4); - elseif strcmpi(type,'tidalgravitationalpotential'), + elseif strcmpi(type,'tidalgravitationalpotential') series=love_numbers(:,5); - elseif strcmpi(type,'tidalhorizontaldisplacement'), + elseif strcmpi(type,'tidalhorizontaldisplacement') series=love_numbers(:,6); else error(['love_numbers error message: unknow type:' type]); end % choose degree 1 term for CF reference system - if strcmpi(frame,'CM'), + if strcmpi(frame,'CM') return; elseif strcmpi(frame,'CF'), % from Blewitt, 2003, JGR - if strcmpi(type,'loadingverticaldisplacement'), + if strcmpi(type,'loadingverticaldisplacement') series(2,1) = -0.269; - elseif strcmpi(type,'loadinggravitationalpotential'), + elseif strcmpi(type,'loadinggravitationalpotential') series(2,1) = 0.021; - elseif strcmpi(type,'loadinghorizontaldisplacement'), + elseif strcmpi(type,'loadinghorizontaldisplacement') series(2,1) = 0.134; end else diff --git a/src/m/classes/SMBarma.m b/src/m/classes/SMBarma.m index 54520250c..67c012660 100755 --- a/src/m/classes/SMBarma.m +++ b/src/m/classes/SMBarma.m @@ -68,7 +68,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) nbas = md.smb.num_basins; nprm = md.smb.num_params; nbrk = md.smb.num_breaks; @@ -265,7 +265,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBcomponents.m b/src/m/classes/SMBcomponents.m index 32be0b0ce..7974fceb2 100644 --- a/src/m/classes/SMBcomponents.m +++ b/src/m/classes/SMBcomponents.m @@ -63,12 +63,12 @@ function disp(self) % {{{ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.accumulation','timeseries',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.runoff','timeseries',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.evaporation','timeseries',1,'NaN',1,'Inf',1); end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) md = checkfield(md,'fieldname','smb.accumulation','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.runoff','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.evaporation','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); @@ -90,7 +90,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBd18opdd.m b/src/m/classes/SMBd18opdd.m index ec6453627..45f851ba8 100644 --- a/src/m/classes/SMBd18opdd.m +++ b/src/m/classes/SMBd18opdd.m @@ -57,11 +57,11 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.s0p), + if isnan(self.s0p) self.s0p=zeros(md.mesh.numberofvertices,1); disp(' no SMBd18opdd.s0p specified: values set as zero'); end - if isnan(self.s0t), + if isnan(self.s0t) self.s0t=zeros(md.mesh.numberofvertices,1); disp(' no SMBd18opdd.s0t specified: values set as zero'); end @@ -83,7 +83,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.desfac','<=',1,'numel',1); md = checkfield(md,'fieldname','smb.s0p','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','smb.s0t','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); @@ -197,7 +197,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBdebrisEvatt.m b/src/m/classes/SMBdebrisEvatt.m index 1fbacaf76..fe21e9c36 100644 --- a/src/m/classes/SMBdebrisEvatt.m +++ b/src/m/classes/SMBdebrisEvatt.m @@ -54,10 +54,10 @@ self.airhumidity=project3d(md,'vector',self.airhumidity,'type','node'); self.temperature_anomaly=project3d(md,'vector',self.temperature_anomaly,'type','node'); self.precipitation_anomaly=project3d(md,'vector',self.precipitation_anomaly,'type','node'); - self.dsradiation_anomaly=project3d(md,'vector',self.temperature_anomaly,'type','node'); - self.dlradiation_anomaly=project3d(md,'vector',self.temperature_anomaly,'type','node'); - self.windspeed_anomaly=project3d(md,'vector',self.temperature_anomaly,'type','node'); - self.airhumidity_anomaly=project3d(md,'vector',self.temperature_anomaly,'type','node'); + self.dsradiation_anomaly=project3d(md,'vector',self.dsradiation_anomaly,'type','node'); + self.dlradiation_anomaly=project3d(md,'vector',self.dlradiation_anomaly,'type','node'); + self.windspeed_anomaly=project3d(md,'vector',self.windspeed_anomaly,'type','node'); + self.airhumidity_anomaly=project3d(md,'vector',self.airhumidity_anomaly,'type','node'); self.s0t=project3d(md,'vector',self.s0t,'type','node'); self.snowheight=project3d(md,'vector',self.snowheight,'type','node'); @@ -68,7 +68,7 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.s0t), + if isnan(self.s0t) self.s0t=zeros(md.mesh.numberofvertices,1); disp(' no SMBdebrisEvatt.s0t specified: values set as zero'); end @@ -95,7 +95,7 @@ if (strcmp(solution,'TransientSolution') & md.transient.issmb == 0), return; end - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.temperature','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 365]); md = checkfield(md,'fieldname','smb.precipitation','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 365]); md = checkfield(md,'fieldname','smb.dsradiation','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 365]); @@ -193,7 +193,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBdebrisML.m b/src/m/classes/SMBdebrisML.m index bf96af29d..c26c92f06 100644 --- a/src/m/classes/SMBdebrisML.m +++ b/src/m/classes/SMBdebrisML.m @@ -19,7 +19,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -62,7 +62,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBemulator.m b/src/m/classes/SMBemulator.m new file mode 100644 index 000000000..bd8461db9 --- /dev/null +++ b/src/m/classes/SMBemulator.m @@ -0,0 +1,133 @@ +%SMBemulator Class definition +% +% Usage: +% SMBemulator=SMBemulator(); + +classdef SMBemulator + properties (SetAccess=public) + + mass_balance = NaN; + elev = NaN; + al = NaN; + st = NaN; + tt = NaN; + swd = NaN; + lwd = NaN; + swu = NaN; + lwu = NaN; + shf = NaN; + lhf = NaN; + steps_per_step = 1; + requested_outputs = {}; + averaging = 0; + module_dir = ''; + pt_name = ''; + py_name = ''; + end + methods + function self = SMBemulator(varargin) % {{{ + switch nargin + case 0 + self=setdefaultparameters(self); + otherwise + error('constructor not supported'); + end + end % }}} + function self = extrude(self,md) % {{{ + self.mass_balance=project3d(md,'vector',self.mass_balance,'type','node'); + self.al=project3d(md,'vector',self.al,'type','node'); + self.st=project3d(md,'vector',self.st,'type','node'); + self.tt=project3d(md,'vector',self.tt,'type','node'); + self.swd=project3d(md,'vector',self.swd,'type','node'); + self.lwd=project3d(md,'vector',self.lwd,'type','node'); + self.swu=project3d(md,'vector',self.swu,'type','node'); + self.lwu=project3d(md,'vector',self.lwu,'type','node'); + self.shf=project3d(md,'vector',self.shf,'type','node'); + self.lhf=project3d(md,'vector',self.lhf,'type','node'); + end % }}} + function list = defaultoutputs(self,md) % {{{ + list = {'SmbMassBalance'}; + end % }}} + function self = initialize(self,md) % {{{ + if isnan(self.mass_balance) + self.mass_balance=zeros(md.mesh.numberofvertices,1); + disp(' no smb.mass_balance specified: values set as zero'); + end + end % }}} + function self = setdefaultparameters(self) % {{{ + self.requested_outputs={'default'}; + end % }}} + function md = checkconsistency(self,md,solution,analyses) % {{{ + if (strcmp(solution,'TransientSolution') & md.transient.issmb == 0), return; end + if ismember('MasstransportAnalysis',analyses) + md = checkfield(md,'fieldname','smb.mass_balance','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.elev','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.al','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.st','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.tt','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.swd','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.lwd','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.swu','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.lwu','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.shf','timeseries',1,'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.lhf','timeseries',1,'NaN',1,'Inf',1); + end + md = checkfield(md,'fieldname','smb.steps_per_step','>=',1,'numel',[1]); + md = checkfield(md,'fieldname','smb.requested_outputs','stringrow',1); + md = checkfield(md,'fieldname','smb.averaging','numel',[1],'values',[0 1 2]); + md = checkfield(md,'fieldname','smb.module_dir','filepath',1); + md = checkfield(md,'fieldname','smb.py_name','string',1); + md = checkfield(md,'fieldname','smb.pt_name','string',1); + end % }}} + function disp(self) % {{{ + disp(sprintf('\n smb emulator based on MAR-IA :')); + fielddisplay(self, 'mass_balance', 'surface mass balance for validation purpose [kg/m^2/day]'); + fielddisplay(self, 'elev', 'surface elevation for validation purpose'); + fielddisplay(self, 'al', 'albedo'); + fielddisplay(self, 'st', 'surface temperature'); + fielddisplay(self, 'tt', 'two meter air temperature'); + fielddisplay(self, 'swd', 'short wave radiation down'); + fielddisplay(self, 'lwd', 'long wave radiation down'); + fielddisplay(self, 'swu', 'short wave radiation up'); + fielddisplay(self, 'lwu', 'long wave radiation up'); + fielddisplay(self, 'shf', 'sensible heat flux'); + fielddisplay(self, 'lhf', 'latent heat flux'); + fielddisplay(self, 'steps_per_step', 'number of smb steps per time step'); + fielddisplay(self,'requested_outputs','additional outputs requested'); + fielddisplay(self,'averaging','averaging methods from short to long steps'); + fielddisplay(self,'module_dir', 'directory of the emulator module'); + fielddisplay(self,'pt_name', 'name of the checkpoint file for pre-trained ML model'); + fielddisplay(self,'py_name', 'name of the python file that defines ML architecture'); + end % }}} + function marshall(self,prefix,md,fid) % {{{ + yts = md.constants.yts; + WriteData(fid,prefix,'name','md.smb.model','data',20,'format','Integer'); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','mass_balance','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); % double check units + WriteData(fid,prefix,'object',self,'class','smb','fieldname','elev','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); % unit of elev? + WriteData(fid,prefix,'object',self,'class','smb','fieldname','al','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','st','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','tt','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','swd','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','lwd','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','swu','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','lwu','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','shf','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','lhf','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',yts); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','module_dir','format','String') + WriteData(fid,prefix,'object',self,'class','smb','fieldname','pt_name','format','String'); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','py_name','format','String'); + WriteData(fid,prefix,'object',self,'fieldname','steps_per_step','format','Integer'); + WriteData(fid,prefix,'object',self,'fieldname','averaging','format','Integer'); + + %process requested outputs + outputs = self.requested_outputs; + pos = find(ismember(outputs,'default')); + if ~isempty(pos) + outputs(pos) = []; %remove 'default' from outputs + outputs = [outputs defaultoutputs(self,md)]; %add defaults + end + WriteData(fid,prefix,'data',outputs,'name','md.smb.requested_outputs','format','StringArray'); + + end % }}} + end +end diff --git a/src/m/classes/SMBforcing.m b/src/m/classes/SMBforcing.m index e24669aeb..f01b4eaf3 100644 --- a/src/m/classes/SMBforcing.m +++ b/src/m/classes/SMBforcing.m @@ -21,7 +21,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -45,10 +45,10 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ if (strcmp(solution,'TransientSolution') & md.transient.issmb == 0), return; end - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.mass_balance','timeseries',1,'NaN',1,'Inf',1); end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) md = checkfield(md,'fieldname','smb.mass_balance','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); end md = checkfield(md,'fieldname','smb.steps_per_step','>=',1,'numel',[1]); @@ -77,7 +77,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBgemb.m b/src/m/classes/SMBgemb.m index e5f8863e9..d550c6d5b 100644 --- a/src/m/classes/SMBgemb.m +++ b/src/m/classes/SMBgemb.m @@ -24,6 +24,8 @@ isconstrainsurfaceT = 0; isdeltaLWup = 0; ismappedforcing = 0; + ismappingusingneighbors = 0; + ismappingneighborxy = 0; isprecipforcingremapped = 0; iscompressedforcing = 0; @@ -49,8 +51,21 @@ dulwrfValue = NaN; %Delta with which to perturb the long wave radiation upwards. Use if isdeltaLWup is true. mappedforcingpoint = NaN; %Mapping of which forcing point will map to each mesh element (integer). Of size number of elements. %Use if ismappedforcing is true. + mappedforcingneighbors = NaN; %Which forcing points should be used, along with mappedforcing point, to interpolate + %forcing between points, onto the element grid. Should be the the next three nearest points after + %mappedforcingpoint, which together surround the element in question. Used with the ismappedforcing + %and the ismappingusingneighbors options set true (integer). Size number of elements x 3. + mappedforcingelevation = NaN; %The elevation of each mapped forcing location (m above sea level). Of size number - %of forcing points. Use if ismappedforcing is true. + %of forcing points. Use if ismappedforcing is true. + lat_mappedforcing = NaN; %The latitude coordinate of each mapped forcing location (m). Of size number + %of forcing points. Use if ismappedforcing and ismappingusingneighbors are true. + lon_mappedforcing = NaN; %The longitude coordinate of each mapped forcing location (m). Of size number + %of forcing points. Use if ismappedforcing and ismappingusingneighbors are true. + x_mappedforcing = NaN; %The x coordinate of each mapped forcing location (m), in same projection as the mesh. Of size number + %of forcing points. Use if ismappedforcing and ismappingusingneighbors are true. + y_mappedforcing = NaN; %The y coordinate of each mapped forcing location (m), in same projection as the mesh. Of size number + %of forcing points. Use if ismappedforcing and ismappingusingneighbors are true. mappedforcingprecipscaling = NaN; %Map of a precipitation multiplier correction term to be applied to forcing P. %Of size number of elements. Use if ismappedforcing is true and isprecipforcingremapped is true. % (Default value is 1) @@ -83,8 +98,9 @@ eIdx = NaN; %method for calculating emissivity (default is 1) % 0: direct input from teValue parameter, no use of teThresh - % 1: default value of 1, in areas with grain radius below teThresh - % 2: default value of 1, in areas with grain radius below teThresh and areas of dry snow (not bare ice or wet) at the surface + % 1: default value of teDefault, in areas with grain radius below teThresh + % 2: default value of teDefault, in areas with grain radius below teThresh and areas of dry snow (not bare ice or wet) at the surface + % 3: default value of teDefault, in areas with grain radius below teThresh and areas of dry snow (no melt) at the surface tcIdx = NaN; %method for calculating thermal conductivity (default is 1) % 1: after Sturm et al, 1997 @@ -139,6 +155,7 @@ teThresh = NaN; %Apply eIdx method to all areas with grain radii above this value (mm), %or else apply direct input value from teValue, allowing emissivity to be altered. %Default value is a effective grain radius of 10 mm. + teDefault = NaN; %Default value for thermal emissivity. %densities: InitDensityScaling= NaN; %initial scaling factor multiplying the density of ice, which describes the density of the snowpack. @@ -182,6 +199,8 @@ function disp(self) % {{{ fielddisplay(self,'isconstrainsurfaceT','constrain surface temperatures to air temperature, turn off EC and surface flux contribution to surface temperature change (default false)'); fielddisplay(self,'isdeltaLWup','set to true to invoke a bias in the long wave upward spatially, specified by dulwrfValue (default false)'); fielddisplay(self,'ismappedforcing','set to true if forcing grid does not match model mesh, mapping specified by mappedforcingpoint (default false)'); + fielddisplay(self,'ismappingusingneighbors','set to true if forcing when ismappedforcing is true, forcing should be interpolated instead of using mappedforcingpoint value (default false). With this method, the forcing to be remapped onto the model mesh should be on a regular (equal degree interval for lat/lon OR equal length interval for x/y) grid, so that the 4 forcing neighbors form a rectangle. NOTE: if using this option with ismappingneighborxy as false, make sure that the model mesh uses the default Polar projections of Northern Hemisphere EPSG:3413 and Southern Hemisphere EPSG:3031.'); + fielddisplay(self,'ismappingneighborxy','set to true if ismappingusingneighbors is true, and the forcing regular grid is x,y instead of lat,lon (default false)'); fielddisplay(self,'isprecipforcingremapped','set to true if ismappedforcing is true and precip should be downscaled from native grid (Default value is true)'); fielddisplay(self,'iscompressedforcing','set to true to compress the input matrices when writing to binary (default false)'); fielddisplay(self,'Ta','2 m air temperature, in Kelvin'); @@ -217,17 +236,24 @@ function disp(self) % {{{ fielddisplay(self,'dulwrfValue','Specified bias to be applied to the outward long wave radiation at every element (W/m-2, +upward)'); fielddisplay(self,'teValue','Outward longwave radiation thermal emissivity forcing at every element (default in code is 1)'); fielddisplay(self,'teThresh',{'Apply eIdx method to all areas with effective grain radius above this value (mm),','or else apply direct input value from teValue, allowing emissivity to be altered.'}); + fielddisplay(self,'teDefault',{'Default value for thermal emissivity.'}); fielddisplay(self,'eIdx',{'method for calculating emissivity (default is 1)',... '0: direct input from teValue parameter, no use of teThresh',... - '1: default value of 1, in areas with grain radius below teThresh',... - '2: default value of 1, in areas with grain radius below teThresh and areas of dry snow (not bare ice or wet) at the surface'}); + '1: default value of teDefault, in areas with grain radius below teThresh',... + '2: default value of teDefault, in areas with grain radius below teThresh and areas of dry snow (not bare ice or wet) at the surface',... + '3: default value of teDefault, in areas with grain radius below teThresh and areas of dry snow (no melt) at the surface'}); fielddisplay(self,'tcIdx',{'method for calculating thermal conductivity (default is 1)',... '1: after Sturm et al, 1997',... '2: after Calonne et al., 2011'}); fielddisplay(self,'mappedforcingpoint','Mapping of which forcing point will map to each mesh element for ismappedforcing option (integer). Size number of elements.'); + fielddisplay(self,'mappedforcingneighbors','Which forcing points should be used, along with mappedforcing point, to interpolate forcing between points, onto the element grid. Should be the the next three nearest points after mappedforcingpoint, which together surround the element in question. Used with the ismappedforcing and the ismappingusingneighbors options set true (integer). Set all columns to 0 to use nearest neighbor for that element. Size number of elements x 3.'); fielddisplay(self,'mappedforcingelevation','The elevation of each mapped forcing location (m above sea level) for ismappedforcing option. Size number of forcing points.'); + fielddisplay(self,'lat_mappedforcing','The latitude coordinate of each mapped forcing location (degrees N) for ismappedforcing and ismappingusingneighbors options, if ismappingneighborxy=false. Size number of forcing points. NOTE that currently the GEMB mapping option (ismappedforcing with ismappingusingneighors is true and ismappingneighborxy is false) assumes that the model mesh uses the default Polar projections of Northern Hemisphere EPSG:3413 or Southern Hemisphere EPSG:3031.'); + fielddisplay(self,'lon_mappedforcing','The longitude coordinate of each mapped forcing location (degrees E) for ismappedforcing and ismappingusingneighbors options, if ismappingneighborxy=false. Size number of forcing points. NOTE that currently the GEMB mapping option (ismappedforcing with ismappingusingneighbors is true and ismappingneighborxy is false) assumes that the model mesh uses the default Polar projections of Northern Hemisphere EPSG:3413 or Southern Hemisphere EPSG:3031.'); + fielddisplay(self,'x_mappedforcing','The x coordinate of each mapped forcing location (m in the same projection as the model mesh) for ismappedforcing and ismappingusingneighbors options, if ismappingneighborxy=true. Size number of forcing points.'); + fielddisplay(self,'y_mappedforcing','The y coordinate of each mapped forcing location (m in the same projection as the model mesh) for ismappedforcing and ismappingusingneighbors options, if ismappingneighborxy=true. Size number of forcing points.'); fielddisplay(self,'mappedforcingprecipscaling','Map of a precipitation multiplier correction term to be applied to forcing P when ismappedforcing and isprecipforcingremapped options are true. Size number of elements. (Default is 1)'); fielddisplay(self,'lapseTaValue','Temperature lapse rate of each mapped forcing location, if forcing has different grid and should be remapped for ismappedforcing option. (Default value is -0.006 K m-1, vector of mapping points)'); fielddisplay(self,'lapsedlwrfValue','Longwave down lapse rate of each mapped forcing location, if forcing has different grid and should be remapped for ismappedforcing option. Where set to 0, dlwrf will scale with a constant effective atmospheric emissivity. (Default value is -0.032 W m-2 m-1, vector of mapping points)'); @@ -380,6 +406,8 @@ function disp(self) % {{{ self.isconstrainsurfaceT=0; self.isdeltaLWup=0; self.ismappedforcing=0; + self.ismappingusingneighbors=0; + self.ismappingneighborxy=0; self.isprecipforcingremapped=1; self.iscompressedforcing=0; @@ -411,6 +439,7 @@ function disp(self) % {{{ self.K = 7; self.adThresh = 1023; self.teThresh = 10; + self.teDefault = 1; self.teValue = ones(mesh.numberofelements,1); self.aValue = self.aSnow*ones(mesh.numberofelements,1); @@ -454,6 +483,8 @@ function disp(self) % {{{ md = checkfield(md,'fieldname','smb.isconstrainsurfaceT','values',[0 1]); md = checkfield(md,'fieldname','smb.isdeltaLWup','values',[0 1]); md = checkfield(md,'fieldname','smb.ismappedforcing','values',[0 1]); + md = checkfield(md,'fieldname','smb.ismappingusingneighbors','values',[0 1]); + md = checkfield(md,'fieldname','smb.ismappingneighborxy','values',[0 1]); md = checkfield(md,'fieldname','smb.isprecipforcingremapped','values',[0 1]); md = checkfield(md,'fieldname','smb.iscompressedforcing','values',[0 1]); @@ -486,6 +517,28 @@ function disp(self) % {{{ end md = checkfield(md,'fieldname','smb.lapseTaValue','size',[sizeta(1)-1 1],'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.lapsedlwrfValue','size',[sizeta(1)-1 1], 'NaN',1,'Inf',1); + + if (self.ismappingusingneighbors) + md = checkfield(md,'fieldname','smb.mappedforcingneighbors','size',[md.mesh.numberofelements 3],'NaN',1,'Inf',1,'>=',0); + if (self.ismappingneighborxy) + md = checkfield(md,'fieldname','smb.x_mappedforcing','size',[sizeta(1)-1 1],'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.y_mappedforcing','size',[sizeta(1)-1 1],'NaN',1,'Inf',1); + else + md = checkfield(md,'fieldname','smb.lat_mappedforcing','size',[sizeta(1)-1 1],'NaN',1,'Inf',1); + md = checkfield(md,'fieldname','smb.lon_mappedforcing','size',[sizeta(1)-1 1],'NaN',1,'Inf',1); + end + if prod(size(self.mappedforcingneighbors))==1 + disp('WARNING:smb.mappedforcingneighbors is now a matrix of size [number_of_elements 3]. If ismappingusingneighbors is true, this matrix mush specify the mapping points, that along with mappedforcing point, surround each element.'); + end + end + + if (self.ismappingusingneighbors) + md = checkfield(md,'fieldname','smb.mappedforcingneighbors','size',[md.mesh.numberofelements 3],'NaN',1,'Inf',1,'>=',0); + if prod(size(self.mappedforcingneighbors))==1 + disp('WARNING:smb.mappedforcingneighbors is now a matrix of size [number_of_elements 3]. If ismappingusingneighbors is true, this matrix mush specify the mapping points, that along with mappedforcing point, surround each element.'); + end + end + if (self.isprecipforcingremapped) md = checkfield(md,'fieldname','smb.mappedforcingprecipscaling','size',[md.mesh.numberofelements 1],'NaN',1,'Inf',1,'>',0); if prod(size(self.mappedforcingprecipscaling))==1 @@ -495,7 +548,7 @@ function disp(self) % {{{ end md = checkfield(md,'fieldname','smb.aIdx','NaN',1,'Inf',1,'values',[0,1,2,3,4]); - md = checkfield(md,'fieldname','smb.eIdx','NaN',1,'Inf',1,'values',[0,1,2]); + md = checkfield(md,'fieldname','smb.eIdx','NaN',1,'Inf',1,'values',[0,1,2,3]); md = checkfield(md,'fieldname','smb.tcIdx','NaN',1,'Inf',1,'values',[1,2]); md = checkfield(md,'fieldname','smb.swIdx','NaN',1,'Inf',1,'values',[0,1]); md = checkfield(md,'fieldname','smb.denIdx','NaN',1,'Inf',1,'values',[1,2,3,4,5,6,7]); @@ -510,6 +563,7 @@ function disp(self) % {{{ md = checkfield(md,'fieldname','smb.ThermoDeltaTScaling','NaN',1,'Inf',1,'>=',0,'<=',1); md = checkfield(md,'fieldname','smb.adThresh','NaN',1,'Inf',1,'>=',0); md = checkfield(md,'fieldname','smb.teThresh','NaN',1,'Inf',1,'>=',0); + md = checkfield(md,'fieldname','smb.teDefault','NaN',1,'Inf',1,'>=',0,'<=',1.1); md = checkfield(md,'fieldname','smb.aValue','timeseries',1,'NaN',1,'Inf',1,'>=',0,'<=',1); switch self.aIdx, @@ -532,7 +586,7 @@ function disp(self) % {{{ %check zTop is < local thickness: he=sum(md.geometry.thickness(md.mesh.elements),2)/size(md.mesh.elements,2); - if any(he=',1,'numel',[1]); @@ -557,6 +611,8 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','smb','fieldname','isconstrainsurfaceT','format','Boolean'); WriteData(fid,prefix,'object',self,'class','smb','fieldname','isdeltaLWup','format','Boolean'); WriteData(fid,prefix,'object',self,'class','smb','fieldname','ismappedforcing','format','Boolean'); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','ismappingusingneighbors','format','Boolean'); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','ismappingneighborxy','format','Boolean'); WriteData(fid,prefix,'object',self,'class','smb','fieldname','isprecipforcingremapped','format','Boolean'); if self.iscompressedforcing @@ -603,6 +659,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','smb','fieldname','K','format','Double'); WriteData(fid,prefix,'object',self,'class','smb','fieldname','adThresh','format','Double'); WriteData(fid,prefix,'object',self,'class','smb','fieldname','teThresh','format','Double'); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','teDefault','format','Double'); WriteData(fid,prefix,'object',self,'class','smb','fieldname','aValue','format','DoubleMat','mattype',2,'timeserieslength',md.mesh.numberofelements+1,'yts',md.constants.yts); WriteData(fid,prefix,'object',self,'class','smb','fieldname','teValue','format','DoubleMat','mattype',2,'timeserieslength',md.mesh.numberofelements+1,'yts',md.constants.yts); @@ -632,6 +689,17 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','smb','fieldname','mappedforcingelevation','format','DoubleMat','mattype',3); WriteData(fid,prefix,'object',self,'class','smb','fieldname','lapseTaValue','format','DoubleMat','mattype',3); WriteData(fid,prefix,'object',self,'class','smb','fieldname','lapsedlwrfValue','format','DoubleMat','mattype',3); + if (self.ismappingusingneighbors) + if (self.ismappingneighborxy) + WriteData(fid,prefix,'object',self,'class','smb','fieldname','x_mappedforcing','format','DoubleMat','mattype',3); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','y_mappedforcing','format','DoubleMat','mattype',3); + else + WriteData(fid,prefix,'object',self,'class','smb','fieldname','lat_mappedforcing','format','DoubleMat','mattype',3); + WriteData(fid,prefix,'object',self,'class','smb','fieldname','lon_mappedforcing','format','DoubleMat','mattype',3); + end + WriteData(fid,prefix,'object',self,'class','smb','fieldname','mappedforcingneighbors','format','DoubleMat','mattype',3); + end + if (self.isprecipforcingremapped) WriteData(fid,prefix,'object',self,'class','smb','fieldname','mappedforcingprecipscaling','format','DoubleMat','mattype',2); end @@ -689,7 +757,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBgemb.py b/src/m/classes/SMBgemb.py index 3ad480cf3..d5e792a20 100644 --- a/src/m/classes/SMBgemb.py +++ b/src/m/classes/SMBgemb.py @@ -32,6 +32,8 @@ def __init__(self, *args): # {{{ self.isconstrainsurfaceT = 0 self.isdeltaLWup = 0 self.ismappedforcing = 0 + self.ismappingusingneighbors = 0 + self.ismappingneighborxy = 0 self.isprecipforcingremapped = 0 self.iscompressedforcing = 0 @@ -55,7 +57,20 @@ def __init__(self, *args): # {{{ self.teValue = np.nan # Outward longwave radiation thermal emissivity forcing at every element (default in code is 1), Used only if eIdx== 0, or effective grain radius exceeds teThresh self.dulwrfValue = np.nan #Delta with which to perturb the long wave radiation upwards. Use if isdeltaLWup is true. self.mappedforcingpoint = np.nan #Mapping of which forcing point will map to each mesh element (integer). Of size number of elements. Use if ismappedforcing is true. + self.mappedforcingneighbors = np.nan #Which forcing points should be used, along with mappedforcing point, to interpolate + # forcing between points, onto the element grid. Should be the the next three nearest points after + # mappedforcingpoint, which together surround the element in question. Used with the ismappedforcing + # and the ismappingusingneighbors options set true (integer). Size number of elements x 3.'); + self.mappedforcingelevation = np.nan #The elevation of each mapped forcing location (m above sea level). Of size number of forcing points. Use if ismappedforcing is true. + self.lat_mappedforcing = np.nan #The latitude coordinate of each mapped forcing location (m). Of size number + # of forcing points. Use if ismappedforcing and ismappingusingneighbors are true. + self.lon_mappedforcing = np.nan #The longitude coordinate of each mapped forcing location (m). Of size number + # of forcing points. Use if ismappedforcing and ismappingusingneighbors are true. + self.x_mappedforcing = np.nan #The x coordinate of each mapped forcing location (m), in same projection as the mesh. Of size number + # of forcing points. Use if ismappedforcing and ismappingusingneighbors are true. + self.y_mappedforcing = np.nan #The y coordinate of each mapped forcing location (m), in same projection as the mesh. Of size number + # of forcing points. Use if ismappedforcing and ismappingusingneighbors are true self.mappedforcingprecipscaling = np.nan #Map of a precipitation multiplier correction term to be applied to forcing P. Of size number of elements. Use if ismappedforcing is true and isprecipforcingremapped is true. (Default value is 1) self.lapseTaValue = np.nan #Temperature lapse rate if forcing has different grid and should be remapped. Use if ismappedforcing is true. (Default value is -0.006 K m-1., vector of mapping points) @@ -84,8 +99,9 @@ def __init__(self, *args): # {{{ self.eIdx = np.nan #method for calculating emissivity (default is 1) # 0: direct input from teValue parameter, no use of teThresh - # 1: default value of 1, in areas with grain radius below teThresh - # 2: default value of 1, in areas with grain radius below teThresh and areas of dry snow (not bare ice or wet) at the surface + # 1: default value of teDefault, in areas with grain radius below teThresh + # 2: default value of teDefault, in areas with grain radius below teThresh and areas of dry snow (not bare ice or wet) at the surface + # 3: default value of teDefault, in areas with grain radius below teThresh and areas of dry snow (no melt) at the surface self.tcIdx = np.nan #method for calculating thermal conductivity (default is 1) # 1: after Sturm et al, 1997 @@ -137,9 +153,10 @@ def __init__(self, *args): # {{{ self.adThresh = np.nan # Apply aIdx method to all areas with densities below this value, # or else apply direct input value from aValue, allowing albedo to be altered. # Default value is rho water (1023 kg m-3). - teThresh = np.nan #Apply eIdx method to all areas with grain radii above this value (mm), + self.teThresh = np.nan #Apply eIdx method to all areas with grain radii above this value (mm), #or else apply direct input value from teValue, allowing emissivity to be altered. #Default value is a effective grain radius of 10 mm. + self.teDefault = np.nan #Default value for thermal emissivity. # Densities self.InitDensityScaling = np.nan # initial scaling factor multiplying the density of ice, which describes the density of the snowpack. @@ -181,6 +198,8 @@ def __repr__(self): # {{{ s += '{}\n'.format(fielddisplay(self, 'isconstrainsurfaceT', 'constrain surface temperatures to air temperature, turn off EC and surface flux contribution to surface temperature change (default false)')) s += '{}\n'.format(fielddisplay(self, 'isdeltaLWup', 'set to true to invoke a bias in the long wave upward spatially, specified by dulwrfValue (default false)')) s += '{}\n'.format(fielddisplay(self,'ismappedforcing','set to true if forcing grid does not match model mesh, mapping specified by mappedforcingpoint (default false)')) + s += '{}\n'.format(fielddisplay(self,'ismappingusingneighbors','set to true if forcing when ismappedforcing is true, forcing should be interpolated instead of using mappedforcingpoint value (default false). With this method, the forcing to be remapped onto the model mesh should be on a regular (equal degree interval for lat/lon OR equal length interval for x/y) grid, so that the 4 forcing neighbors form a rectangle. NOTE: if using this option with ismappingneighborxy as false, make sure that the model mesh uses the default Polar projections of Northern Hemisphere EPSG:3413 and Southern Hemisphere EPSG:3031.')) + s += '{}\n'.format(fielddisplay(self,'ismappingneighborxy','set to true if ismappingusingneighbors is true, and the forcing regular grid is x,y instead of lat,lon (default false)')) s += '{}\n'.format(fielddisplay(self,'isprecipforcingremapped','set to true if ismappedforcing is true and precip should be downscaled from native grid (Default value is true)')) s += '{}\n'.format(fielddisplay(self,'iscompressedforcing','set to true to compress the input matrices when writing to binary (default false)')) s += '{}\n'.format(fielddisplay(self, 'Ta', '2 m air temperature, in Kelvin')) @@ -216,16 +235,23 @@ def __repr__(self): # {{{ s += '{}\n'.format(fielddisplay(self, 'dulwrfValue', 'Specified bias to be applied to the outward long wave radiation at every element (W/m-2, +upward)')) s += '{}\n'.format(fielddisplay(self, 'teValue', 'Outward longwave radiation thermal emissivity forcing at every element (default in code is 1)')) s += '{}\n'.format(fielddisplay(self, 'teThresh', ['Apply eIdx method to all areas with effective grain radius above this value (mm),', 'or else apply direct input value from teValue, allowing emissivity to be altered.'])) + s += '{}\n'.format(fielddisplay(self, 'teDefault', ['Default value for thermal emissivity.'])) s += '{}\n'.format(fielddisplay(self, 'eIdx', ['method for calculating emissivity (default is 1)', '0: direct input from teValue parameter, no use of teThresh', - '1: default value of 1, in areas with grain radius below teThresh', - '2: default value of 1, in areas with grain radius below teThresh and areas of dry snow (not bare ice or wet) at the surface'])) + '1: default value of teDefault, in areas with grain radius below teThresh', + '2: default value of teDefault, in areas with grain radius below teThresh and areas of dry snow (not bare ice or wet) at the surface', + '3: default value of teDefault, in areas with grain radius below teThresh and areas of dry snow (no melt) at the surface'])) s += '{}\n'.format(fielddisplay(self, 'tcIdx', ['method for calculating thermal conductivity (default is 1)', '1: after Sturm et al, 1997', '2: after Calonne et al., 2011'])) s += '{}\n'.format(fielddisplay(self,'mappedforcingpoint','Mapping of which forcing point will map to each mesh element for ismappedforcing option (integer). Size number of elements.')) + s += '{}\n'.format(fielddisplay(self,'mappedforcingneighbors','Which forcing points should be used, along with mappedforcing point, to interpolate forcing between points, onto the element grid. Should be the the next three nearest points after mappedforcingpoint, which together surround the element in question. Used with the ismappedforcing and the ismappingusingneighbors options set true (integer). Set all columns to 0 to use nearest neighbor for that element. Size number of elements x 3.')) s += '{}\n'.format(fielddisplay(self,'mappedforcingelevation','The elevation of each mapped forcing location (m above sea level) for ismappedforcing option. Size number of forcing points.')) + s += '{}\n'.format(fielddisplay(self,'lat_mappedforcing','The latitude coordinate of each mapped forcing location (degrees N) for ismappedforcing and ismappingusingneighbors options, if ismappingneighborxy=false. Size number of forcing points. NOTE that currently the GEMB mapping option (ismappedforcing with ismappingusingneighbors is true and ismappingneighborxy is false) assumes that the model mesh uses the default Polar projections of Northern Hemisphere EPSG:3413 or Southern Hemisphere EPSG:3031.')) + s += '{}\n'.format(fielddisplay(self,'lon_mappedforcing','The longitude coordinate of each mapped forcing location (degrees E) for ismappedforcing and ismappingusingneighbors options, if ismappingneighborxy=false. Size number of forcing points. NOTE that currently the GEMB mapping option (ismappedforcing with ismappingusingneighbors is true and ismappingneighborxy is false) assumes that the model mesh uses the default Polar projections of Northern Hemisphere EPSG:3413 or Southern Hemisphere EPSG:3031.')) + s += '{}\n'.format(fielddisplay(self,'x_mappedforcing','The x coordinate of each mapped forcing location (m in the same projection as the model mesh) for ismappedforcing and ismappingusingneighbors options, if ismappingneighborxy=true. Size number of forcing points.')) + s += '{}\n'.format(fielddisplay(self,'y_mappedforcing','The y coordinate of each mapped forcing location (m in the same projection as the model mesh) for ismappedforcing and ismappingusingneighbors options, if ismappingneighborxy=true. Size number of forcing points.')) s += '{}\n'.format(fielddisplay(self,'mappedforcingprecipscaling','Map of a precipitation multiplier correction term to be applied to forcing P when ismappedforcing and isprecipforcingremapped options are true. Size number of elements. (Default is 1)')) s += '{}\n'.format(fielddisplay(self,'lapseTaValue','Temperature lapse rate of each mapped forcing location, if forcing has different grid and should be remapped for ismappedforcing option. (Default value is -0.006 K m-1, vector of mapping points)')) s += '{}\n'.format(fielddisplay(self,'lapsedlwrfValue','Longwave down lapse rate of each mapped forcing location if forcing has different grid and should be remapped for ismappedforcing option. Where set to 0, dlwrf will scale with a constant effective atmospheric emissivity. (Default value is -0.032 W m-2 m-1., vector of mapping points)')) @@ -355,6 +381,8 @@ def setdefaultparameters(self, mesh): # {{{ self.isconstrainsurfaceT = 0 self.isdeltaLWup = 0 self.ismappedforcing = 0 + self.ismappingusingneighbors = 0 + self.ismappingneighborxy = 0 self.isprecipforcingremapped = 1 self.iscompressedforcing = 0 @@ -386,6 +414,7 @@ def setdefaultparameters(self, mesh): # {{{ self.K = 7 self.adThresh = 1023 self.teThresh = 10 + self.teDefault = 1 self.teValue = np.ones((mesh.numberofelements,)) self.aValue = self.aSnow * np.ones(mesh.numberofelements,) @@ -432,6 +461,8 @@ def checkconsistency(self, md, solution, analyses): # {{{ md = checkfield(md, 'fieldname', 'smb.isdeltaLWup', 'values',[0, 1]) md = checkfield(md, 'fieldname', 'smb.isconstrainsurfaceT', 'values', [0, 1]) md = checkfield(md, 'fieldname', 'smb.ismappedforcing', 'values',[0, 1]) + md = checkfield(md, 'fieldname', 'smb.ismappingusingneighbors', 'values',[0, 1]) + md = checkfield(md, 'fieldname', 'smb.ismappingneighborxy','values',[0, 1]) md = checkfield(md, 'fieldname', 'smb.isprecipforcingremapped', 'values',[0, 1]) md = checkfield(md, 'fieldname', 'smb.iscompressedforcing', 'values',[0, 1]) @@ -462,15 +493,28 @@ def checkconsistency(self, md, solution, analyses): # {{{ if np.prod(np.shape(self.lapsedlwrfValue))==1: print("WARNING:smb.lapsedlwrfValue is now a vector of mapped elements. Set to md.smb.lapsedlwrfValue*np.ones(np.shape(md.smb.mappedforcingelevation)).") - md = checkfield(md, 'fieldname', 'smb.lapseTaValue', 'size',[sizeta[0]-1],'NaN',1,'Inf',1); - md = checkfield(md, 'fieldname', 'smb.lapsedlwrfValue', 'size',[sizeta[0]-1], 'NaN',1,'Inf',1); + md = checkfield(md, 'fieldname', 'smb.lapseTaValue', 'size',[sizeta[0]-1],'NaN',1,'Inf',1) + md = checkfield(md, 'fieldname', 'smb.lapsedlwrfValue', 'size',[sizeta[0]-1], 'NaN',1,'Inf',1) + + if self.ismappingusingneighbors: + md = checkfield(md,'fieldname','smb.mappedforcingneighbors','size',[md.mesh.numberofelements, 3],'NaN',1,'Inf',1,'>=',0) + if self.ismappingneighborxy: + md = checkfield(md,'fieldname','smb.x_mappedforcing','size',[sizeta[0]-1],'NaN',1,'Inf',1) + md = checkfield(md,'fieldname','smb.y_mappedforcing','size',[sizeta[0]-1],'NaN',1,'Inf',1) + else: + md = checkfield(md,'fieldname','smb.lat_mappedforcing','size',[sizeta[0]-1],'NaN',1,'Inf',1) + md = checkfield(md,'fieldname','smb.lon_mappedforcing','size',[sizeta[0]-1],'NaN',1,'Inf',1) + + if np.prod(np.shape(self.mappedforcingneighbors))==1: + print("WARNING:smb.mappedforcingneighbors is now a matrix of size [number_of_elements 3]. If ismappingusingneighbors is true, this matrix mush specify the mapping points, that along with mappedforcing point, surround each element.") + if self.isprecipforcingremapped: md = checkfield(md,'fieldname','smb.mappedforcingprecipscaling','size',[md.mesh.numberofelements],'NaN',1,'Inf',1,'>',0) if np.prod(np.shape(self.mappedforcingprecipscaling))==1: print("WARNING:smb.mappedforcingprecipscaling is now a vector of mapped elements. Set to md.smb.mappedforcingprecipscaling*ones(size(md.smb.mappedforcingelevation)).") md = checkfield(md, 'fieldname', 'smb.aIdx', 'NaN', 1, 'Inf', 1, 'values', [0, 1, 2, 3, 4]) - md = checkfield(md, 'fieldname', 'smb.eIdx', 'NaN', 1, 'Inf', 1, 'values', [0, 1, 2]) + md = checkfield(md, 'fieldname', 'smb.eIdx', 'NaN', 1, 'Inf', 1, 'values', [0, 1, 2, 3]) md = checkfield(md, 'fieldname', 'smb.tcIdx', 'NaN', 1, 'Inf', 1, 'values', [1, 2]) md = checkfield(md, 'fieldname', 'smb.swIdx', 'NaN', 1, 'Inf', 1, 'values', [0, 1]) md = checkfield(md, 'fieldname', 'smb.denIdx', 'NaN', 1, 'Inf', 1, 'values', [1, 2, 3, 4, 5, 6, 7]) @@ -485,6 +529,7 @@ def checkconsistency(self, md, solution, analyses): # {{{ md = checkfield(md, 'fieldname', 'smb.ThermoDeltaTScaling', 'NaN', 1, 'Inf', 1, '> = ', 0, '< = ', 1) md = checkfield(md, 'fieldname', 'smb.adThresh', 'NaN', 1, 'Inf', 1, '>=', 0) md = checkfield(md, 'fieldname', 'smb.teThresh', 'NaN', 1, 'Inf',1,'>=',0) + md = checkfield(md, 'fieldname', 'smb.teDefault', 'NaN', 1, 'Inf',1,'>=',0,'<=',1.1) md = checkfield(md, 'fieldname', 'smb.aValue', 'timeseries', 1, 'NaN', 1, 'Inf', 1, '>=', 0, '<=', 1) if isinstance(self.aIdx, (list, type(np.array([1, 2])))) and (self.aIdx == [1, 2] or (1 in self.aIdx and 2 in self.aIdx)): @@ -528,6 +573,8 @@ def marshall(self, prefix, md, fid): # {{{ WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'isconstrainsurfaceT', 'format', 'Boolean') WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'isdeltaLWup', 'format', 'Boolean') WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'ismappedforcing', 'format', 'Boolean') + WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'ismappingusingneighbors', 'format', 'Boolean') + WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'ismappingneighborxy', 'format', 'Boolean') WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'isprecipforcingremapped', 'format', 'Boolean') if self.iscompressedforcing: @@ -573,6 +620,7 @@ def marshall(self, prefix, md, fid): # {{{ WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'K', 'format', 'Double') WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'adThresh', 'format', 'Double') WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'teThresh', 'format', 'Double') + WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'teDefault', 'format', 'Double') WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'aValue', 'format', 'DoubleMat', 'mattype', 2, 'timeserieslength', md.mesh.numberofelements + 1, 'yts', yts) WriteData(fid, prefix, 'object', self, 'class', 'smb', 'fieldname', 'teValue', 'format', 'DoubleMat', 'mattype', 2, 'timeserieslength', md.mesh.numberofelements + 1, 'yts', yts) @@ -602,6 +650,15 @@ def marshall(self, prefix, md, fid): # {{{ WriteData(fid,prefix,'object',self,'class','smb','fieldname','mappedforcingelevation','format','DoubleMat','mattype',3) WriteData(fid,prefix,'object',self,'class','smb','fieldname','lapseTaValue','format','DoubleMat','mattype',3) WriteData(fid,prefix,'object',self,'class','smb','fieldname','lapsedlwrfValue','format','DoubleMat','mattype',3) + if self.ismappingusingneighbors: + WriteData(fid,prefix,'object',self,'class','smb','fieldname','mappedforcingneighbors','format','DoubleMat','mattype',3) + if self.ismappingneighborxy: + WriteData(fid,prefix,'object',self,'class','smb','fieldname','x_mappedforcing','format','DoubleMat','mattype',3) + WriteData(fid,prefix,'object',self,'class','smb','fieldname','y_mappedforcing','format','DoubleMat','mattype',3) + else: + WriteData(fid,prefix,'object',self,'class','smb','fieldname','lat_mappedforcing','format','DoubleMat','mattype',3) + WriteData(fid,prefix,'object',self,'class','smb','fieldname','lon_mappedforcing','format','DoubleMat','mattype',3) + if self.isprecipforcingremapped: WriteData(fid,prefix,'object',self,'class','smb','fieldname','mappedforcingprecipscaling','format','DoubleMat','mattype',2) diff --git a/src/m/classes/SMBgradients.m b/src/m/classes/SMBgradients.m index 42dbd9a90..838b8bcb4 100644 --- a/src/m/classes/SMBgradients.m +++ b/src/m/classes/SMBgradients.m @@ -43,7 +43,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.href','timeseries',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.smbref','timeseries',1,'NaN',1,'Inf',1); if max(max(abs(md.smb.smbref(1:end-1,:))))<1 @@ -88,7 +88,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBgradientscomponents.m b/src/m/classes/SMBgradientscomponents.m index f02159342..deda280b8 100644 --- a/src/m/classes/SMBgradientscomponents.m +++ b/src/m/classes/SMBgradientscomponents.m @@ -46,7 +46,7 @@ end % }}} function md=checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.accuref','singletimeseries',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.accualti','numel',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.accugrad','singletimeseries',1,'NaN',1,'Inf',1); @@ -92,7 +92,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBgradientsela.m b/src/m/classes/SMBgradientsela.m index dbb12a9e6..3182a5a4b 100644 --- a/src/m/classes/SMBgradientsela.m +++ b/src/m/classes/SMBgradientsela.m @@ -46,7 +46,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.ela','timeseries',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.b_pos','timeseries',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.b_neg','timeseries',1,'NaN',1,'Inf',1); @@ -91,7 +91,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBhenning.m b/src/m/classes/SMBhenning.m index d8bb9d483..a4d2e28ba 100644 --- a/src/m/classes/SMBhenning.m +++ b/src/m/classes/SMBhenning.m @@ -20,7 +20,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -46,10 +46,10 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.smbref','timeseries',1,'NaN',1,'Inf',1); end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) md = checkfield(md,'fieldname','smb.smbref','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); end md = checkfield(md,'fieldname','smb.steps_per_step','>=',1,'numel',[1]); @@ -78,7 +78,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBmeltcomponents.m b/src/m/classes/SMBmeltcomponents.m index c95aedefa..de27c2b6b 100644 --- a/src/m/classes/SMBmeltcomponents.m +++ b/src/m/classes/SMBmeltcomponents.m @@ -68,13 +68,13 @@ function disp(self) % {{{ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.accumulation','timeseries',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.evaporation','timeseries',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.refreeze','timeseries',1,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.melt','timeseries',1,'NaN',1,'Inf',1); end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) md = checkfield(md,'fieldname','smb.accumulation','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.evaporation','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); md = checkfield(md,'fieldname','smb.refreeze','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); @@ -99,7 +99,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBpdd.m b/src/m/classes/SMBpdd.m index 65f442af9..af2d95b4f 100644 --- a/src/m/classes/SMBpdd.m +++ b/src/m/classes/SMBpdd.m @@ -59,11 +59,11 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.s0p), + if isnan(self.s0p) self.s0p=zeros(md.mesh.numberofvertices,1); disp(' no SMBpdd.s0p specified: values set as zero'); end - if isnan(self.s0t), + if isnan(self.s0t) self.s0t=zeros(md.mesh.numberofvertices,1); disp(' no SMBpdd.s0t specified: values set as zero'); end @@ -82,7 +82,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.desfac','<=',1,'numel',1); md = checkfield(md,'fieldname','smb.s0p','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','smb.s0t','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); @@ -210,7 +210,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBpddFast.m b/src/m/classes/SMBpddFast.m index e414650b9..7a05de186 100644 --- a/src/m/classes/SMBpddFast.m +++ b/src/m/classes/SMBpddFast.m @@ -48,23 +48,23 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.s0p), + if isnan(self.s0p) self.s0p=zeros(md.mesh.numberofvertices,1); disp(' no SMBpddFast.s0p specified: values set as zero'); end - if isnan(self.s0t), + if isnan(self.s0t) self.s0t=zeros(md.mesh.numberofvertices,1); disp(' no SMBpddFast.s0t specified: values set as zero'); end - if isnan(self.temperature_anomaly), + if isnan(self.temperature_anomaly) self.temperature_anomaly=zeros(md.mesh.numberofvertices,1); disp(' no SMBpddFast.temperature_anomaly specified: values set as zero'); end - if isnan(self.precipitation_anomaly), + if isnan(self.precipitation_anomaly) self.precipitation_anomaly=ones(md.mesh.numberofvertices,1); disp(' no SMBpddFast.precipitation_anomaly specified: values set as ones'); end - if isnan(self.smb_corr), + if isnan(self.smb_corr) self.smb_corr=zeros(md.mesh.numberofvertices,1); disp(' no SMBpddFast.smb_corr specified: values set as zero'); end @@ -84,7 +84,7 @@ if (strcmp(solution,'TransientSolution') & md.transient.issmb == 0), return; end - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.desfac','<=',1,'numel',1); md = checkfield(md,'fieldname','smb.s0p','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','smb.s0t','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); @@ -148,7 +148,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBpddGCM.m b/src/m/classes/SMBpddGCM.m index 939c9befd..ddfbc757f 100644 --- a/src/m/classes/SMBpddGCM.m +++ b/src/m/classes/SMBpddGCM.m @@ -40,15 +40,15 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.enhance_factor), + if isnan(self.enhance_factor) self.enhance_factor=zeros(md.mesh.numberofvertices,1); disp(' no SMBpddGCM.enhance_factor specified: values set as zero'); end - if isnan(self.lapserates), + if isnan(self.lapserates) self.lapserates=0.0065*ones(md.mesh.numberofvertices,1); disp(' no SMBpddGCM.lapserates specified: values set as 0.0065 °C/m'); end - if isnan(self.ref_surf), + if isnan(self.ref_surf) self.ref_surf = 0*ones(md.mesh.numberofvertices,1); disp(' no SMBpddGCM.ref_surf specified: values set as sea-level 0 m'); end @@ -62,7 +62,7 @@ if (strcmp(solution,'TransientSolution') & md.transient.issmb == 0), return; end - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.x_grid','NaN',1,'Inf',1,'size',[NaN 1]); md = checkfield(md,'fieldname','smb.y_grid','NaN',1,'Inf',1,'size',[NaN 1]); Nx = numel(self.x_grid); @@ -111,7 +111,7 @@ function marshall(self,prefix,md,fid) % {{{ Ny = numel(self.y_grid); % everything in the bin is in SI - if isnan(self.ref_surf), + if isnan(self.ref_surf) % prepare ref surface for the GCM grid, using the initial md.geometry.surface grid_surf = InterpFromMeshToGrid(md.mesh.elements,md.mesh.x,md.mesh.y,md.geometry.surface,self.x_grid,self.y_grid,NaN); self.ref_surf = InterpFromGridToMesh(self.x_grid,self.y_grid,grid_surf,md.mesh.x,md.mesh.y,0); @@ -134,7 +134,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/SMBpddSicopolis.m b/src/m/classes/SMBpddSicopolis.m index 5799758d7..9d6b14a73 100644 --- a/src/m/classes/SMBpddSicopolis.m +++ b/src/m/classes/SMBpddSicopolis.m @@ -46,23 +46,23 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.s0p), + if isnan(self.s0p) self.s0p=zeros(md.mesh.numberofvertices,1); disp(' no SMBpddSicopolis.s0p specified: values set as zero'); end - if isnan(self.s0t), + if isnan(self.s0t) self.s0t=zeros(md.mesh.numberofvertices,1); disp(' no SMBpddSicopolis.s0t specified: values set as zero'); end - if isnan(self.temperature_anomaly), + if isnan(self.temperature_anomaly) self.temperature_anomaly=zeros(md.mesh.numberofvertices,1); disp(' no SMBpddSicopolis.temperature_anomaly specified: values set as zero'); end - if isnan(self.precipitation_anomaly), + if isnan(self.precipitation_anomaly) self.precipitation_anomaly=ones(md.mesh.numberofvertices,1); disp(' no SMBpddSicopolis.precipitation_anomaly specified: values set as ones'); end - if isnan(self.smb_corr), + if isnan(self.smb_corr) self.smb_corr=zeros(md.mesh.numberofvertices,1); disp(' no SMBpddSicopolis.smb_corr specified: values set as zero'); end @@ -82,7 +82,7 @@ if (strcmp(solution,'TransientSolution') & md.transient.issmb == 0), return; end - if ismember('MasstransportAnalysis',analyses), + if ismember('MasstransportAnalysis',analyses) md = checkfield(md,'fieldname','smb.desfac','<=',1,'numel',1); md = checkfield(md,'fieldname','smb.s0p','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','smb.s0t','>=',0,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); @@ -147,7 +147,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/additionalsolidearthsolution.m b/src/m/classes/additionalsolidearthsolution.m index a09d877aa..8587b84a5 100644 --- a/src/m/classes/additionalsolidearthsolution.m +++ b/src/m/classes/additionalsolidearthsolution.m @@ -20,7 +20,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.solidearth.settings.isgrd==0), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.solidearth.settings.isgrd==0) error('additionalsolidearthsolution checkconsistency error message: need to run GRD solution if you are supplying a GRD additional pattern solution'); end self.checkconsistency@solidearthsolution(md,solution,analyses); diff --git a/src/m/classes/adm1qn3inversion.m b/src/m/classes/adm1qn3inversion.m index 4847fd1f2..428d8f9ca 100644 --- a/src/m/classes/adm1qn3inversion.m +++ b/src/m/classes/adm1qn3inversion.m @@ -48,15 +48,11 @@ %Early return if ~self.iscontrol, return; end - if ~IssmConfig('_HAVE_M1QN3_'), - md = checkmessage(md,['M1QN3 has not been installed, ISSM needs to be reconfigured and recompiled with M1QN3']); - end - md = checkfield(md,'fieldname','inversion.iscontrol','values',[0 1]); md = checkfield(md,'fieldname','inversion.maxsteps','numel',1,'>=',0); md = checkfield(md,'fieldname','inversion.maxiter','numel',1,'>=',0); md = checkfield(md,'fieldname','inversion.dxmin','numel',1,'>',0); - md = checkfield(md,'fieldname','inversion.dfmin_frac','numel',1,'>=',0., '<=', 1.); + md = checkfield(md,'fieldname','inversion.dfmin_frac','numel',1,'>=',0., '<=', 1.); md = checkfield(md,'fieldname','inversion.gttol','numel',1,'>',0); end % }}} @@ -66,7 +62,7 @@ function disp(self) % {{{ fielddisplay(self,'maxsteps','maximum number of iterations (gradient computation)'); fielddisplay(self,'maxiter','maximum number of Function evaluation (forward run)'); fielddisplay(self,'dxmin','convergence criterion: two points less than dxmin from eachother (sup-norm) are considered identical'); - fielddisplay(self,'dfmin_frac','expected reduction of J during the first step (e.g., 0.3=30% reduction in cost function)'); + fielddisplay(self,'dfmin_frac','expected reduction of J during the first step (e.g., 0.3=30% reduction in cost function)'); fielddisplay(self,'gttol','convergence criterion: ||g(X)||/||g(X0)|| (g(X0): gradient at initial guess X0)'); end % }}} function marshall(self,prefix,md,fid) % {{{ @@ -79,7 +75,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxsteps','format','Integer'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxiter','format','Integer'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','dxmin','format','Double'); - WriteData(fid,prefix,'object',self,'class','inversion','fieldname','dfmin_frac','format','Double'); + WriteData(fid,prefix,'object',self,'class','inversion','fieldname','dfmin_frac','format','Double'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','gttol','format','Double'); end % }}} @@ -89,7 +85,7 @@ function savemodeljs(self,fid,modelname) % {{{ writejsdouble(fid,[modelname '.inversion.maxsteps'],self.maxsteps); writejsdouble(fid,[modelname '.inversion.maxiter'],self.maxiter); writejsdouble(fid,[modelname '.inversion.dxmin'],self.dxmin); - writejsdouble(fid,[modelname '.inversion.dfmin_frac'],self.dfmin_frac); + writejsdouble(fid,[modelname '.inversion.dfmin_frac'],self.dfmin_frac); writejsdouble(fid,[modelname '.inversion.gttol'],self.gttol); end % }}} diff --git a/src/m/classes/age.m b/src/m/classes/age.m index a122cd27d..397848abd 100644 --- a/src/m/classes/age.m +++ b/src/m/classes/age.m @@ -16,7 +16,7 @@ % old fields must be recovered (make sure they are in the deprecated % model properties) - if verLessThan('matlab','7.9'), + if verLessThan('matlab','7.9') disp('Warning: your matlab version is old and there is a risk that load does not work correctly'); disp(' if the model is not loaded correctly, rename temporarily loadobj so that matlab does not use it'); @@ -45,7 +45,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -98,7 +98,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/amr.m b/src/m/classes/amr.m index e9d5782c8..d386bb259 100644 --- a/src/m/classes/amr.m +++ b/src/m/classes/amr.m @@ -30,7 +30,7 @@ % This function is directly called by matlab when a model object is % loaded. Update old properties here - if verLessThan('matlab','7.9'), + if verLessThan('matlab','7.9') disp('Warning: your matlab version is old and there is a risk that load does not work correctly'); disp(' if the model is not loaded correctly, rename temporarily loadobj so that matlab does not use it'); @@ -43,7 +43,7 @@ end %2017 September 15th - if isstruct(self), + if isstruct(self) disp('WARNING: updating amr. Now the default is amr with bamg'); disp(' some old fields were not converted'); disp(' see the new fields typing md.amr and modify them properly'); diff --git a/src/m/classes/autodiff.m b/src/m/classes/autodiff.m index 87e9a5f7e..ec897630f 100644 --- a/src/m/classes/autodiff.m +++ b/src/m/classes/autodiff.m @@ -65,7 +65,7 @@ md = checkfield(md,'fieldname','autodiff.enablePreaccumulation','>=',0); %go through our dependents and independents and check consistency: - for i=1:numel(self.dependents), + for i=1:numel(self.dependents) dep=self.dependents{i}; if isempty(dep) md = checkmessage(md,['md.autodiff.dependents{' num2str(i) '} is empty!']); @@ -73,7 +73,7 @@ md=checkconsistency(dep,md,solution,analyses); end end - for i=1:numel(self.independents), + for i=1:numel(self.independents) indep=self.independents{i}; if isempty(indep) md = checkmessage(md,['md.autodiff.independents{' num2str(i) '} is empty!']); @@ -132,7 +132,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'data',num_dependent_objects,'name','md.autodiff.num_dependent_objects','format','Integer'); if(num_dependent_objects) names={}; - for i=1:num_dependent_objects, + for i=1:num_dependent_objects dep=self.dependents{i}; names{i}=dep.name; end @@ -154,13 +154,13 @@ function marshall(self,prefix,md,fid) % {{{ %if driver is fos_forward, build inde if strcmpi(self.driver,'fos_forward') index=0; - for i=1:num_independent_objects, + for i=1:num_independent_objects indep=self.independents{i}; - if ~isnan(indep.fos_forward_index), + if ~isnan(indep.fos_forward_index) index=index+indep.fos_forward_index; break; else - if strcmpi(indep.type,'scalar'), + if strcmpi(indep.type,'scalar') index=index+1; else index=index+indep.nods; @@ -172,12 +172,12 @@ function marshall(self,prefix,md,fid) % {{{ end %if driver is fos_reverse, build index: - if strcmpi(self.driver,'fos_reverse'), + if strcmpi(self.driver,'fos_reverse') index=0; - for i=1:num_dependent_objects, + for i=1:num_dependent_objects dep=self.dependents{i}; - if ~isnan(dep.fos_reverse_index), + if ~isnan(dep.fos_reverse_index) index=index+dep.fos_reverse_index; break; else @@ -189,16 +189,16 @@ function marshall(self,prefix,md,fid) % {{{ end %if driver is fov_forward, build indices - if strcmpi(self.driver,'fov_forward'), + if strcmpi(self.driver,'fov_forward') indices=0; - for i=1:num_independent_objects, + for i=1:num_independent_objects indep=self.independents{i}; - if ~isempty(indep.fos_forward_index), + if ~isempty(indep.fos_forward_index) indices=indices+indep.fov_forward_indices; break; else - if strcmpi(indep.type,'scalar'), + if strcmpi(indep.type,'scalar') indices=indices+1; else indices=indices+indep.nods; @@ -211,13 +211,13 @@ function marshall(self,prefix,md,fid) % {{{ %deal with mass fluxes mass_flux_segments=cell(0,1); - for i=1:num_dependent_objects, + for i=1:num_dependent_objects dep=self.dependents{i}; - if strcmpi(dep.name,'MassFlux'), + if strcmpi(dep.name,'MassFlux') mass_flux_segments{end+1,1}=dep.segments; end end - if ~isempty(mass_flux_segments), + if ~isempty(mass_flux_segments) WriteData(fid,prefix,'data',mass_flux_segments,'name','md.autodiff.mass_flux_segments','format','MatArray'); flag=true; else @@ -235,10 +235,10 @@ function marshall(self,prefix,md,fid) % {{{ % mode as described in the Section 4 and Section 5. % - if length(self.driver)<=3, + if length(self.driver)<=3 keep=false; %there is no "_reverse" string within the driver string: else - if strncmpi(self.driver(4:end),'_reverse',8), + if strncmpi(self.driver(4:end),'_reverse',8) keep=true; else keep=false; @@ -249,7 +249,7 @@ function marshall(self,prefix,md,fid) % {{{ end % }}} function savemodeljs(self,fid,modelname) % {{{ %do nothing for now - if self.isautodiff, + if self.isautodiff error('autodiff savemodeljs error message: not implemented yet!'); end end % }}} diff --git a/src/m/classes/bamggeom.m b/src/m/classes/bamggeom.m index d41afcda1..f5374c40b 100644 --- a/src/m/classes/bamggeom.m +++ b/src/m/classes/bamggeom.m @@ -34,7 +34,7 @@ fields=fieldnames(object); for i=1:length(fields) field=fields{i}; - if ismember(field,properties('bamggeom')), + if ismember(field,properties('bamggeom')) bg.(field)=object.(field); end end diff --git a/src/m/classes/bamgmesh.m b/src/m/classes/bamgmesh.m index 3397203cc..57a78e0d5 100644 --- a/src/m/classes/bamgmesh.m +++ b/src/m/classes/bamgmesh.m @@ -38,7 +38,7 @@ fields=fieldnames(object); for i=1:length(fields) field=fields{i}; - if ismember(field,properties('bamgmesh')), + if ismember(field,properties('bamgmesh')) bg.(field)=object.(field); end end diff --git a/src/m/classes/basalforcings.m b/src/m/classes/basalforcings.m index 1a692db1b..0b9ead727 100644 --- a/src/m/classes/basalforcings.m +++ b/src/m/classes/basalforcings.m @@ -38,12 +38,12 @@ function disp(self) % {{{ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end - if isnan(self.floatingice_melting_rate), + if isnan(self.floatingice_melting_rate) self.floatingice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.floatingice_melting_rate specified: values set as zero'); end @@ -54,15 +54,15 @@ function disp(self) % {{{ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0), + if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'Inf',1,'timeseries',1); end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end - if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0), + if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.geothermalflux','NaN',1,'Inf',1,'timeseries',1,'>=',0); diff --git a/src/m/classes/basalforcingsbeckmanngoosse.m b/src/m/classes/basalforcingsbeckmanngoosse.m index d791ee429..8151171c2 100644 --- a/src/m/classes/basalforcingsbeckmanngoosse.m +++ b/src/m/classes/basalforcingsbeckmanngoosse.m @@ -39,15 +39,15 @@ function createxml(self,fid) % {{{ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end - if isnan(self.ocean_temp), + if isnan(self.ocean_temp) self.ocean_temp=-1.7*ones(md.mesh.numberofvertices,1); disp(' no basalforcings.ocean_temp specified: values set as -1.7degC'); end - if isnan(self.ocean_salinity), + if isnan(self.ocean_salinity) self.ocean_salinity=35.0*ones(md.mesh.numberofvertices,1); disp(' no basalforcings.ocean_salinity specified: values set as 35 psu'); end @@ -79,7 +79,7 @@ function createxml(self,fid) % {{{ end - if ismember('MasstransportAnalysis',analyses) & ~(solution=='TransientSolution' & md.transient.ismasstransport==0), + if ismember('MasstransportAnalysis',analyses) & ~(solution=='TransientSolution' & md.transient.ismasstransport==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.meltrate_factor','>=',0,'size','universal','NaN',1,'Inf',1); md = checkfield(md,'fieldname','basalforcings.isthermalforcing','values',[0 1]); @@ -90,7 +90,7 @@ function createxml(self,fid) % {{{ md = checkfield(md,'fieldname','basalforcings.ocean_thermalforcing','NaN',1,'Inf',1,'timeseries',1); end end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','basalforcings.meltrate_factor','>=',0,'size','universal','NaN',1,'Inf',1); md = checkfield(md,'fieldname','basalforcings.isthermalforcing','values',[0 1]); @@ -101,7 +101,7 @@ function createxml(self,fid) % {{{ md = checkfield(md,'fieldname','basalforcings.ocean_thermalforcing','NaN',1,'Inf',1,'timeseries',1); end end - if ismember('ThermalAnalysis',analyses) & ~(solution=='TransientSolution' & md.transient.isthermal==0), + if ismember('ThermalAnalysis',analyses) & ~(solution=='TransientSolution' & md.transient.isthermal==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.geothermalflux','NaN',1,'Inf',1,'timeseries',1,'>=',0); md = checkfield(md,'fieldname','basalforcings.meltrate_factor','>=',0,'size','universal','NaN',1,'Inf',1); diff --git a/src/m/classes/basalforcingsismip6.m b/src/m/classes/basalforcingsismip6.m index af70695f2..ef264d393 100644 --- a/src/m/classes/basalforcingsismip6.m +++ b/src/m/classes/basalforcingsismip6.m @@ -38,11 +38,11 @@ end end % }}} function self = initialize(self,md) % {{{ - if self.gamma_0 == 0, + if self.gamma_0 == 0 self.gamma_0 = 14477; disp(' no basalforcings.gamma_0 specified: value set to 14477 m/yr'); end - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end @@ -62,7 +62,7 @@ md = checkfield(md,'fieldname','basalforcings.islocal','values',[0 1]); md = checkfield(md,'fieldname','basalforcings.geothermalflux','NaN',1,'Inf',1,'>=',0,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); - if length(md.basalforcings.melt_anomaly)>1, + if length(md.basalforcings.melt_anomaly)>1 md = checkfield(md,'fieldname','basalforcings.melt_anomaly','NaN',1,'Inf',1,'timeseries',1); end diff --git a/src/m/classes/basalforcingsismip7.m b/src/m/classes/basalforcingsismip7.m index 4e0bfe16e..5437cad5d 100644 --- a/src/m/classes/basalforcingsismip7.m +++ b/src/m/classes/basalforcingsismip7.m @@ -13,6 +13,9 @@ salinity = NaN; tf = NaN; tf_depths = NaN; + delta_t = NaN; + + islocal = 0; geothermalflux = NaN; groundedice_melting_rate = NaN; @@ -39,7 +42,7 @@ end % }}} function self = initialize(self,md) % {{{ %Update fixed-coriolis parameter - if isnan(md.mesh.lat) | isempty(md.mesh.lat), + if isnan(md.mesh.lat) | isempty(md.mesh.lat) disp(' no md.mesh.lat specified.'); if md.mesh.epsg == 3031 % For Antarctica [lat, lon] = xy2ll(md.mesh.x,md.mesh.y,-1); @@ -54,23 +57,26 @@ omega=7.2921e-5; %angular velocity of the Earth (rad/s) self.coriolis_f=2*omega*sin(lat/180*pi); - if self.gamma == 0, + if self.gamma == 0 self.gamma = 14477; disp(' no basalforcings.gamma specified: value set to 14477 m/yr'); end - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end end % }}} function self = setdefaultparameters(self) % {{{ - self.gamma = 0.0; % ? + self.gamma = 0.0; % ? + self.islocal = 1; end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ md = checkfield(md,'fieldname','basalforcings.num_basins','numel',1,'NaN',1,'Inf',1,'>',0); md = checkfield(md,'fieldname','basalforcings.basin_id','Inf',1,'>=',0,'<=',md.basalforcings.num_basins,'size',[md.mesh.numberofelements 1]); + md = checkfield(md,'fieldname','basalforcings.islocal','values',[0 1]); + md = checkfield(md,'fieldname','basalforcings.delta_t','NaN',1,'Inf',1,'numel',md.basalforcings.num_basins,'size',[1,md.basalforcings.num_basins]); md = checkfield(md,'fieldname','basalforcings.gamma','numel',1,'NaN',1,'Inf',1,'>',0); @@ -89,11 +95,13 @@ end % }}} function disp(self) % {{{ disp(sprintf(' ISMIP7 basal melt rate parameterization:')); - fielddisplay(self,'num_basins','[TODO] number of basins the model domain is partitioned into [unitless]'); - fielddisplay(self,'basin_id','[TODO] basin number assigned to each node (unitless)'); + fielddisplay(self,'num_basins','number of basins the model domain is partitioned into [unitless]'); + fielddisplay(self,'basin_id','basin number assigned to each node (unitless)'); fielddisplay(self,'gamma','melt rate coefficient (m/yr)'); fielddisplay(self,'tf_depths','elevation of vertical layers in ocean thermal forcing dataset'); fielddisplay(self,'tf','thermal forcing (ocean temperature minus freezing point) (degrees C)'); + fielddisplay(self,'delta_t','Ocean temperature correction per basin (degrees C)'); + fielddisplay(self,'islocal','[TODO] boolean to use the local version of the ISMIP7 melt rate parameter (default: true)'); fielddisplay(self,'salinity','salinity (psu)'); fielddisplay(self,'coriolis_f','Coriolis parameter (s^-1)'); fielddisplay(self,'geothermalflux','geothermal heat flux (W/m^2)'); @@ -111,6 +119,8 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','coriolis_f','format','DoubleMat','name','md.basalforcings.coriolis_f','mattype',1); WriteData(fid,prefix,'object',self,'fieldname','tf_depths','format','DoubleMat','name','md.basalforcings.tf_depths'); WriteData(fid,prefix,'object',self,'fieldname','tf','format','MatArray','name','md.basalforcings.tf','timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); + WriteData(fid,prefix,'object',self,'fieldname','delta_t','format','DoubleMat','name','md.basalforcings.delta_t','timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); + WriteData(fid,prefix,'object',self,'fieldname','islocal','format','Boolean'); WriteData(fid,prefix,'object',self,'fieldname','salinity','format','MatArray','name','md.basalforcings.salinity','timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); WriteData(fid,prefix,'object',self,'fieldname','geothermalflux','format','DoubleMat','name','md.basalforcings.geothermalflux','mattype',1,'timeserieslength',md.mesh.numberofelements+1,'yts',md.constants.yts); WriteData(fid,prefix,'object',self,'fieldname','groundedice_melting_rate','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); diff --git a/src/m/classes/basalforcingsismip7.py b/src/m/classes/basalforcingsismip7.py index 8caed0655..de7b2e3b3 100644 --- a/src/m/classes/basalforcingsismip7.py +++ b/src/m/classes/basalforcingsismip7.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import numpy as np +from structtoobj import structtoobj from checkfield import checkfield from fielddisplay import fielddisplay from project3d import project3d @@ -23,6 +24,9 @@ def __init__(self,*args): # {{{ self.salinity = np.nan self.tf = np.nan self.tf_depths = np.nan + self.delta_t = np.nan + + self.islocal = 0 self.geothermalflux = np.nan self.groundedice_melting_rate = np.nan @@ -31,21 +35,19 @@ def __init__(self,*args): # {{{ self.setdefaultparameters() elif len(args) == 1: self.setdefaultparameters() - - constructor = args[0] - for field in vars(self).keys(): - if field in constructor.__dict__.keys(): - setattr(self,field,getattr(constructor,field)) + self=structtoobj(self,args[0]) else: raise Exception('constructuor not supported') # }}} def __repr__(self): # {{{ s = ' ISMIP7 basal melt rate parameterization:\n' - s += '{}\n'.format(fielddisplay(self,'num_basins','[TODO] number of basins the model domain is partitioned into [unitless]')) - s += '{}\n'.format(fielddisplay(self,'basin_id','[TODO] basin number assigned to each node (unitless)')) + s += '{}\n'.format(fielddisplay(self,'num_basins','number of basins the model domain is partitioned into [unitless]')) + s += '{}\n'.format(fielddisplay(self,'basin_id','basin number assigned to each node (unitless)')) s += '{}\n'.format(fielddisplay(self,'gamma','melt rate coefficient (m/yr)')) s += '{}\n'.format(fielddisplay(self,'tf_depths','elevation of vertical layers in ocean thermal forcing dataset')) s += '{}\n'.format(fielddisplay(self,'tf','thermal forcing (ocean temperature minus freezing point) (degrees C)')) + s += '{}\n'.format(fielddisplay(self,'delta_t','Ocean temperature correction per basin (degrees C)')) + s += '{}\n'.format(fielddisplay(self,'islocal','[TODO] boolean to use the local version of the ISMIP7 melt rate parameter (default: true)')) s += '{}\n'.format(fielddisplay(self,'salinity','salinity (psu)')) s += '{}\n'.format(fielddisplay(self,'coriolis_f','Coriolis parameter (s^-1)')) s += '{}\n'.format(fielddisplay(self,'geothermalflux','geothermal heat flux (W/m^2)')) @@ -87,12 +89,15 @@ def initialize(self, md): # {{{ # }}} def setdefaultparameters(self): # {{{ self.gamma = 0.0 + self.islocal = 1; return self # }}} def checkconsistency(self, md, solution, analyses): # {{{ md = checkfield(md,'fieldname','basalforcings.num_basins','numel',1,'NaN',1,'Inf',1,'>',0) md = checkfield(md,'fieldname','basalforcings.basin_id','Inf',1,'>=',0,'<=',md.basalforcings.num_basins,'size',[md.mesh.numberofelements, 1]) + md = checkfield(md,'fieldname','basalforcings.islocal','values',[0, 1]); + md = checkfield(md,'fieldname','basalforcings.delta_t','NaN',1,'Inf',1,'numel',md.basalforcings.num_basins,'size',[1,md.basalforcings.num_basins]); md = checkfield(md,'fieldname','basalforcings.gamma','numel',1,'NaN',1,'Inf',1,'>',0) @@ -121,6 +126,8 @@ def marshall(self, prefix, md, fid): # {{{ WriteData(fid,prefix,'object',self,'fieldname','coriolis_f','format','DoubleMat','name','md.basalforcings.coriolis_f','mattype',1) WriteData(fid,prefix,'object',self,'fieldname','tf_depths','format','DoubleMat','name','md.basalforcings.tf_depths') WriteData(fid,prefix,'object',self,'fieldname','tf','format','MatArray','name','md.basalforcings.tf','timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts) + WriteData(fid,prefix,'object',self,'fieldname','delta_t','format','DoubleMat','name','md.basalforcings.delta_t','timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); + WriteData(fid,prefix,'object',self,'fieldname','islocal','format','Boolean'); WriteData(fid,prefix,'object',self,'fieldname','salinity','format','MatArray','name','md.basalforcings.salinity','timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts) WriteData(fid,prefix,'object',self,'fieldname','geothermalflux','format','DoubleMat','name','md.basalforcings.geothermalflux','mattype',1,'timeserieslength',md.mesh.numberofelements+1,'yts',md.constants.yts) WriteData(fid,prefix,'object',self,'fieldname','groundedice_melting_rate','format','DoubleMat','mattype',1,'scale',1./yts,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts) diff --git a/src/m/classes/basalforcingspico.m b/src/m/classes/basalforcingspico.m index 7b8639670..49fa59dd4 100644 --- a/src/m/classes/basalforcingspico.m +++ b/src/m/classes/basalforcingspico.m @@ -34,7 +34,7 @@ end end % }}} function self = initialize(self,md) % {{{ - if isnan(self.maxboxcount), + if isnan(self.maxboxcount) self.maxboxcount = 5; disp(' no maximum number of boxes set, setting value to 5'); end @@ -46,7 +46,7 @@ self.gamma_T = 2e-5; %m/s disp(' no turbulent temperature exchange velocity set, setting value to 2e-5'); end - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end diff --git a/src/m/classes/basin.m b/src/m/classes/basin.m index 079b7237a..bf34263fc 100644 --- a/src/m/classes/basin.m +++ b/src/m/classes/basin.m @@ -20,7 +20,7 @@ function self = basin(varargin) % {{{ self=setdefaultparameters(self); - if nargin>0, + if nargin>0 options=pairoptions(varargin{:}); %recover field values: @@ -29,14 +29,14 @@ self.continent=getfieldvalue(options,'continent',''); %figure out projection string: - if exist(options,'epsg'), - if exist(options,'proj'), + if exist(options,'epsg') + if exist(options,'proj') error(['Error in constructor for basin ' self.name '. Cannot supply epsg and proj at the same time!']); end epsg=getfieldvalue(options,'epsg'); proj=epsg2proj(epsg); %convert to PROJ.4 format - elseif exist(options,'proj'), - if exist(options,'epsg'), + elseif exist(options,'proj') + if exist(options,'epsg') error(['Error in constructor for basin ' self.name '. Cannot supply proj and epsg at the same time!']); end proj=getfieldvalue(options,'proj'); @@ -60,15 +60,15 @@ function disp(self) % {{{ fielddisplay(self,'name','basin name'); fielddisplay(self,'proj','basin projection string (follows PROJ.4 standard)'); fielddisplay(self,'boundaries','list of boundary objects'); - for i=1:length(self.boundaries), + for i=1:length(self.boundaries) disp(sprintf(' boundary #%i: %s',i,self.boundaries{i}.name)); end end % }}} function boolean=isnameany(self,varargin) % {{{ boolean=0; - for i=1:length(varargin), - if strcmpi(self.name,varargin{i}), + for i=1:length(varargin) + if strcmpi(self.name,varargin{i}) boolean=1; break; end @@ -76,8 +76,8 @@ function disp(self) % {{{ end % }}} function boolean=iscontinentany(self,varargin) % {{{ boolean=0; - for i=1:length(varargin), - if strcmpi(self.continent,varargin{i}), + for i=1:length(varargin) + if strcmpi(self.continent,varargin{i}) boolean=1; break; end @@ -90,7 +90,7 @@ function disp(self) % {{{ extension=getfieldvalue(options,'extension',1); [path,name,ext]=fileparts(self.name); - if extension, + if extension output=[name ext]; else output=name; @@ -99,7 +99,7 @@ function disp(self) % {{{ function plot(self,varargin) % {{{ %add option: - for i=1:length(self.boundaries), + for i=1:length(self.boundaries) self.boundaries{i}.plot('proj',self.proj,varargin{:}); end @@ -107,7 +107,7 @@ function plot(self,varargin) % {{{ function plot3d(self,varargin) % {{{ %add option: - for i=1:length(self.boundaries), + for i=1:length(self.boundaries) self.boundaries{i}.plot3d(varargin{:}); end @@ -120,7 +120,7 @@ function plot3d(self,varargin) % {{{ y=[]; %go through boundaries, recover edges and project them in the basin epsg reference frame: - for i=1:length(self.boundaries), + for i=1:length(self.boundaries) boundary=self.boundaries{i}; contour=boundary.edges(); [contour.x,contour.y]=CoordTransform(contour.x,contour.y,boundary.proj,self.proj); @@ -129,7 +129,7 @@ function plot3d(self,varargin) % {{{ end %close the contour: - if x(end)~=x(1) | y(end)~=y(1), + if x(end)~=x(1) | y(end)~=y(1) x(end+1)=x(1); y(end+1)=y(1); end @@ -143,18 +143,18 @@ function checkconsistency(self,varargin) % {{{ options=pairoptions(varargin{:}); %figure out if two boundaries are identical: - for i=1:length(self.boundaries), + for i=1:length(self.boundaries) namei=self.boundaries{i}.shpfilename; - for j=i+1:length(self.boundaries), + for j=i+1:length(self.boundaries) namej=self.boundaries{j}.shpfilename; - if strcmpi(namei,namej), + if strcmpi(namei,namej) error(['Basin ' self.name ' has two identical boundaries named ' namei ]); end end end %go through boundaries and check their consistency: - for i=1:length(self.boundaries), + for i=1:length(self.boundaries) boundary=self.boundaries{i}; boundary.checkconsistency(); end @@ -172,12 +172,12 @@ function contourplot(self,varargin) % {{{ inshapefile=getfieldvalue(options,'shapefile'); outputshapefile=getfieldvalue(options,'outputshapefile',''); - if (exist(options,'epsgshapefile') & exist(options,'projshapefile')), + if (exist(options,'epsgshapefile') & exist(options,'projshapefile')) error('Basin shapefilecrop error message: cannot specify epsgshapefile and projshapefile at the same time'); end - if exist(options,'epsgshapefile'), + if exist(options,'epsgshapefile') projshapefile=epsg2proj(getfieldvalue(options,'epsgshapefile')); - elseif exist(options,'projshapefile'), + elseif exist(options,'projshapefile') projshapefile=getfieldvalue(options,'projshapefile'); else error('Basin shapefilecrop error message: epsgshapefile or projshapefile should be specified'); @@ -186,18 +186,18 @@ function contourplot(self,varargin) % {{{ %create list of contours that have critical length > threshold (in lat,long): contours=shpread(inshapefile); llist=[]; - for i=1:length(contours), + for i=1:length(contours) contour=contours(i); carea=polyarea(contour.x,contour.y); clength=sqrt(carea); - if clength 0, + if nargin > 0 options=pairoptions(varargin{:}); %recover field values: @@ -30,14 +30,14 @@ self.orientation=getfieldvalue(options,'orientation','normal'); %figure out projection string: - if exist(options,'epsg'), - if exist(options,'proj'), + if exist(options,'epsg') + if exist(options,'proj') error(['Error in constructor for boundary ' self.shppath '. Cannot supply epsg and proj at the same time!']); end epsg=getfieldvalue(options,'epsg'); proj=epsg2proj(epsg); % convert to PROJ.4 format - elseif exist(options,'proj'), - if exist(options,'epsg'), + elseif exist(options,'proj') + if exist(options,'epsg') error(['Error in constructor for boundary ' self.shppath '. Cannot supply proj and epsg at the same time!']); end proj=getfieldvalue(options,'proj'); @@ -69,13 +69,13 @@ function disp(self) % {{{ %read domain: [path,name,ext]=fileparts(self.shpfilename); - if ~strcmpi(ext,'shp'), + if ~strcmpi(ext,'shp') ext='shp'; end output=shpread([self.shppath '/' name '.' ext]); %do we reverse? - if strcmpi(self.orientation,'reverse'), + if strcmpi(self.orientation,'reverse') output.x=flipud(output.x); output.y=flipud(output.y); end @@ -97,12 +97,12 @@ function plot(self,varargin) % {{{ fontsize=getfieldvalue(options,'fontsize',10); label=getfieldvalue(options,'label','on'); - if exist(options,'epsg'), - if exist(options,'proj'), + if exist(options,'epsg') + if exist(options,'proj') error('Boundary plot error message: cannot specify epsg and proj at the same time for plot projection'); end proj=epsg2proj(getfieldvalue(options,'epsg')); - elseif exist(options,'proj'), + elseif exist(options,'proj') proj=getfieldvalue(options,'proj'); else proj=epsg2proj(4326); @@ -110,13 +110,13 @@ function plot(self,varargin) % {{{ %read domain: [path,name,ext]=fileparts(self.shpfilename); - if ~strcmpi(ext,'shp'), + if ~strcmpi(ext,'shp') ext='shp'; end domain=shpread([self.shppath '/' name '.' ext]); %convert boundary to another reference frame: {{{ - for i=1:length(domain), + for i=1:length(domain) try, [x,y] = CoordTransform(domain(i).x,domain(i).y,self.proj,proj); catch me @@ -126,20 +126,20 @@ function plot(self,varargin) % {{{ domain(i).x=x; domain(i).y=y; end - for i=1:length(domain), + for i=1:length(domain) hold on; x=domain(i).x*unitmultiplier; y=domain(i).y*unitmultiplier; - if length(x)==1, + if length(x)==1 p=plot(x,y,'k*'); set(p,'MarkerSize',markersize,'Color',color); - if strcmpi(label,'on'), + if strcmpi(label,'on') t=text(x,y,self.shpfilename,'FontSize',fontsize); end else p=plot(x,y,'k-'); set(p,'MarkerSize',markersize,'Color',color); - if strcmpi(label,'on'), + if strcmpi(label,'on') text(sum(x)/length(x),sum(y)/length(y),self.shpfilename,'FontSize',fontsize); end end @@ -156,7 +156,7 @@ function checkconsistency(self,varargin) % {{{ %recover edges: edges=self.edges(); - if strcmpi(edges.Geometry,'Point'), + if strcmpi(edges.Geometry,'Point') return; else %check we don't have two identical vertices: @@ -164,7 +164,7 @@ function checkconsistency(self,varargin) % {{{ distance=sqrt( (x(1:end-1)-x(2:end)).^2+(y(1:end-1)-y(2:end)).^2); dmax=max(distance); isidentical=find(distance',0,'NaN',1,'Inf',1); md = checkfield(md,'fieldname','calving.stress_threshold_floatingice','>',0,'NaN',1,'Inf',1); - md = checkfield(md,'fieldname','calving.height_above_floatation','<=',0); + md = checkfield(md,'fieldname','calving.height_above_floatation','>=',0); end % }}} function disp(self) % {{{ disp(sprintf(' Calving Dev2 parameters:')); diff --git a/src/m/classes/calvinghab.m b/src/m/classes/calvinghab.m index 383607e72..cc6d7b954 100644 --- a/src/m/classes/calvinghab.m +++ b/src/m/classes/calvinghab.m @@ -18,7 +18,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/calvinglevermann.m b/src/m/classes/calvinglevermann.m index 963c712ca..b617f5c73 100644 --- a/src/m/classes/calvinglevermann.m +++ b/src/m/classes/calvinglevermann.m @@ -18,7 +18,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/calvingminthickness.m b/src/m/classes/calvingminthickness.m index 6db40bc66..d0e021c24 100644 --- a/src/m/classes/calvingminthickness.m +++ b/src/m/classes/calvingminthickness.m @@ -18,7 +18,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/calvingparameterization.m b/src/m/classes/calvingparameterization.m index 72b57f002..2e6e4e216 100644 --- a/src/m/classes/calvingparameterization.m +++ b/src/m/classes/calvingparameterization.m @@ -26,7 +26,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/calvingpollard.m b/src/m/classes/calvingpollard.m index b7e8d5b73..c09f96a33 100644 --- a/src/m/classes/calvingpollard.m +++ b/src/m/classes/calvingpollard.m @@ -18,7 +18,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/calvingtest.m b/src/m/classes/calvingtest.m index cd5ad87ba..97f264eb5 100644 --- a/src/m/classes/calvingtest.m +++ b/src/m/classes/calvingtest.m @@ -19,7 +19,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/calvingvonmises.m b/src/m/classes/calvingvonmises.m index 49fa5158f..c54d944ed 100644 --- a/src/m/classes/calvingvonmises.m +++ b/src/m/classes/calvingvonmises.m @@ -20,7 +20,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/calvingvonmisesAD.m b/src/m/classes/calvingvonmisesAD.m index e83617e6c..7c661597b 100644 --- a/src/m/classes/calvingvonmisesAD.m +++ b/src/m/classes/calvingvonmisesAD.m @@ -12,7 +12,7 @@ min_thickness = 0.; end methods - function self = calvingvonmises(varargin) % {{{ + function self = calvingvonmisesAD(varargin) % {{{ switch nargin case 0 self=setdefaultparameters(self); @@ -22,7 +22,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -35,7 +35,7 @@ function self = setdefaultparameters(self) % {{{ self.basin_id = NaN; - num_basins = 0; + self.num_basins = 0; %Default sigma max self.stress_threshold_groundedice = 1e6; diff --git a/src/m/classes/cfdragcoeffabsgrad.m b/src/m/classes/cfdragcoeffabsgrad.m index 2d1b5103f..2e501ca0d 100644 --- a/src/m/classes/cfdragcoeffabsgrad.m +++ b/src/m/classes/cfdragcoeffabsgrad.m @@ -26,7 +26,7 @@ end end % }}} function self = cfdragcoeffabsgrad(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -44,7 +44,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('cfdragcoeffabsgrad error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; diff --git a/src/m/classes/cfdragcoeffabsgradtransient.m b/src/m/classes/cfdragcoeffabsgradtransient.m index 6f9c12a53..f974edcae 100644 --- a/src/m/classes/cfdragcoeffabsgradtransient.m +++ b/src/m/classes/cfdragcoeffabsgradtransient.m @@ -23,7 +23,7 @@ end end % }}} function self = cfdragcoeffabsgradtransient(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -39,7 +39,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('cfdragcoeffabsgrad error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; diff --git a/src/m/classes/cflevelsetmisfit.m b/src/m/classes/cflevelsetmisfit.m index 411a5b8e1..3acc6c2da 100644 --- a/src/m/classes/cflevelsetmisfit.m +++ b/src/m/classes/cflevelsetmisfit.m @@ -36,7 +36,7 @@ end end % }}} function self = cflevelsetmisfit(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -59,7 +59,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('cflevelsetmisfit error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; diff --git a/src/m/classes/cfrheologybbarabsgrad.m b/src/m/classes/cfrheologybbarabsgrad.m index 80fbdb51a..56309b08e 100644 --- a/src/m/classes/cfrheologybbarabsgrad.m +++ b/src/m/classes/cfrheologybbarabsgrad.m @@ -27,7 +27,7 @@ end end % }}} function self = cfrheologybbarabsgrad(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -45,7 +45,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('cfrheologybbarabsgrad error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; diff --git a/src/m/classes/cfrheologybbarabsgradtransient.m b/src/m/classes/cfrheologybbarabsgradtransient.m index 5031cd0c5..58e1fea3d 100644 --- a/src/m/classes/cfrheologybbarabsgradtransient.m +++ b/src/m/classes/cfrheologybbarabsgradtransient.m @@ -22,7 +22,7 @@ end end % }}} function self = cfrheologybbarabsgradtransient(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -38,7 +38,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('cfrheologybbarabsgradtransient error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; diff --git a/src/m/classes/cfsurfacelogvel.m b/src/m/classes/cfsurfacelogvel.m index 12053cac2..069da74ba 100644 --- a/src/m/classes/cfsurfacelogvel.m +++ b/src/m/classes/cfsurfacelogvel.m @@ -36,7 +36,7 @@ end end % }}} function self = cfsurfacelogvel(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -60,7 +60,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('cfsurfacelogvel error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; diff --git a/src/m/classes/cfsurfacesquare.m b/src/m/classes/cfsurfacesquare.m index e80741320..7754e19ff 100644 --- a/src/m/classes/cfsurfacesquare.m +++ b/src/m/classes/cfsurfacesquare.m @@ -37,7 +37,7 @@ end end % }}} function self = cfsurfacesquare(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -62,7 +62,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('cfsurfacesquare error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; diff --git a/src/m/classes/cfsurfacesquaretransient.m b/src/m/classes/cfsurfacesquaretransient.m index 50cb929e9..88b88b06f 100644 --- a/src/m/classes/cfsurfacesquaretransient.m +++ b/src/m/classes/cfsurfacesquaretransient.m @@ -30,7 +30,7 @@ end end % }}} function self = cfsurfacesquaretransient(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -48,7 +48,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('cfsurfacesquaretransient error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; diff --git a/src/m/classes/clusters/acenet.m b/src/m/classes/clusters/acenet.m index 4b2a8f4b3..6513fec31 100644 --- a/src/m/classes/clusters/acenet.m +++ b/src/m/classes/clusters/acenet.m @@ -50,21 +50,17 @@ function disp(cluster) % {{{ QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time) end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -107,27 +103,15 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n'); %FIXME fprintf(fid,'\n'); - fprintf(fid,'mpiexec %s/issm.exe %s %s %s 2> %s.errlog >%s.outlog\n',... - cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname); + fprintf(fid,'mpiexec %s/%s %s %s %s 2> %s.errlog >%s.outlog\n',... + cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname); fclose(fid); end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ - - %Execute Queue job if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue ']; else @@ -137,11 +121,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/aci.m b/src/m/classes/clusters/aci.m index 787f3e54c..624dc7163 100644 --- a/src/m/classes/clusters/aci.m +++ b/src/m/classes/clusters/aci.m @@ -59,21 +59,17 @@ function disp(cluster) % {{{ if isempty(cluster.executionpath), md = checkmessage(md,'executionpath empty'); end end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -87,28 +83,16 @@ function BuildQueueScript(cluster, md, filename) % {{{ for i=1:numel(cluster.modules) fprintf(fid,'module load %s\n', cluster.modules{i}); end - fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.nodes*cluster.ppn,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -np %i %s/%s %s %s %s\n',cluster.nodes*cluster.ppn,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end fclose(fid); end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch)% {{{ - - %Execute Queue job if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && qsub ' modelname '.queue ']; else @@ -118,11 +102,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch)% {{{ issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function Download(cluster,dirname,filelist)% {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/andes.m b/src/m/classes/clusters/andes.m index 341992785..952a7f9b2 100644 --- a/src/m/classes/clusters/andes.m +++ b/src/m/classes/clusters/andes.m @@ -65,14 +65,10 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -101,22 +97,18 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ fclose(fid); end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind); disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof); disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind); disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof); disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -134,16 +126,16 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'#SBATCH --mail-user=%s@%s\n',cluster.login, cluster.email_domain); end fprintf(fid,'\n'); - fprintf(fid,'mpirun -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(), cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -n %i %s/%s %s %s %s\n',cluster.nprocs(), cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end fclose(fid); %in interactive mode, create a run file, and errlog and outlog file - if cluster.interactive, + if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'mpirun -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(), cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -n %i %s/%s %s %s %s\n',cluster.nprocs(), cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -155,38 +147,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,0,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,0,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,0,directory,filelist, 2); %use {} and not \{\} - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/aurora.m b/src/m/classes/clusters/aurora.m index 3cb55396f..573451ba0 100644 --- a/src/m/classes/clusters/aurora.m +++ b/src/m/classes/clusters/aurora.m @@ -61,31 +61,17 @@ function disp(cluster) % {{{ QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.numnodes.*cluster.cpuspernode,cluster.time) end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; - %checks - if(isvalgrind); disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof); disp('gprof not supported by cluster, ignoring...'); end - - executable='issm.exe' - if isdakota, - version=IssmConfig('_DAKOTA_VERSION_'); - version=str2num(version(1:3)); - if(version>=6) executable='issm_dakota.exe'; end - end - if isoceancoupling - executable='issm_ocean.exe'; - end + %checks + if(md.debug.valgrind); disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof); disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -111,37 +97,19 @@ function BuildQueueScript(cluster, md, filename) % {{{ end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue ']; else launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && qsub ' modelname '.queue ']; end - - %Execute Queue job issmssh(cluster.name,cluster.login,cluster.port,launchcommand); - end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/aws_issm_solution_server.m b/src/m/classes/clusters/aws_issm_solution_server.m index d1bd2308a..35e3a40f8 100644 --- a/src/m/classes/clusters/aws_issm_solution_server.m +++ b/src/m/classes/clusters/aws_issm_solution_server.m @@ -69,11 +69,11 @@ function disp(cluster) % {{{ %}}} function md = checkconsistency(cluster,md,solution,analyses) % {{{ - if ((cluster.numnodes>1 ) | (cluster.numnodes<1)), + if ((cluster.numnodes>1 ) | (cluster.numnodes<1)) md = checkmessage(md,'only 1 node is currently available'); end - if ((cluster.cpuspernode>8 ) | (cluster.cpuspernode<1)), + if ((cluster.cpuspernode>8 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 8'); end @@ -86,33 +86,19 @@ function disp(cluster) % {{{ end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; - - %checks - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end - - executable='issm.exe'; - if isdakota, - version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3)); - if (version>=6) - executable='issm_dakota.exe'; - end - end - if isoceancoupling - executable='issm_ocean.exe'; - end - %write queuing script + %checks + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end + + %write queuing script fid=fopen(filename, 'w'); fprintf(fid,'#!/bin/bash\n'); fprintf(fid,'export PATH="${PATH}:."\n'); @@ -124,13 +110,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n\n'); if cluster.interactive - if IssmConfig('_HAVE_MPI_'), + if IssmConfig('_HAVE_MPI_') fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); else fprintf(fid,'%s/%s %s %s %s\n',cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); end else - if IssmConfig('_HAVE_MPI_'), + if IssmConfig('_HAVE_MPI_') fprintf(fid,'mpiexec -np %i %s/%s %s %s %s 2> %s.errlog > %s.outlog &\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname); else fprintf(fid,'%s/%s %s %s %s 2> %s.errlog > %s.outlog &\n',cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname); @@ -142,27 +128,29 @@ function BuildQueueScript(cluster, md, filename) % {{{ fclose(fid); %in interactive mode, create a run file, and errlog and outlog file - if cluster.interactive, + if cluster.interactive fid=fopen([modelname '.errlog'],'w'); fclose(fid); fid=fopen([modelname '.outlog'],'w'); fclose(fid); end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive - compressstring = [compressstring ' ' modelname '.run ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); + %filelist contains full paths; tar with -C so only basenames are stored in the archive + root=[issmdir() '/execution/' dirname]; + compressstring=['tar -C ' root ' -zcf ' dirname '.tar.gz']; + for i=1:numel(filelist) + if ~exist(filelist{i},'file') + error(['File ' filelist{i} ' not found']); + end + [~,fname,fext]=fileparts(filelist{i}); + compressstring=[compressstring ' ' fname fext]; + end + system(compressstring); %upload input files - if cluster.interactive==10, + if cluster.interactive==10 directory=[pwd() '/run/']; - elseif cluster.interactive, + elseif cluster.interactive directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive)]; else directory=cluster.executionpath; @@ -171,7 +159,7 @@ function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ %NOTE: Replacement for issmscpout(cluster.name,directory,cluster.login,cluster.port,{[dirname '.tar.gz']}); uploadstring=['scp -i ' cluster.idfile ' ' dirname '.tar.gz ' cluster.login '@' cluster.name ':' directory]; [status,result]=system(uploadstring); - if status, + if status error(['cluster.UploadQueueJob error message: ' status]); end end @@ -179,11 +167,11 @@ function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ %launch command, to be executed via ssh - if cluster.interactive, + if cluster.interactive if ~isempty(restart) launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive)]; else - if cluster.interactive==10, + if cluster.interactive==10 launchcommand=['cd ' pwd() '/run && tar -zxf ' dirname '.tar.gz']; else launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive) ' && tar -zxf ' dirname '.tar.gz']; @@ -202,7 +190,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ %NOTE: Replacement for issmssh(cluster.name,cluster.login,cluster.port,launchcommand); launchstring=['ssh -l ' cluster.login ' -i ' cluster.idfile ' ' cluster.name ' "' launchcommand '"']; [status,result]=system(launchstring); - if status, + if status error(['cluster.LaunchQueueJob error message: ' status]); end end @@ -210,20 +198,20 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ function Download(cluster,dirname,filelist) % {{{ %copy files from cluster to current directory - if cluster.interactive==10, + if cluster.interactive==10 directory=[pwd() '/run/']; - elseif ~cluster.interactive, + elseif ~cluster.interactive directory=[cluster.executionpath '/' dirname '/']; else directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive) '/']; end %NOTE: Replacement for issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - if numel(filelist)==1, + if numel(filelist)==1 filestring=filelist{1}; else filestring='\{'; - for i=1:numel(filelist)-1, + for i=1:numel(filelist)-1 filestring=[filestring filelist{i} ',']; end filestring=[filestring filelist{end} '\}']; @@ -231,13 +219,13 @@ function Download(cluster,dirname,filelist) % {{{ downloadstring=['scp -i ' cluster.idfile ' ' cluster.login '@' cluster.name ':' directory '/' filestring ' ./']; [status,result]=system(downloadstring); - if status, + if status error(['cluster.Download error message: ' status]); end %check scp worked - for i=1:numel(filelist), - if ~exist(['./' filelist{i}]), + for i=1:numel(filelist) + if ~exist(['./' filelist{i}]) warning(['cluster.Download error message: could not scp ' filelist{i}]); end end diff --git a/src/m/classes/clusters/camhpc.m b/src/m/classes/clusters/camhpc.m index 9aa11d4c4..1194961a3 100644 --- a/src/m/classes/clusters/camhpc.m +++ b/src/m/classes/clusters/camhpc.m @@ -70,21 +70,17 @@ function disp(cluster) % {{{ end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind); disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof); disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind); disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof); disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -101,7 +97,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n'); %FIXME fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); - fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -110,7 +106,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -122,26 +118,10 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - % - % qsub replaced by sbatch for csd3 system NSA 28/3/18 + %NOTE: restart path uses qsub; non-restart uses sbatch (csd3 system, NSA 28/3/18) if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && qsub ' modelname '.queue ']; else @@ -151,11 +131,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/castor.m b/src/m/classes/clusters/castor.m index a19862cf7..d7399bd74 100644 --- a/src/m/classes/clusters/castor.m +++ b/src/m/classes/clusters/castor.m @@ -45,21 +45,17 @@ function disp(cluster) % {{{ QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time) end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind); disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof); disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind); disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof); disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -75,29 +71,14 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]); fprintf(fid,'cd $PBS_O_WORKDIR\n'); fprintf(fid,'export OMP_NUM_THREADS=1\n'); - fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/issm.exe %s %s %s',cluster.np-1,cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/%s %s %s %s',cluster.np-1,cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); fclose(fid); end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ - - %Execute Queue job if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue ']; else @@ -107,11 +88,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/cloud.m b/src/m/classes/clusters/cloud.m index d6d92c2a3..3b35c4432 100644 --- a/src/m/classes/clusters/cloud.m +++ b/src/m/classes/clusters/cloud.m @@ -19,7 +19,7 @@ function cluster=cloud(varargin) % {{{ %initialize cluster using user settings if provided - if (exist('cloud_settings')==2), + if (exist('cloud_settings')==2) cloud_settings; end @@ -42,50 +42,47 @@ function disp(cluster) % {{{ if cluster.np<1 md = checkmessage(md,['number of processors should be at least 1']); end - if isnan(cluster.np), + if isnan(cluster.np) md = checkmessage(md,'number of processors should not be NaN!'); end end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %write queuing script fid=fopen(filename, 'w'); fprintf(fid,'#!/bin/bash\n'); fprintf(fid,'source %s%s\n',cluster.codepath,'/../etc/environment.sh'); fprintf(fid,'cd %s\n',[cluster.executionpath '/' dirname]); - fprintf(fid,'mpiexec -np %i -f /home/mpich2.hosts %s/issm.exe %s %s/%s %s 2> %s.errlog > /dev/stdout | tee %s.outlog',cluster.np,cluster.codepath,solution,cluster.executionpath,dirname,modelname,modelname,modelname); + fprintf(fid,'mpiexec -np %i -f /home/mpich2.hosts %s/%s %s %s/%s %s 2> %s.errlog > /dev/stdout | tee %s.outlog',cluster.np,cluster.codepath,executable,solution,cluster.executionpath,dirname,modelname,modelname,modelname); end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; + %filelist contains full paths; tar with -C so only basenames are stored in the archive + root=[issmdir() '/execution/' dirname]; + compressstring=['tar -C ' root ' -zcf ' dirname '.tar.gz']; + for i=1:numel(filelist) + if ~exist(filelist{i},'file') + error(['File ' filelist{i} ' not found']); + end + [~,fname,fext]=fileparts(filelist{i}); + compressstring=[compressstring ' ' fname fext]; end system(compressstring); - if isempty(cluster.login), - error('cloud BuildQueueScript: login should be supplied!'); - end - %upload input files - issmstscpout(cluster.name,cluster.executionpath,cluster.login,{[dirname '.tar.gz']}); + issmscpout(cluster.name,cluster.executionpath,cluster.login,0,{[dirname '.tar.gz']}); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ - if cluster.interactive, + if cluster.interactive disp('sending files to remote cluster. once done, please log into cluster and launch job'); if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname]; diff --git a/src/m/classes/clusters/cloud.py b/src/m/classes/clusters/cloud.py index 6ec674069..ca60322f0 100644 --- a/src/m/classes/clusters/cloud.py +++ b/src/m/classes/clusters/cloud.py @@ -1,9 +1,11 @@ +import os import subprocess try: from cloud_settings import cloud_settings except ImportError: print('You need cloud_settings.py to proceed, check presence and sys.path') +from issmdir import issmdir class cloud(object): """CLOUD cluster class definition @@ -54,7 +56,7 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename @@ -76,10 +78,14 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress the files into one zip - compressstring = 'tar -zcf {}.tar.gz'.format(dirname) - for file in filelist: - compressstring += ' {}'.format(file) + # Compress the files into one zip. + # filelist contains full paths; use -C so only basenames are stored in the archive. + root = issmdir() + '/execution/' + dirname + compressstring = 'tar -C {} -zcf {}.tar.gz'.format(root, dirname) + for filepath in filelist: + if not os.path.isfile(filepath): + raise Exception('File {} not found'.format(filepath)) + compressstring += ' {}'.format(os.path.basename(filepath)) subprocess.call(compressstring, shell=True) if isempty(self.login): diff --git a/src/m/classes/clusters/cluster_defaults.m b/src/m/classes/clusters/cluster_defaults.m new file mode 100644 index 000000000..e91148362 --- /dev/null +++ b/src/m/classes/clusters/cluster_defaults.m @@ -0,0 +1,85 @@ +%CLUSTER_DEFAULTS Default method implementations shared across cluster classes. +% +% Most remote cluster classes (andes, frontera, pfe, etc.) share +% identical implementations of UploadQueueJob, LaunchQueueJob, and Download. +% Rather than duplicating those ~30 lines in every file, each cluster can +% delegate to the corresponding static method here. +% +% Clusters whose methods differ from these defaults (e.g. bbftp transfers, +% interactive path variants, ...) should have their own implementations. + +classdef cluster_defaults + methods (Static) + function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ + + % Compress the execution directory into a tar.gz and scp it to the cluster. + % filelist contains full paths; tar with -C so only basenames are stored. + root=[issmdir() '/execution/' dirname]; + compressstring=['tar -C ' root ' -zcf ' dirname '.tar.gz']; + for i=1:numel(filelist) + if ~exist(filelist{i},'file') + error(['File ' filelist{i} ' not found']); + end + [~,fname,fext]=fileparts(filelist{i}); + compressstring=[compressstring ' ' fname fext]; + end + system(compressstring); + + %Copy tar.gz file over + port=0; if isprop(cluster,'port'), port=cluster.port; end + issmscpout(cluster.name,cluster.executionpath,cluster.login,port,{[dirname '.tar.gz']}); + end %}}} + function LaunchQueueJobSbatch(cluster, modelname, dirname, filelist, restart, batch, format) % {{{ + % on cluster: open tar.gz file and submit job + % + % format 1: no scheduler, just source .queue + % format 2: SLURM, use sbatch + % format 3: PBS, use qsub + + if format==1 + %No scheduler: source .queue directly + if ~isempty(restart) + launchcommand=['source ' cluster.etcpath '/environment.sh && cd ' cluster.executionpath ' && cd ' dirname ' && source ' modelname '.queue ']; + else + if ~batch + launchcommand=['source ' cluster.etcpath '/environment.sh && source ' cluster.executionpath '/' dirname '/' modelname '.queue ']; + else + launchcommand=['source ' cluster.etcpath '/environment.sh && cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... + ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz ']; + end + end + + elseif format==2 + %SLURM sbatch launch: unpack the tar and submit the queue script via SSH. + if ~isempty(restart) + launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && sbatch ' modelname '.queue']; + else + launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... + ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && sbatch ' modelname '.queue']; + end + elseif format==3 + %BPS: use qsub + if ~isempty(restart) + launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && /PBS/bin/qsub ' modelname '.queue ']; + else + launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... + ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && /PBS/bin/qsub ' modelname '.queue ']; + end + + else + error('format not supported'); + end + port=0; if isprop(cluster,'port'), port=cluster.port; end + issmssh(cluster.name,cluster.login,port,launchcommand); + + end %}}} + function Download(cluster,dirname,filelist) % {{{ + + %Copy output files from the cluster back to the current directory via scp. + directory=[cluster.executionpath '/' dirname '/']; + port=0; if isprop(cluster,'port'), port=cluster.port; end + issmscpin(cluster.name,cluster.login,port,directory,filelist); + + end %}}} + end +end diff --git a/src/m/classes/clusters/cluster_defaults.py b/src/m/classes/clusters/cluster_defaults.py new file mode 100644 index 000000000..bc5a3e8b0 --- /dev/null +++ b/src/m/classes/clusters/cluster_defaults.py @@ -0,0 +1,95 @@ +"""Default method implementations shared across HPC cluster classes. + +Most remote cluster classes (sherlock, frontera, saga, etc.) share identical +implementations of UploadQueueJob, LaunchQueueJob, and Download. Rather than +duplicating those blocks in every file, each cluster can delegate to the +corresponding function here. + +Clusters whose methods differ from these defaults (e.g. bbftp transfers, +interactive path variants, qsub/PBS schedulers, or local execution) should +keep their own implementations unchanged. +""" + +import os +import subprocess + +from issmdir import issmdir +from issmscpin import issmscpin +from issmscpout import issmscpout +from issmssh import issmssh + +def UploadQueueJob(cluster, modelname, dirname, filelist): # {{{ + """Compress the execution directory into a tar.gz and scp it to the cluster. + + filelist contains full paths; ``-C`` is used so only basenames are stored + in the archive. + """ + root = os.path.join(issmdir(), 'execution', dirname) + compressstring = 'tar -C {} -zcf {}.tar.gz'.format(root, dirname) + for filepath in filelist: + if not os.path.isfile(filepath): + raise Exception('File {} not found'.format(filepath)) + compressstring += ' {}'.format(os.path.basename(filepath)) + subprocess.call(compressstring, shell=True) + + port = getattr(cluster, 'port', 0) + issmscpout(cluster.name, cluster.executionpath, cluster.login, port, [dirname + '.tar.gz']) +# }}} + +def LaunchQueueJobSbatch(cluster, modelname, dirname, filelist, restart, batch, fmt): # {{{ + """Launch a queued job on the cluster via SSH. + + fmt values: + 1 - no scheduler, source .queue directly + 2 - SLURM, use sbatch + 3 - PBS/Torque, use qsub + """ + from helpers import isempty + if fmt == 1: + # No scheduler: source .queue directly + if not isempty(restart): + launchcommand = 'source {}/environment.sh && cd {} && cd {} && source {}.queue'.format( + cluster.etcpath, cluster.executionpath, dirname, modelname) + else: + if batch: + launchcommand = ('source {}/environment.sh && cd {} && rm -rf ./{} && mkdir {} && ' + 'cd {} && mv ../{}.tar.gz ./ && tar -zxf {}.tar.gz' + .format(cluster.etcpath, cluster.executionpath, dirname, dirname, + dirname, dirname, dirname)) + else: + launchcommand = 'source {}/environment.sh && source {}/{}/{}.queue'.format( + cluster.etcpath, cluster.executionpath, dirname, modelname) + elif fmt == 2: + # SLURM sbatch + if not isempty(restart): + launchcommand = 'cd {} && cd {} && sbatch {}.queue'.format( + cluster.executionpath, dirname, modelname) + else: + launchcommand = ( + 'cd {} && rm -rf ./{} && mkdir {} && cd {} && ' + 'mv ../{}.tar.gz ./ && tar -zxf {}.tar.gz && sbatch {}.queue' + .format(cluster.executionpath, dirname, dirname, dirname, + dirname, dirname, modelname)) + elif fmt == 3: + # PBS/Torque qsub + if not isempty(restart): + launchcommand = 'cd {} && cd {} && /PBS/bin/qsub {}.queue'.format( + cluster.executionpath, dirname, modelname) + else: + launchcommand = ( + 'cd {} && rm -rf ./{} && mkdir {} && cd {} && ' + 'mv ../{}.tar.gz ./ && tar -zxf {}.tar.gz && /PBS/bin/qsub {}.queue' + .format(cluster.executionpath, dirname, dirname, dirname, + dirname, dirname, modelname)) + else: + raise ValueError('fmt={} not supported'.format(fmt)) + port = getattr(cluster, 'port', 0) + issmssh(cluster.name, cluster.login, port, launchcommand) +# }}} + +def Download(cluster, dirname, filelist): # {{{ + """Copy output files from the cluster back to the current directory via scp.""" + directory = '{}/{}/'.format(cluster.executionpath, dirname) + port = getattr(cluster, 'port', 0) + issmscpin(cluster.name, cluster.login, port, directory, filelist) +# }}} diff --git a/src/m/classes/clusters/computecanada.m b/src/m/classes/clusters/computecanada.m index 3f5037873..7da8a700e 100644 --- a/src/m/classes/clusters/computecanada.m +++ b/src/m/classes/clusters/computecanada.m @@ -70,21 +70,17 @@ function disp(cluster) % {{{ if ~(cluster.memory > 0), md = checkmessage(md,'memory must be > 0'); end end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; - %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + %checks + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -101,41 +97,19 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'#SBATCH --error=%s.errlog \n\n',modelname); fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); - fprintf(fid,'srun -n %i %s/issm.exe %s %s %s\n',cluster.np(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'srun -n %i %s/%s %s %s %s\n',cluster.np(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); fclose(fid); end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}, 2); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch)% {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && hostname && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist)% {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist, 2); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/cosmos.m b/src/m/classes/clusters/cosmos.m index 93fb17e73..a1dfb9a3c 100644 --- a/src/m/classes/clusters/cosmos.m +++ b/src/m/classes/clusters/cosmos.m @@ -45,21 +45,17 @@ function disp(cluster) % {{{ QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time) end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -75,30 +71,15 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export OMP_NUM_THREADS=1\n'); fprintf(fid,'ulimit -s unlimited\n'); fprintf(fid,'ulimit -c 0\n'); - fprintf(fid,'/opt/mpich/gm/intel10.1/bin/mpiexec -np %i %s/issm.exe %s %s %s',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'/opt/mpich/gm/intel10.1/bin/mpiexec -np %i %s/%s %s %s %s',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); fclose(fid); end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ - - %Execute Queue job if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue ']; else @@ -108,11 +89,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/cyclone.py b/src/m/classes/clusters/cyclone.py index 65ba2632d..1331ffe03 100644 --- a/src/m/classes/clusters/cyclone.py +++ b/src/m/classes/clusters/cyclone.py @@ -1,15 +1,18 @@ +import os import subprocess try: from cyclone_settings import cyclone_settings except ImportError: print('You need cyclone_settings.py to proceed, check presence and sys.path') +import cluster_defaults from fielddisplay import fielddisplay from helpers import * from pairoptions import pairoptions from issmscpin import issmscpin from issmscpout import issmscpout from issmssh import issmssh +from issmdir import issmdir class cyclone(object): @@ -30,7 +33,7 @@ def __init__(self, *args): # {{{ self.time = 100 self.codepath = '' self.executionpath = '' - self.port = '' + self.port = 0 self.interactive = 0 # Use provided options to change fields @@ -70,19 +73,13 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename modelname = md.miscellaneous.name solution = md.private.solution io_gather = md.settings.io_gather - isvalgrind = md.debug.valgrind - isgprof = md.debug.gprof - isdakota = md.qmu.isdakota - isoceancoupling = md.transient.isoceancoupling - - executable = 'issm.exe' # Write queuing script fid = open(filename, 'w') @@ -99,14 +96,7 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - #compress the files into one zip. - compressstring = 'tar -zcf %s.tar.gz ' % dirname - for file in filelist: - compressstring += ' {}'.format(file) - subprocess.call(compressstring, shell=True) - - #upload input files - issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz']) + cluster_defaults.UploadQueueJob(self, modelname, dirname, filelist) # }}} def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch): # {{{ @@ -119,7 +109,5 @@ def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch): # {{{ # }}} def Download(self, dirname, filelist): # {{{ - # Copy files from cluster to current directory - directory = '%s/%s/' % (self.executionpath, dirname) - issmscpin(self.name, self.login, self.port, directory, filelist) + cluster_defaults.Download(self, dirname, filelist) # }}} diff --git a/src/m/classes/clusters/discover.m b/src/m/classes/clusters/discover.m index eb736cb1a..215c5241a 100644 --- a/src/m/classes/clusters/discover.m +++ b/src/m/classes/clusters/discover.m @@ -75,12 +75,12 @@ function disp(cluster) % {{{ QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.nprocs(),cluster.time) %now, check cluster.cpuspernode according to processor type - if ( strcmpi(cluster.processor,'sand')), - if ((cluster.cpuspernode>16 ) | (cluster.cpuspernode<1)), + if ( strcmpi(cluster.processor,'sand')) + if ((cluster.cpuspernode>16 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 16 for ''sand'' processors'); end - elseif strcmpi(cluster.processor,'hasw'), - if ((cluster.cpuspernode>28 ) | (cluster.cpuspernode<1)), + elseif strcmpi(cluster.processor,'hasw') + if ((cluster.cpuspernode>28 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 28 for ''hasw'' processors'); end else @@ -94,31 +94,17 @@ function disp(cluster) % {{{ end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ - - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; - - %checks - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end - - executable='issm.exe'; - if isdakota - version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3)); - if (version>=6), - executable='issm_dakota.exe'; - end - end - if isoceancoupling - executable='issm_ocean.exe'; - end + function BuildQueueScript(cluster, md, filename, executable) % {{{ + + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; + isvalgrind = md.debug.valgrind; + + %checks + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -137,7 +123,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'#SBATCH --mail-type=end \n\n'); end fprintf(fid,'. /usr/share/modules/init/bash\n\n'); - for i=1:numel(cluster.modules), + for i=1:numel(cluster.modules) fprintf(fid,['module load ' cluster.modules{i} '\n']); end fprintf(fid,'export MPI_GROUP_MAX=64\n\n'); @@ -154,9 +140,9 @@ function BuildQueueScript(cluster, md, filename) % {{{ fclose(fid); %in interactive mode, create a run file, and errlog and outlog file - if cluster.interactive, + if cluster.interactive fid=fopen([modelname '.run'],'w'); - if ~isvalgrind, + if ~isvalgrind fprintf(fid,'mpiexec -np %i %s/%s %s %s/%s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,cluster.executionpath,dirname,modelname); else fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/%s %s %s/%s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,cluster.executionpath,dirname,modelname); @@ -172,12 +158,15 @@ function BuildQueueScript(cluster, md, filename) % {{{ function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz']; + %filelist contains full paths; tar with -C so only basenames are stored in the archive + root=[issmdir() '/execution/' dirname]; + compressstring=['tar -C ' root ' -zcf ' dirname '.tar.gz']; for i=1:numel(filelist) - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive - compressstring = [compressstring ' ' modelname '.run ' modelname '.errlog ' modelname '.outlog ']; + if ~exist(filelist{i},'file') + error(['File ' filelist{i} ' not found']); + end + [~,fname,fext]=fileparts(filelist{i}); + compressstring=[compressstring ' ' fname fext]; end system(compressstring); @@ -188,7 +177,7 @@ function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ directory=cluster.executionpath; end - if cluster.bbftp, + if cluster.bbftp issmbbftpout(cluster.name,directory,cluster.login,cluster.port,cluster.numstreams,{[dirname '.tar.gz']}); else issmscpout(cluster.name,directory,cluster.login,cluster.port,{[dirname '.tar.gz']}); @@ -198,7 +187,7 @@ function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - if cluster.interactive, + if cluster.interactive if ~isempty(restart) launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive)]; else @@ -220,13 +209,13 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ function Download(cluster,dirname,filelist) % {{{ %copy files from cluster to current directory - if cluster.interactive, + if cluster.interactive directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive) '/']; else directory=[cluster.executionpath '/' dirname '/']; end - if cluster.bbftp, + if cluster.bbftp issmbbftpin(cluster.name, cluster.login, cluster.port, cluster.numstreams, directory, filelist); else issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); diff --git a/src/m/classes/clusters/discover.py b/src/m/classes/clusters/discover.py index f3fa25fb8..ee840837a 100644 --- a/src/m/classes/clusters/discover.py +++ b/src/m/classes/clusters/discover.py @@ -1,3 +1,4 @@ +import os import subprocess try: @@ -10,6 +11,7 @@ from issmscpin import issmscpin from issmscpout import issmscpout from issmssh import issmssh +from issmdir import issmdir from MatlabFuncs import * from pairoptions import pairoptions from QueueRequirements import QueueRequirements @@ -111,30 +113,17 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename modelname = md.miscellaneous.name solution = md.private.solution io_gather = md.settings.io_gather - isvalgrind = md.debug.valgrind - isgprof = md.debug.gprof - isdakota = md.qmu.isdakota - isoceancoupling = md.transient.isoceancoupling - if isgprof: + if md.debug.gprof: print('gprof not supported by cluster, ignoring...') - executable = 'issm.exe' - if isdakota: - version = IssmConfig('_DAKOTA_VERSION_')[0:2] - version = float(str(version[0])) - if version >= 6: - executable = 'issm_dakota.exe' - if isoceancoupling: - executable = 'issm_ocean.exe' - # Write queuing script fid = open(filename, 'w') fid.write('#!/bin/bash\n') @@ -168,7 +157,7 @@ def BuildQueueScript(self, md, filename): # {{{ # In interactive mode, create a run file, and errlog and outlog file if self.interactive: fid = open(modelname + '.run', 'w') - if not isvalgrind: + if not md.debug.valgrind: fid.write('mpiexec -np {} {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname)) else: fid.write('mpiexec -np {} valgrind --leak-check=full {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname)) @@ -182,12 +171,14 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress the files into one zip - compressstring = 'tar -zcf {}.tar.gz'.format(dirname) - for file in filelist: - compressstring += ' {}'.format(file) - if self.interactive: - compressstring += ' {}.run {}.errlog {}.outlog'.format(modelname, modelname, modelname) + # Compress the files into one zip. + # filelist contains full paths; use -C so only basenames are stored in the archive. + root = issmdir() + '/execution/' + dirname + compressstring = 'tar -C {} -zcf {}.tar.gz'.format(root, dirname) + for filepath in filelist: + if not os.path.isfile(filepath): + raise Exception('File {} not found'.format(filepath)) + compressstring += ' {}'.format(os.path.basename(filepath)) subprocess.call(compressstring, shell=True) #upload input files diff --git a/src/m/classes/clusters/discovery.m b/src/m/classes/clusters/discovery.m index 23acecc88..3f1c94e6a 100644 --- a/src/m/classes/clusters/discovery.m +++ b/src/m/classes/clusters/discovery.m @@ -67,14 +67,10 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queueing script fid=fopen(filename, 'w'); @@ -102,21 +98,17 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ fclose(fid); end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid = fopen(filename, 'w'); @@ -139,7 +131,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n'); fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); - fprintf(fid,'mpirun -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(), cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -n %i %s/%s %s %s %s\n',cluster.nprocs(), cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -151,7 +143,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'mpirun -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(), cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -n %i %s/%s %s %s %s\n',cluster.nprocs(), cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -161,38 +153,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,0,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && hostname && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,0,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,0,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/eis_nasa_smce.py b/src/m/classes/clusters/eis_nasa_smce.py index 23ee022ad..8db18fb21 100644 --- a/src/m/classes/clusters/eis_nasa_smce.py +++ b/src/m/classes/clusters/eis_nasa_smce.py @@ -10,6 +10,7 @@ from helpers import * from IssmConfig import IssmConfig from issmssh import issmssh +from issmdir import issmdir from MatlabFuncs import * from pairoptions import pairoptions @@ -104,7 +105,7 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename @@ -180,12 +181,14 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress the files into one zip - compressstring = 'tar -zcf {}.tar.gz'.format(dirname) - for file in filelist: - compressstring += ' {}'.format(file) - if self.interactive: - compressstring += ' {}.run {}.errlog {}.outlog'.format(modelname, modelname, modelname) + # Compress the files into one zip. + # filelist contains full paths; use -C so only basenames are stored in the archive. + root = issmdir() + '/execution/' + dirname + compressstring = 'tar -C {} -zcf {}.tar.gz'.format(root, dirname) + for filepath in filelist: + if not os.path.isfile(filepath): + raise Exception('File {} not found'.format(filepath)) + compressstring += ' {}'.format(os.path.basename(filepath)) subprocess.call(compressstring, shell=True) print('uploading input file and queueing script') diff --git a/src/m/classes/clusters/fram.py b/src/m/classes/clusters/fram.py index 3dff8b37e..f1f8d6f37 100644 --- a/src/m/classes/clusters/fram.py +++ b/src/m/classes/clusters/fram.py @@ -1,7 +1,9 @@ +import os import subprocess import numpy as np +import cluster_defaults from fielddisplay import fielddisplay try: from fram_settings import fram_settings @@ -13,6 +15,7 @@ from issmscpin import issmscpin from issmscpout import issmscpout from issmssh import issmssh +from issmdir import issmdir from QueueRequirements import QueueRequirements @@ -94,26 +97,13 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename modelname = md.miscellaneous.name solution = md.private.solution io_gather = md.settings.io_gather - isvalgrind = md.debug.valgrind - isgprof = md.debug.gprof - isdakota = md.qmu.isdakota - isoceancoupling = md.transient.isoceancoupling - - executable = 'issm.exe' - if isdakota: - version = IssmConfig('_DAKOTA_VERSION_')[0:2] - version = float(version) - if version >= 6: - executable = 'issm_dakota.exe' - if isoceancoupling: - executable = 'issm_ocean.exe' # Write queuing script shortname = modelname[0:min(12, len(modelname))] fid = open(filename, 'w') @@ -148,28 +138,13 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress the files into one zip - compressstring = 'tar -zcf %s.tar.gz ' % dirname - for file in filelist: - compressstring += ' {}'.format(file) - subprocess.call(compressstring, shell=True) - - #upload input files - issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz']) - + cluster_defaults.UploadQueueJob(self, modelname, dirname, filelist) # }}} def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch): # {{{ - #Execute Queue job - if not isempty(restart): - launchcommand = 'cd %s && cd %s && sbatch %s.queue' % (self.executionpath, dirname, modelname) - else: - launchcommand = 'cd %s && rm -rf ./%s && mkdir %s && cd %s && mv ../%s.tar.gz ./ && tar -zxf %s.tar.gz && sbatch %s.queue' % (self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname) - issmssh(self.name, self.login, self.port, launchcommand) + cluster_defaults.LaunchQueueJobSbatch(self, modelname, dirname, filelist, restart, batch, 2) # }}} def Download(self, dirname, filelist): # {{{ - # Copy files from cluster to current directory - directory = '%s/%s/' % (self.executionpath, dirname) - issmscpin(self.name, self.login, self.port, directory, filelist) + cluster_defaults.Download(self, dirname, filelist) # }}} diff --git a/src/m/classes/clusters/frontera.m b/src/m/classes/clusters/frontera.m index cdd4f63bd..96522e4ba 100644 --- a/src/m/classes/clusters/frontera.m +++ b/src/m/classes/clusters/frontera.m @@ -10,7 +10,8 @@ % {{{ name = 'frontera' login = ''; - modules = {'intel/23.1.0', 'impi/21.9.0', 'petsc/3.21'}; + allocation = '' + modules = {'intel/23.1.0', 'impi/21.9.0', 'petsc/3.21'}; numnodes = 4; cpuspernode = 56; port = 0; @@ -38,6 +39,7 @@ function disp(cluster) % {{{ disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1))); disp(sprintf(' name: %s',cluster.name)); disp(sprintf(' login: %s',cluster.login)); + disp(sprintf(' allocation: %s',cluster.allocation)); disp(sprintf(' modules: %s',strjoin(cluster.modules,', '))); disp(sprintf(' port: %i',cluster.port)); disp(sprintf(' numnodes: %i',cluster.numnodes)); @@ -68,6 +70,7 @@ function disp(cluster) % {{{ %Miscellaneous if isempty(cluster.login), md = checkmessage(md,'login empty'); end + if isempty(cluster.allocation), md = checkmessage(md,'allocation empty'); end if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end if isempty(cluster.executionpath), md = checkmessage(md,'executionpath empty'); end end @@ -79,14 +82,12 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end + + error('Needs to be updated, look at BuildQueueScript'); %write queuing script fid=fopen(filename, 'w'); @@ -108,52 +109,38 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ fclose(fid); end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; - %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end - - executable='issm.exe'; - if isdakota - version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3)); - if (version>=6) - executable='issm_dakota.exe'; - end - end - if isoceancoupling - executable='issm_ocean.exe'; - end + %checks + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end - %write queuing script + %write queuing script fid=fopen(filename, 'w'); fprintf(fid,'#!/bin/bash\n'); fprintf(fid,'#SBATCH -J %s \n',modelname); + fprintf(fid,'#SBATCH -A %s \n', cluster.allocation); fprintf(fid,'#SBATCH -p %s \n',cluster.queue); fprintf(fid,'#SBATCH -o %s.outlog \n',modelname); fprintf(fid,'#SBATCH -e %s.errlog \n',modelname); fprintf(fid,'#SBATCH -n %i \n',cluster.numnodes*max(cluster.nprocs()/cluster.numnodes,56)); fprintf(fid,'#SBATCH -N %i \n',cluster.numnodes); - fprintf(fid,'#SBATCH -t %02i:00:00 \n\n',ceil(cluster.time)); + fprintf(fid,'#SBATCH -t %i:00:00 \n\n',ceil(cluster.time)); if length(find(cluster.email=='@'))>0 fprintf(fid,'#SBATCH --mail-user=%s \n',cluster.email); fprintf(fid,'#SBATCH --mail-type=all \n\n'); end - for i=1:numel(cluster.modules), + for i=1:numel(cluster.modules) fprintf(fid,['module load ' cluster.modules{i} '\n']); end - if isdakota + if strcmp(executable,'issm_dakota.exe') fprintf(fid,'export KMP_AFFINITY="granularity=fine,compact,verbose" \n\n'); end @@ -170,7 +157,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'ibrun -np %i %s/%s %s %s %s\n',cluster.nprocs(),executable,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'ibrun -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -180,38 +167,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && hostname && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist, 2);%use {} instead of \{\} - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/gadi.py b/src/m/classes/clusters/gadi.py index 52d9a30ae..6d7784322 100644 --- a/src/m/classes/clusters/gadi.py +++ b/src/m/classes/clusters/gadi.py @@ -1,11 +1,14 @@ +import os import subprocess +import cluster_defaults from fielddisplay import fielddisplay from helpers import * from IssmConfig import IssmConfig from issmscpin import issmscpin from issmscpout import issmscpout from issmssh import issmssh +from issmdir import issmdir from MatlabFuncs import * from pairoptions import pairoptions try: @@ -29,7 +32,7 @@ def __init__(self, *args): # {{{ self.numnodes = 1 self.cpuspernode = 4 self.memory = 40 # e.g. '40GB' - self.port = '' # typical SSH port + self.port = 0 # typical SSH port self.queue = 'normal' # or "hugemem", "express", etc. self.time = 60 # total minutes of walltime, e.g. 60 => 1 hour self.processor = '' # not usually needed for Gadi @@ -119,7 +122,7 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ """ Create a PBS script for Gadi. Gadi typically uses #PBS lines like: @@ -135,24 +138,10 @@ def BuildQueueScript(self, md, filename): # {{{ modelname = md.miscellaneous.name solution = md.private.solution io_gather = md.settings.io_gather - isvalgrind = md.debug.valgrind - isgprof = md.debug.gprof - isdakota = md.qmu.isdakota - isoceancoupling = md.transient.isoceancoupling - if isgprof: + if md.debug.gprof: print('gprof not typically used on Gadi via this script, ignoring...') - executable = 'issm.exe' - if isdakota: - version_str = IssmConfig('_DAKOTA_VERSION_') - # e.g. "6.14" - version_float = float(version_str[0:3]) - if version_float >= 6.0: - executable = 'issm_dakota.exe' - if isoceancoupling: - executable = 'issm_ocean.exe' - # Convert self.time (minutes) to hh:mm:ss hours = self.time // 60 minutes = self.time % 60 @@ -188,7 +177,7 @@ def BuildQueueScript(self, md, filename): # {{{ fid.write('\n# Now launch the job:\n') - if not isvalgrind: + if not md.debug.valgrind: fid.write('mpiexec -n {} {}/{} {} {}/{} {}\n'.format( self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname)) @@ -211,48 +200,13 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress inputs into a tarball - compressstring = 'tar -zcf {}.tar.gz'.format(dirname) - for f in filelist: - compressstring += ' {}'.format(f) - - subprocess.call(compressstring, shell=True) - print('Uploading input file and queueing script to Gadi...') - directory = self.executionpath - issmscpout(self.name, directory, self.login, self.port, [dirname + '.tar.gz']) + cluster_defaults.UploadQueueJob(self, modelname, dirname, filelist) # }}} def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch): # {{{ - """ - On Gadi, typically you do: - qsub modelname.queue - rather than `./modelname.queue`. - """ - if not isempty(restart): - # If "restart" logic is needed, adapt as necessary - launchcommand = ( - 'cd {executionpath}/{dirname} && qsub {modelname}.queue' - .format(executionpath=self.executionpath, - dirname=dirname, modelname=modelname) - ) - else: - # Create/clean directory, extract tar, then qsub - launchcommand = ( - 'cd {executionpath} && ' - 'rm -rf ./{dirname} && mkdir {dirname} && cd {dirname} && ' - 'mv ../{dirname}.tar.gz ./ && ' - 'tar -zxf {dirname}.tar.gz && ' - 'qsub {modelname}.queue' - .format(executionpath=self.executionpath, - dirname=dirname, modelname=modelname) - ) - - print('Launching solution sequence on Gadi via SSH...') - issmssh(self.name, self.login, self.port, launchcommand) + cluster_defaults.LaunchQueueJobSbatch(self, modelname, dirname, filelist, restart, batch, 3) # }}} def Download(self, dirname, filelist): # {{{ - # Copy files from Gadi back to local machine - directory = '{}/{}/'.format(self.executionpath, dirname) - issmscpin(self.name, self.login, self.port, directory, filelist) + cluster_defaults.Download(self, dirname, filelist) # }}} diff --git a/src/m/classes/clusters/gemini.m b/src/m/classes/clusters/gemini.m index 8cad92912..7d49bea9d 100644 --- a/src/m/classes/clusters/gemini.m +++ b/src/m/classes/clusters/gemini.m @@ -45,21 +45,17 @@ function disp(cluster) % {{{ QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time) end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -76,29 +72,14 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]); fprintf(fid,'cd $PBS_O_WORKDIR\n'); fprintf(fid,'export OMP_NUM_THREADS=1\n'); - fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/issm.exe %s %s %s',cluster.np-1,cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/%s %s %s %s',cluster.np-1,cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); fclose(fid); end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ - - %Execute Queue job if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue ']; else @@ -108,11 +89,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/generic.m b/src/m/classes/clusters/generic.m index 5ec163e16..c239c7717 100644 --- a/src/m/classes/clusters/generic.m +++ b/src/m/classes/clusters/generic.m @@ -78,105 +78,103 @@ function disp(cluster) % {{{ if cluster.np<1 md = checkmessage(md,['number of processors should be at least 1']); end - if isnan(cluster.np), + if isnan(cluster.np) md = checkmessage(md,'number of processors should not be NaN!'); end end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ - - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; - - % Which executable are we calling? - executable='issm.exe'; % default - + function BuildQueueScript(cluster, md, filename, executable) % {{{ + + % Unpack fields used below + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; + isvalgrind = md.debug.valgrind; + isgprof = md.debug.gprof; + isdakota = md.qmu.isdakota; + isoceancoupling = md.transient.isoceancoupling; + + % Determine which executable to call + executable = 'issm.exe'; if isdakota - version=IssmConfig('_DAKOTA_VERSION_'); - version=str2num(version(1:3)); - if(version>=6) executable='issm_dakota.exe'; end + dakota_version_str = IssmConfig('_DAKOTA_VERSION_'); version = str2num(dakota_version_str(1:3)); + if version >= 6, executable = 'issm_dakota.exe'; end end if isoceancoupling - executable='issm_ocean.exe'; + executable = 'issm_ocean.exe'; end if ~ispc() - % Check that executable exists at the right path - if ~exist([cluster.codepath '/' executable],'file'), - error(['File ' cluster.codepath '/' executable ' does not exist']); + + % Verify the executable exists + exepath = [cluster.codepath '/' executable]; + if ~exist(exepath, 'file') + error('File %s does not exist', exepath); end - % Process codepath and prepend empty spaces with \ to avoid errors in queuing script - codepath=strrep(cluster.codepath,' ','\ '); + % Escape spaces in codepath for the shell script + codepath = strrep(cluster.codepath, ' ', '\ '); + execpath = [cluster.executionpath '/' dirname]; - % Write queuing script - fid=fopen(filename, 'w'); - fprintf(fid,'#!%s\n',cluster.shell); + % Build the mpi prefix once (empty string when MPI is not available) + mpiprefix = ''; + if IssmConfig('_HAVE_MPI_') + mpiprefix = sprintf('mpiexec -np %i ', cluster.np); + end + + % Build the core command string if isvalgrind - %Add --gen-suppressions=all to get suppression lines - %fprintf(fid,'LD_PRELOAD=%s \\\n',cluster.valgrindlib); it could be deleted if ismac - if IssmConfig('_HAVE_MPI_') - fprintf(fid,'mpiexec -np %i %s --leak-check=full --leak-check=full --show-leak-kinds=all --error-limit=no --dsymutil=yes --suppressions=%s %s/%s %s %s %s 2> %s.errlog > %s.outlog ',... - cluster.np,cluster.valgrind,cluster.valgrindsup,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname], modelname,modelname,modelname); - else - fprintf(fid,'%s --leak-check=full --dsymutil=yes --error-limit=no --leak-check=full --show-leak-kinds=all --suppressions=%s %s/%s %s %s %s 2> %s.errlog > %s.outlog',... - cluster.valgrind,cluster.valgrindsup,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname], modelname,modelname,modelname); - end + vgflags = '--leak-check=full --show-leak-kinds=all --error-limit=no --dsymutil=yes'; else - if IssmConfig('_HAVE_MPI_'), - fprintf(fid,'mpiexec -np %i %s --leak-check=full --error-limit=no --suppressions=%s %s/%s %s %s %s 2> %s.errlog > %s.outlog',... - cluster.np,cluster.valgrind,cluster.valgrindsup,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname); - else - fprintf(fid,'%s --leak-check=full --error-limit=no --suppressions=%s %s/%s %s %s %s 2> %s.errlog > %s.outlog',... - cluster.valgrind,cluster.valgrindsup,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname); - end + vgflags = '--leak-check=full --error-limit=no'; end - elseif isgprof, - fprintf(fid,'\n gprof %s/issm.exe gmon.out > %s.performance',cluster.codepath,modelname); + cmd = sprintf('%s%s %s --suppressions=%s %s/%s %s %s %s 2> %s.errlog > %s.outlog', ... + mpiprefix, cluster.valgrind, vgflags, cluster.valgrindsup, ... + codepath, executable, solution, execpath, modelname, modelname, modelname); + + elseif isgprof + cmd = sprintf('gprof %s/issm.exe gmon.out > %s.performance', cluster.codepath, modelname); + + elseif cluster.interactive + cmd = sprintf('%s%s/%s %s %s %s', mpiprefix, codepath, executable, solution, execpath, modelname); + else - if cluster.interactive - if IssmConfig('_HAVE_MPI_'), - fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); - else - fprintf(fid,'%s/%s %s %s %s',cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); - end + % Non-interactive: redirect output and run in background + if IssmConfig('_HAVE_MPI_') + cmd = sprintf('%s%s/%s %s %s %s 2> %s/%s.errlog > %s/%s.outlog &', ... + mpiprefix, codepath, executable, solution, execpath, modelname, execpath, modelname, execpath, modelname); else - if IssmConfig('_HAVE_MPI_'), - fprintf(fid,'mpiexec -np %i %s/%s %s %s %s 2> %s.errlog > %s.outlog &',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname); - else - fprintf(fid,'%s/%s %s %s %s 2> %s.errlog > %s.outlog &',cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname,modelname,modelname); - end + cmd = sprintf('%s/%s %s %s %s 2> %s.errlog > %s.outlog &', ... + codepath, executable, solution, execpath, modelname, modelname, modelname); end end - if ~io_gather, %concatenate the output files: - fprintf(fid,'\ncat %s.outbin.* > %s.outbin',modelname,modelname); + + % Write the queue script + fid = fopen(filename, 'w'); + fprintf(fid, '#!%s\n', cluster.shell); + fprintf(fid, '%s', cmd); + if ~io_gather + % Concatenate distributed output files into one + fprintf(fid, '\ncat %s.outbin.* > %s.outbin', modelname, modelname); end fclose(fid); else % Windows - fid=fopen([modelname '.bat'],'w'); - fprintf(fid,'@echo off\n'); - if cluster.np>1, - fprintf(fid,'"C:\\Program Files\\Microsoft MPI\\Bin\\mpiexec.exe" -n %i "%s/%s" %s ./ %s',cluster.np,cluster.codepath,executable,solution,modelname); + batfilename = [filename(1:end-6) '.bat']; + execdir = [cluster.executionpath '\' dirname]; + fid = fopen(batfilename, 'w'); + fprintf(fid, '@echo off\n'); + if cluster.np > 1 + fprintf(fid, '"C:\\Program Files\\Microsoft MPI\\Bin\\mpiexec.exe" -n %i "%s\\%s" %s "%s" %s', ... + cluster.np, cluster.codepath, executable, solution, execdir, modelname); else - fprintf(fid,'"%s\\%s" %s ./ %s',cluster.codepath,executable,solution,modelname); + fprintf(fid, '"%s\\%s" %s "%s" %s', cluster.codepath, executable, solution, execdir, modelname); end fclose(fid); - end - %in interactive mode, create a run file, and errlog and outlog file - if cluster.interactive - fid=fopen([modelname '.errlog'],'w'); fclose(fid); - fid=fopen([modelname '.outlog'],'w'); fclose(fid); end end %}}} @@ -215,7 +213,7 @@ function BuildQueueScriptMultipleModels(cluster, slm, dirnames, modelnames, nps, mpistring=[mpistring sprintf(' %i ',length(dirnames))]; %icecaps, glaciers and earth location, names and number of processors associated: - for i=1:length(dirnames), + for i=1:length(dirnames) mpistring=[mpistring sprintf(' %s/%s %s %i ',cluster.executionpath,dirnames{i},modelnames{i},nps{i})]; end @@ -227,12 +225,6 @@ function BuildQueueScriptMultipleModels(cluster, slm, dirnames, modelnames, nps, %write this long string to disk: fprintf(fid,mpistring); fclose(fid); - - %in interactive mode, create a run file, and errlog and outlog file - if cluster.interactive - fid=fopen([modelname '.errlog'],'w'); fclose(fid); - fid=fopen([modelname '.outlog'],'w'); fclose(fid); - end end %}}} function BuildQueueScriptIceOcean(cluster, md, filename) % {{{ @@ -260,12 +252,6 @@ function BuildQueueScriptIceOcean(cluster, md, filename) % {{{ cluster.np,cluster.valgrind,cluster.valgrindsup,cluster.codepath,executable,solution,cluster.executionpath,modelname,cluster.npocean); end fclose(fid); - - %in interactive mode, create a run file, and errlog and outlog file - if cluster.interactive - fid=fopen([modelname '.errlog'],'w'); fclose(fid); - fid=fopen([modelname '.outlog'],'w'); fclose(fid); - end end %}}} function BuildKrigingQueueScript(cluster, md, filename) % {{{ @@ -285,13 +271,13 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ fid=fopen(filename, 'w'); fprintf(fid,'#!/bin/sh\n'); - if ~isvalgrind, + if ~isvalgrind if cluster.interactive fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s ',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname); else fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s 2> %s.errlog >%s.outlog ',cluster.np,cluster.codepath,[cluster.executionpath '/' modelname],modelname,modelname,modelname); end - elseif isgprof, + elseif isgprof fprintf(fid,'\n gprof %s/kriging.exe gmon.out > %s.performance',cluster.codepath,modelname); else %Add --gen-suppressions=all to get suppression lines @@ -303,12 +289,6 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ else % Windows error('not supported'); end - - %in interactive mode, create a run file, and errlog and outlog file - if cluster.interactive - fid=fopen([modelname '.errlog'],'w'); fclose(fid); - fid=fopen([modelname '.outlog'],'w'); fclose(fid); - end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ @@ -316,15 +296,15 @@ function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ if ~ispc %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), + %filelist contains full paths; tar with -C so only basenames are stored in the archive + root=[issmdir() '/execution/' dirname]; + compressstring=['tar -C ' root ' -zcf ' dirname '.tar.gz']; + for i=1:numel(filelist) if ~exist(filelist{i},'file') error(['File ' filelist{i} ' not found']); end - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; + [~,fname,fext]=fileparts(filelist{i}); + compressstring=[compressstring ' ' fname fext]; end system(compressstring); @@ -334,64 +314,15 @@ function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ if ~ispc - %figure out what shell extension we will use: - if isempty(strfind(cluster.shell,'csh')), - shellext='sh'; - else - shellext='csh'; - end - - if ~isempty(restart) - launchcommand=['source ' cluster.etcpath '/environment.' shellext ' && cd ' cluster.executionpath ' && cd ' dirname ' && source ' modelname '.queue ']; - else - if ~batch - launchcommand=['source ' cluster.etcpath '/environment.' shellext ' && cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && source ' modelname '.queue ']; - else - launchcommand=['source ' cluster.etcpath '/environment.' shellext ' && cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz ']; - end - end - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 1); else - system([modelname '.bat']); - end - - end %}}} - function LaunchQueueJobIceOcean(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - if ~ispc - - %figure out what shell extension we will use: - if isempty(strfind(cluster.shell,'csh')), - shellext='sh'; - else - shellext='csh'; - end - - if ~isempty(restart) - launchcommand=['source ' cluster.etcpath '/environment.' shellext ' && cd ' cluster.executionpath ' && cd ' dirname ' && source ' modelname '.queue ']; - else - if ~batch, - launchcommand=['source ' cluster.etcpath '/environment.' shellext ' && cd ' cluster.executionpath ' && tar -zxf ' dirname '.tar.gz && source ' modelname '.queue ']; - else - launchcommand=['source ' cluster.etcpath '/environment.' shellext ' && cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz ']; - end - end - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); - else - system([modelname '.bat']); + batfile=[cluster.executionpath '\' dirname '\' modelname '.bat']; + system(['"' batfile '"']); end end %}}} function Download(cluster,dirname,filelist) % {{{ - if ispc() - %do nothing - return; - end - %copy files from cluster to current directory directory=[cluster.executionpath '/' dirname '/']; issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); diff --git a/src/m/classes/clusters/generic.py b/src/m/classes/clusters/generic.py index 31e8fe003..048337ab1 100644 --- a/src/m/classes/clusters/generic.py +++ b/src/m/classes/clusters/generic.py @@ -1,3 +1,4 @@ +import os from subprocess import call from fielddisplay import fielddisplay @@ -86,9 +87,9 @@ def checkconsistency(self, md, solution, analyses): # {{{ return md # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ - # Get variables from md + # Unpack fields used below dirname = md.private.runtimename modelname = md.miscellaneous.name solution = md.private.solution @@ -98,68 +99,63 @@ def BuildQueueScript(self, md, filename): # {{{ isdakota = md.qmu.isdakota isoceancoupling = md.transient.isoceancoupling - # Which executable are we calling? - executable = 'issm.exe' # default + # Determine which executable to call + executable = 'issm.exe' if isdakota: - version = IssmConfig('_DAKOTA_VERSION_') - version = float(version[0]) - if version >= 6: executable = 'issm_dakota.exe' + if float(IssmConfig('_DAKOTA_VERSION_')[0]) >= 6: + executable = 'issm_dakota.exe' if isoceancoupling: executable = 'issm_ocean.exe' - # Write queuing script if not ispc(): - fid = open(filename, 'w') - fid.write('#!/bin/sh\n') - if not isvalgrind: - if self.interactive: - if IssmConfig('_HAVE_MPI_')[0]: - fid.write('mpiexec -np {} {}/{} {} {}/{} {}'.format(self.np, self.codepath, executable, solution, self.executionpath, dirname, modelname)) - else: - fid.write('{}/{} {} {}/{} {}'.format(self.codepath, executable, solution, self.executionpath, dirname, modelname)) - else: - if IssmConfig('_HAVE_MPI_')[0]: - fid.write('mpiexec -np {} {}/{} {} {}/{} {} 2> {}.errlog > {}.outlog'. - format(self.np, self.codepath, executable, solution, self.executionpath, dirname, modelname, modelname, modelname)) - else: - fid.write('{}/{} {} {}/{} {} 2> {}.errlog > {}.outlog '. - format(self.codepath, executable, solution, self.executionpath, dirname, modelname, modelname, modelname)) + + # Verify the executable exists + exepath = '{}/{}'.format(self.codepath, executable) + if not os.path.isfile(exepath): + raise RuntimeError('File {} does not exist'.format(exepath)) + + execpath = '{}/{}'.format(self.executionpath, dirname) + mpiprefix = 'mpiexec -np {} '.format(self.np) if IssmConfig('_HAVE_MPI_')[0] else '' + + # Build the core command string + if isvalgrind: + supstring = ' '.join('--suppressions=' + s for s in self.valgrindsup) + cmd = '{}{} --leak-check=full {} {}/{} {} {} {} 2> {}.errlog > {}.outlog'.format( + mpiprefix, self.valgrind, supstring, + self.codepath, executable, solution, execpath, modelname, + modelname, modelname) + elif isgprof: - fid.write('\n gprof {}/{} gmon.out > {}.performance'.format(self.codepath, executable, modelname)) - else: - #Add --gen -suppressions = all to get suppression lines - #fid.write('LD_PRELOAD={} \\\n'.format(self.valgrindlib)) it could be deleted - supstring = '' - for supfile in self.valgrindsup: - supstring += ' --suppressions=' + supfile - - if IssmConfig('_HAVE_MPI_')[0]: - fid.write('mpiexec -np {} {} --leak-check=full {} {}/{} {} {}/{} {} 2> {}.errlog > {}.outlog '. - format(self.np, self.valgrind, supstring, self.codepath, executable, solution, self.executionpath, dirname, modelname, modelname, modelname)) - else: - fid.write('{} --leak-check=full {} {}/{} {} {}/{} {} 2> {}.errlog > {}.outlog '. - format(self.valgrind, supstring, self.codepath, executable, solution, self.executionpath, dirname, modelname, modelname, modelname)) + cmd = 'gprof {}/{} gmon.out > {}.performance'.format(self.codepath, executable, modelname) - if not io_gather: #concatenate the output files: - fid.write('\ncat {}.outbin .*>{}.outbin'.format(modelname, modelname)) - fid.close() + elif self.interactive: + cmd = '{}{}/{} {} {} {}'.format(mpiprefix, self.codepath, executable, solution, execpath, modelname) - else: # Windows - fid = open(modelname + '.bat', 'w') - fid.write('@echo off\n') - if self.interactive: - fid.write('"{}/{}" {} "{}/{}" {} '.format(self.codepath, executable, solution, self.executionpath, dirname, modelname)) else: - fid.write('"{}/{}" {} "{}/{}" {} 2>{}.errlog>{}.outlog'. - format(self.codepath, executable, solution, self.executionpath, dirname, modelname, modelname, modelname)) - fid.close() + # Non-interactive: redirect output and run in background + cmd = '{}{}/{} {} {} {} 2> {}.errlog > {}.outlog &'.format( + mpiprefix, self.codepath, executable, solution, execpath, modelname, + modelname, modelname) + + # Write the queue script + with open(filename, 'w') as fid: + fid.write('#!{}\n'.format(self.shell)) + fid.write(cmd) + if not io_gather: + # Concatenate distributed output files into one + fid.write('\ncat {}.outbin.* > {}.outbin'.format(modelname, modelname)) - #in interactive mode, create a run file, and errlog and outlog file - if self.interactive: - fid = open(modelname + '.errlog', 'w') - fid.close() - fid = open(modelname + '.outlog', 'w') - fid.close() + else: # Windows + + batfilename = filename[:-6] + '.bat' + execdir = '{}/{}'.format(self.executionpath, dirname) + with open(batfilename, 'w') as fid: + fid.write('@echo off\n') + if self.interactive: + fid.write('"{}/{}" {} "{}" {}'.format(self.codepath, executable, solution, execdir, modelname)) + else: + fid.write('"{}/{}" {} "{}" {} 2> {}.errlog > {}.outlog'.format( + self.codepath, executable, solution, execdir, modelname, modelname, modelname)) # }}} def BuildKrigingQueueScript(self, md, filename): # {{{ @@ -194,7 +190,8 @@ def BuildKrigingQueueScript(self, md, filename): # {{{ fid.close() else: # Windows - fid = open(modelname + '.bat', 'w') + batfilename = filename[:-6] + '.bat' + fid = open(batfilename, 'w') fid.write('@echo off\n') if self.interactive: fid.write('"{}/issm.exe" {} "{}/{}" {} '.format(self.codepath, solution, self.executionpath, modelname, modelname)) @@ -202,22 +199,15 @@ def BuildKrigingQueueScript(self, md, filename): # {{{ fid.write('"{}/issm.exe" {} "{}/{}" {} 2>{}.errlog>{}.outlog'.format (self.codepath, solution, self.executionpath, modelname, modelname, modelname, modelname)) fid.close() - - # In interactive mode, create a run file, and errlog and outlog file - if self.interactive: - fid = open(modelname + '.errlog', 'w') - fid.close() - fid = open(modelname + '.outlog', 'w') - fid.close() # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress the files into one zip - compressstring = 'tar -zcf {}.tar.gz '.format(dirname) - for file in filelist: - compressstring += ' {}'.format(file) - if self.interactive: - compressstring += ' {}.errlog {}.outlog '.format(modelname, modelname) + # Compress the files into one zip. + # filelist contains full paths; use -C so only basenames are stored in the archive. + root = os.path.join(self.executionpath, dirname) + compressstring = 'tar -C {} -zcf {}.tar.gz'.format(root, dirname) + for filepath in filelist: + compressstring += ' {}'.format(os.path.basename(filepath)) call(compressstring, shell=True) issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz']) @@ -226,19 +216,16 @@ def UploadQueueJob(self, modelname, dirname, filelist): # {{{ def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch): # {{{ if not isempty(restart): - launchcommand = 'cd {} && cd {} chmod 755 {}.queue && ./{}.queue'.format(self.executionpath, dirname, modelname, modelname) + launchcommand = 'cd {} && cd {} && chmod 755 {}.queue && ./{}.queue'.format(self.executionpath, dirname, modelname, modelname) else: if batch: - launchcommand = 'cd {} && rm -rf ./{} && mkdir {} && cd {} && mv ../{}.tar.gz ./&& tar -zxf {}.tar.gz'.format(self.executionpath, dirname, dirname, dirname, dirname, dirname) + launchcommand = 'cd {} && rm -rf ./{} && mkdir {} && cd {} && mv ../{}.tar.gz ./ && tar -zxf {}.tar.gz'.format(self.executionpath, dirname, dirname, dirname, dirname, dirname) else: - launchcommand = 'cd {} && rm -rf ./{} && mkdir {} && cd {} && mv ../{}.tar.gz ./&& tar -zxf {}.tar.gz && chmod 755 {}.queue && ./{}.queue'.format(self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname, modelname) + launchcommand = 'chmod 755 {}/{}/{}.queue && {}/{}/{}.queue'.format(self.executionpath, dirname, modelname, self.executionpath, dirname, modelname) issmssh(self.name, self.login, self.port, launchcommand) # }}} def Download(self, dirname, filelist): # {{{ - if ispc(): - # Do nothing - return # Copy files from cluster to current directory directory = '{}/{}/'.format(self.executionpath, dirname) issmscpin(self.name, self.login, self.port, directory, filelist) diff --git a/src/m/classes/clusters/generic_static.m b/src/m/classes/clusters/generic_static.m deleted file mode 100755 index 0b471d215..000000000 --- a/src/m/classes/clusters/generic_static.m +++ /dev/null @@ -1,140 +0,0 @@ -%GENERIC cluster class definition -% -% Usage: -% cluster=generic_static('name','astrid','np',3); -% cluster=generic('name',oshostname(),'np',3,'login','username'); -% -% TODO: -% - Add support for restart to Windows (under MSYS2), then activate tests 125 -% and 126 in test suite -% - -classdef generic_static - properties (SetAccess=public) - % {{{ - name=''; - np=1; - codepath=fileparts(which('issm.exe')); - executionpath='.'; - interactive=1; - shell='/bin/sh'; - %}}} - end - methods - function cluster=generic_static(varargin) % {{{ - - %use provided options to change fields - options=pairoptions(varargin{:}); - - %get name - cluster.name=getfieldvalue(options,'name',oshostname()); - - %initialize cluster using user settings if provided - if (exist([cluster.name '_settings'])==2), eval([cluster.name '_settings']); end - - %OK get other fields - cluster=AssignObjectFields(pairoptions(varargin{:}),cluster); - end - %}}} - function disp(cluster) % {{{ - % display the object - disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1))); - disp(sprintf(' name: %s',cluster.name)); - disp(sprintf(' np: %i',cluster.np)); - disp(sprintf(' codepath: %s',cluster.codepath)); - disp(sprintf(' executionpath: %s',cluster.executionpath)); - disp(sprintf(' interactive: %s',cluster.interactive)); - disp(sprintf(' shell: %s',cluster.shell)); - end - %}}} - function numprocs=nprocs(cluster) % {{{ - numprocs=cluster.np; - end - %}}} - function md = checkconsistency(cluster,md,solution,analyses) % {{{ - if cluster.np<1 - md = checkmessage(md,['number of processors should be at least 1']); - end - if isnan(cluster.np), - md = checkmessage(md,'number of processors should not be NaN!'); - end - end - %}}} - function BuildQueueScript(cluster, md, filename) % {{{ - - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; - - % Which executable are we calling? - executable='issm.exe'; % default - if isdakota - version=IssmConfig('_DAKOTA_VERSION_'); - version=str2num(version(1:3)); - if(version>=6) executable='issm_dakota.exe'; end - end - if isoceancoupling - executable='issm_ocean.exe'; - end - - if ~ispc() - % Check that executable exists at the right path - if ~exist([cluster.codepath '/' executable],'file') - error(['File ' cluster.codepath '/' executable ' does not exist']); - end - - % Process codepath and prepend empty spaces with \ to avoid errors in queuing script - codepath=strrep(cluster.codepath,' ','\ '); - - % Write queuing script - fid=fopen(filename, 'w'); - fprintf(fid,'#!%s\n',cluster.shell); - fprintf(fid,['%s/mpiexec -np %i %s/%s %s %s %s \n'],codepath,cluster.np,codepath,executable,solution,'./',modelname); - fclose(fid); - else % Windows - fid=fopen([modelname '.bat'], 'w'); - fprintf(fid,'@echo off\n'); - if cluster.np>1 - fprintf(fid,'"%s\\mpiexec.exe" -n %i "%s/%s" %s ./ %s',cluster.codepath,cluster.np,cluster.codepath,executable,solution,modelname); - else - fprintf(fid,'"%s\\%s" %s ./ %s',cluster.codepath,executable,solution,modelname); - end - fclose(fid); - end - - %Create an errlog and outlog file - fid=fopen([modelname '.errlog'],'w'); fclose(fid); - fid=fopen([modelname '.outlog'],'w'); fclose(fid); - end - %}}} - function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - % Do nothing - return; - end %}}} - function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - if ~ispc - % Figure out which file extension to use - if isempty(strfind(cluster.shell,'csh')) - shellext='sh'; - else - shellext='csh'; - end - - launchcommand=['source ' modelname '.queue ']; - issmssh(cluster.name,'',0,launchcommand); - else - system([modelname '.bat']); - end - end %}}} - function Download(cluster,dirname,filelist) % {{{ - % Do nothing - return; - end %}}} - end -end diff --git a/src/m/classes/clusters/generic_static.py b/src/m/classes/clusters/generic_static.py deleted file mode 100755 index 08254cbc0..000000000 --- a/src/m/classes/clusters/generic_static.py +++ /dev/null @@ -1,138 +0,0 @@ -import math -import os -import subprocess -import numpy as np -from IssmConfig import IssmConfig -from issmdir import issmdir -from issmssh import issmssh -from issmscpin import issmscpin -from issmscpout import issmscpout -from MatlabFuncs import * -from pairoptions import pairoptions - - -class generic_static(object): - """GENERIC cluster class definition - - Usage: - cluster = generic_static('name', 'astrid', 'np', 3) - """ - - def __init__(self, *args): # {{{ - codepath = subprocess.check_output(["which", "issm.exe"]).rstrip('\r\n') - codepath = codepath.replace('/issm.exe', '') - - self.name = '' - self.np = 1 - self.codepath = codepath - self.executionpath = '.' - self.interactive = 1 - self.shell = '/bin/sh' - - #use provided options to change fields - options = pairoptions(*args) - - #get name - self.name = oshostname() - - #initialize cluster using user settings if provided - if os.path.exists(self.name + '_settings.py'): - exec(compile(open(self.name + '_settings.py').read(), self.name + '_settings.py', 'exec'), globals()) - - #OK get other fields - self = options.AssignObjectFields(self) - # }}} - - def __repr__(self): # {{{ - # display the object - s = "class '%s' object '%s' = \n" % (type(self), 'self') - s += " name: %s\n" % self.name - s += " np: %i\n" % self.np - s += " codepath: %s\n" % self.codepath - s += " shell: %s\n" % self.shell - return s - # }}} - - def nprocs(self): # {{{ - return self.np - # }}} - - def checkconsistency(self, md, solution, analyses): # {{{ - if self.np < 1: - md.checkmessage('number of processors should be at least 1') - if np.isnan(self.np): - md.checkmessage('number of processors should not be NaN!') - - return md - # }}} - - def BuildQueueScript(self, md, filename): # {{{ - - # Get variables from md - dirname = md.private.runtimename - modelname = md.miscellaneous.name - solution = md.private.solution - io_gather = md.settings.io_gather - isvalgrind = md.debug.valgrind - isgprof = md.debug.gprof - isdakota = md.qmu.isdakota - isoceancoupling = md.transient.isoceancoupling - - # Which executable are we calling? - executable = 'issm.exe' # default - - if isdakota: - version = IssmConfig('_DAKOTA_VERSION_') - version = float(version[0]) - if version >= 6: - executable = 'issm_dakota.exe' - if isoceancoupling: - executable = 'issm_ocean.exe' - - # Check that executable exists at the right path - if not os.path.isfile(self.codepath + '/' + executable): - raise RuntimeError('File ' + self.codepath + '/' + executable + ' does not exist') - - # Process codepath and prepend empty spaces with \ to avoid errors in queuing script - codepath = self.codepath.replace(' ', r'\ ') - - # Write queuing script - fid = open(filename, 'w') - fid.write('#!{}'.format(self.shell) + '\n') - fid.write('{}/mpiexec -np {} {}/{} {} {} {}'.format(codepath, self.np, codepath, executable, solution, './', modelname)) - fid.close() - - # Set permissions on queue script so that it can be run - subprocess.call(['chmod', '0755', modelname + '.queue']) - - # Create an errlog and outlog file - fid = open(modelname + '.errlog', 'w') - fid.close() - fid = open(modelname + '.outlog', 'w') - fid.close() - # }}} - - def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Do nothing - return - # }}} - - def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch): # {{{ - if not ispc(): - # Figure out which file extension to use - if self.shell.find('csh') == -1: - shellext='sh' - else: - shellext='csh' - - launchcommand = './' + modelname + '.queue' - subprocess.call([launchcommand]) - else: - launchcommand = './' + modelname + '.bat' - subprocess.call([launchcommand]) - # }}} - - def Download(self, dirname, filelist): # {{{ - # Do nothing - return - # }}} diff --git a/src/m/classes/clusters/greenplanet.m b/src/m/classes/clusters/greenplanet.m index d3c991f5c..5de634150 100644 --- a/src/m/classes/clusters/greenplanet.m +++ b/src/m/classes/clusters/greenplanet.m @@ -68,21 +68,17 @@ function disp(cluster) % {{{ end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -105,16 +101,16 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n'); %FIXME fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); - fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec -n %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end fclose(fid); %in interactive mode, create a run file, and errlog and outlog file - if cluster.interactive, + if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec -n %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -124,38 +120,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && hostname && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/hpc.m b/src/m/classes/clusters/hpc.m index c84b7d1bf..16d3a5e46 100644 --- a/src/m/classes/clusters/hpc.m +++ b/src/m/classes/clusters/hpc.m @@ -71,14 +71,10 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -100,21 +96,17 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ fclose(fid); end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -129,7 +121,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n'); %FIXME fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); - fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -138,7 +130,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -148,24 +140,9 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && qsub ' modelname '.queue ']; else @@ -175,11 +152,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/hpc_simba.m b/src/m/classes/clusters/hpc_simba.m index b5a1a1e23..d54f36f3e 100644 --- a/src/m/classes/clusters/hpc_simba.m +++ b/src/m/classes/clusters/hpc_simba.m @@ -67,14 +67,10 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -96,21 +92,17 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ fclose(fid); end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -140,7 +132,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'module load intel18/impi-18\n'); fprintf(fid,'\n'); fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); - fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -149,7 +141,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -159,24 +151,9 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && qsub ' modelname '.queue ']; else @@ -186,11 +163,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/local.m b/src/m/classes/clusters/local.m index c54282036..2bf16850c 100644 --- a/src/m/classes/clusters/local.m +++ b/src/m/classes/clusters/local.m @@ -45,12 +45,12 @@ function disp(cluster) % {{{ if cluster.np<1 md = checkmessage(md,['number of processors should be at least 1']); end - if isnan(cluster.np), + if isnan(cluster.np) md = checkmessage(md,'number of processors should not be NaN!'); end end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; @@ -78,7 +78,8 @@ function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{ %do nothing really. end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch)% {{{ - system(['source ' modelname '.queue']); + root=[issmdir() '/execution/' dirname]; + system(['source ' root '/' modelname '.queue']); end %}}} function Download(cluster,dirname,filelist)% {{{ end %}}} diff --git a/src/m/classes/clusters/local.py b/src/m/classes/clusters/local.py index ad8617de9..7f64ac36f 100644 --- a/src/m/classes/clusters/local.py +++ b/src/m/classes/clusters/local.py @@ -1,3 +1,4 @@ +import subprocess from subprocess import call import numpy as np @@ -58,7 +59,7 @@ def checkconsistency(self, md, solution, analyses): # {{{ return md # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename @@ -88,7 +89,8 @@ def UploadQueueJob(cluster, modelname, dirname, filelist): # {{{ # }}} def LaunchQueueJob(cluster, modelname, dirname, filelist, restart, batch): # {{{ - subprocess.call('source ' + modelname + '.queue') + root = issmdir() + '/execution/' + dirname + subprocess.call('source ' + root + '/' + modelname + '.queue', shell=True) # }}} def Download(cluster, dirname, filelist): # {{{ diff --git a/src/m/classes/clusters/localpfe.m b/src/m/classes/clusters/localpfe.m index 772970741..4baa8a576 100644 --- a/src/m/classes/clusters/localpfe.m +++ b/src/m/classes/clusters/localpfe.m @@ -27,7 +27,7 @@ function cluster=localpfe(varargin) % {{{ %Change the defaults if ispc and not ismingw - if ispc & ~ismingw, + if ispc & ~ismingw cluster.codepath = [issmdir() '\bin']; cluster.etcpath = [issmdir() '\etc']; cluster.executionpath = [issmdir() '\execution']; @@ -69,12 +69,12 @@ function disp(cluster) % {{{ if cluster.np<1 md = checkmessage(md,['number of processors should be at least 1']); end - if isnan(cluster.np), + if isnan(cluster.np) md = checkmessage(md,'number of processors should not be NaN!'); end end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; @@ -89,9 +89,9 @@ function BuildQueueScript(cluster, md, filename) % {{{ %write queuing script %what is the executable being called? executable='issm.exe'; - if isdakota, + if isdakota version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3)); - if (version>=6), + if (version>=6) executable='issm_dakota.exe'; end end @@ -158,7 +158,7 @@ function BuildQueueScriptMultipleModels(cluster, slm, dirnames, modelnames, nps, mpistring=[mpistring sprintf(' %i ',length(dirnames))]; %icecaps, glaciers and earth location, names and number of processors associated: - for i=1:length(dirnames), + for i=1:length(dirnames) mpistring=[mpistring sprintf(' %s/%s %s %i ',cluster.executionpath,dirnames{i},modelnames{i},nps{i})]; end @@ -250,12 +250,15 @@ function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{ if ~ispc || ismingw %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.run ' modelname '.errlog ' modelname '.outlog ']; + %filelist contains full paths; tar with -C so only basenames are stored in the archive + root=[issmdir() '/execution/' dirname]; + compressstring=['tar -C ' root ' -zcf ' dirname '.tar.gz']; + for i=1:numel(filelist) + if ~exist(filelist{i},'file') + error(['File ' filelist{i} ' not found']); + end + [~,fname,fext]=fileparts(filelist{i}); + compressstring=[compressstring ' ' fname fext]; end system(compressstring); @@ -264,37 +267,13 @@ function UploadQueueJob(cluster,modelname,dirname,filelist)% {{{ end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch)% {{{ - %figure out what shell extension we will use: - if isempty(strfind(cluster.shell,'csh')), - shellext='sh'; - else - shellext='csh'; - end - - if cluster.verbose, %Execute Queue job end - launchcommand=['cd ' cluster.executionpath ' && rm -rf *.lock && rm -rf ADOLC* && tar -zxf ' dirname '.tar.gz && rm -rf *.tar.gz']; issmssh(cluster.name,cluster.login,cluster.port,launchcommand); - end %}}} - function LaunchQueueJobIceOcean(cluster,modelname,dirname,filelist,restart,batch)% {{{ - - %figure out what shell extension we will use: - if isempty(strfind(cluster.shell,'csh')), - shellext='sh'; - else - shellext='csh'; - end - - if cluster.verbose, %Execute Queue job end - - launchcommand=['cd ' cluster.executionpath ' && rm -rf *.lock && tar -zxf ' dirname '.tar.gz && rm -rf *.tar.gz']; - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); - end %}}} function Download(cluster,dirname,filelist)% {{{ - if ispc && ~ismingw, + if ispc && ~ismingw %do nothing return; end diff --git a/src/m/classes/clusters/lonestar.m b/src/m/classes/clusters/lonestar.m index 3832d60b7..49e81d7fa 100644 --- a/src/m/classes/clusters/lonestar.m +++ b/src/m/classes/clusters/lonestar.m @@ -78,14 +78,10 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -107,34 +103,19 @@ function BuildKrigingQueueScript(cluster, md, filename) % {{{ fclose(fid); end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; - %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end - - executable='issm.exe'; - if isdakota - version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3)); - if (version>=6), - executable='issm_dakota.exe'; - end - end - if isoceancoupling - executable='issm_ocean.exe'; - end + %checks + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end - %write queuing script + %write queuing script fid=fopen(filename,'w'); fprintf(fid,'#!/bin/bash\n'); @@ -145,19 +126,17 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'#SBATCH -n %i \n',cluster.numnodes*max(cluster.nprocs()/cluster.numnodes,24)); fprintf(fid,'#SBATCH -N %i \n',cluster.numnodes); fprintf(fid,'#SBATCH -t %02i:%02i:00 \n\n',floor(cluster.time/3600),floor(mod(cluster.time,3600)/60)); - for i=1:numel(cluster.modules), + for i=1:numel(cluster.modules) fprintf(fid,['module load ' cluster.modules{i} '\n']); end - if isdakota + if strcmp(executable,'issm_dakota.exe') fprintf(fid,'export KMP_AFFINITY="granularity=fine,compact,verbose" \n\n'); end if length(find(cluster.email=='@'))>0 fprintf(fid,'#SBATCH --mail-user=%s \n',cluster.email); fprintf(fid,'#SBATCH --mail-type=end \n\n'); - - %fprintf(fid,'ssh login1 "mail -s ''SLURM Jobid=${SLURM_JOBID} Name=${SLURM_JOB_NAME} Began on Lonestar 5.'' %s <<< ''Job Started'' " \n\n',cluster.email); end fprintf(fid,'export PATH="$PATH:."\n\n'); @@ -174,7 +153,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'ibrun -np %i %s/%s %s %s %s\n',cluster.nprocs(),executable,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'ibrun -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -184,38 +163,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && hostname && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/maui.m b/src/m/classes/clusters/maui.m index d221a16bb..e764a236f 100644 --- a/src/m/classes/clusters/maui.m +++ b/src/m/classes/clusters/maui.m @@ -69,21 +69,17 @@ function disp(cluster) % {{{ if isempty(cluster.executionpath), md = checkmessage(md,'executionpath empty'); end end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -101,7 +97,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n'); %FIXME fprintf(fid,'module swap PrgEnv-cray PrgEnv-intel\n'); fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); - fprintf(fid,'srun -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'srun -n %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -110,7 +106,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec -n %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -120,38 +116,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && hostname && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/pace.m b/src/m/classes/clusters/pace.m index e2afcc490..113608880 100644 --- a/src/m/classes/clusters/pace.m +++ b/src/m/classes/clusters/pace.m @@ -51,23 +51,18 @@ function disp(cluster) % {{{ end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end - executable = 'issm.exe'; %write queuing script fid=fopen(filename, 'w'); @@ -92,35 +87,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/pfe.m b/src/m/classes/clusters/pfe.m index 4835be184..1e10fe814 100644 --- a/src/m/classes/clusters/pfe.m +++ b/src/m/classes/clusters/pfe.m @@ -76,66 +76,66 @@ function disp(cluster) % {{{ QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.nprocs(),cluster.time) %now, check cluster.cpuspernode according to processor type - if strcmpi(cluster.processor,'ivy'), - if cluster.hyperthreading, - if ((cluster.cpuspernode>40 ) | (cluster.cpuspernode<1)), + if strcmpi(cluster.processor,'ivy') + if cluster.hyperthreading + if ((cluster.cpuspernode>40 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 40 for ''ivy'' processors in hyperthreading mode'); end else - if ((cluster.cpuspernode>20 ) | (cluster.cpuspernode<1)), + if ((cluster.cpuspernode>20 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 20 for ''ivy'' processors'); end end - elseif strcmpi(cluster.processor,'bro'), - if cluster.hyperthreading, - if ((cluster.cpuspernode>56 ) | (cluster.cpuspernode<1)), + elseif strcmpi(cluster.processor,'bro') + if cluster.hyperthreading + if ((cluster.cpuspernode>56 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 56 for ''bro'' processors in hyperthreading mode'); end else - if ((cluster.cpuspernode>28 ) | (cluster.cpuspernode<1)), + if ((cluster.cpuspernode>28 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 28 for ''bro'' processors'); end end - elseif strcmpi(cluster.processor,'has'), - if cluster.hyperthreading, - if ((cluster.cpuspernode>48 ) | (cluster.cpuspernode<1)), + elseif strcmpi(cluster.processor,'has') + if cluster.hyperthreading + if ((cluster.cpuspernode>48 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 48 for ''has'' processors in hyperthreading mode'); end else - if ((cluster.cpuspernode>24 ) | (cluster.cpuspernode<1)), + if ((cluster.cpuspernode>24 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 24 for ''has'' processors'); end end - elseif strcmpi(cluster.processor,'san'), - if cluster.hyperthreading, - if ((cluster.cpuspernode>32 ) | (cluster.cpuspernode<1)), + elseif strcmpi(cluster.processor,'san') + if cluster.hyperthreading + if ((cluster.cpuspernode>32 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 32 for ''san'' processors in hyperthreading mode'); end else - if ((cluster.cpuspernode>16 ) | (cluster.cpuspernode<1)), + if ((cluster.cpuspernode>16 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 16 for ''san'' processors'); end end - elseif strcmpi(cluster.processor,'cas_ait'), - if cluster.hyperthreading, - if ((cluster.cpuspernode>80 ) | (cluster.cpuspernode<1)), + elseif strcmpi(cluster.processor,'cas_ait') + if cluster.hyperthreading + if ((cluster.cpuspernode>80 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 80 for ''cas_ait'' processors in hyperthreading mode'); end else - if ((cluster.cpuspernode>40 ) | (cluster.cpuspernode<1)), + if ((cluster.cpuspernode>40 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 40 for ''cas_ait'' processors'); end end - elseif strcmpi(cluster.processor,'rom_ait'), - if cluster.hyperthreading, - if ((cluster.cpuspernode>256 ) | (cluster.cpuspernode<1)), + elseif strcmpi(cluster.processor,'rom_ait') + if cluster.hyperthreading + if ((cluster.cpuspernode>256 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 80 for ''rom_ait'' processors in hyperthreading mode'); end else - if ((cluster.cpuspernode>128 ) | (cluster.cpuspernode<1)), + if ((cluster.cpuspernode>128 ) | (cluster.cpuspernode<1)) md = checkmessage(md,'cpuspernode should be between 1 and 128 for ''rom_ait'' processors'); end end @@ -153,33 +153,19 @@ function disp(cluster) % {{{ end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; - - %checks - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; + isvalgrind = md.debug.valgrind; - executable='issm.exe'; - if isdakota - version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3)); - if (version>=6), - executable='issm_dakota.exe'; - end - end - if isoceancoupling - executable='issm_ocean.exe'; - end + %checks + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end - %write queuing script + %write queuing script fid=fopen(filename, 'w'); fprintf(fid,'#PBS -S /bin/bash\n'); % fprintf(fid,'#PBS -N %s\n',modelname); @@ -215,7 +201,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([filename '.run'],'w'); - if cluster.interactive==10, + if cluster.interactive==10 fprintf(fid,'module unload mpi-mvapich2/1.4.1/gcc\n'); fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[pwd() '/run'],modelname); else @@ -282,7 +268,7 @@ function BuildQueueScriptMultipleModels(cluster, slm, dirnames, modelnames, nps, mpistring=[mpistring sprintf(' %i ',length(dirnames))]; %icecaps, glaciers and earth location, names and number of processors associated: - for i=1:length(dirnames), + for i=1:length(dirnames) mpistring=[mpistring sprintf(' %s/%s %s %i ',cluster.executionpath,dirnames{i},modelnames{i},nps{i})]; end @@ -322,22 +308,19 @@ function BuildQueueScriptMultipleModels(cluster, slm, dirnames, modelnames, nps, end end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; + isvalgrind = md.debug.valgrind; - %checks - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + %checks + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end - %write queuing script + %write queuing script fid=fopen(filename, 'w'); fprintf(fid,'#PBS -S /bin/bash\n'); % fprintf(fid,'#PBS -N %s\n',modelname); @@ -362,9 +345,9 @@ function BuildQueueScript(cluster, md, filename) % {{{ fclose(fid); %in interactive mode, create a run file, and errlog and outlog file - if cluster.interactive, + if cluster.interactive fid=fopen([modelname '.run'],'w'); - if ~isvalgrind, + if ~isvalgrind fprintf(fid,'mpiexec -np %i %s/kriging.exe %s %s\n',cluster.nprocs(),cluster.codepath,[cluster.executionpath '/' modelname],modelname); else fprintf(fid,'mpiexec -np %i valgrind --leak-check=full %s/kriging.exe %s %s\n',cluster.nprocs(),cluster.codepath,[cluster.executionpath '/' modelname],modelname); @@ -430,25 +413,28 @@ function BuildOceanQueueScript(cluster, md, filename) % {{{ function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.run ' modelname '.errlog ' modelname '.outlog ']; + %filelist contains full paths; tar with -C so only basenames are stored in the archive + root=[issmdir() '/execution/' dirname]; + compressstring=['tar -C ' root ' -zcf ' dirname '.tar.gz']; + for i=1:numel(filelist) + if ~exist(filelist{i},'file') + error(['File ' filelist{i} ' not found']); + end + [~,fname,fext]=fileparts(filelist{i}); + compressstring=[compressstring ' ' fname fext]; end system(compressstring); disp('uploading input file and queueing script'); - if cluster.interactive==10, + if cluster.interactive==10 directory=[pwd() '/run/']; - elseif cluster.interactive, + elseif cluster.interactive directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive)]; else directory=cluster.executionpath; end - if cluster.bbftp, + if cluster.bbftp issmbbftpout(cluster.name,directory,cluster.login,cluster.port,cluster.numstreams,{[dirname '.tar.gz']}); else issmscpout(cluster.name,directory,cluster.login,cluster.port,{[dirname '.tar.gz']}); @@ -459,41 +445,36 @@ function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ %launch command, to be executed via ssh - if cluster.interactive, + if cluster.interactive if ~isempty(restart) launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive)]; else - if cluster.interactive==10, + if cluster.interactive==10 launchcommand=['cd ' pwd() '/run && tar -zxf ' dirname '.tar.gz']; else launchcommand=['cd ' cluster.executionpath '/Interactive' num2str(cluster.interactive) ' && tar -zxf ' dirname '.tar.gz']; end end + issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + else - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && /PBS/bin/qsub ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && /PBS/bin/qsub ' modelname '.queue ']; - end + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 3); end - %Execute Queue job - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function Download(cluster,dirname,filelist) % {{{ %copy files from cluster to current directory - if cluster.interactive==10, + if cluster.interactive==10 directory=[pwd() '/run/']; - elseif ~cluster.interactive, + elseif ~cluster.interactive directory=[cluster.executionpath '/' dirname '/']; else directory=[cluster.executionpath '/Interactive' num2str(cluster.interactive) '/']; end - if cluster.bbftp, + if cluster.bbftp issmbbftpin(cluster.name, cluster.login, cluster.port, cluster.numstreams, directory, filelist); else issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); diff --git a/src/m/classes/clusters/pfe.py b/src/m/classes/clusters/pfe.py index 8627b9579..fcc287dc6 100644 --- a/src/m/classes/clusters/pfe.py +++ b/src/m/classes/clusters/pfe.py @@ -1,3 +1,4 @@ +import os import subprocess from fielddisplay import fielddisplay @@ -6,6 +7,7 @@ from issmscpin import issmscpin from issmscpout import issmscpout from issmssh import issmssh +from issmdir import issmdir from MatlabFuncs import * from pairoptions import pairoptions try: @@ -148,30 +150,17 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename modelname = md.miscellaneous.name solution = md.private.solution io_gather = md.settings.io_gather - isvalgrind = md.debug.valgrind - isgprof = md.debug.gprof - isdakota = md.qmu.isdakota - isoceancoupling = md.transient.isoceancoupling - if isgprof: + if md.debug.gprof: print('gprof not supported by cluster, ignoring...') - executable = 'issm.exe' - if isdakota: - version = IssmConfig('_DAKOTA_VERSION_')[0:2] - version = float(version) - if version >= 6: - executable = 'issm_dakota.exe' - if isoceancoupling: - executable = 'issm_ocean.exe' - # Write queuing script fid = open(filename, 'w') fid.write('#PBS -S /bin/bash\n') @@ -199,16 +188,17 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress the files into one zip - compressstring = 'tar -zcf {}.tar.gz'.format(dirname) - for file in filelist: - compressstring += ' {}'.format(file) + # Compress the files into one zip. + # filelist contains full paths; use -C so only basenames are stored in the archive. + root = issmdir() + '/execution/' + dirname + compressstring = 'tar -C {} -zcf {}.tar.gz'.format(root, dirname) + for filepath in filelist: + if not os.path.isfile(filepath): + raise Exception('File {} not found'.format(filepath)) + compressstring += ' {}'.format(os.path.basename(filepath)) subprocess.call(compressstring, shell=True) - print('uploading input file and queueing script') - directory = self.executionpath - issmscpout(self.name, directory, self.login, self.port, [dirname + '.tar.gz']) - + issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz']) # }}} def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch): # {{{ diff --git a/src/m/classes/clusters/pollux.m b/src/m/classes/clusters/pollux.m index 9247d64c0..30c1b1ed7 100644 --- a/src/m/classes/clusters/pollux.m +++ b/src/m/classes/clusters/pollux.m @@ -45,21 +45,17 @@ function disp(cluster) % {{{ QueueRequirements(available_queues,queue_requirements_time,queue_requirements_np,cluster.queue,cluster.np,cluster.time) end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -67,7 +63,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'#PBS -l walltime=%i\n',cluster.time*60); %walltime is in seconds. fprintf(fid,'#PBS -N %s\n',modelname); fprintf(fid,'#PBS -l ncpus=%i\n',cluster.np); - if ~isempty(queue), + if ~isempty(queue) fprintf(fid,'#PBS -q %s\n',cluster.queue); end fprintf(fid,'#PBS -o %s.outlog \n',modelname); @@ -75,13 +71,11 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export PBS_O_WORKDIR=%s\n',[cluster.executionpath '/' dirname]); fprintf(fid,'cd $PBS_O_WORKDIR\n'); fprintf(fid,'export OMP_NUM_THREADS=1\n'); - fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/issm.exe %s %s %s',cluster.np-1,cluster.np,cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'dplace -s1 -c0-%i mpiexec -np %i %s/%s %s %s %s',cluster.np-1,cluster.np,cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); fclose(fid); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ - - %Execute Queue job if ~isempty(restart) launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && qsub ' modelname '.queue ']; else @@ -91,24 +85,10 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart) % {{{ issmssh(cluster.name,cluster.login,cluster.port,launchcommand); end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/saga.py b/src/m/classes/clusters/saga.py index 342e3ab3c..135a73baa 100644 --- a/src/m/classes/clusters/saga.py +++ b/src/m/classes/clusters/saga.py @@ -1,12 +1,15 @@ import datetime +import os import subprocess +import cluster_defaults from fielddisplay import fielddisplay from helpers import * from IssmConfig import IssmConfig from issmscpin import issmscpin from issmscpout import issmscpout from issmssh import issmssh +from issmdir import issmdir from pairoptions import pairoptions from QueueRequirements import QueueRequirements try: @@ -91,26 +94,13 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename modelname = md.miscellaneous.name solution = md.private.solution io_gather = md.settings.io_gather - isvalgrind = md.debug.valgrind - isgprof = md.debug.gprof - isdakota = md.qmu.isdakota - isoceancoupling = md.transient.isoceancoupling - - executable = 'issm.exe' - if isdakota: - version = IssmConfig('_DAKOTA_VERSION_')[0:2] - version = float(version) - if version >= 6: - executable = 'issm_dakota.exe' - if isoceancoupling: - executable = 'issm_ocean.exe' # Write queuing script shortname = modelname[0:min(12, len(modelname))] timeobj = datetime.timedelta(minutes=self.time) @@ -142,11 +132,11 @@ def BuildQueueScript(self, md, filename): # {{{ fid.write('module load CMake/3.15.3-GCCcore-8.3.0\n') fid.write('module load PETSc/3.12.4-foss-2019b\n') fid.write('module load ParMETIS/4.0.3-gompi-2019b\n') - if isvalgrind: + if md.debug.valgrind: fid.write('module --ignore-cache load Valgrind/3.16.1-gompi-2019b \n') fid.write('cd %s/%s/ \n\n' % (self.executionpath, dirname)) - if isvalgrind: + if md.debug.valgrind: # profiling #fid.write('srun {} --tool=callgrind {}/{} {} {}/{} {} 2>{}.errlog>{}.outlog \n'.format(self.valgrind, self.codepath, executable, solution, self.executionpath, dirname, modelname, modelname, modelname)) # leak check @@ -158,30 +148,16 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress the files into one zip - compressstring = 'tar -zcf %s.tar.gz ' % dirname - for file in filelist: - compressstring += ' {}'.format(file) - subprocess.call(compressstring, shell=True) - - #upload input files - issmscpout(self.name, self.executionpath, self.login, self.port, [dirname + '.tar.gz']) + cluster_defaults.UploadQueueJob(self, modelname, dirname, filelist) # }}} def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch): # {{{ - #Execute Queue job - if not isempty(restart): - launchcommand = 'cd %s && cd %s && sbatch %s.queue' % (self.executionpath, dirname, modelname) - else: - launchcommand = 'cd %s && rm -rf ./%s && mkdir %s && cd %s && mv ../%s.tar.gz ./ && tar -zxf %s.tar.gz && sbatch %s.queue' % (self.executionpath, dirname, dirname, dirname, dirname, dirname, modelname) - issmssh(self.name, self.login, self.port, launchcommand) + cluster_defaults.LaunchQueueJobSbatch(self, modelname, dirname, filelist, restart, batch, 2) # }}} def Download(self, dirname, filelist): # {{{ - # Copy files from cluster to current directory - directory = '%s/%s/' % (self.executionpath, dirname) try: - issmscpin(self.name, self.login, self.port, directory, filelist) + cluster_defaults.Download(self, dirname, filelist) except OSError: print("File does not exsit, skiping") - # }}} + # }}} diff --git a/src/m/classes/clusters/sherlock.m b/src/m/classes/clusters/sherlock.m index 06d8ab724..5aa4f55b2 100644 --- a/src/m/classes/clusters/sherlock.m +++ b/src/m/classes/clusters/sherlock.m @@ -60,23 +60,19 @@ function disp(cluster) % {{{ end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; - %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + %checks + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end - %write queuing script + %write queuing script fid=fopen(filename, 'w'); fprintf(fid,'#!/bin/bash\n'); fprintf(fid,'#SBATCH --job-name=%s\n',modelname); @@ -88,7 +84,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); %FIXME fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n'); %FIXME fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); - fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec -n %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -97,7 +93,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([modelname '.run'],'w'); - fprintf(fid,'mpiexec -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec -n %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -107,38 +103,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,cluster.port,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && hostname && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/stanage.m b/src/m/classes/clusters/stanage.m index 0fa2921f7..7d6bce0a0 100644 --- a/src/m/classes/clusters/stanage.m +++ b/src/m/classes/clusters/stanage.m @@ -60,21 +60,17 @@ function disp(cluster) % {{{ if isempty(cluster.executionpath), md = checkmessage(md,'executionpath empty'); end end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ %Get variables from md dirname = md.private.runtimename; modelname = md.miscellaneous.name; solution = md.private.solution; io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end %write queuing script fid=fopen(filename, 'w'); @@ -94,7 +90,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'export ISSM_DIR="%s/../"\n',cluster.codepath); fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n'); fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); - fprintf(fid,'mpirun -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(), cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -n %i %s/%s %s %s %s\n',cluster.nprocs(), cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -107,7 +103,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([filename '.run'],'w'); - fprintf(fid,'mpirun -n %i %s/issm.exe %s %s %s\n',cluster.nprocs(), cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpirun -n %i %s/%s %s %s %s\n',cluster.nprocs(), cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -117,38 +113,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - if cluster.interactive, - compressstring = [compressstring ' ' modelname '.errlog ' modelname '.outlog ']; - end - system(compressstring); - - %upload input files - issmscpout(cluster.name,cluster.executionpath,cluster.login,0,{[dirname '.tar.gz']}); - + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - if ~isempty(restart) - launchcommand=['cd ' cluster.executionpath ' && cd ' dirname ' && hostname && sbatch ' modelname '.queue ']; - else - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && hostname && sbatch ' modelname '.queue ']; - end - issmssh(cluster.name,cluster.login,0,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,0,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/tetralith.m b/src/m/classes/clusters/tetralith.m index 771472188..f8b5f40ac 100644 --- a/src/m/classes/clusters/tetralith.m +++ b/src/m/classes/clusters/tetralith.m @@ -71,39 +71,19 @@ function disp(cluster) % {{{ numprocs=self.numnodes*self.cpuspernode; end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ + function BuildQueueScript(cluster, md, filename, executable) % {{{ - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; - %checks - if(isvalgrind) disp('valgrind not supported by cluster, ignoring...'); end - if(isgprof) disp('gprof not supported by cluster, ignoring...'); end + %checks + if(md.debug.valgrind) disp('valgrind not supported by cluster, ignoring...'); end + if(md.debug.gprof) disp('gprof not supported by cluster, ignoring...'); end - executable='issm.exe'; - if isdakota, - version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3)); - if (version>=6), - executable='issm_dakota.exe'; - end - end - if isoceancoupling, - executable='issm_ocean.exe'; - end - - %compute number of processors -% cluster.np=cluster.numnodes*cluster.cpuspernode; - nprocs(cluster);%=cluster.numnodes*cluster.cpuspernode; -% shortname = substring(modelname,1,min(12,length(modelname))); - - %write queuing script + %write queuing script fid=fopen(filename, 'w'); fprintf(fid,'#!/bin/bash\n'); fprintf(fid,'#\n'); @@ -128,7 +108,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'source $ISSM_DIR/etc/environment.sh\n'); %FIXME fprintf(fid,'cd %s/%s\n\n',cluster.executionpath,dirname); % fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); - fprintf(fid,'mpiexec -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); % fprintf(fid,'mpirun -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); % fprintf(fid,'mpiexec_mpt -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); @@ -140,7 +120,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ %in interactive mode, create a run file, and errlog and outlog file if cluster.interactive fid=fopen([filename '.run'],'w'); - fprintf(fid,'mpiexec_mpt -np %i %s/issm.exe %s %s %s\n',cluster.nprocs(),cluster.codepath,solution,[cluster.executionpath '/' dirname],modelname); + fprintf(fid,'mpiexec_mpt -np %i %s/%s %s %s %s\n',cluster.nprocs(),cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); if ~io_gather, %concatenate the output files: fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); end @@ -150,34 +130,13 @@ function BuildQueueScript(cluster, md, filename) % {{{ end end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - system(compressstring); - %upload input files - directory=cluster.executionpath; -% issmbbftpout(cluster.name,directory,cluster.login,cluster.port,cluster.numstreams,{[dirname '.tar.gz']}); - issmscpout(cluster.name,directory,cluster.login,cluster.port,{[dirname '.tar.gz']}); - - end - %}}} + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); + end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ - - %Execute Queue job - launchcommand=['cd ' cluster.executionpath ' && rm -rf ./' dirname ' && mkdir ' dirname ... - ' && cd ' dirname ' && mv ../' dirname '.tar.gz ./ && tar -zxf ' dirname '.tar.gz && hostname && sbatch ' modelname '.queue ']; - - issmssh(cluster.name,cluster.login,cluster.port,launchcommand); + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/clusters/ub_ccr.py b/src/m/classes/clusters/ub_ccr.py index e0d3f1092..2bd2b84aa 100644 --- a/src/m/classes/clusters/ub_ccr.py +++ b/src/m/classes/clusters/ub_ccr.py @@ -13,6 +13,7 @@ from issmscpin import issmscpin from issmscpout import issmscpout from issmssh import issmssh +from issmdir import issmdir from MatlabFuncs import * from pairoptions import pairoptions from QueueRequirements import QueueRequirements @@ -31,7 +32,7 @@ class ub_ccr(object): def __init__(self, *args): # {{{ self.name = oshostname() self.login = '' - self.port = '' + self.port = 0 self.cluster = 'ub-hpc' self.partition = 'general-compute' self.qos = 'general-compute' @@ -135,30 +136,17 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename modelname = md.miscellaneous.name solution = md.private.solution io_gather = md.settings.io_gather - isvalgrind = md.debug.valgrind - isgprof = md.debug.gprof - isdakota = md.qmu.isdakota - isoceancoupling = md.transient.isoceancoupling - if isgprof: + if md.debug.gprof: print('gprof not supported by cluster, ignoring...') - executable = 'issm.exe' - if isdakota: - version = IssmConfig('_DAKOTA_VERSION_')[0:2] - version = float(str(version[0])) - if version >= 6: - executable = 'issm_dakota.exe' - if isoceancoupling: - executable = 'issm_ocean.exe' - # Write queuing script fid = open(filename, 'w') @@ -202,7 +190,7 @@ def BuildQueueScript(self, md, filename): # {{{ # In interactive mode, create a run file, and errlog and outlog file if self.interactive: fid = open(modelname + '.run', 'w') - if not isvalgrind: + if not md.debug.valgrind: fid.write('mpiexec -np {} {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname)) else: fid.write('mpiexec -np {} valgrind --leak-check=full {}/{} {} {}/{} {}\n'.format(self.nprocs(), self.codepath, executable, solution, self.executionpath, dirname, modelname)) @@ -216,12 +204,14 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress the files into one zip - compressstring = 'tar -zcf {}.tar.gz'.format(dirname) - for file in filelist: - compressstring += ' {}'.format(file) - if self.interactive: - compressstring += ' {}.run {}.errlog {}.outlog'.format(modelname, modelname, modelname) + # Compress the files into one zip. + # filelist contains full paths; use -C so only basenames are stored in the archive. + root = issmdir() + '/execution/' + dirname + compressstring = 'tar -C {} -zcf {}.tar.gz'.format(root, dirname) + for filepath in filelist: + if not os.path.isfile(filepath): + raise Exception('File {} not found'.format(filepath)) + compressstring += ' {}'.format(os.path.basename(filepath)) subprocess.call(compressstring, shell=True) #upload input files @@ -266,11 +256,6 @@ def Download(self, dirname, filelist): # {{{ else: directory = '{}/{}/'.format(self.executionpath, dirname) - # if self.bbftp: - # issmbbftpin(self.name, self.login, self.port, self.numstreams, directory, filelist) - # else: - # issmscpin(self.name, self.login, self.port, directory, filelist) - # NOTE: Replacement for issmscpin(self.name, self.login, self.port, directory, filelist) filelist = [os.path.join(directory, x) for x in filelist] fileliststr = ' '.join([str(x) for x in filelist]) diff --git a/src/m/classes/clusters/ub_ccr_from_ghub.py b/src/m/classes/clusters/ub_ccr_from_ghub.py index 0ac8155cd..2634c9bd0 100644 --- a/src/m/classes/clusters/ub_ccr_from_ghub.py +++ b/src/m/classes/clusters/ub_ccr_from_ghub.py @@ -1,3 +1,4 @@ +import os import subprocess try: @@ -11,6 +12,7 @@ from issmscpin import issmscpin from issmscpout import issmscpout from issmssh import issmssh +from issmdir import issmdir from MatlabFuncs import * from pairoptions import pairoptions from QueueRequirements import QueueRequirements @@ -88,30 +90,17 @@ def checkconsistency(self, md, solution, analyses): # {{{ return self # }}} - def BuildQueueScript(self, md, filename): # {{{ + def BuildQueueScript(self, md, filename, executable): # {{{ # Get variables from md dirname = md.private.runtimename modelname = md.miscellaneous.name solution = md.private.solution io_gather = md.settings.io_gather - isvalgrind = md.debug.valgrind - isgprof = md.debug.gprof - isdakota = md.qmu.isdakota - isoceancoupling = md.transient.isoceancoupling - if isgprof: + if md.debug.gprof: print('gprof not supported by cluster, ignoring...') - executable = 'issm.exe' - if isdakota: - version = IssmConfig('_DAKOTA_VERSION_')[0:2] - version = float(str(version[0])) - if version >= 6: - executable = 'issm_dakota.exe' - if isoceancoupling: - executable = 'issm_ocean.exe' - # Write queuing script fid = open(filename, 'w') @@ -160,18 +149,20 @@ def BuildQueueScript(self, md, filename): # {{{ # }}} def UploadQueueJob(self, modelname, dirname, filelist): # {{{ - # Compress the files into one zip - compressstring = 'tar -zcf {}.tar.gz'.format(dirname) - for file in filelist: - compressstring += ' {}'.format(file) - if self.interactive: - compressstring += ' {}.run {}.errlog {}.outlog'.format(modelname, modelname, modelname) + # Compress the files into one zip. + # filelist contains full paths; use -C so only basenames are stored in the archive. + root = issmdir() + '/execution/' + dirname + compressstring = 'tar -C {} -zcf {}.tar.gz'.format(root, dirname) + for filepath in filelist: + if not os.path.isfile(filepath): + raise Exception('File {} not found'.format(filepath)) + compressstring += ' {}'.format(os.path.basename(filepath)) subprocess.call(compressstring, shell=True) #upload input files directory = issmexecdir - issmscpout(self.name, directory, self.login, self.port, ['{}.tar.gz'.format(dirname)]) + issmscpout(self.name, directory, self.login, 0, ['{}.tar.gz'.format(dirname)]) # }}} def LaunchQueueJob(self, modelname, dirname, filelist, restart, batch): # {{{ diff --git a/src/m/classes/clusters/unity.m b/src/m/classes/clusters/unity.m new file mode 100644 index 000000000..e7055a361 --- /dev/null +++ b/src/m/classes/clusters/unity.m @@ -0,0 +1,99 @@ +%UNITY (Massachusetts Green High Performance Computing Center) cluster class definition +% +% Usage: +% cluster=unity(); +% cluster=unity('np',3); +% cluster=unity('np',3,'login','username'); + +classdef unity + properties (SetAccess=public) + % {{{ + name = 'unity' + login = ''; + numnodes = 1; + cpuspernode = 16; + codepath = ''; + executionpath = ''; + time = 10; %in hours + memory = 32; %in Gb + email = ''; + end + %}}} + methods + function cluster=unity(varargin) % {{{ + + %initialize cluster using default settings if provided + if (exist('unity_settings')==2), unity_settings; end + + %use provided options to change fields + cluster=AssignObjectFields(pairoptions(varargin{:}),cluster); + end + %}}} + function disp(cluster) % {{{ + % display the object + disp(sprintf('class ''%s'' object ''%s'' = ',class(cluster),inputname(1))); + disp(sprintf(' name: %s',cluster.name)); + disp(sprintf(' login: %s',cluster.login)); + disp(sprintf(' numnodes: %i',cluster.numnodes)); + disp(sprintf(' cpuspernode: %i',cluster.cpuspernode)); + disp(sprintf(' time: %i hours',cluster.time)); + disp(sprintf(' memory: %i Gb',cluster.memory)); + disp(sprintf(' email: %s (receive notifications if END,FAIL)',cluster.email)); + disp(sprintf(' codepath: %s',cluster.codepath)); + disp(sprintf(' executionpath: %s',cluster.executionpath)); + end + %}}} + function numprocs=nprocs(cluster) % {{{ + %compute number of processors + numprocs=cluster.numnodes*cluster.cpuspernode; + end + %}}} + function md = checkconsistency(cluster,md,solution,analyses) % {{{ + %Miscellaneous + if isempty(cluster.login), md = checkmessage(md,'login empty'); end + if isempty(cluster.codepath), md = checkmessage(md,'codepath empty'); end + if isempty(cluster.executionpath), md = checkmessage(md,'executionpath empty'); end + end + %}}} + function BuildQueueScript(cluster, md, filename, executable) % {{{ + + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; + + %write queuing script + fid=fopen(filename, 'w'); + fprintf(fid,'#!/bin/bash -l\n'); + fprintf(fid,'#SBATCH --job-name=%s\n',modelname); + fprintf(fid,'#SBATCH -p cpu # Partition\n'); + fprintf(fid,'#SBATCH -o %s.outlog \n',modelname); + fprintf(fid,'#SBATCH -e %s.errlog \n',modelname); + fprintf(fid,'#SBATCH --nodes=%i\n',cluster.numnodes); + fprintf(fid,'#SBATCH --ntasks-per-node=%i\n',cluster.cpuspernode); + fprintf(fid,'#SBATCH --time=%s\n',eraseBetween(datestr(cluster.time/24,'dd-HH:MM:SS'),1,1)); %walltime is in d-HH:MM:SS format. cluster.time is in hour + fprintf(fid,'#SBATCH --mem=%iG\n',cluster.memory); + if ~isempty(cluster.email) + fprintf(fid,'#SBATCH --mail-type=END,FAIL\n'); + fprintf(fid,'#SBATCH --mail-user=%s\n', cluster.email); + end + fprintf(fid,'\n'); + fprintf(fid,'module load intel-oneapi-compilers/2024.1.0 intel-oneapi-mpi/2021.12.1 petsc/3.22.1\n'); + fprintf(fid,'mpiexec -n %i %s/%s %s %s %s\n',cluster.nprocs(), cluster.codepath,executable,solution,[cluster.executionpath '/' dirname],modelname); + if ~io_gather, %concatenate the output files: + fprintf(fid,'cat %s.outbin.* > %s.outbin',modelname,modelname); + end + fclose(fid); + end %}}} + function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); + end %}}} + function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ + cluster_defaults.LaunchQueueJobSbatch(cluster,modelname,dirname,filelist,restart,batch, 2); + end %}}} + function Download(cluster,dirname,filelist) % {{{ + cluster_defaults.Download(cluster,dirname,filelist); + end %}}} + end +end diff --git a/src/m/classes/clusters/yellowstone.m b/src/m/classes/clusters/yellowstone.m index a9ab5d111..4fa6db66f 100644 --- a/src/m/classes/clusters/yellowstone.m +++ b/src/m/classes/clusters/yellowstone.m @@ -71,28 +71,13 @@ function disp(cluster) % {{{ end %}}} - function BuildQueueScript(cluster, md, filename) % {{{ - - %Get variables from md - dirname = md.private.runtimename; - modelname = md.miscellaneous.name; - solution = md.private.solution; - io_gather = md.settings.io_gather; - isvalgrind = md.debug.valgrind; - isgprof = md.debug.gprof; - isdakota = md.qmu.isdakota; - isoceancoupling = md.transient.isoceancoupling; - - executable='issm.exe'; - if isdakota - version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3)); - if (version>=6), - executable='issm_dakota.exe'; - end - end - if isoceancoupling - executable='issm_ocean.exe'; - end + function BuildQueueScript(cluster, md, filename, executable) % {{{ + + %Get variables from md + dirname = md.private.runtimename; + modelname = md.miscellaneous.name; + solution = md.private.solution; + io_gather = md.settings.io_gather; %write queuing script @@ -107,7 +92,7 @@ function BuildQueueScript(cluster, md, filename) % {{{ fprintf(fid,'#BSUB -q %s\n',cluster.queue); fprintf(fid,'module purge\n'); - for i=1:length(cluster.modules), + for i=1:length(cluster.modules) fprintf(fid,'module load %s\n',cluster.modules{i}); end @@ -128,21 +113,8 @@ function BuildQueueScript(cluster, md, filename) % {{{ fclose(fid); end %}}} function UploadQueueJob(cluster,modelname,dirname,filelist) % {{{ - - %compress the files into one zip. - compressstring=['tar -zcf ' dirname '.tar.gz ']; - for i=1:numel(filelist), - compressstring = [compressstring ' ' filelist{i}]; - end - system(compressstring); - - %upload input files - directory=cluster.executionpath; - - issmscpout(cluster.name,directory,cluster.login,cluster.port,{[dirname '.tar.gz']}); - - end - %}}} + cluster_defaults.UploadQueueJob(cluster,modelname,dirname,filelist); + end %}}} function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ %launch command, to be executed via ssh @@ -154,11 +126,7 @@ function LaunchQueueJob(cluster,modelname,dirname,filelist,restart,batch) % {{{ end %}}} function Download(cluster,dirname,filelist) % {{{ - - %copy files from cluster to current directory - directory=[cluster.executionpath '/' dirname '/']; - issmscpin(cluster.name,cluster.login,cluster.port,directory,filelist); - + cluster_defaults.Download(cluster,dirname,filelist); end %}}} end end diff --git a/src/m/classes/damage.m b/src/m/classes/damage.m index b41dc7273..3a0a4f579 100644 --- a/src/m/classes/damage.m +++ b/src/m/classes/damage.m @@ -40,7 +40,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -87,13 +87,13 @@ function md = checkconsistency(self,md,solution,analyses) % {{{ md = checkfield(md,'fieldname','damage.isdamage','values',[1,0]); - if self.isdamage, + if self.isdamage md = checkfield(md,'fieldname','damage.law','numel',[1],'values',[0,1,2,3]); md = checkfield(md,'fieldname','damage.D','>=',0,'<=',self.max_damage,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','damage.spcdamage','Inf',1,'timeseries',1); md = checkfield(md,'fieldname','damage.max_damage','<',1,'>=',0); md = checkfield(md,'fieldname','damage.stabilization','numel',[1],'values',[0 1 2 4]); - md = checkfield(md,'fieldname','damage.maxiter','>=0',0); + md = checkfield(md,'fieldname','damage.maxiter','>=',0); md = checkfield(md,'fieldname','damage.elementinterp','values',{'P1','P2'}); md = checkfield(md,'fieldname','damage.stress_threshold','>=',0); md = checkfield(md,'fieldname','damage.stress_ubound','>=',0); @@ -105,15 +105,15 @@ md = checkfield(md,'fieldname','damage.c4','>=',0); md = checkfield(md,'fieldname','damage.equiv_stress','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','damage.requested_outputs','stringrow',1); - elseif (self.law~=0), - if (strcmp(solution,'DamageEvolutionSolution')), + elseif (self.law~=0) + if (strcmp(solution,'DamageEvolutionSolution')) error('Invalid evolution law (md.damage.law) for a damage solution'); end end end % }}} function list=defaultoutputs(self,md) % {{{ - if strcmp(domaintype(md.mesh),'2Dhorizontal'), + if strcmp(domaintype(md.mesh),'2Dhorizontal') list = {'DamageDbar'}; else list = {'DamageD'}; @@ -123,7 +123,7 @@ function disp(self) % {{{ disp(sprintf(' Damage:\n')); fielddisplay(self,'isdamage','is damage mechanics being used? {true,false}'); - if self.isdamage, + if self.isdamage fielddisplay(self,'law','damage law {''0: analytical'',''1: pralong''}'); fielddisplay(self,'D','damage tensor (scalar)'); fielddisplay(self,'spcdamage','damage constraints (NaN means no constraint)'); @@ -148,7 +148,7 @@ function disp(self) % {{{ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','isdamage','format','Boolean'); - if self.isdamage, + if self.isdamage WriteData(fid,prefix,'object',self,'fieldname','law','format','Integer'); WriteData(fid,prefix,'object',self,'fieldname','D','format','DoubleMat','mattype',1); WriteData(fid,prefix,'object',self,'fieldname','spcdamage','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); @@ -171,11 +171,11 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end - if self.isdamage, + if self.isdamage WriteData(fid,prefix,'data',outputs,'name','md.damage.requested_outputs','format','StringArray'); end @@ -183,7 +183,7 @@ function marshall(self,prefix,md,fid) % {{{ function savemodeljs(self,fid,modelname) % {{{ writejsdouble(fid,[modelname '.damage.isdamage'],self.isdamage); - if self.isdamage, + if self.isdamage error('savemodeljs error message: not implemented yet!'); end diff --git a/src/m/classes/damage.py b/src/m/classes/damage.py index e8def903b..71e372220 100644 --- a/src/m/classes/damage.py +++ b/src/m/classes/damage.py @@ -118,7 +118,7 @@ def checkconsistency(self, md, solution, analyses): # {{{ md = checkfield(md, 'fieldname', 'damage.law', 'numel', [1], 'values', [0, 1, 2, 3]) md = checkfield(md, 'fieldname', 'damage.spcdamage', 'Inf', 1, 'timeseries', 1) md = checkfield(md, 'fieldname', 'damage.stabilization', 'numel', [1], 'values', [0, 1, 2, 4]) - md = checkfield(md, 'fieldname', 'damage.maxiter', ' >= 0', 0) + md = checkfield(md, 'fieldname', 'damage.maxiter', '>=', 0) md = checkfield(md, 'fieldname', 'damage.elementinterp', 'values', ['P1', 'P2']) md = checkfield(md, 'fieldname', 'damage.stress_threshold', '>=', 0) md = checkfield(md, 'fieldname', 'damage.stress_ubound', '>=', 0) diff --git a/src/m/classes/debris.m b/src/m/classes/debris.m index 77257b442..1d123af34 100644 --- a/src/m/classes/debris.m +++ b/src/m/classes/debris.m @@ -24,7 +24,7 @@ % old fields must be recovered (make sure they are in the deprecated % model properties) - if verLessThan('matlab','7.9'), + if verLessThan('matlab','7.9') disp('Warning: your matlab version is old and there is a risk that load does not work correctly'); disp(' if the model is not loaded correctly, rename temporarily loadobj so that matlab does not use it'); @@ -53,7 +53,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -113,7 +113,7 @@ md = checkfield(md,'fieldname','debris.removal_slope_threshold','>=',0); md = checkfield(md,'fieldname','debris.removal_stress_threshold','>=',0); md = checkfield(md,'fieldname','debris.requested_outputs','stringrow',1); - if ~any(isnan(md.stressbalance.vertex_pairing)), + if ~any(isnan(md.stressbalance.vertex_pairing)) md = checkfield(md,'fieldname','stressbalance.vertex_pairing','>',0); end end % }}} @@ -149,7 +149,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/dependent.m b/src/m/classes/dependent.m index a0f5ba144..190b025f4 100644 --- a/src/m/classes/dependent.m +++ b/src/m/classes/dependent.m @@ -23,9 +23,9 @@ self.nods=getfieldvalue(options,'nods',0); %if name is mass flux: - if strcmpi(self.name,'MassFlux'), + if strcmpi(self.name,'MassFlux') %make sure that we supplied a file and that it exists! - if exist(self.exp)~=2, + if exist(self.exp)~=2 error('dependent checkconsistency: specified ''exp'' file does not exist!'); end %process the file and retrieve segments @@ -38,19 +38,19 @@ %do nothing end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if strcmpi(self.name,'MassFlux'), - if isempty(self.segments), + if strcmpi(self.name,'MassFlux') + if isempty(self.segments) error('dependent checkconsistency error: need segments to compute this dependent response'); end - if self.index<=0, + if self.index<=0 error('dependent checkconsistency error: index for segments should be >=1'); end end - if ~isnan(self.fos_reverse_index), - if ~strcmpi(driver,'fos_reverse'), + if ~isnan(self.fos_reverse_index) + if ~strcmpi(driver,'fos_reverse') error('cannot declare a dependent with a fos_reverse_index when the driver is not fos_reverse!'); end - if self.nods==0, + if self.nods==0 error('dependent checkconsistency error: nods should be set to the size of the independent variable'); end end @@ -60,10 +60,10 @@ function disp(self) % {{{ disp(sprintf(' dependent variable:')); fielddisplay(self,'name','variable name (must match corresponding String)'); - if ~isnan(self.fos_reverse_index), + if ~isnan(self.fos_reverse_index) fielddisplay(self,'fos_reverse_index','index for fos_reverse driver of ADOLC'); end - if ~isempty(self.exp), + if ~isempty(self.exp) fielddisplay(self,'exp','file needed to compute dependent variable'); fielddisplay(self,'segments','mass flux segments'); end diff --git a/src/m/classes/dsl.m b/src/m/classes/dsl.m index 028d257f7..8908e7c21 100644 --- a/src/m/classes/dsl.m +++ b/src/m/classes/dsl.m @@ -40,14 +40,14 @@ function disp(self) % {{{ function md = checkconsistency(self,md,solution,analyses) % {{{ %Early return - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc == 0) | (md.transient.isoceantransport==0), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc == 0) | (md.transient.isoceantransport==0) return; end md = checkfield(md,'fieldname','dsl.global_average_thermosteric_sea_level','NaN',1,'Inf',1); md = checkfield(md,'fieldname','dsl.sea_surface_height_above_geoid','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','dsl.sea_water_pressure_at_sea_floor','NaN',1,'Inf',1,'timeseries',1); - if md.solidearth.settings.compute_bp_grd==1, + if md.solidearth.settings.compute_bp_grd==1 md = checkfield(md,'fieldname','dsl.sea_water_pressure_at_sea_floor','empty',1); end diff --git a/src/m/classes/dslmme.m b/src/m/classes/dslmme.m index b4e8abeaf..08e605af6 100644 --- a/src/m/classes/dslmme.m +++ b/src/m/classes/dslmme.m @@ -34,17 +34,17 @@ function md = checkconsistency(self,md,solution,analyses) % {{{ %Early return - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc == 0) | (md.transient.isoceantransport==0), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc == 0) | (md.transient.isoceantransport==0) return; end - for i=1:length(self.global_average_thermosteric_sea_level), + for i=1:length(self.global_average_thermosteric_sea_level) md = checkfield(md,'field',self.global_average_thermosteric_sea_level{i},'NaN',1,'Inf',1); md = checkfield(md,'field',self.sea_surface_height_above_geoid{i},'NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'field',self.sea_water_pressure_at_sea_floor{i},'NaN',1,'Inf',1,'timeseries',1); end md = checkfield(md,'field',self.modelid,'NaN',1,'Inf',1,'>=',1,'<=',length(self.global_average_thermosteric_sea_level)); - if md.solidearth.settings.compute_bp_grd==1, + if md.solidearth.settings.compute_bp_grd==1 md = checkfield(md,'fieldname','dsl.sea_water_pressure_at_sea_floor','empty',1); end @@ -68,7 +68,7 @@ function marshall(self,prefix,md,fid) % {{{ end % }}} function self = extrude(self,md) % {{{ - for i=1:length(self.global_average_thermosteric_sea_level), + for i=1:length(self.global_average_thermosteric_sea_level) self.sea_surface_height_above_geoid{i}=project3d(md,'vector',self.sea_surface_height_above_geoid{i},'type','node','layer',1); self.sea_water_pressure_at_sea_floor{i}=project3d(md,'vector',self.sea_water_pressure_at_sea_floor{i},'type','node','layer',1); end diff --git a/src/m/classes/esa.m b/src/m/classes/esa.m index 9fb3eb1be..d657203f3 100644 --- a/src/m/classes/esa.m +++ b/src/m/classes/esa.m @@ -48,7 +48,7 @@ md = checkfield(md,'fieldname','esa.requested_outputs','stringrow',1); %check that love numbers are provided at the same level of accuracy: - if (size(self.love_h,1)~=size(self.love_l,1)), + if (size(self.love_h,1)~=size(self.love_l,1)) error('esa error message: love numbers should be provided at the same level of accuracy'); end @@ -56,7 +56,7 @@ pos=find(self.deltathickness); maskpos=md.mask.ice_levelset(md.mesh.elements(pos,:)); [els,vertices]=find(maskpos>0); - if length(els), + if length(els) error('esa checkconsistency fail: there are elements with ice loads where some vertices are not on the ice!'); end @@ -87,7 +87,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/flowequation.m b/src/m/classes/flowequation.m index 6505cf67d..bdafaac34 100644 --- a/src/m/classes/flowequation.m +++ b/src/m/classes/flowequation.m @@ -34,7 +34,7 @@ % old fields must be recovered (make sure they are in the deprecated % model properties) - if verLessThan('matlab','7.9'), + if verLessThan('matlab','7.9') disp('Warning: your matlab version is old and there is a risk that load does not work correctly'); disp(' if the model is not loaded correctly, rename temporarily loadobj so that matlab does not use it'); @@ -129,17 +129,17 @@ elseif strcmp(domaintype(md.mesh),'2Dvertical') md = checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices 1],'values',[2,5,6]); md = checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements 1],'values',[2,5,6]); - elseif strcmp(domaintype(md.mesh),'3D'), + elseif strcmp(domaintype(md.mesh),'3D') md = checkfield(md,'fieldname','flowequation.vertex_equation','size',[md.mesh.numberofvertices 1],'values',[0:9]); md = checkfield(md,'fieldname','flowequation.element_equation','size',[md.mesh.numberofelements 1],'values',[0:9]); else error('Case not supported yet'); end - if ~(self.isSIA || self.isSSA || self.isL1L2 || self.isMOLHO || self.isHO || self.isFS), + if ~(self.isSIA || self.isSSA || self.isL1L2 || self.isMOLHO || self.isHO || self.isFS) md = checkmessage(md,['no element types set for this model']); end - if ismember('StressbalanceSIAAnalysis',analyses), - if any(self.element_equation==1), + if ismember('StressbalanceSIAAnalysis',analyses) + if any(self.element_equation==1) if(self.vertex_equation & md.mask.ocean_levelset<0.), disp(sprintf('\n !!! Warning: SIA''s model is not consistent on ice shelves !!!\n')); end @@ -200,8 +200,8 @@ function savemodeljs(self,fid,modelname) % {{{ writejsdouble(fid,[modelname '.flowequation.isMOLHO'],self.isMOLHO); writejsdouble(fid,[modelname '.flowequation.isHO'],self.isHO); writejsdouble(fid,[modelname '.flowequation.isFS'],self.isFS); - writejsstring(fid,[modelname '.flowequation.isNitscheBC'],self.isNitscheBC); - writejsstring(fid,[modelname '.flowequation.FSNitscheGamma'],self.FSNitscheGamma); + writejsdouble(fid,[modelname '.flowequation.isNitscheBC'],self.isNitscheBC); + writejsdouble(fid,[modelname '.flowequation.FSNitscheGamma'],self.FSNitscheGamma); writejsstring(fid,[modelname '.flowequation.fe_SSA'],self.fe_SSA); writejsstring(fid,[modelname '.flowequation.fe_HO'],self.fe_HO); writejsstring(fid,[modelname '.flowequation.fe_FS'],self.fe_FS); diff --git a/src/m/classes/frictionemulator.m b/src/m/classes/frictionemulator.m new file mode 100644 index 000000000..44ae7d182 --- /dev/null +++ b/src/m/classes/frictionemulator.m @@ -0,0 +1,44 @@ +%FRICTIONEMULATOR class definition +% +% Usage: +% frictionemulator=frictionemulator(); + +classdef frictionemulator + properties (SetAccess=public) + module_dir = ''; + pt_name = ''; + py_name = ''; + C = NaN; + end + methods + function self = extrude(self,md) % {{{ + self.C=project3d(md,'vector',self.C,'type','node','layer',1); + end % }}} + function self = frictionemulator(varargin) % {{{ + end % }}} + function md = checkconsistency(self,md,solution,analyses) % {{{ + md = checkfield(md,'fieldname','friction.module_dir','filepath',1); + md = checkfield(md,'fieldname','friction.py_name','string',1); + md = checkfield(md,'fieldname','friction.pt_name','string',1); + md = checkfield(md,'fieldname','friction.C','timeseries',1,'NaN',1,'Inf',1); + end % }}} + function disp(self) % {{{ + disp(sprintf('Basal shear stress parameters for pre-trained python emulator')); + fielddisplay(self,'module_dir', 'directory of the emulator module'); + fielddisplay(self,'pt_name', 'name of the checkpoint file for pre-trained ML model'); + fielddisplay(self,'py_name', 'name of the python file that defines ML architecture'); + fielddisplay(self,'C','friction coefficient [SI]'); + end % }}} + function marshall(self,prefix,md,fid) % {{{ + yts=md.constants.yts; + WriteData(fid,prefix,'name','md.friction.law','data',20,'format','Integer'); + WriteData(fid,prefix,'class','friction','object',self,'fieldname','module_dir','format','String') + WriteData(fid,prefix,'class','friction','object',self,'fieldname','pt_name','format','String'); + WriteData(fid,prefix,'class','friction','object',self,'fieldname','py_name','format','String'); + WriteData(fid,prefix,'class','friction','object',self,'fieldname','C','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); + end % }}} + function savemodeljs(self,fid,modelname) % {{{ + error('not implemented yet!'); + end % }}} + end +end diff --git a/src/m/classes/frictionregcoulomb.m b/src/m/classes/frictionregcoulomb.m index a24c543b1..96a5def67 100644 --- a/src/m/classes/frictionregcoulomb.m +++ b/src/m/classes/frictionregcoulomb.m @@ -38,7 +38,7 @@ md = checkfield(md,'fieldname','friction.m','NaN',1,'Inf',1,'>',0.,'size',[md.mesh.numberofelements,1]); end % }}} function disp(self) % {{{ - %See Joughin et al. 2019 (equivalent form by Matt Trevers, poster at AGU 2022) https://agupubs.onlinelåibrary.wiley.com/doi/full/10.1029/2019GL082526 + %See Joughin et al. 2019 (equivalent form by Matt Trevers, poster at AGU 2022) https://agupubs.onlinelibrary.wiley.com/doi/full/10.1029/2019GL082526 disp('Regularized Coulomb friction law (Joughin et al., 2019) parameters:'); disp(' Regularized Coulomb friction law reads:'); disp(' C^2 |u|^(1/m) '); diff --git a/src/m/classes/frictionweertman.m b/src/m/classes/frictionweertman.m index 8fc225fb5..c0c9984a9 100644 --- a/src/m/classes/frictionweertman.m +++ b/src/m/classes/frictionweertman.m @@ -24,7 +24,6 @@ end end % }}} function self = extrude(self,md) % {{{ - disp('-------------- file: frictionweertman.m line: 27'); self.C=project3d(md,'vector',self.C,'type','node','layer',1); self.m=project3d(md,'vector',self.m,'type','element'); end % }}} diff --git a/src/m/classes/frontalforcings.m b/src/m/classes/frontalforcings.m index c14d5120e..74a4a059f 100644 --- a/src/m/classes/frontalforcings.m +++ b/src/m/classes/frontalforcings.m @@ -19,7 +19,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/frontalforcingsrignot.m b/src/m/classes/frontalforcingsrignot.m index 073d14b99..90e25c18c 100644 --- a/src/m/classes/frontalforcingsrignot.m +++ b/src/m/classes/frontalforcingsrignot.m @@ -21,7 +21,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/frontalforcingsrignotarma.m b/src/m/classes/frontalforcingsrignotarma.m index 65dc98035..3011d4c2a 100644 --- a/src/m/classes/frontalforcingsrignotarma.m +++ b/src/m/classes/frontalforcingsrignotarma.m @@ -44,7 +44,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/geometry.m b/src/m/classes/geometry.m index 050c77c2b..bae517396 100644 --- a/src/m/classes/geometry.m +++ b/src/m/classes/geometry.m @@ -17,7 +17,7 @@ % loaded. Update old properties here %2014 March 26th - if isstruct(self), + if isstruct(self) disp('WARNING: updating geometry'); disp(' md.geometry.bed is now md.geometry.base'); disp(' md.geometry.bathymetry is now md.geometry.bed'); @@ -45,22 +45,22 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if strcmpi(solution,'LoveSolution'), + if strcmpi(solution,'LoveSolution') return; else md = checkfield(md,'fieldname','geometry.surface' ,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','geometry.base' ,'NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','geometry.thickness','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1],'>=',0); - if any(abs(self.thickness-self.surface+self.base)>10^-9), + if any(abs(self.thickness-self.surface+self.base)>10^-9) md = checkmessage(md,['equality thickness=surface-base violated']); end - if strcmp(solution,'TransientSolution') & md.transient.isgroundingline, + if strcmp(solution,'TransientSolution') & md.transient.isgroundingline md = checkfield(md,'fieldname','geometry.bed','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); - if any(self.bed-self.base>10^-12), + if any(self.bed-self.base>10^-12) md = checkmessage(md,['base0); - if any(abs(self.bed(pos)-self.base(pos))>10^-9), + if any(abs(self.bed(pos)-self.base(pos))>10^-9) md = checkmessage(md,['equality base=bed on grounded ice violated']); end md = checkfield(md,'fieldname','geometry.bed','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); @@ -78,9 +78,9 @@ function disp(self) % {{{ end % }}} function marshall(self,prefix,md,fid) % {{{ length_thickness=size(self.thickness,1); - if length_thickness==md.mesh.numberofvertices | length_thickness==md.mesh.numberofvertices+1, + if length_thickness==md.mesh.numberofvertices | length_thickness==md.mesh.numberofvertices+1 WriteData(fid,prefix,'object',self,'fieldname','thickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); - elseif length_thickness==md.mesh.numberofelements | length_thickness==md.mesh.numberofelements+1, + elseif length_thickness==md.mesh.numberofelements | length_thickness==md.mesh.numberofelements+1 WriteData(fid,prefix,'object',self,'fieldname','thickness','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofelements+1,'yts',md.constants.yts); else error('geometry thickness time series should be a vertex or element time series'); diff --git a/src/m/classes/giacaron.m b/src/m/classes/giacaron.m index 64ec17a4f..8b22a99b7 100644 --- a/src/m/classes/giacaron.m +++ b/src/m/classes/giacaron.m @@ -55,13 +55,13 @@ otherwise options=pairoptions(varargin{:}); body=getfieldvalue(options,'body'); - if strcmpi(body,'earth'), + if strcmpi(body,'earth') self.numlayers=getfieldvalue(options,'numlayers',5); self.calculate_sea_level=true; %[self.radius,self.lame_mu, self.lame_lambda, self.issolid, self.density, ... %self.viscosity, self.isburger, self.transient_viscosity, self.transient_mu]=... %modelinit(self.numlayers); - elseif strcmpi(body,'europa'), + elseif strcmpi(body,'europa') error('giacaron constructor error message: ''europa'' body not implemented yet!'); else error('giacaron constructor error message: body not implemented yet!'); diff --git a/src/m/classes/gpuoptions.py b/src/m/classes/gpuoptions.py new file mode 100644 index 000000000..8d636ed75 --- /dev/null +++ b/src/m/classes/gpuoptions.py @@ -0,0 +1,35 @@ +from collections import OrderedDict +from pairoptions import pairoptions + + +def gpuoptions(*args): + """ + GPUOPTIONS - PETSc options for GPU-accelerated (CUDA) solves. + + Uses aijcusparse matrices and CUDA vectors so that KSPSolve runs on GPU. + Requires a CUDA-enabled PETSc build (see + externalpackages/petsc/install-3.22-gadi-gpu.sh). + + The preconditioner defaults to block-Jacobi with ILU sub-solves, which + PETSc can run on GPU via CUDA. For larger problems consider switching to + 'gamg' (algebraic multigrid) which also has CUDA support. + + Usage: + options = gpuoptions() + options = gpuoptions('ksp_type', 'cg', 'pc_type', 'gamg') + """ + + # Retrieve any overrides passed by the caller + options = pairoptions(*args) + gpu = OrderedDict() + + gpu['toolkit'] = 'petsc' + gpu['vec_type'] = options.getfieldvalue('vec_type', 'cuda') + gpu['mat_type'] = options.getfieldvalue('mat_type', 'aijcusparse') + gpu['ksp_type'] = options.getfieldvalue('ksp_type', 'gmres') + gpu['pc_type'] = options.getfieldvalue('pc_type', 'bjacobi') + gpu['sub_pc_type'] = options.getfieldvalue('sub_pc_type', 'ilu') + gpu['ksp_rtol'] = options.getfieldvalue('ksp_rtol', 1e-10) + gpu['ksp_max_it'] = options.getfieldvalue('ksp_max_it', 500) + + return gpu diff --git a/src/m/classes/groundingline.m b/src/m/classes/groundingline.m index b1752f8de..a508386f8 100644 --- a/src/m/classes/groundingline.m +++ b/src/m/classes/groundingline.m @@ -39,16 +39,16 @@ md = checkfield(md,'fieldname','groundingline.intrusion_distance','NaN',1,'Inf',1,'>=',0); md = checkfield(md,'fieldname','groundingline.requested_outputs','stringrow',1); - if ~strcmp(self.migration,'None') & strcmp(solution,'TransientSolution') & md.transient.isgroundingline==1, - if isnan(md.geometry.bed), + if ~strcmp(self.migration,'None') & strcmp(solution,'TransientSolution') & md.transient.isgroundingline==1 + if isnan(md.geometry.bed) md = checkmessage(md,['requesting grounding line migration, but bathymetry is absent!']); end pos=find(md.mask.ocean_levelset>0. & md.mask.ice_levelset<=0); - if any(abs(md.geometry.base(pos)-md.geometry.bed(pos))>10^-10), + if any(abs(md.geometry.base(pos)-md.geometry.bed(pos))>10^-10) md = checkmessage(md,['base not equal to bed on grounded ice!']); end pos=find(md.mask.ocean_levelset<=0. & md.mask.ice_levelset<=0); - if any(md.geometry.bed(pos) - md.geometry.base(pos) > 10^-9), + if any(md.geometry.bed(pos) - md.geometry.base(pos) > 10^-9) md = checkmessage(md,['bed superior to base on floating ice!']); end end @@ -77,7 +77,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/hydrologydc.m b/src/m/classes/hydrologydc.m index 5243966fd..fdb0f36fe 100644 --- a/src/m/classes/hydrologydc.m +++ b/src/m/classes/hydrologydc.m @@ -63,19 +63,19 @@ end% }}} function list = defaultoutputs(self,md) % {{{ list = {'SedimentHead','SedimentHeadResidual','EffectivePressure'}; - if self.isefficientlayer, + if self.isefficientlayer list=[list,{'EplHead','HydrologydcMaskEplactiveNode','HydrologydcMaskEplactiveElt','EplHeadSlopeX','EplHeadSlopeY','HydrologydcEplThickness'}]; end - if self.steps_per_step>1 | self.step_adapt, + if self.steps_per_step>1 | self.step_adapt list = [list,'EffectivePressureSubstep','SedimentHeadSubstep']; - if self.isefficientlayer, + if self.isefficientlayer list = [list,'EplHeadSubstep','HydrologydcEplThicknessSubstep']; end end end % }}} function self = initialize(self,md) % {{{ self.epl_colapse_thickness = self.sediment_transmitivity/self.epl_conductivity; - if isnan(self.basal_moulin_input), + if isnan(self.basal_moulin_input) self.basal_moulin_input=zeros(md.mesh.numberofvertices,1); disp(' no hydrology.basal_moulin_input specified: values set as zero'); end @@ -116,7 +116,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses)% {{{ %Early return - if ~ismember('HydrologyDCInefficientAnalysis',analyses) & ~ismember('HydrologyDCEfficientAnalysis',analyses), + if ~ismember('HydrologyDCInefficientAnalysis',analyses) & ~ismember('HydrologyDCEfficientAnalysis',analyses) return; end @@ -133,10 +133,10 @@ md = checkfield(md,'fieldname','hydrology.transfer_flag','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','hydrology.unconfined_flag','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','hydrology.requested_outputs','stringrow',1); - if self.sedimentlimit_flag==1, + if self.sedimentlimit_flag==1 md = checkfield(md,'fieldname','hydrology.sedimentlimit','>',0,'numel',1); end - if self.transfer_flag==1, + if self.transfer_flag==1 md = checkfield(md,'fieldname','hydrology.leakage_factor','>',0,'numel',1); end md = checkfield(md,'fieldname','hydrology.basal_moulin_input','NaN',1,'Inf',1,'timeseries',1); @@ -148,7 +148,7 @@ md = checkfield(md,'fieldname','hydrology.sediment_transmitivity','>=',0,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','hydrology.mask_thawed_node','size',[md.mesh.numberofvertices 1],'values',[0 1]); - if self.isefficientlayer==1, + if self.isefficientlayer==1 md = checkfield(md,'fieldname','hydrology.spcepl_head','Inf',1,'timeseries',1); md = checkfield(md,'fieldname','hydrology.mask_eplactive_node','size',[md.mesh.numberofvertices 1],'values',[0 1]); md = checkfield(md,'fieldname','hydrology.epl_compressibility','>',0,'numel',1); @@ -159,7 +159,7 @@ md = checkfield(md,'fieldname','hydrology.epl_max_thickness','>',0,'numel',1); md = checkfield(md,'fieldname','hydrology.epl_conductivity','>',0,'numel',1); md = checkfield(md,'fieldname','hydrology.eplflip_lock','>=',0,'numel',1); - if (self.epl_colapse_thickness>self.epl_initial_thickness), + if (self.epl_colapse_thickness>self.epl_initial_thickness) md = checkmessage(md,'Colapsing thickness for EPL larger than initial thickness'); end end @@ -184,13 +184,13 @@ function disp(self)% {{{ disp(sprintf('%55s 1: user defined: %s',' ','sedimentlimit')); disp(sprintf('%55s 2: hydrostatic pressure',' ')); disp(sprintf('%55s 3: normal stress',' ')); - if self.sedimentlimit_flag==1, + if self.sedimentlimit_flag==1 fielddisplay(self,'sedimentlimit','user defined upper limit for the inefficient layer [m]'); end fielddisplay(self,'transfer_flag','what kind of transfer method is applied between the layers'); disp(sprintf('%55s 0: no transfer',' ')); disp(sprintf('%55s 1: constant leakage factor: %s',' ','leakage_factor')); - if self.transfer_flag==1, + if self.transfer_flag==1 fielddisplay(self,'leakage_factor','user defined leakage factor [m]'); end fielddisplay(self,'unconfined_flag','Do you want unconfined scheme to be used (transitory)'); @@ -206,7 +206,7 @@ function disp(self)% {{{ fielddisplay(self,'sediment_transmitivity','sediment transmitivity [m^2/s]'); fielddisplay(self,'mask_thawed_node','deactivate (0) hydrology on frozen nodes'); - if self.isefficientlayer==1, + if self.isefficientlayer==1 disp(sprintf(' - for the epl layer')); fielddisplay(self,'spcepl_head','epl water head constraints (NaN means no constraint) [m above MSL]'); fielddisplay(self,'mask_eplactive_node','active (1) or not (0) EPL'); @@ -234,10 +234,10 @@ function marshall(self,prefix,md,fid)% {{{ WriteData(fid,prefix,'object',self,'fieldname','sedimentlimit_flag','format','Integer'); WriteData(fid,prefix,'object',self,'fieldname','transfer_flag','format','Integer'); WriteData(fid,prefix,'object',self,'fieldname','unconfined_flag','format','Integer'); - if self.sedimentlimit_flag==1, + if self.sedimentlimit_flag==1 WriteData(fid,prefix,'object',self,'fieldname','sedimentlimit','format','Double'); end - if self.transfer_flag==1, + if self.transfer_flag==1 WriteData(fid,prefix,'object',self,'fieldname','leakage_factor','format','Double'); end WriteData(fid,prefix,'object',self,'fieldname','basal_moulin_input','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts) @@ -248,7 +248,7 @@ function marshall(self,prefix,md,fid)% {{{ WriteData(fid,prefix,'object',self,'fieldname','sediment_thickness','format','Double'); WriteData(fid,prefix,'object',self,'fieldname','sediment_transmitivity','format','DoubleMat','mattype',1'); WriteData(fid,prefix,'object',self,'fieldname','mask_thawed_node','format','DoubleMat','mattype',1); - if self.isefficientlayer==1, + if self.isefficientlayer==1 WriteData(fid,prefix,'object',self,'fieldname','spcepl_head','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); WriteData(fid,prefix,'object',self,'fieldname','mask_eplactive_node','format','DoubleMat','mattype',1); WriteData(fid,prefix,'object',self,'fieldname','epl_compressibility','format','Double'); @@ -262,7 +262,7 @@ function marshall(self,prefix,md,fid)% {{{ end outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/hydrologyglads.m b/src/m/classes/hydrologyglads.m index 6e4d312c4..86f1e2624 100644 --- a/src/m/classes/hydrologyglads.m +++ b/src/m/classes/hydrologyglads.m @@ -171,7 +171,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','hydrology','fieldname','istransition','format','Boolean'); outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/hydrologyshakti.m b/src/m/classes/hydrologyshakti.m index f6a036353..29ffbe579 100644 --- a/src/m/classes/hydrologyshakti.m +++ b/src/m/classes/hydrologyshakti.m @@ -124,7 +124,7 @@ function marshall(self,prefix,md,fid) % {{{ outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/hydrologyshreve.m b/src/m/classes/hydrologyshreve.m index 80446b2d9..c047d0d39 100644 --- a/src/m/classes/hydrologyshreve.m +++ b/src/m/classes/hydrologyshreve.m @@ -49,7 +49,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','stabilization','format','Double'); outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/hydrologytws.m b/src/m/classes/hydrologytws.m index a0e33d694..d8d98f328 100644 --- a/src/m/classes/hydrologytws.m +++ b/src/m/classes/hydrologytws.m @@ -47,7 +47,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','spcwatercolumn','format','DoubleMat','mattype',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/hydrologytws.py b/src/m/classes/hydrologytws.py index e849014d4..d0eadc6a9 100644 --- a/src/m/classes/hydrologytws.py +++ b/src/m/classes/hydrologytws.py @@ -34,7 +34,7 @@ def defaultoutputs(self, md): # {{{ # }}} def setdefaultparameters(self): # {{{ - self.requested_outputs = ['defualt'] + self.requested_outputs = ['default'] return self # }}} diff --git a/src/m/classes/independent.m b/src/m/classes/independent.m index 4e2afc5f1..43ef78f0e 100644 --- a/src/m/classes/independent.m +++ b/src/m/classes/independent.m @@ -41,19 +41,19 @@ end % }}} function md = checkconsistency(self,md,i,solution,analyses,driver) % {{{ if ~isnan(self.fos_forward_index) - if ~strcmpi(driver,'fos_forward'), + if ~strcmpi(driver,'fos_forward') error('cannot declare an independent with a fos_forward_index when the driver is not fos_forward!'); end - if self.nods==0, + if self.nods==0 error('independent checkconsistency error: nods should be set to the size of the independent variable'); end end if ~isempty(self.fov_forward_indices) - if ~strcmpi(driver,'fov_forward'), + if ~strcmpi(driver,'fov_forward') error('cannot declare an independent with fov_forward_indices when the driver is not fov_forward!'); end - if self.nods==0, + if self.nods==0 error('independent checkconsistency error: nods should be set to the size of the independent variable'); end md = checkfield(md,'fieldname',['autodiff.independents{' num2str(i) '}.fov_forward_indices'],'>=',1,'<=',self.nods,'size',[NaN 1]); @@ -73,10 +73,10 @@ function disp(self) % {{{ fielddisplay(self,'min_parameters','absolute minimum acceptable value of the inversed parameter on each vertex'); fielddisplay(self,'max_parameters','absolute maximum acceptable value of the inversed parameter on each vertex'); fielddisplay(self,'control_scaling_factor','order of magnitude of each control (useful for multi-parameter optimization)'); - if ~isnan(self.fos_forward_index), + if ~isnan(self.fos_forward_index) fielddisplay(self,'fos_forward_index','index for fos_foward driver of ADOLC'); end - if ~isnan(self.fov_forward_indices), + if ~isnan(self.fov_forward_indices) fielddisplay(self,'fov_forward_indices','indices for fov_foward driver of ADOLC'); end end % }}} diff --git a/src/m/classes/initialization.m b/src/m/classes/initialization.m index ba0966a43..a9574538f 100644 --- a/src/m/classes/initialization.m +++ b/src/m/classes/initialization.m @@ -39,24 +39,24 @@ function self = setdefaultparameters(self) % {{{ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('StressbalanceAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isstressbalance == 0), + if ismember('StressbalanceAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isstressbalance == 0) if numel(md.initialization.vx)>1 | numel(md.initialization.vy)>1 md = checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end end - if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport == 0), + if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport == 0) md = checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end if ismember('OceantransportAnalysis',analyses) - if strcmp(solution,'TransientSolution') & md.transient.isslc & md.transient.isoceantransport, + if strcmp(solution,'TransientSolution') & md.transient.isslc & md.transient.isoceantransport md = checkfield(md,'fieldname','initialization.bottompressure','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','initialization.dsl','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','initialization.str','NaN',1,'Inf',1,'size',[1 1]); end end - if ismember('BalancethicknessAnalysis',analyses) & strcmp(solution,'BalancethicknessSolution'), + if ismember('BalancethicknessAnalysis',analyses) & strcmp(solution,'BalancethicknessSolution') md = checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); %Triangle with zero velocity @@ -64,7 +64,7 @@ md = checkmessage(md,'at least one triangle has all its vertices with a zero velocity'); end end - if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal == 0), + if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal == 0) md = checkfield(md,'fieldname','initialization.vx','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','initialization.vy','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); if dimension(md.mesh)==3 @@ -82,54 +82,54 @@ %'message','set temperature to pressure melting point at locations with waterfraction>0'); end end - if ismember('HydrologyShreveAnalysis',analyses), - if isa(md.hydrology,'hydrologyshreve'), - if (strcmp(solution,'TransientSolution') & md.transient.ishydrology) | strcmp(solution,'HydrologySolution'), + if ismember('HydrologyShreveAnalysis',analyses) + if isa(md.hydrology,'hydrologyshreve') + if (strcmp(solution,'TransientSolution') & md.transient.ishydrology) | strcmp(solution,'HydrologySolution') md = checkfield(md,'fieldname','initialization.watercolumn','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end end end - if ismember('HydrologyTwsAnalysis',analyses), - if isa(md.hydrology,'hydrologytws'), + if ismember('HydrologyTwsAnalysis',analyses) + if isa(md.hydrology,'hydrologytws') md = checkfield(md,'fieldname','initialization.watercolumn','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end end - if ismember('SealevelchangeAnalysis',analyses), - if strcmp(solution,'TransientSolution') & md.transient.isslc, + if ismember('SealevelchangeAnalysis',analyses) + if strcmp(solution,'TransientSolution') & md.transient.isslc md = checkfield(md,'fieldname','initialization.sealevel','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end end - if ismember('HydrologyGlaDSAnalysis',analyses), - if isa(md.hydrology,'hydrologyglads'), + if ismember('HydrologyGlaDSAnalysis',analyses) + if isa(md.hydrology,'hydrologyglads') md = checkfield(md,'fieldname','initialization.watercolumn','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','initialization.hydraulic_potential','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','initialization.channelarea','NaN',1,'Inf',1,'>=',0,'size',[md.mesh.numberofedges 1]); end end - if ismember('HydrologyDCInefficientAnalysis',analyses), - if isa(md.hydrology,'hydrologydc'), + if ismember('HydrologyDCInefficientAnalysis',analyses) + if isa(md.hydrology,'hydrologydc') md = checkfield(md,'fieldname','initialization.sediment_head','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end end - if ismember('HydrologyDCEfficientAnalysis',analyses), - if isa(md.hydrology,'hydrologydc'), - if md.hydrology.isefficientlayer==1, + if ismember('HydrologyDCEfficientAnalysis',analyses) + if isa(md.hydrology,'hydrologydc') + if md.hydrology.isefficientlayer==1 md = checkfield(md,'fieldname','initialization.epl_head','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','initialization.epl_thickness','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end end end - if ismember('SamplingAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.issampling == 0), + if ismember('SamplingAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.issampling == 0) if ~isnan(md.initialization.sample) md = checkfield(md,'fieldname','initialization.sample','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end end - if ismember('DebrisAnalysis',analyses), + if ismember('DebrisAnalysis',analyses) if ~isnan(md.initialization.debris) md = checkfield(md,'fieldname','initialization.debris','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end end - if ismember('AgeAnalysis',analyses), + if ismember('AgeAnalysis',analyses) if ~isnan(md.initialization.age) md = checkfield(md,'fieldname','initialization.age','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end @@ -183,8 +183,8 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','debris','format','DoubleMat','mattype',1); WriteData(fid,prefix,'object',self,'fieldname','age','format','DoubleMat','mattype',1,'scale',yts); - if md.thermal.isenthalpy, - if numel(self.enthalpy) <= 1, + if md.thermal.isenthalpy + if numel(self.enthalpy) <= 1 %reconstruct enthalpy tpmp = md.materials.meltingpoint - md.materials.beta*md.initialization.pressure; pos = find(md.initialization.waterfraction>0.); @@ -212,8 +212,8 @@ function marshall(self,prefix,md,fid) % {{{ self.bottompressure=project3d(md,'vector',self.bottompressure,'type','node','layer',1); self.dsl=project3d(md,'vector',self.dsl,'type','node','layer',1); self.str=project3d(md,'vector',self.str,'type','node','layer',1); - self.str=project3d(md,'vector',self.debris,'type','node','layer',1); - self.str=project3d(md,'vector',self.age,'type','node','layer',1); + self.debris=project3d(md,'vector',self.debris,'type','node','layer',1); + self.age=project3d(md,'vector',self.age,'type','node','layer',1); %Lithostatic pressure by default self.pressure=md.constants.g*md.materials.rho_ice*(md.geometry.surface-md.mesh.z); diff --git a/src/m/classes/inversion.m b/src/m/classes/inversion.m index 2722e4a4b..a0c4db436 100644 --- a/src/m/classes/inversion.m +++ b/src/m/classes/inversion.m @@ -103,7 +103,7 @@ %Only SSA, HO and FS are supported right now if strcmp(solution,'StressbalanceSolution') - if ~(md.flowequation.isSSA || md.flowequation.isMOLHO || md.flowequation.isHO || md.flowequation.isFS || md.flowequation.isL1L2), + if ~(md.flowequation.isSSA || md.flowequation.isMOLHO || md.flowequation.isHO || md.flowequation.isFS || md.flowequation.isL1L2) md = checkmessage(md,['inversion can only be performed for SSA, MOLHO, HO or FS ice flow models']); end end diff --git a/src/m/classes/inversionnudging.m b/src/m/classes/inversionnudging.m new file mode 100644 index 000000000..9c6e10314 --- /dev/null +++ b/src/m/classes/inversionnudging.m @@ -0,0 +1,57 @@ +%INVERSIONVALIDATION class definition +% +% Usage: +% inversionnudging=inversionnudging(); + +classdef inversionnudging + properties (SetAccess=public) + iscontrol = 0 + tau_C = 0.0; + dhdt_obs = NaN; + end + methods + function self = extrude(self,md) % {{{ + self.dhdt_obs =project3d(md,'vector',self.dhdt_obs, 'type', 'node'); + end % }}} + function self = inversionnudging(varargin) % {{{ + switch nargin + case 0 + self=setdefaultparameters(self); + case 1 + self=structtoobj(inversionnudging(),varargin{1}); + otherwise + error('constructor not supported'); + end + end % }}} + function self = setdefaultparameters(self) % {{{ + + % Cadjustment timescale 100 yrs used in van den Akker et al (2025) + self.tau_C = 100.0; + end % }}} + function md = checkconsistency(self,md,solution,analyses) % {{{ + + %Early return + if(~self.iscontrol) return; end + + md = checkfield(md,'fieldname','inversion.iscontrol','values',[0 1]); + md = checkfield(md,'fieldname','inversion.tau_C','numel',1,'>',0); + md = checkfield(md,'fieldname','inversion.dhdt_obs','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); + end % }}} + function disp(self) % {{{ + disp(sprintf(' Nudging parameters:')); + fielddisplay(self,'iscontrol','is inversion activated?'); + fielddisplay(self,'tau_C','adjustment timescale for friction coefficient [yr]'); + fielddisplay(self,'dhdt_obs','observed thickness rate of change [m/yr]'); + end % }}} + function marshall(self, prefix, md, fid) % {{{ + + yts=md.constants.yts; + + WriteData(fid,prefix,'object',self,'class','inversion','fieldname','iscontrol','format','Boolean'); + WriteData(fid,prefix,'name','md.inversion.type','data',5,'format','Integer'); + if ~self.iscontrol, return; end + WriteData(fid,prefix,'object',self,'class','inversion','fieldname','tau_C','format','Double','scale',yts); + WriteData(fid,prefix,'object',self,'class','inversion','fieldname','dhdt_obs','format','DoubleMat','mattype',1,'scale',1./yts); + end % }}} + end +end diff --git a/src/m/classes/inversionvalidation.m b/src/m/classes/inversionvalidation.m index ce0c6bedd..4a8eccebf 100644 --- a/src/m/classes/inversionvalidation.m +++ b/src/m/classes/inversionvalidation.m @@ -78,7 +78,7 @@ md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); else md = checkfield(md,'fieldname','inversion.vx_obs','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); - if ~strcmp(domaintype(md.mesh),'2Dvertical'), + if ~strcmp(domaintype(md.mesh),'2Dvertical') md = checkfield(md,'fieldname','inversion.vy_obs','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); end end diff --git a/src/m/classes/issmsettings.m b/src/m/classes/issmsettings.m index be4bc33a9..bb5a4ecb9 100644 --- a/src/m/classes/issmsettings.m +++ b/src/m/classes/issmsettings.m @@ -127,7 +127,7 @@ function savemodeljs(self,fid,modelname) % {{{ writejsstring(fid,[modelname '.settings.upload_login'],self.upload_login); writejsdouble(fid,[modelname '.settings.upload_port'],self.upload_port); writejsstring(fid,[modelname '.settings.upload_filename'],self.upload_filename); - writejsstring(fid,[modelname '.settings.solver_residue_threshold'],self.solver_residue_threshold); + writejsdouble(fid,[modelname '.settings.solver_residue_threshold'],self.solver_residue_threshold); end % }}} end end diff --git a/src/m/classes/levelset.m b/src/m/classes/levelset.m index d8853cefc..b2cfd708c 100644 --- a/src/m/classes/levelset.m +++ b/src/m/classes/levelset.m @@ -23,7 +23,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/linearbasalforcings.m b/src/m/classes/linearbasalforcings.m index 9a61752b2..b32a62f44 100644 --- a/src/m/classes/linearbasalforcings.m +++ b/src/m/classes/linearbasalforcings.m @@ -31,7 +31,7 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end @@ -53,21 +53,21 @@ md = checkfield(md,'fieldname','basalforcings.perturbation_melting_rate','NaN',1,'Inf',1,'timeseries',1); end - if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0), + if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0,'singletimeseries',1); md = checkfield(md,'fieldname','basalforcings.upperwater_melting_rate','>=',0,'singletimeseries',1); md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','<','basalforcings.upperwater_elevation','singletimeseries',1); md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','<=',0,'singletimeseries',1); end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0,'singletimeseries',1); md = checkfield(md,'fieldname','basalforcings.upperwater_melting_rate','>=',0,'singletimeseries',1); md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','<','basalforcings.upperwater_elevation','singletimeseries',1); md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','<=',0,'singletimeseries',1); end - if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0), + if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0,'singletimeseries',1); md = checkfield(md,'fieldname','basalforcings.upperwater_melting_rate','>=',0,'singletimeseries',1); diff --git a/src/m/classes/linearbasalforcings.py b/src/m/classes/linearbasalforcings.py index 59970924c..30d62c39b 100644 --- a/src/m/classes/linearbasalforcings.py +++ b/src/m/classes/linearbasalforcings.py @@ -16,7 +16,6 @@ class linearbasalforcings(object): def __init__(self, *args): # {{{ nargs = len(args) if nargs == 0: - print('empty init') self.deepwater_melting_rate = 0. self.deepwater_elevation = 0. self.upperwater_melting_rate = 0. diff --git a/src/m/classes/linearbasalforcingsarma.m b/src/m/classes/linearbasalforcingsarma.m index ca8b3c26f..9763d57c9 100644 --- a/src/m/classes/linearbasalforcingsarma.m +++ b/src/m/classes/linearbasalforcingsarma.m @@ -41,7 +41,7 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end @@ -75,7 +75,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0), + if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0) nbas = md.basalforcings.num_basins; nprm = md.basalforcings.num_params; nbrk = md.basalforcings.num_breaks; @@ -109,10 +109,10 @@ error('md.basalforcings.num_breaks is 0 but md.basalforcings.datebreaks is not empty'); end end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) error('not implemented yet!'); end - if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0), + if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0) error('not implemented yet!'); end if numel(md.basalforcings.geothermalflux)>1 diff --git a/src/m/classes/love.m b/src/m/classes/love.m index bee307a4a..a4c31afcc 100644 --- a/src/m/classes/love.m +++ b/src/m/classes/love.m @@ -41,7 +41,7 @@ % This function is directly called by matlab when a model object is % loaded. Update old properties here - if isstruct(self), + if isstruct(self) oldself=self; %Assign property values from struct self=structtoobj(love(),oldself); diff --git a/src/m/classes/lovenumbers.m b/src/m/classes/lovenumbers.m index b10f9bb50..1f33ea87e 100644 --- a/src/m/classes/lovenumbers.m +++ b/src/m/classes/lovenumbers.m @@ -79,7 +79,7 @@ function disp(self) % {{{ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0) return; end @@ -98,7 +98,7 @@ function disp(self) % {{{ md = checkfield(md,'fieldname','solidearth.lovenumbers.istime','NaN',1,'Inf',1,'values',[0 1]); %check that love numbers are provided at the same level of accuracy: - if (size(self.h,1)~=size(self.k,1) | size(self.h,1)~=size(self.l,1)), + if (size(self.h,1)~=size(self.k,1) | size(self.h,1)~=size(self.l,1)) error('lovenumbers error message: love numbers should be provided at the same level of accuracy'); end @@ -128,7 +128,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','pmtf_ortho','name','md.solidearth.lovenumbers.pmtf_ortho','format','DoubleMat','mattype',1); WriteData(fid,prefix,'object',self,'data',self.tk2secular,'fieldname','lovenumbers.tk2secular','format','Double'); - if self.istime, + if self.istime scale=md.constants.yts; else scale=1.0/md.constants.yts; diff --git a/src/m/classes/m1qn3inversion.m b/src/m/classes/m1qn3inversion.m index b62d2825e..1a5882c4c 100644 --- a/src/m/classes/m1qn3inversion.m +++ b/src/m/classes/m1qn3inversion.m @@ -75,10 +75,6 @@ %Early return if ~self.iscontrol, return; end - - if ~IssmConfig('_HAVE_M1QN3_'), - md = checkmessage(md,['M1QN3 has not been installed, ISSM needs to be reconfigured and recompiled with M1QN3']); - end num_controls=numel(md.inversion.control_parameters); num_costfunc=size(md.inversion.cost_functions,2); @@ -89,7 +85,7 @@ md = checkfield(md,'fieldname','inversion.maxsteps','numel',1,'>=',0); md = checkfield(md,'fieldname','inversion.maxiter','numel',1,'>=',0); md = checkfield(md,'fieldname','inversion.dxmin','numel',1,'>',0); - md = checkfield(md,'fieldname','inversion.dfmin_frac','numel',1,'>=',0,'<=',1); + md = checkfield(md,'fieldname','inversion.dfmin_frac','numel',1,'>=',0,'<=',1); md = checkfield(md,'fieldname','inversion.gttol','numel',1,'>',0); md = checkfield(md,'fieldname','inversion.cost_functions','size',[1 num_costfunc],'values',supportedcostfunctions()); md = checkfield(md,'fieldname','inversion.cost_functions_coefficients','size',[md.mesh.numberofvertices num_costfunc],'>=',0); @@ -103,7 +99,7 @@ md = checkfield(md,'fieldname','inversion.thickness_obs','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); else md = checkfield(md,'fieldname','inversion.vx_obs','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); - if ~strcmp(domaintype(md.mesh),'2Dvertical'), + if ~strcmp(domaintype(md.mesh),'2Dvertical') md = checkfield(md,'fieldname','inversion.vy_obs','size',[md.mesh.numberofvertices 1],'NaN',1,'Inf',1); end end @@ -117,7 +113,7 @@ function disp(self) % {{{ fielddisplay(self,'maxsteps','maximum number of iterations (gradient computation)'); fielddisplay(self,'maxiter','maximum number of Function evaluation (forward run)'); fielddisplay(self,'dxmin','convergence criterion: two points less than dxmin from eachother (sup-norm) are considered identical'); - fielddisplay(self,'dfmin_frac','expected reduction of J during the first step (e.g., 0.3=30% reduction in cost function)'); + fielddisplay(self,'dfmin_frac','expected reduction of J during the first step (e.g., 0.3=30% reduction in cost function)'); fielddisplay(self,'gttol','convergence criterion: ||g(X)||/||g(X0)|| (g(X0): gradient at initial guess X0)'); fielddisplay(self,'cost_functions','indicate the type of response for each optimization step'); fielddisplay(self,'cost_functions_coefficients','cost_functions_coefficients applied to the misfit of each vertex and for each control_parameter'); @@ -151,7 +147,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxsteps','format','Integer'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','maxiter','format','Integer'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','dxmin','format','Double'); - WriteData(fid,prefix,'object',self,'class','inversion','fieldname','dfmin_frac','format','Double'); + WriteData(fid,prefix,'object',self,'class','inversion','fieldname','dfmin_frac','format','Double'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','gttol','format','Double'); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','cost_functions_coefficients','format','DoubleMat','mattype',1); WriteData(fid,prefix,'object',self,'class','inversion','fieldname','min_parameters','format','DoubleMat','mattype',3); @@ -188,7 +184,7 @@ function savemodeljs(self,fid,modelname) % {{{ writejsdouble(fid,[modelname '.inversion.maxsteps'],self.maxsteps); writejsdouble(fid,[modelname '.inversion.maxiter'],self.maxiter); writejsdouble(fid,[modelname '.inversion.dxmin'],self.dxmin); - writejsdouble(fid,[modelname '.inversion.dfmin_frac'],self.dfmin_frac); + writejsdouble(fid,[modelname '.inversion.dfmin_frac'],self.dfmin_frac); writejsdouble(fid,[modelname '.inversion.gttol'],self.gttol); writejs2Darray(fid,[modelname '.inversion.cost_functions'],self.cost_functions); writejs2Darray(fid,[modelname '.inversion.cost_functions_coefficients'],self.cost_functions_coefficients); diff --git a/src/m/classes/m1qn3inversion.py b/src/m/classes/m1qn3inversion.py index 0a03475f2..43cc7d437 100644 --- a/src/m/classes/m1qn3inversion.py +++ b/src/m/classes/m1qn3inversion.py @@ -17,7 +17,6 @@ class m1qn3inversion(object): def __init__(self, *args): # {{{ if not len(args): - print('empty init') self.iscontrol = 0 self.incomplete_adjoint = 0 self.control_parameters = np.nan diff --git a/src/m/classes/mask.m b/src/m/classes/mask.m index fcf1284c0..4f76cc5b1 100644 --- a/src/m/classes/mask.m +++ b/src/m/classes/mask.m @@ -57,22 +57,22 @@ function disp(self) % {{{ end end % }}} function self=setocean(self,varargin) % {{{ - if nargin==3, + if nargin==3 ocean=varargin{1}; index=varargin{2}; self.ocean_levelset(index)=-ocean; - elseif nargin==2, + elseif nargin==2 ocean=varargin{1}; self.ocean_levelset=-ocean; else error('oceanset error message: not supported yet'); end end % }}} function self=setice(self,varargin) % {{{ - if nargin==3, + if nargin==3 ice=varargin{1}; index=varargin{2}; self.ice_levelset(index)=-ice; - elseif nargin==2, + elseif nargin==2 ice=varargin{1}; self.ice_levelset=-ice; else error('iceset error message: not supported yet'); @@ -82,35 +82,35 @@ function disp(self) % {{{ function md = checkconsistency(self,md,solution,analyses) % {{{ if strcmpi(solution,'LoveSolution'), return; end; - if isa(self.ocean_levelset,'cell'), - for i=1:length(self.ocean_levelset), - md = checkfield(md,'field',self.ocean_levelset{i},'NaN',0,'Inf',1,'timeserieslength',1,'Inf',1); + if isa(self.ocean_levelset,'cell') + for i=1:length(self.ocean_levelset) + md = checkfield(md,'field',self.ocean_levelset{i},'NaN',0,'Inf',1,'timeserieslength',1); end else md = checkfield(md,'fieldname','mask.ocean_levelset','timeseries',1,'NaN',1); end - if isa(self.ice_levelset,'cell'), - for i=1:length(self.ice_levelset), - md = checkfield(md,'field',self.ice_levelset{i},'NaN',0,'Inf',1,'timeserieslength',1,'Inf',1); + if isa(self.ice_levelset,'cell') + for i=1:length(self.ice_levelset) + md = checkfield(md,'field',self.ice_levelset{i},'NaN',0,'Inf',1,'timeserieslength',1); end else md = checkfield(md,'fieldname','mask.ice_levelset','timeseries',1,'NaN',1); isice=(md.mask.ice_levelset<=0); - if sum(isice)==0, + if sum(isice)==0 warning('no ice present in the domain'); end end end % }}} function marshall(self,prefix,md,fid) % {{{ - if isa(self.ocean_levelset,'cell'), + if isa(self.ocean_levelset,'cell') WriteData(fid,prefix,'object',self,'fieldname','ocean_levelset','name','md.mask.ocean_levelset','format','MatArray','timeseries',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); else WriteData(fid,prefix,'object',self,'fieldname','ocean_levelset','format','DoubleMat','mattype',1,'timeseries',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); end - if isa(self.ice_levelset,'cell'), + if isa(self.ice_levelset,'cell') WriteData(fid,prefix,'object',self,'fieldname','ice_levelset','name','md.mask.ice_levelset','format','MatArray','timeseries',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); else WriteData(fid,prefix,'object',self,'fieldname','ice_levelset','format','DoubleMat','mattype',1,'timeseries',1,'timeserieslength',md.mesh.numberofvertices+1,'yts',md.constants.yts); diff --git a/src/m/classes/masscon.m b/src/m/classes/masscon.m index 828e3fc80..98c444579 100644 --- a/src/m/classes/masscon.m +++ b/src/m/classes/masscon.m @@ -24,7 +24,7 @@ end end % }}} function self = masscon(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -41,7 +41,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('masscon error message: ''name'' field should be a string!'); end diff --git a/src/m/classes/massconaxpby.m b/src/m/classes/massconaxpby.m index 8abc2c41a..e00658624 100644 --- a/src/m/classes/massconaxpby.m +++ b/src/m/classes/massconaxpby.m @@ -25,7 +25,7 @@ function self = extrude(self,md) % {{{ end % }}} function self = massconaxpby(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields diff --git a/src/m/classes/massfluxatgate.m b/src/m/classes/massfluxatgate.m index 9fd877085..7c419d71d 100644 --- a/src/m/classes/massfluxatgate.m +++ b/src/m/classes/massfluxatgate.m @@ -18,7 +18,7 @@ function self = extrude(self,md) % {{{ end % }}} function self = massfluxatgate(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -34,10 +34,10 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('massfluxatgate error message: ''name'' field should be a string!'); end - if ~ischar(self.profilename), + if ~ischar(self.profilename) error('massfluxatgate error message: ''profilename'' field should be a string!'); end @@ -48,7 +48,7 @@ md = checkfield(md,'field',self.definitionstring,'values',OutputdefinitionStringArray); %check the profilename points to a file!: - if exist(self.profilename,'file')~=2, + if exist(self.profilename,'file')~=2 error('massfluxatgate error message: file name for profile corresponding to gate does not point to a legitimate file on disk!'); end end % }}} diff --git a/src/m/classes/masstransport.m b/src/m/classes/masstransport.m index 4c2502bf5..182db6804 100644 --- a/src/m/classes/masstransport.m +++ b/src/m/classes/masstransport.m @@ -21,7 +21,7 @@ % old fields must be recovered (make sure they are in the deprecated % model properties) - if verLessThan('matlab','7.9'), + if verLessThan('matlab','7.9') disp('Warning: your matlab version is old and there is a risk that load does not work correctly'); disp(' if the model is not loaded correctly, rename temporarily loadobj so that matlab does not use it'); @@ -50,7 +50,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -94,7 +94,7 @@ md = checkfield(md,'fieldname','masstransport.stabilization','values',[0 1 2 3 4 5]); md = checkfield(md,'fieldname','masstransport.min_thickness','>',0); md = checkfield(md,'fieldname','masstransport.requested_outputs','stringrow',1); - if ~any(isnan(md.stressbalance.vertex_pairing)), + if ~any(isnan(md.stressbalance.vertex_pairing)) md = checkfield(md,'fieldname','stressbalance.vertex_pairing','>',0); end end % }}} @@ -127,7 +127,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/matdamageice.m b/src/m/classes/matdamageice.m index fc3dcc88e..5993555bc 100644 --- a/src/m/classes/matdamageice.m +++ b/src/m/classes/matdamageice.m @@ -41,7 +41,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -108,7 +108,7 @@ md = checkfield(md,'fieldname','materials.rheology_law','values',{'None' 'BuddJacka' 'Cuffey' 'CuffeyTemperate' 'Paterson' 'Arrhenius' 'LliboutryDuval'}); md = checkfield(md,'fieldname','materials.effectiveconductivity_averaging','numel',[1],'values',[0 1 2]); - if ismember('SealevelchangeAnalysis',analyses), + if ismember('SealevelchangeAnalysis',analyses) md = checkfield(md,'fieldname','materials.earth_density','>',0,'numel',1); end diff --git a/src/m/classes/matenhancedice.m b/src/m/classes/matenhancedice.m index 170655d55..173686541 100644 --- a/src/m/classes/matenhancedice.m +++ b/src/m/classes/matenhancedice.m @@ -43,7 +43,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -111,7 +111,7 @@ md = checkfield(md,'fieldname','materials.rheology_law','values',{'None' 'BuddJacka' 'Cuffey' 'CuffeyTemperate' 'Paterson' 'Arrhenius' 'LliboutryDuval'}); md = checkfield(md,'fieldname','materials.effectiveconductivity_averaging','numel',[1],'values',[0 1 2]); - if ismember('SealevelchangeAnalysis',analyses), + if ismember('SealevelchangeAnalysis',analyses) md = checkfield(md,'fieldname','materials.earth_density','>',0,'numel',1); end diff --git a/src/m/classes/materials.m b/src/m/classes/materials.m index c61a6b432..08474d60b 100755 --- a/src/m/classes/materials.m +++ b/src/m/classes/materials.m @@ -17,14 +17,14 @@ end %check this is acceptable: - for i=1:length(self.nature), - if ~(strcmpi(self.nature{i},'litho') | strcmpi(self.nature{i},'ice') | strcmpi(self.nature{i},'hydro')), + for i=1:length(self.nature) + if ~(strcmpi(self.nature{i},'litho') | strcmpi(self.nature{i},'ice') | strcmpi(self.nature{i},'hydro')) error('materials constructor error message: nature of the material not supported yet! (''ice'' or ''litho'' or ''hydro'')'); end end %start filling in the dynamic fields: - for i=1:length(self.nature), + for i=1:length(self.nature) nat=self.nature{i}; switch nat case 'ice' @@ -75,7 +75,7 @@ end % }}} function self = setdefaultparameters(self) % {{{ - for i=1:length(self.nature), + for i=1:length(self.nature) nat=self.nature{i}; switch nat case 'ice' @@ -170,7 +170,7 @@ function disp(self) % {{{ disp(sprintf(' Materials:')); - for i=1:length(self.nature), + for i=1:length(self.nature) nat=self.nature{i}; switch nat case 'ice' @@ -223,7 +223,7 @@ function disp(self) % {{{ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - for i=1:length(self.nature), + for i=1:length(self.nature) nat=self.nature{i}; switch nat case 'ice' @@ -257,11 +257,11 @@ function disp(self) % {{{ if any(diff(md.materials.radius)<=0) error('materials checkconsistency error message: radius should be monotonously increasing'); end - for i=1:md.materials.numlayers, - if md.materials.rheologymodel(i)==1 & (isnan(md.materials.burgers_viscosity(i) | isnan(md.materials.burgers_mu(i)))), + for i=1:md.materials.numlayers + if md.materials.rheologymodel(i)==1 & (isnan(md.materials.burgers_viscosity(i) | isnan(md.materials.burgers_mu(i)))) error('materials checkconsistency error message: Litho burgers_viscosity or burgers_mu has NaN values, inconsistent with rheologymodel choice'); end - if md.materials.rheologymodel(i)==2 & (isnan(md.materials.ebm_alpha(i)) | isnan(md.materials.ebm_delta(i)) | isnan(md.materials.ebm_taul(i)) | isnan(md.materials.ebm_tauh(i))), + if md.materials.rheologymodel(i)==2 & (isnan(md.materials.ebm_alpha(i)) | isnan(md.materials.ebm_delta(i)) | isnan(md.materials.ebm_taul(i)) | isnan(md.materials.ebm_tauh(i))) error('materials checkconsistency error message: Litho ebm_alpha, ebm_delta, ebm_taul or ebm_tauh has NaN values, inconsistent with rheologymodel choice'); end end @@ -290,7 +290,7 @@ function marshall(self,prefix,md,fid) % {{{ %1: MatdamageiceEnum 2: MatestarEnum 3: MaticeEnum 4: MatenhancediceEnum 5: MaterialsEnum WriteData(fid,prefix,'name','md.materials.nature','data',naturetointeger(self.nature),'format','IntMat','mattype',3); WriteData(fid,prefix,'name','md.materials.type','data',5,'format','Integer'); %DANGER: this can evolve if you have classes. - for i=1:length(self.nature), + for i=1:length(self.nature) nat=self.nature{i}; switch nat case 'ice' @@ -327,7 +327,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','materials','fieldname','ebm_tauh','format','DoubleMat','mattype',3); %compute earth density compatible with our layer density distribution: earth_density=0; - for i=1:self.numlayers, + for i=1:self.numlayers earth_density=earth_density + (self.radius(i+1)^3-self.radius(i)^3)*self.density(i); end earth_density=earth_density/self.radius(self.numlayers+1)^3; @@ -343,7 +343,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'data',self.earth_density,'name','md.materials.earth_density','format','Double'); end % }}} function self = extrude(self,md) % {{{ - for i=1:length(self.nature), + for i=1:length(self.nature) nat=self.nature{i}; switch nat case 'ice' @@ -354,7 +354,7 @@ function marshall(self,prefix,md,fid) % {{{ end % }}} function savemodeljs(self,fid,modelname) % {{{ - for i=1:length(self.nature), + for i=1:length(self.nature) nat=self.nature{i}; switch nat case 'ice' @@ -566,7 +566,7 @@ function setlitho2prem(self) % {{{ function intnat = naturetointeger(strnat) % {{{ intnat=zeros(length(strnat),1); - for i=1:length(strnat), + for i=1:length(strnat) switch strnat{i}, case 'damageice' intnat(i)=1; diff --git a/src/m/classes/matestar.m b/src/m/classes/matestar.m index 5d819da76..f5ffcb852 100644 --- a/src/m/classes/matestar.m +++ b/src/m/classes/matestar.m @@ -43,11 +43,11 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end - if strcmp(class(inputstruct),'matice'), + if strcmp(class(inputstruct),'matice') disp('Converting materials to ESTAR, keeping a Glen type relation'); %Set parameters so that we still use a Glen's like flow relation self.rheology_Es = ones(size(inputstruct.rheology_B)); @@ -118,7 +118,7 @@ md = checkfield(md,'fieldname','materials.rheology_law','values',{'None' 'BuddJacka' 'Cuffey' 'CuffeyTemperate' 'Paterson' 'Arrhenius' 'LliboutryDuval'}); md = checkfield(md,'fieldname','materials.effectiveconductivity_averaging','numel',[1],'values',[0 1 2]); - if ismember('SealevelchangeAnalysis',analyses), + if ismember('SealevelchangeAnalysis',analyses) md = checkfield(md,'fieldname','materials.earth_density','>',0,'numel',1); end diff --git a/src/m/classes/matice.m b/src/m/classes/matice.m index ff1cd8912..35119336f 100644 --- a/src/m/classes/matice.m +++ b/src/m/classes/matice.m @@ -41,7 +41,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -104,7 +104,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if strcmpi(solution,'TransientSolution') & md.transient.isslc, + if strcmpi(solution,'TransientSolution') & md.transient.isslc md = checkfield(md,'fieldname','materials.earth_density','>',0,'numel',1); else md = checkfield(md,'fieldname','materials.rho_ice','>',0); @@ -179,7 +179,6 @@ function savemodeljs(self,fid,modelname) % {{{ writejsdouble(fid,[modelname '.materials.beta'],self.beta); writejsdouble(fid,[modelname '.materials.mixed_layer_capacity'],self.mixed_layer_capacity); writejsdouble(fid,[modelname '.materials.thermal_exchange_velocity'],self.thermal_exchange_velocity); - writejsdouble(fid,[modelname '.materials.mixed_layer_capacity'],self.mixed_layer_capacity); writejs1Darray(fid,[modelname '.materials.rheology_B'],self.rheology_B); writejs1Darray(fid,[modelname '.materials.rheology_n'],self.rheology_n); writejsstring(fid,[modelname '.materials.rheology_law'],self.rheology_law); diff --git a/src/m/classes/mesh2d.m b/src/m/classes/mesh2d.m index 4cc0cfffd..4920eaf78 100644 --- a/src/m/classes/mesh2d.m +++ b/src/m/classes/mesh2d.m @@ -36,13 +36,13 @@ % loaded. Update old properties here %2014 Oct. 1st - if isstruct(self), + if isstruct(self) oldself=self; %Assign property values from struct self=structtoobj(mesh2d(),oldself); - if isfield(oldself,'hemisphere'), + if isfield(oldself,'hemisphere') disp('md.mesh.hemisphere has been automatically converted to EPSG code'); - if strcmpi(oldself.hemisphere,'n'), + if strcmpi(oldself.hemisphere,'n') self.epsg=3413; self.proj=epsg2proj(3413); else @@ -65,7 +65,7 @@ fields=fieldnames(object); for i=1:length(fields) field=fields{i}; - if ismember(field,properties('mesh2d')), + if ismember(field,properties('mesh2d')) self.(field)=object.(field); end end @@ -97,7 +97,7 @@ md = checkfield(md,'fieldname','mesh.numberofvertices','>',0); md = checkfield(md,'fieldname','mesh.average_vertex_connectivity','>=',9,'message','''mesh.average_vertex_connectivity'' should be at least 9 in 2d'); md = checkfield(md,'fieldname','mesh.segments','NaN',1,'Inf',1,'>',0,'size',[NaN 3]); - if numel(md.mesh.scale_factor)>1, + if numel(md.mesh.scale_factor)>1 md = checkfield(md,'fieldname','mesh.scale_factor','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end @@ -150,7 +150,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','mesh','fieldname','vertexonboundary','format','DoubleMat','mattype',1); WriteData(fid,prefix,'object',self,'class','mesh','fieldname','segments','format','DoubleMat','mattype',3); WriteData(fid,prefix,'object',self,'class','mesh','fieldname','scale_factor','format','DoubleMat','mattype',1); - if md.transient.isoceancoupling, %Need to add lat/long coordinates to couple with ocean as they rely on lat/long coordinate system + if md.transient.isoceancoupling | isa(md.smb,'SMBemulator'), %Need to add lat/long coordinates to couple with ocean as they rely on lat/long coordinate system WriteData(fid,prefix,'object',self,'class','mesh','fieldname','lat','format','DoubleMat','mattype',1); WriteData(fid,prefix,'object',self,'class','mesh','fieldname','long','format','DoubleMat','mattype',1); end @@ -199,16 +199,16 @@ function export(self,varargin) % {{{ %prepare contours: contours= struct([]); - if strcmpi(geometry,'point'), - for i=1:self.numberofvertices, + if strcmpi(geometry,'point') + for i=1:self.numberofvertices contours(i).x = self.x(i); contours(i).y = self.y(i); contours(i).id = i; contours(i).Geometry = 'Point'; end - elseif strcmpi(geometry,'line'), + elseif strcmpi(geometry,'line') counter=1; - for i=1:self.numberofelements, + for i=1:self.numberofelements el=self.elements(i,:); %first line: contours(counter).x = [self.x(el(1)) self.x(el(2))]; @@ -228,10 +228,10 @@ function export(self,varargin) % {{{ %increase counter: counter=counter+3; end - elseif strcmpi(geometry,'polygon'), - if isempty(index), + elseif strcmpi(geometry,'polygon') + if isempty(index) counter=1; - for i=1:self.numberofelements, + for i=1:self.numberofelements el=self.elements(i,:); contours(i).x=[self.x(el(1)) self.x(el(2)) self.x(el(3)) self.x(el(1))]; contours(i).y=[self.y(el(1)) self.y(el(2)) self.y(el(3)) self.y(el(1))]; @@ -240,7 +240,7 @@ function export(self,varargin) % {{{ end else counter=1; - for i=1:length(index), + for i=1:length(index) el=self.elements(index(i),:); contours(i).x=[self.x(el(1)) self.x(el(2)) self.x(el(3)) self.x(el(1))]; contours(i).y=[self.y(el(1)) self.y(el(2)) self.y(el(3)) self.y(el(1))]; @@ -253,16 +253,16 @@ function export(self,varargin) % {{{ end %write file: - if strcmpi(format,'shp'), + if strcmpi(format,'shp') shpwrite(contours,filename); - elseif strcmpi(format,'exp'), + elseif strcmpi(format,'exp') expwrite(contours,filename); else error(sprintf('mesh3dsurface ''export'' error message: file format %s not supported yet',format)); end %write projection file: - if ~isempty(proj), + if ~isempty(proj) proj2shpprj(filename,proj); end %write style file: diff --git a/src/m/classes/mesh2dvertical.m b/src/m/classes/mesh2dvertical.m index 6f1c4d52c..4c7113a2c 100644 --- a/src/m/classes/mesh2dvertical.m +++ b/src/m/classes/mesh2dvertical.m @@ -35,13 +35,13 @@ % loaded. Update old properties here %2014 Oct. 1st - if isstruct(self), + if isstruct(self) oldself=self; %Assign property values from struct self=structtoobj(mesh2dvertical(),oldself); - if isfield(oldself,'hemisphere'), + if isfield(oldself,'hemisphere') disp('md.mesh.hemisphere has been automatically converted to EPSG code'); - if strcmpi(oldself.hemisphere,'n'), + if strcmpi(oldself.hemisphere,'n') self.epsg=3413; self.proj=epsg2proj(3413); else @@ -64,7 +64,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -97,7 +97,7 @@ md = checkfield(md,'fieldname','mesh.vertexonbase','size',[md.mesh.numberofvertices 1],'values',[0 1]); md = checkfield(md,'fieldname','mesh.vertexonsurface','size',[md.mesh.numberofvertices 1],'values',[0 1]); md = checkfield(md,'fieldname','mesh.average_vertex_connectivity','>=',9,'message','''mesh.average_vertex_connectivity'' should be at least 9 in 2d'); - if numel(md.mesh.scale_factor)>1, + if numel(md.mesh.scale_factor)>1 md = checkfield(md,'fieldname','mesh.scale_factor','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end @@ -166,7 +166,7 @@ function marshall(self,prefix,md,fid) % {{{ function [data datatype] = processdata(self,md,data,options) % {{{ %transpose data if necessary - if (size(data,2) > size(data,1)), + if (size(data,2) > size(data,1)) data=data'; end datasize=size(data); @@ -183,7 +183,7 @@ function marshall(self,prefix,md,fid) % {{{ end %quiver? - if datasize(2)>1, + if datasize(2)>1 datatype=3; end @@ -195,14 +195,14 @@ function marshall(self,prefix,md,fid) % {{{ end %element data - if (datasize(1)==md.mesh.numberofelements & datasize(2)==1), + if (datasize(1)==md.mesh.numberofelements & datasize(2)==1) datatype=1; %Mask? - if exist(options,'mask'), + if exist(options,'mask') flags=getfieldvalue(options,'mask'); pos=find(~flags); - if length(flags)==md.mesh.numberofvertices, + if length(flags)==md.mesh.numberofvertices [pos2 dummy]=find(ismember(md.mesh.elements,pos)); data(pos2,:)=NaN; elseif length(flags)==md.mesh.numberofelements @@ -213,10 +213,10 @@ function marshall(self,prefix,md,fid) % {{{ end %log? - if exist(options,'log'), + if exist(options,'log') bounds=getfieldvalue(options,'caxis',[min(data(:)) max(data(:))]); data(find(data=',md.geometry.base-10^-10,'message','''mesh.z'' lower than bedrock'); md = checkfield(md,'fieldname','mesh.z','<=',md.geometry.surface+10^-10,'message','''mesh.z'' higher than surface elevation'); - if any(max(abs(project2d(md,md.mesh.z,1)-project2d(md,md.geometry.base,1)))>1e-10), + if any(max(abs(project2d(md,md.mesh.z,1)-project2d(md,md.geometry.base,1)))>1e-10) md = checkmessage(md,'md.mesh.z is not consistent with md.geometry.base, you changed the geometry after extrusion'); end - if any(max(abs(project2d(md,md.mesh.z,md.mesh.numberoflayers)-project2d(md,md.geometry.surface,1)))>1e-10), + if any(max(abs(project2d(md,md.mesh.z,md.mesh.numberoflayers)-project2d(md,md.geometry.surface,1)))>1e-10) md = checkmessage(md,'md.mesh.z is not consistent with md.geometry.surface, you changed the geometry after extrusion !!'); end - if any(max(abs(project2d(md,md.mesh.z,md.mesh.numberoflayers)-project2d(md,md.mesh.z,1) - project2d(md,md.geometry.thickness,1)))>1e-10), + if any(max(abs(project2d(md,md.mesh.z,md.mesh.numberoflayers)-project2d(md,md.mesh.z,1) - project2d(md,md.geometry.thickness,1)))>1e-10) md = checkmessage(md,'md.mesh.z is not consistent with md.geometry.thickness, you changed the geometry after extrusion !!'); end - if numel(md.mesh.scale_factor)>1, + if numel(md.mesh.scale_factor)>1 md = checkfield(md,'fieldname','mesh.scale_factor','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end end % }}} @@ -195,7 +195,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','mesh','fieldname','numberofvertices2d','format','Integer'); WriteData(fid,prefix,'object',self,'class','mesh','fieldname','numberofelements2d','format','Integer'); WriteData(fid,prefix,'object',self,'class','mesh','fieldname','scale_factor','format','DoubleMat','mattype',1); - if md.transient.isoceancoupling, + if md.transient.isoceancoupling WriteData(fid,prefix,'object',self,'class','mesh','fieldname','lat','format','DoubleMat','mattype',1); WriteData(fid,prefix,'object',self,'class','mesh','fieldname','long','format','DoubleMat','mattype',1); end diff --git a/src/m/classes/mesh3dsurface.m b/src/m/classes/mesh3dsurface.m index c6b87e6c6..27e3ecd12 100644 --- a/src/m/classes/mesh3dsurface.m +++ b/src/m/classes/mesh3dsurface.m @@ -35,7 +35,7 @@ % loaded. Update old properties here %2014 Oct. 1st - if isstruct(self), + if isstruct(self) oldself=self; %Assign property values from struct self=structtoobj(mesh3dsurface(),oldself); @@ -62,7 +62,7 @@ fields=fieldnames(object); for i=1:length(fields) field=fields{i}; - if ismember(field,properties('mesh3dsurface')), + if ismember(field,properties('mesh3dsurface')) self.(field)=object.(field); end end @@ -204,16 +204,16 @@ function export(self,varargin) % {{{ %prepare contours: contours= struct([]); - if strcmpi(geometry,'point'), - for i=1:self.numberofvertices, + if strcmpi(geometry,'point') + for i=1:self.numberofvertices contours(i).x = self.long(i); contours(i).y = self.lat(i); contours(i).id = i; contours(i).Geometry = 'Point'; end - elseif strcmpi(geometry,'line'), + elseif strcmpi(geometry,'line') count=1; - for i=1:self.numberofelements, + for i=1:self.numberofelements el=self.elements(i,:); %first line: contours(count).x = [self.long(el(1)) self.long(el(2))]; @@ -233,11 +233,11 @@ function export(self,varargin) % {{{ %increase count: count = count+3; end - elseif strcmpi(geometry,'polygon'), + elseif strcmpi(geometry,'polygon') % TODO: Refactor the following to reduce repeated code, or % leave as is because it is more readable? - if isempty(index), - for i=1:self.numberofelements, + if isempty(index) + for i=1:self.numberofelements el=self.elements(i,:); contours(i).x=[self.long(el(1)) self.long(el(2)) self.long(el(3)) self.long(el(1))]; contours(i).y=[self.lat(el(1)) self.lat(el(2)) self.lat(el(3)) self.lat(el(1))]; @@ -245,7 +245,7 @@ function export(self,varargin) % {{{ contours(i).Geometry = 'Polygon'; end else - for i=1:length(index), + for i=1:length(index) el=self.elements(index(i),:); contours(i).x=[self.long(el(1)) self.long(el(2)) self.long(el(3)) self.long(el(1))]; contours(i).y=[self.lat(el(1)) self.lat(el(2)) self.lat(el(3)) self.lat(el(1))]; @@ -258,16 +258,16 @@ function export(self,varargin) % {{{ end %write file: - if strcmpi(format,'shp'), + if strcmpi(format,'shp') shpwrite(contours,filename); - elseif strcmpi(format,'exp'), + elseif strcmpi(format,'exp') expwrite(contours,filename); else error(sprintf('mesh3dsurface ''export'' error message: file format %s not supported yet',format)); end %write projection file: - if ~isempty(proj), + if ~isempty(proj) proj2shpprj(filename,proj); end diff --git a/src/m/classes/mesh3dtetras.m b/src/m/classes/mesh3dtetras.m index 063d31565..4febdd688 100644 --- a/src/m/classes/mesh3dtetras.m +++ b/src/m/classes/mesh3dtetras.m @@ -46,13 +46,13 @@ % loaded. Update old properties here %2014 Oct. 1st - if isstruct(self), + if isstruct(self) oldself=self; %Assign property values from struct self=structtoobj(mesh3dtetras(),oldself); - if isfield(oldself,'hemisphere'), + if isfield(oldself,'hemisphere') disp('md.mesh.hemisphere has been automatically converted to EPSG code'); - if strcmpi(oldself.hemisphere,'n'), + if strcmpi(oldself.hemisphere,'n') self.epsg=3413; self.proj=epsg2proj(3413); else @@ -75,7 +75,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -112,7 +112,7 @@ md = checkfield(md,'fieldname','mesh.z','>=',md.geometry.base-10^-10,'message','''mesh.z'' lower than bedrock'); md = checkfield(md,'fieldname','mesh.z','<=',md.geometry.surface+10^-10,'message','''mesh.z'' higher than surface elevation'); md = checkfield(md,'fieldname','mesh.average_vertex_connectivity','>=',24,'message','''mesh.average_vertex_connectivity'' should be at least 24 in 3d'); - if numel(md.mesh.scale_factor)>1, + if numel(md.mesh.scale_factor)>1 md = checkfield(md,'fieldname','mesh.scale_factor','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); end diff --git a/src/m/classes/miscellaneous.m b/src/m/classes/miscellaneous.m index b60b8a5d2..cd671dd28 100644 --- a/src/m/classes/miscellaneous.m +++ b/src/m/classes/miscellaneous.m @@ -50,8 +50,8 @@ function savemodeljs(self,fid,modelname) % {{{ writejsstring(fid,[modelname '.miscellaneous.notes'],regexprep(self.notes,newline,';')); writejsstring(fid,[modelname '.miscellaneous.name'],self.name); - if strcmpi(class(self.dummy),'double'), - if size(self.dummy,2)==1, + if strcmpi(class(self.dummy),'double') + if size(self.dummy,2)==1 writejs1Darray(fid,[modelname '.miscellaneous.dummy'],self.dummy); else writejs2Darray(fid,[modelname '.miscellaneous.dummy'],self.dummy); diff --git a/src/m/classes/misfit.m b/src/m/classes/misfit.m index d4ae8b774..e17585bee 100644 --- a/src/m/classes/misfit.m +++ b/src/m/classes/misfit.m @@ -38,7 +38,7 @@ end end % }}} function self = misfit(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -63,7 +63,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('misfit error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; @@ -72,7 +72,7 @@ end md = checkfield(md,'fieldname','self.definitionstring','field',self.definitionstring,'values',OutputdefinitionStringArray); - if ~ischar(self.timeinterpolation), + if ~ischar(self.timeinterpolation) error('misfit error message: ''timeinterpolation'' field should be a string!'); end md = checkfield(md,'fieldname','self.observation','field',self.observation,'timeseries',1,'NaN',1,'Inf',1); diff --git a/src/m/classes/mismipbasalforcings.m b/src/m/classes/mismipbasalforcings.m index 657d42341..850bc8e7a 100644 --- a/src/m/classes/mismipbasalforcings.m +++ b/src/m/classes/mismipbasalforcings.m @@ -28,7 +28,7 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end @@ -44,26 +44,26 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0), + if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.meltrate_factor','>=',0,'size','universal','NaN',1,'Inf',1); md = checkfield(md,'fieldname','basalforcings.threshold_thickness','>=',0,'numel',1); md = checkfield(md,'fieldname','basalforcings.upperdepth_melt','<=',0,'numel',1); end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','basalforcings.meltrate_factor','>=',0,'size','universal','NaN',1,'Inf',1); md = checkfield(md,'fieldname','basalforcings.threshold_thickness','>=',0,'numel',1); md = checkfield(md,'fieldname','basalforcings.upperdepth_melt','<=',0,'numel',1); end - if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0), + if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.meltrate_factor','>=',0,'size','universal','NaN',1,'Inf',1); md = checkfield(md,'fieldname','basalforcings.threshold_thickness','>=',0,'numel',1); md = checkfield(md,'fieldname','basalforcings.upperdepth_melt','<=',0,'numel',1); md = checkfield(md,'fieldname','basalforcings.geothermalflux','NaN',1,'Inf',1,'timeseries',1,'>=',0); end - if isnan(md.geometry.bed), + if isnan(md.geometry.bed) md = checkmessage(md,['requesting mismip basal melting parameterization, but bathymetry is absent!']); end end % }}} diff --git a/src/m/classes/mmeadditionalsolidearthsolution.m b/src/m/classes/mmeadditionalsolidearthsolution.m index 672b18fec..ff952f7bd 100644 --- a/src/m/classes/mmeadditionalsolidearthsolution.m +++ b/src/m/classes/mmeadditionalsolidearthsolution.m @@ -23,7 +23,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.solidearth.settings.isgrd==0), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.solidearth.settings.isgrd==0) error('mmeadditionalsolidearthsolution checkconsistency error message: need to run GRD solution if you are supplying a GRD additional pattern solution'); end @@ -32,21 +32,21 @@ sup=length(self.displacementup); sgeoid=length(self.geoid); - if (seast-snorth)~=0, + if (seast-snorth)~=0 error('mmeadditionalsolidearthsolution checkconsistency error message: displacementeast and displacementnorth should be the same size'); end - if (seast-sup)~=0, + if (seast-sup)~=0 error('mmeadditionalsolidearthsolution checkconsistency error message: displacementeast and displacementup should be the same size'); end - if (seast-sgeoid)~=0, + if (seast-sgeoid)~=0 error('mmeadditionalsolidearthsolution checkconsistency error message: displacementeast and geoid should be the same size'); end md = checkfield(md,'field',self.modelid,'NaN',1,'Inf',1,'>=',1,'<=',length(self.displacementeast)); - for i=1:seast, + for i=1:seast md = checkfield(md,'field',self.displacementeast{i},'NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'field',self.displacementup{i},'NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'field',self.displacementnorth{i},'NaN',1,'Inf',1,'timeseries',1); @@ -68,7 +68,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','modelid','format','Double'); %transform our cell array of time series into cell array of time series of rates - for i=1:nummodels, + for i=1:nummodels displacementeast=self.displacementeast{i}; displacementnorth=self.displacementnorth{i}; displacementup=self.displacementup{i}; diff --git a/src/m/classes/mmemasstransport.m b/src/m/classes/mmemasstransport.m index 46b7efc1f..51e01fc2d 100644 --- a/src/m/classes/mmemasstransport.m +++ b/src/m/classes/mmemasstransport.m @@ -46,12 +46,12 @@ nids=length(self.ids); nt=length(self.thickness); - if size(self.ids,1) < size(self.ids,2), + if size(self.ids,1) < size(self.ids,2) error('mmemasstransport checkconsistency error message: ids should be a column vector'); end md = checkfield(md,'field',self.partition,'fieldname','partition','NaN',1,'Inf',1,'>=',-1,'<=',nids-1,'size',[md.mesh.numberofelements,1]); md = checkfield(md,'field',self.ids,'fieldname','ids','NaN',1,'Inf',1,'>=',1,'<=',nt); - for i=1:nt, + for i=1:nt md = checkfield(md,'field',self.thickness{i},'fieldname',['self.thickness{' num2str(i) '}'],'NaN',0,'Inf',1,'timeseries',1,'timeserieslength',md.mesh.numberofelements+1); %don't check for NaN, as it's a legit value here for vertices that do not belong to the current Mme. end md = checkfield(md,'fieldname','mmemasstransport.requested_outputs','stringrow',1); @@ -76,7 +76,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/mmeofflinesolidearthsolution.m b/src/m/classes/mmeofflinesolidearthsolution.m index e0d5d786a..b177b8a30 100644 --- a/src/m/classes/mmeofflinesolidearthsolution.m +++ b/src/m/classes/mmeofflinesolidearthsolution.m @@ -23,7 +23,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.solidearth.settings.isgrd==1), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.solidearth.settings.isgrd==1) error('mmeofflinesolidearthsolution checkconsistency error message: trying to run GRD patterns while supplying an offline solution for those patterns!'); end @@ -32,21 +32,21 @@ sup=length(self.displacementup); sgeoid=length(self.geoid); - if (seast-snorth)~=0, + if (seast-snorth)~=0 error('mmeofflinesolidearthsolution checkconsistency error message: displacementeast and displacementnorth should be the same size'); end - if (seast-sup)~=0, + if (seast-sup)~=0 error('mmeofflinesolidearthsolution checkconsistency error message: displacementeast and displacementup should be the same size'); end - if (seast-sgeoid)~=0, + if (seast-sgeoid)~=0 error('mmeofflinesolidearthsolution checkconsistency error message: displacementeast and geoid should be the same size'); end md = checkfield(md,'field',self.modelid,'NaN',1,'Inf',1,'>=',1,'<=',length(self.displacementeast)); - for i=1:seast, + for i=1:seast md = checkfield(md,'field',self.displacementeast{i},'NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'field',self.displacementup{i},'NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'field',self.displacementnorth{i},'NaN',1,'Inf',1,'timeseries',1); @@ -67,7 +67,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'name','md.solidearth.external.nummodels','data',nummodels,'format','Integer'); %transform our cell array of time series into cell array of time series of rates - for i=1:nummodels, + for i=1:nummodels displacementeast=self.displacementeast{i}; displacementnorth=self.displacementnorth{i}; displacementup=self.displacementup{i}; diff --git a/src/m/classes/model.m b/src/m/classes/model.m index 432cf3c3a..b8329b015 100644 --- a/src/m/classes/model.m +++ b/src/m/classes/model.m @@ -67,7 +67,7 @@ % old fields must be recovered (make sure they are in the deprecated % model properties) - if verLessThan('matlab','7.9'), + if verLessThan('matlab','7.9') disp('Warning: your matlab version is old and there is a risk that load does not work correctly'); disp(' if the model is not loaded correctly, rename temporarily loadobj so that matlab does not use it'); @@ -85,9 +85,9 @@ end %2012 August 4th - if isa(md.materials,'materials'), + if isa(md.materials,'materials') disp('Recovering old materials'); - if numel(md.materials.rheology_Z)==1 & isnan(md.materials.rheology_Z), + if numel(md.materials.rheology_Z)==1 & isnan(md.materials.rheology_Z) md.materials=matice(md.materials); else md.materials=matdamageice(md.materials); @@ -98,25 +98,25 @@ md.stressbalance.loadingforce=0*ones(md.mesh.numberofvertices,3); end %2013 April 17 - if isa(md.hydrology,'hydrology'), + if isa(md.hydrology,'hydrology') disp('Recovering old hydrology class'); md.hydrology=hydrologyshreve(md.materials); end %2013 October 9 - if ~isa(md.damage,'damage'), + if ~isa(md.damage,'damage') md.damage=damage(); md.damage.D=zeros(md.mesh.numberofvertices,1); md.damage.spcdamage=NaN*ones(md.mesh.numberofvertices,1); end %2013 November 18 - if ~isa(md.outputdefinition,'outputdefinition'), + if ~isa(md.outputdefinition,'outputdefinition') md.outputdefinition=outputdefinition(); end %2014 March 26th - if isa(md.mesh,'mesh'), + if isa(md.mesh,'mesh') disp('Recovering old mesh class'); - if isprop(md.mesh,'dimension'), - if md.mesh.dimension==2, + if isprop(md.mesh,'dimension') + if md.mesh.dimension==2 md.mesh=mesh2d(md.mesh); else md.mesh=mesh3dprisms(md.mesh); @@ -131,7 +131,7 @@ if isa(md.esa,'double'); md.esa=esa(); end %2017 February 10th if isa(md.settings,'settings'), %this 'isa' verification: 2018 October 24th - if md.settings.solver_residue_threshold==0, + if md.settings.solver_residue_threshold==0 md.settings.solver_residue_threshold = 1e-6; end end @@ -337,7 +337,7 @@ function disp(self) % {{{ % See also: EXTRUDE, EXTRACT %Check that the model is really a 3d model - if ~strcmp(md.mesh.elementtype(),'Penta'), + if ~strcmp(md.mesh.elementtype(),'Penta') error('collapse error message: only 3d mesh can be collapsed') end @@ -345,32 +345,32 @@ function disp(self) % {{{ %dealing with the friction law %drag is limited to nodes that are on the bedrock. - if isa(md.friction,'friction'), + if isa(md.friction,'friction') md.friction.coefficient=project2d(md,md.friction.coefficient,1); md.friction.p=project2d(md,md.friction.p,1); md.friction.q=project2d(md,md.friction.q,1); - elseif isa(md.friction,'frictioncoulomb'), + elseif isa(md.friction,'frictioncoulomb') md.friction.coefficient=project2d(md,md.friction.coefficient,1); md.friction.coefficientcoulomb=project2d(md,md.friction.coefficientcoulomb,1); md.friction.p=project2d(md,md.friction.p,1); md.friction.q=project2d(md,md.friction.q,1); - elseif isa(md.friction,'frictionhydro'), + elseif isa(md.friction,'frictionhydro') md.friction.q=project2d(md,md.friction.q,1); md.friction.C=project2d(md,md.friction.C,1); md.friction.As=project2d(md,md.friction.As,1); md.friction.effective_pressure=project2d(md,md.friction.effective_pressure,1); - elseif isa(md.friction,'frictionwaterlayer'), + elseif isa(md.friction,'frictionwaterlayer') md.friction.coefficient=project2d(md,md.friction.coefficient,1); md.friction.p=project2d(md,md.friction.p,1); md.friction.q=project2d(md,md.friction.q,1); md.friction.water_layer=project2d(md,md.friction.water_layer,1); - elseif isa(md.friction,'frictionweertman'), + elseif isa(md.friction,'frictionweertman') md.friction.C=project2d(md,md.friction.C,1); md.friction.m=project2d(md,md.friction.m,1); - elseif isa(md.friction,'frictionweertmantemp'), + elseif isa(md.friction,'frictionweertmantemp') md.friction.C=project2d(md,md.friction.C,1); md.friction.m=project2d(md,md.friction.m,1); - elseif isa(md.friction,'frictionjosh'), + elseif isa(md.friction,'frictionjosh') md.friction.coefficient=project2d(md,md.friction.coefficient,1); md.friction.pressure_adjusted_temperature=project2d(md,md.friction.pressure_adjusted_temperature,1); else @@ -378,30 +378,30 @@ function disp(self) % {{{ end %observations - if ~isnan(md.inversion.vx_obs), + if ~isnan(md.inversion.vx_obs) md.inversion.vx_obs=project2d(md,md.inversion.vx_obs,md.mesh.numberoflayers); end - if ~isnan(md.inversion.vy_obs), + if ~isnan(md.inversion.vy_obs) md.inversion.vy_obs=project2d(md,md.inversion.vy_obs,md.mesh.numberoflayers); end - if ~isnan(md.inversion.vel_obs), + if ~isnan(md.inversion.vel_obs) md.inversion.vel_obs=project2d(md,md.inversion.vel_obs,md.mesh.numberoflayers); end - if ~isnan(md.inversion.thickness_obs), + if ~isnan(md.inversion.thickness_obs) md.inversion.thickness_obs=project2d(md,md.inversion.thickness_obs,md.mesh.numberoflayers); end - if ~isnan(md.inversion.cost_functions_coefficients), + if ~isnan(md.inversion.cost_functions_coefficients) md.inversion.cost_functions_coefficients=project2d(md,md.inversion.cost_functions_coefficients,md.mesh.numberoflayers); end - if numel(md.inversion.min_parameters)>1, + if numel(md.inversion.min_parameters)>1 md.inversion.min_parameters=project2d(md,md.inversion.min_parameters,md.mesh.numberoflayers); end - if numel(md.inversion.max_parameters)>1, + if numel(md.inversion.max_parameters)>1 md.inversion.max_parameters=project2d(md,md.inversion.max_parameters,md.mesh.numberoflayers); end - if isa(md.smb,'SMBforcing') & ~isnan(md.smb.mass_balance), + if isa(md.smb,'SMBforcing') & ~isnan(md.smb.mass_balance) md.smb.mass_balance=project2d(md,md.smb.mass_balance,md.mesh.numberoflayers); - elseif isa(md.smb,'SMBhenning') & ~isnan(md.smb.smbref), + elseif isa(md.smb,'SMBhenning') & ~isnan(md.smb.smbref) md.smb.smbref=project2d(md,md.smb.smbref,md.mesh.numberoflayers); elseif isa(md.smb, 'SMBpddSicopolis') || isa(md.smb, 'SMBpddFast'); md.smb.s0p = project2d(md, md.smb.s0p, md.mesh.numberoflayers); @@ -414,40 +414,40 @@ function disp(self) % {{{ end %results - if ~isnan(md.initialization.vx), + if ~isnan(md.initialization.vx) md.initialization.vx=DepthAverage(md,md.initialization.vx); end - if ~isnan(md.initialization.vy), + if ~isnan(md.initialization.vy) md.initialization.vy=DepthAverage(md,md.initialization.vy); end - if ~isnan(md.initialization.vz), + if ~isnan(md.initialization.vz) md.initialization.vz=DepthAverage(md,md.initialization.vz); end - if ~isnan(md.initialization.vel), + if ~isnan(md.initialization.vel) md.initialization.vel=DepthAverage(md,md.initialization.vel); end - if ~isnan(md.initialization.temperature), + if ~isnan(md.initialization.temperature) md.initialization.temperature=DepthAverage(md,md.initialization.temperature); end - if ~isnan(md.initialization.pressure), + if ~isnan(md.initialization.pressure) md.initialization.pressure=project2d(md,md.initialization.pressure,1); end - if ~isnan(md.initialization.sediment_head), + if ~isnan(md.initialization.sediment_head) md.initialization.sediment_head=project2d(md,md.initialization.sediment_head,1); end - if ~isnan(md.initialization.epl_head), + if ~isnan(md.initialization.epl_head) md.initialization.epl_head=project2d(md,md.initialization.epl_head,1); end - if ~isnan(md.initialization.epl_thickness), + if ~isnan(md.initialization.epl_thickness) md.initialization.epl_thickness=project2d(md,md.initialization.epl_thickness,1); end - if ~isnan(md.initialization.waterfraction), + if ~isnan(md.initialization.waterfraction) md.initialization.waterfraction=project2d(md,md.initialization.waterfraction,1); end - if ~isnan(md.initialization.watercolumn), + if ~isnan(md.initialization.watercolumn) md.initialization.watercolumn=project2d(md,md.initialization.watercolumn,1); end - if ~isnan(md.initialization.debris), + if ~isnan(md.initialization.debris) md.initialization.debris=project2d(md,md.initialization.debris,1); end @@ -466,13 +466,13 @@ function disp(self) % {{{ md.stressbalance.spcvz=project2d(md,md.stressbalance.spcvz,md.mesh.numberoflayers); md.stressbalance.referential=project2d(md,md.stressbalance.referential,md.mesh.numberoflayers); md.stressbalance.loadingforce=project2d(md,md.stressbalance.loadingforce,md.mesh.numberoflayers); - if numel(md.masstransport.spcthickness)>1, + if numel(md.masstransport.spcthickness)>1 md.masstransport.spcthickness=project2d(md,md.masstransport.spcthickness,md.mesh.numberoflayers); end - if numel(md.damage.spcdamage)>1, + if numel(md.damage.spcdamage)>1 md.damage.spcdamage=project2d(md,md.damage.spcdamage,md.mesh.numberoflayers); end - if numel(md.levelset.spclevelset)>1, + if numel(md.levelset.spclevelset)>1 md.levelset.spclevelset=project2d(md,md.levelset.spclevelset,md.mesh.numberoflayers); end md.thermal.spctemperature=project2d(md,md.thermal.spctemperature,md.mesh.numberoflayers); @@ -496,15 +496,15 @@ function disp(self) % {{{ end %damage: - if md.damage.isdamage, + if md.damage.isdamage md.damage.D=DepthAverage(md,md.damage.D); end %special for thermal modeling: - if ~isnan(md.basalforcings.groundedice_melting_rate), + if ~isnan(md.basalforcings.groundedice_melting_rate) md.basalforcings.groundedice_melting_rate=project2d(md,md.basalforcings.groundedice_melting_rate,1); end - if isprop(md.basalforcings,'floatingice_melting_rate') & ~isnan(md.basalforcings.floatingice_melting_rate), + if isprop(md.basalforcings,'floatingice_melting_rate') & ~isnan(md.basalforcings.floatingice_melting_rate) md.basalforcings.floatingice_melting_rate=project2d(md,md.basalforcings.floatingice_melting_rate,1); end if isprop(md.basalforcings,'deepwater_melting_rate') @@ -515,10 +515,10 @@ function disp(self) % {{{ end md.basalforcings.geothermalflux=project2d(md,md.basalforcings.geothermalflux,1); %bedrock only gets geothermal flux - if isprop(md.calving,'coeff') & ~isnan(md.calving.coeff), + if isprop(md.calving,'coeff') & ~isnan(md.calving.coeff) md.calving.coeff=project2d(md,md.calving.coeff,1); end - if isprop(md.frontalforcings,'meltingrate') & ~isnan(md.frontalforcings.meltingrate), + if isprop(md.frontalforcings,'meltingrate') & ~isnan(md.frontalforcings.meltingrate) md.frontalforcings.meltingrate=project2d(md,md.frontalforcings.meltingrate,1); end @@ -533,21 +533,21 @@ function disp(self) % {{{ md.geometry.surface=project2d(md,md.geometry.surface,1); md.geometry.thickness=project2d(md,md.geometry.thickness,1); md.geometry.base=project2d(md,md.geometry.base,1); - if ~isnan(md.geometry.bed), + if ~isnan(md.geometry.bed) md.geometry.bed=project2d(md,md.geometry.bed,1); end - if ~isnan(md.mask.ocean_levelset), + if ~isnan(md.mask.ocean_levelset) md.mask.ocean_levelset=project2d(md,md.mask.ocean_levelset,1); end - if ~isnan(md.mask.ice_levelset), + if ~isnan(md.mask.ice_levelset) md.mask.ice_levelset=project2d(md,md.mask.ice_levelset,1); end %lat long - if numel(md.mesh.lat)==md.mesh.numberofvertices, + if numel(md.mesh.lat)==md.mesh.numberofvertices md.mesh.lat=project2d(md,md.mesh.lat,1); end - if numel(md.mesh.long)==md.mesh.numberofvertices, + if numel(md.mesh.long)==md.mesh.numberofvertices md.mesh.long=project2d(md,md.mesh.long,1); end @@ -556,9 +556,9 @@ function disp(self) % {{{ if isobject(md.outputdefinition.definitions{i}) %get subfields solutionsubfields=fields(md.outputdefinition.definitions{i}); - for j=1:length(solutionsubfields), + for j=1:length(solutionsubfields) field=md.outputdefinition.definitions{i}.(solutionsubfields{j}); - if length(field)==md.mesh.numberofvertices | length(field)==md.mesh.numberofelements, + if length(field)==md.mesh.numberofvertices | length(field)==md.mesh.numberofelements md.outputdefinition.definitions{i}.(solutionsubfields{j})=project2d(md,md.outputdefinition.definitions{i}.(solutionsubfields{j}),1); end end @@ -572,20 +572,20 @@ function disp(self) % {{{ mesh.numberofvertices=md.mesh.numberofvertices2d; mesh.numberofelements=md.mesh.numberofelements2d; mesh.elements=md.mesh.elements2d; - if numel(md.mesh.lat)==md.mesh.numberofvertices, + if numel(md.mesh.lat)==md.mesh.numberofvertices mesh.lat=project2d(md,md.mesh.lat,1); end - if numel(md.mesh.long)==md.mesh.numberofvertices, + if numel(md.mesh.long)==md.mesh.numberofvertices mesh.long=project2d(md,md.mesh.long,1); end mesh.epsg=md.mesh.epsg; - if numel(md.mesh.scale_factor)==md.mesh.numberofvertices, + if numel(md.mesh.scale_factor)==md.mesh.numberofvertices mesh.scale_factor=project2d(md,md.mesh.scale_factor,1); end - if ~isnan(md.mesh.vertexonboundary), + if ~isnan(md.mesh.vertexonboundary) mesh.vertexonboundary=project2d(md,md.mesh.vertexonboundary,1); end - if ~isnan(md.mesh.elementconnectivity), + if ~isnan(md.mesh.elementconnectivity) mesh.elementconnectivity=project2d(md,md.mesh.elementconnectivity,1); end md.mesh=mesh; @@ -620,14 +620,14 @@ function disp(self) % {{{ options=pairoptions(varargin{:}); %some checks - if ((nargin<2) | (nargout~=1)), + if ((nargin<2) | (nargout~=1)) help extract error('extract error message: bad usage'); end %get elements that are inside area flag_elem=FlagElements(md1,area); - if ~any(flag_elem), + if ~any(flag_elem) error('extracted model is empty'); end @@ -665,7 +665,7 @@ function disp(self) % {{{ elements_2(:,1)=Pnode(elements_2(:,1)); elements_2(:,2)=Pnode(elements_2(:,2)); elements_2(:,3)=Pnode(elements_2(:,3)); - if isa(md1.mesh,'mesh3dprisms'), + if isa(md1.mesh,'mesh3dprisms') elements_2(:,4)=Pnode(elements_2(:,4)); elements_2(:,5)=Pnode(elements_2(:,5)); elements_2(:,6)=Pnode(elements_2(:,6)); @@ -680,13 +680,13 @@ function disp(self) % {{{ %loop over model fields model_fields=fields(md1); - for i=1:length(model_fields), + for i=1:length(model_fields) %get field field=md1.(model_fields{i}); fieldsize=size(field); if isobject(field), %recursive call object_fields=fields(md1.(model_fields{i})); - for j=1:length(object_fields), + for j=1:length(object_fields) %get field field=md1.(model_fields{i}).(object_fields{j}); fieldsize=size(field); @@ -725,7 +725,7 @@ function disp(self) % {{{ md2.mesh.elements=elements_2; %mesh.uppervertex mesh.lowervertex - if isa(md1.mesh,'mesh3dprisms'), + if isa(md1.mesh,'mesh3dprisms') md2.mesh.uppervertex=md1.mesh.uppervertex(pos_node); pos=find(~isnan(md2.mesh.uppervertex)); md2.mesh.uppervertex(pos)=Pnode(md2.mesh.uppervertex(pos)); @@ -744,7 +744,7 @@ function disp(self) % {{{ end %Initial 2d mesh - if isa(md1.mesh,'mesh3dprisms'), + if isa(md1.mesh,'mesh3dprisms') flag_elem_2d=flag_elem(1:md1.mesh.numberofelements2d); pos_elem_2d=find(flag_elem_2d); flag_node_2d=flag_node(1:md1.mesh.numberofvertices2d); @@ -791,13 +791,13 @@ function disp(self) % {{{ end %Penalties - if ~isnan(md2.stressbalance.vertex_pairing), + if ~isnan(md2.stressbalance.vertex_pairing) for i=1:size(md1.stressbalance.vertex_pairing,1); md2.stressbalance.vertex_pairing(i,:)=Pnode(md1.stressbalance.vertex_pairing(i,:)); end md2.stressbalance.vertex_pairing=md2.stressbalance.vertex_pairing(find(md2.stressbalance.vertex_pairing(:,1)),:); end - if ~isnan(md2.masstransport.vertex_pairing), + if ~isnan(md2.masstransport.vertex_pairing) for i=1:size(md1.masstransport.vertex_pairing,1); md2.masstransport.vertex_pairing(i,:)=Pnode(md1.masstransport.vertex_pairing(i,:)); end @@ -805,7 +805,7 @@ function disp(self) % {{{ end %recreate segments - if isa(md1.mesh,'mesh2d') | isa(md1.mesh','mesh3dsurface'), + if isa(md1.mesh,'mesh2d') | isa(md1.mesh','mesh3dsurface') md2.mesh.vertexconnectivity=NodeConnectivity(md2.mesh.elements,md2.mesh.numberofvertices); md2.mesh.elementconnectivity=ElementConnectivity(md2.mesh.elements,md2.mesh.vertexconnectivity); md2.mesh.segments=contourenvelope(md2.mesh); @@ -831,7 +831,7 @@ function disp(self) % {{{ %Figure out which node are on the boundary between md2 and md1 nodestoflag1=intersect(orphans_node,pos_node); nodestoflag2=Pnode(nodestoflag1); - if numel(md1.stressbalance.spcvx)>1 & numel(md1.stressbalance.spcvy)>1 & numel(md1.stressbalance.spcvz)>1, + if numel(md1.stressbalance.spcvx)>1 & numel(md1.stressbalance.spcvy)>1 & numel(md1.stressbalance.spcvz)>1 if isprop(md1.inversion,'vx_obs') & numel(md1.inversion.vx_obs)>1 & numel(md1.inversion.vy_obs)>1 disp('NOTE: using observed velocities to create constraints along new boundary'); md2.stressbalance.spcvx(nodestoflag2)=md2.inversion.vx_obs(nodestoflag2); @@ -858,26 +858,26 @@ function disp(self) % {{{ %put 0 for vz md2.stressbalance.spcvz(nodestoflag2)=0; end - if ~isnan(md1.thermal.spctemperature), + if ~isnan(md1.thermal.spctemperature) md2.thermal.spctemperature(nodestoflag2,1)=1; end %Results fields - if isstruct(md1.results), + if isstruct(md1.results) md2.results=struct(); solutionfields=fields(md1.results); - for i=1:length(solutionfields), + for i=1:length(solutionfields) if isstruct(md1.results.(solutionfields{i})) %get subfields % loop over time steps for p=1:length(md1.results.(solutionfields{i})) current = md1.results.(solutionfields{i})(p); solutionsubfields=fields(current); - for j=1:length(solutionsubfields), + for j=1:length(solutionsubfields) field=md1.results.(solutionfields{i})(p).(solutionsubfields{j}); - if length(field)==numberofvertices1, + if length(field)==numberofvertices1 md2.results.(solutionfields{i})(p).(solutionsubfields{j})=field(pos_node); - elseif length(field)==numberofelements1, + elseif length(field)==numberofelements1 md2.results.(solutionfields{i})(p).(solutionsubfields{j})=field(pos_elem); else md2.results.(solutionfields{i})(p).(solutionsubfields{j})=field; @@ -886,9 +886,9 @@ function disp(self) % {{{ end else field=md1.results.(solutionfields{i}); - if length(field)==numberofvertices1, + if length(field)==numberofvertices1 md2.results.(solutionfields{i})=field(pos_node); - elseif length(field)==numberofelements1, + elseif length(field)==numberofelements1 md2.results.(solutionfields{i})=field(pos_elem); else md2.results.(solutionfields{i})=field; @@ -898,15 +898,15 @@ function disp(self) % {{{ end %OutputDefinitions fields - for i=1:length(md1.outputdefinition.definitions), + for i=1:length(md1.outputdefinition.definitions) if isobject(md1.outputdefinition.definitions{i}) %get subfields solutionsubfields=fields(md1.outputdefinition.definitions{i}); - for j=1:length(solutionsubfields), + for j=1:length(solutionsubfields) field=md1.outputdefinition.definitions{i}.(solutionsubfields{j}); - if length(field)==numberofvertices1, + if length(field)==numberofvertices1 md2.outputdefinition.definitions{i}.(solutionsubfields{j})=field(pos_node); - elseif length(field)==numberofelements1, + elseif length(field)==numberofelements1 md2.outputdefinition.definitions{i}.(solutionsubfields{j})=field(pos_elem); elseif size(field,1)==numberofvertices1+1 md2.outputdefinition.definitions{i}.(solutionsubfields{j})=[field(pos_node,:); field(end,:)]; @@ -1048,13 +1048,13 @@ function disp(self) % {{{ %loop over model fields (except mesh) model_fields=setxor(fields(md),{'mesh'}); - for i=1:length(model_fields), + for i=1:length(model_fields) %get field field=md.(model_fields{i}); fieldsize=size(field); if isobject(field), %recursive call object_fields=fields(md.(model_fields{i})); - for j=1:length(object_fields), + for j=1:length(object_fields) %get field field=md.(model_fields{i}).(object_fields{j}); fieldsize=size(field); @@ -1142,7 +1142,7 @@ function disp(self) % {{{ % See also: EXTRACT, COLLAPSE %some checks on list of arguments - if ((nargin>4) | (nargin<2) | (nargout~=1)), + if ((nargin>4) | (nargin<2) | (nargout~=1)) help extrude; error('extrude error message'); end @@ -1153,13 +1153,13 @@ function disp(self) % {{{ %Extrude the mesh if nargin==2, %list of coefficients clist=varargin{1}; - if any(clist<0) | any(clist>1), + if any(clist<0) | any(clist>1) error('extrusioncoefficients must be between 0 and 1'); end extrusionlist=sort(unique([clist(:);0;1])); numlayers=length(extrusionlist); elseif nargin==3, %one polynomial law - if varargin{2}<=0, + if varargin{2}<=0 help extrude; error('extrusionexponent must be >=0'); end @@ -1170,7 +1170,7 @@ function disp(self) % {{{ lowerexp=varargin{2}; upperexp=varargin{3}; - if varargin{2}<=0 | varargin{3}<=0, + if varargin{2}<=0 | varargin{3}<=0 help extrude; error('lower and upper extrusionexponents must be >=0'); end @@ -1181,7 +1181,7 @@ function disp(self) % {{{ end - if numlayers<2, + if numlayers<2 error('number of layers should be at least 2'); end if strcmp(md.mesh.domaintype(),'3D') @@ -1219,7 +1219,7 @@ function disp(self) % {{{ bed3d=md.geometry.base; %Create the new layers - for i=1:numlayers, + for i=1:numlayers x3d=[x3d; md.mesh.x]; y3d=[y3d; md.mesh.y]; %nodes are distributed between bed and surface accordingly to the given exponent @@ -1229,7 +1229,7 @@ function disp(self) % {{{ %Extrude elements elements3d=[]; - for i=1:numlayers-1, + for i=1:numlayers-1 elements3d=[elements3d;[md.mesh.elements+(i-1)*md.mesh.numberofvertices md.mesh.elements+i*md.mesh.numberofvertices]]; %Create the elements of the 3d mesh for the non extruded part end number_el3d=size(elements3d,1); %number of 3d nodes for the non extruded part of the mesh @@ -1302,7 +1302,7 @@ function disp(self) % {{{ if ~isnan(md.mesh.elementconnectivity) md.mesh.elementconnectivity=repmat(md.mesh.elementconnectivity,numlayers-1,1); md.mesh.elementconnectivity(find(md.mesh.elementconnectivity==0))=NaN; - for i=2:numlayers-1, + for i=2:numlayers-1 md.mesh.elementconnectivity((i-1)*md.mesh.numberofelements2d+1:(i)*md.mesh.numberofelements2d,:)... =md.mesh.elementconnectivity((i-1)*md.mesh.numberofelements2d+1:(i)*md.mesh.numberofelements2d,:)+md.mesh.numberofelements2d; end @@ -1317,7 +1317,7 @@ function disp(self) % {{{ md.outputdefinition=extrude(md.outputdefinition,md); %increase connectivity if less than 25: - if md.mesh.average_vertex_connectivity<=25, + if md.mesh.average_vertex_connectivity<=25 md.mesh.average_vertex_connectivity=100; end end % }}} @@ -1463,7 +1463,7 @@ function disp(self) % {{{ if isfield(structmd,'y2d'), md.mesh.y2d=structmd.y2d; end if isfield(structmd,'x2d'), md.mesh.x2d=structmd.x2d; end if isfield(structmd,'elements'), md.mesh.elements=structmd.elements; end - if isfield(structmd,'edges'), + if isfield(structmd,'edges') md.mesh.edges=structmd.edges; md.mesh.edges(isnan(md.mesh.edges))=-1; end @@ -1474,11 +1474,11 @@ function disp(self) % {{{ if isfield(structmd,'npart'); md.qmu.numberofpartitions=structmd.npart; end if isfield(structmd,'part'); md.qmu.partition=structmd.part; end - if isnumeric(md.verbose), + if isnumeric(md.verbose) md.verbose=verbose; end - if isfield(structmd,'spcvelocity'), + if isfield(structmd,'spcvelocity') md.stressbalance.spcvx=NaN*ones(md.mesh.numberofvertices,1); md.stressbalance.spcvy=NaN*ones(md.mesh.numberofvertices,1); md.stressbalance.spcvz=NaN*ones(md.mesh.numberofvertices,1); @@ -1486,26 +1486,26 @@ function disp(self) % {{{ pos=find(structmd.spcvelocity(:,2)); md.stressbalance.spcvy(pos)=structmd.spcvelocity(pos,5); pos=find(structmd.spcvelocity(:,3)); md.stressbalance.spcvz(pos)=structmd.spcvelocity(pos,6); end - if isfield(structmd,'spcvx'), + if isfield(structmd,'spcvx') md.stressbalance.spcvx=NaN*ones(md.mesh.numberofvertices,1); pos=find(~isnan(structmd.spcvx)); md.stressbalance.spcvx(pos)=structmd.spcvx(pos); end - if isfield(structmd,'spcvy'), + if isfield(structmd,'spcvy') md.stressbalance.spcvy=NaN*ones(md.mesh.numberofvertices,1); pos=find(~isnan(structmd.spcvy)); md.stressbalance.spcvy(pos)=structmd.spcvy(pos); end - if isfield(structmd,'spcvz'), + if isfield(structmd,'spcvz') md.stressbalance.spcvz=NaN*ones(md.mesh.numberofvertices,1); pos=find(~isnan(structmd.spcvz)); md.stressbalance.spcvz(pos)=structmd.spcvz(pos); end - if isfield(structmd,'pressureload'), - if ~isempty(structmd.pressureload) & ismember(structmd.pressureload(end,end),[118 119 120]), + if isfield(structmd,'pressureload') + if ~isempty(structmd.pressureload) & ismember(structmd.pressureload(end,end),[118 119 120]) pos=find(structmd.pressureload(:,end)==120); md.stressbalance.icefront(pos,end)=0; pos=find(structmd.pressureload(:,end)==118); md.stressbalance.icefront(pos,end)=1; pos=find(structmd.pressureload(:,end)==119); md.stressbalance.icefront(pos,end)=2; end end - if isfield(structmd,'elements_type') & structmd.elements_type(end,end)>50, + if isfield(structmd,'elements_type') & structmd.elements_type(end,end)>50 pos=find(structmd.elements_type==59); md.flowequation.element_equation(pos,end)=0; pos=find(structmd.elements_type==55); md.flowequation.element_equation(pos,end)=1; pos=find(structmd.elements_type==56); md.flowequation.element_equation(pos,end)=2; @@ -1515,7 +1515,7 @@ function disp(self) % {{{ pos=find(structmd.elements_type==58); md.flowequation.element_equation(pos,end)=6; pos=find(structmd.elements_type==61); md.flowequation.element_equation(pos,end)=7; end - if isfield(structmd,'vertices_type') & structmd.vertices_type(end,end)>50, + if isfield(structmd,'vertices_type') & structmd.vertices_type(end,end)>50 pos=find(structmd.vertices_type==59); md.flowequation.vertex_equation(pos,end)=0; pos=find(structmd.vertices_type==55); md.flowequation.vertex_equation(pos,end)=1; pos=find(structmd.vertices_type==56); md.flowequation.vertex_equation(pos,end)=2; @@ -1525,22 +1525,22 @@ function disp(self) % {{{ pos=find(structmd.vertices_type==58); md.flowequation.vertex_equation(pos,end)=6; pos=find(structmd.vertices_type==61); md.flowequation.vertex_equation(pos,end)=7; end - if isfield(structmd,'rheology_law') & isnumeric(structmd.rheology_law), + if isfield(structmd,'rheology_law') & isnumeric(structmd.rheology_law) if (structmd.rheology_law==272), md.materials.rheology_law='None'; end if (structmd.rheology_law==368), md.materials.rheology_law='Paterson'; end if (structmd.rheology_law==369), md.materials.rheology_law='Arrhenius'; end end - if isfield(structmd,'groundingline_migration') & isnumeric(structmd.groundingline_migration), + if isfield(structmd,'groundingline_migration') & isnumeric(structmd.groundingline_migration) if (structmd.groundingline_migration==272), md.groundingline.migration='None'; end if (structmd.groundingline_migration==273), md.groundingline.migration='AggressiveMigration'; end if (structmd.groundingline_migration==274), md.groundingline.migration='SoftMigration'; end end - if isfield(structmd,'control_type') & isnumeric(structmd.control_type), + if isfield(structmd,'control_type') & isnumeric(structmd.control_type) if (structmd.control_type==143), md.inversion.control_parameters={'FrictionCoefficient'}; end if (structmd.control_type==190), md.inversion.control_parameters={'RheologyBbar'}; end if (structmd.control_type==147), md.inversion.control_parameters={'Thickeningrate'}; end end - if isfield(structmd,'cm_responses') & ismember(structmd.cm_responses(end,end),[165:170 383 388 389]), + if isfield(structmd,'cm_responses') & ismember(structmd.cm_responses(end,end),[165:170 383 388 389]) pos=find(structmd.cm_responses==166); md.inversion.cost_functions(pos)=101; pos=find(structmd.cm_responses==167); md.inversion.cost_functions(pos)=102; pos=find(structmd.cm_responses==168); md.inversion.cost_functions(pos)=103; @@ -1552,13 +1552,13 @@ function disp(self) % {{{ pos=find(structmd.cm_responses==382); md.inversion.cost_functions(pos)=503; end - if isfield(structmd,'artificial_diffusivity') & structmd.artificial_diffusivity==2, + if isfield(structmd,'artificial_diffusivity') & structmd.artificial_diffusivity==2 md.thermal.stabilization=2; md.masstransport.stabilization=1; md.balancethickness.stabilization=1; end if isnumeric(md.masstransport.hydrostatic_adjustment) - if md.masstransport.hydrostatic_adjustment==269, + if md.masstransport.hydrostatic_adjustment==269 md.masstransport.hydrostatic_adjustment='Incremental'; else md.masstransport.hydrostatic_adjustment='Absolute'; @@ -1582,35 +1582,35 @@ function disp(self) % {{{ end %2013 August 9 - if isfield(structmd,'prognostic') & isa(structmd.prognostic,'prognostic'), + if isfield(structmd,'prognostic') & isa(structmd.prognostic,'prognostic') disp('Recovering old prognostic class'); md.masstransport=masstransport(structmd.prognostic); end %2013 August 9 - if isfield(structmd,'diagnostic') & (isa(structmd.diagnostic,'diagnostic') || isa(structmd.diagnostic,'stressbalance')), + if isfield(structmd,'diagnostic') & (isa(structmd.diagnostic,'diagnostic') || isa(structmd.diagnostic,'stressbalance')) disp('Recovering old diagnostic class'); md.stressbalance=stressbalance(structmd.diagnostic); end %2014 January 9th - if isfield(structmd,'surfaceforcings') & isa(md.smb,'surfaceforcings'), + if isfield(structmd,'surfaceforcings') & isa(md.smb,'surfaceforcings') disp('Recovering old surfaceforcings class'); mass_balance=structmd.surfaceforcings.mass_balance; md.smb=SMB(); md.smb.mass_balance=mass_balance; end %2015 September 10 - if isfield(structmd,'surfaceforcings') & isa(structmd.surfaceforcings,'SMB'), + if isfield(structmd,'surfaceforcings') & isa(structmd.surfaceforcings,'SMB') disp('Recovering old SMB class'); md.smb=SMBforcing(structmd.surfaceforcings); end - if isfield(structmd,'surfaceforcings') & isa(structmd.surfaceforcings,'SMBhenning'), + if isfield(structmd,'surfaceforcings') & isa(structmd.surfaceforcings,'SMBhenning') disp('Recovering old SMBhenning class'); md.smb=SMBhenning(structmd.surfaceforcings); end if isfield(structmd,'slr') && ~isempty(structmd.slr) md.solidearth = solidearth('Earth'); disp('Recovering old slr class'); - if isfield(structmd.slr,'sealevel'), + if isfield(structmd.slr,'sealevel') md.solidearth.sealevel=structmd.slr.sealevel; end md.solidearth.planetradius=structmd.slr.planetradius; @@ -1727,7 +1727,7 @@ function disp(self) % {{{ for j=1:3 element = elements(3*(i-1)+j,:); matrix = [md.mesh.x(element), md.mesh.y(element), md.mesh.z(element), ones(4,1)]; - if det(matrix)>0, + if det(matrix)>0 elements(3*(i-1)+j,1)=element(2); elements(3*(i-1)+j,2)=element(1); end @@ -1738,7 +1738,7 @@ function disp(self) % {{{ %subelement2 = [4 6 5 1]; %subelement3 = [5 6 3 1]; %elements=[md.mesh.elements(:,subelement1);md.mesh.elements(:,subelement2);md.mesh.elements(:,subelement3)]; - if steiner==0, + if steiner==0 disp('No Steiner point required to split prismatic mesh into tets'); else disp([num2str(steiner) ' Steiner points had to be included']) @@ -1751,7 +1751,7 @@ function disp(self) % {{{ md.mesh.numberofelements=size(elements,1); %p and q (same deal, except for element that are on the bedrock: ) - if ~isnan(md.friction.p), + if ~isnan(md.friction.p) md.friction.p=md.friction.p(pos_elements); md.friction.q=md.friction.q(pos_elements); end @@ -1766,12 +1766,12 @@ function disp(self) % {{{ md.mesh.elementconnectivity=NaN; %materials - if ~isnan(md.materials.rheology_n), + if ~isnan(md.materials.rheology_n) md.materials.rheology_n=md.materials.rheology_n(pos_elements); end %increase connectivity if less than 25: - if md.mesh.average_vertex_connectivity<=25, + if md.mesh.average_vertex_connectivity<=25 md.mesh.average_vertex_connectivity=100; end end % }}} @@ -1782,7 +1782,7 @@ function memory(self) % {{{ fields=properties('model'); mem=0; - for i=1:length(fields), + for i=1:length(fields) field=self.(fields{i}); s=whos('field'); mem=mem+s.bytes/1e6; @@ -1812,13 +1812,13 @@ function netcdf(self,filename) % {{{ %Preallocate variable id, needed to write variables in netcdf file var_id=zeros(1000,1);%preallocate - for step=1:2, + for step=1:2 counter=0; [var_id,counter]=structtonc(ncid,'md',self,0,var_id,counter,step); if step==1, netcdf.endDef(ncid); end end - if counter>1000, + if counter>1000 warning(['preallocation of var_id need to be updated from ' num2str(1000) ' to ' num2str(counter)]); end @@ -1872,7 +1872,7 @@ function saveasstruct(md,filename) % {{{ disp('Converting all model fields to struct...'); warning off MATLAB:structOnObject - for i=1:length(mdfields), + for i=1:length(mdfields) %convert md field to struct field=mdfields{i}; @@ -1916,18 +1916,18 @@ function savemodeljs(md,modelname,websiteroot,varargin) % {{{ %now go through all the classes and fwrite all the corresponding fields: fields=properties('model'); - for i=1:length(fields), + for i=1:length(fields) field=fields{i}; %Some properties do not need to be saved - if ismember(field,{'results','cluster'}), + if ismember(field,{'results','cluster'}) continue; end %some optimization: - if optimization==1, + if optimization==1 %optimize for plotting only: - if ~ismember(field,{'geometry','mesh','mask'}), + if ~ismember(field,{'geometry','mesh','mask'}) continue; end end diff --git a/src/m/classes/modellist.m b/src/m/classes/modellist.m index 78ec9cb41..bdcab5c64 100644 --- a/src/m/classes/modellist.m +++ b/src/m/classes/modellist.m @@ -31,7 +31,7 @@ %in flags. %2D or 3D? - if dimension(md.mesh)==3, + if dimension(md.mesh)==3 numberofelements=md.mesh.numberofelements2d; %this will be forgotten when we get out. flags=project2d(md,flags,1); else @@ -40,15 +40,15 @@ %recover extra arguments: distance=0; - if nargin==4, + if nargin==4 distance=varargin{1}; end flag_list=cell(0,1); - for i=1:size(flags,1), + for i=1:size(flags,1) - if (flags(i)), + if (flags(i)) %ok, we are sure element i is part of a new pool. pool=zeros(numberofelements,1); @@ -63,16 +63,16 @@ %go through flag_list and discard any pool of less than minel elements: ex_pos=[]; - for i=1:length(flag_list), - if length(find(flag_list{i}))7, - if strcmpi(string(end-5:end),'Locked'), + if length(string)>7 + if strcmpi(string(end-5:end),'Locked') error('organizer: you are trying to run a locked step! Unlock it first!'); end end @@ -279,7 +279,7 @@ function savedata(org,varargin) % {{{ disp(['saving data in: ' name]); %Skip if requested - if org.skipio, + if org.skipio disp(['WARNING: Skipping saving ' name]); return; end @@ -289,7 +289,7 @@ function savedata(org,varargin) % {{{ %list of variable names: variables=''; - for i=2:nargin, + for i=2:nargin variables=[variables ',' '''' inputname(i) '''']; eval([inputname(i) '= varargin{' num2str(i-1) '};']); end @@ -305,7 +305,7 @@ function savedatanoprefix(org,varargin) % {{{ disp(['saving data in: ' name]); %Skip if requested - if org.skipio, + if org.skipio disp(['WARNING: Skipping saving ' name]); return; end @@ -315,7 +315,7 @@ function savedatanoprefix(org,varargin) % {{{ %list of variable names: variables=''; - for i=2:nargin, + for i=2:nargin variables=[variables ',' '''' inputname(i) '''']; eval([inputname(i) '= varargin{' num2str(i-1) '};']); end diff --git a/src/m/classes/outputdefinition.m b/src/m/classes/outputdefinition.m index 70a07826a..34f4b5f56 100644 --- a/src/m/classes/outputdefinition.m +++ b/src/m/classes/outputdefinition.m @@ -30,7 +30,7 @@ md = checkfield(md,'fieldname','outputdefinition.definitions','cell',1); - for i=1:length(self.definitions), + for i=1:length(self.definitions) md=checkconsistency(self.definitions{i},md,solution,analyses); end @@ -54,7 +54,7 @@ function marshall(self,prefix,md,fid) % {{{ function savemodeljs(self,fid,modelname) % {{{ fprintf(fid,'%s.outputdefinition.definitions=[];\n',modelname); - if ~isempty(self.definitions), + if ~isempty(self.definitions) error('outputdefinition savemodeljs error message: not supported yet!'); end diff --git a/src/m/classes/pairoptions.m b/src/m/classes/pairoptions.m index e91f2b39d..304439949 100644 --- a/src/m/classes/pairoptions.m +++ b/src/m/classes/pairoptions.m @@ -12,7 +12,7 @@ function self = pairoptions(varargin) % {{{ %initialize list - if nargin==0, + if nargin==0 %Do nothing, else self=buildlist(self,varargin{:}); @@ -45,7 +45,7 @@ end end % }}} function self = addfield(self,field,value) % {{{ - if ischar(field), + if ischar(field) self.list{end+1,1} = field; self.list{end,2} = value; self.list{end,3} = false; @@ -53,8 +53,8 @@ end % }}} function self = addfielddefault(self,field,value) % {{{ %ADDFIELDDEFAULT - add a field to an options list if it does not exist - if ischar(field), - if ~exist(self,field), + if ischar(field) + if ~exist(self,field) self.list{end+1,1} = field; self.list{end,2} = value; self.list{end,3} = true; %It is a default so user will not be notified if not used @@ -64,10 +64,10 @@ function obj2 = AssignObjectFields(options,obj2) % {{{ %ASSIGNOBJECTFIELDS - assign object fields from options listproperties=properties(obj2); - for i=1:size(options.list,1), + for i=1:size(options.list,1) fieldname=options.list{i,1}; fieldvalue=options.list{i,2}; - if ismember(fieldname,listproperties), + if ismember(fieldname,listproperties) obj2.(fieldname)=fieldvalue; else disp(['WARNING: ''' fieldname ''' is not a property of ''' class(obj2) '''']); @@ -81,12 +81,12 @@ lines=find(strcmpi(self.list(:,1),field)); %replace value - if isempty(lines), + if isempty(lines) %add new field if not found self=addfield(self,field,newvalue); self.list{end,3}=true; % do not notify user if unused else - for i=1:length(lines), + for i=1:length(lines) self.list{lines(i),2}=newvalue; end end @@ -99,10 +99,10 @@ clear dummy %warn user if requested - if warn, + if warn numoptions=size(self.list,1); - for i=1:numoptions, - if ~ismember(i,lines), + for i=1:numoptions + if ~ismember(i,lines) disp(['WARNING: option ' self.list{i,1} ' appeared more than once. Only its first occurrence will be kept']) end end @@ -115,21 +115,21 @@ function displayunused(self) % {{{ %DISPLAYUNUSED - display unused options numoptions=size(self.list,1); - for i=1:numoptions, - if ~self.list{i,3}, + for i=1:numoptions + if ~self.list{i,3} disp(['WARNING: option ' self.list{i,1} ' was not used']) end end end % }}} function disp(self) % {{{ - if ~isempty(self.list), + if ~isempty(self.list) disp(sprintf(' list: (%ix%i)\n',size(self.list,1),size(self.list,2))); - for i=1:size(self.list,1), - if ischar(self.list{i,2}), + for i=1:size(self.list,1) + if ischar(self.list{i,2}) disp(sprintf(' field: %-10s value: ''%s''',self.list{i,1},self.list{i,2})); - elseif isnumeric(self.list{i,2}) & length(self.list{i,2})==1, + elseif isnumeric(self.list{i,2}) & length(self.list{i,2})==1 disp(sprintf(' field: %-10s value: %g',self.list{i,1},self.list{i,2})); - elseif isnumeric(self.list{i,2}) & length(self.list{i,2})==2, + elseif isnumeric(self.list{i,2}) & length(self.list{i,2})==2 disp(sprintf(' field: %-10s value: [%g %g]',self.list{i,1},self.list{i,2})); else disp(sprintf(' field: %-10s value: (%ix%i)',self.list{i,1},size(self.list{i,2},1),size(self.list{i,2},2))); @@ -143,16 +143,16 @@ function disp(self) % {{{ %EXIST - check if the option exists %some argument checking: - if ((nargin~=2) | (nargout~=1)), + if ((nargin~=2) | (nargout~=1)) error('exist error message: bad usage'); end - if ~ischar(field), + if ~ischar(field) error('exist error message: field should be a string'); end %Recover option pos=find(strcmpi(field,self.list(:,1))); - if ~isempty(pos), + if ~isempty(pos) bool=true; self.list{pos,3} = true; %It is a default so user will not be notified if not used else @@ -163,7 +163,7 @@ function disp(self) % {{{ %FIELDOCCURRENCES - get number of occurrence of a field %check input - if ~ischar(field), + if ~ischar(field) error('fieldoccurrences error message: field should be a string'); end @@ -184,25 +184,25 @@ function disp(self) % {{{ % value=getfieldvalue(options,'caxis',[0 2]); %some argument checking: - if nargin~=2 && nargin~=3, + if nargin~=2 && nargin~=3 help getfieldvalue error('getfieldvalue error message: bad usage'); end - if ~ischar(field), + if ~ischar(field) error('getfieldvalue error message: field should be a string'); end %Recover option pos=find(strcmpi(self.list(:,1),field)); - if ~isempty(pos), + if ~isempty(pos) value=self.list{pos(1),2}; % ignore extra entry self.list{pos(1),3}=true; % option used return; end %The option has not been found, output default if provided - if nargin==3, + if nargin==3 value=varargin{1}; else error(['error message: field ' field ' has not been provided by user (and no default value has been specified)']) @@ -222,20 +222,20 @@ function disp(self) % {{{ % values=getfieldvalues(options,'caxis',{[0 2],[3 4]}); %some argument checking: - if nargin~=2 && nargin~=3, + if nargin~=2 && nargin~=3 help getfieldvalues error('getfieldvalues error message: bad usage'); end - if ~ischar(field), + if ~ischar(field) error('getfieldvalues error message: field should be a string'); end %Recover options pos=find(strcmpi(self.list(:,1),field)); - if ~isempty(pos), + if ~isempty(pos) values={}; - for i=1:length(pos), + for i=1:length(pos) values{i}=self.list{pos(i),2}; self.list{pos(i),3}=true; % option used end @@ -243,7 +243,7 @@ function disp(self) % {{{ end %The option has not been found, output default if provided - if nargin==3, + if nargin==3 values=varargin{1}; else error(['error message: field ' field ' has not been provided by user (and no default value has been specified)']) @@ -259,7 +259,7 @@ function disp(self) % {{{ % some of their options have been removed. %check is field exist - if exist(self,field), + if exist(self,field) %find where the field is located lines=find(~strcmpi(self.list(:,1),field)); @@ -275,14 +275,14 @@ function disp(self) % {{{ end % }}} function marshall(self,fid)% {{{ - for i=1:size(self.list,1), + for i=1:size(self.list,1) name = self.list{i,1}; value = self.list{i,2}; %Write option value - if (isnumeric(value) & numel(value)==1), + if (isnumeric(value) & numel(value)==1) WriteData(fid,'','name',['md.' name],'data',value,'format','Double'); - elseif ischar(value), + elseif ischar(value) WriteData(fid,'','name',['md.' name],'data',value,'format','String'); else error(['Cannot marshall option ' name ': format not supported yet']); diff --git a/src/m/classes/pairoptions.py b/src/m/classes/pairoptions.py index d498ff413..efe6b97da 100644 --- a/src/m/classes/pairoptions.py +++ b/src/m/classes/pairoptions.py @@ -1,5 +1,5 @@ from collections import OrderedDict - +import numpy as np class pairoptions(object): """PAIROPTIONS class definition @@ -12,6 +12,7 @@ class pairoptions(object): def __init__(self, *arg): # {{{ #self.functionname = '' self.list = OrderedDict() + self.used = [] #get calling function name #import inspect @@ -50,11 +51,13 @@ def buildlist(self, *arg): # {{{ if len(arg) % 2: raise TypeError('Invalid parameter/value pair arguments') numoptions = int(len(arg) / 2) + self.used = np.zeros((numoptions,),dtype=bool) # initialize used options #go through arg and build list of objects for i in range(numoptions): if isinstance(arg[2 * i], str): self.list[arg[2 * i]] = arg[2 * i + 1] + self.used[i] = False else: #option is not a string, ignore it print(("WARNING: option number {} is not a string and will be ignored.".format(i + 1))) @@ -67,6 +70,8 @@ def addfield(self, field, value): # {{{ if isinstance(field, str): if field in self.list: print(("WARNING: field '{}' with value={} exists and will be overwritten with value={}.".format(field, str(self.list[field]), str(value)))) + else: + self.used = np.append(self.used,[False]) self.list[field] = value # }}} @@ -77,6 +82,7 @@ def addfielddefault(self, field, value): # {{{ if isinstance(field, str): if field not in self.list: self.list[field] = value + self.used = np.append(self.used,[True]) # It is a default so user will not be notified if not used # }}} def AssignObjectFields(self, obj2): # {{{ @@ -95,14 +101,32 @@ def changefieldvalue(self, field, newvalue): # {{{ """CHANGEOPTIONVALUE - change the value of an option in an option list """ - self.list[field] = newvalue + #track occurrence of field + try: + lines=list(self.list.keys()).index(field) + except: + lines=[] # tricky part: if we cannot find field in list, return empty array. Looks like matlab. + + #replace value + if ~np.any(lines): + #add new field if not found + self.addfield(field,newvalue) + else: + keys = list(self.list.keys()) + self.list[keys[lines]] = newvalue # }}} def displayunused(self): # {{{ """DISPLAYUNUSED - display unused options """ - print('WARNING: pairoptions::displayunused is not yet implemented') + numoptions=len(self.list) + keys = list(self.list.keys()) # get keys in OrderedDict + for i in range(numoptions): + if ~self.used[i]: + print('WARNING: option ' + str(keys[i]) + ' was not used') + + #print('WARNING: pairoptions::displayunused is not yet implemented') # }}} def exist(self, field): # {{{ @@ -143,8 +167,13 @@ def getfieldvalue(self, field, default=None): # {{{ raise TypeError("getfieldvalue error message: field '%s' should be a string." % str(field)) #Recover option + keys=list(self.list.keys()) if field in self.list: value = self.list[field] + + # Find field + pos = keys.index(field) + self.used[pos] = True # option used else: if default is not None: value = default @@ -166,9 +195,12 @@ def removefield(self, field, warn): # {{{ #check if field exist if field in self.list: + pos = np.ones((len(self.list),),dtype=bool) + pos[list(self.list.keys()).index(field)] = False #remove duplicates from the options list del self.list[field] + self.used = self.used[pos] #warn user if requested if warn: diff --git a/src/m/classes/plotoptions.m b/src/m/classes/plotoptions.m index aac6d25a9..f5edacfb6 100644 --- a/src/m/classes/plotoptions.m +++ b/src/m/classes/plotoptions.m @@ -20,15 +20,15 @@ function disp(opt) % {{{ disp(sprintf('\n%s = \n',inputname(1))); disp(sprintf(' numberofplots: %i',opt.numberofplots)); disp(sprintf(' figurenumber: %i',opt.figurenumber)); - if ~isempty(opt.list), + if ~isempty(opt.list) disp(sprintf(' list: (%ix%i)',size(opt.list,1),size(opt.list,2))); - for i=1:size(opt.list,1), + for i=1:size(opt.list,1) unit=opt.list{i}; disp(sprintf('\n options of plot number %i',i)); for j=1:size(unit.list,1) - if ischar(unit.list{j,2}), + if ischar(unit.list{j,2}) disp(sprintf(' field: %-10s value: ''%s''',unit.list{j,1},unit.list{j,2})); - elseif isnumeric(unit.list{j,2}) & length(unit.list{j,2})==1, + elseif isnumeric(unit.list{j,2}) & length(unit.list{j,2})==1 disp(sprintf(' field: %-10s value: %g',unit.list{j,1},unit.list{j,2})); else disp(sprintf(' field: %-10s value: (%ix%i)',unit.list{j,1},size(unit.list{j,2},1),size(unit.list{j,2},2))); @@ -43,9 +43,9 @@ function disp(opt) % {{{ function opt=buildlist(opt,varargin) % {{{ %check length of input - if mod((nargin-1),2), + if mod((nargin-1),2) for i=1:2:(nargin-1) - if ~ischar(varargin{i}), + if ~ischar(varargin{i}) disp(['Last valid option: ' varargin{i-2} ]); break; end @@ -58,10 +58,10 @@ function disp(opt) % {{{ numoptions = (nargin-1)/2; rawlist=cell(numoptions,2); counter=1; - for i=1:numoptions, + for i=1:numoptions optionname = varargin{2*i-1}; optionval = varargin{2*i}; - if ischar(optionname), + if ischar(optionname) rawlist{counter,1}=optionname; rawlist{counter,2}=optionval; counter=counter+1; @@ -77,8 +77,8 @@ function disp(opt) % {{{ numberofplots=fieldoccurrences(rawoptions,'data'); opt.numberofplots=numberofplots; - %figure out wether alloptions flog is on - if strcmpi(getfieldvalue(rawoptions,'alloptions','off'),'on'), + %figure out whether alloptions flag is on + if strcmpi(getfieldvalue(rawoptions,'alloptions','off'),'on') allflag=1; else allflag=0; @@ -86,21 +86,21 @@ function disp(opt) % {{{ %initialize opt.list opt.list=cell(numberofplots,1); - for i=1:numberofplots, + for i=1:numberofplots opt.list{i}=pairoptions; end %process plot options - for i=1:size(rawlist,1), + for i=1:size(rawlist,1) %If alloptions flag has is on, apply to all plots - if (allflag & ~strcmpi(rawlist{i,1},'data') & ~ismember('#',rawlist{i,1})), - for j=1:numberofplots, + if (allflag & ~strcmpi(rawlist{i,1},'data') & ~ismember('#',rawlist{i,1})) + for j=1:numberofplots opt.list{j}=addfield(opt.list{j},rawlist{i,1},rawlist{i,2}); end %option contains '#' - elseif ismember('#',rawlist{i,1}), + elseif ismember('#',rawlist{i,1}) %get suplot(s) associated string=strsplit_strict(rawlist{i,1},'#'); @@ -115,12 +115,12 @@ function disp(opt) % {{{ plotnum=plotnums{k}; %Empty - if isempty(plotnum), + if isempty(plotnum) continue; %pound all elseif strcmpi(plotnum,'all'); - for j=1:numberofplots, + for j=1:numberofplots opt.list{j}=addfield(opt.list{j},field,rawlist{i,2}); end @@ -131,14 +131,14 @@ function disp(opt) % {{{ if isempty(str2num(nums{1}))|isempty(str2num(nums{2})) error(['the option #i-j is not set properly for ' field]); end - for j=str2num(nums{1}):str2num(nums{2}), + for j=str2num(nums{1}):str2num(nums{2}) opt.list{j}=addfield(opt.list{j},field,rawlist{i,2}); end %pound i else %assign to subplot - if str2num(plotnum)>numberofplots, + if str2num(plotnum)>numberofplots error(['opt error message: ' field ' cannot be assigned (' plotnum ' exceed maximum number of plot)']); end opt.list{str2num(plotnum)}=addfield(opt.list{str2num(plotnum)},field,rawlist{i,2}); @@ -150,7 +150,7 @@ function disp(opt) % {{{ %go through all subplot and assign to the first one free j=1; - while (j<=numberofplots), + while (j<=numberofplots) if ~exist(opt.list{j},rawlist{i,1}); opt.list{j}=addfield(opt.list{j},rawlist{i,1},rawlist{i,2}); break @@ -158,14 +158,14 @@ function disp(opt) % {{{ j=j+1; end end - if j>numberofplots, + if j>numberofplots disp(['plot info message: too many ''' rawlist{i,1} ''' options']); end end end %check that there is no duplicates - for i=1:numberofplots, + for i=1:numberofplots opt.list{i}=deleteduplicates(opt.list{i},1); end diff --git a/src/m/classes/plumebasalforcings.m b/src/m/classes/plumebasalforcings.m index 2d46b1af5..5b304edba 100644 --- a/src/m/classes/plumebasalforcings.m +++ b/src/m/classes/plumebasalforcings.m @@ -38,11 +38,11 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end - if isnan(self.floatingice_melting_rate), + if isnan(self.floatingice_melting_rate) self.floatingice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.floatingice_melting_rate specified: values set as zero'); end @@ -65,15 +65,15 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0), + if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'timeseries',1); end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'size',[md.mesh.numberofvertices 1]); end - if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0), + if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.floatingice_melting_rate','NaN',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.mantleconductivity','>=',0,'numel',1); diff --git a/src/m/classes/qmu.m b/src/m/classes/qmu.m index 427f5ecbd..420125afb 100644 --- a/src/m/classes/qmu.m +++ b/src/m/classes/qmu.m @@ -35,7 +35,7 @@ % old fields must be recovered (make sure they are in the deprecated % model properties) - if verLessThan('matlab','7.9'), + if verLessThan('matlab','7.9') disp('Warning: your matlab version is old and there is a risk that load does not work correctly'); disp(' if the model is not loaded correctly, rename temporarily loadobj so that matlab does not use it'); @@ -79,29 +79,29 @@ version=IssmConfig('_DAKOTA_VERSION_'); version=str2num(version(1:3)); - if version < 6, - if md.qmu.params.evaluation_concurrency~=1, + if version < 6 + if md.qmu.params.evaluation_concurrency~=1 md = checkmessage(md,['concurrency should be set to 1 when running dakota in library mode']); end else - if ~strcmpi(self.params.evaluation_scheduling,'master'), + if ~strcmpi(self.params.evaluation_scheduling,'master') md = checkmessage(md,['evaluation_scheduling in qmu.params should be set to ''master''']); end - if md.cluster.nprocs()<=1, + if md.cluster.nprocs()<=1 md = checkmessage(md,['in parallel library mode, Dakota needs to run on at least 2 cpus, 1 cpu for the master, 1 cpu for the slave. Modify md.cluster.np accordingly.']); end - if self.params.processors_per_evaluation<1, + if self.params.processors_per_evaluation<1 md = checkmessage(md,['in parallel library mode, Dakota needs to run at least one slave on one cpu (md.qmu.params.processors_per_evaluation >=1)!']); end - if mod(md.cluster.nprocs()-1,self.params.processors_per_evaluation), + if mod(md.cluster.nprocs()-1,self.params.processors_per_evaluation) %md = checkmessage(md,['in parallel library mode, the requirement is for md.cluster.np = md.qmu.params.processors_per_evaluation * number_of_slaves, where number_of_slaves will automatically be determined by Dakota. Modify md.cluster.np accordingly']); end end %go through variables and check for consistency: fv=fieldnames(self.variables); - for i=1:length(fv), + for i=1:length(fv) self.variables.(fv{i}).checkconsistency(md,solution,analyses); end @@ -110,20 +110,20 @@ %partitions for scaled variables, they better show up in the order dakota is feeding them to us %in InputUpdateFromDakotax! fv=fieldnames(self.variables); classlist={}; - for i=1:length(fv), + for i=1:length(fv) classlist{i}=class(self.variables.(fv{i})); end n=0; u=0; h=0; - for i=1:length(classlist), + for i=1:length(classlist) if strcmpi(classlist{i},'normal_uncertain') - if (u~=0 | h~=0), + if (u~=0 | h~=0) error('normal_uncertain variables should be declared before uniform and histogram_bin uncertain variables'); else n=1; end end if strcmpi(classlist{i},'uniform_uncertain') - if (h~=0), + if (h~=0) error('uniform_uncertain variables should be declared before histogram_bin uncertain variables'); else u=1; @@ -221,11 +221,11 @@ function disp(self) % {{{ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','isdakota','format','Boolean'); WriteData(fid,prefix,'object',self,'fieldname','output','format','Boolean'); - if ~self.isdakota, + if ~self.isdakota WriteData(fid,prefix,'data',false,'name','md.qmu.mass_flux_segments_present','format','Boolean'); return; end - if strcmpi(self.method.method,'nond_sampling'), + if strcmpi(self.method.method,'nond_sampling') WriteData(fid,prefix,'data',self.method.params.samples,'name','md.qmu.method.params.samples','format','Integer'); end WriteData(fid,prefix,'object',self,'fieldname','numberofresponses','format','Integer'); @@ -236,7 +236,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','responsedescriptors','format','StringArray'); WriteData(fid,prefix,'object',self,'fieldname','responsepartitions','format','MatArray'); WriteData(fid,prefix,'object',self,'fieldname','responsepartitions_npart','format','IntMat','mattype',3); - if ~isempty(self.mass_flux_segments), + if ~isempty(self.mass_flux_segments) WriteData(fid,prefix,'data',self.mass_flux_segments,'name','md.qmu.mass_flux_segments','format','MatArray'); flag=true; else @@ -248,7 +248,7 @@ function marshall(self,prefix,md,fid) % {{{ end % }}} function savemodeljs(self,fid,modelname) % {{{ - if self.isdakota, + if self.isdakota error('qmu savemodeljs error message: not supported yet!'); end diff --git a/src/m/classes/qmu/continuous_design.m b/src/m/classes/qmu/continuous_design.m index 1681df95f..22cb2ab95 100644 --- a/src/m/classes/qmu/continuous_design.m +++ b/src/m/classes/qmu/continuous_design.m @@ -58,20 +58,20 @@ %if the variable is scaled, a partition vector should have been %supplied, and that partition vector should have as many partitions %as the upper and lower vectors: - if self.isscaled() | self.isdistributed(), + if self.isscaled() | self.isdistributed() self.partition=getfieldvalue(options,'partition'); self.nsteps=getfieldvalue(options,'nsteps',1); npart=qmupart2npart(self.partition); - if npart~=size(self.upper,1), + if npart~=size(self.upper,1) error(['continuous_design constructor: for the scaled variable ' self.descriptor ' the row size of the upper field should be identical to the number of partitions']); end - if npart~=size(self.lower,1), + if npart~=size(self.lower,1) error(['continuous_design constructor: for the scaled variable ' self.descriptor ' the row size of the lower field should be identical to the number of partitions']); end - if self.nsteps~=size(self.upper,2), + if self.nsteps~=size(self.upper,2) error(['continuous_design constructor: for the scaled variable ' self.descriptor ' the col size of the upper field should be identical to the number of time steps']); end - if self.nsteps~=size(self.lower,2), + if self.nsteps~=size(self.lower,2) error(['continuous_design constructor: for the scaled variable ' self.descriptor ' the col size of the lower field should be identical to the number of time steps']); end @@ -95,37 +95,37 @@ function disp(self) % {{{ md = checkfield(md,'field',self.upper,'fieldname','continuous_design.upper','NaN',1,'Inf',1,'>=',0); md = checkfield(md,'field',self.lower,'fieldname','continuous_design.lower','NaN',1,'Inf',1,'>=',0); - if self.isscaled(), - if isempty(self.partition), + if self.isscaled() + if isempty(self.partition) error('continuous_design is a scaled variable, but it''s missing a partition vector'); end %better have a partition vector that has as many partitions as loer's size: - if size(self.lower,1)~=partition_npart(self.partition), + if size(self.lower,1)~=partition_npart(self.partition) error('continuous_design error message: row size of lower and partition size should be identical'); end - if size(self.upper,1)~=partition_npart(self.partition), + if size(self.upper,1)~=partition_npart(self.partition) error('continuous_design error message: row size of upper and partition size should be identical'); end %we need as steps in lower and upper as there are time steps: - if size(self.lower,2)~=self.nsteps, + if size(self.lower,2)~=self.nsteps error('continuous_design error message: col size of lower and number of time steps should be identical'); end - if size(self.upper,2)~=self.nsteps, + if size(self.upper,2)~=self.nsteps error('continuous_design error message: col size of upper and number of time steps should be identical'); end md = checkfield(md,'field',self.partition,'fieldname','continuous_design.partition','NaN',1,'Inf',1,'>=',-1,'numel',[md.mesh.numberofvertices,md.mesh.numberofelements]); - if size(self.partition,2)>1, + if size(self.partition,2)>1 error('continuous_design error message: partition should be a column vector'); end partcheck=unique(self.partition); partmin=min(partcheck); partmax=max(partcheck); - if partmax<-1, + if partmax<-1 error('continuous_design error message: partition vector''s min value should be -1 (for no partition), or start at 0'); end nmax=max(md.mesh.numberofelements,md.mesh.numberofvertices); - if partmax>nmax, + if partmax>nmax error('continuous_design error message: partition vector''s values cannot go over the number of vertices or elements'); end end @@ -200,14 +200,14 @@ function disp(self) % {{{ end % }}} %new methods: function distributed=isdistributed(self) % {{{ - if strncmp(self.descriptor,'distributed_',12), + if strncmp(self.descriptor,'distributed_',12) distributed=1; else distributed=0; end end % }}} function scaled=isscaled(self) % {{{ - if strncmp(self.descriptor,'scaled_',7), + if strncmp(self.descriptor,'scaled_',7) scaled=1; else scaled=0; diff --git a/src/m/classes/qmu/histogram_bin_uncertain.m b/src/m/classes/qmu/histogram_bin_uncertain.m index 09ccce74c..ca2bfeb1f 100644 --- a/src/m/classes/qmu/histogram_bin_uncertain.m +++ b/src/m/classes/qmu/histogram_bin_uncertain.m @@ -41,16 +41,16 @@ %if the variable is distributed, a partition vector should have been %supplied, and that partition vector should have as many partitions %as the pairs_per_variable, abscissas and counts arrays: - if self.isdistributed(), + if self.isdistributed() self.partition=getfieldvalue(options,'partition'); npart=qmupart2npart(self.partition); - if npart~=length(self.pairs_per_variable), + if npart~=length(self.pairs_per_variable) error(sprintf('histogram_bin_uncertain constructor: for the distributed variable %s the number of pairs_per_variable arrays (%i) should be equal to the number of partitions (%i)',self.descriptor,length(self.pairs_per_variable),npart)); end - if npart~=length(self.abscissas), + if npart~=length(self.abscissas) error(sprintf('histogram_bin_uncertain constructor: for the distributed variable %s the number of abscissas arrays (%i) should be equal to the number of partitions (%i)',self.descriptor,length(self.abscissas),npart)); end - if npart~=length(self.counts), + if npart~=length(self.counts) error(sprintf('histogram_bin_uncertain constructor: for the distributed variable %s the size of counts (%i) should be equal to the number of partitions (%i)',self.descriptor,length(self.counts),npart)); end end @@ -63,7 +63,7 @@ function disp(self) % {{{ fielddisplay(self,'pairs_per_variable','number of bins in histogram'); fielddisplay(self,'abscissas','abscissas for histogram'); fielddisplay(self,'counts','probabilities for histogram'); - if ~isempty(self.partition), + if ~isempty(self.partition) fielddisplay(self,'partition','partition vector defining where sampling will occur'); end end @@ -130,14 +130,14 @@ function disp(self) % {{{ scale=[]; end % }}} function scaled=isscaled(self) % {{{ - if strncmp(self.descriptor,'scaled_',7), + if strncmp(self.descriptor,'scaled_',7) scaled=1; else scaled=0; end end % }}} function distributed=isdistributed(self) % {{{ - if strncmp(self.descriptor,'distributed_',12), + if strncmp(self.descriptor,'distributed_',12) distributed=1; else distributed=0; diff --git a/src/m/classes/qmu/normal_uncertain.m b/src/m/classes/qmu/normal_uncertain.m index 026f6cc0e..b4b55a80c 100644 --- a/src/m/classes/qmu/normal_uncertain.m +++ b/src/m/classes/qmu/normal_uncertain.m @@ -33,20 +33,20 @@ %if the variable is scaled, a partition vector should have been %supplied, and that partition vector should have as many partitions %as the mean and stddev vectors: - if self.isscaled(), + if self.isscaled() self.partition=getfieldvalue(options,'partition'); self.nsteps=getfieldvalue(options,'nsteps',1); npart=qmupart2npart(self.partition); - if npart~=size(self.mean,1), + if npart~=size(self.mean,1) error(['normal_uncertain constructor: for the scaled variable ' self.descriptor ' the row size of the mean field should be identical to the number of partitions']); end - if npart~=size(self.stddev,1), + if npart~=size(self.stddev,1) error(['normal_uncertain constructor: for the scaled variable ' self.descriptor ' the row size of the stddev field should be identical to the number of partitions']); end - if self.nsteps~=size(self.mean,2), + if self.nsteps~=size(self.mean,2) error(['normal_uncertain constructor: for the scaled variable ' self.descriptor ' the col size of the mean field should be identical to the number of time steps']); end - if self.nsteps~=size(self.stddev,2), + if self.nsteps~=size(self.stddev,2) error(['normal_uncertain constructor: for the scaled variable ' self.descriptor ' the col size of the stddev field should be identical to the number of time steps']); end @@ -58,7 +58,7 @@ function disp(self) % {{{ fielddisplay(self,'descriptor','name tag'); fielddisplay(self,'mean','pdf mean'); fielddisplay(self,'stddev','pdf standard deviation'); - if ~isempty(self.partition), + if ~isempty(self.partition) fielddisplay(self,'partition','partition vector defining where sampling will occur'); end fielddisplay(self,'nsteps','number of time steps'); @@ -68,37 +68,37 @@ function disp(self) % {{{ md = checkfield(md,'field',self.mean,'fieldname','normal_uncertain.mean','NaN',1,'Inf',1,'>=',0); md = checkfield(md,'field',self.stddev,'fieldname','normal_uncertain.stddev','NaN',1,'Inf',1,'>=',0); - if self.isscaled(), - if isempty(self.partition), + if self.isscaled() + if isempty(self.partition) error('normal_uncertain is a scaled variable, but it''s missing a partition vector'); end %better have a partition vector that has as many partitions as stddev's size: - if size(self.stddev,1)~=partition_npart(self.partition), + if size(self.stddev,1)~=partition_npart(self.partition) error('normal_uncertain error message: row size of stddev and partition size should be identical'); end - if size(self.mean,1)~=partition_npart(self.partition), + if size(self.mean,1)~=partition_npart(self.partition) error('normal_uncertain error message: row size of mean and partition size should be identical'); end %we need as steps in stddev and mean as there are time steps: - if size(self.stddev,2)~=self.nsteps, + if size(self.stddev,2)~=self.nsteps error('normal_uncertain error message: col size of stddev and number of time steps should be identical'); end - if size(self.mean,2)~=self.nsteps, + if size(self.mean,2)~=self.nsteps error('normal_uncertain error message: col size of mean and number of time steps should be identical'); end md = checkfield(md,'field',self.partition,'fieldname','normal_uncertain.partition','NaN',1,'Inf',1,'>=',-1,'numel',[md.mesh.numberofvertices,md.mesh.numberofelements]); - if size(self.partition,2)>1, + if size(self.partition,2)>1 error('normal_uncertain error message: partition should be a column vector'); end partcheck=unique(self.partition); partmin=min(partcheck); partmax=max(partcheck); - if partmax<-1, + if partmax<-1 error('normal_uncertain error message: partition vector''s min value should be -1 (for no partition), or start at 0'); end nmax=max(md.mesh.numberofelements,md.mesh.numberofvertices); - if partmax>nmax, + if partmax>nmax error('normal_uncertain error message: partition vector''s values cannot go over the number of vertices or elements'); end end @@ -161,14 +161,14 @@ function disp(self) % {{{ end % }}} %new methods: function distributed=isdistributed(self) % {{{ - if strncmp(self.descriptor,'distributed_',12), + if strncmp(self.descriptor,'distributed_',12) distributed=1; else distributed=0; end end % }}} function scaled=isscaled(self) % {{{ - if strncmp(self.descriptor,'scaled_',7), + if strncmp(self.descriptor,'scaled_',7) scaled=1; else scaled=0; diff --git a/src/m/classes/qmu/partition_npart.m b/src/m/classes/qmu/partition_npart.m index 5b4764a88..00c6937dc 100644 --- a/src/m/classes/qmu/partition_npart.m +++ b/src/m/classes/qmu/partition_npart.m @@ -7,7 +7,7 @@ %ok, so now we should have a vector from 0 to npart-1: npart=max(uvec)+1; - if npart~=length(uvec), + if npart~=length(uvec) error('partition vector should be in the range 0 to numberofpartitions, with -1 values for vertices or elements not belonging to any partition'); end diff --git a/src/m/classes/qmu/response_function.m b/src/m/classes/qmu/response_function.m index 4aa6fc8a7..a2775e124 100644 --- a/src/m/classes/qmu/response_function.m +++ b/src/m/classes/qmu/response_function.m @@ -35,7 +35,7 @@ self.grell=getfieldvalue(options,'general_reliability_levels',[]); %if the response is scaled, a partition vector should have been supplied. - if self.isscaled(), + if self.isscaled() self.partition=getfieldvalue(options,'partition'); npart=partition_npart(self.partition); end @@ -52,7 +52,7 @@ disp(sprintf(' probl: %s' ,string_vec(rf(i).probl))); disp(sprintf(' rell: %s' ,string_vec(rf(i).rell))); disp(sprintf(' grell: %s' ,string_vec(rf(i).grell))); - if ~isempty(rf.partition), + if ~isempty(rf.partition) fielddisplay(rf,'partition','partition vector defining where response will be computed'); end disp(sprintf('\n')); @@ -116,7 +116,7 @@ end % }}} %new methods: function scaled =isscaled(self) % {{{ - if strncmp(self.descriptor,'scaled_',7), + if strncmp(self.descriptor,'scaled_',7) scaled=1; else scaled=0; diff --git a/src/m/classes/qmu/uniform_uncertain.m b/src/m/classes/qmu/uniform_uncertain.m index fb01fb3ce..f5361d1f9 100644 --- a/src/m/classes/qmu/uniform_uncertain.m +++ b/src/m/classes/qmu/uniform_uncertain.m @@ -33,20 +33,20 @@ %if the variable is scaled, a partition vector should have been %supplied, and that partition vector should have as many partitions %as the lower and upper vectors: - if self.isscaled(), + if self.isscaled() self.partition=getfieldvalue(options,'partition'); self.nsteps=getfieldvalue(options,'nsteps',1); npart=qmupart2npart(self.partition); - if npart~=size(self.upper,1), + if npart~=size(self.upper,1) error(['uniform_uncertain constructor: for the scaled variable' self.descriptor ' the row size of the upper field should be identical to the number of partitions']); end - if npart~=size(self.lower,1), + if npart~=size(self.lower,1) error(['uniform_uncertain constructor: for the scaled variable' self.descriptor ' the row size of the lower field should be identical to the number of partitions']); end - if self.nsteps~=size(self.upper,2), + if self.nsteps~=size(self.upper,2) error(['uniform_uncertain constructor: for the scaled variable ' self.descriptor ' the col size of the upper field should be identical to the number of time steps']); end - if self.nsteps~=size(self.lower,2), + if self.nsteps~=size(self.lower,2) error(['uniform_uncertain constructor: for the scaled variable ' self.descriptor ' the col size of the lower field should be identical to the number of time steps']); end end @@ -58,7 +58,7 @@ function disp(self) % {{{ fielddisplay(self,'descriptor','name tag'); fielddisplay(self,'lower','pdf lower bound'); fielddisplay(self,'upper','pdf upper bound'); - if ~isempty(self.partition), + if ~isempty(self.partition) fielddisplay(self,'partition','partition vector defining where sampling will occur'); end fielddisplay(self,'nsteps','number of time steps'); @@ -68,37 +68,37 @@ function disp(self) % {{{ md = checkfield(md,'field',self.upper,'fieldname','uniform_uncertain.upper','NaN',1,'Inf',1,'>',self.lower,'numel',length(self.lower)); md = checkfield(md,'field',self.lower,'fieldname','uniform_uncertain.lower','NaN',1,'Inf',1,'<',self.upper,'numel',length(self.upper)); - if self.isscaled(), - if isempty(self.partition), + if self.isscaled() + if isempty(self.partition) error('uniform_uncertain is a scaled variable, but it''s missing a partition vector'); end %better have a partition vector that has as many partitions as upper and lower's size: - if size(self.upper,1)~=partition_npart(self.partition), + if size(self.upper,1)~=partition_npart(self.partition) error('uniform_uncertain error message: row size of upper and partition size should be identical'); end - if size(self.lower,1)~=partition_npart(self.partition), + if size(self.lower,1)~=partition_npart(self.partition) error('uniform_uncertain error message: row size of lower and partition size should be identical'); end %we need as steps in upper and lower as there are time steps: - if size(self.upper,2)~=self.nsteps, + if size(self.upper,2)~=self.nsteps error('uniform_uncertain error message: col size of upper and number of time steps should be identical'); end - if size(self.lower,2)~=self.nsteps, + if size(self.lower,2)~=self.nsteps error('uniform_uncertain error message: col size of lower and number of time steps should be identical'); end md = checkfield(md,'field',self.partition,'fieldname','uniform_uncertain.partition','NaN',1,'Inf',1,'>=',-1,'numel',[md.mesh.numberofvertices,md.mesh.numberofelements]); - if size(self.partition,2)>1, + if size(self.partition,2)>1 error('uniform_uncertain error message: partition should be a column vector'); end partcheck=unique(self.partition); partmin=min(partcheck); partmax=max(partcheck); - if partmax<-1, + if partmax<-1 error('uniform_uncertain error message: partition vector''s min value should be -1 (for no partition), or start at 0'); end nmax=max(md.mesh.numberofelements,md.mesh.numberofvertices); - if partmax>nmax, + if partmax>nmax error('uniform_uncertain error message: partition vector''s values cannot go over the number of vertices or elements'); end end @@ -164,14 +164,14 @@ function disp(self) % {{{ end % }}} %new methods: function distributed=isdistributed(self) % {{{ - if strncmp(self.descriptor,'distributed_',12), + if strncmp(self.descriptor,'distributed_',12) distributed=1; else distributed=0; end end % }}} function scaled=isscaled(self) % {{{ - if strncmp(self.descriptor,'scaled_',7), + if strncmp(self.descriptor,'scaled_',7) scaled=1; else scaled=0; diff --git a/src/m/classes/qmustatistics.m b/src/m/classes/qmustatistics.m index 355e4a0b1..95076cc30 100644 --- a/src/m/classes/qmustatistics.m +++ b/src/m/classes/qmustatistics.m @@ -30,7 +30,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -53,24 +53,24 @@ %Checks: md = checkfield(md,'fieldname','qmu.statistics.nfiles_per_directory','>=',1); - if self.ndirectories>md.cluster.np, + if self.ndirectories>md.cluster.np error('qmustatistics consistency check: number of cluster CPUs should be > number of output directories'); end - if (self.ndirectories*self.nfiles_per_directory)~=md.qmu.method.params.samples, + if (self.ndirectories*self.nfiles_per_directory)~=md.qmu.method.params.samples error('qmustatistics consistency check: number of directories x number of files per directory should be == to number of samples requested!'); end - for i=1:length(self.method), + for i=1:length(self.method) m=self.method(i); - if strcmpi(m.name,'Histogram'), + if strcmpi(m.name,'Histogram') md = checkfield(md,'fieldname',sprintf('qmu.statistics.method(%i).nbins',i),'>=',1,'<=',md.qmu.method.params.samples); end - for f=1:length(m.fields), - if ~ischar(m.fields{f}), + for f=1:length(m.fields) + if ~ischar(m.fields{f}) error(sprintf('qmustatistics consistency check error: qmu.statistics.method(%i).fields{%i} is not a string!',i,f)); end end - for s=1:length(m.steps), - if m.steps(s)<=0, + for s=1:length(m.steps) + if m.steps(s)<=0 error(sprintf('qmustatistics consistency check error: qmu.statistics.method(%i).steps(%i) should be > 0!',i,s)); end if m.steps(s)> md.mesh.numberofvertices @@ -93,7 +93,7 @@ function disp(self) % {{{ fielddisplay(self,'nfiles_per_directory','number of files per output directory'); fielddisplay(self,'ndirectories','number of output directories; should be < numcpus'); - for i=1:length(self.method), + for i=1:length(self.method) disp([' method #' num2str(i)]); disp(self.method(i)); end @@ -101,7 +101,7 @@ function disp(self) % {{{ end % }}} function marshall(self,prefix,md,fid) % {{{ - if strcmpi(self.method(1).name,'None'), + if strcmpi(self.method(1).name,'None') WriteData(fid,prefix,'name','md.qmu.statistics','data',0,'format','Boolean'); statistics=0; return; @@ -110,21 +110,21 @@ function marshall(self,prefix,md,fid) % {{{ statistics=1; end - if statistics, + if statistics WriteData(fid,prefix,'name','md.qmu.statistics.nfiles_per_directory','data',self.nfiles_per_directory,'format','Integer'); WriteData(fid,prefix,'name','md.qmu.statistics.ndirectories','data',self.ndirectories,'format','Integer'); WriteData(fid,prefix,'name','md.qmu.statistics.numstatistics','data',length(self.method),'format','Integer'); - for i=1:length(self.method), + for i=1:length(self.method) m=self.method(i); WriteData(fid,prefix,'name',sprintf('md.qmu.statistics.method(%i).name',i),'data',m.name,'format','String'); WriteData(fid,prefix,'data',m.fields,'name',sprintf('md.qmu.statistics.method(%i).fields',i),'format','StringArray'); WriteData(fid,prefix,'data',m.steps,'name',sprintf('md.qmu.statistics.method(%i).steps',i),'format','IntMat','mattype',3); - if strcmpi(m.name,'Histogram'), + if strcmpi(m.name,'Histogram') WriteData(fid,prefix,'name',sprintf('md.qmu.statistics.method(%i).nbins',i),'data',m.nbins,'format','Integer'); - elseif strcmpi(m.name,'MeanVariance'), + elseif strcmpi(m.name,'MeanVariance') %do nothing - elseif strcmpi(m.name,'SampleSeries'), + elseif strcmpi(m.name,'SampleSeries') WriteData(fid,prefix,'data',m.indices,'name',sprintf('md.qmu.statistics.method(%i).indices',i),'format','IntMat','mattype',3); else error(sprintf('qmustatistics marshall error message: unknown type ''%s'' for qmu.statistics.method(%i)',m.name,i)); diff --git a/src/m/classes/radar.m b/src/m/classes/radar.m index d0a84e236..5ae01145e 100644 --- a/src/m/classes/radar.m +++ b/src/m/classes/radar.m @@ -18,7 +18,7 @@ return; end % }}} function self = radar(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -33,7 +33,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('radar error message: ''name'' field should be a string!'); end OutputdefinitionStringArray={}; diff --git a/src/m/classes/radaroverlay.m b/src/m/classes/radaroverlay.m index 8f71c6b20..98b0c888d 100644 --- a/src/m/classes/radaroverlay.m +++ b/src/m/classes/radaroverlay.m @@ -39,7 +39,7 @@ function disp(self) % {{{ end % }}} function savemodeljs(self,fid,modelname) % {{{ - if ~isnan(self.pwr), + if ~isnan(self.pwr) writejs1Darray(fid,[modelname '.radaroverlay.xlim'],[min(self.x) max(self.x)]); writejs1Darray(fid,[modelname '.radaroverlay.ylim'],[min(self.y) max(self.y)]); writejs2Darray(fid,[modelname '.radaroverlay.outerindex'],self.outerindex); diff --git a/src/m/classes/regionaloutput.m b/src/m/classes/regionaloutput.m index d45dea2ee..789290993 100644 --- a/src/m/classes/regionaloutput.m +++ b/src/m/classes/regionaloutput.m @@ -29,7 +29,7 @@ end end % }}} function self = regionaloutput(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else %use provided options to change fields @@ -65,10 +65,10 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ischar(self.name), + if ~ischar(self.name) error('regionaloutput error message: ''name'' field should be a string!'); end - if ~ischar(self.outputnamestring), + if ~ischar(self.outputnamestring) error('regionaloutput error message: ''outputnamestring'' field should be a string!'); end diff --git a/src/m/classes/rifts.m b/src/m/classes/rifts.m index f301098e5..14341e418 100644 --- a/src/m/classes/rifts.m +++ b/src/m/classes/rifts.m @@ -21,27 +21,27 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if isempty(self.riftstruct) | isnans(self.riftstruct), + if isempty(self.riftstruct) | isnans(self.riftstruct) numrifts=0; else numrifts=numel(self.riftstruct); end - if numrifts, - if ~(strcmp(domaintype(md.mesh),'2Dhorizontal')), + if numrifts + if ~(strcmp(domaintype(md.mesh),'2Dhorizontal')) md = checkmessage(md,['models with rifts are only supported in 2d for now!']); end - if ~isstruct(self.riftstruct), + if ~isstruct(self.riftstruct) md = checkmessage(md,['rifts.riftstruct should be a structure!']); end - if ~isempty(find(md.mesh.segmentmarkers>=2)), + if ~isempty(find(md.mesh.segmentmarkers>=2)) %We have segments with rift markers, but no rift structure! md = checkmessage(md,['model should be processed for rifts (run meshprocessrifts)!']); end - for i=1:numrifts, + for i=1:numrifts md = checkfield(md,'fieldname',sprintf('rifts.riftstruct(%d).fill',i),'values',{'Air','Ice','Melange','Water'}); end else - if ~isnans(self.riftstruct), + if ~isnans(self.riftstruct) md = checkmessage(md,['riftstruct should be NaN since numrifts is 0!']); end end @@ -56,14 +56,14 @@ function disp(self) % {{{ function marshall(self,prefix,md,fid) % {{{ %Process rift info - if isempty(self.riftstruct) | isnans(self.riftstruct), + if isempty(self.riftstruct) | isnans(self.riftstruct) numrifts=0; else numrifts=numel(self.riftstruct); end numpairs=0; - for i=1:numrifts, + for i=1:numrifts numpairs=numpairs+size(self.riftstruct(i).penaltypairs,1); end @@ -84,7 +84,7 @@ function marshall(self,prefix,md,fid) % {{{ % 2 for nodes + 2 for elements+ 2 for normals + 1 for length + 1 for fill + 1 for friction + 1 for fraction + 1 for fractionincrement + 1 for state. data=zeros(numpairs,12); count=1; - for i=1:numrifts, + for i=1:numrifts numpairsforthisrift=size(self.riftstruct(i).penaltypairs,1); data(count:count+numpairsforthisrift-1,1:7)=self.riftstruct(i).penaltypairs; data(count:count+numpairsforthisrift-1,8)=self.riftstruct(i).fill; @@ -100,13 +100,13 @@ function marshall(self,prefix,md,fid) % {{{ end % }}} function savemodeljs(self,fid,modelname) % {{{ - if isempty(self.riftstruct) | isnans(self.riftstruct), + if isempty(self.riftstruct) | isnans(self.riftstruct) numrifts=0; else numrifts=numel(self.riftstruct); end - if numrifts, + if numrifts error('rifts savemodeljs error message: not supported yet!'); end diff --git a/src/m/classes/rotational.m b/src/m/classes/rotational.m index f188df55d..c70123a03 100644 --- a/src/m/classes/rotational.m +++ b/src/m/classes/rotational.m @@ -29,7 +29,7 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0) return; end diff --git a/src/m/classes/sampling.m b/src/m/classes/sampling.m index 39bc8c773..f8cd0b486 100644 --- a/src/m/classes/sampling.m +++ b/src/m/classes/sampling.m @@ -93,7 +93,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/sealevelmodel.m b/src/m/classes/sealevelmodel.m index e8df67f73..50a7801a3 100644 --- a/src/m/classes/sealevelmodel.m +++ b/src/m/classes/sealevelmodel.m @@ -28,7 +28,7 @@ function slm = sealevelmodel(varargin) % {{{ slm=setdefaultparameters(slm); - if nargin==1, + if nargin==1 options=pairoptions(varargin{:}); @@ -67,12 +67,12 @@ function checkconsistency(slm,solutiontype) % {{{ error('earth.transient.isslc should be turned on') end - for i=1:length(slm.icecaps), + for i=1:length(slm.icecaps) md= slm.icecaps{i}; %check that the transition vectors have the right size: - if md.mesh.numberofvertices ~= length(slm.earth.solidearth.transitions{i}), + if md.mesh.numberofvertices ~= length(slm.earth.solidearth.transitions{i}) error(['issue with size of transition vector for ice cap: ' num2str(i) ' name: ' md.miscellaneous.name]); end @@ -137,27 +137,27 @@ function disp(self) % {{{ end % }}} function self=mergeresults(self) % {{{ champs=fieldnames(self.icecaps{1}.results.TransientSolution); - for i=1:length(self.mergedcaps)/2, + for i=1:length(self.mergedcaps)/2 md=self.mergedcaps{2*(i-1)+1}; trans=self.mergedcaps{2*(i-1)+2}; %icecaps=self.icecaps(self.range{2*(i-1)+2}); - for j=1:length(self.icecaps{1}.results.TransientSolution), - for k=1:length(champs), - if strcmpi(class(icecaps{1}.results.TransientSolution(j).(champs{k})),'double'), + for j=1:length(self.icecaps{1}.results.TransientSolution) + for k=1:length(champs) + if strcmpi(class(icecaps{1}.results.TransientSolution(j).(champs{k})),'double') %vertex or element? - if length(icecaps{1}.results.TransientSolution(j).(champs{k}))==icecaps{1}.mesh.numberofvertices, + if length(icecaps{1}.results.TransientSolution(j).(champs{k}))==icecaps{1}.mesh.numberofvertices md.results.TransientSolution(j).(champs{k})=zeros(md.mesh.numberofvertices,1); - for l=1:length(trans), + for l=1:length(trans) resultcap=icecaps{l}.results.TransientSolution(j).(champs{k}); md.results.TransientSolution(j).(champs{k})(trans{l})=resultcap; end else - if strcmpi(champs{k},'IceVolume') | strcmpi(champs{k},'IceVolumeAboveFloatation') , + if strcmpi(champs{k},'IceVolume') | strcmpi(champs{k},'IceVolumeAboveFloatation') md.results.TransientSolution(j).(champs{k})=0; - for l=1:length(trans), + for l=1:length(trans) resultcap=icecaps{l}.results.TransientSolution(j).(champs{k}); md.results.TransientSolution(j).(champs{k})= md.results.TransientSolution(j).(champs{k})+resultcap; end - elseif strcmpi(champs{k},'time'), + elseif strcmpi(champs{k},'time') md.results.TransientSolution(j).(champs{k})= icecaps{1}.results.TransientSolution(j).(champs{k}); else continue; @@ -172,7 +172,7 @@ function disp(self) % {{{ end end % }}} function listcaps(self) % {{{ - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) disp(sprintf('%i: %s',i,self.icecaps{i}.miscellaneous.name)); end end % }}} @@ -181,15 +181,15 @@ function listcaps(self) % {{{ end % }}} function list=continents(self) % {{{ list={}; - for i=1:length(self.basins), + for i=1:length(self.basins) list{end+1}=self.basins{i}.continent; end list=unique(list); end % }}} function list=basinsfromcontinent(self,continent) % {{{ list={}; - for i=1:length(self.icecaps), - if strcmpi(self.basins{i}.continent,continent), + for i=1:length(self.icecaps) + if strcmpi(self.basins{i}.continent,continent) list{end+1}=self.basins{i}.name; end end @@ -214,7 +214,7 @@ function intersections2d(self,varargin) % {{{ xe=self.earth.mesh.x(self.earth.mesh.elements)*[1;1;1]/3; ye=self.earth.mesh.y(self.earth.mesh.elements)*[1;1;1]/3; - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) mdi=self.icecaps{i}; %for elements: @@ -243,7 +243,7 @@ function intersections(self,varargin) % {{{ ye=self.earth.mesh.y(self.earth.mesh.elements)*[1;1;1]/3; ze=self.earth.mesh.z(self.earth.mesh.elements)*[1;1;1]/3; - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) mdi=self.icecaps{i}; mdi=TwoDToThreeD(mdi,self.planet); @@ -261,20 +261,20 @@ function intersections(self,varargin) % {{{ self.earth.solidearth.transfercount(self.transitions{i})=self.earth.solidearth.transfercount(self.transitions{i})+1; end - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) self.icecaps{i}.solidearth.transfercount=self.earth.solidearth.transfercount(self.transitions{i}); end end % }}} function checkintersections(self) % {{{ flags=zeros(self.earth.mesh.numberofvertices,1); - for i=1:length(self.basins), + for i=1:length(self.basins) flags(self.transitions{i})=i; end plotmodel(self.earth,'data',flags,'coastlines','on'); end % }}} function checkbasinconsistency(self) % {{{ - for i=1:length(self.basins), + for i=1:length(self.basins) self.basins{i}.checkconsistency(); end @@ -285,12 +285,12 @@ function checkbasinconsistency(self) % {{{ bas=getfieldvalue(options,'basin','all'); %expand continent list: {{{ - if iscell(continent), - if length(continent)==1, - if strcmpi(continent{1},'all'), + if iscell(continent) + if length(continent)==1 + if strcmpi(continent{1},'all') %need to transform this into a list of continents: continent={}; - for i=1:length(self.basins), + for i=1:length(self.basins) continent{end+1}=self.basins{i}.continent; end continent=unique(continent); @@ -301,10 +301,10 @@ function checkbasinconsistency(self) % {{{ %nothing to do: assume we have a list of continents end else - if strcmpi(continent,'all'), + if strcmpi(continent,'all') %need to transform this into a list of continents: continent={}; - for i=1:length(self.basins), + for i=1:length(self.basins) continent{end+1}=self.basins{i}.continent; end continent=unique(continent); @@ -314,13 +314,13 @@ function checkbasinconsistency(self) % {{{ end %}}} %expand basins list using the continent list above and the extra bas discriminator: %{{{ - if iscell(bas), - if length(bas)==1, - if strcmpi(bas{1},'all'), + if iscell(bas) + if length(bas)==1 + if strcmpi(bas{1},'all') %need to transform this into a list of basins: baslist=[]; - for i=1:length(self.basins), - if self.basins{i}.iscontinentany(continent{:}), + for i=1:length(self.basins) + if self.basins{i}.iscontinentany(continent{:}) baslist(end+1)=i; end end @@ -328,9 +328,9 @@ function checkbasinconsistency(self) % {{{ else bas=bas{1}; baslist=[]; - for i=1:length(self.basins), - if self.basins{i}.iscontinentany(continent{:}), - if self.basins{i}.isnameany(bas), + for i=1:length(self.basins) + if self.basins{i}.iscontinentany(continent{:}) + if self.basins{i}.isnameany(bas) baslist(end+1)=i; end end @@ -340,11 +340,11 @@ function checkbasinconsistency(self) % {{{ else %we have a list of basin names: baslist=[]; - for i=1:length(bas), + for i=1:length(bas) basname=bas{i}; - for j=1:length(self.basins), - if self.basins{j}.iscontinentany(continent{:}), - if self.basins{j}.isnameany(basname), + for j=1:length(self.basins) + if self.basins{j}.iscontinentany(continent{:}) + if self.basins{j}.isnameany(basname) baslist(end+1)=j; end end @@ -353,19 +353,19 @@ function checkbasinconsistency(self) % {{{ end end else - if strcmpi(bas,'all'), + if strcmpi(bas,'all') baslist=[]; - for i=1:length(self.basins), - if self.basins{i}.iscontinentany(continent{:}), + for i=1:length(self.basins) + if self.basins{i}.iscontinentany(continent{:}) baslist(end+1)=i; end end baslist=unique(baslist); else baslist=[]; - for i=1:length(self.basins), - if self.basins{i}.iscontinentany(continent{:}), - if self.basins{i}.isnameany(bas), + for i=1:length(self.basins) + if self.basins{i}.iscontinentany(continent{:}) + if self.basins{i}.isnameany(bas) baslist(end+1)=i; end end @@ -383,7 +383,7 @@ function addicecap(self,md) % {{{ self.icecaps{end+1}=md; end % }}} function basinsplot3d(self,varargin) % {{{ - for i=1:length(self.basins), + for i=1:length(self.basins) self.basins{i}.plot3d(varargin{:}); end end % }}} @@ -396,23 +396,23 @@ function caticecaps(self,varargin) % {{{ %make 3D model: models=self.icecaps; - for i=1:length(models), + for i=1:length(models) models{i}=TwoDToThreeD(models{i},self.planet); end %Plug all models together: md=models{1}; - for i=2:length(models), + for i=2:length(models) md=modelmerge3d(md,models{i},'tolerance',tolerance); md.private.bamg.landmask=[md.private.bamg.landmask;models{i}.private.bamg.landmask]; end %Look for lone edges if asked for it: {{{ - if loneedgesdetect, + if loneedgesdetect edges=loneedges(md); plotmodel(md,'data',md.mask.land_levelset); hold on; - for i=1:length(edges), + for i=1:length(edges) ind1=edges(i,1); ind2=edges(i,2); %plot([md.mesh.x(ind1),md.mesh.x(ind2)],[md.mesh.y(ind1),md.mesh.y(ind2)],'r*-'); @@ -437,15 +437,15 @@ function caticecaps2d(self,varargin) % {{{ %Plug all models together: md=models{1}; - for i=2:length(models), + for i=2:length(models) md=modelmerge2d(md,models{i},'tolerance',tolerance); end %Look for lone edges if asked for it: {{{ - if loneedgesdetect, + if loneedgesdetect edges=loneedges(md); hold on; - for i=1:length(edges), + for i=1:length(edges) ind1=edges(i,1); ind2=edges(i,2); plot([md.mesh.x(ind1),md.mesh.x(ind2)],[md.mesh.y(ind1),md.mesh.y(ind2)],'g*-'); @@ -457,17 +457,17 @@ function caticecaps2d(self,varargin) % {{{ end % }}} function viscousiterations(self) % {{{ - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) ic=self.icecaps{i}; mvi=ic.results.TransientSolution(1).StressbalanceConvergenceNumSteps; - for j=2:length(ic.results.TransientSolution)-1, + for j=2:length(ic.results.TransientSolution)-1 mvi=max(mvi,ic.results.TransientSolution(j).StressbalanceConvergenceNumSteps); end disp(sprintf('%i, %s: %i',i,self.icecaps{i}.miscellaneous.name,mvi)); end end % }}} function maxtimestep(self) % {{{ - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) ic=self.icecaps{i}; mvi=length(ic.results.TransientSolution); timei=ic.results.TransientSolution(end).time; @@ -480,19 +480,19 @@ function maxtimestep(self) % {{{ function transfer(self,string) % {{{ %Recover field size in one icecap: eval(['n=size(self.icecaps{1}.' string ',1);']); - if n==self.icecaps{1}.mesh.numberofvertices, + if n==self.icecaps{1}.mesh.numberofvertices eval(['self.earth.' string '=zeros(self.earth.mesh.numberofvertices,1);']); - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) eval(['self.earth.' string '(self.transitions{' num2str(i) '})=self.icecaps{' num2str(i) '}.' string ';']); end - elseif n==(self.icecaps{1}.mesh.numberofvertices+1), + elseif n==(self.icecaps{1}.mesh.numberofvertices+1) %dealing with a transient dataset. %check that all timetags are similar between all icecaps: %{{{ - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) eval(['capfieldi= self.icecaps{' num2str(i) '}.' string ';']); - for j=(i+1):length(self.icecaps), + for j=(i+1):length(self.icecaps) eval(['capfieldj= self.icecaps{' num2str(j) '}.' string ';']); - if ~isequal(capfieldi(end,:),capfieldj(end,:)), + if ~isequal(capfieldi(end,:),capfieldj(end,:)) error(['Time stamps for ' string ' field are different between icecaps ' num2str(i) ' and ' num2str(j)]); end end @@ -506,17 +506,17 @@ function transfer(self,string) % {{{ eval(['field(end,:)=times;']); %transfer the times only, not the values %}}} %transfer all time fields: {{{ - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) eval(['capfieldi= self.icecaps{' num2str(i) '}.' string ';']); - for j=1:nsteps, + for j=1:nsteps eval(['field(self.transitions{' num2str(i) '},' num2str(j) ')=capfieldi(1:end-1,' num2str(j) ');']); %transfer only the values, not the time. end end eval(['self.earth.' string '=field;']); %do not forget to plug the field variable into its final location %}}} - elseif n==self.icecaps{1}.mesh.numberofelements, + elseif n==self.icecaps{1}.mesh.numberofelements eval(['self.earth.' string '=zeros(self.earth.mesh.numberofelements,1);']); - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) eval(['self.earth.' string '(self.eltransitions{' num2str(i) '})=self.icecaps{' num2str(i) '}.' string ';']); end else @@ -524,32 +524,32 @@ function transfer(self,string) % {{{ end end % }}} function self=homogeneize(self,noearth) % {{{ - if nargin==1, + if nargin==1 noearth=0; end mintimestep=Inf; - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) ic=self.icecaps{i}; mintimestep=min(mintimestep, length(ic.results.TransientSolution)); end - if ~noearth, + if ~noearth mintimestep=min(mintimestep, length(self.earth.results.TransientSolution)); end - for i=1:length(self.icecaps), + for i=1:length(self.icecaps) ic=self.icecaps{i}; ic.results.TransientSolution=ic.results.TransientSolution(1:mintimestep); self.icecaps{i}=ic; end ic=self.earth; - if ~noearth, + if ~noearth ic.results.TransientSolution=ic.results.TransientSolution(1:mintimestep); end self.earth=ic; end % }}} function self=initializemodels(self) % {{{ - for i=1:length(self.basins), + for i=1:length(self.basins) md=model(); md.miscellaneous.name=self.basins{i}.name; self.addicecap(md); diff --git a/src/m/classes/snowpack.m b/src/m/classes/snowpack.m index dbc683b87..fc59a32d2 100644 --- a/src/m/classes/snowpack.m +++ b/src/m/classes/snowpack.m @@ -114,7 +114,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end diff --git a/src/m/classes/solidearth.m b/src/m/classes/solidearth.m index eb4bc5b9a..454c844d5 100644 --- a/src/m/classes/solidearth.m +++ b/src/m/classes/solidearth.m @@ -60,7 +60,7 @@ function disp(self) % {{{ self.settings.disp(); self.lovenumbers.disp(); self.rotational.disp(); - if ~isempty(self.external), + if ~isempty(self.external) self.external.disp(); end @@ -87,7 +87,7 @@ function disp(self) % {{{ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0) return; end @@ -96,8 +96,8 @@ function disp(self) % {{{ self.settings.checkconsistency(md,solution,analyses); self.lovenumbers.checkconsistency(md,solution,analyses); self.rotational.checkconsistency(md,solution,analyses); - if ~isempty(self.external), - if ~isa(self.external,'solidearthsolution'), + if ~isempty(self.external) + if ~isa(self.external,'solidearthsolution') error('solidearth consistency check: external field should be a solidearthsolution'); end self.external.checkconsistency(md,solution,analyses); @@ -113,18 +113,18 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','transitions','format','MatArray'); WriteData(fid,prefix,'object',self,'fieldname','transfercount','format','DoubleMat','mattype',1); - if ~isempty(self.partitionice), + if ~isempty(self.partitionice) npartice=max(self.partitionice)+2; else npartice=0; end - if ~isempty(self.partitionhydro), + if ~isempty(self.partitionhydro) nparthydro=max(self.partitionhydro)+2; else nparthydro=0; end - if ~isempty(self.partitionocean), + if ~isempty(self.partitionocean) npartocean=max(self.partitionocean)+2; else npartocean=0; @@ -138,7 +138,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'data',npartocean,'format','Integer','name','md.solidearth.npartocean'); self.settings.marshall(prefix,md,fid); - if ~isempty(self.external), + if ~isempty(self.external) WriteData(fid,prefix,'data',1,'format','Integer','name','md.solidearth.isexternal'); self.external.marshall(prefix,md,fid); else @@ -150,7 +150,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/solidearthsettings.m b/src/m/classes/solidearthsettings.m index 10cae954a..83f22588a 100644 --- a/src/m/classes/solidearthsettings.m +++ b/src/m/classes/solidearthsettings.m @@ -20,6 +20,7 @@ compute_bp_grd = 0; %will GRD patterns for bottom pressures be computed? degacc = 0; %degree increment for resolution of Green tables. timeacc = 1; %time step accuracy required to compute Green tables + viscoussampling = 8; %number of samples kept before doubling spacing in the viscous memory time grid horiz = 0; %compute horizontal deformation grdmodel = 1; %grd model (0 by default, 1 for (visco-)elastic, 2 for Ivins) cross_section_shape = 0; %cross section only used when grd model is Ivins @@ -77,6 +78,7 @@ %numerical discretization accuracy self.degacc=.01; self.timeacc=1; + self.viscoussampling=8; %how many time steps we skip before we run solidearthsettings solver during transient self.runfrequency=1; @@ -107,6 +109,7 @@ function disp(self) % {{{ disp(sprintf(' resolution:')); fielddisplay(self,'degacc','spatial accuracy (default: .01 deg) for numerical discretization of the Green''s functions'); fielddisplay(self,'timeacc','time accuracy (default: 1 yr) for numerical discretization of the Green''s functions'); + fielddisplay(self,'viscoussampling','number of samples kept at each spacing before doubling the spacing in the viscous memory time grid (default: 100)'); disp(sprintf(' sea-level equation:')); fielddisplay(self,'grdocean','does this planet have an ocean, if set to 1: global water mass is conserved in GRD module (default: 1)'); fielddisplay(self,'sealevelloading','enables surface loading from sea-level change (default: 1)'); @@ -118,7 +121,7 @@ function disp(self) % {{{ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0) return; end md = checkfield(md,'fieldname','solidearth.settings.reltol','size',[1 1]); @@ -127,28 +130,29 @@ function disp(self) % {{{ md = checkfield(md,'fieldname','solidearth.settings.runfrequency','size',[1 1],'>=',1); md = checkfield(md,'fieldname','solidearth.settings.degacc','size',[1 1],'>=',1e-10); md = checkfield(md,'fieldname','solidearth.settings.timeacc','size',[1 1],'>',0); + md = checkfield(md,'fieldname','solidearth.settings.viscoussampling','size',[1 1],'>=',1); md = checkfield(md,'fieldname','solidearth.settings.horiz','NaN',1,'Inf',1,'values',[0 1]); md = checkfield(md,'fieldname','solidearth.settings.grdmodel','>=',0,'<=',2); md = checkfield(md,'fieldname','solidearth.settings.cross_section_shape','numel',[1],'values',[1,2]); - if self.elastic==1 & self.selfattraction==0, + if self.elastic==1 & self.selfattraction==0 error('solidearthsettings checkconsistency error message: need selfattraction on if elastic flag is set'); end - if self.viscous==1 & self.elastic==0, + if self.viscous==1 & self.elastic==0 error('solidearthsettings checkconsistency error message: need elastic on if viscous flag is set'); end - if self.rotation==1 & self.elastic==0, + if self.rotation==1 & self.elastic==0 error('solidearthsettings checkconsistency error message: need elastic on if rotation flag is set'); end %a GRD computation has been requested, make some checks on the nature of the meshes provided. - if self.isgrd, - if strcmpi(class(md.mesh),'mesh3dsurface'), - if self.grdmodel==2, + if self.isgrd + if strcmpi(class(md.mesh),'mesh3dsurface') + if self.grdmodel==2 error('model requires a 2D mesh to run gia Ivins computations (change mesh from mesh3dsurface to mesh2d)'); end else - if self.grdmodel==1, + if self.grdmodel==1 error('model requires a 3D surface mesh to run GRD computations (change mesh from mesh2d to mesh3dsurface)'); end end @@ -157,7 +161,7 @@ function disp(self) % {{{ end end - if self.compute_bp_grd==1 & md.solidearth.settings.isgrd==0, + if self.compute_bp_grd==1 & md.solidearth.settings.isgrd==0 error('solidearthsettings checkconsistency error message; if bottom pressure grd patterns are requested, solidearth settings class should have isgrd flag on'); end @@ -175,6 +179,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'fieldname','runfrequency','name','md.solidearth.settings.runfrequency','format','Integer'); WriteData(fid,prefix,'object',self,'fieldname','degacc','name','md.solidearth.settings.degacc','format','Double'); WriteData(fid,prefix,'object',self,'fieldname','timeacc','name','md.solidearth.settings.timeacc','format','Double','scale',md.constants.yts); + WriteData(fid,prefix,'object',self,'fieldname','viscoussampling','name','md.solidearth.settings.viscoussampling','format','Integer'); WriteData(fid,prefix,'object',self,'fieldname','horiz','name','md.solidearth.settings.horiz','format','Integer'); WriteData(fid,prefix,'object',self,'fieldname','sealevelloading','name','md.solidearth.settings.sealevelloading','format','Integer'); WriteData(fid,prefix,'object',self,'fieldname','isgrd','name','md.solidearth.settings.isgrd','format','Integer'); @@ -201,6 +206,7 @@ function savemodeljs(self,fid,modelname) % {{{ writejsdouble(fid,[modelname '.solidearth.settings.compute_bp_grd'],self.compute_bp_grd); writejsdouble(fid,[modelname '.solidearth.settings.degacc'],self.degacc); writejsdouble(fid,[modelname '.solidearth.settings.timeacc'],self.timeacc); + writejsdouble(fid,[modelname '.solidearth.settings.viscoussampling'],self.viscoussampling); writejsdouble(fid,[modelname '.solidearth.settings.horiz'],self.horiz); writejsdouble(fid,[modelname '.solidearth.settings.grdmodel'],self.grdmodel); writejsdouble(fid,[modelname '.solidearth.settings.cross_section_shape'],self.cross_section_shape); diff --git a/src/m/classes/spatiallinearbasalforcings.m b/src/m/classes/spatiallinearbasalforcings.m index 0b3107b03..6d3359c2b 100644 --- a/src/m/classes/spatiallinearbasalforcings.m +++ b/src/m/classes/spatiallinearbasalforcings.m @@ -49,7 +49,7 @@ end % }}} function self = initialize(self,md) % {{{ - if isnan(self.groundedice_melting_rate), + if isnan(self.groundedice_melting_rate) self.groundedice_melting_rate=zeros(md.mesh.numberofvertices,1); disp(' no basalforcings.groundedice_melting_rate specified: values set as zero'); end @@ -69,14 +69,14 @@ md = checkfield(md,'fieldname','basalforcings.perturbation_melting_rate','NaN',1,'Inf',1,'timeseries',1); end - if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0), + if ismember('MasstransportAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.ismasstransport==0) md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','NaN',1,'Inf',1,'timeseries',1,'>=',0); md = checkfield(md,'fieldname','basalforcings.deepwater_elevation','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.upperwater_melting_rate','NaN',1,'Inf',1,'timeseries',1,'>=',0); md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','NaN',1,'Inf',1,'timeseries',1,'<=',0); end - if ismember('BalancethicknessAnalysis',analyses), + if ismember('BalancethicknessAnalysis',analyses) error('not implemented yet!'); md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'size',[md.mesh.numberofvertices 1]); md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0,'numel',1); @@ -84,7 +84,7 @@ md = checkfield(md,'fieldname','basalforcings.upperwater_melting_rate','>=',0,'numel',1); md = checkfield(md,'fieldname','basalforcings.upperwater_elevation','<=',0,'numel',1); end - if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0), + if ismember('ThermalAnalysis',analyses) & ~(strcmp(solution,'TransientSolution') & md.transient.isthermal==0) error('not implemented yet!'); md = checkfield(md,'fieldname','basalforcings.groundedice_melting_rate','NaN',1,'Inf',1,'timeseries',1); md = checkfield(md,'fieldname','basalforcings.deepwater_melting_rate','>=',0,'numel',1); diff --git a/src/m/classes/steadystate.m b/src/m/classes/steadystate.m index 517d1c8ac..1d967b458 100644 --- a/src/m/classes/steadystate.m +++ b/src/m/classes/steadystate.m @@ -38,12 +38,12 @@ %Early return if ~strcmp(solution,'SteadystateSolution'), return; end; - if md.timestepping.time_step~=0, + if md.timestepping.time_step~=0 md = checkmessage(md,['for a steadystate computation, timestepping.time_step must be zero.']); end md = checkfield(md,'fieldname','steadystate.requested_outputs','stringrow',1); - if isnan(md.stressbalance.reltol), + if isnan(md.stressbalance.reltol) md = checkmessage(md,['for a steadystate computation, stressbalance.reltol (relative convergence criterion) must be defined!']); end end % }}} @@ -62,7 +62,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/stressbalance.m b/src/m/classes/stressbalance.m index 4ce4065ea..c94a7b71f 100644 --- a/src/m/classes/stressbalance.m +++ b/src/m/classes/stressbalance.m @@ -5,6 +5,10 @@ classdef stressbalance properties (SetAccess=public) + isemulator = 0; + module_dir = ''; + pt_name = ''; + py_name = ''; spcvx = NaN; spcvy = NaN; spcvx_base = NaN; @@ -54,7 +58,7 @@ list2 = fieldnames(inputstruct); for i=1:length(list1) fieldname = list1{i}; - if ismember(fieldname,list2), + if ismember(fieldname,list2) self.(fieldname) = inputstruct.(fieldname); end end @@ -91,6 +95,14 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ + + % CHECK EMULATOR + md = checkfield(md,'fieldname','stressbalance.isemulator','numel',[1],'values',[0 1 2]); + if self.isemulator + md = checkfield(md,'fieldname','stressbalance.module_dir','filepath',1); + md = checkfield(md,'fieldname','stressbalance.py_name','string', 1); + md = checkfield(md,'fieldname','stressbalance.pt_name','string', 1); + end %Early return if ~ismember('StressbalanceAnalysis',analyses), return; end @@ -109,28 +121,28 @@ md = checkfield(md,'fieldname','stressbalance.referential','size',[md.mesh.numberofvertices 6]); md = checkfield(md,'fieldname','stressbalance.loadingforce','size',[md.mesh.numberofvertices 3]); md = checkfield(md,'fieldname','stressbalance.requested_outputs','stringrow',1); - if ~any(isnan(md.stressbalance.vertex_pairing)), + if ~any(isnan(md.stressbalance.vertex_pairing)) md = checkfield(md,'fieldname','stressbalance.vertex_pairing','>',0); end %singular solution - if ((~(any(~isnan(md.stressbalance.spcvx)) | any(~isnan(md.stressbalance.spcvy)))) & ~any(md.mask.ocean_levelset>0)), + if ((~(any(~isnan(md.stressbalance.spcvx)) | any(~isnan(md.stressbalance.spcvy)))) & ~any(md.mask.ocean_levelset>0)) disp(sprintf('\n !!! Warning: no spc applied, model might not be well posed if no basal friction is applied, check for solution crash\n')); end %CHECK THAT EACH LINE CONTAINS ONLY NAN VALUES OR NO NAN VALUES - if any(sum(isnan(md.stressbalance.referential),2)~=0 & sum(isnan(md.stressbalance.referential),2)~=6), + if any(sum(isnan(md.stressbalance.referential),2)~=0 & sum(isnan(md.stressbalance.referential),2)~=6) md = checkmessage(md,['Each line of stressbalance.referential should contain either only NaN values or no NaN values']); end %CHECK THAT THE TWO VECTORS PROVIDED ARE ORTHOGONAL - if any(sum(isnan(md.stressbalance.referential),2)==0), + if any(sum(isnan(md.stressbalance.referential),2)==0) pos=find(sum(isnan(md.stressbalance.referential),2)==0); - if any(abs(dot(md.stressbalance.referential(pos,1:3),md.stressbalance.referential(pos,4:6),2))>eps), + if any(abs(dot(md.stressbalance.referential(pos,1:3),md.stressbalance.referential(pos,4:6),2))>eps) md = checkmessage(md,['Vectors in stressbalance.referential (columns 1 to 3 and 4 to 6) must be orthogonal']); end end %CHECK THAT NO rotation specified for FS Grounded ice at base - if strcmp(domaintype(md.mesh),'3D') & md.flowequation.isFS, + if strcmp(domaintype(md.mesh),'3D') & md.flowequation.isFS pos=find(md.mask.ocean_levelset>0. & md.mesh.vertexonbase); - if any(~isnan(md.stressbalance.referential(pos,:))), + if any(~isnan(md.stressbalance.referential(pos,:))) md = checkmessage(md,['no referential should be specified for basal vertices of grounded ice']); end md = checkfield(md,'fieldname','stressbalance.FSreconditioning','>',0); @@ -142,12 +154,13 @@ md = checkfield(md,'fieldname','stressbalance.spcvx_shear','Inf',1,'timeseries',1); md = checkfield(md,'fieldname','stressbalance.spcvy_shear','Inf',1,'timeseries',1); end + end % }}} function list=defaultoutputs(self,md) % {{{ - if dimension(md.mesh)==3, + if dimension(md.mesh)==3 list = {'Vx','Vy','Vz','Vel','Pressure'}; - elseif dimension(md.mesh)==2, + elseif dimension(md.mesh)==2 list = {'Vx','Vy','Vel','Pressure'}; else error('mesh type not supported yet'); @@ -158,6 +171,12 @@ function disp(self) % {{{ disp(sprintf(' StressBalance solution parameters:')); + disp(sprintf('\n %s','Emulator parameters:')); + fielddisplay(self,'isemulator','0: finite element (default), 1: gnn emulator, 2: hybrid (not implementd)'); + fielddisplay(self,'module_dir', 'directory of the emulator module'); + fielddisplay(self,'pt_name', 'name of the checkpoint file for pre-trained ML model'); + fielddisplay(self,'py_name', 'name of the python file that defines ML architecture'); + disp(sprintf('\n %s','Convergence criteria:')); fielddisplay(self,'restol','mechanical equilibrium residual convergence criterion'); fielddisplay(self,'reltol','velocity relative convergence criterion, NaN: not applied'); @@ -196,6 +215,12 @@ function disp(self) % {{{ end % }}} function marshall(self,prefix,md,fid) % {{{ + WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','isemulator','format','Integer'); + if self.isemulator + WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','module_dir','format','String') + WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','pt_name','format','String'); + WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','py_name','format','String'); + end WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','vertex_pairing','format','DoubleMat','mattype',3); @@ -217,7 +242,7 @@ function marshall(self,prefix,md,fid) % {{{ WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','rift_penalty_threshold','format','Integer'); WriteData(fid,prefix,'object',self,'class','stressbalance','fieldname','referential','format','DoubleMat','mattype',1); - if size(self.loadingforce,2)==3, + if size(self.loadingforce,2)==3 WriteData(fid,prefix,'data',self.loadingforce(:,1),'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcex'); WriteData(fid,prefix,'data',self.loadingforce(:,2),'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcey'); WriteData(fid,prefix,'data',self.loadingforce(:,3),'format','DoubleMat','mattype',1,'name','md.stressbalance.loadingforcez'); @@ -226,7 +251,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end @@ -259,8 +284,8 @@ function savemodeljs(self,fid,modelname) % {{{ writejs2Darray(fid,[modelname '.stressbalance.loadingforce'],self.loadingforce); writejscellstring(fid,[modelname '.stressbalance.requested_outputs'],self.requested_outputs); - writejs1Darray(fid,[modelname '.stressbalance.spcvx_base'],self.spcvx_shear); - writejs1Darray(fid,[modelname '.stressbalance.spcvy_base'],self.spcvy_shear); + writejs1Darray(fid,[modelname '.stressbalance.spcvx_base'],self.spcvx_base); + writejs1Darray(fid,[modelname '.stressbalance.spcvy_base'],self.spcvy_base); writejs1Darray(fid,[modelname '.stressbalance.spcvx_shear'],self.spcvx_shear); writejs1Darray(fid,[modelname '.stressbalance.spcvy_shear'],self.spcvy_shear); end % }}} diff --git a/src/m/classes/surfaceload.m b/src/m/classes/surfaceload.m index cc26f9baf..b6d00cf5c 100644 --- a/src/m/classes/surfaceload.m +++ b/src/m/classes/surfaceload.m @@ -27,22 +27,22 @@ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ - if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0), + if ~ismember('SealevelchangeAnalysis',analyses) | (strcmp(solution,'TransientSolution') & md.transient.isslc==0) return; end - if ~isempty(self.icethicknesschange), - if isa(self.icethicknesschange,'cell'), - for i=1:length(self.icethicknesschange), + if ~isempty(self.icethicknesschange) + if isa(self.icethicknesschange,'cell') + for i=1:length(self.icethicknesschange) md = checkfield(md,'field',self.icethicknesschange{i},'NaN',0,'Inf',1,'timeserieslength',1,'Inf',1); end else md = checkfield(md,'field',self.icethicknesschange,'NaN',1,'Inf',1,'timeserieslength',1,'Inf',1); end end - if ~isempty(self.waterheightchange), + if ~isempty(self.waterheightchange) md = checkfield(md,'fieldname','solidearth.surfaceload.waterheightchange','timeseries',1,'NaN',1,'Inf',1); end - if ~isempty(self.otherchange), + if ~isempty(self.otherchange) md = checkfield(md,'fieldname','solidearth.surfaceload.other','timeseries',1,'NaN',1,'Inf',1); end @@ -66,16 +66,16 @@ function disp(self) % {{{ function marshall(self,prefix,md,fid) % {{{ %deal with ice thickness change: {{{ - if isempty(self.icethicknesschange), + if isempty(self.icethicknesschange) self.icethicknesschange=zeros(md.mesh.numberofelements+1,1); end yts=md.constants.yts; - if isa(self.icethicknesschange,'cell'), + if isa(self.icethicknesschange,'cell') %transform our cell array of time series into cell array of time series of rates nummodels=length(self.icethicknesschange); - for i=1:nummodels, + for i=1:nummodels icethicknesschange=self.icethicknesschange{i}; time=icethicknesschange(end,:); dt=diff(time,1,2); @@ -96,14 +96,14 @@ function marshall(self,prefix,md,fid) % {{{ end %}}} %deal with water height change: {{{ - if isempty(self.waterheightchange), + if isempty(self.waterheightchange) self.waterheightchange=zeros(md.mesh.numberofelements+1,1); end - if isa(self.waterheightchange,'cell'), + if isa(self.waterheightchange,'cell') %transform our cell array of time series into cell array of time series of rates nummodels=length(self.waterheightchange); - for i=1:nummodels, + for i=1:nummodels waterheightchange=self.waterheightchange{i}; time=waterheightchange(end,:); dt=diff(time,1,2); @@ -124,14 +124,14 @@ function marshall(self,prefix,md,fid) % {{{ end %}}} %deal with other: {{{ - if isempty(self.otherchange), + if isempty(self.otherchange) self.otherchange=zeros(md.mesh.numberofelements+1,1); end - if isa(self.otherchange,'cell'), + if isa(self.otherchange,'cell') %transform our cell array of time series into cell array of time series of rates nummodels=length(self.otherchange); - for i=1:nummodels, + for i=1:nummodels otherchange=self.otherchange{i}; time=otherchange(end,:); dt=diff(time,1,2); diff --git a/src/m/classes/taoinversion.m b/src/m/classes/taoinversion.m index 1b1bf8ea5..02573af2e 100644 --- a/src/m/classes/taoinversion.m +++ b/src/m/classes/taoinversion.m @@ -85,7 +85,7 @@ %Early return if ~self.iscontrol, return; end - if ~IssmConfig('_HAVE_TAO_'), + if ~IssmConfig('_HAVE_TAO_') md = checkmessage(md,['TAO has not been installed, ISSM needs to be reconfigured and recompiled with TAO']); end diff --git a/src/m/classes/thermal.m b/src/m/classes/thermal.m index 099ee6bd4..41716c426 100644 --- a/src/m/classes/thermal.m +++ b/src/m/classes/thermal.m @@ -22,7 +22,7 @@ methods function self = extrude(self,md) % {{{ self.spctemperature=project3d(md,'vector',self.spctemperature,'type','node','layer',md.mesh.numberoflayers,'padding',NaN); - if (length(md.initialization.temperature)==md.mesh.numberofvertices), + if (length(md.initialization.temperature)==md.mesh.numberofvertices) self.spctemperature=NaN(md.mesh.numberofvertices,1); pos=find(md.mesh.vertexonsurface); self.spctemperature(pos)=md.initialization.temperature(pos); %impose observed temperature on surface @@ -38,7 +38,7 @@ end % }}} function list = defaultoutputs(self,md) % {{{ - if self.isenthalpy, + if self.isenthalpy list = {'Enthalpy','Temperature','Waterfraction','Watercolumn','BasalforcingsGroundediceMeltingRate'}; else list = {'Temperature','BasalforcingsGroundediceMeltingRate'}; @@ -68,7 +68,7 @@ %will basal boundary conditions be set dynamically self.isdynamicbasalspc=0; - %wether waterfraction drainage is enabled + %whether waterfraction drainage is enabled self.isdrainicecolumn=1; %set an upper limit for local stored watercolumn @@ -88,7 +88,7 @@ md = checkfield(md,'fieldname','thermal.stabilization','numel',[1],'values',[0 1 2 3]); md = checkfield(md,'fieldname','thermal.spctemperature','Inf',1,'timeseries',1,'>=',0); md = checkfield(md,'fieldname','thermal.fe','values',{'P1','P1xP2','P1xP3'}); - if (ismember('EnthalpyAnalysis',analyses) & md.thermal.isenthalpy & dimension(md.mesh)==3), + if (ismember('EnthalpyAnalysis',analyses) & md.thermal.isenthalpy & dimension(md.mesh)==3) md = checkfield(md,'fieldname','thermal.isdrainicecolumn','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','thermal.watercolumn_upperlimit','>=',0); @@ -103,7 +103,7 @@ md = checkfield(md,'fieldname','thermal.isenthalpy','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','thermal.isdynamicbasalspc','numel', [1],'values',[0 1]); if(md.thermal.isenthalpy) - if isnan(md.stressbalance.reltol), + if isnan(md.thermal.reltol) md = checkmessage(md,['for a steadystate computation, thermal.reltol (relative convergence criterion) must be defined!']); end md = checkfield(md,'fieldname','thermal.reltol','>',0.,'message','reltol must be larger than zero'); @@ -124,7 +124,7 @@ function disp(self) % {{{ fielddisplay(self,'penalty_factor','scaling exponent (default is 3)'); fielddisplay(self,'isenthalpy','use an enthalpy formulation to include temperate ice (default is 0)'); fielddisplay(self,'isdynamicbasalspc','enable dynamic setting of basal forcing. required for enthalpy formulation (default is 0)'); - fielddisplay(self,'isdrainicecolumn','wether waterfraction drainage is enabled for enthalpy formulation (default is 1)'); + fielddisplay(self,'isdrainicecolumn','whether waterfraction drainage is enabled for enthalpy formulation (default is 1)'); fielddisplay(self,'watercolumn_upperlimit','upper limit of basal watercolumn for enthalpy formulation (default is 1000m)'); fielddisplay(self,'fe','Finite Element type: ''P1'' (default), ''P1xP2'''); fielddisplay(self,'requested_outputs','additional outputs requested'); @@ -147,7 +147,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/thermal.py b/src/m/classes/thermal.py index f9aedfe9a..32121be73 100644 --- a/src/m/classes/thermal.py +++ b/src/m/classes/thermal.py @@ -40,7 +40,7 @@ def __repr__(self): # {{{ s += '{}\n'.format(fielddisplay(self, 'penalty_threshold', 'threshold to declare convergence of thermal solution (default is 0)')) s += '{}\n'.format(fielddisplay(self, 'isenthalpy', 'use an enthalpy formulation to include temperate ice (default is 0)')) s += '{}\n'.format(fielddisplay(self, 'isdynamicbasalspc', 'enable dynamic setting of basal forcing. required for enthalpy formulation (default is 0)')) - s += '{}\n'.format(fielddisplay(self, 'isdrainicecolumn', 'wether waterfraction drainage is enabled for enthalpy formulation (default is 1)')) + s += '{}\n'.format(fielddisplay(self, 'isdrainicecolumn', 'whether waterfraction drainage is enabled for enthalpy formulation (default is 1)')) s += '{}\n'.format(fielddisplay(self, 'watercolumn_upperlimit', 'upper limit of basal watercolumn for enthalpy formulation (default is 1000m)')) s += '{}\n'.format(fielddisplay(self, 'fe', 'Finite Element type: ''P1'' (default), ''P1xP2''')) s += '{}\n'.format(fielddisplay(self, 'requested_outputs', 'additional outputs requested')) @@ -78,7 +78,7 @@ def setdefaultparameters(self): # {{{ self.isenthalpy = 0 #will basal boundary conditions be set dynamically self.isdynamicbasalspc = 0 - #wether waterfraction drainage is enabled + #whether waterfraction drainage is enabled self.isdrainicecolumn = 1 #set an upper limit for local stored watercolumn self.watercolumn_upperlimit = 1000 @@ -114,7 +114,7 @@ def checkconsistency(self, md, solution, analyses): # {{{ md = checkfield(md, 'fieldname', 'thermal.isenthalpy', 'numel', [1], 'values', [0, 1]) md = checkfield(md, 'fieldname', 'thermal.isdynamicbasalspc', 'numel', [1], 'values', [0, 1]) if(md.thermal.isenthalpy): - if np.isnan(md.stressbalance.reltol): + if np.isnan(md.thermal.reltol): md.checkmessage("for a steadystate computation, thermal.reltol (relative convergence criterion) must be defined!") md = checkfield(md, 'fieldname', 'thermal.reltol', '>', 0., 'message', "reltol must be larger than zero") return md diff --git a/src/m/classes/timestepping.m b/src/m/classes/timestepping.m index 77970fd6d..51ca7e5af 100644 --- a/src/m/classes/timestepping.m +++ b/src/m/classes/timestepping.m @@ -58,10 +58,10 @@ function disp(self) % {{{ md = checkfield(md,'fieldname','timestepping.interp_forcing','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','timestepping.average_forcing','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','timestepping.cycle_forcing','numel',[1],'values',[0 1]); - if self.final_time-self.start_time<0, + if self.final_time-self.start_time<0 md = checkmessage(md,'timestepping.final_time should be larger than timestepping.start_time'); end - if strcmp(solution,'TransientSolution'), + if strcmp(solution,'TransientSolution') md = checkfield(md,'fieldname','timestepping.time_step','numel',[1],'>',0,'NaN',1,'Inf',1); end end % }}} @@ -83,7 +83,7 @@ function savemodeljs(self,fid,modelname) % {{{ writejsdouble(fid,[modelname '.timestepping.final_time'],self.final_time); writejsdouble(fid,[modelname '.timestepping.time_step'],self.time_step); writejsdouble(fid,[modelname '.timestepping.interp_forcing'],self.interp_forcing); - writejsdouble(fid,[modelname '.timestepping.average_forcing'],self.interp_forcing); + writejsdouble(fid,[modelname '.timestepping.average_forcing'],self.average_forcing); writejsdouble(fid,[modelname '.timestepping.cycle_forcing'],self.cycle_forcing); end % }}} diff --git a/src/m/classes/timesteppingadaptive.m b/src/m/classes/timesteppingadaptive.m index b7e18dd1a..fba8fab8d 100644 --- a/src/m/classes/timesteppingadaptive.m +++ b/src/m/classes/timesteppingadaptive.m @@ -54,7 +54,7 @@ md = checkfield(md,'fieldname','timestepping.average_forcing','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','timestepping.cycle_forcing','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','timestepping.coupling_time','numel',[1],'>=',md.timestepping.coupling_time,'NaN',1,'Inf',1); - if self.final_time-self.start_time<0, + if self.final_time-self.start_time<0 md = checkmessage(md,'timestepping.final_time should be larger than timestepping.start_time'); end end % }}} @@ -95,9 +95,9 @@ function savemodeljs(self,fid,modelname) % {{{ writejsdouble(fid,[modelname '.timesteppingadaptive.time_step_max'],self.time_step_max); writejsdouble(fid,[modelname '.timesteppingadaptive.cfl_coefficient'],self.cfl_coefficient); writejsdouble(fid,[modelname '.timesteppingadaptive.interp_forcing'],self.interp_forcing); - writejsdouble(fid,[modelname '.timesteppingadaptive.average_forcing'],self.interp_forcing); + writejsdouble(fid,[modelname '.timesteppingadaptive.average_forcing'],self.average_forcing); writejsdouble(fid,[modelname '.timesteppingadaptive.cycle_forcing'],self.cycle_forcing); - writejsdouble(fid,[modelname '.timesteppingadaptive.coupling_time'],self.time_step_max); + writejsdouble(fid,[modelname '.timesteppingadaptive.coupling_time'],self.coupling_time); end % }}} end diff --git a/src/m/classes/toolkits.m b/src/m/classes/toolkits.m index 408463b0d..a0b38d43b 100644 --- a/src/m/classes/toolkits.m +++ b/src/m/classes/toolkits.m @@ -41,12 +41,12 @@ % md.toolkits=addoptions(md.toolkits,'StressbalanceAnalysis'); %Create dynamic property if property does not exist yet - if ~ismember(analysis,properties(self)), + if ~ismember(analysis,properties(self)) self.addprop(analysis); end %Add toolkits options to analysis - if nargin==3, + if nargin==3 self.(analysis) = varargin{1}; end end @@ -54,17 +54,17 @@ function self = setdefaultparameters(self) % {{{ %default toolkits: - if IssmConfig('_HAVE_PETSC_'), + if IssmConfig('_HAVE_PETSC_') %MUMPS is the default toolkits - if IssmConfig('_HAVE_MUMPS_'), + if IssmConfig('_HAVE_MUMPS_') self.DefaultAnalysis = mumpsoptions(); else self.DefaultAnalysis = iluasmoptions(); end else - if IssmConfig('_HAVE_MUMPS_'), + if IssmConfig('_HAVE_MUMPS_') self.DefaultAnalysis = issmmumpssolver(); - elseif IssmConfig('_HAVE_GSL_'), + elseif IssmConfig('_HAVE_GSL_') self.DefaultAnalysis = issmgslsolver(); else disp('WARNING: Need at least MUMPS or GSL to define an ISSM solver type, no default solver assigned'); @@ -79,7 +79,7 @@ function disp(self) % {{{ analyses=properties(self); disp(sprintf('List of toolkits options per analysis:\n')); - for i=1:numel(analyses), + for i=1:numel(analyses) analysis=analyses{i}; disp([analysis ':']); disp(self.(analysis)); @@ -87,7 +87,7 @@ function disp(self) % {{{ end % }}} function md = checkconsistency(self,md,solution,analyses) % {{{ analyses=properties(self); - for i=1:numel(analyses), + for i=1:numel(analyses) switch analyses{i} case 'DefaultAnalysis' case 'RecoveryAnalysis' @@ -131,7 +131,7 @@ function ToolkitsFile(toolkits,filename) % {{{ %open file for writing fid=fopen(filename,'w'); - if fid==-1, + if fid==-1 error(['ToolkitsFile error: could not open ' filename ' for writing']); end @@ -140,7 +140,7 @@ function ToolkitsFile(toolkits,filename) % {{{ %start writing options analyses=properties(toolkits); - for i=1:numel(analyses), + for i=1:numel(analyses) analysis=analyses{i}; options=toolkits.(analysis); @@ -149,18 +149,18 @@ function ToolkitsFile(toolkits,filename) % {{{ %now, write options optionslist=fieldnames(options); - for j=1:numel(optionslist), + for j=1:numel(optionslist) optionname=optionslist{j}; optionvalue=options.(optionname); - if isempty(optionvalue), + if isempty(optionvalue) %this option has only one argument fprintf(fid,'-%s\n',optionname); else %option with value. value can be string or scalar - if isnumeric(optionvalue), + if isnumeric(optionvalue) fprintf(fid,'-%s %g\n',optionname,optionvalue); - elseif ischar(optionvalue), + elseif ischar(optionvalue) fprintf(fid,'-%s %s\n',optionname,optionvalue); else error(['ToolkitsFile error: option ' optionname ' is not well formatted']); @@ -174,7 +174,7 @@ function ToolkitsFile(toolkits,filename) % {{{ function savemodeljs(self,fid,modelname) % {{{ analyses=properties(self); - for i=1:numel(analyses), + for i=1:numel(analyses) if isempty(fieldnames(self.(analyses{i}))) error(['md.toolkits.' analyses{i} ' is empty']); else diff --git a/src/m/classes/transient.m b/src/m/classes/transient.m index aa9fca68c..983aac978 100644 --- a/src/m/classes/transient.m +++ b/src/m/classes/transient.m @@ -108,10 +108,10 @@ md = checkfield(md,'fieldname','transient.issampling','numel',[1],'values',[0 1]); md = checkfield(md,'fieldname','transient.amr_frequency','numel',[1],'>=',0,'NaN',1,'Inf',1); - if (~strcmp(solution,'TransientSolution') & md.transient.iscoupling==1), + if (~strcmp(solution,'TransientSolution') & md.transient.isoceancoupling==1) md = checkmessage(md,['Coupling with ocean model can only be performed for transient simulations!']); end - if (md.transient.isdamageevolution & ~isa(md.materials,'matdamageice')), + if (md.transient.isdamageevolution & ~isa(md.materials,'matdamageice')) md = checkmessage(md,['requesting damage evolution but md.materials is not of class matdamageice']); end end % }}} @@ -160,7 +160,7 @@ function marshall(self,prefix,md,fid) % {{{ %process requested outputs outputs = self.requested_outputs; pos = find(ismember(outputs,'default')); - if ~isempty(pos), + if ~isempty(pos) outputs(pos) = []; %remove 'default' from outputs outputs = [outputs defaultoutputs(self,md)]; %add defaults end diff --git a/src/m/classes/transient.py b/src/m/classes/transient.py index b43410940..d9c4d3d3f 100644 --- a/src/m/classes/transient.py +++ b/src/m/classes/transient.py @@ -136,7 +136,7 @@ def checkconsistency(self, md, solution, analyses): # {{{ md = checkfield(md, 'fieldname', 'transient.isoceancoupling', 'numel', [1], 'values', [0, 1, 2]) md = checkfield(md, 'fieldname', 'transient.amr_frequency', 'numel', [1], '>=', 0, 'NaN', 1, 'Inf', 1) - if solution != 'TransientSolution' and md.transient.iscoupling: + if solution != 'TransientSolution' and md.transient.isoceancoupling: md.checkmessage("Coupling with ocean can only be done in transient simulations!") if md.transient.isdamageevolution and not hasattr(md.materials, 'matdamageice'): md.checkmessage("requesting damage evolution but md.materials is not of class matdamageice") diff --git a/src/m/classes/verbose.m b/src/m/classes/verbose.m index a941f6b4f..23f510cf4 100644 --- a/src/m/classes/verbose.m +++ b/src/m/classes/verbose.m @@ -48,8 +48,8 @@ verbose.control=true; case 1, binary=varargin{1}; - if ischar(binary), - if strcmpi(binary,'all'), + if ischar(binary) + if strcmpi(binary,'all') binary=2^11-1; %all ones verbose=BinaryToVerbose(verbose,binary); verbose.solver=false; %Do not use by default @@ -57,7 +57,7 @@ binary=bin2dec(binary); verbose=BinaryToVerbose(verbose,binary); end - elseif isnumeric(binary), + elseif isnumeric(binary) verbose=BinaryToVerbose(verbose,binary); end otherwise, @@ -66,10 +66,10 @@ %Cast to logicals listproperties=properties('verbose'); - for i=1:numel(listproperties), + for i=1:numel(listproperties) fieldname=listproperties{i}; fieldvalue=verbose.(fieldname); - if (islogical(fieldvalue) | isnumeric(fieldvalue)) & numel(fieldvalue)==1, + if (islogical(fieldvalue) | isnumeric(fieldvalue)) & numel(fieldvalue)==1 verbose.(fieldname)=logical(fieldvalue); else error('verbose supported field values are logicals only (true or false)'); diff --git a/src/m/consistency/QueueRequirements.m b/src/m/consistency/QueueRequirements.m index 07060fba1..1585de36d 100644 --- a/src/m/consistency/QueueRequirements.m +++ b/src/m/consistency/QueueRequirements.m @@ -6,14 +6,14 @@ function QueueRequirements(available_queues,queue_requirements_time,queue_requir %Ok, go through requirements for current queue: index=ismemberi(queue,available_queues); -if ~index, +if ~index %ok, either we a generic cluster, with 'none' queue, or we could not find the queue requirements - if strcmpi(available_queues{1},'none'), + if strcmpi(available_queues{1},'none') %reset index to 1, so we can fish the requirements index=1; else string=available_queues{1}; - for i=2:length(available_queues), + for i=2:length(available_queues) string=[string ' ' available_queues{i}]; end error(['QueueRequirements error message: available queues are ' string]); @@ -22,14 +22,14 @@ function QueueRequirements(available_queues,queue_requirements_time,queue_requir %check on time requirements rtime=queue_requirements_time(index); -if time<=0, +if time<=0 error('QueueRequirements: time should be a positive number'); end -if time>rtime, +if time>rtime error(['QueueRequirements: time should be < ' num2str(rtime) ' for queue: ' queue]); end %check on np requirements -if np<=0, +if np<=0 error('QueueRequirements: np should be a positive number'); end diff --git a/src/m/consistency/checkfield.m b/src/m/consistency/checkfield.m index ffcc6ed1b..b8d721b2f 100644 --- a/src/m/consistency/checkfield.m +++ b/src/m/consistency/checkfield.m @@ -19,6 +19,7 @@ % - numel: list of acceptable number of elements % - cell: 1 if check that is cell % - empty: 1 if check that non empty +% - filepath: 1 if check file exists % - message: overloaded error message % % Usage: @@ -106,7 +107,7 @@ %Check numel if exist(options,'numel') fieldnumel=getfieldvalue(options,'numel'); - if ~ismember(numel(field),fieldnumel), + if ~ismember(numel(field),fieldnumel) if length(fieldnumel)==1 md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' size should be ' sprintf('%g ',fieldnumel) ])); @@ -148,8 +149,8 @@ if exist(options,'values') fieldvalues=getfieldvalue(options,'values'); if iscell(fieldvalues) %strings - if ischar(field) | iscell(fieldvalues), - if any(~ismember(field,fieldvalues)), + if ischar(field) | iscell(fieldvalues) + if any(~ismember(field,fieldvalues)) if length(fieldvalues)==1 md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' value should be ''' fieldvalues{1} ''''])); @@ -168,7 +169,7 @@ else field2=field(:); if isnumeric(field) - if any(~ismember(field2,fieldvalues)), + if any(~ismember(field2,fieldvalues)) md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' should have values in [' num2str(fieldvalues) ']'])); end @@ -186,7 +187,7 @@ if getfieldvalue(options,'timeseries',0), field2=reshape(field(1:end-1,:),prod(size(field(1:end-1,:))),1); end if getfieldvalue(options,'singletimeseries',0), field2=reshape(field(1,:),prod(size(field(1,:))),1); end if getfieldvalue(options,'mappedtimeseries',0), field2=reshape(field(1:end-1,:),prod(size(field(1:end-1,:))),1); end - if any(field2upperbound), + if any(field2>upperbound) md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' should have values below ' num2str(upperbound(1,1))])); end @@ -221,7 +222,7 @@ if getfieldvalue(options,'timeseries',0), field2=reshape(field(1:end-1,:),prod(size(field(1:end-1,:))),1); end if getfieldvalue(options,'singletimeseries',0), field2=reshape(field(1,:),prod(size(field(1,:))),1); end if getfieldvalue(options,'mappedtimeseries',0), field2=reshape(field(1:end-1,:),prod(size(field(1:end-1,:))),1); end - if any(field2>=upperbound), + if any(field2>=upperbound) md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' should have values below ' num2str(upperbound(1,1))])); end @@ -233,12 +234,12 @@ md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' should have only one row'])); end - if ~iscell(field), + if ~iscell(field) md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' should be a cell of strings'])); else - for i=1:size(field,2), - if ~ischar(field{i}), + for i=1:size(field,2) + if ~ischar(field{i}) md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' values should a cell of chars'])); end @@ -247,7 +248,7 @@ end %check file -if getfieldvalue(options,'file',0), +if getfieldvalue(options,'file',0) if ~exist(field,'file') md = checkmessage(md,['file provided in ''' fieldname ''': ''' field ''' does not exist']); end @@ -255,13 +256,13 @@ %Check forcings (size and times) if getfieldvalue(options,'timeseries',0) - if (size(field,1)==md.mesh.numberofvertices | size(field,1)==md.mesh.numberofelements), + if (size(field,1)==md.mesh.numberofvertices | size(field,1)==md.mesh.numberofelements) if size(field,2)~=1 md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' should have only one column as there are md.mesh.numberofvertices lines'])); end elseif (size(field,1)==md.mesh.numberofvertices+1 | size(field,1)==md.mesh.numberofelements+1) - if any(field(end,:)~=sort(field(end,:))), + if any(field(end,:)~=sort(field(end,:))) md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' columns should be sorted chronologically'])); end @@ -299,7 +300,7 @@ %Check mapped forcings (size and times) if getfieldvalue(options,'mappedtimeseries',0) - if any(field(end,:)~=sort(field(end,:))), + if any(field(end,:)~=sort(field(end,:))) md = checkmessage(md,getfieldvalue(options,'message',... ['field ''' fieldname ''' columns should be sorted chronologically'])); end @@ -308,3 +309,27 @@ ['field ''' fieldname ''' columns must not contain duplicate timesteps'])); end end + +%Check filepath +if getfieldvalue(options,'filepath',0) + if ~ischar(field) + md = checkmessage(md,getfieldvalue(options,'message',... + ['field ''' fieldname ''' should be a file path (char)'])); + else + if ~exist(field, 'file') + md = checkmessage(md,getfieldvalue(options,'message',... + ['field ''' fieldname ''' file does not exist'])); + end + end +end + +%Check scalar string +if getfieldvalue(options,'string',0) + if ~ischar(field) + md = checkmessage(md,getfieldvalue(options,'message',... + ['field ''' fieldname ''' should be a string'])); + elseif size(field,1)~=1 + md = checkmessage(md,getfieldvalue(options,'message',... + ['field ''' fieldname ''' should have only one row'])); + end +end diff --git a/src/m/consistency/comparemodels.m b/src/m/consistency/comparemodels.m index ca126926f..cd7fa2536 100644 --- a/src/m/consistency/comparemodels.m +++ b/src/m/consistency/comparemodels.m @@ -2,7 +2,7 @@ %loop over model fields model_fields=fieldnames(md1); - for i=1:length(model_fields), + for i=1:length(model_fields) field1=md1.(model_fields{i}); field2=md2.(model_fields{i}); if isobject(field1), %recursive call @@ -11,7 +11,7 @@ continue; end object_fields=fieldnames(md1.(model_fields{i})); - for j=1:length(object_fields), + for j=1:length(object_fields) field1=md1.(model_fields{i}).(object_fields{j}); field2=md2.(model_fields{i}).(object_fields{j}); compare([model_fields{i} '.' object_fields{j}],field1,field2); @@ -24,16 +24,16 @@ end function compare(fieldname,field1,field2), - if any(size(field1)~=size(field2)), + if any(size(field1)~=size(field2)) disp([fieldname ' do not have the same size']); elseif isnumeric(field1) - if numel(field1)==1 & isnan(field1) & isnan(field2), + if numel(field1)==1 & isnan(field1) & isnan(field2) %Do not do anything elseif any(field1(:)~=field2(:)) %Deal with NaN... pos1=find(isnan(field1)); pos2=find(isnan(field2)); - if numel(pos1)==numel(pos2) & all(pos1==pos2), + if numel(pos1)==numel(pos2) & all(pos1==pos2) field1(pos1)=0; field2(pos2)=0; if any(field1(:)~=field2(:)) disp([fieldname ' differs']); diff --git a/src/m/consistency/ismodelselfconsistent.m b/src/m/consistency/ismodelselfconsistent.m index ff54c8caa..0153f0709 100644 --- a/src/m/consistency/ismodelselfconsistent.m +++ b/src/m/consistency/ismodelselfconsistent.m @@ -17,7 +17,7 @@ function ismodelselfconsistent(md) field=fields{i}; %Some properties do not need to be checked - if ismember(field,{'results' 'debug' 'radaroverlay'}), + if ismember(field,{'results' 'debug' 'radaroverlay'}) continue; end diff --git a/src/m/contrib/chenggong/dataprocessing/expxy2shpll.m b/src/m/contrib/chenggong/dataprocessing/expxy2shpll.m index e4346cf46..e45fecbed 100644 --- a/src/m/contrib/chenggong/dataprocessing/expxy2shpll.m +++ b/src/m/contrib/chenggong/dataprocessing/expxy2shpll.m @@ -14,12 +14,12 @@ function expxy2shpll(expfilename,shpfilename,geometry) %check file extensions [pathstr,name,ext] = fileparts(shpfilename); -if ~strcmp(ext,'.shp'), +if ~strcmp(ext,'.shp') error(['Shapefile ' shpfilename ' does not have an extension .shp']); end [pathstr,name,ext] = fileparts(expfilename); -if ~strcmp(ext,'.exp'), +if ~strcmp(ext,'.exp') error(['Exp file ' expfilename ' does not have an extension .exp']); end @@ -32,7 +32,7 @@ function expxy2shpll(expfilename,shpfilename,geometry) count=1; contours=struct([]); -for i=1:length(shp), +for i=1:length(shp) if nargin < 3 %TEMP @@ -50,7 +50,7 @@ function expxy2shpll(expfilename,shpfilename,geometry) elseif length(shp(i).x) < 3 geometry = 'Line'; else - if (shp(i).x(end)==shp(i).x(1) && shp(i).y(end)==shp(i).y(1)), + if (shp(i).x(end)==shp(i).x(1) && shp(i).y(end)==shp(i).y(1)) geometry = 'Polygon'; else geometry = 'Line'; diff --git a/src/m/contrib/chenggong/dataprocessing/integrateOverDomain.m b/src/m/contrib/chenggong/dataprocessing/integrateOverDomain.m index 2313abfe2..0d528dd01 100644 --- a/src/m/contrib/chenggong/dataprocessing/integrateOverDomain.m +++ b/src/m/contrib/chenggong/dataprocessing/integrateOverDomain.m @@ -13,8 +13,8 @@ masked = masked | isnan(data) | isnan(weights); % Set the area with masked=1 to nan -data(masked) = nan; -weights(masked) =nan; +data(masked) = 0; +weights(masked) =0; % get the mesh diff --git a/src/m/contrib/chenggong/modeldata/interpdH.m b/src/m/contrib/chenggong/modeldata/interpdH.m index d1192c9c8..859912a1c 100644 --- a/src/m/contrib/chenggong/modeldata/interpdH.m +++ b/src/m/contrib/chenggong/modeldata/interpdH.m @@ -43,6 +43,7 @@ % load dH data = ncread(ncdata, 'dhdt_vol', [idx_min, idy_min, idt_min], [idx_max-idx_min+1, idy_max-idy_min+1, idt_max-idt_min+1], [1,1,1]); +data(data <= -9999) = nan; % Convert to ice_levelset values dH = zeros(numel(X)+1, numel(t)); @@ -50,3 +51,9 @@ for i = 1:numel(t) dH(1:end-1, i) = InterpFromGrid(x, y, data(:,:,i)', X, Y,'nearest'); end + +% crop anything outside the data domain +pos = find(X>max(x) | (Xmax(y) | (Y ice m yr-1 + + temp_time = double(ncread(smb_file{i},'time')); + temp_matrix_time = cat(1,temp_matrix_time, temp_time); % concatenate time series + + % Now, interpolate SMB + for j = 1:size(smb_data,3) + temp_smb = InterpFromGridToMesh(x_n,y_n,smb_data(:,:,j)',md.mesh.x,md.mesh.y,NaN); + + % Concatenate dataset + temp_matrix_smb = [temp_matrix_smb, temp_smb]; + clear temp_smb; + end + end + + clear smb_data, x_n, y_n; + + % convert days in year decimal + %FIXME: standard calendar for time is 365 days in year (with noleap)? + temp_matrix_time = temp_matrix_time/365 + 1850; + if size(temp_matrix_time,2) == 1 + temp_matrix_time = transpose(temp_matrix_time); + end + + % Save data + smb = SMBforcing(); + smb.mass_balance = [temp_matrix_smb; temp_matrix_time']; +end + +function smb_file = search_forcing_file(datadir, modelname, scenario, start_time, end_time) % {{{ + %{ + %Explain + %------- + % Return specific file names... + % + %Example + %------- + %.. code-block:: matlab + % smb_file = search_filenames(datadir, 'cesm2-waccm', 'ssp585') + % + %Parameters + %---------- + %datadir: str + % + %modelname: str + % + %scenario: str + % Scenarios in CMIP6 (ssp126, ssp585, ssp370) + % + %start_time, end_time: int + % Start and final year for searching files + % + %Returns + %------- + %smb_file: cell with strings + % SMB forcing files, respectively. + %} + + modelname = lower(modelname); + + switch modelname + case 'obs' + %FIXME: Assign smb file lists. + error('Not supported yet. We do not find any observation data set for SMB.'); + + case 'cesm2-waccm' + %FIXME: SDBN1 now is replaced with SDBN1-2000m or SDBN1-8000m. These search logic should be changed according to ISMIP7 repository. + smb_file_hist = dir(fullfile(datadir,'CESM2-WACCM','historical','SDBN1/acabf/v2/acabf*.nc')); + smb_file_proj = dir(fullfile(datadir,'CESM2-WACCM',scenario,'SDBN1/acabf/v2/acabf*.nc')); + + [~,pos]=sort({smb_file_hist.name}); + smb_file_hist = smb_file_hist(pos); + [~,pos]=sort({smb_file_proj.name}); + smb_file_proj = smb_file_proj(pos); + + smb_file = cat(1,smb_file_hist, smb_file_proj); + + % Choose specific year + %NOTE: + %File format: acabf_AIS_CESM2-WACCM_historical_SDBN1_v2_2014.nc + years = [start_time:1:end_time]; + + pos = zeros(numel(smb_file),1); + for i = 1:numel(smb_file) + tmp_year = strsplit(smb_file(i).name,'_'); + tmp_year = tmp_year{7}; + tmp_year = split(tmp_year,'.nc'); + tmp_year = str2int(tmp_year{1}); + + % Now, check this find in years + if any(years == tmp_year) + pos(i) = 1; + end + end + smb_file = smb_file(find(pos)); + + % Recover file names in cell. + smb_file = fullfile({smb_file.folder},{smb_file.name}); + + otherwise + error('Error: not implemented yet.'); + end +end % }}} diff --git a/src/m/contrib/larour/applyqgisstyle.m b/src/m/contrib/larour/applyqgisstyle.m index fd217ccad..0e39d7bb2 100644 --- a/src/m/contrib/larour/applyqgisstyle.m +++ b/src/m/contrib/larour/applyqgisstyle.m @@ -4,17 +4,17 @@ [path,name,ext]=fileparts(filename); %New name: - if isempty(path), + if isempty(path) newname=[name '.qml']; else newname=[path '/' name '.qml']; end - if strcmpi(type,'mesh'), + if strcmpi(type,'mesh') system(['cp /Users/larour/issm-jpl/usr/larour/Qgis/Mesh.qml ' newname]); - elseif strcmpi(type,'line'), + elseif strcmpi(type,'line') system(['cp /Users/larour/issm-jpl/usr/larour/Qgis/LineStyle.qml ' newname]); - elseif strcmpi(type,'point'), + elseif strcmpi(type,'point') system(['cp /Users/larour/issm-jpl/usr/larour/Qgis/SummitStyle.qml ' newname]); else error(['applyqgisstyle error message: ' type ' style not supported yet']); diff --git a/src/m/contrib/larour/confidenceintervals.m b/src/m/contrib/larour/confidenceintervals.m index 8206d63a9..7618e2f73 100644 --- a/src/m/contrib/larour/confidenceintervals.m +++ b/src/m/contrib/larour/confidenceintervals.m @@ -4,7 +4,7 @@ nods=size(h,1); nbins=size(h,2); %make sure h is one column smaller than x - if size(x,2) ~= (size(h,2)+1), + if size(x,2) ~= (size(h,2)+1) error('x should be one column larger than the histogram'); end diff --git a/src/m/contrib/larour/contouradjust.m b/src/m/contrib/larour/contouradjust.m index d299badad..e17fa3105 100644 --- a/src/m/contrib/larour/contouradjust.m +++ b/src/m/contrib/larour/contouradjust.m @@ -6,20 +6,20 @@ newxi=xi; newyi=yi; - for i=1:length(xi)-1, + for i=1:length(xi)-1 x1=xi(i); y1=yi(i); x2=xi(i+1); y2=yi(i+1); %is there in x and y someone on the segments [x1,y1][x2,y2] newx=[]; newy=[]; - for j=1:length(x), - if pointonsegment(x1,y1,x2,y2,x(j),y(j)), + for j=1:length(x) + if pointonsegment(x1,y1,x2,y2,x(j),y(j)) newx(end+1,1)=x(j); newy(end+1,1)=y(j); end end plot(newx,newy,'k*'); xlim(xl),ylim(yl); - if ~isempty(newx), + if ~isempty(newx) %ok, we have found points on this segment, need to order them: distance=sqrt((newx-x1).^2+(newy-y1).^2); distance diff --git a/src/m/contrib/larour/converttopowerof2.m b/src/m/contrib/larour/converttopowerof2.m index 39fdb84f6..2785517ab 100644 --- a/src/m/contrib/larour/converttopowerof2.m +++ b/src/m/contrib/larour/converttopowerof2.m @@ -4,7 +4,7 @@ function converttopowerof2(tiffname,pngname) % Usage: converttopowerof2('temp.tif','temp.png') % - if ismac, + if ismac dyld_library_path_old=getenv('DYLD_LIBRARY_PATH'); setenv('DYLD_LIBRARY_PATH','/opt/local/lib:/usr/lib'); end diff --git a/src/m/contrib/larour/diagnostics.m b/src/m/contrib/larour/diagnostics.m index 85723039f..49285153e 100644 --- a/src/m/contrib/larour/diagnostics.m +++ b/src/m/contrib/larour/diagnostics.m @@ -28,19 +28,19 @@ function diagnostics(md,varargin) path=getfieldvalue(options,'path','./'); %mesh: - if getfieldvalue(options,'mesh',0), + if getfieldvalue(options,'mesh',0) mesh2shp(md,[path '/mesh']); end %grounding line : - if getfieldvalue(options,'gl',0), + if getfieldvalue(options,'gl',0) contours=isoline(md,md.mask.ocean_levelset); expwrite(contours,[path '/groundingline.exp']); exp2shp([path '/groundingline.shp'],[path '/groundingline.exp']); end %velocity: - if exist(options,'vel'), + if exist(options,'vel') vel=getfieldvalue(options,'vel',md.initialization.vel); xposting=getfieldvalue(options,'velposting',500); yposting=getfieldvalue(options,'velposting',500); @@ -61,7 +61,7 @@ function diagnostics(md,varargin) end %hot spots: - if getfieldvalue(options,'hotspots',0), + if getfieldvalue(options,'hotspots',0) threshold=getfieldvalue(options,'threshold',5000); i=getfieldvalue(options,'hotspotsi',length(md.results.TransientSolution)); pos=find(md.results.TransientSolution(i).Vel>threshold); diff --git a/src/m/contrib/larour/ecco/MeltingGroundingLines.m b/src/m/contrib/larour/ecco/MeltingGroundingLines.m index 512313c13..1a93e6241 100644 --- a/src/m/contrib/larour/ecco/MeltingGroundingLines.m +++ b/src/m/contrib/larour/ecco/MeltingGroundingLines.m @@ -11,14 +11,14 @@ for i=1:length(pos_shelf) - if (mod(i,100)==0), + if (mod(i,100)==0) fprintf('\b\b\b\b\b\b\b%5.2f%s',i/length(pos_shelf)*100,' %'); end %search the node on ice sheet the closest to i [d posd]=min(sqrt((md.mesh.x(pos_shelf(i))-md.mesh.x(pos_GL)).^2+(md.mesh.y(pos_shelf(i))-md.mesh.y(pos_GL)).^2)); - if dny, + if count>ny error('need to enlarge connectivity table to at least'); end self.element_connectivity(el,count+1)=j; @@ -310,7 +310,7 @@ function mesh_connectivity2d(self,md,proj,varargin) % {{{ [lat0,long0]=projlatlong(proj); [mpartition,npartition]=self.partition(); - for i=subsetregions, + for i=subsetregions region=self.regions(i); disp(sprintf(' progress for region: %s',region.name)); @@ -328,11 +328,11 @@ function mesh_connectivity2d(self,md,proj,varargin) % {{{ end %build element connectivity table: - for j=1:length(self.glacier_connectivity), + for j=1:length(self.glacier_connectivity) el=self.glacier_connectivity(j); if ~el,continue; end; count=self.element_connectivity(el,ny); - if count>ny, + if count>ny error('need to enlarge connectivity table to at least'); end self.element_connectivity(el,count+1)=j; @@ -349,7 +349,7 @@ function checkconnectivity(self,mesh) % {{{ vector=find(self.element_connectivity(:,end)); - for i=1:length(vector), + for i=1:length(vector) el=vector(i); flags=zeros(mesh.numberofelements,1); @@ -361,7 +361,7 @@ function checkconnectivity(self,mesh) % {{{ [lids,rids]=self.gidtolid(glaciers); lat=zeros(length(glaciers),1); long=zeros(length(glaciers),1); - for j=1:nglaciers, + for j=1:nglaciers lat(j)=self.regions(rids(j)).CenLat(lids(j)); long(j)=self.regions(rids(j)).CenLon(lids(j)); end @@ -381,12 +381,12 @@ function checkconnectivity(self,mesh) % {{{ function totalarea=area(self,varargin) % {{{ region=-1; totalarea=0; - if nargin==2, + if nargin==2 region=varargin{1}; end - if region==-1, + if region==-1 %figure out the areas of everybody: - for i=1:self.nregions(), + for i=1:self.nregions() totalarea=totalarea+sum(self.regions(i).Area); end else @@ -398,7 +398,7 @@ function checkconnectivity(self,mesh) % {{{ mpartition=zeros(self.nregions(),1); npartition=zeros(self.nregions(),1); counter=0; - for i=1:self.nregions(), + for i=1:self.nregions() mpartition(i)=counter+1; npartition(i)=counter+self.nglaciers(i); counter=counter+self.nglaciers(i); @@ -411,15 +411,15 @@ function checkconnectivity(self,mesh) % {{{ %}}} function counter = nglaciers(self,varargin) % {{{ - if nargin==1, + if nargin==1 region=-1; %all regions. else region=varargin{1}; %only one. end - if region==-1, + if region==-1 counter=0; - for i=1:self.nregions(), + for i=1:self.nregions() counter=counter+length(self.regions(i).Area); end else @@ -441,7 +441,7 @@ function checkconnectivity(self,mesh) % {{{ [mpartition,npartition]=self.partition(); lid=zeros(length(gid),1); rid=zeros(length(gid),1); - for i=1:self.nregions(), + for i=1:self.nregions() pos=find(gid>=mpartition(i) & gid<=npartition(i)); rid(pos)=i; lid(pos)=gid(pos)-mpartition(i)+1; @@ -457,7 +457,7 @@ function units(self) % {{{ %}}} function listboxes(self) % {{{ - for i=1:length(self.boxes), + for i=1:length(self.boxes) b=self.boxes(i); disp(sprintf('Region #%i: %s (%s)',i,b.FULL_NAME,b.RGI_CODE)); end diff --git a/src/m/contrib/larour/glaciermip.m b/src/m/contrib/larour/glaciermip.m index 94446f90a..a18c6ae77 100644 --- a/src/m/contrib/larour/glaciermip.m +++ b/src/m/contrib/larour/glaciermip.m @@ -28,7 +28,7 @@ methods function self = glaciermip(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else self=setdefaultparameters(self); @@ -40,7 +40,7 @@ %read variables: - if self.version==1, + if self.version==1 self.region=ncread(self.ncfile,'region'); self.time=ncread(self.ncfile,'time'); self.run=ncread(self.ncfile,'run'); @@ -50,7 +50,7 @@ self.realization=ncread(self.ncfile,'realization'); self.area=ncread(self.ncfile,'area'); self.volume=ncread(self.ncfile,'volume'); - elseif self.version==2, + elseif self.version==2 self.area=ncread(self.ncfile,'Area'); self.mass=ncread(self.ncfile,'Mass'); self.region=ncread(self.ncfile,'Region'); @@ -86,22 +86,22 @@ unit=getfieldvalue(options,'unit','Gt'); sumregion=getfieldvalue(options,'sumregion',0); - if self.version==1, + if self.version==1 error(sprintf('getmass not supported yet for Glacier MIP version %i',self.version)); end %serialize: - if sumregion, - for i=rg, + if sumregion + for i=rg masses_regioni=[]; - for j=cm, - for k=gm, - for l=sc, + for j=cm + for k=gm + for l=sc masses_regioni=[masses_regioni; squeeze(self.mass(i,:,j,k,l))]; end end end - if i==1, + if i==1 masses=masses_regioni; else masses=masses+masses_regioni; @@ -109,20 +109,20 @@ end else masses=[]; - for i=rg, - for j=cm, - for k=gm, - for l=sc, + for i=rg + for j=cm + for k=gm + for l=sc masses=[masses; squeeze(self.mass(i,:,j,k,l))]; end end end end end - if zerostonan, + if zerostonan masses(find(masses==0))=NaN; end - if strcmpi(unit,'mmSLE'), + if strcmpi(unit,'mmSLE') masses=masses/sletogt(); end @@ -142,11 +142,11 @@ dm=diff(masses,1,2); massrates=dm; - for i=1:size(massrates,1), + for i=1:size(massrates,1) massrates(i,:)= massrates(i,:)./dt'; end - if strcmpi(unit,'mmSLE/yr'), + if strcmpi(unit,'mmSLE/yr') massrates=massrates/sletogt(); end @@ -154,7 +154,7 @@ function disp(self) % {{{ disp(sprintf(' Glacier MIP (version %i):',self.version)); - if self.version==1, + if self.version==1 fielddisplay(self,'ncfile','netcdf file for GlacierMIP results'); fielddisplay(self,'time','time scale in yr'); fielddisplay(self,'region','region'); @@ -166,7 +166,7 @@ function disp(self) % {{{ fielddisplay(self,'area','area'); fielddisplay(self,'volume','volume'); end - if self.version==2, + if self.version==2 fielddisplay(self,'ncfile','netcdf file for GlacierMIP results'); fielddisplay(self,'time','time'); fielddisplay(self,'region','region'); @@ -179,7 +179,7 @@ function disp(self) % {{{ end % }}} function part=partition(self,md,rgi2mesh,part,value) % {{{ - for i=1:size(rgi2mesh,2), + for i=1:size(rgi2mesh,2) dh=rgi2mesh(:,i); pos=find(dh); part(pos)=value; diff --git a/src/m/contrib/larour/graticule.m b/src/m/contrib/larour/graticule.m index 5752d8c7e..b44568ce7 100644 --- a/src/m/contrib/larour/graticule.m +++ b/src/m/contrib/larour/graticule.m @@ -3,15 +3,15 @@ grat.lat=[]; grat.long=[]; -for i=-180:longdeg:180, - for j=-90:refdeg:90, +for i=-180:longdeg:180 + for j=-90:refdeg:90 grat.lat=[grat.lat; j]; grat.long=[grat.long; i]; end end -for i=-90:latdeg:90, - for j=-180:refdeg:180, +for i=-90:latdeg:90 + for j=-180:refdeg:180 grat.lat=[grat.lat; i]; grat.long=[grat.long; j]; end diff --git a/src/m/contrib/larour/interpBedmachine.m b/src/m/contrib/larour/interpBedmachine.m index d86ff712d..d6641a7a6 100644 --- a/src/m/contrib/larour/interpBedmachine.m +++ b/src/m/contrib/larour/interpBedmachine.m @@ -1,6 +1,6 @@ function output = interpBedmachine(X,Y,string,continent), -if strcmpi(continent,'antarctica'), +if strcmpi(continent,'antarctica') ncdate='2014-09-23'; morlighemnc=['/Users/larour/ModelData2/MMAntarctica2013/AntarcticaMCdataset-' ncdate '.nc']; else @@ -32,7 +32,7 @@ data(find(data==-999999))=NaN; disp(sprintf(' -- BedMachine %s : interpolating %s',continent,string)); -if strcmp(string,'mask') | strcmp(string,'source'), +if strcmp(string,'mask') | strcmp(string,'source') %Need nearest neighbor to avoid interpolation between 0 and 2 if strcmpi(continent,'greenland'), ydata=flipud(ydata); data=flipud(data); end output = InterpFromGridToMesh(xdata,ydata,data,double(X),double(Y),0); diff --git a/src/m/contrib/larour/ismip6.m b/src/m/contrib/larour/ismip6.m index d309b7c36..d8c6dc949 100644 --- a/src/m/contrib/larour/ismip6.m +++ b/src/m/contrib/larour/ismip6.m @@ -30,7 +30,7 @@ methods function self = ismip6(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else self=setdefaultparameters(self); @@ -42,15 +42,15 @@ self.n=length(self.directories); %verify the directories exist: - for i=1:self.n, - if ~exist([self.root '/' self.directories{i}],'dir'), + for i=1:self.n + if ~exist([self.root '/' self.directories{i}],'dir') error(['ismip6 constructor error: ' self.root '/' self.directories{i} ' does not exist']); end end %figure out names of experiments: self.experiments=self.directories; - for i=1:self.n, + for i=1:self.n dir=self.directories{i}; ind=findstr(dir,'exp'); name=dir(1:ind-2); @@ -87,7 +87,7 @@ function disp(self) % {{{ end % }}} function listexp(self) % {{{ disp('ISMIP6 list of experiments:'); - for i=1:self.n, + for i=1:self.n disp([' ' self.experiments{i}]); end @@ -95,11 +95,11 @@ function listexp(self) % {{{ function [output,time,timestart,calendar]=read(self,experiment,field) % {{{ %go through list of experiments and find the right one: - if strcmpi(class(experiment),'double'), + if strcmpi(class(experiment),'double') ind=experiment; - elseif strcmpi(class(experiment),'char'), - for i=1:self.n, - if strcmpi(experiment,self.experiments{i}), + elseif strcmpi(class(experiment),'char') + for i=1:self.n + if strcmpi(experiment,self.experiments{i}) ind=i; break; end @@ -120,11 +120,11 @@ function listexp(self) % {{{ cd(currentdir); %go through list of files and figure out which one starts with the field: - for i=1:length(list), + for i=1:length(list) file=list{i}; ind=findstr(file,'_'); file_field=file(1:ind-1); - if strcmpi(file_field,field), + if strcmpi(file_field,field) break; end end @@ -137,14 +137,14 @@ function listexp(self) % {{{ %figure out start time: info=ncinfo([self.root '/' dir '/' file]); attributes=[]; - for i=1:length(info.Variables), - if strcmpi(info.Variables(i).Name,'time'), + for i=1:length(info.Variables) + if strcmpi(info.Variables(i).Name,'time') attributes=info.Variables(i).Attributes; break; end end - for j=1:length(attributes), - if strcmpi(attributes(j).Name,'units') | strcmpi(attributes(j).Name,'unit'), + for j=1:length(attributes) + if strcmpi(attributes(j).Name,'units') | strcmpi(attributes(j).Name,'unit') timestart=attributes(j).Value; end if strcmpi(attributes(j).Name,'calendar') @@ -159,11 +159,11 @@ function listexp(self) % {{{ function info=readinfo(self,experiment,field) % {{{ %go through list of experiments and find the right one: - if strcmpi(class(experiment),'double'), + if strcmpi(class(experiment),'double') ind=experiment; - elseif strcmpi(class(experiment),'char'), - for i=1:self.n, - if strcmpi(experiment,self.experiments{i}), + elseif strcmpi(class(experiment),'char') + for i=1:self.n + if strcmpi(experiment,self.experiments{i}) ind=i; break; end @@ -184,11 +184,11 @@ function listexp(self) % {{{ cd(currentdir); %go through list of files and figure out which one starts with the field: - for i=1:length(list), + for i=1:length(list) file=list{i}; ind=findstr(file,'_'); file_field=file(1:ind-1); - if strcmpi(file_field,field), + if strcmpi(file_field,field) break; end end @@ -199,7 +199,7 @@ function listexp(self) % {{{ end % }}} function interpolate(self,md,field,ismip2mesh,ismip2mesh_correction) % {{{ - for i=1:self.n, + for i=1:self.n disp(['reading and interpolating field ' field ' for model ' self.experiments{i}]); %read field from disk: @@ -207,12 +207,12 @@ function interpolate(self,md,field,ismip2mesh,ismip2mesh_correction) % {{{ %map onto 1 dimension field: ht=zeros(size(h,1)*size(h,2),nt); - for j=1:size(h,3), + for j=1:size(h,3) hj= h(:,:,j)'; hj=hj(:); ht(:,j)=double(hj); end %map onto mesh: correct only for thicknesses - if strcmpi(field,'lithk') | strcmpi(field,'orog') | strcmpi(field,'base'), + if strcmpi(field,'lithk') | strcmpi(field,'orog') | strcmpi(field,'base') hg=ismip2mesh_correction.*(ismip2mesh*ht) ; %hg=ismip2mesh*ht ; else @@ -220,30 +220,30 @@ function interpolate(self,md,field,ismip2mesh,ismip2mesh_correction) % {{{ end %keep field: - if strcmpi(field,'lithk'), + if strcmpi(field,'lithk') pos=find(isnan(hg)); hg(pos)=0; self.thickness{i}=hg; end - if strcmpi(field,'orog'), + if strcmpi(field,'orog') pos=find(isnan(hg)); hg(pos)=0; self.surface{i}=hg; end - if strcmpi(field,'base'), + if strcmpi(field,'base') pos=find(isnan(hg)); hg(pos)=0; self.base{i}=hg; end - if strcmpi(field,'sftgif'), + if strcmpi(field,'sftgif') hge=ones(md.mesh.numberofvertices,size(hg,2)); - for j=1:size(hg,2), + for j=1:size(hg,2) hgj=hg(:,j); pos=find(hgj>0); hge(md.mesh.elements(pos,:),j)=-1; end self.icemask{i}=hge; end - if strcmpi(field,'sftgrf'), + if strcmpi(field,'sftgrf') hgv=-ones(md.mesh.numberofvertices,size(hg,2)); - for j=1:size(hg,2), + for j=1:size(hg,2) hgj=hg(:,j); pos=find(hgj>.99); %we want fully grounded %pos=find(hgj>0); %we want slightly grounded @@ -260,9 +260,9 @@ function interpolate(self,md,field,ismip2mesh,ismip2mesh_correction) % {{{ end % }}} function part=partition(self,md,part,value) % {{{ - for i=1:self.n, + for i=1:self.n dh=self.deltathickness{i}; - for j=1:size(dh,2), + for j=1:size(dh,2) dhj=dh(:,j); pos=find(dhj); part(pos)=value; diff --git a/src/m/contrib/larour/legendd.m b/src/m/contrib/larour/legendd.m index ca63de232..7e26f54ef 100644 --- a/src/m/contrib/larour/legendd.m +++ b/src/m/contrib/larour/legendd.m @@ -18,7 +18,7 @@ function legendd(varargin) rectangle('Position',[x,y,w,h],'FaceColor',facecolor,'EdgeColor',edgecolor); nl=length(strings); - for i=1:nl, + for i=1:nl l=line([x+w/6 x+w/3],[y+(nl+1-i)*h/(nl+1) y+(nl+1-i)*h/(nl+1)]); set(l,'Color',colors{i}); set(l,'LineWidth',linewidth); diff --git a/src/m/contrib/larour/mdanalysis.m b/src/m/contrib/larour/mdanalysis.m index b90c44e28..43d693b91 100644 --- a/src/m/contrib/larour/mdanalysis.m +++ b/src/m/contrib/larour/mdanalysis.m @@ -22,7 +22,7 @@ %variables: }}} %global variables: %{{{ global md modelname -if strcmpi(class(varargin{1}),'model') | strcmpi(class(varargin{1}),'sealevelmodel'), +if strcmpi(class(varargin{1}),'model') | strcmpi(class(varargin{1}),'sealevelmodel') md=varargin{1}; modelname=inputname(1); end @@ -160,12 +160,12 @@ function Step_CreateFcn(hObject, eventdata, handles) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called if issealevel(), if isearth, results=md.earth.results; else results=md.icecaps{1}.results; end; else results=md.results; end; -if isfield(results,'TransientSolution'), +if isfield(results,'TransientSolution') strings=cell(length(results.TransientSolution),1); - for i=1:length(results.TransientSolution), + for i=1:length(results.TransientSolution) strings{i}=sprintf('%4.2f (%i)',results.TransientSolution(i).time,i); end - if length(strings)>40, + if length(strings)>40 %too many strings, reduce! lt=length(strings); modlt=floor(lt/40); @@ -221,9 +221,9 @@ function Field_Callback(hObject, eventdata, handles) strings=get(hObject,'String'); value=get(hObject,'Value'); string=strings(value); -if strcmpi(string,'IceVolume') | strcmpi(string,'IceVolumeAboveFloatation'), +if strcmpi(string,'IceVolume') | strcmpi(string,'IceVolumeAboveFloatation') plotv(); -elseif strcmpi(string,'SealevelRSLEustatic'), +elseif strcmpi(string,'SealevelRSLEustatic') %display directly: displayscalar(); else @@ -242,15 +242,15 @@ function Field_CreateFcn(hObject, eventdata, handles) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called if issealevel(), if isearth, results=md.earth.results; else results=md.icecaps{1}.results; end; else results=md.results; end; -if isfield(results,'TransientSolution'), +if isfield(results,'TransientSolution') fields=listfields(results,'TransientSolution'); set(hObject,'String',fields); - for i=1:length(fields), - if ~issealevel & strcmpi(fields{i},'Vel'), + for i=1:length(fields) + if ~issealevel & strcmpi(fields{i},'Vel') set(hObject,'Value',i); break; end - if issealevel & isearth & strcmpi(fields{i},'Sealevel'), + if issealevel & isearth & strcmpi(fields{i},'Sealevel') set(hObject,'Value',i); break; end @@ -307,8 +307,8 @@ function ModelChoice_CreateFcn(hObject, eventdata, handles) %figure out how many models are in the workspace! whores=evalin('base','whos'); flags=zeros(length(whores),1); -for i=1:length(whores), - if strcmpi(whores(i).class,'model') | strcmpi(whores(i).class,'sealevelmodel'), +for i=1:length(whores) + if strcmpi(whores(i).class,'model') | strcmpi(whores(i).class,'sealevelmodel') flags(i)=1; end end @@ -316,19 +316,19 @@ function ModelChoice_CreateFcn(hObject, eventdata, handles) whores=whores(pos); strings={}; -for i=1:length(whores), +for i=1:length(whores) strings{end+1}=[whores(i).name ' (' whores(i).class ')']; end %match with varargin{1}'s name: counter=-1; -for i=1:length(strings), - if strcmpi(modelname,whores(i).name), +for i=1:length(strings) + if strcmpi(modelname,whores(i).name) counter=i; break; end end -if counter==-1, +if counter==-1 error('could not find input model name matching base workspace names!'); end @@ -487,7 +487,7 @@ function Time_CreateFcn(hObject, eventdata, handles) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called if issealevel, if isearth, results=md.earth.results; else results=md.icecaps{1}.results; end; else results=md.results; end; -if isfield(results,'TransientSolution'), +if isfield(results,'TransientSolution') set(hObject,'String',sprintf('%4.2f',results.TransientSolution(1).time)); else set(hObject,'String',sprintf('%4.2f',0)); @@ -521,8 +521,8 @@ function Masque_CreateFcn(hObject, eventdata, handles) % hObject handle to Masque (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called -if issealevel, - if isearth, +if issealevel + if isearth mv=md.earth.mask; else mv=md.icecaps{1}.mask; @@ -557,12 +557,12 @@ function DiffStep_CreateFcn(hObject, eventdata, handles) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called if issealevel, if isearth, results=md.earth.results; else results=md.icecaps{1}.results; end; else results=md.results; end; -if isfield(results,'TransientSolution'), +if isfield(results,'TransientSolution') strings=cell(length(results.TransientSolution),1); - for i=1:length(results.TransientSolution), + for i=1:length(results.TransientSolution) strings{i}=sprintf('%4.2f (%i)',results.TransientSolution(i).time,i); end - if length(strings)>20, + if length(strings)>20 %too many strings, reduce! lt=length(strings); modlt=floor(lt/20); @@ -633,8 +633,8 @@ function ModelFields_CreateFcn(hObject, eventdata, handles) 'slr.deltathickness'... }; - if issealevel(), - if isearth, + if issealevel() + if isearth mask=md.earth.mask; else mask=md.icecaps{1}.mask; @@ -643,7 +643,7 @@ function ModelFields_CreateFcn(hObject, eventdata, handles) mask=md.mask; end - if strcmpi(class(mask),'maskpsl'), + if strcmpi(class(mask),'maskpsl') fields{end+1}='mask.ocean_levelset'; fields{end+1}='mask.land_levelset'; end @@ -690,8 +690,8 @@ function popupmenu10_CreateFcn(hObject, eventdata, handles) % hObject handle to popupmenu10 (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called -if issealevel, - if isearth, +if issealevel + if isearth resultfields=fieldnames(md.earth.results); else resultfields=fieldnames(md.icecaps{1}.results); @@ -699,17 +699,17 @@ function popupmenu10_CreateFcn(hObject, eventdata, handles) else resultfields=fieldnames(md.results); end -if isempty(resultfields), +if isempty(resultfields) resultfields={'None'}; end %default solution: -for i=1:length(resultfields), +for i=1:length(resultfields) solutiontype=resultfields{i}; - if strcmpi(solutiontype,'StressbalanceSolution'), + if strcmpi(solutiontype,'StressbalanceSolution') i0=i; break; - elseif strcmpi(solutiontype,'StressbalanceSolution'), + elseif strcmpi(solutiontype,'StressbalanceSolution') i0=i; break; else @@ -755,7 +755,7 @@ function popupmenu11_CreateFcn(hObject, eventdata, handles) % handles empty - handles not created until after all CreateFcns called global md range; -if issealevel(), +if issealevel() strings=md.continents(); set(hObject,'String',strings); set(hObject,'Value',1); @@ -790,7 +790,7 @@ function popupmenu12_CreateFcn(hObject, eventdata, handles) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called -if issealevel(), +if issealevel() %need the continent name: default first one. continents=md.continents(); @@ -833,7 +833,7 @@ function radiobutton18_Callback(hObject, eventdata, handles) %Change Field: if issealevel, if isearth, results=md.earth.results; else results=md.icecaps{1}.results; end; else results=md.results; end; fieldHandle=findobj('Tag', 'Field'); -if isfield(results,'TransientSolution'), +if isfield(results,'TransientSolution') fieldss=listfields(results,'TransientSolution'); set(fieldHandle,'String',fieldss); set(fieldHandle,'Value',1); @@ -843,8 +843,8 @@ function radiobutton18_Callback(hObject, eventdata, handles) end %Change Masque: -if issealevel, - if isearth, +if issealevel + if isearth mv=md.earth.mask; else mv=md.icecaps{1}.mask; @@ -914,22 +914,22 @@ function plotv() % {{{ %}}} %lock limits: % {{{ lockHandle=findobj('Tag', 'Lock'); lockvalue=get(lockHandle,'Value'); - if lockvalue, + if lockvalue xl=xlim; yl=ylim; end %}}} cla, reset(gca); hold on ; - if issealevel, - if isearth, + if issealevel + if isearth %do nothing. no ice volume. else dt=md.earth.timestepping.time_step*md.earth.settings.output_frequency; - for j=1:length(range), + for j=1:length(range) i=range(j); vols=resultstomatrix(md.icecaps{i},'TransientSolution',field); - if j==1, + if j==1 volst=vols; else volst(1,:)=volst(1,:)+vols(1,:); @@ -979,7 +979,7 @@ function displayscalar() % {{{ stepHandle=findobj('Tag', 'Step'); stepstrings=get(stepHandle,'String'); stepvalue=get(stepHandle,'Value'); - if ~isempty(stepstrings), + if ~isempty(stepstrings) stepstring=stepstrings{stepvalue}; %grab second integer: A=sscanf(stepstring,'%g (%i)'); counter=A(2); @@ -989,9 +989,9 @@ function displayscalar() % {{{ %}}} - if issealevel, - if isearth, - if strcmpi(field,'SealevelRSLEustatic'), + if issealevel + if isearth + if strcmpi(field,'SealevelRSLEustatic') dt=md.earth.timestepping.time_step*md.earth.slr.geodetic_run_frequency; eus=md.earth.results.TransientSolution(counter-1).(field)/dt*1000; %in mm/yr scalarHandle=findobj('Tag', 'Scalar'); @@ -1009,18 +1009,18 @@ function plotm() % {{{ strings=get(hObject,'String'); value=get(hObject,'Value'); string=''; - if value, - if ~isempty(strings), + if value + if ~isempty(strings) string=strings(value); end end - if strcmpi(string,'IceVolume') | strcmpi(string,'IceVolumeAboveFloatation'), + if strcmpi(string,'IceVolume') | strcmpi(string,'IceVolumeAboveFloatation') plotv(); - elseif strcmpi(string,'SealevelRSLEustatic'), + elseif strcmpi(string,'SealevelRSLEustatic') displayscalar(); else - if issealevel(), + if issealevel() plotsl(); else plotmd(); @@ -1034,7 +1034,7 @@ function plotmd() % {{{ stepHandle=findobj('Tag', 'Step'); stepstrings=get(stepHandle,'String'); stepvalue=get(stepHandle,'Value'); - if ~isempty(stepstrings), + if ~isempty(stepstrings) stepstring=stepstrings{stepvalue}; %grab second integer: A=sscanf(stepstring,'%g (%i)'); counter=A(2); @@ -1049,11 +1049,11 @@ function plotmd() % {{{ interpHandle=findobj('Tag', 'Interp'); interpvalue=get(interpHandle,'Value'); flatHandle=findobj('Tag', 'Flat'); flatvalue=get(flatHandle,'Value'); facetedHandle=findobj('Tag', 'Faceted'); facetedvalue=get(facetedHandle,'Value'); - if interpvalue, + if interpvalue shadingv='interp'; - elseif flatvalue, + elseif flatvalue shadingv='flat'; - elseif facetedvalue, + elseif facetedvalue shadingv='faceted'; else shadingv='interp'; @@ -1065,23 +1065,23 @@ function plotmd() % {{{ maskfieldvalue=get(maskfieldHandle,'Value'); maskfield=maskfieldstrings(maskfieldvalue); maskfield=maskfield{:}; - if strcmpi(maskfield,'all'), + if strcmpi(maskfield,'all') maskv=ones(md.mesh.numberofvertices,1); else maskv=md.mask.(maskfield); end - if strcmpi(maskfield,'all'), + if strcmpi(maskfield,'all') %do nothing; - elseif strcmpi(maskfield,'groundedice_levelset'), + elseif strcmpi(maskfield,'groundedice_levelset') maskv=maskv>=0; - elseif strcmpi(maskfield,'ice_levelset'), + elseif strcmpi(maskfield,'ice_levelset') maskv=maskv<=0; - elseif strcmpi(maskfield,'ocean_levelset'), + elseif strcmpi(maskfield,'ocean_levelset') maskv=maskv==1; - elseif strcmpi(maskfield,'land_levelset'), + elseif strcmpi(maskfield,'land_levelset') maskv=maskv==1; - elseif strcmpi(maskfield,'glacier_levelset'), - if isnan(maskv), + elseif strcmpi(maskfield,'glacier_levelset') + if isnan(maskv) maskv=ones(md.mesh.numberofvertices,1); else maskv=maskv==1; @@ -1091,7 +1091,7 @@ function plotmd() % {{{ %}}} %lock limits: % {{{ lockHandle=findobj('Tag', 'Lock'); lockvalue=get(lockHandle,'Value'); - if lockvalue, + if lockvalue xl=xlim; yl=ylim; else xl=[min(md.mesh.x) max(md.mesh.x)]; @@ -1099,7 +1099,7 @@ function plotmd() % {{{ end %}}} %time: {{{ timeHandle=findobj('Tag','Time'); - if strcmpi(solutiontype,'TransientSolution'), + if strcmpi(solutiontype,'TransientSolution') set(timeHandle,'String',sprintf('%4.2f',md.results.TransientSolution(counter).time)); else set(timeHandle,'String',sprintf('%4.2f',0)); @@ -1109,7 +1109,7 @@ function plotmd() % {{{ stepHandle=findobj('Tag', 'DiffStep'); stepstrings=get(stepHandle,'String'); stepvalue=get(stepHandle,'Value'); - if ~isempty(stepstrings), + if ~isempty(stepstrings) stepstring=stepstrings{stepvalue}; %grab second integer: A=sscanf(stepstring,'%g (%i)'); diffcounter=A(2); @@ -1123,39 +1123,39 @@ function plotmd() % {{{ fieldHandle=findobj('Tag', 'Field'); fieldstrings=get(fieldHandle,'String'); fieldvalue=get(fieldHandle,'Value'); - if ~isempty(fieldstrings), + if ~isempty(fieldstrings) fieldv=fieldstrings{fieldvalue}; else fieldv=NaN; end mfHandle=findobj('Tag', 'Mf'); mf=get(mfHandle,'Value'); - if mf | strcmpi(solutiontype,'None'), + if mf | strcmpi(solutiontype,'None') fieldHandle=findobj('Tag', 'ModelFields'); fieldstrings=get(fieldHandle,'String'); fieldvalue=get(fieldHandle,'Value'); fieldv=fieldstrings{fieldvalue}; eval(['field=md.' fieldv ';']); - if isnan(field), + if isnan(field) field='mesh'; end else - if strcmpi(solutiontype,'TransientSolution'), + if strcmpi(solutiontype,'TransientSolution') field=md.results.TransientSolution(counter).(fieldv); dfield=md.results.TransientSolution(diffcounter).(fieldv); - elseif strcmpi(solutiontype,'StressbalanceSolution'), + elseif strcmpi(solutiontype,'StressbalanceSolution') field=md.results.StressbalanceSolution.(fieldv); dfield=NaN; else error('unknown solution type!'); end end - if comparison, - if strcmpi(solutiontype,'None'), + if comparison + if strcmpi(solutiontype,'None') error('cannot compare a solution field to model as no solution was run or selected!'); end %figure out second field: - if strcmpi(fieldv,'Vel'), + if strcmpi(fieldv,'Vel') field2=md.inversion.vel_obs; end end @@ -1166,7 +1166,7 @@ function plotmd() % {{{ cmaxHandle=findobj('Tag','Cmax'); cmax=str2num(get(cmaxHandle,'String')); if isnan(cmin) - if logvalue, + if logvalue cmin=.1; else pos=find(maskv); @@ -1181,14 +1181,14 @@ function plotmd() % {{{ %}}} cla; - if logvalue, + if logvalue plotmodel(md,'data',field,'figurestatement','off','clf','off','mask',maskv,'caxis',colaxis,'log',10,'xlim',xl,'ylim',yl,'shading',shadingv); else - if ~diff, - if comparison, + if ~diff + if comparison plotmodel(md,'data',field,'data',field2,'figurestatement','off','clf','off','mask#all',maskv,'caxis#all',colaxis,'xlim#all',xl,'ylim#all',yl,'shading#all',shadingv,'nlines',2,'ncols',1); else - if ischar(field) & strcmpi(field,'mesh'), + if ischar(field) & strcmpi(field,'mesh') plotmodel(md,'data','mesh','figurestatement','off','clf','off','xlim',xl,'ylim',yl); else plotmodel(md,'data',field,'figurestatement','off','clf','off','mask',maskv,'caxis',colaxis,'xlim',xl,'ylim',yl,'shading',shadingv); @@ -1208,7 +1208,7 @@ function plotsl() % {{{ stepHandle=findobj('Tag', 'Step'); stepstrings=get(stepHandle,'String'); stepvalue=get(stepHandle,'Value'); - if ~isempty(stepstrings), + if ~isempty(stepstrings) stepstring=stepstrings{stepvalue}; %grab second integer: A=sscanf(stepstring,'%g (%i)'); counter=A(2); @@ -1223,11 +1223,11 @@ function plotsl() % {{{ interpHandle=findobj('Tag', 'Interp'); interpvalue=get(interpHandle,'Value'); flatHandle=findobj('Tag', 'Flat'); flatvalue=get(flatHandle,'Value'); facetedHandle=findobj('Tag', 'Faceted'); facetedvalue=get(facetedHandle,'Value'); - if interpvalue, + if interpvalue shadingv='interp'; - elseif flatvalue, + elseif flatvalue shadingv='flat'; - elseif facetedvalue, + elseif facetedvalue shadingv='faceted'; else shadingv='interp'; @@ -1235,8 +1235,8 @@ function plotsl() % {{{ %}}} %time: {{{ timeHandle=findobj('Tag','Time'); - if strcmpi(solutiontype,'TransientSolution'), - if isearth, + if strcmpi(solutiontype,'TransientSolution') + if isearth set(timeHandle,'String',sprintf('%4.2f',md.earth.results.TransientSolution(counter).time)); else set(timeHandle,'String',sprintf('%4.2f',md.icecaps{1}.results.TransientSolution(counter).time)); @@ -1249,7 +1249,7 @@ function plotsl() % {{{ stepHandle=findobj('Tag', 'DiffStep'); stepstrings=get(stepHandle,'String'); stepvalue=get(stepHandle,'Value'); - if ~isempty(stepstrings), + if ~isempty(stepstrings) stepstring=stepstrings{stepvalue}; %grab second integer: A=sscanf(stepstring,'%g (%i)'); diffcounter=A(2); @@ -1260,46 +1260,46 @@ function plotsl() % {{{ diff=get(diffHandle,'Value'); %}}} - if isearth, + if isearth %Earth plotting: {{{ %field: % {{{ fieldHandle=findobj('Tag', 'Field'); fieldstrings=get(fieldHandle,'String'); fieldvalue=get(fieldHandle,'Value'); - if ~isempty(fieldstrings), + if ~isempty(fieldstrings) fieldv=fieldstrings{fieldvalue}; else fieldv=NaN; end colorbartitle={fieldv,''}; - if strcmpi(fieldv,'SealevelRSLRate'), + if strcmpi(fieldv,'SealevelRSLRate') colorbartitle={'SealevelRSLRate (mm/yr)',''}; end mfHandle=findobj('Tag', 'Mf'); mf=get(mfHandle,'Value'); - if mf | strcmpi(solutiontype,'None'), + if mf | strcmpi(solutiontype,'None') fieldHandle=findobj('Tag', 'ModelFields'); fieldstrings=get(fieldHandle,'String'); fieldvalue=get(fieldHandle,'Value'); fieldv=fieldstrings{fieldvalue}; eval(['field=md.earth.' fieldv ';']); - if isnan(field), + if isnan(field) field='mesh'; end else - if strcmpi(solutiontype,'TransientSolution'), + if strcmpi(solutiontype,'TransientSolution') field=md.earth.results.TransientSolution(counter).(fieldv); dfield=md.earth.results.TransientSolution(diffcounter).(fieldv); - elseif strcmpi(solutiontype,'StressbalanceSolution'), + elseif strcmpi(solutiontype,'StressbalanceSolution') field=md.earth.results.StressbalanceSolution.(fieldv); dfield=NaN; else error('unknown solution type!'); end end - if comparison, - if strcmpi(solutiontype,'None'), + if comparison + if strcmpi(solutiontype,'None') error('cannot compare a solution field to model as no solution was run or selected!'); end %figure out second field: @@ -1313,23 +1313,23 @@ function plotsl() % {{{ maskfieldvalue=get(maskfieldHandle,'Value'); maskfield=maskfieldstrings(maskfieldvalue); maskfield=maskfield{:}; - if strcmpi(maskfield,'all'), + if strcmpi(maskfield,'all') maskv=ones(md.earth.mesh.numberofvertices,1); else maskv=md.earth.mask.(maskfield); end - if strcmpi(maskfield,'all'), + if strcmpi(maskfield,'all') %do nothing; - elseif strcmpi(maskfield,'groundedice_levelset'), + elseif strcmpi(maskfield,'groundedice_levelset') maskv=maskv>=0; - elseif strcmpi(maskfield,'ice_levelset'), + elseif strcmpi(maskfield,'ice_levelset') maskv=maskv<=0; - elseif strcmpi(maskfield,'ocean_levelset'), + elseif strcmpi(maskfield,'ocean_levelset') maskv=maskv==1; - elseif strcmpi(maskfield,'land_levelset'), + elseif strcmpi(maskfield,'land_levelset') maskv=maskv==1; - elseif strcmpi(maskfield,'glacier_levelset'), - if isnan(maskv), + elseif strcmpi(maskfield,'glacier_levelset') + if isnan(maskv) maskv=ones(md.earth.mesh.numberofvertices,1); else maskv=maskv==1; @@ -1338,12 +1338,12 @@ function plotsl() % {{{ maskvalue=0; %}}} %color limits: % {{{ - if ~ischar(field), + if ~ischar(field) cminHandle=findobj('Tag','Cmin'); cmin=str2num(get(cminHandle,'String')); cmaxHandle=findobj('Tag','Cmax'); cmax=str2num(get(cmaxHandle,'String')); if isnan(cmin) - if logvalue, + if logvalue cmin=.1; else pos=find(maskv); @@ -1355,7 +1355,7 @@ function plotsl() % {{{ cmax=max(field(pos)); end - if cmin==cmax, + if cmin==cmax colaxis=[cmin-eps,cmax+eps]; else colaxis=[cmin,cmax]; @@ -1365,7 +1365,7 @@ function plotsl() % {{{ %}}} %lock limits: % {{{ lockHandle=findobj('Tag', 'Lock'); lockvalue=get(lockHandle,'Value'); - if lockvalue, + if lockvalue xl=xlim; yl=ylim; zl=zlim; [az,el]=view; v=[az,el]; else @@ -1377,14 +1377,14 @@ function plotsl() % {{{ %some quirks: cla; - if logvalue, + if logvalue plotmodel(md.earth,'data',field,'figurestatement','off','clf','off','mask',maskv,'caxis',colaxis,'log',10,'xlim',xl,'ylim',yl,'zlim',zl,'shading',shadingv,'colorbar','on','view',v,'colorbartitle',colorbartitle); else - if ~diff, - if comparison, + if ~diff + if comparison plotmodel(md.earth,'data',field,'data',field2,'figurestatement','off','clf','off','mask#all',maskv,'caxis#all',colaxis,'xlim#all',xl,'ylim#all',yl,'zlim#all',zl,'shading#all',shadingv,'nlines',2,'ncols',1,'view#all',v,'colorbartitle',colorbartitle); else - if ischar(field) & strcmpi(field,'mesh'), + if ischar(field) & strcmpi(field,'mesh') plotmodel(md.earth,'data','mesh','figurestatement','off','clf','off','xlim',xl,'ylim',yl,'zlim',zl,'view#all',v,'colorbartitle',colorbartitle); else plotmodel(md.earth,'data',field,'figurestatement','off','clf','off','mask',maskv,'maskvalue',maskvalue,'caxis',colaxis,'xlim',xl,'ylim',yl,'zlim',zl,'shading',shadingv,'axes','equal','colorbarpos',[.95 .5 .01 .15],'view#all',v,'colorbartitle',colorbartitle); @@ -1413,7 +1413,7 @@ function plotsl() % {{{ stepHandle=findobj('Tag', 'Step'); stepstrings=get(stepHandle,'String'); stepvalue=get(stepHandle,'Value'); - if ~isempty(stepstrings), + if ~isempty(stepstrings) stepstring=stepstrings{stepvalue}; %grab second integer: A=sscanf(stepstring,'%g (%i)'); counter=A(2); @@ -1428,11 +1428,11 @@ function plotsl() % {{{ interpHandle=findobj('Tag', 'Interp'); interpvalue=get(interpHandle,'Value'); flatHandle=findobj('Tag', 'Flat'); flatvalue=get(flatHandle,'Value'); facetedHandle=findobj('Tag', 'Faceted'); facetedvalue=get(facetedHandle,'Value'); - if interpvalue, + if interpvalue shadingv='interp'; - elseif flatvalue, + elseif flatvalue shadingv='flat'; - elseif facetedvalue, + elseif facetedvalue shadingv='faceted'; else shadingv='interp'; @@ -1440,7 +1440,7 @@ function plotsl() % {{{ %}}} %time: {{{ timeHandle=findobj('Tag','Time'); - if strcmpi(solutiontype,'TransientSolution'), + if strcmpi(solutiontype,'TransientSolution') set(timeHandle,'String',sprintf('%4.2f',md.icecaps{1}.results.TransientSolution(counter).time)); else set(timeHandle,'String',sprintf('%4.2f',0)); @@ -1450,7 +1450,7 @@ function plotsl() % {{{ stepHandle=findobj('Tag', 'DiffStep'); stepstrings=get(stepHandle,'String'); stepvalue=get(stepHandle,'Value'); - if ~isempty(stepstrings), + if ~isempty(stepstrings) stepstring=stepstrings{stepvalue}; %grab second integer: A=sscanf(stepstring,'%g (%i)'); diffcounter=A(2); @@ -1462,7 +1462,7 @@ function plotsl() % {{{ %}}} %range: % {{{ basins=getbasins(); - if strcmpi(basins,'All'), + if strcmpi(basins,'All') range=md.basinindx('continent',{getcontinent()}); else range=md.basinindx('basin',basins); @@ -1470,7 +1470,7 @@ function plotsl() % {{{ %}}} cla; - for j=1:length(range), + for j=1:length(range) i=range(j); %mask: %{{{ maskfieldHandle=findobj('Tag', 'Masque'); @@ -1478,23 +1478,23 @@ function plotsl() % {{{ maskfieldvalue=get(maskfieldHandle,'Value'); maskfield=maskfieldstrings(maskfieldvalue); maskfield=maskfield{:}; - if strcmpi(maskfield,'all'), + if strcmpi(maskfield,'all') maskv=ones(md.icecaps{i}.mesh.numberofvertices,1); else maskv=md.icecaps{i}.mask.(maskfield); end - if strcmpi(maskfield,'all'), + if strcmpi(maskfield,'all') %do nothing; - elseif strcmpi(maskfield,'groundedice_levelset'), + elseif strcmpi(maskfield,'groundedice_levelset') maskv=maskv>=0; - elseif strcmpi(maskfield,'ice_levelset'), + elseif strcmpi(maskfield,'ice_levelset') maskv=maskv<=0; - elseif strcmpi(maskfield,'ocean_levelset'), + elseif strcmpi(maskfield,'ocean_levelset') maskv=maskv==1; - elseif strcmpi(maskfield,'land_levelset'), + elseif strcmpi(maskfield,'land_levelset') maskv=maskv==1; - elseif strcmpi(maskfield,'glacier_levelset'), - if isnan(maskv), + elseif strcmpi(maskfield,'glacier_levelset') + if isnan(maskv) maskv=ones(md.icecaps{i}.mesh.numberofvertices,1); else maskv=maskv==1; @@ -1504,15 +1504,15 @@ function plotsl() % {{{ %}}} %lock limits: % {{{ lockHandle=findobj('Tag', 'Lock'); lockvalue=get(lockHandle,'Value'); - if lockvalue, + if lockvalue xl=xlim; yl=ylim; else - if j==1, + if j==1 xl=[min(md.icecaps{i}.mesh.x) max(md.icecaps{i}.mesh.x)]; else xl=[min([md.icecaps{i}.mesh.x;xl(1)]) max([md.icecaps{i}.mesh.x;xl(2)])]; end - if j==1, + if j==1 yl=[min(md.icecaps{i}.mesh.y) max(md.icecaps{i}.mesh.y)]; else yl=[min([md.icecaps{i}.mesh.y; yl(1)]) max([md.icecaps{i}.mesh.y; yl(2)])]; @@ -1522,35 +1522,35 @@ function plotsl() % {{{ fieldHandle=findobj('Tag', 'Field'); fieldstrings=get(fieldHandle,'String'); fieldvalue=get(fieldHandle,'Value'); - if ~isempty(fieldstrings), + if ~isempty(fieldstrings) fieldv=fieldstrings{fieldvalue}; else fieldv=NaN; end mfHandle=findobj('Tag', 'Mf'); mf=get(mfHandle,'Value'); - if mf | strcmpi(solutiontype,'None'), + if mf | strcmpi(solutiontype,'None') fieldHandle=findobj('Tag', 'ModelFields'); fieldstrings=get(fieldHandle,'String'); fieldvalue=get(fieldHandle,'Value'); fieldv=fieldstrings{fieldvalue}; eval(['field=md.icecaps{' num2str(i) '}.' fieldv ';']); - if isnan(field), + if isnan(field) field='mesh'; end else - if strcmpi(solutiontype,'TransientSolution'), + if strcmpi(solutiontype,'TransientSolution') field=md.icecaps{i}.results.TransientSolution(counter).(fieldv); dfield=md.icecaps{i}.results.TransientSolution(diffcounter).(fieldv); - elseif strcmpi(solutiontype,'StressbalanceSolution'), + elseif strcmpi(solutiontype,'StressbalanceSolution') field=md.icecaps{i}.results.StressbalanceSolution.(fieldv); dfield=NaN; else error('unknown solution type!'); end end - if comparison, - if strcmpi(solutiontype,'None'), + if comparison + if strcmpi(solutiontype,'None') error('cannot compare a solution field to model as no solution was run or selected!'); end %figure out second field: @@ -1567,11 +1567,11 @@ function plotsl() % {{{ cmaxHandle=findobj('Tag','Cmax'); cmaxfield=str2num(get(cmaxHandle,'String')); if isnan(cminfield) - if logvalue, + if logvalue cmin=.1; else pos=find(maskv); - if j==1, + if j==1 cmin=min(field(pos)); else cmin=min(min(field(pos)),cmin); @@ -1590,40 +1590,40 @@ function plotsl() % {{{ else cmax=cmaxfield; end - if cmin==cmax, + if cmin==cmax cmin=cmin-1e-10; cmax=cmax+1e-10; end colaxis=[cmin,cmax]; %}}} %contour levels? {{{ contourlevels=0; - if strncmpi(fieldv,'Mask',4), + if strncmpi(fieldv,'Mask',4) contourexp=[tempname '.exp']; isoline(md.icecaps{i},field,'output',contourexp); contourlevels=1; - if diff, + if diff contourdiffexp=[tempname '.exp']; isoline(md.icecaps{i},dfield,'output',contourdiffexp); end end %}}} %display : {{{ - if logvalue, + if logvalue plotmodel(md.icecaps{i},'data',field,'figurestatement','off','clf','off','mask',maskv,'caxis',colaxis,'log',10,'xlim',xl,'ylim',yl,'shading',shadingv); else - if ~diff, - if comparison, + if ~diff + if comparison plotmodel(md.icecaps{i},'data',field,'data',field2,'figurestatement','off','clf','off','mask#all',maskv,'caxis#all',colaxis,'xlim#all',xl,'ylim#all',yl,'shading#all',shadingv,'nlines',2,'ncols',1); else - if ischar(field) & strcmpi(field,'mesh'), + if ischar(field) & strcmpi(field,'mesh') plotmodel(md.icecaps{i},'data','mesh','figurestatement','off','clf','off','xlim',xl,'ylim',yl); else plotmodel(md.icecaps{i},'data',field,'figurestatement','off','clf','off','mask',maskv,'caxis',colaxis,'xlim',xl,'ylim',yl,'shading',shadingv); - if contourlevels, + if contourlevels contour=expread(contourexp); hold on; - for k=1:length(contour), + for k=1:length(contour) plot(contour(k).x,contour(k).y,'r-'); end end @@ -1631,15 +1631,15 @@ function plotsl() % {{{ end else plotmodel(md.icecaps{i},'data',dfield-field,'figurestatement','off','clf','off','mask',maskv,'caxis',colaxis,'xlim',xl,'ylim',yl,'shading',shadingv); - if contourlevels, + if contourlevels contour=expread(contourexp); hold on; - for k=1:length(contour), + for k=1:length(contour) plot(contour(k).x,contour(k).y,'k-'); end dcontour=expread(contourdiffexp); hold on; - for k=1:length(dcontour), + for k=1:length(dcontour) plot(dcontour(k).x,dcontour(k).y,'r-'); end end @@ -1649,7 +1649,7 @@ function plotsl() % {{{ end %end for - if ~comparison, + if ~comparison set(gca,'Position',[0.2300 0.1100 0.7750 0.8150]); end % }}} end @@ -1660,7 +1660,7 @@ function plotsl() % {{{ %}}} function result=issealevel() % {{{ global md; - if strcmpi(class(md),'sealevelmodel'), + if strcmpi(class(md),'sealevelmodel') result=1; else result=0; diff --git a/src/m/contrib/larour/mme_autotime_correlation_matrix.m b/src/m/contrib/larour/mme_autotime_correlation_matrix.m index aea503faf..c9dcc336d 100644 --- a/src/m/contrib/larour/mme_autotime_correlation_matrix.m +++ b/src/m/contrib/larour/mme_autotime_correlation_matrix.m @@ -11,8 +11,8 @@ matrix=eye(nsteps,nsteps); %go through time steps, and fill up the top part. - for i=1:nsteps, - for j=i+1:nsteps, + for i=1:nsteps + for j=i+1:nsteps matrix(i,j)=corr(mme(:,i),mme(:,j),'Type',type); matrix(j,i)=matrix(i,j); end diff --git a/src/m/contrib/larour/morphological/aggregation.m b/src/m/contrib/larour/morphological/aggregation.m index ec3364789..d6dea5a69 100644 --- a/src/m/contrib/larour/morphological/aggregation.m +++ b/src/m/contrib/larour/morphological/aggregation.m @@ -15,14 +15,14 @@ %check input arguments %{{{ %even windowsize -if mod(windowsize,2)==0, +if mod(windowsize,2)==0 error('windowsize should be an even number'); end %check on presence of varargin: optional=0; -if nargin>3, - if nargin~=5, +if nargin>3 + if nargin~=5 help aggregation; error('wrong number of optional arguments specified'); else @@ -33,8 +33,8 @@ end %check on presence of varargout: -if optional, - if nargout~=3, +if optional + if nargout~=3 help aggregation; error('wrong number of optional output arguments specified'); end @@ -58,7 +58,7 @@ s=size(mask); mask=mask(1:windowsize:s(1),1:windowsize:s(2)); -if optional, +if optional varargout{1}=x(1:windowsize:s(2)); varargout{2}=y(1:windowsize:s(1)); end diff --git a/src/m/contrib/larour/morphological/dilation.m b/src/m/contrib/larour/morphological/dilation.m index 89667e464..df037cb94 100644 --- a/src/m/contrib/larour/morphological/dilation.m +++ b/src/m/contrib/larour/morphological/dilation.m @@ -7,7 +7,7 @@ %4 neighboorhood: %corners -if neighboorhood==4, +if neighboorhood==4 matrix(1,1)=0; matrix(1,3)=0; matrix(3,1)=0; diff --git a/src/m/contrib/larour/morphological/erosion.m b/src/m/contrib/larour/morphological/erosion.m index 9632b4629..ffecd0a80 100644 --- a/src/m/contrib/larour/morphological/erosion.m +++ b/src/m/contrib/larour/morphological/erosion.m @@ -7,7 +7,7 @@ %4 neighboorhood: %corners -if neighboorhood==4, +if neighboorhood==4 matrix(1,1)=0; matrix(1,3)=0; matrix(3,1)=0; diff --git a/src/m/contrib/larour/morphological/vectorialize.m b/src/m/contrib/larour/morphological/vectorialize.m index 65c981e31..722b66766 100644 --- a/src/m/contrib/larour/morphological/vectorialize.m +++ b/src/m/contrib/larour/morphological/vectorialize.m @@ -3,7 +3,7 @@ vec=bwboundaries(mask,connectivity); contours=struct([]); - for i=1:length(vec), + for i=1:length(vec) contours(end+1).x=vec{i}(:,2); contours(end).y=vec{i}(:,1); contours(end).density=1; diff --git a/src/m/contrib/larour/oceanmip.m b/src/m/contrib/larour/oceanmip.m index 88d189186..c8e7ba7af 100644 --- a/src/m/contrib/larour/oceanmip.m +++ b/src/m/contrib/larour/oceanmip.m @@ -25,7 +25,7 @@ methods function self = oceanmip(varargin) % {{{ - if nargin==0, + if nargin==0 self=setdefaultparameters(self); else self=setdefaultparameters(self); @@ -37,14 +37,14 @@ self.n=length(self.files); %read files: - for f=1:self.n, + for f=1:self.n file=[self.root '/' self.files{f}]; disp(['reading file ' file]); %figure out time interval and remove historical: time=ncread(file,'time'); pos=find(diff(time)<0); - if isempty(pos), + if isempty(pos) %pos=(length(time)-12*100+1):length(time); pos=1:length(time); else @@ -62,7 +62,7 @@ %zos: zos=ncread(file,'zos'); nx=size(zos,1); ny=size(zos,2); zos=zos(:,:,pos); zosm=zeros(nx,ny,nt/12); - for i=12:12:nt, + for i=12:12:nt year=i/12; zosm(:,:,year)=mean(zos(:,:,(i-11):i),3); end @@ -71,7 +71,7 @@ %zostoga: zostoga=ncread(file,'zostoga'); zostoga=zostoga(pos); zostogam=zeros(nt/12,1); - for i=12:12:nt, + for i=12:12:nt year=i/12; zostogam(year)=mean(zostoga(i-11:i)); end @@ -82,7 +82,7 @@ %pbo: pbo=ncread(file,'pbo'); nx=size(pbo,1); ny=size(pbo,2); pbo=pbo(:,:,pos); pbom=zeros(nx,ny,nt/12); - for i=12:12:nt, + for i=12:12:nt year=i/12; pbom(:,:,year)=mean(pbo(:,:,i-11:i),3); end @@ -108,11 +108,11 @@ pos=find(meshlong<0); meshlong(pos)=meshlong(pos)+360; meshlat=md.mesh.lat; - for i=1:self.n, + for i=1:self.n disp(['interpolating model ' self.model{i} ' onto model mesh']); %If we have 182 cells in long, trim by 1 on each side: - if size(self.pbo{i},1)==182, + if size(self.pbo{i},1)==182 self.pbo{i}=self.pbo{i}(2:181,:,:); self.zos{i}=self.zos{i}(2:181,:,:); self.long{i}=self.long{i}(2:181,:,:); @@ -149,7 +149,7 @@ parfor j=1:length(time), %for j=1:length(time), - if mod(j,10)==0, + if mod(j,10)==0 s=sprintf(' progress: %.2g ',j/length(time)*100); fprintf(s); pause(1e-3); fprintf(repmat('\b',1,numel(s))); end @@ -179,7 +179,7 @@ end %}}} function self = rawclean(self) % {{{ - for i=1:self.n, + for i=1:self.n self.zos{i}=[]; self.pbo{i}=[]; end @@ -187,7 +187,7 @@ %}}} function [rate,time]= zostoga_mean(self) % {{{ series=zeros(length(self.time{1}),self.n); - for i=1:self.n, + for i=1:self.n series(:,i)=self.zostoga{i}; end rate=mean(series,2); @@ -196,7 +196,7 @@ %}}} function [rate,time]= zostoga_std(self) % {{{ series=zeros(length(self.time{1}),self.n); - for i=1:self.n, + for i=1:self.n series(:,i)=self.zostoga{i}; end rate=std(series,1,2); @@ -205,7 +205,7 @@ %}}} function [average,stddev,time]= zostoga_stats(self) % {{{ series=zeros(length(self.time{1}),self.n); - for i=1:self.n, + for i=1:self.n series(:,i)=self.zostoga{i}; end average=mean(series,2); @@ -214,9 +214,9 @@ end %}}} function array= bottompressure(self,model,gridded) % {{{ - for i=1:self.n, - if strcmpi(model,self.model{i}), - if gridded, + for i=1:self.n + if strcmpi(model,self.model{i}) + if gridded pbo=self.pbo{i}; pbo=pbo/1000; %in meters else pbo=self.mesh_pbo{i}; pbo=pbo/1000; %in meters @@ -232,10 +232,10 @@ units=getfieldvalue(options,'units','mm/yr'); arrays=cell(self.n,1); - for i=1:self.n, + for i=1:self.n pbo=self.mesh_pbo{i}; dpbo=diff(pbo,1,2); - if strcmpi(units,'m/yr'), + if strcmpi(units,'m/yr') dpbo=dpbo/1000; end time=self.time{i}; time=time(1:end-1); @@ -248,10 +248,10 @@ units=getfieldvalue(options,'units','mm/yr'); arrays=cell(self.n,1); - for i=1:self.n, + for i=1:self.n zos=self.mesh_zos{i}; dzos=diff(zos,1,2); - if strcmpi(units,'m/yr'), + if strcmpi(units,'m/yr') dzos=dzos/1000; end time=self.time{i};time=time(1:end-1); @@ -264,10 +264,10 @@ units=getfieldvalue(options,'units','mm/yr'); arrays=cell(self.n,1); - for i=1:self.n, + for i=1:self.n zostoga=self.zostoga{i}; dzostoga=diff(zostoga); - if strcmpi(units,'m/yr'), + if strcmpi(units,'m/yr') dzostoga=dzostoga/1000; end time=self.time{i};time=time(1:end-1); @@ -276,8 +276,8 @@ end end %}}} function [lat,long]= latlong(self,model) % {{{ - for i=1:self.n, - if strcmpi(model,self.model{i}), + for i=1:self.n + if strcmpi(model,self.model{i}) lat=self.lat{i}; long=self.long{i}; break; diff --git a/src/m/contrib/larour/prjwrite.m b/src/m/contrib/larour/prjwrite.m index 02b260271..b076196ec 100644 --- a/src/m/contrib/larour/prjwrite.m +++ b/src/m/contrib/larour/prjwrite.m @@ -4,9 +4,9 @@ function prjwrite(filename,proj) projname=[path '/' name '.prj']; projdir='/Users/larour/issm-jpl/proj-group/qgis/Proj/'; - if strcmpi(proj,'EPSG:3031'), + if strcmpi(proj,'EPSG:3031') copyfile([projdir '/3031.prj'],projname,'f'); - elseif strcmpi(proj,'EPSG:3413'), + elseif strcmpi(proj,'EPSG:3413') copyfile([projdir '/3413.prj'],projname,'f'); else error('not supported yet'); diff --git a/src/m/contrib/larour/resultstomatrix.m b/src/m/contrib/larour/resultstomatrix.m index 91a3e3c1e..a74094faf 100644 --- a/src/m/contrib/larour/resultstomatrix.m +++ b/src/m/contrib/larour/resultstomatrix.m @@ -22,14 +22,14 @@ %first, figure out the size: count=0; nods=0; - for i=1:length(results), - if ~isempty(results(i).(field)), + for i=1:length(results) + if ~isempty(results(i).(field)) count=count+1; nods=size(results(i).(field),1); end end - if ~count, + if ~count error(['could not find any result ' field ' in ' resultname]); end @@ -38,8 +38,8 @@ %fill it up: count=0; - for i=1:length(results), - if ~isempty(results(i).(field)), + for i=1:length(results) + if ~isempty(results(i).(field)) count=count+1; matrix(1:end-1,count)=results(i).(field); matrix(end,count)=results(i).time; @@ -47,12 +47,12 @@ end newtime=getfieldvalue(options,'time',[]); - if ~isempty(newtime), + if ~isempty(newtime) newmatrix=zeros(nods+1,length(newtime)); newmatrix(end,:)=newtime; %we are asked to reinterpolate to this new time: - for i=1:nods, + for i=1:nods warning off; ts=timeseries(matrix(i,:), matrix(end,:)); ts=resample(ts,newtime); diff --git a/src/m/contrib/morlighem/bamg/YamsCall.m b/src/m/contrib/morlighem/bamg/YamsCall.m index 7b4c06a90..d7d700d39 100644 --- a/src/m/contrib/morlighem/bamg/YamsCall.m +++ b/src/m/contrib/morlighem/bamg/YamsCall.m @@ -49,11 +49,11 @@ numberofelements1=md.mesh.numberofelements; %Deal with rifts -if ~isnan(md.rifts.riftstruct), +if ~isnan(md.rifts.riftstruct) %we have the list of triangles that make up the rift. keep those triangles around during refinement. triangles=[]; - for i=1:size(md.rifts.riftstruct,1), + for i=1:size(md.rifts.riftstruct,1) triangles=[triangles md.rifts(i).riftstruct.segments(:,3)']; end diff --git a/src/m/contrib/morlighem/bamg/gmsh.m b/src/m/contrib/morlighem/bamg/gmsh.m index 9bf5875d8..915592036 100644 --- a/src/m/contrib/morlighem/bamg/gmsh.m +++ b/src/m/contrib/morlighem/bamg/gmsh.m @@ -10,7 +10,7 @@ t1=clock; fprintf('%s',' writing initial mesh files...'); fid=fopen('model.geo','w'); fprintf(fid,['// Gmsh input file, created by ISSM on ' date '\n']); -for i=1:nbv, +for i=1:nbv fprintf(fid,'Point(%i) = {%8g, %8g, %8g};\n',i,x(i),y(i),0.); end for i=1:nbv-1 diff --git a/src/m/contrib/morlighem/bamg/gmsh3d.m b/src/m/contrib/morlighem/bamg/gmsh3d.m index 043f257f9..d1ee437a4 100644 --- a/src/m/contrib/morlighem/bamg/gmsh3d.m +++ b/src/m/contrib/morlighem/bamg/gmsh3d.m @@ -12,11 +12,11 @@ fprintf(fid,['// Gmsh input file, created by ISSM on ' date '\n']); %Lower points -for i=1:nbv, +for i=1:nbv fprintf(fid,'Point(%i) = {%8g, %8g, %8g};\n',i,x(i),y(i),0.); end %Upper points -for i=1:nbv, +for i=1:nbv fprintf(fid,'Point(%i) = {%8g, %8g, %8g};\n',nbv+i,x(i),y(i),1.); end @@ -58,7 +58,7 @@ fprintf(fid,['Plane Surface(' num2str(counter+1) ') = {' num2str(counter) '};\n']); counter = counter+2; %Sides surfaces -for i=1:nbv-1, +for i=1:nbv-1 fprintf(fid,['Line Loop(' num2str(counter) ') = {' num2str(i) ',' num2str(2*nbv+i+1) ',-' num2str(nbv+i) ',-' num2str(2*nbv+i) '};\n']); fprintf(fid,['Plane Surface(' num2str(counter+1) ') = {' num2str(counter) '};\n']); ps(2+i)=counter+1; diff --git a/src/m/contrib/morlighem/bamg/meshread.m b/src/m/contrib/morlighem/bamg/meshread.m index cffb9c61d..b30844264 100644 --- a/src/m/contrib/morlighem/bamg/meshread.m +++ b/src/m/contrib/morlighem/bamg/meshread.m @@ -1,34 +1,34 @@ function Struct=meshread(filename) %some checks -if ~exist(filename), +if ~exist(filename) error(['meshread error message: file ' filename ' not found!']); end fid=fopen(filename,'r'); -while (~feof(fid)), +while (~feof(fid)) A=fscanf(fid,'%s',1); if strcmp(A,'MeshVersionFormatted'); Struct.Version=fscanf(fid,'%s',1); - elseif strcmp(A,'Dimension'), + elseif strcmp(A,'Dimension') Struct.Dimension=fscanf(fid,'%i',1); - elseif strcmp(A,'Vertices'), + elseif strcmp(A,'Vertices') Struct.nods=fscanf(fid,'%i',1); A=fscanf(fid,'%f %f %f',[3 Struct.nods]); Struct.x=A(1,:)'; Struct.y=A(2,:)'; - elseif strcmp(A,'Triangles'), + elseif strcmp(A,'Triangles') Struct.nels=fscanf(fid,'%i',1); A=fscanf(fid,'%i %i %i',[4 Struct.nels]); Struct.index=A(1:3,:)'; - elseif strcmp(A,'Quadrilaterals'), + elseif strcmp(A,'Quadrilaterals') Struct.nels=fscanf(fid,'%i',1); A=fscanf(fid,'%i %i %i %i',[5 Struct.nels]); Struct.index=A(1:4,:)'; diff --git a/src/m/contrib/morlighem/bamg/yams.m b/src/m/contrib/morlighem/bamg/yams.m index 457927bcc..fb5f79d11 100644 --- a/src/m/contrib/morlighem/bamg/yams.m +++ b/src/m/contrib/morlighem/bamg/yams.m @@ -64,12 +64,12 @@ Vel=load(velocities); %start mesh adaptation -for i=1:nsteps, +for i=1:nsteps disp(['Iteration #' num2str(i) '/' num2str(nsteps)]); %interpolate velocities onto mesh disp(' interpolating velocities...'); - if strcmpi(Names.interp,'node'), + if strcmpi(Names.interp,'node') vx_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0); vy_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0); else @@ -84,7 +84,7 @@ %if we have rifts, we just messed them up, we need to recreate the segments that constitute those %rifts, because the segments are used in YamsCall to freeze the rifts elements during refinement. - if md.rifts.numrifts, + if md.rifts.numrifts md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices); md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity); md.mesh.segments=findsegments(md); @@ -107,7 +107,7 @@ md.mesh.z=zeros(md.mesh.numberofvertices,1); md.mesh.vertexonbase=ones(md.mesh.numberofvertices,1); md.mesh.vertexonsurface=ones(md.mesh.numberofvertices,1); -if strcmpi(Names.interp,'node'), +if strcmpi(Names.interp,'node') md.inversion.vx_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,0); md.inversion.vy_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,0); else @@ -117,12 +117,12 @@ md.inversion.vel_obs=sqrt(md.inversion.vx_obs.^2+md.inversion.vy_obs.^2); %deal with rifts -if md.rifts.numrifts, +if md.rifts.numrifts %first, recreate rift segments md=meshyamsrecreateriftsegments(md); %using the segments, recreate the penaltypairs - for j=1:md.rifts.numrifts, + for j=1:md.rifts.numrifts rift=md.rifts.riftstruct(j); %build normals and lengths of segments: @@ -134,7 +134,7 @@ numpenaltypairs=length(rift.segments)/2-1; rift.penaltypairs=zeros(numpenaltypairs,7); - for i=1:numpenaltypairs, + for i=1:numpenaltypairs rift.penaltypairs(i,1)=rift.segments(i,2); rift.penaltypairs(i,2)=rift.segments(end-i,2); rift.penaltypairs(i,3)=rift.segments(i,3); diff --git a/src/m/contrib/morlighem/dassflow/importgmsh.m b/src/m/contrib/morlighem/dassflow/importgmsh.m index 433fcc20c..79bde0fc1 100644 --- a/src/m/contrib/morlighem/dassflow/importgmsh.m +++ b/src/m/contrib/morlighem/dassflow/importgmsh.m @@ -1,7 +1,7 @@ function md = importgmsh(filename,dim) %some checks -if ~exist(filename), +if ~exist(filename) error(['expread error message: file ' filename ' not found!']); end @@ -10,18 +10,18 @@ %Get Mesh format A=fscanf(fid,'%s',1); -if ~strcmp(A,'$MeshFormat'), +if ~strcmp(A,'$MeshFormat') error(['Expecting $MeshFormat (' A ')']); end A=fscanf(fid,'%f %i %i',[1 3]); A=fscanf(fid,'%s',1); -if ~strcmp(A,'$EndMeshFormat'), +if ~strcmp(A,'$EndMeshFormat') error(['Expecting $EndMeshFormat (' A ')']); end %Nodes A=fscanf(fid,'%s',1); -if ~strcmp(A,'$Nodes'), +if ~strcmp(A,'$Nodes') error(['Expecting $Nodes (' A ')']); end nbv=fscanf(fid,'%i',1); @@ -32,23 +32,23 @@ z = A(4,:)'; A=fscanf(fid,'%s',1); -if ~strcmp(A,'$EndNodes'), +if ~strcmp(A,'$EndNodes') error(['Expecting $EndNodes (' A ')']); end %Elements A=fscanf(fid,'%s',1); -if ~strcmp(A,'$Elements'), +if ~strcmp(A,'$Elements') error(['Expecting $Elements (' A ')']); end nbt=fscanf(fid,'%i',1); disp(['Number of elements: ' num2str(nbt) ]); counter = 0; -if (dim==2), +if (dim==2) index = zeros(0,3); segments = zeros(0,2); segmentmarkers = zeros(0,1); -elseif (dim==3), +elseif (dim==3) index = zeros(0,4); segments = zeros(0,3); segmentmarkers = zeros(0,1); @@ -106,17 +106,17 @@ end %recreate segments -if dim==2, +if dim==2 nbs = size(segments,1); segments = [segments zeros(nbs,1)]; - for i=1:nbs, + for i=1:nbs E = find(sum(ismember(index,segments(i,:)),2)>1); segments(i,3)=E; end else nbs = size(segments,1); segments = [segments zeros(nbs,1)]; - for i=1:nbs, + for i=1:nbs E = find(sum(ismember(index,segments(i,:)),2)>2); segments(i,4)=E; end diff --git a/src/m/contrib/morlighem/gslib/gamv.m b/src/m/contrib/morlighem/gslib/gamv.m index 91e424d7a..93d42ecba 100644 --- a/src/m/contrib/morlighem/gslib/gamv.m +++ b/src/m/contrib/morlighem/gslib/gamv.m @@ -52,13 +52,13 @@ counter1 = 1; counter2 = 1; fid=fopen('gamv.out','r'); -while (~feof(fid)), +while (~feof(fid)) A=fscanf(fid,'%s',1); if strcmp(A,'Covariance'); A=fscanf(fid,'%s',4); %Read tail:Data head:Data direction 2 output(counter1).Covariance=fscanf(fid,'%i %g %g %i %g %g',[6 nlag+2])'; counter1=counter1+1; - elseif strcmp(A,'Semivariogram'), + elseif strcmp(A,'Semivariogram') A=fscanf(fid,'%s',4); %Read tail:Data head:Data direction 2 output(counter2).Semivariogram=fscanf(fid,'%i %g %g %i %g %g',[6 nlag+2])'; counter2=counter2+1; diff --git a/src/m/contrib/morlighem/gslib/gslib.m b/src/m/contrib/morlighem/gslib/gslib.m index afb58b6b5..2adac678f 100644 --- a/src/m/contrib/morlighem/gslib/gslib.m +++ b/src/m/contrib/morlighem/gslib/gslib.m @@ -87,14 +87,14 @@ %Read output fid=fopen('kb2d.out','r'); - while (~feof(fid)), + while (~feof(fid)) A=fscanf(fid,'%s',1); if strcmp(A,'KB2D'); A=fscanf(fid,'%s',1); %Read output params=fscanf(fid,'%i %i %i %i %g %g %g %g %g %g %1',[11 1]); - elseif strcmp(A,' Estimate'), + elseif strcmp(A,' Estimate') continue; - elseif strcmp(A,'Estimation'), + elseif strcmp(A,'Estimation') A=fscanf(fid,'%s',1); %Read Variance A=fscanf(fid,'%g %g',[params(1) params(2)*params(3)]); B=A(1,:); B=reshape(B,[params(3),params(2)])'; diff --git a/src/m/contrib/morlighem/gslib/pkriging.m b/src/m/contrib/morlighem/gslib/pkriging.m index f65a17a9b..bb286d2ce 100644 --- a/src/m/contrib/morlighem/gslib/pkriging.m +++ b/src/m/contrib/morlighem/gslib/pkriging.m @@ -9,13 +9,28 @@ options=removefield(options,'cluster',0); name = ['krig' num2str(feature('GetPid'))]; -if 1 +%Prepare directory in execution +if strcmpi(cluster.name, oshostname()) + localexecdir = cluster.executionpath; +else + localexecdir = [issmdir() '/execution/']; +end +if ~exist(localexecdir, 'dir') + error(['Could not find directory ' issmdir() '/execution/']); +elseif numel(dir(localexecdir))>200 + warning([localexecdir ' has more than 200 subdirectories. Consider cleaning up your execution directory']) +end +root = [localexecdir '/' name]; +if exist(root, 'dir') + rmdir(root, 's'); +end +mkdir(root); +basename = [root '/' name]; + % ========================================= MARSHALL.m ================================================= disp(['marshalling file ' name '.bin']); -fid=fopen([name '.bin'],'wb'); -if fid==-1, - error(['marshall error message: could not open ' name '.bin file for binary writing']); -end +fid=fopen([basename '.bin'],'wb'); +if(fid==-1) error(['marshall error message: could not open ' name '.bin file for binary writing']); end %Write all data WriteData(fid,'','name','md.x','data',x,'format','DoubleMat'); @@ -23,26 +38,22 @@ WriteData(fid,'','name','md.data','data',observations,'format','DoubleMat'); WriteData(fid,'','name','md.x_interp','data',x_interp,'format','DoubleMat'); WriteData(fid,'','name','md.y_interp','data',y_interp,'format','DoubleMat'); - -%Now, write number of options options.marshall(fid); - -%Last, write "md.EOF" to make sure that the binary file is not corrupt WriteData(fid,'','name','md.EOF','data',true,'format','Boolean'); +fclose(fid); %Fake md as a place holder md=model; md.cluster=cluster; md.settings.waitonlock=Inf; md.private.runtimename=name;md.miscellaneous.name=name; %Launch job on remote cluster -BuildKrigingQueueScript(cluster, md, [name '.queue']); -UploadQueueJob(cluster,name,name,{[name '.bin'] [name '.queue']}) -LaunchQueueJob(cluster,name,name,{[name '.bin'] [name '.queue']},'',0); +BuildQueueScript(cluster, md, [basename '.queue'], 'kriging.exe'); +UploadQueueJob(cluster,name,name,{[basename '.bin'] [basename '.queue']}) +LaunchQueueJob(cluster,name,name,{[basename '.bin'] [basename '.queue']},'',0); %Call waitonlock waitonlock(md); %Download -end Download(cluster,name,{[name '.outbin']}); structure=parseresultsfromdisk(md,[name '.outbin'],0); delete([name '.outlog']); diff --git a/src/m/contrib/morlighem/massbalance/contourmassbalance.m b/src/m/contrib/morlighem/massbalance/contourmassbalance.m index 0e8bb0691..85f3d45e7 100644 --- a/src/m/contrib/morlighem/massbalance/contourmassbalance.m +++ b/src/m/contrib/morlighem/massbalance/contourmassbalance.m @@ -5,14 +5,14 @@ % dhdt=contourmassbalance(md,file) %some checks -if nargin~=2, +if nargin~=2 help contourmassbalance error('contourmassbalance error message: bad usage'); end if ((length(md.initialization.vx)~=md.mesh.numberofvertices)|(length(md.initialization.vy)~=md.mesh.numberofvertices)) error(['thicknessevolution error message: vx and vy should have a length of ' num2str(md.mesh.numberofvertices)]) end -if ~exist(file), +if ~exist(file) error(['thicknessevolution error message: file ' file ' not found']); end diff --git a/src/m/contrib/morlighem/massbalance/divergence.m b/src/m/contrib/morlighem/massbalance/divergence.m index fe080ed6d..45d438e3d 100644 --- a/src/m/contrib/morlighem/massbalance/divergence.m +++ b/src/m/contrib/morlighem/massbalance/divergence.m @@ -4,11 +4,11 @@ % Usage: % div=divergence(md,a,b) -if (dimension(md.mesh)==2), +if (dimension(md.mesh)==2) numberofelements=md.mesh.numberofelements; numberofnodes=md.mesh.numberofvertices; index=md.mesh.elements; - x=md.mesh.x; y=md.mesh.y; z=md.mesh.z; + x=md.mesh.x; y=md.mesh.y; %z=md.mesh.z; else numberofelements=md.mesh.numberofelements2d; numberofnodes=md.mesh.numberofvertices2d; diff --git a/src/m/contrib/morlighem/massbalance/outflux.m b/src/m/contrib/morlighem/massbalance/outflux.m index 983515c1c..c7dd1e6ed 100644 --- a/src/m/contrib/morlighem/massbalance/outflux.m +++ b/src/m/contrib/morlighem/massbalance/outflux.m @@ -14,8 +14,8 @@ Nx=lx./L; Ny=ly./L; -if nargin==1, - if dimension(md.mesh)==3, +if nargin==1 + if dimension(md.mesh)==3 vxa=DepthAverage(md,md.initialization.vx); vya=DepthAverage(md,md.initialization.vy); else @@ -27,7 +27,7 @@ H=(md.geometry.thickness(A)+md.geometry.thickness(B))/2; else step=varargin{1}; - if dimension(md.mesh)==3, + if dimension(md.mesh)==3 vxa=DepthAverage(md,md.results.TransientSolution(step).Vx); vya=DepthAverage(md,md.results.TransientSolution(step).Vy); else diff --git a/src/m/contrib/morlighem/sia.m b/src/m/contrib/morlighem/sia.m index 736b63e7d..e53feb892 100644 --- a/src/m/contrib/morlighem/sia.m +++ b/src/m/contrib/morlighem/sia.m @@ -13,7 +13,7 @@ rhog = (md.materials.rho_ice*md.constants.g); -if md.mesh.dimension==2, +if md.mesh.dimension==2 %Get slope [sx,sy,s]=slope(md); diff --git a/src/m/contrib/tsantos/AMRexportVTK.m b/src/m/contrib/tsantos/AMRexportVTK.m index c9b229bf9..178c02a8a 100644 --- a/src/m/contrib/tsantos/AMRexportVTK.m +++ b/src/m/contrib/tsantos/AMRexportVTK.m @@ -17,7 +17,7 @@ function AMRexportVTK(filename,model,varargin) mkdir(filename); %get the element related variables -if dimension(model.mesh)==2, +if dimension(model.mesh)==2 points=[model.mesh.x model.mesh.y zeros(model.mesh.numberofvertices,1)]; else error('Dimension not supported yet \n'); @@ -173,7 +173,7 @@ function AMRexportVTK(filename,model,varargin) %also checking for verry small value that mess up smallval=(abs(res_struct.(fieldnames{k}))<1.0e-20); res_struct.(fieldnames{k})(smallval)=0.0; - if (size(res_struct.(fieldnames{k}),2)==num_of_timesteps), + if (size(res_struct.(fieldnames{k}),2)==num_of_timesteps) fprintf(fid,'SCALARS %s float 1 \n',fieldnames{k}); fprintf(fid,'LOOKUP_TABLE default\n'); s='%e\n'; @@ -200,9 +200,9 @@ function AMRexportVTK(filename,model,varargin) end lowtime=res_struct.(fieldnames{k})(end,index); lowlim=res_struct.(fieldnames{k})(1:end-1,index); - if uptime==currenttime, + if uptime==currenttime interp=uplim; - elseif lowtime==currenttime, + elseif lowtime==currenttime interp=lowlim; else interp=lowlim+(uplim-lowlim)*((currenttime-lowtime)/(uptime-lowtime)); diff --git a/src/m/contrib/tsantos/mismip/MismipGLPosition.m b/src/m/contrib/tsantos/mismip/MismipGLPosition.m index d64a450f9..68297c740 100644 --- a/src/m/contrib/tsantos/mismip/MismipGLPosition.m +++ b/src/m/contrib/tsantos/mismip/MismipGLPosition.m @@ -7,7 +7,7 @@ GLy40 = []; nsteps = length(t); - for i=1:nsteps, + for i=1:nsteps xi = xGL(i,:); yi = yGL(i,:); diff --git a/src/m/contrib/tsantos/mismip/gl_position.m b/src/m/contrib/tsantos/mismip/gl_position.m index 6f9d02795..68361307d 100644 --- a/src/m/contrib/tsantos/mismip/gl_position.m +++ b/src/m/contrib/tsantos/mismip/gl_position.m @@ -67,7 +67,7 @@ numelems=length(poselem); %if no element has been flagged, skip to the next level - if numelems==0, + if numelems==0 return, end @@ -78,7 +78,7 @@ y2=zeros(numelems,1); edge_l=zeros(numelems,2); - for j=1:numelems, + for j=1:numelems weight1=(level-Data1(poselem(j),1))/(Data1(poselem(j),2)-Data1(poselem(j),1)); weight2=(level-Data2(poselem(j),1))/(Data2(poselem(j),2)-Data2(poselem(j),1)); @@ -93,7 +93,7 @@ edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg2_num(poselem(j)); - elseif poselem13(poselem(j)), + elseif poselem13(poselem(j)) x1(j)=x(Seg1(poselem(j),1))+weight1*(x(Seg1(poselem(j),2))-x(Seg1(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -102,7 +102,7 @@ edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg3_num(poselem(j)); - elseif poselem23(poselem(j)), + elseif poselem23(poselem(j)) x1(j)=x(Seg2(poselem(j),1))+weight2*(x(Seg2(poselem(j),2))-x(Seg2(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -119,7 +119,7 @@ %loop over the subcontours indice=0; - while ~isempty(edge_l), + while ~isempty(edge_l) indice=indice+1; %take the right edge of the second segment and connect it to the next segments if any @@ -135,7 +135,7 @@ while ~isempty(ro1) - if co1==1, + if co1==1 xc=[x2(ro1);xc]; yc=[y2(ro1);yc]; %next edge: @@ -162,7 +162,7 @@ while ~isempty(ro2) - if co2==1, + if co2==1 xc=[xc;x2(ro2)]; yc=[yc;y2(ro2)]; %next edge: diff --git a/src/m/contrib/tsantos/mismip/gl_position_static.m b/src/m/contrib/tsantos/mismip/gl_position_static.m index 68dae3a5b..96c6e30e9 100644 --- a/src/m/contrib/tsantos/mismip/gl_position_static.m +++ b/src/m/contrib/tsantos/mismip/gl_position_static.m @@ -67,7 +67,7 @@ numelems=length(poselem); %if no element has been flagged, skip to the next level - if numelems==0, + if numelems==0 return, end @@ -78,7 +78,7 @@ y2=zeros(numelems,1); edge_l=zeros(numelems,2); - for j=1:numelems, + for j=1:numelems weight1=(level-Data1(poselem(j),1))/(Data1(poselem(j),2)-Data1(poselem(j),1)); weight2=(level-Data2(poselem(j),1))/(Data2(poselem(j),2)-Data2(poselem(j),1)); @@ -93,7 +93,7 @@ edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg2_num(poselem(j)); - elseif poselem13(poselem(j)), + elseif poselem13(poselem(j)) x1(j)=x(Seg1(poselem(j),1))+weight1*(x(Seg1(poselem(j),2))-x(Seg1(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -102,7 +102,7 @@ edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg3_num(poselem(j)); - elseif poselem23(poselem(j)), + elseif poselem23(poselem(j)) x1(j)=x(Seg2(poselem(j),1))+weight2*(x(Seg2(poselem(j),2))-x(Seg2(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -119,7 +119,7 @@ %loop over the subcontours indice=0; - while ~isempty(edge_l), + while ~isempty(edge_l) indice=indice+1; %take the right edge of the second segment and connect it to the next segments if any @@ -135,7 +135,7 @@ while ~isempty(ro1) - if co1==1, + if co1==1 xc=[x2(ro1);xc]; yc=[y2(ro1);yc]; %next edge: @@ -162,7 +162,7 @@ while ~isempty(ro2) - if co2==1, + if co2==1 xc=[xc;x2(ro2)]; yc=[yc;y2(ro2)]; %next edge: diff --git a/src/m/contrib/tsantos/mismip/ice_evolution.m b/src/m/contrib/tsantos/mismip/ice_evolution.m index 890eed848..f2a53bd33 100644 --- a/src/m/contrib/tsantos/mismip/ice_evolution.m +++ b/src/m/contrib/tsantos/mismip/ice_evolution.m @@ -56,7 +56,7 @@ nsteps = length(md.results.TransientSolution); - for i=i0:nsteps, + for i=i0:nsteps ga(i) = md.results.TransientSolution(i).GroundedArea; iv(i) = md.results.TransientSolution(i).IceVolume; ivaf(i) = md.results.TransientSolution(i).IceVolumeAboveFloatation; diff --git a/src/m/contrib/tsantos/mismip/if_position.m b/src/m/contrib/tsantos/mismip/if_position.m index 920b32e22..0b106883e 100755 --- a/src/m/contrib/tsantos/mismip/if_position.m +++ b/src/m/contrib/tsantos/mismip/if_position.m @@ -66,7 +66,7 @@ numelems=length(poselem); %if no element has been flagged, skip to the next level - if numelems==0, + if numelems==0 return, end @@ -77,7 +77,7 @@ y2=zeros(numelems,1); edge_l=zeros(numelems,2); - for j=1:numelems, + for j=1:numelems weight1=(level-Data1(poselem(j),1))/(Data1(poselem(j),2)-Data1(poselem(j),1)); weight2=(level-Data2(poselem(j),1))/(Data2(poselem(j),2)-Data2(poselem(j),1)); @@ -92,7 +92,7 @@ edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg2_num(poselem(j)); - elseif poselem13(poselem(j)), + elseif poselem13(poselem(j)) x1(j)=x(Seg1(poselem(j),1))+weight1*(x(Seg1(poselem(j),2))-x(Seg1(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -101,7 +101,7 @@ edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg3_num(poselem(j)); - elseif poselem23(poselem(j)), + elseif poselem23(poselem(j)) x1(j)=x(Seg2(poselem(j),1))+weight2*(x(Seg2(poselem(j),2))-x(Seg2(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -118,7 +118,7 @@ %loop over the subcontours indice=0; - while ~isempty(edge_l), + while ~isempty(edge_l) indice=indice+1; %take the right edge of the second segment and connect it to the next segments if any @@ -134,7 +134,7 @@ while ~isempty(ro1) - if co1==1, + if co1==1 xc=[x2(ro1);xc]; yc=[y2(ro1);yc]; %next edge: @@ -161,7 +161,7 @@ while ~isempty(ro2) - if co2==1, + if co2==1 xc=[xc;x2(ro2)]; yc=[yc;y2(ro2)]; %next edge: diff --git a/src/m/contrib/tsantos/mismip/writeNetCDF.m b/src/m/contrib/tsantos/mismip/writeNetCDF.m index 35ea68b83..476b7fe8b 100644 --- a/src/m/contrib/tsantos/mismip/writeNetCDF.m +++ b/src/m/contrib/tsantos/mismip/writeNetCDF.m @@ -29,7 +29,7 @@ function writeNetCDF(md0,md,step,dt,ncfile), uBaseGL{1} = griddata(x,y,md0.results.TransientSolution(end).Vx,xgl_step,ygl_step); vBaseGL{1} = griddata(x,y,md0.results.TransientSolution(end).Vy,xgl_step,ygl_step); - for i=2:length(step), + for i=2:length(step) if(isfield(md.results.TransientSolution,'MeshElements')) x = md.results.TransientSolution(step(i)).MeshX; y = md.results.TransientSolution(step(i)).MeshY; @@ -102,7 +102,7 @@ function writeNetCDF(md0,md,step,dt,ncfile), netcdf.putVar(ncid,volume_var_id,iceVolume); netcdf.putVar(ncid,VAF_var_id,iceVAF); netcdf.putVar(ncid,grounded_var_id,groundedArea); - for i=1:length(time), + for i=1:length(time) netcdf.putVar(ncid,xgl_var_id,[i-1,0],[1,length(xGL{i})],xGL{i}'); netcdf.putVar(ncid,ygl_var_id,[i-1,0],[1,length(xGL{i})],yGL{i}'); netcdf.putVar(ncid,thickness_var_id,[i-1,0],[1,length(xGL{i})],iceThicknessGL{i}'); diff --git a/src/m/contrib/tsantos/remesh.m b/src/m/contrib/tsantos/remesh.m index 835b77163..79de76aa7 100644 --- a/src/m/contrib/tsantos/remesh.m +++ b/src/m/contrib/tsantos/remesh.m @@ -1,6 +1,6 @@ function mdOut = remesh(md,parfile,time_step) %Set the new mesh (refined) into the model md -if nargin<3, +if nargin<3 time_step=length(md.results.TransientSolution); end @@ -21,15 +21,15 @@ segments(:,1) = k(1:nsegments); segments(:,2) = k(2:(nsegments+1)); disp('Building segments: searching boundary elements...'); -for s=1:nsegments, - for e=1:nelements, +for s=1:nsegments + for e=1:nelements if any(NewModel.mesh.elements(e,:)==segments(s,1)) && any(NewModel.mesh.elements(e,:)==segments(s,2)) segments(s,3)=e; break; end end - if segments(s,3)==0, + if segments(s,3)==0 %error('Element not found!'); end end diff --git a/src/m/coordsystems/flaglatlongradius.m b/src/m/coordsystems/flaglatlongradius.m index ecffef921..8938fb57f 100644 --- a/src/m/coordsystems/flaglatlongradius.m +++ b/src/m/coordsystems/flaglatlongradius.m @@ -4,9 +4,9 @@ % lat and long should be between -90 and 90, and -180 and +180 respectively. %three cases, depending on whether our circle goes past the -180 +180 longitude line: - if (long0-radius)<=-180, + if (long0-radius)<=-180 pos=find(long>0); long(pos)=long(pos)-360; - elseif (long0+radius)>=180, + elseif (long0+radius)>=180 pos=find(long<0); long(pos)=360+long(pos); else end diff --git a/src/m/coordsystems/flaglatlongradiuselements.m b/src/m/coordsystems/flaglatlongradiuselements.m index 90202ec1f..b61b9cd00 100644 --- a/src/m/coordsystems/flaglatlongradiuselements.m +++ b/src/m/coordsystems/flaglatlongradiuselements.m @@ -6,9 +6,9 @@ distance=sqrt( (lat-lat0).^2+ (long-long0).^2); %three cases, depending on whether our circle goes past the -180 +180 longitude line: - if (long0-radius)<=-180, + if (long0-radius)<=-180 pos=find(long>0); long(pos)=long(pos)-360; - elseif (long0+radius)>=180, + elseif (long0+radius)>=180 pos=find(long<0); long(pos)=360+long(pos); else end @@ -17,7 +17,7 @@ %now that we know the indices, determine elements which own these indices: outelements=zeros(length(elements),1); - for i=1:length(indices), + for i=1:length(indices) [pos,dummy]=find(elements==indices(i)); outelements(pos)=1; end diff --git a/src/m/coordsystems/flagradiuselements.m b/src/m/coordsystems/flagradiuselements.m index 0c093dab9..f13928d10 100644 --- a/src/m/coordsystems/flagradiuselements.m +++ b/src/m/coordsystems/flagradiuselements.m @@ -12,7 +12,7 @@ %now that we know the indices, determine elements which own these indices: outelements=zeros(length(elements),1); - for i=1:length(indices), + for i=1:length(indices) [pos,dummy]=find(elements==indices(i)); outelements(pos)=1; end diff --git a/src/m/coordsystems/gdaltransform.m b/src/m/coordsystems/gdaltransform.m index 0242d5b07..5b4fa3a8e 100644 --- a/src/m/coordsystems/gdaltransform.m +++ b/src/m/coordsystems/gdaltransform.m @@ -31,7 +31,7 @@ fclose(fid); [s,r]=system(['gdaltransform -s_srs "',proj_in,'" -t_srs "',proj_out,'" < ' filename_in ' > ' filename_out]); - if s~=0 | ~isempty(deblank(r)), + if s~=0 | ~isempty(deblank(r)) error(r); end diff --git a/src/m/coordsystems/gmtmask.m b/src/m/coordsystems/gmtmask.m index f7ff63888..e23a96add 100644 --- a/src/m/coordsystems/gmtmask.m +++ b/src/m/coordsystems/gmtmask.m @@ -9,7 +9,7 @@ % gmtmaskparallel.m %are we doing a recursive call? - if nargin==3, + if nargin==3 recursive=1; else recursive=0; @@ -20,10 +20,10 @@ end %Check lat and long size is not more than 50,000; If so, recursively call gmtmask: - if length(lat)>50000, - for i=1:50000:length(lat), + if length(lat)>50000 + for i=1:50000:length(lat) j=i+50000-1; - if j>length(lat), + if j>length(lat) j=length(lat); end mask(i:j)=gmtmask(lat(i:j),long(i:j),1); @@ -45,13 +45,13 @@ % gmt_select_options='-Ve -h0 -Df -R0/360/-90/90 -A0 -JQ180/200 -Nk/s/s/k/s'; [status,result]=system(['gmt select ./' filename_all ' ' gmt_select_options ' > ./' filename_oce]); - if status~=0, + if status~=0 disp(['gmt select failed with: ' result]); disp(['trying again with gmtselect']); %assume we are working with GMT 6.0.0 gmt_select_options='-h0 -Df -R0/360/-90/90 -A0 -JQ180/200 -Nk/s/s/k/s'; [status,result] = system(['gmtselect ./' filename_all ' ' gmt_select_options ' > ./' filename_oce]); - if status~=0, + if status~=0 error(result); end end @@ -61,7 +61,7 @@ line=fgets(fid); line=fgets(fid); oce_vertices=[]; - while line~=-1, + while line~=-1 ind=str2num(line); ind=ind(3); oce_vertices=[oce_vertices;ind]; line=fgets(fid); diff --git a/src/m/coordsystems/gmtmaskparallel.m b/src/m/coordsystems/gmtmaskparallel.m index 89960f9e8..fd74c6c88 100644 --- a/src/m/coordsystems/gmtmaskparallel.m +++ b/src/m/coordsystems/gmtmaskparallel.m @@ -16,11 +16,11 @@ nnv(end)=nv+1; %For each segment, write all vertices file: - for i=1:length(nnv)-1, + for i=1:length(nnv)-1 dlmwrite(['./all_vertices' num2str(i) '.txt'],[long(nnv(i):nnv(i+1)-1) lat(nnv(i):nnv(i+1)-1) (nnv(i):nnv(i+1)-1)'],'delimiter','\t','precision',7); end - if ismac, + if ismac dyld_library_path_old=getenv('DYLD_LIBRARY_PATH'); setenv('DYLD_LIBRARY_PATH',[ issmdir '/externalpackages/curl/install/lib:' issmdir '/externalpackages/hdf5/install/lib:' issmdir '/externalpackages/netcdf/install/lib' ]); end @@ -29,17 +29,17 @@ paths = {[issmdir() '/bin'],[issmdir() '/externalpackages/gmt/install/bin'],'/Applications/GMT-5.4.3.app/Contents/Resources/bin'}; gmt_path = ''; for i=paths - if exist([i{1} '/gmt'],'file'), + if exist([i{1} '/gmt'],'file') gmt_path = i{1}; break; end end - if isempty(gmt_path), + if isempty(gmt_path) error('gmt not found, make sure it is properly installed, or add its path to this file (line 26)'); end %Figure out if we have gmtselect executable - if exist([gmt_path '/gmtselect'],'file'), + if exist([gmt_path '/gmtselect'],'file') gmt_exec=[gmt_path '/gmtselect']; else, gmt_exec=[gmt_path '/gmtselect']; @@ -47,7 +47,7 @@ %Build xjobs script: fid=fopen('xjobs.script','w'); - for i=1:length(nnv)-1, + for i=1:length(nnv)-1 fprintf(fid,'%s ./all_vertices%i.txt -h0 -Df -R0/360/-90/90 -A0 -JQ180/200 -Nk/s/s/k/s > ./oce_vertices%i.txt\n',gmt_exec,i,i); end fclose(fid); @@ -56,7 +56,7 @@ system(sprintf('xjobs -j %i -s ./xjobs.script',ncores)); %reset DYLD_LIBRARY_PATH to what it was: - if ismac, + if ismac setenv('DYLD_LIBRARY_PATH',dyld_library_path_old); end diff --git a/src/m/coordsystems/lambert2xy.m b/src/m/coordsystems/lambert2xy.m index 1d0caea62..3097b679f 100755 --- a/src/m/coordsystems/lambert2xy.m +++ b/src/m/coordsystems/lambert2xy.m @@ -15,14 +15,14 @@ % -1 S hemisphere [default projection center lat = -90 lon=0] %Get projection_center_lat and projection_center_lon -if nargin==5, +if nargin==5 latitude0 = projection_center_lat; longitude0 = projection_center_lon; -elseif nargin==3, - if sgn==1, +elseif nargin==3 + if sgn==1 latitude0 = 90; longitude0 = 0; disp('Info: creating coordinates in polar stereographic (Projection center lat: 90N lon: 0)'); - elseif sgn==-1, + elseif sgn==-1 latitude0 = -90; longitude0 = 0; disp('Info: creating coordinates in polar stereographic (Projection center lat: 90S lon: 0)'); else diff --git a/src/m/coordsystems/ll2xy.m b/src/m/coordsystems/ll2xy.m index 4578e4233..fcdfc3e5e 100644 --- a/src/m/coordsystems/ll2xy.m +++ b/src/m/coordsystems/ll2xy.m @@ -16,14 +16,14 @@ % -1 : south latitude (default is mer=0 lat=71) %Get central_meridian and standard_parallel depending on hemisphere -if nargin==5, +if nargin==5 delta = central_meridian; slat = standard_parallel; elseif nargin==3 - if sgn == 1, + if sgn == 1 delta = 45; slat = 70; disp('Info: creating coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)'); - elseif sgn==-1, + elseif sgn==-1 delta = 0; slat = 71; disp('Info: creating coordinates in polar stereographic (Std Latitude: 71ºS Meridian: 0º)'); else @@ -34,7 +34,7 @@ error('bad usage'); end -if nargout~=3 & nargout~=2, +if nargout~=3 & nargout~=2 help ll2xy error('bad usage'); end @@ -79,7 +79,7 @@ y(cnt1) = 0.0; end -if nargout==3, +if nargout==3 m=((1+sin(abs(slat)*pi/180))*ones(length(lat),1)./(1+sin(abs(lat)*pi/180))); scale_factor=(1./m).^2; end diff --git a/src/m/coordsystems/xy2lambert.m b/src/m/coordsystems/xy2lambert.m index 690706fd9..8ae0bb883 100755 --- a/src/m/coordsystems/xy2lambert.m +++ b/src/m/coordsystems/xy2lambert.m @@ -14,14 +14,14 @@ % -1 S hemisphere [default projection center lat = -90 lon=0] %Get projection_center_lat and projection_center_lon -if nargin==5, +if nargin==5 latitude0 = projection_center_lat; longitude0 = projection_center_lon; -elseif nargin==3, - if sgn==1, +elseif nargin==3 + if sgn==1 latitude0 = 90; longitude0 = 0; disp('Info: creating coordinates in Lambert Azimuthal equal-area (Projection center lat: 90N lon: 0)'); - elseif sgn==-1, + elseif sgn==-1 latitude0 = -90; longitude0 = 0; disp('Info: creating coordinates in Lambert Azimuthal equal-area (Projection center lat: 90S lon: 0)'); else diff --git a/src/m/coordsystems/xy2ll.m b/src/m/coordsystems/xy2ll.m index 59c861ad5..5b76414b0 100644 --- a/src/m/coordsystems/xy2ll.m +++ b/src/m/coordsystems/xy2ll.m @@ -17,14 +17,14 @@ % -1 : south latitude (default is mer=0 lat=71) %Get central_meridian and standard_parallel depending on hemisphere -if nargin==5, +if nargin==5 delta = central_meridian; slat = standard_parallel; elseif nargin==3 - if sgn == 1, + if sgn == 1 delta = 45; slat = 70; disp('Warning: expecting coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)'); - elseif sgn==-1, + elseif sgn==-1 delta = 0; slat = 71; disp('Warning: expecting coordinates in polar stereographic (Std Latitude: 71ºS Meridian: 0º)'); else @@ -79,7 +79,7 @@ lon = lon * 180. / pi; lat = lat * 180. / pi; lon = lon - delta; -if nargout==3, +if nargout==3 m=((1+sin(abs(slat)*pi/180))*ones(length(lat),1)./(1+sin(abs(lat)*pi/180))); scale_factor=(1./m).^2; end diff --git a/src/m/dev/devpath.m b/src/m/dev/devpath.m index 415a17fb1..2aab02708 100755 --- a/src/m/dev/devpath.m +++ b/src/m/dev/devpath.m @@ -2,13 +2,13 @@ lastwarn(''); %Recover ISSM_DIR , or if on a Windows machine, ISSM_DIR_WIN -if ispc, +if ispc ISSM_DIR=getenv('ISSM_DIR_WIN'); else ISSM_DIR=getenv('ISSM_DIR'); end -if (isempty(ISSM_DIR)), +if (isempty(ISSM_DIR)) error('''ISSM_DIR'' environment variable is empty. You should define ISSM_DIR in your .zshrc or .bashrc'); end @@ -31,7 +31,7 @@ addpath(recursivepath([ISSM_DIR '/externalpackages/pcatool'])); %Check on any warning messages that might indicate that the paths were not correct. -if ~isempty(lastwarn), +if ~isempty(lastwarn) fprintf('\n Error trying to setup ''ISSM'' code paths. Try and update the ISSM_DIR variable in your .zshrc or .bashrc\n'); fprintf(' ''ISSM'' will not work at all until this is resolved\n\n'); else diff --git a/src/m/dev/issmversion.m b/src/m/dev/issmversion.m index 75fb20248..10a8ac60c 100644 --- a/src/m/dev/issmversion.m +++ b/src/m/dev/issmversion.m @@ -1,12 +1,11 @@ -function vers = issmversion(), +function vers = issmversion() %ISSMVERSION - display ISSM version % % Usage: % issmversion() % version = issmversion() - -if exist('IssmConfig_matlab')~=3, +if exist('IssmConfig_matlab')~=3 error('ISSM not correctly installed. "IssmConfig_matlab" not found'); end diff --git a/src/m/dev/issmversion.py b/src/m/dev/issmversion.py index 6f7844fb2..51657a0a1 100644 --- a/src/m/dev/issmversion.py +++ b/src/m/dev/issmversion.py @@ -1,6 +1,5 @@ from IssmConfig import IssmConfig - def issmversion(): """ ISSMVERSION - display ISSM version @@ -9,7 +8,6 @@ def issmversion(): issmversion() """ - print(' ') print((IssmConfig('PACKAGE_NAME')[0] + ' Version ' + IssmConfig('PACKAGE_VERSION')[0])) print(('(website: ' + IssmConfig('PACKAGE_URL')[0] + ' contact: ' + IssmConfig('PACKAGE_BUGREPORT')[0] + ')')) diff --git a/src/m/exp/exp2shp.m b/src/m/exp/exp2shp.m index bdb314bc7..d3cafb2d2 100644 --- a/src/m/exp/exp2shp.m +++ b/src/m/exp/exp2shp.m @@ -13,12 +13,12 @@ function exp2shp(expfilename,shpfilename,geometry) %check file extensions [pathstr,name,ext] = fileparts(shpfilename); -if ~strcmp(ext,'.shp'), +if ~strcmp(ext,'.shp') error(['Shapefile ' shpfilename ' does not have an extension .shp']); end [pathstr,name,ext] = fileparts(expfilename); -if ~strcmp(ext,'.exp'), +if ~strcmp(ext,'.exp') error(['Exp file ' expfilename ' does not have an extension .exp']); end @@ -28,7 +28,7 @@ function exp2shp(expfilename,shpfilename,geometry) count=1; contours=struct([]); -for i=1:length(shp), +for i=1:length(shp) if nargin < 3 %TEMP @@ -46,7 +46,7 @@ function exp2shp(expfilename,shpfilename,geometry) elseif length(shp(i).x) < 3 geometry = 'Line'; else - if (shp(i).x(end)==shp(i).x(1) && shp(i).y(end)==shp(i).y(1)), + if (shp(i).x(end)==shp(i).x(1) && shp(i).y(end)==shp(i).y(1)) geometry = 'Polygon'; else geometry = 'Line'; diff --git a/src/m/exp/expbox.m b/src/m/exp/expbox.m index 716fdddbe..b20296168 100644 --- a/src/m/exp/expbox.m +++ b/src/m/exp/expbox.m @@ -8,9 +8,9 @@ function expbox(filename) % expbox(filename) %check -if exist(filename,'file'), +if exist(filename,'file') choice=input(['A file ' filename ' already exists, do you want to modify it? (y/n)'],'s'); - if ~strcmpi(choice,'y'), + if ~strcmpi(choice,'y') disp('no modification done ... exiting'); return end diff --git a/src/m/exp/expcoarsen.m b/src/m/exp/expcoarsen.m index f62522a6f..b122746cb 100644 --- a/src/m/exp/expcoarsen.m +++ b/src/m/exp/expcoarsen.m @@ -12,10 +12,10 @@ function expcoarsen(newfile,varargin) % expcoarsen('DomainOutline.exp','Antarctica.exp',4000) %Some checks -if nargin==2, +if nargin==2 resolution = varargin{1}; oldfile= newfile; -elseif nargin==3, +elseif nargin==3 oldfile = varargin{1}; resolution = varargin{2}; else @@ -24,9 +24,9 @@ function expcoarsen(newfile,varargin) if ~exist(oldfile) error(['expcoarsen error message: file ''' oldfile ''' does not exist']) -elseif exist(newfile), +elseif exist(newfile) choice=input(['A file ' newfile ' already exists, do you want to modify it? (y/n)'],'s'); - if ~strcmpi(choice,'y'), + if ~strcmpi(choice,'y') disp('no modification done ... exiting'); return; end @@ -39,14 +39,14 @@ function expcoarsen(newfile,varargin) %Go through the profiles count=1; -while count<=numprofiles, +while count<=numprofiles %get number of points and initialize j numpoints=length(A(count).x); j=1; %stop if we have reached end of profile (always keep the last point) - while j=2, + if division>=2 x=linspace(A(count).x(j),A(count).x(j+1),division)'; y=linspace(A(count).y(j),A(count).y(j+1),division)'; A(count).x=[A(count).x(1:j);x(2:end-1); A(count).x(j+1:end)]; @@ -71,7 +71,7 @@ function expcoarsen(newfile,varargin) end end end - if length(A(count).x)<=1, + if length(A(count).x)<=1 A(count)=[]; numprofiles=numprofiles-1; else diff --git a/src/m/exp/expcontract.m b/src/m/exp/expcontract.m index 9942623e4..fe53ffaff 100644 --- a/src/m/exp/expcontract.m +++ b/src/m/exp/expcontract.m @@ -12,7 +12,7 @@ normal=zeros(num-1,2); normal_node=zeros(num-1,2); -for i=1:num-1, +for i=1:num-1 normal(i,:)=[ contour.y(i)-contour.y(i+1) contour.x(i+1)-contour.x(i)]; normal(i,:)=normal(i,:)/sqrt(normal(i,1)^2+normal(i,2)^2); end diff --git a/src/m/exp/expdisp.m b/src/m/exp/expdisp.m index d61f51024..6be577f8a 100644 --- a/src/m/exp/expdisp.m +++ b/src/m/exp/expdisp.m @@ -30,19 +30,19 @@ function expdisp(domainoutline,varargin) domain=expread(domainoutline); %Create figure if needed and hold -if exist(options,'figure'), +if exist(options,'figure') figure(getfieldvalue(options,'figure')); end hold on -for i=1:length(domain), +for i=1:length(domain) if domain(i).nods==1 plot(domain(i).x*unitmultiplier,domain(i).y*unitmultiplier,'o','MarkerEdgeColor','k','MarkerFaceColor','r','MarkerSize',10); if exist(options,'title') text(domain(i).x*unitmultiplier,domain(i).y*unitmultiplier,domain(i).name,'BackgroundColor',[1. .0 .0]); end else - if ispatch, + if ispatch patch(domain(i).x*unitmultiplier,domain(i).y*unitmultiplier,linestyle); else if (isnumeric(linestyle)) diff --git a/src/m/exp/expexcludeoutliers.m b/src/m/exp/expexcludeoutliers.m index 1fccadaee..a8a708ba3 100644 --- a/src/m/exp/expexcludeoutliers.m +++ b/src/m/exp/expexcludeoutliers.m @@ -9,7 +9,7 @@ function excludeoutliers(newcontourname,contourname,domainname) contour=expread(contourname); -for i=1:length(contour), +for i=1:length(contour) flags=ContourToNodes(contour(i).x,contour(i).y,domainname,0); contour(i).x=contour(i).x(find(flags)); contour(i).y=contour(i).y(find(flags)); diff --git a/src/m/exp/expflip.m b/src/m/exp/expflip.m index 49385ed59..ecad7fab6 100644 --- a/src/m/exp/expflip.m +++ b/src/m/exp/expflip.m @@ -7,7 +7,7 @@ function expflip(domainname) a=expread(domainname); -for i=1:length(a), +for i=1:length(a) a(i).x=flipud(a(i).x); a(i).y=flipud(a(i).y); end diff --git a/src/m/exp/expll2xy.m b/src/m/exp/expll2xy.m index 553ee1b39..761a6dbb1 100644 --- a/src/m/exp/expll2xy.m +++ b/src/m/exp/expll2xy.m @@ -6,14 +6,14 @@ function expll2xy(filename,sgn,central_meridian,standard_parallel) % -1 : south latitude (default is mer=0 lat=71) %Get central_meridian and standard_parallel depending on hemisphere -if nargin==4, +if nargin==4 delta = central_meridian; slat = standard_parallel; elseif nargin==2 - if sgn == 1, + if sgn == 1 delta = 45; slat = 70; disp('Info: creating coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)'); - elseif sgn==-1, + elseif sgn==-1 delta = 0; slat = 71; disp('Info: creating coordinates in polar stereographic (Std Latitude: 71ºS Meridian: 0º)'); else @@ -28,7 +28,7 @@ function expll2xy(filename,sgn,central_meridian,standard_parallel) domain=expread(filename); %change to x,y: -for i=1:length(domain), +for i=1:length(domain) [domain(i).x domain(i).y]= ll2xy(domain(i).y,domain(i).x,sgn,delta,slat); end diff --git a/src/m/exp/expread.m b/src/m/exp/expread.m index a80197b25..f8a521362 100644 --- a/src/m/exp/expread.m +++ b/src/m/exp/expread.m @@ -21,7 +21,7 @@ options=pairoptions(varargin{:}); %some checks -if ~exist(filename), +if ~exist(filename) error(['expread error message: file ' filename ' not found!']); end @@ -33,7 +33,7 @@ fid=fopen(filename,'r'); %loop over the number of profiles -while (~feof(fid)), +while (~feof(fid)) %update number of profiles count=count+1; @@ -41,7 +41,7 @@ %Get file name A=fscanf(fid,'%s %s',2); if ~strncmp(A,'##Name:',7), break; end - if length(A)>7, + if length(A)>7 Struct(count).name=A(8:end); else Struct(count).name=''; @@ -89,8 +89,8 @@ fclose(fid); invert=getfieldvalue(options,'invert',0); -if invert, - for i=1:length(Struct), +if invert + for i=1:length(Struct) Struct(i).x=flipud(Struct(i).x); Struct(i).y=flipud(Struct(i).y); end diff --git a/src/m/exp/expsquare.m b/src/m/exp/expsquare.m index d98f433f3..a013fca5c 100644 --- a/src/m/exp/expsquare.m +++ b/src/m/exp/expsquare.m @@ -8,9 +8,9 @@ function expsquare(filename) % expbox(filename) %check -if exist(filename,'file'), +if exist(filename,'file') choice=input(['A file ' filename ' already exists, do you want to modify it? (y/n)'],'s'); - if ~strcmpi(choice,'y'), + if ~strcmpi(choice,'y') disp('no modification done ... exiting'); return end diff --git a/src/m/exp/exptool.m b/src/m/exp/exptool.m index 73b729581..1606d7cc0 100644 --- a/src/m/exp/exptool.m +++ b/src/m/exp/exptool.m @@ -31,16 +31,16 @@ function exptool(newfile,varargin) %Some checks if ~nargin | nargout error('exptool usage: exptool(newfile,varargin)') -elseif exist(newfile,'file'), +elseif exist(newfile,'file') %recursive call to exptool if file already exists - if ~exist(options,'include'), + if ~exist(options,'include') exptool(newfile,'include',newfile,varargin{:}); return; end %check modification choice=input(['A file ' newfile ' already exists, do you want to modify it? (y/n)'],'s'); - if ~strcmpi(choice,'y'), + if ~strcmpi(choice,'y') disp('no modification done ... exiting'); return end @@ -62,12 +62,12 @@ function exptool(newfile,varargin) closed=[]; %initialize the variables with files provided by 'include' option -if exist(options,'include'), +if exist(options,'include') files=getfieldvalue(options,'include'); if ischar(files), files={files}; end - for i=1:length(files), + for i=1:length(files) filename=files{i}; - if ~exist(filename,'file'), + if ~exist(filename,'file') error(['exptool error message:, ' filename ' does not exist. Exiting...']); else %read file @@ -99,7 +99,7 @@ function exptool(newfile,varargin) %get current figure nofigurecopy=getfieldvalue(options,'nofigurecopy',1); -if ~nofigurecopy, +if ~nofigurecopy if ~isempty(get(0,'children')),%if there is already a figure (return the number of opened figures) set(gcf,'Renderer','zbuffer'); %fixes a bug on Mac OS X (not needed in future Matlab version) P=get(gcf,'position'); @@ -163,13 +163,13 @@ function exptool(newfile,varargin) %Now erase all that have been done and plot the new structure A as it is undoplots(prevplot); if numprofiles - if ~nofigurecopy, + if ~nofigurecopy prevplot2=1; else prevplot2=L; end for i=1:numprofiles - if length(A(i).x)==1, + if length(A(i).x)==1 plot(A(i).x,A(i).y,'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth'),... 'MarkerEdgeColor',getfieldvalue(options,'MarkerEdgeColor'),'MarkerSize',getfieldvalue(options,'MarkerSize'),'Marker','o'); else @@ -354,6 +354,6 @@ function exptool(newfile,varargin) end %close window -if ~nofigurecopy, +if ~nofigurecopy close; end diff --git a/src/m/exp/expwrite.m b/src/m/exp/expwrite.m index a09615628..1216ef451 100644 --- a/src/m/exp/expwrite.m +++ b/src/m/exp/expwrite.m @@ -15,32 +15,32 @@ function expwrite(a,filename) % See also EXPDOC, EXPREAD, EXPWRITEASVERTICES %check input variable -if ~isstruct(a), +if ~isstruct(a) error('first argument is not a structure'); end %Add density if it's not there -if ~isfield(a,'density'), - for n=1:length(a), +if ~isfield(a,'density') + for n=1:length(a) a(n).density=1; end end fid=fopen(filename,'w'); -if fid==-1, +if fid==-1 choice=input(['WARNING: file ' filename ' could not be created, would you like to save your exp as ./temp_expwrite.exp? (y/n)'],'s'); - if ~strcmpi(choice,'y'), + if ~strcmpi(choice,'y') disp('no file written... exiting'); return end fid=fopen('./temp_expwrite.exp','w'); end -for n=1:length(a), +for n=1:length(a) if(length(a(n).x)~=length(a(n).y)), error('contours x and y coordinates must be of identical size'); end - if isfield(a,'name'), + if isfield(a,'name') fprintf(fid,'%s%s\n','## Name:',a(n).name); else fprintf(fid,'%s%s\n','## Name:',filename); @@ -48,8 +48,8 @@ function expwrite(a,filename) fprintf(fid,'%s\n','## Icon:0'); fprintf(fid,'%s\n','# Points Count Value'); - if isfield(a,'density'), - if ~isempty(a(n).density), + if isfield(a,'density') + if ~isempty(a(n).density) fprintf(fid,'%i %f\n',[length(a(n).x) a(n).density]); else fprintf(fid,'%i %f\n',[length(a(n).x) 1.]); diff --git a/src/m/exp/expxy2ll.m b/src/m/exp/expxy2ll.m index c060ca029..9e1c94ebe 100644 --- a/src/m/exp/expxy2ll.m +++ b/src/m/exp/expxy2ll.m @@ -6,14 +6,14 @@ function expxy2ll(filename,sgn,central_meridian,standard_parallel) % -1 : south latitude (default is mer=0 lat=71) %Get central_meridian and standard_parallel depending on hemisphere -if nargin==4, +if nargin==4 delta = central_meridian; slat = standard_parallel; elseif nargin==2 - if sgn == 1, + if sgn == 1 delta = 45; slat = 70; disp('Info: creating coordinates in polar stereographic (Std Latitude: 70ºN Meridian: 45º)'); - elseif sgn==-1, + elseif sgn==-1 delta = 0; slat = 71; disp('Info: creating coordinates in polar stereographic (Std Latitude: 71ºS Meridian: 0º)'); else @@ -28,7 +28,7 @@ function expxy2ll(filename,sgn,central_meridian,standard_parallel) domain=expread(filename); %change to x,y: -for i=1:length(domain), +for i=1:length(domain) [domain(i).y domain(i).x]= xy2ll(domain(i).x,domain(i).y,sgn,delta,slat); %watch out to swap lat and long end diff --git a/src/m/exp/flowlines.m b/src/m/exp/flowlines.m index 0e2a1a36c..95f507f25 100644 --- a/src/m/exp/flowlines.m +++ b/src/m/exp/flowlines.m @@ -19,13 +19,13 @@ % - 'cutoff': velocity threshold to stop propagating flowlines (default: 0) %check input -if (length(x)~=length(y) | length(x)~=length(u) | length(x)~=length(v)), +if (length(x)~=length(y) | length(x)~=length(u) | length(x)~=length(v)) error('flowlines error message: x,y,u and v must have the same length'); end -if length(x)<3, +if length(x)<3 error('flowlines error message: at least one element is required'); end -if length(x0)~=length(y0), +if length(x0)~=length(y0) error('flowlines error message: x0 and y0 do not have the same length'); end @@ -49,7 +49,7 @@ N=length(x0); X=x0; Y=y0; flowpath=struct('x',cell(N,1),'y',cell(N,1),'name','','density',1); -for i=1:N, +for i=1:N flowpath(i).x=x0(i); flowpath(i).y=y0(i); end @@ -64,7 +64,7 @@ u=u(index)*[1;1;1]/3; v=v(index)*[1;1;1]/3; -if downstream, +if downstream %initialization: counter=1; @@ -85,7 +85,7 @@ tria(listnan)=[]; queue(listnan)=[]; - if isempty(tria), + if isempty(tria) break; end @@ -114,7 +114,7 @@ end %same process but reverse (vel=-vel) to have a vcomplete flow line -if upstream, +if upstream queue=[]; counter=1; X=x0; Y=y0; @@ -137,7 +137,7 @@ tria(listnan)=[]; queue(listnan)=[]; - if isempty(tria), + if isempty(tria) break; end diff --git a/src/m/exp/isoline.m b/src/m/exp/isoline.m index 9c7909001..c5c8cddf3 100644 --- a/src/m/exp/isoline.m +++ b/src/m/exp/isoline.m @@ -22,7 +22,7 @@ options = pairoptions(varargin{:}); %process data -if dimension(md.mesh)==3, +if dimension(md.mesh)==3 % error('contourlevelzero error message: routine not supported for 3d meshes, project on a layer'); x = md.mesh.x2d; y = md.mesh.y2d; @@ -40,14 +40,14 @@ end %Deal with z coordinate -if isprop(md.mesh,'z'), +if isprop(md.mesh,'z') z=md.mesh.z; else z=zeros(numel(x),1); end if isempty(field), error('field provided is empty'); end -if dimension(md.mesh)==3, +if dimension(md.mesh)==3 if length(field)~=md.mesh.numberofvertices2d error('field provided should be of size md.mesh.numberofvertices2d'); end @@ -114,7 +114,7 @@ numelems=length(poselem); %if no element has been flagged, skip to the next level -if numelems==0, +if numelems==0 warning('isoline warning message: no elements found with corresponding value'); contours=struct([]); return; @@ -130,7 +130,7 @@ edge_l=zeros(numelems,2); -for j=1:numelems, +for j=1:numelems weight1=(level-Data1(poselem(j),1))/(Data1(poselem(j),2)-Data1(poselem(j),1)); weight2=(level-Data2(poselem(j),1))/(Data2(poselem(j),2)-Data2(poselem(j),1)); @@ -148,7 +148,7 @@ edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg2_num(poselem(j)); - elseif poselem13(poselem(j)), + elseif poselem13(poselem(j)) x1(j)=x(Seg1(poselem(j),1))+weight1*(x(Seg1(poselem(j),2))-x(Seg1(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -160,7 +160,7 @@ edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg3_num(poselem(j)); - elseif poselem23(poselem(j)), + elseif poselem23(poselem(j)) x1(j)=x(Seg2(poselem(j),1))+weight2*(x(Seg2(poselem(j),2))-x(Seg2(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -181,7 +181,7 @@ %loop over the subcontours contours=struct([]); -while ~isempty(edge_l), +while ~isempty(edge_l) %take the right edge of the second segment and connect it to the next segments if any e1=edge_l(1,1); e2=edge_l(1,2); @@ -198,7 +198,7 @@ while ~isempty(ro1) - if co1==1, + if co1==1 xc=[x2(ro1);xc]; yc=[y2(ro1);yc];zc=[z2(ro1);zc]; %next edge: @@ -226,7 +226,7 @@ while ~isempty(ro2) - if co2==1, + if co2==1 xc=[xc;x2(ro2)]; yc=[yc;y2(ro2)];zc=[zc;z2(ro2)]; %next edge: diff --git a/src/m/exp/masktoexp.m b/src/m/exp/masktoexp.m index b6c7c0ac6..608d6b276 100644 --- a/src/m/exp/masktoexp.m +++ b/src/m/exp/masktoexp.m @@ -24,7 +24,7 @@ function masktoexp(x,y,mask,threshold,filename) %Create exp structure A=struct(); if(j-1<1), error('no contour found'); end -for i=1:j-1, +for i=1:j-1 A(i).x=s(i).x; A(i).y=s(i).y; end; diff --git a/src/m/exp/meshtodomain.m b/src/m/exp/meshtodomain.m index 8883873f6..b49534a98 100644 --- a/src/m/exp/meshtodomain.m +++ b/src/m/exp/meshtodomain.m @@ -17,14 +17,14 @@ function meshtodomain(mh,domainname,varargin) %build domain contour: x=[]; y=[]; - if strcmpi(getfieldvalue(options,'latlong','off'),'on'), + if strcmpi(getfieldvalue(options,'latlong','off'),'on') if isnan(mh.lat) | isnan(mh.long), error('meshtodomain error message: requested domain be output in lat,long referential, but mesh does not contain this information!'); end - for i=1:nt, + for i=1:nt x=[x;mh.long(segments(i,1))]; y=[y;mh.lat(segments(i,1))]; end else - for i=1:nt, + for i=1:nt x=[x;mh.x(segments(i,1))]; y=[y;mh.y(segments(i,1))]; end diff --git a/src/m/exp/operation/closeprofile.m b/src/m/exp/operation/closeprofile.m index 7e15a1990..edc34b4f5 100644 --- a/src/m/exp/operation/closeprofile.m +++ b/src/m/exp/operation/closeprofile.m @@ -26,7 +26,7 @@ disp('no profile present, exiting...') return end - if ~any(~closed), + if ~any(~closed) disp('All the profiles are closed, exiting...') return end @@ -44,7 +44,7 @@ %back to regular color plot(A(profsel).x,A(profsel).y,... 'color',getfieldvalue(options,'color'),'LineStyle',getfieldvalue(options,'LineStyle'),'LineWidth',getfieldvalue(options,'LineWidth')); - elseif closed(profsel), + elseif closed(profsel) %profile already closed, do nothing disp('selected profile aready closed, make another selection'), else @@ -56,7 +56,7 @@ end else %close the profiles - for i=1:length(selection), + for i=1:length(selection) A(selection(i)).x(end+1)=A(selection(i)).x(1); A(selection(i)).y(end+1)=A(selection(i)).y(1); numpoints=numpoints+1; diff --git a/src/m/exp/operation/closestpoint.m b/src/m/exp/operation/closestpoint.m index f70f19c98..72de297ab 100644 --- a/src/m/exp/operation/closestpoint.m +++ b/src/m/exp/operation/closestpoint.m @@ -9,10 +9,10 @@ % [profsel indsel]=closestpoint(A,numprofiles,xi,yi) %loop over the points of each profile, find the closest to (xi,yi) - for i=1:numprofiles, + for i=1:numprofiles distance=(xi-A(i).x).^2+(yi-A(i).y).^2; [newdistance p]=min(distance); - if ((i==1) | (newdistance1 middles=[(A(i).x(1:end-1)+A(i).x(2:end))/2 (A(i).y(1:end-1)+A(i).y(2:end))/2]; distance=(xi-middles(:,1)).^2+(yi-middles(:,2)).^2; [newdistance p]=min(distance); - if (first | (newdistancemd3d.mesh.numberoflayers)), +if ((layer<1) | (layer>md3d.mesh.numberoflayers)) error(['layer must be between 1 and ' num2str(md3d.mesh.numberoflayers)]); end if numel(value)==1 projection_value=value; -elseif size(value,1)==md3d.mesh.numberofvertices, +elseif size(value,1)==md3d.mesh.numberofvertices projection_value=value((layer-1)*md3d.mesh.numberofvertices2d+1:layer*md3d.mesh.numberofvertices2d,:); elseif size(value,1)==md3d.mesh.numberofvertices+1 projection_value=[value((layer-1)*md3d.mesh.numberofvertices2d+1:layer*md3d.mesh.numberofvertices2d,:); value(end,:)]; diff --git a/src/m/extrusion/project3d.m b/src/m/extrusion/project3d.m index 0181b5f7f..13528821b 100644 --- a/src/m/extrusion/project3d.m +++ b/src/m/extrusion/project3d.m @@ -19,7 +19,7 @@ % extruded_vector=project3d(md,'vector',vector2d,'type','node'); %some regular checks -if nargin==0, +if nargin==0 help project3d error('bad usage'); end @@ -35,10 +35,10 @@ paddingvalue = getfieldvalue(options,'padding',0); %0 by default polyexponent = getfieldvalue(options,'degree',0); %0 by default, 0-degree polynomial -if length(vector2d)==1, +if length(vector2d)==1 projected_vector=vector2d; -elseif strcmpi(type,'node'), +elseif strcmpi(type,'node') %Initialize 3d vector if size(vector2d,1)==md.mesh.numberofvertices2d projected_vector=paddingvalue*ones(md.mesh.numberofvertices, size(vector2d,2)); @@ -51,15 +51,15 @@ end %Fill in - if layer==0, - for i=1:md.mesh.numberoflayers, + if layer==0 + for i=1:md.mesh.numberoflayers projected_vector(((i-1)*md.mesh.numberofvertices2d+1):(i*md.mesh.numberofvertices2d),:)=vector2d; end else projected_vector(((layer-1)*md.mesh.numberofvertices2d+1):(layer*md.mesh.numberofvertices2d),:)=vector2d; end -elseif strcmpi(type,'element'), +elseif strcmpi(type,'element') %Initialize 3d vector if size(vector2d,1)==md.mesh.numberofelements2d @@ -73,8 +73,8 @@ end %Fill in - if layer==0, - for i=1:(md.mesh.numberoflayers-1), + if layer==0 + for i=1:(md.mesh.numberoflayers-1) projected_vector( ((i-1)*md.mesh.numberofelements2d+1):(i*md.mesh.numberofelements2d),:)=vector2d; end else @@ -96,8 +96,8 @@ polycoeff = [0:1./(md.mesh.numberoflayers-1):1]; %Fill in - if layer==0, - for i=1:md.mesh.numberoflayers, + if layer==0 + for i=1:md.mesh.numberoflayers projected_vector(((i-1)*md.mesh.numberofvertices2d+1):(i*md.mesh.numberofvertices2d),:)=vector2d*(1-(1-polycoeff(i)).^polyexponent); end else diff --git a/src/m/geometry/FlagElements.m b/src/m/geometry/FlagElements.m index b76c60c51..c414ba68e 100644 --- a/src/m/geometry/FlagElements.m +++ b/src/m/geometry/FlagElements.m @@ -12,8 +12,8 @@ % flag=FlagElements(md,'Domain.exp'); % flag=FlagElements(md,'~Domain.exp'); - if ischar(region), - if isempty(region), + if ischar(region) + if isempty(region) flag=zeros(md.mesh.numberofelements,1); invert=0; elseif strcmpi(region,'all') @@ -21,7 +21,7 @@ invert=0; else %make sure that we actually don't want the elements outside the domain outline! - if strcmpi(region(1),'~'), + if strcmpi(region(1),'~') region=region(2:length(region)); invert=1; else @@ -29,8 +29,8 @@ end %does the region domain outline exist or do we have to look for xlim,ylim in basinzoom? - if ~exist(region,'file'), - if (length(region)>3 & ~strcmp(region(end-3),'.exp')), + if ~exist(region,'file') + if (length(region)>3 & ~strcmp(region(end-3),'.exp')) error(['Error: File ' region ' not found!']); end [xlim,ylim]=basinzoom('basin',region); @@ -41,13 +41,13 @@ flag=ContourToMesh(md.mesh.elements(:,1:3),md.mesh.x,md.mesh.y,region,'element',1); end end - if invert, + if invert flag=~flag; end - elseif isfloat(region) | islogical(region), - if size(region,1)==md.mesh.numberofelements, + elseif isfloat(region) | islogical(region) + if size(region,1)==md.mesh.numberofelements flag=region; - elseif size(region,1)==md.mesh.numberofvertices, + elseif size(region,1)==md.mesh.numberofvertices flag=logical(sum(region(md.mesh.elements)>0,2)==size(md.mesh.elements,2)); else help FlagElements diff --git a/src/m/geometry/GetAreas.m b/src/m/geometry/GetAreas.m index 5a02b1fd5..7a91beaec 100644 --- a/src/m/geometry/GetAreas.m +++ b/src/m/geometry/GetAreas.m @@ -18,20 +18,20 @@ if nargin==4, z=varargin{1}; end %some checks -if nargout~=1 | (nargin~=3 & nargin~=4), +if nargout~=1 | (nargin~=3 & nargin~=4) help GetAreas error('GetAreas error message: bad usage') end -if ((length(y)~=nods) | (nargin==4 & length(z)~=nods)), +if ((length(y)~=nods) | (nargin==4 & length(z)~=nods)) error('GetAreas error message: x,y and z do not have the same length') end -if max(index(:))>nods, +if max(index(:))>nods error(['GetAreas error message: index should not have values above ' num2str(nods) ]) end -if (nargin==3 & size(index,2)~=3), +if (nargin==3 & size(index,2)~=3) error('GetAreas error message: index should have 3 columns for 2d meshes.') end -if (nargin==4 & size(index,2)~=6), +if (nargin==4 & size(index,2)~=6) error('GetAreas error message: index should have 6 columns for 3d meshes.') end @@ -41,7 +41,7 @@ y1=y(index(:,1)); y2=y(index(:,2)); y3=y(index(:,3)); %compute the volume of each element -if nargin==3, +if nargin==3 %compute the surface of the triangle areas=(0.5*((x2-x1).*(y3-y1)-(y2-y1).*(x3-x1))); else diff --git a/src/m/geometry/GetAreas3DTria.m b/src/m/geometry/GetAreas3DTria.m index 275d56db5..29e256ecf 100644 --- a/src/m/geometry/GetAreas3DTria.m +++ b/src/m/geometry/GetAreas3DTria.m @@ -14,18 +14,18 @@ nods=length(x); %some checks -if nargout~=1 | (nargin~=3 & nargin~=4), +if nargout~=1 | (nargin~=3 & nargin~=4) help GetAreas3DTria error('GetAreas3DTria error message: bad usage') end -if ((length(y)~=nods) | (nargin==4 & length(z)~=nods)), +if ((length(y)~=nods) | (nargin==4 & length(z)~=nods)) error('GetAreas3DTria error message: x, y, and z do not have the same length') end -if max(index(:))>nods, +if max(index(:))>nods error(['GetAreas3DTria error message: index should not have values above ' num2str(nods) ]) end -if (nargin==4 & size(index,2)~=3), +if (nargin==4 & size(index,2)~=3) error('GetAreas3DTria error message: index should have 3 columns for 2d meshes') end @@ -36,7 +36,7 @@ z1=z(index(:,1)); z2=z(index(:,2)); z3=z(index(:,3)); %compute the volume of each element -if nargin==4, +if nargin==4 % area of triangles with 3D coordinates for i=1:nels m1=[x1(i) x2(i) x3(i); y1(i) y2(i) y3(i); 1 1 1]; diff --git a/src/m/geometry/GetAreasSphericalTria.m b/src/m/geometry/GetAreasSphericalTria.m index 74b9dec23..4b6b53559 100644 --- a/src/m/geometry/GetAreasSphericalTria.m +++ b/src/m/geometry/GetAreasSphericalTria.m @@ -15,14 +15,14 @@ nods=length(x); %some checks -if nargout~=1 | (nargin~=3 & nargin~=4), +if nargout~=1 | (nargin~=3 & nargin~=4) help GetAreasSphericalTria error('GetAreasSphericalTria error message: bad usage') end -if (length(y)~=nods), +if (length(y)~=nods) error('GetAreasSphericalTria error message: x and y do not have the same length') end -if max(index(:))>nods, +if max(index(:))>nods error(['GetAreasSphericalTria error message: index should not have values above ' num2str(nods) ]) end @@ -32,7 +32,7 @@ y1=y(index(:,1)); y2=y(index(:,2)); y3=y(index(:,3)); %compute the volume of each element -if nargin==4, +if nargin==4 % arc lengths arc_12=distance(x1,y1,x2,y2).*pi./180; arc_23=distance(x2,y2,x3,y3).*pi./180; diff --git a/src/m/geometry/HeightAboveFloatation.m b/src/m/geometry/HeightAboveFloatation.m new file mode 100644 index 000000000..eb0705100 --- /dev/null +++ b/src/m/geometry/HeightAboveFloatation.m @@ -0,0 +1,66 @@ +function H = HeightAboveFloatation(md,step) +%HEIGHTABOVEFLOATATION - returns height above hydrostatic floatation per element within the ice levelset. +% H<0 will be returned for elements which are floating. +% +% USAGE: +% H = HeightAboveFloatation(md) % calculate HAF from md.geometry +% H = HeightAboveFloatation(md,[]) % calculate HAF from md.geometry +% H = HeightAboveFloatation(md,10) % calculate HAF from md.results.TransientSolution(10) -- step 10 of transient solution +% +% INPUT: +% md % ISSM model containing the geometry +% step % index of md.results.TransientSolution(step) from which to pull the geometry +% +% OUTPUT: +% H % height above floatation over each element +% +% SEE ALSO: VolumeAboveFloatation + +% process inputs +if (nargin<2 | isempty(step)) + istransientstep = 0; +else + istransientstep = 1; +end + +% define element index +switch class(md.mesh) + case 'mesh2d' + index = md.mesh.elements; + case 'mesh3dprisms' + index = md.mesh.elements2d; + otherwise + error('not supported yet'); +end + +% define density parameters +rho_ice = md.materials.rho_ice; % density of glacial ice (kg m^-3) +rho_water = md.materials.rho_water; % density of ocean water (kg m^-3) + +% compute geometry on the elements and define ice levelset +if ~istransientstep + base = mean(md.geometry.base(index),2); + surface = mean(md.geometry.surface(index),2); + bed = mean(md.geometry.bed(index),2); + ice_levelset = md.mask.ice_levelset; +else + if isprop(md.results.TransientSolution(step),'MaskIceLevelset') + ice_levelset = md.results.TransientSolution(step).MaskIceLevelset; + else + ice_levelset = md.mask.ice_levelset; + end + base = mean(md.results.TransientSolution(step).Base(index),2); + surface = mean(md.results.TransientSolution(step).Surface(index),2); + if isprop(md.results.TransientSolution(step),'Bed') + bed = mean(md.results.TransientSolution(step).Bed(index),2); + else + bed = mean(md.geometry.bed(index),2); + end +end + +% compute height above floatation +H = surface - base + min(rho_water/rho_ice*bed,0); + +% mask out elements which are outside the ice levelset +pos = find(min(ice_levelset(index),[],2)>0); +H(pos) = 0; diff --git a/src/m/geometry/VolumeAboveFloatation.m b/src/m/geometry/VolumeAboveFloatation.m index 330833644..03e8dd12f 100644 --- a/src/m/geometry/VolumeAboveFloatation.m +++ b/src/m/geometry/VolumeAboveFloatation.m @@ -1,33 +1,52 @@ function V = VolumeAboveFloatation(md,step,flags) %VOLUMEABOVEFLOATATION - returns volume above floatation +% Sums per-element volume above floatation over grounded ice, considering only positive height above floatation. % -% Usage: -% V = VolumeAboveFloatation(md) % uses model fiels alone -% V = VolumeAboveFloatation(md,10) % Will look at step 10 of transient solution -% V = VolumeAboveFloatation(md,10,flags) % Will look at step 10 of transient solution, only flaged elements +% USAGE: +% V = VolumeAboveFloatation(md) % calculate VAF from md.geometry +% V = VolumeAboveFloatation(md,10) % calculate VAF from md.results.TransientSolution(10) -- step 10 of transient solution +% V = VolumeAboveFloatation(md,10,flags) % calculate VAF from md.results.TransientSolution(10), only flagged elements +% V = VolumeAboveFloatation(md,[],flags) % calculate VAF from md.geometry, only flagged elements +% +% INPUT: +% md % ISSM model containing the geometry +% step % index of md.results.TransientSolution(step) from which to pull the geometry +% flags % boolean vector of length md.mesh.numberofelements flagging which elements to integrate over +% +% OUTPUT: +% V % volume above floatation over each element +% +% SEE ALSO: HeightAboveFloatation, GetAreas -%Special case if 3d -if isa(md.mesh,'mesh3dprisms') - index = md.mesh.elements2d; - x = md.mesh.x2d; - y = md.mesh.y2d; -elseif isa(md.mesh,'mesh2d'), - index = md.mesh.elements; - x = md.mesh.x; - y = md.mesh.y; +% process inputs +if nargin<2 + step = []; % calculate VAF from md.geometry +end +if nargin<3 + flags = []; % integrate over entire domain +end +if (nargin<2 | isempty(step)) + istransientstep = 0; else - error('not supported yet'); + istransientstep = 1; end -%1. get some parameters -rho_ice = md.materials.rho_ice; -rho_water = md.materials.rho_water; +% define element index +switch class(md.mesh) + case 'mesh2d' + index = md.mesh.elements; + x = md.mesh.x; + y = md.mesh.y; + case 'mesh3dprisms' + index = md.mesh.elements2d; + x = md.mesh.x2d; + y = md.mesh.y2d; + otherwise + error('not supported yet'); +end -%2. compute averages -if nargin==1 - base = mean(md.geometry.base(index),2); - surface = mean(md.geometry.surface(index),2); - bathymetry = mean(md.geometry.bed(index),2); +% retrieve ice and ocean levelsets +if ~istransientstep ice_levelset = md.mask.ice_levelset; ocean_levelset = md.mask.ocean_levelset; else @@ -37,29 +56,22 @@ ice_levelset = md.mask.ice_levelset; end ocean_levelset = md.results.TransientSolution(step).MaskOceanLevelset; - base = mean(md.results.TransientSolution(step).Base(index),2); - surface = mean(md.results.TransientSolution(step).Surface(index),2); - if isprop(md.results.TransientSolution(step),'Bed') - bathymetry = mean(md.results.TransientSolution(step).Bed(index),2); - else - bathymetry = mean(md.geometry.bed(index),2); - end end -%3. get areas of all triangles -areas = GetAreas(index,x,y); +% compute height above floatation per element +H = HeightAboveFloatation(md,step); % (m) -%4. Compute volume above floatation -V = areas.*(surface-base+min(rho_water/rho_ice*bathymetry,0.)); +% mask out elements which are outside the levelset or are floating +pos = find(min(ice_levelset(index),[],2)>0 | min(ocean_levelset(index),[],2)<0); % index of elements outside ice or inside ocean mask +H(pos) = 0; +H = max(H,0); % Ensure that negative height above floatation is not integrated -%5. take out the ones that are outside of levelset or floating -pos = find(min(ice_levelset(index),[],2)>0 | min(ocean_levelset(index),[],2)<0); -V(pos) = 0; +% compute volume above floatation per element +areas = GetAreas(index,x,y); % (m^2) +V = areas.*H; % (m^3) -%In case we are only looking at one portion of the domain... -if nargin==3 - V(find(~flags)) = 0; -end +% apply flags +V(find(~flags)) = 0; -%sum individual contributions +% sum over all elements V = sum(V); diff --git a/src/m/geometry/isconnected.m b/src/m/geometry/isconnected.m index 0be5618cf..b42e624f3 100755 --- a/src/m/geometry/isconnected.m +++ b/src/m/geometry/isconnected.m @@ -6,7 +6,7 @@ % elements=ElementsFromEdge(elements,A,B); -if isempty(elements), +if isempty(elements) flag=0; else flag=1; diff --git a/src/m/geometry/locationtonode.m b/src/m/geometry/locationtonode.m index 9479d2b36..38cc06aee 100644 --- a/src/m/geometry/locationtonode.m +++ b/src/m/geometry/locationtonode.m @@ -7,7 +7,7 @@ % % See also: geoCode (in externalpackages), find_point - if nargin==3, + if nargin==3 radius=varargin{1}; else radius=0; @@ -17,7 +17,7 @@ latny=coords(1); longny=coords(2); node=find_point(md.mesh.lat,md.mesh.long,latny,longny); - if radius>0, + if radius>0 distance=sqrt( (md.mesh.x-md.mesh.x(node)).^2 + (md.mesh.y-md.mesh.y(node)).^2 + (md.mesh.z-md.mesh.z(node)).^2); nodes=find(distancemd.mesh.numberoflayers, +if dimension(md.mesh)==3 & nargin==4 + if varargin{1}<=0 | varargin{1}>md.mesh.numberoflayers error('layer should be between 1 and md.mesh.numberoflayers'); end layer=varargin{1}; @@ -34,7 +34,7 @@ end %initialization -if layer==0, +if layer==0 weights=zeros(md.mesh.numberofvertices,1); data=data(:); else @@ -43,7 +43,7 @@ end %load some variables (it is much faster if the variables are loaded from md once for all) -if layer==0, +if layer==0 index=md.mesh.elements; numberofnodes=md.mesh.numberofvertices; numberofelements=md.mesh.numberofelements; @@ -55,15 +55,15 @@ %build some variables line=index(:); -if dimension(md.mesh)==3 & layer==0, +if dimension(md.mesh)==3 & layer==0 rep=6; areas=GetAreas(index,md.mesh.x,md.mesh.y,md.mesh.z); -elseif dimension(md.mesh)==2, +elseif dimension(md.mesh)==2 rep=3; areas=GetAreas(index,md.mesh.x,md.mesh.y); else rep=3; - if isa(md.mesh,'mesh3dsurface'), + if isa(md.mesh,'mesh3dsurface') areas=GetAreas3DTria(md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.z); else areas=GetAreas(index,md.mesh.x,md.mesh.y); diff --git a/src/m/interp/plugvelocities.m b/src/m/interp/plugvelocities.m index ce165e4ad..c9c0cabc4 100644 --- a/src/m/interp/plugvelocities.m +++ b/src/m/interp/plugvelocities.m @@ -28,7 +28,7 @@ Vel=load(filename); %Interpolation -if strcmpi(Names.interp,'node'), +if strcmpi(Names.interp,'node') md.inversion.vx_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vxname),md.mesh.x,md.mesh.y,default_value); md.inversion.vy_obs=InterpFromGridToMesh(Vel.(Names.xname),Vel.(Names.yname),Vel.(Names.vyname),md.mesh.x,md.mesh.y,default_value); else @@ -71,7 +71,7 @@ %find x,y,vx and vy xenum=NaN; yenum=NaN; vxenum=NaN; vyenum=NaN; indexenum=NaN; -if length(A)==4, +if length(A)==4 isnode=1; for i=1:4 if strcmpi(A(i).name(1),'x'); @@ -86,7 +86,7 @@ end end end -elseif length(A)==5, +elseif length(A)==5 isnode=0; for i=1:5 if strcmpi(A(i).name(1),'x'); @@ -113,14 +113,14 @@ end %find index -if (~isnode & isnan(indexenum)), +if (~isnode & isnan(indexenum)) for i=1:5 lengthi=min(A(i).size); - if (lengthi==3), + if (lengthi==3) indexenum=i; end end - if isnan(indexenum), + if isnan(indexenum) error(['VelFindVarNames error message: file ' filename ' not supported yet (index not found)']); end end @@ -129,19 +129,19 @@ if (isnan(xenum) | isnan(yenum)) %check the size - if A(vxenum).size(1)==A(vxenum).size(2), + if A(vxenum).size(1)==A(vxenum).size(2) error(['VelFindVarNames error message: file ' filename ' not supported (velocities is a square matrix, save x and y with another name)']); end - if ~(A(vxenum).size(1)==A(vyenum).size(1) & A(vxenum).size(2)==A(vyenum).size(2)), + if ~(A(vxenum).size(1)==A(vyenum).size(1) & A(vxenum).size(2)==A(vyenum).size(2)) error(['VelFindVarNames error message: file ' filename ' not supported (vx and vy matrices do not have the same size)']); end %find xenum and yenum for i=1:4 lengthi=max(A(i).size); - if ((i~=vxenum) & (lengthi==A(vxenum).size(1) | lengthi==A(vxenum).size(1)+1)), + if ((i~=vxenum) & (lengthi==A(vxenum).size(1) | lengthi==A(vxenum).size(1)+1)) yenum=i; - elseif ((i~=vxenum) & (lengthi==A(vxenum).size(2) | lengthi==A(vxenum).size(2)+1)), + elseif ((i~=vxenum) & (lengthi==A(vxenum).size(2) | lengthi==A(vxenum).size(2)+1)) xenum=i; end end @@ -158,7 +158,7 @@ Names.yname=A(yenum).name; Names.vxname=A(vxenum).name; Names.vyname=A(vyenum).name; -if ~isnode, +if ~isnode Names.indexname=A(indexenum).name; Names.interp='mesh'; else diff --git a/src/m/inversions/parametercontrolB.m b/src/m/inversions/parametercontrolB.m index 51f4424ba..0509f8322 100644 --- a/src/m/inversions/parametercontrolB.m +++ b/src/m/inversions/parametercontrolB.m @@ -3,7 +3,7 @@ % % It is possible to specify the number of steps, values for the % minimum and maximum values of B, the -% kind of cm_responses to use or the the optscal. +% kind of cm_responses to use or the optscal. % % Usage: % md=parametercontrolB(md,varargin) @@ -86,9 +86,9 @@ %cm_responses found=0; -if exist(options,'cm_responses'), +if exist(options,'cm_responses') cm_responses=getfieldvalue(options,'cm_responses'); - if ~any(~ismember(cm_responses,[ 101:105])), + if ~any(~ismember(cm_responses,[ 101:105])) md.inversion.cost_functions=repmat(cm_responses(:),md.inversion.nsteps,1); md.inversion.cost_functions(md.inversion.nsteps+1:end)=[]; found=1; @@ -106,9 +106,9 @@ %optscal found=0; -if exist(options,'optscal'), +if exist(options,'optscal') optscal=getfieldvalue(options,'optscal'); - if ~any(optscal<0), + if ~any(optscal<0) md.inversion.gradient_scaling=repmat(optscal(:),md.inversion.nsteps,1); md.inversion.gradient_scaling(md.inversion.nsteps+1:end)=[]; found=1; diff --git a/src/m/inversions/parametercontroldrag.m b/src/m/inversions/parametercontroldrag.m index 00ccb54de..7cf5625d4 100644 --- a/src/m/inversions/parametercontroldrag.m +++ b/src/m/inversions/parametercontroldrag.m @@ -3,7 +3,7 @@ % % It is possible to specify the number of steps, values for the % minimum and maximum values of the drag, the -% kind of cm_responses to use or the the optscal. +% kind of cm_responses to use or the optscal. % % Usage: % md=parametercontroldrag(md,varargin) @@ -86,7 +86,7 @@ %cm_responses found=0; -if exist(options,'cm_responses'), +if exist(options,'cm_responses') cm_responses=getfieldvalue(options,'cm_responses'); if ~any(~ismember(cm_responses,[101 105])) md.inversion.cost_functions=repmat(cm_responses(:),md.inversion.nsteps,1); @@ -106,9 +106,9 @@ %optscal found=0; -if exist(options,'optscal'), +if exist(options,'optscal') optscal=getfieldvalue(options,'optscal'); - if ~any(optscal<0), + if ~any(optscal<0) md.inversion.gradient_scaling=repmat(optscal(:),md.inversion.nsteps,1); md.inversion.gradient_scaling(md.inversion.nsteps+1:end)=[]; found=1; diff --git a/src/m/inversions/parametercontroldrag.py b/src/m/inversions/parametercontroldrag.py index a55e9451e..657860071 100644 --- a/src/m/inversions/parametercontroldrag.py +++ b/src/m/inversions/parametercontroldrag.py @@ -8,7 +8,7 @@ def parametercontroldrag(md, *args): It is possible to specify the number of steps, values for the minimum and maximum values of the drag, the - kind of cm_responses to use or the the optscal. + kind of cm_responses to use or the optscal. Usage: md = parametercontroldrag(md, varargin) diff --git a/src/m/inversions/velocitymisfit.m b/src/m/inversions/velocitymisfit.m index 8b7be83eb..c26869a30 100644 --- a/src/m/inversions/velocitymisfit.m +++ b/src/m/inversions/velocitymisfit.m @@ -8,7 +8,7 @@ % - observed velocities will be pulled from md.inversion.vx_obs/vy_obs -if dimension(md.mesh)==2, +if dimension(md.mesh)==2 elements=md.mesh.elements; x=md.mesh.x; y=md.mesh.y; diff --git a/src/m/io/loadmodel.m b/src/m/io/loadmodel.m index ac7cf4ca4..86e8635ac 100644 --- a/src/m/io/loadmodel.m +++ b/src/m/io/loadmodel.m @@ -8,7 +8,7 @@ % loadmodel path %check nargout -if nargout>1, +if nargout>1 error('loadmodel usage error: md=loadmodel(path)'); end @@ -31,11 +31,11 @@ warning on MATLAB:load:classNotFound name=char(fieldnames(struc)); - if size(name,1)>1, + if size(name,1)>1 error(['loadmodel error message: file ' path ' contains several variables. Only one model should be present.']); end md=struc.(name); - if nargout, + if nargout varargout{1}=md; else assignin('caller',name,md); diff --git a/src/m/io/loadmodellist.m b/src/m/io/loadmodellist.m index 2c156e3e9..7c59c0aa1 100644 --- a/src/m/io/loadmodellist.m +++ b/src/m/io/loadmodellist.m @@ -8,7 +8,7 @@ % loadmodellist path %check nargout -if nargout>1, +if nargout>1 error('loadmodellist usage error: mds=loadmodellist(path)'); end %check existence @@ -23,7 +23,7 @@ end %check number of variables -if length(whos('-file',path))>1, +if length(whos('-file',path))>1 error(['loadmodellist error message: file ' path ' contains several variables. Only one model should be present.']); end @@ -33,13 +33,13 @@ %get name of model variable fieldname=char(fieldnames(struc)); mds=eval(['struc.' fieldname]); - if ~strcmpi(class(mds),'model'), + if ~strcmpi(class(mds),'model') mds2=modellist; mds2=structtomodel(mds2,mds); mds=mds2; clear mds2; end - if nargout, + if nargout varargout{1}=mds; else assignin('caller',fieldname,mds); diff --git a/src/m/io/structtonc.m b/src/m/io/structtonc.m index 16966919f..722fea1a3 100644 --- a/src/m/io/structtonc.m +++ b/src/m/io/structtonc.m @@ -9,7 +9,7 @@ counter = counter+1; %Check that field is not empty -if isempty(field) | (isa(field,'struct') & numel(fields(field))==0), +if isempty(field) | (isa(field,'struct') & numel(fields(field))==0) if(step==1), disp(['skipping ' fieldname ' (empty)...']); end return; end @@ -18,17 +18,17 @@ [var_id,counter] = declareclass(ncid,[fieldname '_class'],class(field),depth,var_id,counter,step); %Double scalar -if isa(field,'double') & numel(field)==1, - if step==1, +if isa(field,'double') & numel(field)==1 + if step==1 var_id(counter) = netcdf.defVar(ncid,fieldname,'NC_DOUBLE',[]); else netcdf.putVar(ncid,var_id(counter),field); end %Double vector -elseif isa(field,'double') & size(field,2)==1, +elseif isa(field,'double') & size(field,2)==1 -if step==1, +if step==1 dim_id = netcdf.defDim(ncid,[fieldname '_size1'],size(field,1)); var_id(counter) = netcdf.defVar(ncid,fieldname,'NC_DOUBLE',dim_id); else @@ -36,8 +36,8 @@ end %double matrix -elseif isa(field,'double') & size(field,2)>1, - if step==1, +elseif isa(field,'double') & size(field,2)>1 + if step==1 dim1_id = netcdf.defDim(ncid,[fieldname '_size1'],size(field,1)); dim2_id = netcdf.defDim(ncid,[fieldname '_size2'],size(field,2)); var_id(counter) = netcdf.defVar(ncid,fieldname,'NC_DOUBLE',[dim2_id dim1_id]); @@ -47,7 +47,7 @@ %string elseif isa(field,'char') - if step==1, + if step==1 dim_id = netcdf.defDim(ncid,[fieldname '_size1'],numel(field)); var_id(counter) = netcdf.defVar(ncid,fieldname,'NC_CHAR',dim_id); else @@ -55,60 +55,60 @@ end %Boolean of size 1 -elseif isa(field,'logical') & numel(field)==1, - if step==1, +elseif isa(field,'logical') & numel(field)==1 + if step==1 var_id(counter) = netcdf.defVar(ncid,fieldname,'NC_BYTE',[]); else netcdf.putVar(ncid,var_id(counter),int8(field)); end %Structures -elseif isa(field,'struct'), +elseif isa(field,'struct') sublength = numel(field); subfields = fields(field); allsubfields = ''; - for i=1:length(subfields), + for i=1:length(subfields) allsubfields=[allsubfields subfields{i}]; if i~=length(subfields), allsubfields=[allsubfields ' ']; end end %Write size - if step==1, + if step==1 var_id(counter) = netcdf.defVar(ncid,[fieldname '_length'],'NC_INT',[]); else netcdf.putVar(ncid,var_id(counter),sublength); end counter=counter+1; %Write fields - if step==1, + if step==1 dim_id = netcdf.defDim(ncid,[fieldname '_fields_length'],numel(allsubfields)); var_id(counter) = netcdf.defVar(ncid,[fieldname '_fields'],'NC_CHAR',dim_id); else netcdf.putVar(ncid,var_id(counter),allsubfields); end - for n=1:sublength, - for i=1:length(subfields), + for n=1:sublength + for i=1:length(subfields) [var_id,counter] = structtonc(ncid,[fieldname '.' subfields{i} '(' num2str(n) ')'],field(n).(subfields{i}),depth+1,var_id,counter,step); end end %Cell -elseif isa(field,'cell'), +elseif isa(field,'cell') sublength = numel(field); %Write size - if step==1, + if step==1 var_id(counter) = netcdf.defVar(ncid,[fieldname '_length'],'NC_INT',[]); else netcdf.putVar(ncid,var_id(counter),sublength); end - for i=1:sublength, + for i=1:sublength [var_id,counter] = structtonc(ncid,[fieldname '{' num2str(i) '}'],field{i},depth+1,var_id,counter,step); end %Objects -elseif isobject(field), +elseif isobject(field) subfields = fields(field); - for i=1:length(subfields), + for i=1:length(subfields) [var_id,counter] = structtonc(ncid,[fieldname '.' subfields{i}],field.(subfields{i}),depth+1,var_id,counter,step); end else @@ -118,7 +118,7 @@ function [var_id,counter] = declareclass(ncid,fieldname,field,depth,var_id,counter,step); if isa(field,'char') - if step==1, + if step==1 dim_id = netcdf.defDim(ncid,[fieldname '_length'],numel(field)); var_id(counter) = netcdf.defVar(ncid,fieldname,'NC_CHAR',dim_id); else diff --git a/src/m/js/writejs1Darray.m b/src/m/js/writejs1Darray.m index 6eb187250..53cd29ded 100644 --- a/src/m/js/writejs1Darray.m +++ b/src/m/js/writejs1Darray.m @@ -6,7 +6,7 @@ function writejs1Darray(fid,prefix,array) fprintf(fid,'%s=%g;\n',prefix,array); else fprintf(fid,'%s=[',prefix); - for i=1:length(array)-1, + for i=1:length(array)-1 fprintf(fid,'%g,',array(i)); end fprintf(fid,'%g];\n',array(end)); diff --git a/src/m/js/writejs2Darray.m b/src/m/js/writejs2Darray.m index c8eaf25b1..f65e10715 100644 --- a/src/m/js/writejs2Darray.m +++ b/src/m/js/writejs2Darray.m @@ -1,18 +1,18 @@ function writejs2Darray(fid,prefix,array) - if isscalar(array), + if isscalar(array) fprintf(fid,'%s=%g;\n',prefix,array); else fprintf(fid,'%s=[',prefix); - for i=1:size(array,1)-1, + for i=1:size(array,1)-1 fprintf(fid,'[%g,',array(i,1)); - for j=2:size(array,2)-1, + for j=2:size(array,2)-1 fprintf(fid,'%g,',array(i,j)); end fprintf(fid,'%g],',array(i,end)); end fprintf(fid,'[%g,',array(end,1)); - for j=2:size(array,2)-1, + for j=2:size(array,2)-1 fprintf(fid,'%g,',array(end,j)); end fprintf(fid,'%g]];\n',array(end,end)); diff --git a/src/m/js/writejscellarray.m b/src/m/js/writejscellarray.m index b8b62b161..50cfe61a8 100644 --- a/src/m/js/writejscellarray.m +++ b/src/m/js/writejscellarray.m @@ -1,14 +1,14 @@ function writejscellarray(fid,prefix,cell) - if ~iscell(cell), + if ~iscell(cell) fprintf(fid,'%s=%g;\n',prefix,cell); else fprintf(fid,'%s=[',prefix); - for i=1:length(cell), + for i=1:length(cell) array=cell{i}; fprintf(fid,'['); - for j=1:length(array)-1, + for j=1:length(array)-1 fprintf(fid,'%g,',array(j)); end fprintf(fid,'%g]',array(end)); diff --git a/src/m/js/writejscellstring.m b/src/m/js/writejscellstring.m index 17e578d43..656034fb2 100644 --- a/src/m/js/writejscellstring.m +++ b/src/m/js/writejscellstring.m @@ -1,15 +1,15 @@ function writejscellstring(fid,prefix,cell) - if ~iscell(cell), + if ~iscell(cell) fprintf(fid,'%s=%g;\n',prefix,cell); else - if length(cell), - if length(cell)==1, + if length(cell) + if length(cell)==1 fprintf(fid,'%s=[''%s''];\n',prefix,cell{1}); else fprintf(fid,'%s=[''%s'',',prefix,cell{1}); - for i=2:length(cell)-1, + for i=2:length(cell)-1 fprintf(fid,'''%s'',',cell{i}); end fprintf(fid,'''%s''];\n',cell{end}); diff --git a/src/m/js/writejsdouble.m b/src/m/js/writejsdouble.m index bcc279748..b09fb91a6 100644 --- a/src/m/js/writejsdouble.m +++ b/src/m/js/writejsdouble.m @@ -1,5 +1,5 @@ function writejsdouble(fid,prefix,scalar) - if isinf(scalar), + if isinf(scalar) fprintf(fid,'%s=Infinity;\n',prefix); else fprintf(fid,'%s=%g;\n',prefix,scalar); diff --git a/src/m/js/writejsstruct.m b/src/m/js/writejsstruct.m index 835ef4e84..56952494c 100644 --- a/src/m/js/writejsstruct.m +++ b/src/m/js/writejsstruct.m @@ -3,13 +3,13 @@ function writejsstruct(fid,prefix,structure) fprintf(fid,'%s={};\n',prefix); fields=fieldnames(structure); - for i=1:numel(fields), + for i=1:numel(fields) fieldname=fields{i}; field=structure.(fieldname); - if isscalar(field), + if isscalar(field) fprintf(fid,'%s[''%s'']=%g;\n',prefix,fieldname,field); end - if ischar(field), + if ischar(field) fprintf(fid,'%s[''%s'']=''%s'';\n',prefix,fieldname,field); end end diff --git a/src/m/materials/cuffeytemperate.m b/src/m/materials/cuffeytemperate.m index 78ddc9c12..2c921b4b2 100644 --- a/src/m/materials/cuffeytemperate.m +++ b/src/m/materials/cuffeytemperate.m @@ -8,7 +8,7 @@ % Usage: % rigidity=cuffeytemperate(temperature, waterfraction, stressexp) -if (any(size(temperature)~=size(waterfraction))), +if (any(size(temperature)~=size(waterfraction))) error('input temperature and waterfraction should have same size!'); end if any(temperature<0) diff --git a/src/m/materials/paterson.m b/src/m/materials/paterson.m index 38257a580..6cd012f8b 100755 --- a/src/m/materials/paterson.m +++ b/src/m/materials/paterson.m @@ -1,7 +1,7 @@ function rigidity=paterson(temperature) %PATERSON - figure out the rigidity of ice for a given temperature % -% rigidity (in s^(1/3)Pa) is the flow law paramter in the flow law sigma=B*e(1/3) (Paterson, p97). +% rigidity (in s^(1/3)Pa) is the flow law parameter in the flow law sigma=B*e(1/3) (Paterson, p97). % temperature is in Kelvin degrees % % Usage: diff --git a/src/m/materials/paterson.py b/src/m/materials/paterson.py index 05ac46321..65c4ee708 100644 --- a/src/m/materials/paterson.py +++ b/src/m/materials/paterson.py @@ -4,7 +4,7 @@ def paterson(temperature): """PATERSON - figure out the rigidity of ice for a given temperature - rigidity (in s^(1/3)Pa) is the flow law paramter in the flow law + rigidity (in s^(1/3)Pa) is the flow law parameter in the flow law sigma = B * e(1/3) (Paterson, p97). temperature is in Kelvin degrees diff --git a/src/m/mech/analyticaldamage.m b/src/m/mech/analyticaldamage.m index 27bec3cd2..bee1b3d06 100755 --- a/src/m/mech/analyticaldamage.m +++ b/src/m/mech/analyticaldamage.m @@ -40,17 +40,17 @@ % [damage,B,backstress]=analyticaldamage(md,'eq','Weertman2D','smoothing',2,'sigmab',10e3,'coordsys','longitudinal'); % check inputs -if (nargin<1), +if (nargin<1) help analyticaldamage error('bad usage'); end -if isempty(fieldnames(md.results)), +if isempty(fieldnames(md.results)) error(['md.results.strainrate is not present. Calculate using md=mechanicalproperties(md,vx,vy)']); end -if dimension(md.mesh)~=2, +if dimension(md.mesh)~=2 error('only 2d model supported currently'); end -if any(md.flowequation.element_equation~=2), +if any(md.flowequation.element_equation~=2) disp('Warning: the model has some non SSA elements. These will be treated like SSA elements'); end @@ -60,7 +60,7 @@ smoothing = getfieldvalue(options,'smoothing',0); sigmab = getfieldvalue(options,'sigmab',0); coordsys = getfieldvalue(options,'coordsys','longitudinal'); -if length(sigmab)==1, +if length(sigmab)==1 sigmab=sigmab*ones(md.mesh.numberofvertices,1); end diff --git a/src/m/mech/backstressfrominversion.m b/src/m/mech/backstressfrominversion.m index a15ef2bf3..09fb7c2b4 100644 --- a/src/m/mech/backstressfrominversion.m +++ b/src/m/mech/backstressfrominversion.m @@ -32,17 +32,17 @@ % backstress=backstressfrominversion(md,'smoothing',2,'coordsys','longitudinal','tempmask',true); % check inputs -if (nargin<1), +if (nargin<1) help backstressfrominversion error('bad usage'); end -if isempty(fieldnames(md.results)), +if isempty(fieldnames(md.results)) error(['md.results.strainrate is not present. Calculate using md=mechanicalproperties(md,vx,vy)']); end -if dimension(md.mesh)~=2, +if dimension(md.mesh)~=2 error('only 2d model supported currently'); end -if any(md.flowequation.element_equation~=2), +if any(md.flowequation.element_equation~=2) disp('Warning: the model has some non SSA elements. These will be treated like SSA elements'); end diff --git a/src/m/mech/basalstress.m b/src/m/mech/basalstress.m index 68fdc38b9..06f1be8c2 100644 --- a/src/m/mech/basalstress.m +++ b/src/m/mech/basalstress.m @@ -1,85 +1,65 @@ function [bx by b]=basalstress(md) -%BASALSTRESS - compute basal stress from basal drag and geometric information. -% -% Computes basal stress from geometric information and ice velocity in md.initialization. Follows the basal stress definition in "src/c/classes/Loads/Friction.cpp", lines 1102-1136. -% -% Usage: -% [bx by b]=basalstress(md); -% -% See also: plot_basaldrag + % BASALSTRESS - compute basal stress from friction law and geometric information. + % Computes basal stress from basal sliding parametrization in md.friction and geometry and ice velocity in md.initialization. Follows the basal stress definition in "src/c/classes/Loads/Friction.cpp", lines 1102-1136. + % + % USEAGE: + % b = basalstress(md); % one argout returns the scalar magnitude + % [bx by b] = basalstress(md); % multiple argout returns the horizontal vector components + % INPUT: + % md ISSM model from which to take md.friction and md.initialization. + % OUTPUT: + % bx x component of basal stress + % by y component of basal stress + % b scalar magnitude of basal stress + % + % See also: EFFECTIVEPRESSURE, PLOT_BASALDRAG -%Compute effective pressure -g = md.constants.g; -rho_ice = md.materials.rho_ice; -rho_water = md.materials.rho_water; + % compute sliding velocity + ub = sqrt(md.initialization.vx.^2+md.initialization.vy.^2)/md.constants.yts; % horizontal vel (m/s) + ubx = md.initialization.vx/md.constants.yts; % vx (m/s) + uby = md.initialization.vy/md.constants.yts; % vy (m/s) -sealevel = 0; -p_ice = g*rho_ice*md.geometry.thickness; + %compute basal drag (S.I.) + switch(class(md.friction)) + case 'friction' + % calculate effective pressure using coupling definition in md.friction + N = effectivepressure(md); % effective pressure (Pa) -if isprop(md.friction, 'coupling') - coupling = md.friction.coupling; -else - warning(sprintf('md.friction.coupling is not found. Default coupling is set to 0.')); - coupling = 0; -end + % compute exponents + s=averaging(md,1./md.friction.p,0); + r=averaging(md,md.friction.q./md.friction.p,0); -switch(coupling) - case 0 - p_water=g*rho_water*(sealevel-md.geometry.base); - N = p_ice-p_water; - case 1 - N = p_ice; - case 2 - p_water=g*rho_water*(sealevel-md.geometry.base); - p_water=max(p_water,0.0); - N = p_ice-p_water; - case 3 - N = max(md.friction.effective_pressure, 0); - case 4 - error('md.friction.coupling=4 is not supported yet.'); - otherwise - error('not supported yet'); -end + alpha2 = (N.^r).*(md.friction.coefficient.^2).*(ub.^(s-1)); -%compute sliding velocity -ub=sqrt(md.initialization.vx.^2+md.initialization.vy.^2)/md.constants.yts; -ubx=md.initialization.vx/md.constants.yts; -uby=md.initialization.vy/md.constants.yts; + case 'frictionschoof' + % calculate effective pressure using coupling definition in md.friction + N = effectivepressure(md); % effective pressure (Pa) + if any(N < 0) + %NOTE: Negative values of effective pressure N return a complex number in alpha2. Treated here with minimum threshold. + warning('Find effective pressure value N < 0. Enforcing minimum effective pressure of N_min = 0.1'); + N = max(N, 0.1); + end -%compute basal drag (S.I.) -switch(class(md.friction)) - case 'friction' - %compute exponents - s=averaging(md,1./md.friction.p,0); - r=averaging(md,md.friction.q./md.friction.p,0); + % compute parameters + m=averaging(md,md.friction.m,0); + C=averaging(md,md.friction.C,0); + Cmax=averaging(md,md.friction.Cmax,0); - alpha2 = (N.^r).*(md.friction.coefficient.^2).*(ub.^(s-1)); + alpha2 = (C.^2 .* ub.^(m-1))./(1 + (C.^2./(Cmax.*N)).^(1./m).*ub).^(m); - case 'frictionschoof' - if any(N < 0) - %NOTE: Sometimes, negative value of effective pressure N gives image number in alpha2. To prevent the image value in alpha2, we use small values. - warning('Find effective pressure value < 0. Treating minimum effective value with 0.1'); - N = max(N, 0.1); - end - m=averaging(md,md.friction.m,0); - C=averaging(md,md.friction.C,0); - Cmax=averaging(md,md.friction.Cmax,0); - - alpha2 = (C.^2 .* ub.^(m-1))./(1 + (C.^2./(Cmax.*N)).^(1./m).*ub).^(m); + case 'frictionweertman' + m = averaging(md,md.friction.m,0); + C = md.friction.C; + alpha2 = C.^2 .* ub.^(1./m-1); - case 'frictionweertman' - m = averaging(md,md.friction.m,0); - C = md.friction.C; - alpha2 = C.^2 .* ub.^(1./m-1); + otherwise + error('friction class not supported yet'); + end + b = alpha2.*ub; + bx = -alpha2.*ubx; + by = -alpha2.*uby; - otherwise - error('friction class not supported yet'); -end -b = alpha2.*ub; -bx = -alpha2.*ubx; -by = -alpha2.*uby; - -%return magnitude of only one output is requested -if nargout==1 - bx = b; -end + %return magnitude of only one output is requested + if nargout==1 + bx = b; + end diff --git a/src/m/mech/basalstress.py b/src/m/mech/basalstress.py index 6b14d1c7a..e894e36da 100644 --- a/src/m/mech/basalstress.py +++ b/src/m/mech/basalstress.py @@ -1,75 +1,64 @@ from friction import friction from frictionweertman import frictionweertman from frictionschoof import frictionschoof +from effectivepressure import effectivepressure from averaging import averaging import numpy as np def basalstress(md): ''' - BASALSTRESS - compute basal stress from basal drag and geometric information. + BASALSTRESS - compute basal stress from friction law and geometric information. + Computes basal stress from basal sliding parametrization in md.friction and geometry and ice velocity in md.initialization. Follows the basal stress definition in "src/c/classes/Loads/Friction.cpp", lines 1102-1136. - Computes basal stress from geometric information and ice velocity in md.initialization. Follows the basal stress definition in "src/c/classes/Loads/Friction.cpp", lines 1102-1136. + Usage: + bx, by, b=basalstress(md) - Usage: - [bx by b]=basalstress(md); + INPUT: + md ISSM model from which to take md.friction and md.initialization - See also: plot_basaldrag - ''' + OUTPUT: + bx x component of basal stress + by y component of basal stress + b scalar magnitude of basal stress - #Check md.friction class - if not (isinstance(md.friction,friction) | isinstance(md.friction,frictionschoof) | isinstance(md.friction,frictionweertman)): - raise Exception('Error: md.friction only supports "friction.m" class.') - - #Compute effective pressure - g =md.constants.g - rho_ice =md.materials.rho_ice - rho_water=md.materials.rho_water - - sealevel=0 - p_ice=g*rho_ice*md.geometry.thickness - - coupling=md.friction.coupling - if coupling==0: - p_water=g*rho_water*(sealevel-md.geometry.base) - N = p_ice-p_water - elif coupling==1: - N = p_ice - elif coupling==2: - p_water=g*rho_water*(sealevel-md.geometry.base) - p_water=np.maximum(p_water,0.0) - N = p_ice-p_water - elif coupling==3: - N = np.maximum(md.friction.effective_pressure,0.0) - elif coupling==4: - raise Exception('md.friction.coupling=4 is not supported yet.') - else: - raise Exception('not supported yet') + See also: plot_basaldrag, effectivepressure + ''' - #compute sliding velocity + # compute sliding velocity ub=np.sqrt(md.initialization.vx**2+md.initialization.vy**2)/md.constants.yts ubx=md.initialization.vx/md.constants.yts uby=md.initialization.vy/md.constants.yts - ub =np.ravel(ub) - ubx =np.ravel(ubx) - uby =np.ravel(uby) + + # coerce 1-D array + ub =np.ravel(ub) + ubx =np.ravel(ubx) + uby =np.ravel(uby) #compute basal drag (S.I.) - #reshape array to vector (N,) - N =np.ravel(N) - if isinstance(md.friction,friction): - #compute exponents + # calculate effective pressure using coupling definition in md.friction + N = effectivepressure(md) # effective pressure (Pa) + + # compute exponents s=averaging(md,1/md.friction.p,0) r=averaging(md,md.friction.q/md.friction.p,0) coefficient=np.ravel(md.friction.coefficient) - r =np.ravel(r) - s =np.ravel(s) + + # coerce 1-D array + r =np.ravel(r) + s =np.ravel(s) alpha2 = (N**r)*(md.friction.coefficient**2)*(ub**(s-1)) elif isinstance(md.friction,frictionschoof): - if np.any(N<0): - #NOTE: Sometimes, N negative values gives image number in alpha2. To prevent the image value in alpha2, we use small values. + # calculate effective pressure using coupling definition in md.friction + N = effectivepressure(md) # effective pressure (Pa) + + if np.any(N<=0): + #NOTE: Negative values of effective pressure N return a complex number in alpha2. Treated here with minimum threshold. + warnings.warn('Find effective pressure value N < 0. Enforcing minimum effective pressure of N_min = 0.1'); N = np.maximum(N,0.1) + + # compute parameters m=averaging(md,md.friction.m,0) C=averaging(md,md.friction.C,0) Cmax=averaging(md,md.friction.Cmax,0) diff --git a/src/m/mech/calcbackstress.m b/src/m/mech/calcbackstress.m index d39b59a81..7c4133842 100644 --- a/src/m/mech/calcbackstress.m +++ b/src/m/mech/calcbackstress.m @@ -29,17 +29,17 @@ % backstress=backstressfrominversion(md,'smoothing',2,'coordsys','longitudinal'); % check inputs -if (nargin<1), +if (nargin<1) help backstressfrominversion error('bad usage'); end -if isempty(fieldnames(md.results)), +if isempty(fieldnames(md.results)) error(['md.results.strainrate is not present. Calculate using md=mechanicalproperties(md,vx,vy)']); end -if dimension(md.mesh)~=2, +if dimension(md.mesh)~=2 error('only 2d model supported currently'); end -if any(md.flowequation.element_equation~=2), +if any(md.flowequation.element_equation~=2) disp('Warning: the model has some non SSA elements. These will be treated like SSA elements'); end @@ -52,7 +52,7 @@ T=0.5*md.materials.rho_ice*md.constants.g*(1-md.materials.rho_ice/md.materials.rho_water)*md.geometry.thickness; n=averaging(md,md.materials.rheology_n,0); B=md.materials.rheology_B; -if md.damage.isdamage, +if md.damage.isdamage D=md.damage.D else D=0; diff --git a/src/m/mech/cfl_step.m b/src/m/mech/cfl_step.m index b7ff5e2fe..00a8b21a4 100755 --- a/src/m/mech/cfl_step.m +++ b/src/m/mech/cfl_step.m @@ -10,7 +10,7 @@ % dt=cfl_step(md,md.results.StressbalanceSolution.Vx,md.results.StressbalanceSolution.Vy) %Check length of velocities -if size(vx,1)~=md.mesh.numberofvertices & size(vy,1)~=md.mesh.numberofvertices, +if size(vx,1)~=md.mesh.numberofvertices & size(vy,1)~=md.mesh.numberofvertices error('timesteps error message: size of velocity components must be the same as md.mesh.numberofvertices'); end diff --git a/src/m/mech/damagefrominversion.m b/src/m/mech/damagefrominversion.m index 7fd443c30..eb2a1a53d 100644 --- a/src/m/mech/damagefrominversion.m +++ b/src/m/mech/damagefrominversion.m @@ -13,17 +13,17 @@ % damage=damagefrominversion(md) % check inputs -if (nargin<1), +if (nargin<1) help backstressfrominversion error('bad usage'); end -if isempty(fieldnames(md.results)), +if isempty(fieldnames(md.results)) error(['md.results.strainrate is not present. Calculate using md=mechanicalproperties(md,vx,vy)']); end -if dimension(md.mesh)~=2, +if dimension(md.mesh)~=2 error('only 2d model supported currently'); end -if any(md.flowequation.element_equation~=2), +if any(md.flowequation.element_equation~=2) disp('Warning: the model has some non SSA elements. These will be treated like SSA elements'); end diff --git a/src/m/mech/effectivepressure.m b/src/m/mech/effectivepressure.m new file mode 100644 index 000000000..73504c699 --- /dev/null +++ b/src/m/mech/effectivepressure.m @@ -0,0 +1,55 @@ +function N = effectivepressure(md,varargin) +% EFFECTIVEPRESSURE - Calculate the effective basal pressure N from md.geometry and effective pressure coupling rule in md.friction +% USEAGE: +% N = effectivepressure(md); +% INPUT: +% md ISSM model from which to calculate pressure +% OUTPUT: +% N effective pressure at base (Pa) +% +% See also: BASALSTRESS + +% Get options +options = pairoptions(varargin{:}); + +if isprop(md.friction, 'coupling') + coupling = md.friction.coupling; +else + warning(sprintf('md.friction.coupling is not found. Default coupling is set to 0.')); + coupling = 0; +end + +sealevel = 0; % sea level reference elevation(m) + +p_ice = md.constants.g * md.materials.rho_ice * md.geometry.thickness; % ice pressure (Pa) +p_water = md.constants.g * md.materials.rho_water * (sealevel-md.geometry.base); % water pressure (Pa) + +% calculate effective pressure using coupling definition in md.friction (Pa) +switch(coupling) + case 0 % uniform sheet (negative water pressure ok, default) + N = p_ice-p_water; + case 1 % effective pressure is equal to the overburden pressure + N = p_ice; + case 2 % uniform sheet (water pressure >= 0) + p_water=max(p_water,0.0); + N = p_ice-p_water; + case 3 % Use effective pressure prescribed in md.friction.effective_pressure + N = max(md.friction.effective_pressure, 0); + case 4 % Use effective pressure dynamically calculated by the hydrology model (i.e., fully coupled) + + if exist(options,'head') + head = getfieldvalue(options,'head'); + assert(length(head) == md.mesh.numberofvertices,['Error: Given head size is not numberofvertices. Check size of given head ' num2str(size(head))]); + p_water = md.constants.g*md.materials.rho_freshwater*(head-md.geometry.base); + else + if isa(md.hydrology,'hydrologyprescribe') + p_water=md.constants.g*md.materials.rho_freshwater*(md.hydrology.head -md.geometry.base); + else + error(['Coupling method = ' num2str(coupling,'%i') ' is not supported yet with ' class(md.hydrology) '. Only for hydrologyprescribe']); + end + end + + N = p_ice-p_water; + otherwise + error('not supported yet'); +end diff --git a/src/m/mech/effectivepressure.py b/src/m/mech/effectivepressure.py new file mode 100644 index 000000000..38e35eee9 --- /dev/null +++ b/src/m/mech/effectivepressure.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +import numpy as np +import warnings +from pairoptions import pairoptions + +from hydrologyprescribe import hydrologyprescribe + +def effectivepressure(md, *args): + ''' + EFFECTIVEPRESSURE - Calculate the effective basal pressure N from md.geometry and effective pressure coupling rule in md.friction + + USEAGE: + N = effectivepressure(md); + + INPUT: + md ISSM model from which to calculate pressure + + OUTPUT: + N effective pressure at base (Pa) + + See also: BASALSTRESS + ''' + + # Get options + options = pairoptions(*args) + + if hasattr(md.friction, 'coupling'): + coupling = md.friction.coupling + else: + warnings.warn(sprintf('md.friction.coupling is not found. Default coupling is set to 0.')) + coupling = 0 + + sealevel = 0 # sea level reference elevation(m) + + p_ice = md.constants.g * md.materials.rho_ice * md.geometry.thickness # ice pressure (Pa) + p_water = md.constants.g * md.materials.rho_water * (sealevel-md.geometry.base) # water pressure (Pa) + + # calculate effective pressure using coupling definition in md.friction (Pa) + if coupling == 0: # uniform sheet (negative water pressure ok, default) + N = p_ice-p_water + elif coupling == 1: # effective pressure is equal to the overburden pressure + N = p_ice + elif coupling == 2: # uniform sheet (water pressure >= 0) + p_water=max(p_water,0.0) + N = p_ice-p_water + elif coupling == 3: # Use effective pressure prescribed in md.friction.effective_pressure + N = np.maximum(md.friction.effective_pressure, 0) + elif coupling == 4: # Use effective pressure dynamically calculated by the hydrology model (i.e., fully coupled) + if options.exist('head'): + head = options.getfieldvalue('head') + assert(length(head) == md.mesh.numberofvertices,'Error: Given head size is not numberofvertices. Check size of given head ' + f'{np.shape(head)}') + p_water = md.constants.g*md.materials.rho_freshwater*(head-md.geometry.base) + else: + if isinstance(md.hydrology,hydrologyprescribe): + p_water=md.constants.g*md.materials.rho_freshwater*(md.hydrology.head -md.geometry.base) + else: + raise Exception('Coupling method = ' + str(coupling,'%i') + ' is not supported yet with ' + class(md.hydrology) + '. Only for hydrologyprescribe') + + N = p_ice-p_water + else: + raise Exception('not supported yet') + + return N + diff --git a/src/m/mech/shear2d.m b/src/m/mech/shear2d.m index e404f65f1..f7242a5ae 100644 --- a/src/m/mech/shear2d.m +++ b/src/m/mech/shear2d.m @@ -18,6 +18,6 @@ s=sqrt(sx.^2+sy.^2+sxy.^2+sx.*sy); %if user requested only one output, it must be the norm -if nargout==1, +if nargout==1 sx=s; end diff --git a/src/m/mech/strainrateuncert.m b/src/m/mech/strainrateuncert.m index 8d46715df..012f75483 100644 --- a/src/m/mech/strainrateuncert.m +++ b/src/m/mech/strainrateuncert.m @@ -16,25 +16,25 @@ % md=mechanicalproperties(md,md.inversion.vx_obs,md.inversion.vy_obs,dv); %some checks -if length(vx)~=md.mesh.numberofvertices | length(vy)~=md.mesh.numberofvertices, +if length(vx)~=md.mesh.numberofvertices | length(vy)~=md.mesh.numberofvertices error(['the input velocity should be of size ' num2str(md.mesh.numberofvertices) '!']) end -if length(dvx)==1, +if length(dvx)==1 dvx=dvx*ones(md.mesh.numberofelements,1); end -if length(dvx)~=md.mesh.numberofelements, +if length(dvx)~=md.mesh.numberofelements error(['the velocity error dvx should be of size ' num2str(md.mesh.numberofelements) ' or 1!']) end -if length(dvy)==1, +if length(dvy)==1 dvy=dvy*ones(md.mesh.numberofelements,1); end -if length(dvy)~=md.mesh.numberofelements, +if length(dvy)~=md.mesh.numberofelements error(['the velocity error dvy should be of size ' num2str(md.mesh.numberofelements) ' or 1!']) end -if dimension(md.mesh)~=2, +if dimension(md.mesh)~=2 error('only 2d model supported yet'); end -if any(md.flowequation.element_equation~=2), +if any(md.flowequation.element_equation~=2) disp('Warning: the model has some non SSA elements. These will be treated like SSA''s elements'); end diff --git a/src/m/mech/thomasparams.m b/src/m/mech/thomasparams.m index 9bd425e77..fd822d614 100644 --- a/src/m/mech/thomasparams.m +++ b/src/m/mech/thomasparams.m @@ -47,13 +47,13 @@ help ThomasParams error('bad usage'); end -if isempty(fieldnames(md.results)), +if isempty(fieldnames(md.results)) error(['md.results.strainrate is not present. Calculate using md=mechanicalproperties(md,vx,vy)']) end -if dimension(md.mesh)~=2, +if dimension(md.mesh)~=2 error('only 2d model supported currently'); end -if any(md.flowequation.element_equation~=2), +if any(md.flowequation.element_equation~=2) disp('Warning: the model has some non SSA elements. These will be treated like SSA elements'); end @@ -130,7 +130,7 @@ % a < -1 in areas of strong lateral compression or longitudinal compression and % theta flips sign at a = -2 pos=find(abs((abs(a)-2))<1e-3); -if length(pos)>0, +if length(pos)>0 disp(['Warning: ', num2str(length(pos)), ' vertices have alpha within 1e-3 of -2']) end a(pos)=-2+1e-3; diff --git a/src/m/mesh/ComputeHessian.m b/src/m/mesh/ComputeHessian.m index d38f99c33..298ae1ee2 100644 --- a/src/m/mesh/ComputeHessian.m +++ b/src/m/mesh/ComputeHessian.m @@ -16,10 +16,10 @@ numberofelements=size(index,1); %some checks -if length(field)~=numberofnodes & length(field)~=numberofelements, +if length(field)~=numberofnodes & length(field)~=numberofelements error('ComputeHessian error message: the given field size not supported yet'); end -if ~strcmpi(type,'node') & ~strcmpi(type,'element'), +if ~strcmpi(type,'node') & ~strcmpi(type,'element') error('ComputeHessian error message: only ''node'' or ''element'' type supported yet'); end @@ -35,7 +35,7 @@ weights=sparse(line,ones(linesize,1),repmat(areas,3,1),numberofnodes,1); %compute field on nodes if on elements -if length(field)==numberofelements, +if length(field)==numberofelements field=sparse(line,ones(linesize,1),repmat(areas.*field,3,1),numberofnodes,1)./weights ; end diff --git a/src/m/mesh/ComputeMetric.m b/src/m/mesh/ComputeMetric.m index 33f17ebd0..ffcedd2bb 100644 --- a/src/m/mesh/ComputeMetric.m +++ b/src/m/mesh/ComputeMetric.m @@ -45,7 +45,7 @@ %take care of NaNs if any (use Matlab eig in a loop) [pos posj]=find(isnan(metric)); clear posj; -if ~isempty(pos), +if ~isempty(pos) fprintf(' %i %s',length(pos),'NaN found in the metric. Use Matlab routine...'); for i=1:length(pos) H=[hessian(pos(i),1) hessian(pos(i),2) @@ -61,6 +61,6 @@ end end -if any(isnan(metric)), +if any(isnan(metric)) error('ComputeMetric error message: NaN in the metric despite our efforts...') end diff --git a/src/m/mesh/FixMesh.m b/src/m/mesh/FixMesh.m index ceaa9aaf4..4d7004ccb 100644 --- a/src/m/mesh/FixMesh.m +++ b/src/m/mesh/FixMesh.m @@ -20,7 +20,7 @@ flags=zeros(length(x2),1); flags(index2)=1; orphans=find(flags==0); -while ~isempty(orphans), +while ~isempty(orphans) %take the first orphan, the lower numbered, and take it out orphan=orphans(1); diff --git a/src/m/mesh/GetNodalFunctionsCoeff.m b/src/m/mesh/GetNodalFunctionsCoeff.m index 25c542fb2..b381cdcfe 100644 --- a/src/m/mesh/GetNodalFunctionsCoeff.m +++ b/src/m/mesh/GetNodalFunctionsCoeff.m @@ -21,17 +21,17 @@ nods=length(x); %some checks -if nargin~=3 | (nargout~=2 & nargout~=3), +if nargin~=3 | (nargout~=2 & nargout~=3) help GetNodalFunctionsCoeff error('GetNodalFunctionsCoeff error message: bad usage') end -if length(y)~=nods, +if length(y)~=nods error('GetNodalFunctionsCoeff error message: x and y do not have the same length') end -if max(index(:))>nods, +if max(index(:))>nods error(['GetNodalFunctionsCoeff error message: index should not have values above ' num2str(nods) ]) end -if size(index,2)~=3, +if size(index,2)~=3 error('GetNodalFunctionsCoeff error message: only 2d meshes supported. index should have 3 columns.') end @@ -49,7 +49,7 @@ beta =[invdet.*(x3-x2) invdet.*(x1-x3) invdet.*(x2-x1)]; %get gamma if requested -if nargout==3, +if nargout==3 gamma=zeros(nels,3); gamma=[invdet.*(x2.*y3-x3.*y2) invdet.*(y1.*x3-y3.*x1) invdet.*(x1.*y2-x2.*y1)]; varargout{1}=gamma; diff --git a/src/m/mesh/MeshToShp.m b/src/m/mesh/MeshToShp.m index 788c4cded..6e4adca12 100755 --- a/src/m/mesh/MeshToShp.m +++ b/src/m/mesh/MeshToShp.m @@ -5,7 +5,7 @@ function MeshToShp(md,shapefilename) % MeshToShp(md,'Greenland.shp'); contours= struct([]); - for i=1:md.mesh.numberofvertices, + for i=1:md.mesh.numberofvertices contours(i).x = md.mesh.x(i); contours(i).y = md.mesh.y(i); contours(i).id = i; diff --git a/src/m/mesh/NodeInElement.m b/src/m/mesh/NodeInElement.m index c35fe8b79..97ec4da5a 100644 --- a/src/m/mesh/NodeInElement.m +++ b/src/m/mesh/NodeInElement.m @@ -21,7 +21,7 @@ max_connectivity=max(nodeconnectivity(:,end)); node_in_element=zeros(length(newx),max_connectivity+1); %last column is the number of elements to which the row node is connected. -for i=1:length(newx), +for i=1:length(newx) x0=newx(i); y0=newy(i); diff --git a/src/m/mesh/ProfileProjectOntoMesh.m b/src/m/mesh/ProfileProjectOntoMesh.m index 60fe58ba2..51c0c0124 100644 --- a/src/m/mesh/ProfileProjectOntoMesh.m +++ b/src/m/mesh/ProfileProjectOntoMesh.m @@ -24,7 +24,7 @@ processed_indices=[]; processed_x=[]; processed_y=[]; -for i=1:numel(indices), +for i=1:numel(indices) if(((indices(i)-floor(indices(i)))~=0) && ((ceil(indices(i))-indices(i))~=0)) processed_indices=[processed_indices;floor(indices(i))]; processed_x=[processed_x;x0(i)]; @@ -37,9 +37,9 @@ newy=profile.y; count=1; -for i=1:numel(profile.x), +for i=1:numel(profile.x) pos=find(processed_indices==i); - if ~isempty(pos), + if ~isempty(pos) newx=[newx(1:count); processed_x(pos); newx(count+1:end)]; newy=[newy(1:count); processed_y(pos); newy(count+1:end)]; count=count+length(pos)+1; @@ -60,7 +60,7 @@ mesh_profile=[newx(1:end-1) newy(1:end-1) newx(2:end) newy(2:end) zeros(length(newy(2:end)),1)]; %find which element each segment belongs to. -for i=1:length(newx)-1, +for i=1:length(newx)-1 common=intersect(node_in_element(i,1:node_in_element(i,end)), node_in_element(i+1,1:node_in_element(i+1,end))); mesh_profile(i,end)=common(1); end diff --git a/src/m/mesh/TwoDToThreeD.m b/src/m/mesh/TwoDToThreeD.m index 5436bd18f..40d713f2f 100644 --- a/src/m/mesh/TwoDToThreeD.m +++ b/src/m/mesh/TwoDToThreeD.m @@ -1,6 +1,6 @@ function md=TwoDToThreeD(md,planet) %reproject model into lat,long if necessary: - if ~strcmpi(md.mesh.proj,epsg2proj(4326)), + if ~strcmpi(md.mesh.proj,epsg2proj(4326)) [md.mesh.x,md.mesh.y]=CoordTransform(md.mesh.x,md.mesh.y,md.mesh.proj,'EPSG:4326'); end diff --git a/src/m/mesh/argusmesh.m b/src/m/mesh/argusmesh.m index c7a6f3cbc..130203df8 100644 --- a/src/m/mesh/argusmesh.m +++ b/src/m/mesh/argusmesh.m @@ -11,7 +11,7 @@ % md=argusmesh(md,'Domain.exp') %some argument check: -if nargin~=2 | nargout~=1, +if nargin~=2 | nargout~=1 help argustomodel; error('argustomodel error message: bad usage'); end @@ -24,13 +24,13 @@ %open infile: fileid=fopen(infile,'r'); -if fileid==-1, +if fileid==-1 error(['Could not open file ' infile ' for reading']); end %Read first line of the argus mesh: node and element parameters [buffer,bytecount]=fscanf(fileid,'%i %i %i %i',[1 4]); -if bytecount~=4, +if bytecount~=4 error(['Problem reading ' infile ' file at line #1']); end nel=buffer(1); @@ -49,11 +49,11 @@ %read nodes: format_string='%s %i %f %f '; -for n=1:num_node_parameters, +for n=1:num_node_parameters format_string=[format_string ' %i ']; end -for n=1:nods, +for n=1:nods [buffer,bytecount]=fscanf(fileid,format_string,[1,num_node_parameters+4]); x(n)=buffer(3); y(n)=buffer(4); @@ -62,10 +62,10 @@ %read elements: format_string='%s %i %i %i %i'; -for n=1:num_element_parameters, +for n=1:num_element_parameters format_string=[format_string ' %i ']; end -for n=1:nel, +for n=1:nel [buffer,bytecount]=fscanf(fileid,format_string,[1,num_element_parameters+5]); elements(n,:)=buffer(3:5); element_parameters(n,:)=buffer(6:length(buffer)); diff --git a/src/m/mesh/augment2dmesh.m b/src/m/mesh/augment2dmesh.m index 20b2c0f0c..1829919f1 100644 --- a/src/m/mesh/augment2dmesh.m +++ b/src/m/mesh/augment2dmesh.m @@ -22,13 +22,13 @@ %The innner segments of mhband and the outer segments of mh are identical. Go into the elements of %mhband and set them to their md1 equivalent: tol=getfieldvalue(options,'tolerance',1); %1 meter -for i=1:length(mhband.segments), +for i=1:length(mhband.segments) node2=mhband.segments(i,1); %this node2 has an equivalent on the segments of mdh: - for j=1:length(mh.segments), + for j=1:length(mh.segments) node1=mh.segments(j,1); %if mhband.x(node2-mh.numberofvertices) == mh.x(node1) && mhband.y(node2-mh.numberofvertices) == mh.y(node1), - if sqrt((mhband.x(node2-mh.numberofvertices) - mh.x(node1))^2 + (mhband.y(node2-mh.numberofvertices) - mh.y(node1))^2)1, + if i>1 flags=ContourToNodes(domain(i).x,domain(i).y,domain(1),0); - if any(~flags), + if any(~flags) error('bamg error message: All holes should be strictly inside the principal domain'); end end @@ -150,7 +150,7 @@ %Check orientation nods=domain(i).nods-1; %the domain is closed (domain[1] = domain[end]) test = sum([(domain(i).x(2:nods+1) - domain(i).x(1:nods)).*(domain(i).y(2:nods+1) + domain(i).y(1:nods))]); - if (i==1 && test>0) || (i>1 && test<0), + if (i==1 && test>0) || (i>1 && test<0) disp('At least one contour was not correctly oriented and has been re-oriented'); domain(i).x = flipud(domain(i).x); domain(i).y = flipud(domain(i).y); end @@ -168,7 +168,7 @@ new_edge_length=length(bamg_geometry.Edges); edges_required=(edge_length+1):new_edge_length; - if i>1, + if i>1 bamg_geometry.SubDomains=[bamg_geometry.SubDomains; 2 count+1 1 -subdomain_ref]; subdomain_ref = subdomain_ref+1; else @@ -178,10 +178,10 @@ %update counter count=count+nods; end - for i=1:length(holes), + for i=1:length(holes) %Check that the hole is closed - if (holes(i).x(1)~=holes(i).x(end) | holes(i).y(1)~=holes(i).y(end)), + if (holes(i).x(1)~=holes(i).x(end) | holes(i).y(1)~=holes(i).y(end)) error('bamg error message: all contours provided in ''holes'' should be closed'); end @@ -204,16 +204,16 @@ %update counter count=count+nods; end - for i=1:length(subdomains), + for i=1:length(subdomains) %Check that the subdomain is closed - if (subdomains(i).x(1)~=subdomains(i).x(end) | subdomains(i).y(1)~=subdomains(i).y(end)), + if (subdomains(i).x(1)~=subdomains(i).x(end) | subdomains(i).y(1)~=subdomains(i).y(end)) error('bamg error message: all contours provided in ''subdomains'' should be closed'); end %Checks that all subdomains are INSIDE the principal domain (principal domain should be index 0) flags=ContourToNodes(subdomains(i).x,subdomains(i).y,domain(1),0); - if any(~flags), + if any(~flags) error('bamg error message: All subdomains should be strictly inside the principal domain'); end @@ -236,48 +236,48 @@ count=count+nods; end - if getfieldvalue(options,'vertical',0), - if numel(getfieldvalue(options,'Markers',[]))~=size(bamg_geometry.Edges,1), + if getfieldvalue(options,'vertical',0) + if numel(getfieldvalue(options,'Markers',[]))~=size(bamg_geometry.Edges,1) error(['for 2d vertical mesh, ''Markers'' option is required, and should be of size ' num2str(size(bamg_geometry.Edges,1))]); end end - if numel(getfieldvalue(options,'Markers',[]))==size(bamg_geometry.Edges,1), + if numel(getfieldvalue(options,'Markers',[]))==size(bamg_geometry.Edges,1) bamg_geometry.Edges(:,3)=getfieldvalue(options,'Markers'); end %take care of rifts - if exist(options,'rifts'), + if exist(options,'rifts') %read rift file according to its extension: riftfile=getfieldvalue(options,'rifts'); [path,name,ext]=fileparts(riftfile); - if strcmp(ext,'.exp'), + if strcmp(ext,'.exp') rift=expread(riftfile); - elseif strcmp(ext,'.shp'), + elseif strcmp(ext,'.shp') rift=shpread(riftfile); else error(['bamg error message: file ' riftfile ' format not supported (.exp or .shp)']); end - for i=1:length(rift), + for i=1:length(rift) %detect whether all points of the rift are inside the domain flags=ContourToNodes(rift(i).x,rift(i).y,domain(1),0); - if ~flags, + if ~flags error('one rift has all its points outside of the domain outline'), - elseif any(~flags), + elseif any(~flags) %We have LOTS of work to do disp('Rift tip outside of or on the domain has been detected and is being processed...'); %check that only one point is outside (for now) - if sum(~flags)~=1, + if sum(~flags)~=1 error('bamg error message: only one point outside of the domain is supported at this time'); end %Move tip outside to the first position - if flags(1)==0, + if flags(1)==0 %OK, first point is outside (do nothing), - elseif (flags(end)==0), + elseif (flags(end)==0) rift(i).x=flipud(rift(i).x); rift(i).y=flipud(rift(i).y); else @@ -290,7 +290,7 @@ x2=rift(i).x(2); y2=rift(i).y(2); for j=1:length(domain(1).x)-1; - if SegIntersect([x1 y1; x2 y2],[domain(1).x(j) domain(1).y(j); domain(1).x(j+1) domain(1).y(j+1)]), + if SegIntersect([x1 y1; x2 y2],[domain(1).x(j) domain(1).y(j); domain(1).x(j+1) domain(1).y(j+1)]) %Get position of the two nodes of the edge in domain i1=j; @@ -306,11 +306,11 @@ segdis= sqrt((x4-x3)^2+(y4-y3)^2); tipdis=[sqrt((x-x3)^2+(y-y3)^2) sqrt((x-x4)^2+(y-y4)^2)]; - if (min(tipdis)/segdis) < getfieldvalue(options,'toltip',0), + if (min(tipdis)/segdis) < getfieldvalue(options,'toltip',0) disp('moving tip-domain intersection point'); %Get position of the closer point - if tipdis(1)>tipdis(2), + if tipdis(1)>tipdis(2) pos=i2; else pos=i1; @@ -362,10 +362,10 @@ end %Deal with tracks - if exist(options,'tracks'), + if exist(options,'tracks') %read tracks intrack=getfieldvalue(options,'tracks'); - if all(ischar(intrack)), + if all(ischar(intrack)) intrack=expread(intrack); else intrack=double(intrack); %for some reason, it is of class "single" @@ -377,7 +377,7 @@ track=[]; edges=[]; newcount=count; - for i=1:length(intrack), + for i=1:length(intrack) nods=size(intrack(i).x,1); newtrack=[intrack(i).x intrack(i).y]; newedges=[transpose(newcount+1:newcount+nods-1) transpose(newcount+2:newcount+nods) 3.*ones(nods-1,1)]; @@ -388,8 +388,8 @@ %calculate edge offset, accounting for broken tracks offsets=zeros(size(edgeflags,1)+1,3); - for j=2:size(offsets,1), - if edgeflags(j-1)==0, + for j=2:size(offsets,1) + if edgeflags(j-1)==0 offsets(j,:)=offsets(j-1,:)+[1 1 0]; else offsets(j,:)=offsets(j-1,:); @@ -417,7 +417,7 @@ end %Deal with vertices that need to be kept by mesher - if exist(options,'RequiredVertices'), + if exist(options,'RequiredVertices') %recover RequiredVertices requiredvertices=double(getfieldvalue(options,'RequiredVertices')); %for some reason, it is of class "single" @@ -437,25 +437,25 @@ end %Deal with RequiredEdges - if getfieldvalue(options,'NoBoundaryRefinement',0)==1, + if getfieldvalue(options,'NoBoundaryRefinement',0)==1 bamg_geometry.RequiredEdges=edges_required'; - elseif getfieldvalue(options,'NoBoundaryRefinementAllBoundaries',0)==1, + elseif getfieldvalue(options,'NoBoundaryRefinementAllBoundaries',0)==1 bamg_geometry.RequiredEdges=[1:size(bamg_geometry.Edges,1)]'; end %process geom %bamg_geometry=processgeometry(bamg_geometry,getfieldvalue(options,'tol',NaN),domain(1)); -elseif isstruct(md.private.bamg) & isfield(md.private.bamg,'geometry'), +elseif isstruct(md.private.bamg) & isfield(md.private.bamg,'geometry') bamg_geometry=bamggeom(md.private.bamg.geometry); else %do nothing... end %}}} % BAMG Mesh parameters {{{ -if (~exist(options,'domain') & md.mesh.numberofvertices~=0 & strcmp(elementtype(md.mesh),'Tria')), +if (~exist(options,'domain') & md.mesh.numberofvertices~=0 & strcmp(elementtype(md.mesh),'Tria')) - if isstruct(md.private.bamg) & isfield(md.private.bamg,'mesh'), + if isstruct(md.private.bamg) & isfield(md.private.bamg,'mesh') bamg_mesh=bamgmesh(md.private.bamg.mesh); else bamg_mesh.Vertices=[md.mesh.x md.mesh.y ones(md.mesh.numberofvertices,1)]; @@ -498,7 +498,7 @@ %call BAMG [bamgmesh_out bamggeom_out]=BamgMesher(bamg_mesh,bamg_geometry,bamg_options); -if getfieldvalue(options,'vertical',0), +if getfieldvalue(options,'vertical',0) md.mesh=mesh2dvertical(); md.mesh.x=bamgmesh_out.Vertices(:,1); md.mesh.y=bamgmesh_out.Vertices(:,2); @@ -514,7 +514,7 @@ md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1; -elseif getfieldvalue(options,'3dsurface',0), +elseif getfieldvalue(options,'3dsurface',0) md.mesh=mesh3dsurface(); md.mesh.x=bamgmesh_out.Vertices(:,1); @@ -567,7 +567,7 @@ %Deal with edges disp('Checking Edge crossing...'); i=0; -while (i1, + if length(els2)>1 %find the common vertices to the two elements connected to el1 (1 or 2) flag=intersect(md.mesh.elements(els2(1),:),md.mesh.elements(els2(2),:)); @@ -55,7 +55,7 @@ ord1=find(nods1(1)==md.mesh.elements(el1,:)); ord2=find(nods1(2)==md.mesh.elements(el1,:)); - if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ), + if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ) temp=segments(count,1); segments(count,1)=segments(count,2); segments(count,2)=temp; @@ -68,17 +68,17 @@ %find the vertex that 'el1' does not share with 'els2' flag=setdiff(nods1,md.mesh.elements(els2,:)); - for j=1:3, + for j=1:3 nods=nods1; nods(j)=[]; - if any(ismember(flag,nods)), + if any(ismember(flag,nods)) segments(count,:)=[nods el1]; %swap segment nodes if necessary ord1=find(nods(1)==md.mesh.elements(el1,:)); ord2=find(nods(2)==md.mesh.elements(el1,:)); - if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ), + if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ) temp=segments(count,1); segments(count,1)=segments(count,2); segments(count,2)=temp; diff --git a/src/m/mesh/labelconnectedregions.m b/src/m/mesh/labelconnectedregions.m index 3f1af673b..b2bafe8e0 100644 --- a/src/m/mesh/labelconnectedregions.m +++ b/src/m/mesh/labelconnectedregions.m @@ -4,7 +4,7 @@ % Usage: % labels = labelconnectedregions(md) -if size(md.mesh.elements,2)~=3, +if size(md.mesh.elements,2)~=3 error('not suppored yet (but easy to extend :)'); end diff --git a/src/m/mesh/loneedges.m b/src/m/mesh/loneedges.m index a4d46456e..c36aa16d8 100644 --- a/src/m/mesh/loneedges.m +++ b/src/m/mesh/loneedges.m @@ -2,9 +2,9 @@ edges=[]; - for e=1:md.mesh.numberofelements, - for j=1:3, - if j==3, + for e=1:md.mesh.numberofelements + for j=1:3 + if j==3 ind1=md.mesh.elements(e,3); ind2=md.mesh.elements(e,1); else @@ -16,7 +16,7 @@ els1=md.mesh.vertexconnectivity(ind1,1: md.mesh.vertexconnectivity(ind1,end)); els2=md.mesh.vertexconnectivity(ind2,1: md.mesh.vertexconnectivity(ind2,end)); els=intersect(els1,els2); - if length(els)~=2, + if length(els)~=2 edges=[edges;[ind1,ind2]]; end end diff --git a/src/m/mesh/mesh3dsurfaceplug2d.m b/src/m/mesh/mesh3dsurfaceplug2d.m index 079676248..a1cce9bbc 100644 --- a/src/m/mesh/mesh3dsurfaceplug2d.m +++ b/src/m/mesh/mesh3dsurfaceplug2d.m @@ -20,12 +20,12 @@ %The segments of md2 and the outer segments of md are identical. Go into the elements of %dmd2 and set them to their md equivalent: - for i=1:length(mh2.segments), + for i=1:length(mh2.segments) node2=mh2.segments(i,1); %this node2 has an equivalent on the segments of md: - for j=1:length(segments), + for j=1:length(segments) node1=segments(j,1); - if mh2.x(node2-mh.numberofvertices) == xsegs(j) && mh2.y(node2-mh.numberofvertices) == ysegs(j), + if mh2.x(node2-mh.numberofvertices) == xsegs(j) && mh2.y(node2-mh.numberofvertices) == ysegs(j) %go into the mesh of md2, and replace by node1. pos=find(mh2.elements==node2); mh2.elements(pos)=node1; segs=mh2.segments(:,1:2); pos=find(segs==node2); segs(pos)=node1; mh2.segments(:,1:2)=segs; @@ -46,7 +46,7 @@ lat=mh.lat; long=mh.long; elements=mh.elements; segments=mh.segments; orphan=find(~ismember([1:length(lat)],sort(unique(elements(:))))); - for i=1:length(orphan), + for i=1:length(orphan) %disp('WARNING: removing orphans'); %get rid of the orphan node i %update lat and long diff --git a/src/m/mesh/meshband.m b/src/m/mesh/meshband.m index e100862c7..7bb98f3f0 100644 --- a/src/m/mesh/meshband.m +++ b/src/m/mesh/meshband.m @@ -19,24 +19,24 @@ %create domain outine from inner and outer domain inner=expread([temproot '/innerdomain.exp']); - if inner.closed==0, + if inner.closed==0 inner.nods=inner.nods+1; inner.x(end+1)=inner.x(1); inner.y(end+1)=inner.y(1); inner.closed=1; - if getfieldvalue(options,'invert',0), + if getfieldvalue(options,'invert',0) inner.x=flipud(inner.x); inner.y=flipud(inner.y); end end [path,name,ext]=fileparts(outerdomain); - if strcmpi(ext,'.shp'), + if strcmpi(ext,'.shp') outer=shpread(outerdomain); else outer=expread(outerdomain); end - if outer.closed==0, + if outer.closed==0 outer.nods=outer.nods+1; outer.x(end+1)=outer.x(1); outer.y(end+1)=outer.y(1); @@ -59,7 +59,7 @@ expwrite(domain,[temproot '/Band.exp']); - if getfieldvalue(options,'plot',0), + if getfieldvalue(options,'plot',0) figure(1),clf,hold on,axis image; expdisp([temproot '/Band.exp'],'linestyle','k-*'); end @@ -67,18 +67,18 @@ %mesh: md=bamg(model(),'domain',[temproot '/Band.exp'],'MaxCornerAngle',1e-15,'gradation',10000); band=md.mesh; clear md; - if getfieldvalue(options,'plot',0), + if getfieldvalue(options,'plot',0) figure(2),clf,trisurf(band.elements,band.x,band.y,band.x),view(2),shading faceted; hold on,expdisp([temproot '/Band.exp'],'linestyle','k-*'); end %check that the domain vertices = the number of segments: - if abs(length(band.segments) - (length(domain(1).x)+length(domain(2).x)-2))>=2, + if abs(length(band.segments) - (length(domain(1).x)+length(domain(2).x)-2))>=2 disp(sprintf('band mesh not consistent: %i!=%i+%i\n',length(band.segments), length(domain(1).x), length(domain(2).x))); figure(3),clf,expdisp([temproot '/Band.exp'],'linestyle','r*'); hold on; - for i=1:length(band.segments), + for i=1:length(band.segments) i1=band.segments(i,1); i2=band.segments(i,2); plot([band.x(i1) band.x(i2)],[band.y(i1) band.y(i2)],'k*-'); plot([band.x(i1)+ band.x(i2)]/2,[band.y(i1)+ band.y(i2)]/2,'g*'); diff --git a/src/m/mesh/meshconvert.m b/src/m/mesh/meshconvert.m index e5d78ba5b..c0a4ec2d4 100644 --- a/src/m/mesh/meshconvert.m +++ b/src/m/mesh/meshconvert.m @@ -5,12 +5,12 @@ % md=meshconvert(md); % md=meshconvert(md,index,x,y); -if nargin~=1 & nargin~=4, +if nargin~=1 & nargin~=4 help meshconvert error('meshconvert error message: bad usage'); end -if nargin==1, +if nargin==1 index = md.mesh.elements; x = md.mesh.x; y = md.mesh.y; diff --git a/src/m/mesh/meshintersect.m b/src/m/mesh/meshintersect.m index a6dfaa952..c919fd14f 100644 --- a/src/m/mesh/meshintersect.m +++ b/src/m/mesh/meshintersect.m @@ -16,18 +16,18 @@ %go through lats,longs and find within tolerance, the index of the corresponding value in lat,long: indices=zeros(length(lats),1); - for i=1:length(lats), + for i=1:length(lats) distance=sqrt((lat-lats(i)).^2+(long-longs(i)).^2); s=find(distance1, + if length(s)>1 indices(i)=s(1); format long [lats(i) longs(i)] - for j=1:length(s), + for j=1:length(s) [lat(s(j)) long(s(j))] end error('one or more vertices on the global mesh were duplicated!'); - elseif isempty(s), + elseif isempty(s) plot(distance) min(distance) error('could not find vertices in common, relax tolerance?'); diff --git a/src/m/mesh/meshintersect2d.m b/src/m/mesh/meshintersect2d.m index 9fa535d27..cfd987db3 100644 --- a/src/m/mesh/meshintersect2d.m +++ b/src/m/mesh/meshintersect2d.m @@ -15,21 +15,21 @@ %go through lats,longs and find within tolerance, the index of the corresponding value in lat,long: indices=zeros(length(xs),1); - for i=1:length(xs), + for i=1:length(xs) tolerance=0; distance=sqrt((x-xs(i)).^2+(y-ys(i)).^2); s=find(distance==0); - if ~isempty(s), - if length(s)>1, + if ~isempty(s) + if length(s)>1 %we have two vertices that are coincident! Not good. - for j=1:length(s), + for j=1:length(s) hold on;plot(x(s(j)),y(s(j)),'c.','MarkerSize',40) end disp(['Vertex ' num2str(i) ' of input mesh coincides with the following output mesh vertices ']); s - if force, + if force indices(i)=s(1); else error(''); @@ -41,8 +41,8 @@ %we could not find a 0 distance, find the lowest tolerance that generates a find: count=1; - while isempty(s), - if count>1000, + while isempty(s) + if count>1000 disp(['could not find a vertex matching vertex ' num2str(i) ' of input mesh!']); disp('Might think about changing tolerance increment'); error(''); @@ -51,7 +51,7 @@ s=find(distancemaxtol, + if tolerance>maxtol disp(['found matching vertices ' num2str(s) ' in output mesh for input mesh vertex ' num2str(i) ]); disp(' however, these vertices are farther that the max tolerance allowed!'); error(''); diff --git a/src/m/mesh/meshintersect3d.m b/src/m/mesh/meshintersect3d.m index 0fd8fa208..0371a8c57 100644 --- a/src/m/mesh/meshintersect3d.m +++ b/src/m/mesh/meshintersect3d.m @@ -16,21 +16,21 @@ %go through lats,longs and find within tolerance, the index of the corresponding value in lat,long: indices=zeros(length(xs),1); - for i=1:length(xs), + for i=1:length(xs) tolerance=0; distance=sqrt((x-xs(i)).^2+(y-ys(i)).^2+(z-zs(i)).^2); s=find(distance==0); - if ~isempty(s), - if length(s)>1, + if ~isempty(s) + if length(s)>1 %we have two vertices that are coincident! Not good. - for j=1:length(s), + for j=1:length(s) hold on;plot3(x(s(j)),y(s(j)),z(s(j)),'c.','MarkerSize',40) end disp(['Vertex ' num2str(i) ' of input mesh coincides with the following output mesh vertices ']); s - if force, + if force indices(i)=s(1); else error(''); @@ -42,8 +42,8 @@ %we could not find a 0 distance, find the lowest tolerance that generates a find: count=1; - while isempty(s), - if count>1000, + while isempty(s) + if count>1000 disp(['could not find a vertex matching vertex ' num2str(i) ' of input mesh!']); disp('Might think about changing tolerance increment'); error(''); @@ -52,7 +52,7 @@ s=find(distancemaxtol, + if tolerance>maxtol disp(['found matching vertices ' num2str(s) ' in output mesh for input mesh vertex ' num2str(i) ]); disp(' however, these vertices are farther that the max tolerance allowed!'); error(''); diff --git a/src/m/mesh/modelmerge2d.m b/src/m/mesh/modelmerge2d.m index 101827797..810b809fc 100755 --- a/src/m/mesh/modelmerge2d.m +++ b/src/m/mesh/modelmerge2d.m @@ -33,11 +33,11 @@ %go into the vertices on boundary of mesh 1, and figure out which ones are common to mesh2: verticesonboundary=find(md1.mesh.vertexonboundary); - for i=1:length(verticesonboundary), + for i=1:length(verticesonboundary) node1=verticesonboundary(i); xnode1=x1(node1); ynode1=y1(node1); %is there another node with these coordinates in mesh2? ind=find(sqrt(((x2-xnode1).^2+(y2-ynode1).^2))(i+nods1)); elements2(pos)=elements2(pos)-1; x2(i)=[]; @@ -82,7 +82,7 @@ md.mesh.vertexonboundary=zeros(md.mesh.numberofvertices,1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1; - if getfieldvalue(options,'full',0), + if getfieldvalue(options,'full',0) %we are asked to merge the classes fields too. We need have vertex and element mappings first: %vertex intersections: md.mesh.extractedvertices={meshintersect(x,y,md1.mesh.x,md1.mesh.y,'tolerance',1e-5), meshintersect(x,y,md2.mesh.x,md2.mesh.y,'tolerance',1e-5)}; @@ -96,7 +96,7 @@ md=transfer_fields(md,md1,md2,'geometry',{'thickness','surface','bed','base'}); md=transfer_fields(md,md1,md2,'mask',{'ocean_levelset','ice_levelset','ocean_levelset','land_levelset','glacier_levelset'}); md=transfer_fields(md,md1,md2,'smb',{'mass_balance'}); - if strcmpi(class(md1.basalforcings),'linearbasalforcings'), + if strcmpi(class(md1.basalforcings),'linearbasalforcings') md=transfer_fields(md,md1,md2,'basalforcings',{'groundedice_melting_rate','geothermalflux'}); else md=transfer_fields(md,md1,md2,'basalforcings',{'groundedice_melting_rate','deepwater_melting_rate','deepwater_elevation','upperwater_elevation','geothermalflux'}); @@ -123,10 +123,10 @@ %identify corners between both basins ends=[]; - for i=1:length(pos), + for i=1:length(pos) v=pos(i); [indi,indj]=find(md.mesh.elements==v); conn=unique(md.mesh.elements(indi,:)); - if (sum(boundary(conn))==2), + if (sum(boundary(conn))==2) ends(end+1)=v; end end @@ -137,7 +137,7 @@ %some checks: - if max(md.mesh.elements)>md.mesh.numberofvertices, + if max(md.mesh.elements)>md.mesh.numberofvertices error('issue in modelmerge, one of the element ids is > number of vertices!'); end @@ -145,7 +145,7 @@ function prop=transfer_vertices(md,md1,md2,field1,field2) % {{{ f1=getfield(md1,field1); f2=getfield(f1,field2); - if length(f2)==md1.mesh.numberofvertices, + if length(f2)==md1.mesh.numberofvertices prop=zeros(md.mesh.numberofvertices,1); prop(md.mesh.extractedvertices{1})=f2; f1=getfield(md2,field1); f2=getfield(f1,field2); prop(md.mesh.extractedvertices{2})=f2; @@ -166,9 +166,9 @@ end %end of function %}}} function md=transfer_fields(md,md1,md2,classname,classfields) % {{{ - for i=1:length(classfields), + for i=1:length(classfields) field1=eval(['md1.' classname '.' classfields{i}]); - if length(field1)==md1.mesh.numberofvertices | length(field1)==md1.mesh.numberofvertices+1, + if length(field1)==md1.mesh.numberofvertices | length(field1)==md1.mesh.numberofvertices+1 eval(['md.' classname '.' classfields{i} '=transfer_vertices(md,md1,md2,''' classname ''',''' classfields{i} ''');']); else eval(['md.' classname '.' classfields{i} '=transfer_elements(md,md1,md2,''' classname ''',''' classfields{i} ''');']); diff --git a/src/m/mesh/modelmerge3d.m b/src/m/mesh/modelmerge3d.m index 953631eaf..d29d6514e 100755 --- a/src/m/mesh/modelmerge3d.m +++ b/src/m/mesh/modelmerge3d.m @@ -36,7 +36,7 @@ %go into the vertices on boundary of mesh 1 and figure out which ones are common with mesh2: verticesonboundary=find(md1.mesh.vertexonboundary); - for i=1:length(verticesonboundary), + for i=1:length(verticesonboundary) node1=verticesonboundary(i); xnode1=x1(node1); ynode1=y1(node1); @@ -44,10 +44,10 @@ %is there another node with these coordinates in mesh 2? ind=find(sqrt((x2-xnode1).^2+(y2-ynode1).^2+(z2-znode1).^2)1, + if length(ind)>1 disp('should reduce the tolerance, several vertices picked up!'); end - if ~isempty(ind), + if ~isempty(ind) x2(ind)=NaN; y2(ind)=NaN; z2(ind)=NaN; @@ -98,6 +98,6 @@ md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1; %some checks: - if max(md.mesh.elements)>md.mesh.numberofvertices, + if max(md.mesh.elements)>md.mesh.numberofvertices error('issue in modelmerge, one of the element ids is > number of vertices!'); end diff --git a/src/m/mesh/patchglobe.m b/src/m/mesh/patchglobe.m index a799240f0..7dbac1d68 100644 --- a/src/m/mesh/patchglobe.m +++ b/src/m/mesh/patchglobe.m @@ -76,7 +76,7 @@ mhb=mdb.mesh; clear mdb; %double check: - if length(mhb.segments) ~= (length(dom(1).x)+length(env(1).x)-2), + if length(mhb.segments) ~= (length(dom(1).x)+length(env(1).x)-2) error('band mesh not consistent'); end diff --git a/src/m/mesh/planet/gmshplanet.m b/src/m/mesh/planet/gmshplanet.m index 4876b5c93..ed05ab4cf 100644 --- a/src/m/mesh/planet/gmshplanet.m +++ b/src/m/mesh/planet/gmshplanet.m @@ -16,10 +16,10 @@ %Get Gmsh version [s,r]=system(['gmsh -info | grep ''Version'' | sed -e ''s/Version[[:blank:]]*:[[:blank:]]//'' | cut -d ''.'' -f1']); - if contains(r, 'dyld'), + if contains(r, 'dyld') error(['gmshplanet: ' r]); end - if s~=0, + if s~=0 %gmsh executable may not be on path; attempt to find it paths={ @@ -32,25 +32,25 @@ }; gmshpath=''; for i=paths - if exist([i{1} '/gmsh'],'file'), + if exist([i{1} '/gmsh'],'file') gmshpath = i{1}; break; end end - if isempty(gmshpath), + if isempty(gmshpath) error('gmshplanet: gmsh executable not found!'); end setenv('PATH', [gmshpath ':' getenv('PATH')]); %Get Gmsh version [s,r]=system(['gmsh -info | grep ''Version'' | sed -e ''s/Version[[:blank:]]*:[[:blank:]]//'' | cut -d ''.'' -f1']); - if contains(r, 'dyld'), + if contains(r, 'dyld') error(['gmshplanet: ' r]); end end gmshmajorversion=str2num(r); - if ~ismember([3,4],gmshmajorversion), + if ~ismember([3,4],gmshmajorversion) error(['gmshplanet: Gmsh major version ' gmshmajorversion ' not supported!']); end @@ -79,10 +79,10 @@ fprintf(fid,'Mesh.Algorithm = 1;\n'); % MeshAdapt fprintf(fid,'Mesh.MshFileVersion = 2;\n'); fprintf(fid,'Mesh.RandomFactor = 1e-10;\n'); - if exist(options,'refine'), + if exist(options,'refine') fprintf(fid,'Mesh.Algorithm = 7;\n'); % BAMG fprintf(fid,'Mesh.CharacteristicLengthFromPoints = 0;\n'); - if gmshmajorversion == 3, + if gmshmajorversion == 3 fprintf(fid,'Mesh.RemeshAlgorithm = 1;\n'); end end @@ -108,9 +108,9 @@ fprintf(fid,'Circle(11) = {4,1,6};\n'); fprintf(fid,'Circle(12) = {6,1,2};\n'); - if gmshmajorversion == 3, + if gmshmajorversion == 3 curvename='Line Loop'; - elseif gmshmajorversion == 4, + elseif gmshmajorversion == 4 curvename='Curve Loop'; end @@ -137,7 +137,7 @@ fclose(fid); %}}} - if exist(options,'refine'), + if exist(options,'refine') meshini=getfieldvalue(options,'refine'); metric=getfieldvalue(options,'refinemetric'); @@ -145,7 +145,7 @@ fid=fopen('sphere.pos','w'); fprintf(fid,'View "background mesh" {\n'); - for i=1:meshini.numberofelements, + for i=1:meshini.numberofelements fprintf(fid,'ST(%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g};\n',... meshini.x(meshini.elements(i,1)), meshini.y(meshini.elements(i,1)), meshini.z(meshini.elements(i,1)),... meshini.x(meshini.elements(i,2)), meshini.y(meshini.elements(i,2)), meshini.z(meshini.elements(i,2)),... @@ -165,7 +165,7 @@ % modifying our parsing scheme for Gmsh 4, for now, we simply set the % "-format" option. % - if exist(options,'refine'), + if exist(options,'refine') system(['gmsh -2 sphere.geo -bgm sphere.pos']); else system(['gmsh -2 sphere.geo']); @@ -176,19 +176,19 @@ %Get Mesh format A=fscanf(fid,'%s',1); - if ~strcmp(A,'$MeshFormat'), + if ~strcmp(A,'$MeshFormat') error(['Expecting $MeshFormat (' A ')']); end A=fscanf(fid,'%f %i %i',[1 3]); A=fscanf(fid,'%s',1); - if ~strcmp(A,'$EndMeshFormat'), + if ~strcmp(A,'$EndMeshFormat') error(['Expecting $EndMeshFormat (' A ')']); end %Nodes A=fscanf(fid,'%s',1); - if ~strcmp(A,'$Nodes'), + if ~strcmp(A,'$Nodes') error(['Expecting $Nodes (' A ')']); end @@ -199,20 +199,20 @@ mesh.z = A(4,:)'; A=fscanf(fid,'%s',1); - if ~strcmp(A,'$EndNodes'), + if ~strcmp(A,'$EndNodes') error(['Expecting $EndNodes (' A ')']); end %Elements A=fscanf(fid,'%s',1); - if ~strcmp(A,'$Elements'), + if ~strcmp(A,'$Elements') error(['Expecting $Elements (' A ')']); end mesh.numberofelements=fscanf(fid,'%i',1); A=fscanf(fid,'%i %i %i %i %i %i %i %i',[8 mesh.numberofelements]); mesh.elements=A(6:8,:)'; A=fscanf(fid,'%s',1); - if ~strcmp(A,'$EndElements'), + if ~strcmp(A,'$EndElements') error(['Expecting $EndElements (' A ')']); end fclose(fid); diff --git a/src/m/mesh/planet/mesh_refine_tri4.m b/src/m/mesh/planet/mesh_refine_tri4.m index 4f5c6dc93..909455473 100644 --- a/src/m/mesh/planet/mesh_refine_tri4.m +++ b/src/m/mesh/planet/mesh_refine_tri4.m @@ -76,7 +76,7 @@ V2 = zeros(Nface*3,3); F2 = zeros(Nface*4,3); -for f = 1:Nface, +for f = 1:Nface % Get the triangle vertex indices NA = FV.faces(f,1); @@ -128,8 +128,8 @@ Vexist = find( FV.vertices(:,1) == Va(:,1) & ... FV.vertices(:,2) == Va(:,2) & ... FV.vertices(:,3) == Va(:,3) ); - if Vexist, - if size(Vexist) == [1,1], + if Vexist + if size(Vexist) == [1,1] N = Vexist; else, msg = sprintf('replicated vertices'); diff --git a/src/m/mesh/planet/sphere_project.m b/src/m/mesh/planet/sphere_project.m index ef5b44488..a5af853b4 100644 --- a/src/m/mesh/planet/sphere_project.m +++ b/src/m/mesh/planet/sphere_project.m @@ -22,7 +22,7 @@ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -if ~exist('v','var'), +if ~exist('v','var') msg = sprintf('SPHERE_PROJECT: No input vertices (X,Y,Z)\n'); error(msg); end @@ -31,7 +31,7 @@ Y = v(:,2); Z = v(:,3); -if ~exist('c','var'), +if ~exist('c','var') xo = 0; yo = 0; zo = 0; diff --git a/src/m/mesh/planet/sphere_tri.m b/src/m/mesh/planet/sphere_tri.m index 3772fa6e4..c8036751c 100644 --- a/src/m/mesh/planet/sphere_tri.m +++ b/src/m/mesh/planet/sphere_tri.m @@ -58,22 +58,22 @@ eegversion = '$Revision: 1.2 $'; fprintf('SPHERE_TRI [v %s]\n',eegversion(11:15)); tic -if ~exist('shape','var') || isempty(shape), +if ~exist('shape','var') || isempty(shape) shape = 'ico'; end fprintf('...creating sphere tesselation based on %s\n',shape); % default maximum subdivision level -if ~exist('maxlevel','var') || isempty(maxlevel) || maxlevel < 0, +if ~exist('maxlevel','var') || isempty(maxlevel) || maxlevel < 0 maxlevel = 0; end % default radius -if ~exist('r','var') || isempty(r), +if ~exist('r','var') || isempty(r) r = 1; end -if ~exist('winding','var') || isempty(winding), +if ~exist('winding','var') || isempty(winding) winding = 0; end @@ -172,10 +172,10 @@ % ----------------- % refine the starting shapes with subdivisions -if maxlevel, +if maxlevel % Subdivide each starting triangle (maxlevel) times - for level = 1:maxlevel, + for level = 1:maxlevel % Subdivide each triangle and normalize the new points thus % generated to lie on the surface of a sphere radius r. @@ -188,7 +188,7 @@ end end -if winding, +if winding fprintf('...returning counterclockwise vertex order (viewed from outside)\n'); FV.faces = FV.faces(:,[1 3 2]); else diff --git a/src/m/mesh/rifts/meshaddrifts.m b/src/m/mesh/rifts/meshaddrifts.m index 631178836..5a45ef90d 100644 --- a/src/m/mesh/rifts/meshaddrifts.m +++ b/src/m/mesh/rifts/meshaddrifts.m @@ -17,7 +17,7 @@ rifts=domains(2:2:end); %now loop over rifts: -for rift_i=1:length(rifts), +for rift_i=1:length(rifts) %refine rift to desired resolution: contour=contours(rift_i); @@ -35,7 +35,7 @@ %create domain of md2 model: md2.mesh.segments=contourenvelope(md2.mesh,'Meshaddrifts.Contour.exp'); domain_index=md2.mesh.segments(1,1:2); - while (domain_index(end)~=domain_index(1)), + while (domain_index(end)~=domain_index(1)) pos=find(md2.mesh.segments(:,1)==domain_index(end)); domain_index(end+1)=md2.mesh.segments(pos,2); end @@ -60,11 +60,11 @@ %update md2 rifts using elconv and nodeconv, and plug them into md: md2.rifts=updateriftindexing(md2.rifts,elconv2,nodeconv2); - for i=1:md.rifts.numrifts, + for i=1:md.rifts.numrifts md.rifts.riftstruct(i)=updateriftindexing(md.rifts.riftstruct(i),elconv,nodeconv); end - if md.rifts.numrifts==0, + if md.rifts.numrifts==0 md.rifts.riftstruct=md2.rifts; md.rifts.numrifts=1; else diff --git a/src/m/mesh/rifts/meshplug.m b/src/m/mesh/rifts/meshplug.m index c07333e54..47bf34d14 100644 --- a/src/m/mesh/rifts/meshplug.m +++ b/src/m/mesh/rifts/meshplug.m @@ -36,13 +36,13 @@ y2(1:length(domain))=NaN; %redirect border nodes in elements2 to elements -for i=1:length(domain), +for i=1:length(domain) pos=find(elements2==(i+length(x))); elements2(pos)=extractednodes(domain(i)); end %same deal for nodeconv2: -for i=1:length(domain), +for i=1:length(domain) nodeconv2(i)=extractednodes(domain(i)); end @@ -55,7 +55,7 @@ z=[z; z2]; %now, get rid of NaN in x: -while ~isempty(find(isnan(x))), +while ~isempty(find(isnan(x))) pos=find(isnan(x)); node=pos(1); diff --git a/src/m/mesh/rifts/meshprocessoutsiderifts.m b/src/m/mesh/rifts/meshprocessoutsiderifts.m index 099a9e14c..a60b47f66 100644 --- a/src/m/mesh/rifts/meshprocessoutsiderifts.m +++ b/src/m/mesh/rifts/meshprocessoutsiderifts.m @@ -6,7 +6,7 @@ % %go through rifts, and figure out which ones touch the domain outline -for i=1:length(md.rifts.riftstruct), +for i=1:length(md.rifts.riftstruct) %first, flag nodes that belong to the domain outline flags=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,domainoutline,'node',0); @@ -16,13 +16,13 @@ outsidetips=tips(find(flags(rift.tips)==0)); %we have found outsidetips, tips that touch the domain outline. go through them - for j=1:length(outsidetips), + for j=1:length(outsidetips) tip=outsidetips(j); %find tip in the segments, take first segment (there should be 2) that holds tip, %and node_connected_to_tip is the other node on this segment: tipindex=find(rift.segments(:,1)==tip); - if length(tipindex), + if length(tipindex) tipindex=tipindex(1); node_connected_to_tip=rift.segments(tipindex,2); else @@ -66,11 +66,11 @@ %deal with segments tipsegments=find((md.mesh.segments(:,1)==tip) | (md.mesh.segments(:,2)==tip)); - for k=1:length(tipsegments), + for k=1:length(tipsegments) segment_index=tipsegments(k); pos=find(md.mesh.segments(segment_index,1:2)~=tip); other_node=md.mesh.segments(segment_index,pos); - if ~isconnected(md.mesh.elements,other_node,tip), + if ~isconnected(md.mesh.elements,other_node,tip) pos=find(md.mesh.segments(segment_index,1:2)==tip); md.mesh.segments(segment_index,pos)=num; end @@ -92,7 +92,7 @@ % elements=ElementsFromEdge(elements,A,B); - if isempty(elements), + if isempty(elements) flag=0; else flag=1; diff --git a/src/m/mesh/rifts/meshprocessrifts.m b/src/m/mesh/rifts/meshprocessrifts.m index 8c958e8be..3298dc43b 100644 --- a/src/m/mesh/rifts/meshprocessrifts.m +++ b/src/m/mesh/rifts/meshprocessrifts.m @@ -13,19 +13,19 @@ % %some checks on arguments: -if nargout~=1, +if nargout~=1 help meshprocessrifts error('meshprocessrifts usage error:'); end -if nargin~=2, +if nargin~=2 help meshprocessrifts error('meshprocessrifts usage error:'); end %Call MEX file [md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers,md.rifts.riftstruct]=ProcessRifts(md.mesh.elements,md.mesh.x,md.mesh.y,md.mesh.segments,md.mesh.segmentmarkers); -if ~isstruct(md.rifts.riftstruct), +if ~isstruct(md.rifts.riftstruct) error('ProcessRifts did not find any rift'); end @@ -36,7 +36,7 @@ md.mesh.vertexonboundary=zeros(length(md.mesh.x),1); md.mesh.vertexonboundary(md.mesh.segments(:,1:2))=1; %get coordinates of rift tips -for i=1:numrifts, +for i=1:numrifts md.rifts.riftstruct(i).tip1coordinates=[md.mesh.x(md.rifts.riftstruct(i).tips(1)) md.mesh.y(md.rifts.riftstruct(i).tips(1))]; md.rifts.riftstruct(i).tip2coordinates=[md.mesh.x(md.rifts.riftstruct(i).tips(2)) md.mesh.y(md.rifts.riftstruct(i).tips(2))]; end @@ -44,17 +44,17 @@ %In case we have rifts that open up the domain outline, we need to open them: flags=ContourToMesh(md.mesh.elements,md.mesh.x,md.mesh.y,domainoutline,'node',0); found=0; -for i=1:numrifts, - if flags(md.rifts.riftstruct(i).tips(1))==0, +for i=1:numrifts + if flags(md.rifts.riftstruct(i).tips(1))==0 found=1; break; end - if flags(md.rifts.riftstruct(i).tips(2))==0, + if flags(md.rifts.riftstruct(i).tips(2))==0 found=1; break; end end -if found, +if found md=meshprocessoutsiderifts(md,domainoutline); end @@ -64,6 +64,6 @@ md.mesh.elements(pos,:)=[md.mesh.elements(pos,2) md.mesh.elements(pos,1) md.mesh.elements(pos,3)]; %case of 3D surface mesh: -if strcmpi(class(md.mesh),'mesh3dsurface'), +if strcmpi(class(md.mesh),'mesh3dsurface') md.mesh.z=md.mesh.x; md.mesh.z(:)=0; end diff --git a/src/m/mesh/rifts/meshyamsrecreateriftsegments.m b/src/m/mesh/rifts/meshyamsrecreateriftsegments.m index 4810b7f22..43a4ce2a5 100644 --- a/src/m/mesh/rifts/meshyamsrecreateriftsegments.m +++ b/src/m/mesh/rifts/meshyamsrecreateriftsegments.m @@ -2,12 +2,12 @@ %recreate rift segments: just used for yams. temporaroy routine. pos_record=[]; - if md.rifts.numrifts, - for i=1:md.rifts.numrifts, + if md.rifts.numrifts + for i=1:md.rifts.numrifts rift=md.rifts.riftstruct(i); %closed rifts first: - if length(rift.tips)==2, + if length(rift.tips)==2 %find tip1 and tip2 for this rift, in the new mesh created by yams. pos=find_point(md.mesh.x(md.mesh.segments(:,1)),md.mesh.y(md.mesh.segments(:,1)),rift.tip1coordinates(1),rift.tip1coordinates(2)); @@ -19,13 +19,13 @@ pos=find_point(md.mesh.x(md.mesh.segments(:,1)),md.mesh.y(md.mesh.segments(:,1)),rift.tip1coordinates(1),rift.tip1coordinates(2)); pos_record=[pos_record; pos]; riftsegs=md.mesh.segments(pos,:); - while 1, + while 1 A=riftsegs(end,1); B=riftsegs(end,2); el=riftsegs(end,3); %find other segment that holds B. pos=find(md.mesh.segments(:,1)==B); pos_record=[pos_record; pos]; riftsegs=[riftsegs; md.mesh.segments(pos,:)]; - if riftsegs(end,2)==tip1, + if riftsegs(end,2)==tip1 break; end end @@ -42,7 +42,7 @@ tip1=md.mesh.segments(pos1,1); pos2=find_point(md.mesh.x(md.mesh.segments(:,1)),md.mesh.y(md.mesh.segments(:,1)),rift.tip2coordinates(1),rift.tip2coordinates(2)); tip2=md.mesh.segments(pos2,1); - if length(tip1)==2, + if length(tip1)==2 %swap. temp=tip1; tip1=tip2; tip2=temp; temp=pos1; pos1=pos2; pos2=temp; @@ -53,13 +53,13 @@ pos_record=[pos_record; pos]; riftsegs=md.mesh.segments(pos,:); - while 1, + while 1 A=riftsegs(end,1); B=riftsegs(end,2); el=riftsegs(end,3); %find other segment that holds B. pos=find(md.mesh.segments(:,1)==B); pos_record=[pos_record; pos]; riftsegs=[riftsegs; md.mesh.segments(pos,:)]; - if ((riftsegs(end,2)==tip2(1)) | (riftsegs(end,2)==tip2(2))), + if ((riftsegs(end,2)==tip2(1)) | (riftsegs(end,2)==tip2(2))) %figure out which tip we reached if riftsegs(end,2)==tip2(1), index=2; else index=1; end break; @@ -70,13 +70,13 @@ pos=pos2(index); pos_record=[pos_record; pos]; riftsegs=[riftsegs; md.mesh.segments(pos,:)]; - while 1, + while 1 A=riftsegs(end,1); B=riftsegs(end,2); el=riftsegs(end,3); %find other segment that holds B. pos=find(md.mesh.segments(:,1)==B); pos_record=[pos_record; pos]; riftsegs=[riftsegs; md.mesh.segments(pos,:)]; - if riftsegs(end,2)==tip1, + if riftsegs(end,2)==tip1 break; end end diff --git a/src/m/mesh/rifts/rifttipsonmesh.m b/src/m/mesh/rifts/rifttipsonmesh.m index fa6296c75..6811c2220 100644 --- a/src/m/mesh/rifts/rifttipsonmesh.m +++ b/src/m/mesh/rifts/rifttipsonmesh.m @@ -4,9 +4,9 @@ %read rift file according to its extension: [path,name,ext]=fileparts(riftoutline); -if strcmp(ext,'.exp'), +if strcmp(ext,'.exp') rifts=expread(riftoutline); -elseif strcmp(ext,'.shp'), +elseif strcmp(ext,'.shp') rifts=shpread(riftoutline); else error(['bamg error message: file ' riftoutline ' format not supported (.shp or .exp)']); @@ -14,7 +14,7 @@ tips=[]; -for i=1:length(rifts), +for i=1:length(rifts) rift=rifts(i); x_tip=rift.x(1); diff --git a/src/m/mesh/rifts/rifttipsrefine.m b/src/m/mesh/rifts/rifttipsrefine.m index 1ebfe3809..1be7272ec 100644 --- a/src/m/mesh/rifts/rifttipsrefine.m +++ b/src/m/mesh/rifts/rifttipsrefine.m @@ -10,7 +10,7 @@ rifts=expread(filename); !echo -n "" > Circles.exp -for i=1:length(rifts), +for i=1:length(rifts) tip1=[rifts(i).x(1) rifts(i).y(1)]; tip2=[rifts(i).x(end) rifts(i).y(end)]; %create circle around tip diff --git a/src/m/mesh/triangle.m b/src/m/mesh/triangle.m index d2fbf6885..316619f64 100644 --- a/src/m/mesh/triangle.m +++ b/src/m/mesh/triangle.m @@ -16,17 +16,17 @@ %Figure out a characteristic area. Resolution is a node oriented concept (ex a 1000m resolution node would %be made of 1000*1000 area squares). -if (nargin==3), +if (nargin==3) resolution=varargin{1}; riftname=''; end -if (nargin==4), +if (nargin==4) riftname=varargin{1}; resolution=varargin{2}; end %Check that mesh was not already run, and warn user: -if md.mesh.numberofelements~=0, +if md.mesh.numberofelements~=0 choice=input('This model already has a mesh. Are you sure you want to go ahead? (y/n)','s'); if ~strcmp(choice,'y') disp('no meshing done ... exiting'); @@ -46,10 +46,10 @@ %check that all the created nodes belong to at least one element removeorphans=1; -if removeorphans, +if removeorphans uniqueelements=sort(unique(elements(:))); orphans=find(~ismember([1:length(x)],uniqueelements)); - for i=1:length(orphans), + for i=1:length(orphans) disp('WARNING: removing orphans'); %get rid of the orphan node i %update x and y diff --git a/src/m/mesh/triangle2dvertical.m b/src/m/mesh/triangle2dvertical.m index a97f2db5a..6e815d90e 100644 --- a/src/m/mesh/triangle2dvertical.m +++ b/src/m/mesh/triangle2dvertical.m @@ -13,7 +13,7 @@ % md=triangle(md,'DomainOutline.exp',1000); %Check that mesh was not already run, and warn user: -if md.mesh.numberofelements~=0, +if md.mesh.numberofelements~=0 choice=input('This model already has a mesh. Are you sure you want to go ahead? (y/n)','s'); if ~strcmp(choice,'y') disp('no meshing done ... exiting'); @@ -28,7 +28,7 @@ %check that all the created nodes belong to at least one element orphan=find(~ismember([1:length(x)],sort(unique(elements(:))))); -for i=1:length(orphan), +for i=1:length(orphan) disp('WARNING: removing orphans'); %get rid of the orphan node i %update x and y diff --git a/src/m/miscellaneous/alignsegments.m b/src/m/miscellaneous/alignsegments.m index 5c2742492..f66cd4da7 100644 --- a/src/m/miscellaneous/alignsegments.m +++ b/src/m/miscellaneous/alignsegments.m @@ -7,10 +7,10 @@ newsegments=zeros(nt,3); newsegments(1,:)=segments(1,:); - for i=2:nt, + for i=2:nt last=newsegments(i-1,2); %last vertex of the previous segment: - for j=1:nt, - if last==segments(j,1), + for j=1:nt + if last==segments(j,1) %we found the next segment: newsegments(i,:)=segments(j,:); break; diff --git a/src/m/miscellaneous/colinearity.m b/src/m/miscellaneous/colinearity.m index a3b048097..436c8bd00 100644 --- a/src/m/miscellaneous/colinearity.m +++ b/src/m/miscellaneous/colinearity.m @@ -1,7 +1,7 @@ function theta = colinearity(md) %load some variables (it is much faster if the variab;es are loaded from md once for all) -if ~strcmpi(meshtype(md.mesh),'3D'), +if ~strcmpi(meshtype(md.mesh),'3D') numberofelements=md.mesh.numberofelements; numberofnodes=md.mesh.numberofvertices; index=md.mesh.elements; diff --git a/src/m/miscellaneous/fielddisplay.m b/src/m/miscellaneous/fielddisplay.m index 1ea4c2af9..5b3ba9729 100644 --- a/src/m/miscellaneous/fielddisplay.m +++ b/src/m/miscellaneous/fielddisplay.m @@ -15,7 +15,7 @@ function fielddisplay(md,name,comment) function parsedisplay(offset,name,field,comment) % {{{ %string - if ischar(field), + if ischar(field) displayunit(offset,name,['''' field ''''],comment) @@ -23,7 +23,7 @@ function parsedisplay(offset,name,field,comment) % {{{ elseif isnumeric(field) %double - if numel(field)==1, + if numel(field)==1 displayunit(offset,name,num2str(field),comment) %matrix else @@ -43,7 +43,7 @@ function parsedisplay(offset,name,field,comment) % {{{ fieldsize=size(field); %single value - if max(fieldsize)==1, + if max(fieldsize)==1 if (field) displayunit(offset,name,'true',comment) else @@ -55,11 +55,11 @@ function parsedisplay(offset,name,field,comment) % {{{ end %structure - elseif isstruct(field), + elseif isstruct(field) struct_display(offset,name,field,comment) %cell - elseif iscell(field), + elseif iscell(field) cell_display(offset,name,field,comment) else @@ -76,7 +76,7 @@ function struct_display(offset,name,field,comment) % {{{ structure_fields=fieldnames(field); - for i=1:length(structure_fields), + for i=1:length(structure_fields) %get current field sfield=field.(structure_fields{i}); @@ -97,8 +97,8 @@ function cell_display(offset,name,field,comment) % {{{ %go through the cell and fill string if length(field)<5; - for i=1:length(field), - if ischar(field{i}), + for i=1:length(field) + if ischar(field{i}) string=[string '''' field{i} ''',']; elseif (isnumeric(field{i}) & length(field{i})==1) string=[string num2str(field{i}) ',' ]; @@ -108,7 +108,7 @@ function cell_display(offset,name,field,comment) % {{{ end end end - if strcmp(string,'{'), + if strcmp(string,'{') string=['(' num2str(size(field,1)) 'x' num2str(size(field,2)) ')']; else string=[string(1:end-1) '}']; @@ -120,15 +120,15 @@ function cell_display(offset,name,field,comment) % {{{ function displayunit(offset,name,characterization,comment)% {{{ %take care of name - if length(name)>23, + if length(name)>23 name=[name(1:20) '...']; end %take care of characterization - if (strcmp(characterization,['''' '''']) | strcmp(characterization,'NaN')), + if (strcmp(characterization,['''' '''']) | strcmp(characterization,'NaN')) characterization='N/A'; end - if length(characterization)>15, + if length(characterization)>15 characterization=[characterization(1:12) '...']; end @@ -136,11 +136,11 @@ function displayunit(offset,name,characterization,comment)% {{{ if isempty(comment) disp(sprintf('%s%-23s: %-15s',offset,name,characterization)); else - if ischar(comment), + if ischar(comment) disp(sprintf('%s%-23s: %-15s -- %s',offset,name,characterization,comment)); - elseif iscell(comment), + elseif iscell(comment) disp(sprintf('%s%-23s: %-15s -- %s',offset,name,characterization,comment{1})); - for i=2:length(comment), + for i=2:length(comment) disp(sprintf('%s%-23s %-15s %s',offset,'','',comment{i})); end else diff --git a/src/m/miscellaneous/isnans.m b/src/m/miscellaneous/isnans.m index 9d79418fd..4d120d476 100644 --- a/src/m/miscellaneous/isnans.m +++ b/src/m/miscellaneous/isnans.m @@ -5,7 +5,7 @@ % % See also : ISNAN -if isstruct(array), +if isstruct(array) returnvalue=0; elseif iscell(array) returnvalue=0; diff --git a/src/m/miscellaneous/netcdf2struct.m b/src/m/miscellaneous/netcdf2struct.m index f7f118a11..11faeea11 100644 --- a/src/m/miscellaneous/netcdf2struct.m +++ b/src/m/miscellaneous/netcdf2struct.m @@ -12,7 +12,7 @@ %All the variables are in VarArray field variables=data.VarArray; - for i=1:size(variables,2), + for i=1:size(variables,2) fieldname=deblank(variables(i).Str); fieldvalue=double(squeeze(variables(i).Data)); S.(fieldname)=fieldvalue; @@ -20,7 +20,7 @@ %All the variables are in AttArray field variables=data.AttArray; - for i=1:size(variables,2), + for i=1:size(variables,2) fieldname=deblank(variables(i).Str); fieldvalue=double(variables(i).Val); S.(fieldname)=fieldvalue; diff --git a/src/m/miscellaneous/parallelrange.m b/src/m/miscellaneous/parallelrange.m index 4ed0324b7..006543d34 100644 --- a/src/m/miscellaneous/parallelrange.m +++ b/src/m/miscellaneous/parallelrange.m @@ -6,7 +6,7 @@ num_local_rows=zeros(numprocs,1); -for i=1:numprocs, +for i=1:numprocs %we use floor. we under distribute rows. The rows left are then redistributed, therefore resulting in a more even distribution. num_local_rows(i)=floor(globalsize/numprocs); end @@ -14,7 +14,7 @@ %There may be some rows left. Distribute evenly. row_rest=globalsize - numprocs*floor(globalsize/numprocs); -for i=1:row_rest, +for i=1:row_rest num_local_rows(i)=num_local_rows(i)+1; end diff --git a/src/m/miscellaneous/round_ice.m b/src/m/miscellaneous/round_ice.m index 68223be64..42e521be7 100644 --- a/src/m/miscellaneous/round_ice.m +++ b/src/m/miscellaneous/round_ice.m @@ -7,7 +7,7 @@ % new_x=round_ice(x,numnonzeros) %some checks -if (nargin ~=2 | nargout>1), +if (nargin ~=2 | nargout>1) error('round_ice usage: new_x=round_ice(x,numonzeros)'); end if ~isnumeric(x) diff --git a/src/m/miscellaneous/structtoobj.m b/src/m/miscellaneous/structtoobj.m index 6e2053287..a4564f078 100644 --- a/src/m/miscellaneous/structtoobj.m +++ b/src/m/miscellaneous/structtoobj.m @@ -6,9 +6,9 @@ objprops =properties(class(obj)); %recover object properties - for i=1:length(structfields), + for i=1:length(structfields) fieldname=structfields{i}; - if ismember(fieldname,objprops), + if ismember(fieldname,objprops) fieldvalue=getfield(S,fieldname); obj=setfield(obj,fieldname,fieldvalue); end diff --git a/src/m/modeldata/interpArcticdem.m b/src/m/modeldata/interpArcticdem.m index 48bbc898c..0fa73f45a 100644 --- a/src/m/modeldata/interpArcticdem.m +++ b/src/m/modeldata/interpArcticdem.m @@ -10,7 +10,7 @@ end usemap = 0; -if license('test','map_toolbox')==0, +if license('test','map_toolbox')==0 disp('WARNING: map toolbox not installed, trying house code'); usemap = 0; elseif license('checkout','map_toolbox')==0 @@ -18,7 +18,7 @@ usemap = 0; end -if usemap, +if usemap [data,R] = geotiffread(path); data=double(flipud(data)); xdata=R.XLimWorld(1):R.DeltaX:R.XLimWorld(2); xdata=xdata(:); @@ -48,7 +48,7 @@ id1x=max(1,find(xdata>=xmin,1)-offset); id2x=min(numel(xdata),posx(end)+offset); - if 0, + if 0 ymin=min(Y(:)); ymax=max(Y(:)); posy=find(ydata<=ymax); id1y=max(1,find(ydata>=ymin,1)-offset); diff --git a/src/m/modeldata/interpBamber2013.m b/src/m/modeldata/interpBamber2013.m index a826a4e9c..1958cf65f 100644 --- a/src/m/modeldata/interpBamber2013.m +++ b/src/m/modeldata/interpBamber2013.m @@ -28,7 +28,7 @@ end verbose = 0; -if nargin==2, +if nargin==2 string = 'BedrockElevation'; end diff --git a/src/m/modeldata/interpBedmachineAntarctica.m b/src/m/modeldata/interpBedmachineAntarctica.m index 92dd3c2e6..28b545334 100644 --- a/src/m/modeldata/interpBedmachineAntarctica.m +++ b/src/m/modeldata/interpBedmachineAntarctica.m @@ -15,7 +15,7 @@ % Supported interpolation methos: 'linear','cubic','nearest' % - optional 5th input argument: path to dataset. % -% Version 11/30/2018 Mathieu Morlighem mmorligh@uci.edu +% Version 11/30/2018 Mathieu Morlighem mmorligh@dartmouth.edu if nargin<3, string = 'bed'; end if nargin<4 @@ -26,8 +26,10 @@ end end if nargin<5 + ncdate='2019-11-05'; %BedMachine v1 ncdate='2020-07-15'; %BedMachine v2 - ncdate='v3.5'; %Official v3 release + ncdate='v3.5'; %BedMachine v3 + ncdate='v4.1'; %BedMachine v4 end basename = 'BedMachineAntarctica'; @@ -76,7 +78,7 @@ id1y=max(1,find(ydata<=ymax,1)-offset); id2y=min(numel(ydata),posy(end)+offset); -if strcmp(string,'icemask'), +if strcmp(string,'icemask') disp([' -- BedMachine Antarctica: loading ' string]); %data = double(ncread(ncfile,'mask'))'; data = double(ncread(ncfile,'mask',[id1x id1y],[id2x-id1x+1 id2y-id1y+1],[1 1]))'; @@ -94,7 +96,7 @@ disp([' -- BedMachine Antarctica: interpolating ' string]); disp([' -- Interpolation method: ' method]); -if strcmp(string,'mask') | strcmp(string,'source'), +if strcmp(string,'mask') | strcmp(string,'source') %Need nearest neighbor to avoid interpolation between 0 and 2 output = InterpFromGrid(xdata,ydata,data,double(X),double(Y),'nearest'); %tic @@ -128,7 +130,7 @@ % Fill Zi with NaNs zi = NaN(size(xi)); - if strcmpi(method,'nearest'), + if strcmpi(method,'nearest') % Find the nearest point in index space rxi = round(xi)+1; ryi = round(yi)+1; % Find points that are in X,Y range diff --git a/src/m/modeldata/interpBedmachineGreenland.m b/src/m/modeldata/interpBedmachineGreenland.m index be7404e53..6210a7e81 100644 --- a/src/m/modeldata/interpBedmachineGreenland.m +++ b/src/m/modeldata/interpBedmachineGreenland.m @@ -15,17 +15,14 @@ % Supported interpolation methos: 'linear','cubic','nearest' % - optional 5th input argument: path to dataset. % -% Version 11/30/2018 Mathieu Morlighem mmorligh@uci.edu +% Version 11/30/2018 Mathieu Morlighem mmorligh@dartmouth.edu if nargin<5 - %ncdate='2015-04-27'; %BedMachine v2 + ncdate='2015-04-27'; %BedMachine v2 ncdate='2017-09-25'; %BedMachine v3 - ncdate='2020-04-14'; - ncdate='2021-08-27'; - ncdate='2022-03-17'; - ncdate='2022-05-18'; - ncdate='2022-07-28'; - ncdate='v6.6'; %BedMachine v6 + ncdate='2021-01-09'; %BedMachine v4 + ncdate='2022-07-28'; %BedMachine v5 + ncdate='v6.6'; %BedMachine v6 end if nargin<4 if strcmp(string,'mask') | strcmp(string,'source') @@ -90,7 +87,7 @@ disp([' -- BedMachine Greenland: interpolating ' string]); disp([' -- Interpolation method: ' method]); -if strcmp(string,'mask') | strcmp(string,'source'), +if strcmp(string,'mask') | strcmp(string,'source') %Need nearest neighbor to avoid interpolation between 0 and 2 output = InterpFromGrid(xdata,ydata,data,double(X),double(Y),'nearest'); else @@ -113,7 +110,7 @@ % Fill Zi with NaNs zi = NaN(size(xi)); - if strcmpi(method,'nearest'), + if strcmpi(method,'nearest') % Find the nearest point in index space rxi = round(xi)+1; ryi = round(yi)+1; % Find points that are in X,Y range diff --git a/src/m/modeldata/interpBedmap.m b/src/m/modeldata/interpBedmap.m index e0bf9e69a..279442e90 100644 --- a/src/m/modeldata/interpBedmap.m +++ b/src/m/modeldata/interpBedmap.m @@ -10,7 +10,7 @@ path=[jplsvn() '/proj-morlighem/DatasetAntarctica/Data/BedMap/gridded/']; -if strcmp(string,'bed'), +if strcmp(string,'bed') path = [path '/bed.mat']; load(path); x_m =(x_m(2:end)+x_m(1:end-1))/2.; diff --git a/src/m/modeldata/interpBedmap2.m b/src/m/modeldata/interpBedmap2.m index 0421497f7..67b57c5f8 100644 --- a/src/m/modeldata/interpBedmap2.m +++ b/src/m/modeldata/interpBedmap2.m @@ -50,11 +50,11 @@ xdata=xdata(id1x:id2x); ydata=ydata(id1y:id2y); - if ~strcmp(string,'coverage'), + if ~strcmp(string,'coverage') data(find(data==-9999))=NaN; end - if strcmpi(string,'icemask_grounded_and_shelves') | strcmpi(string,'rockmask'), + if strcmpi(string,'icemask_grounded_and_shelves') | strcmpi(string,'rockmask') output = InterpFromGrid(xdata,ydata,data,double(X),double(Y),'nearest'); else output = InterpFromGrid(xdata,ydata,data,double(X),double(Y)); % linear interpolation is default @@ -65,7 +65,7 @@ elseif exist('/Users/larour/ModelData/BedMap2/bedmap2_bin/','dir') % ================================ OLD =============================================== path='/Users/larour/ModelData/BedMap2/bedmap2_bin/' - if strcmp(string,'gl04c_geoid_to_wgs84'), + if strcmp(string,'gl04c_geoid_to_wgs84') filepath = [path '/gl04c_geiod_to_wgs84.flt']; else filepath = [path '/bedmap2_' string '.flt']; @@ -75,7 +75,7 @@ fclose(fid); % define grid - if strcmp(string,'thickness_uncertainty_5km'), + if strcmp(string,'thickness_uncertainty_5km') ncols =1361; nrows =1361; xll =-3401000; @@ -92,7 +92,7 @@ y_m=yll+(0:1:nrows-1)'*gridsize; %Change default to NaN - if ~strcmp(string,'coverage'), + if ~strcmp(string,'coverage') data(find(data==-9999))=NaN; end @@ -100,7 +100,7 @@ data = rot90(data); %Interpolate - if strcmpi(string,'icemask_grounded_and_shelves') | strcmpi(string,'rockmask'), + if strcmpi(string,'icemask_grounded_and_shelves') | strcmpi(string,'rockmask') dataout = InterpFromGrid(x_m,y_m,data,double(X),double(Y),'nearest'); else dataout = InterpFromGrid(x_m,y_m,data,double(X),double(Y)); diff --git a/src/m/modeldata/interpDTU19MDT.m b/src/m/modeldata/interpDTU19MDT.m index 53cd4c14a..dde950b2c 100644 --- a/src/m/modeldata/interpDTU19MDT.m +++ b/src/m/modeldata/interpDTU19MDT.m @@ -11,7 +11,7 @@ verbose = 1; -if hemisphere==+1, +if hemisphere==+1 if verbose, disp(' -- DTU19MDT: convert to lat/lon using Greenland projection'); end [LAT, LON ] = xy2ll(double(X(:)),double(Y(:)),+1,45,70); elseif hemisphere==-1; diff --git a/src/m/modeldata/interpDhdt.m b/src/m/modeldata/interpDhdt.m index 012c5713c..cb1c87941 100644 --- a/src/m/modeldata/interpDhdt.m +++ b/src/m/modeldata/interpDhdt.m @@ -34,7 +34,7 @@ id1x=max(1,find(xdata>=xmin,1)-offset); id2x=min(numel(xdata),posx(end)+offset); -if 0, +if 0 ymin=min(Y(:)); ymax=max(Y(:)); posy=find(ydata<=ymax); id1y=max(1,find(ydata>=ymin,1)-offset); diff --git a/src/m/modeldata/interpGeoid.m b/src/m/modeldata/interpGeoid.m index 42c17f666..2dc2d0408 100644 --- a/src/m/modeldata/interpGeoid.m +++ b/src/m/modeldata/interpGeoid.m @@ -10,13 +10,13 @@ end verbose = 1; -if nargin==3, +if nargin==3 hemisphere = varargin{1}; else hemisphere = +1; end -if hemisphere==+1, +if hemisphere==+1 if verbose, disp(' -- Geoid: convert to lat/lon using Greenland projection'); end [LAT, LON ] = xy2ll(double(X(:)),double(Y(:)),+1,45,70); else diff --git a/src/m/modeldata/interpGimpdem.m b/src/m/modeldata/interpGimpdem.m index 4b699cf35..71d8142ed 100644 --- a/src/m/modeldata/interpGimpdem.m +++ b/src/m/modeldata/interpGimpdem.m @@ -13,7 +13,7 @@ end usemap = 0; -if license('test','map_toolbox')==0, +if license('test','map_toolbox')==0 disp('WARNING: map toolbox not installed, trying house code'); usemap = 0; elseif license('checkout','map_toolbox')==0 @@ -21,7 +21,7 @@ usemap = 0; end -if usemap, +if usemap [data,R] = geotiffread(howatpath); data=double(flipud(data)); xdata=R.XLimWorld(1):R.DeltaX:R.XLimWorld(2); xdata=xdata(:); @@ -51,7 +51,7 @@ id1x=max(1,find(xdata>=xmin,1)-offset); id2x=min(numel(xdata),posx(end)+offset); - if 0, + if 0 ymin=min(Y(:)); ymax=max(Y(:)); posy=find(ydata<=ymax); id1y=max(1,find(ydata>=ymin,1)-offset); diff --git a/src/m/modeldata/interpGimpicemask.m b/src/m/modeldata/interpGimpicemask.m index f43dd075e..7af0bf9f5 100644 --- a/src/m/modeldata/interpGimpicemask.m +++ b/src/m/modeldata/interpGimpicemask.m @@ -10,7 +10,7 @@ end usemap = 0; -if license('test','map_toolbox')==0, +if license('test','map_toolbox')==0 disp('WARNING: map toolbox not installed, trying house code'); usemap = 0; elseif license('checkout','map_toolbox')==0 @@ -18,7 +18,7 @@ usemap = 0; end -if usemap, +if usemap [data,R] = geotiffread(howatpath); data=double(flipud(data)); xdata=R.XLimWorld(1):R.DeltaX:R.XLimWorld(2); xdata=xdata(:); @@ -48,7 +48,7 @@ id1x=max(1,find(xdata>=xmin,1)-offset); id2x=min(numel(xdata),posx(end)+offset); - if 0, + if 0 ymin=min(Y(:)); ymax=max(Y(:)); posy=find(ydata<=ymax); id1y=max(1,find(ydata>=ymin,1)-offset); diff --git a/src/m/modeldata/interpGimpoceanmask.m b/src/m/modeldata/interpGimpoceanmask.m index a84de1256..3f2cb8708 100644 --- a/src/m/modeldata/interpGimpoceanmask.m +++ b/src/m/modeldata/interpGimpoceanmask.m @@ -10,7 +10,7 @@ end usemap = 0; -if license('test','map_toolbox')==0, +if license('test','map_toolbox')==0 disp('WARNING: map toolbox not installed, trying house code'); usemap = 0; elseif license('checkout','map_toolbox')==0 @@ -18,7 +18,7 @@ usemap = 0; end -if usemap, +if usemap [data,R] = geotiffread(howatpath); data=double(flipud(data)); xdata=R.XLimWorld(1):R.DeltaX:R.XLimWorld(2); xdata=xdata(:); @@ -48,7 +48,7 @@ id1x=max(1,find(xdata>=xmin,1)-offset); id2x=min(numel(xdata),posx(end)+offset); - if 0, + if 0 ymin=min(Y(:)); ymax=max(Y(:)); posy=find(ydata<=ymax); id1y=max(1,find(ydata>=ymin,1)-offset); diff --git a/src/m/modeldata/interpGrIMP.m b/src/m/modeldata/interpGrIMP.m index 1ec636984..280ff1cdd 100644 --- a/src/m/modeldata/interpGrIMP.m +++ b/src/m/modeldata/interpGrIMP.m @@ -9,7 +9,7 @@ end usemap = 0; -if license('test','map_toolbox')==0, +if license('test','map_toolbox')==0 disp('WARNING: map toolbox not installed, trying house code'); usemap = 0; elseif license('checkout','map_toolbox')==0 @@ -17,7 +17,7 @@ usemap = 0; end -if usemap, +if usemap [data,R] = geotiffread(datapath); data=double(flipud(data)); xdata=R.XLimWorld(1):R.DeltaX:R.XLimWorld(2); xdata=xdata(:); @@ -47,7 +47,7 @@ id1x=max(1,find(xdata>=xmin,1)-offset); id2x=min(numel(xdata),posx(end)+offset); - if 0, + if 0 ymin=min(Y(:)); ymax=max(Y(:)); posy=find(ydata<=ymax); id1y=max(1,find(ydata>=ymin,1)-offset); diff --git a/src/m/modeldata/interpGridsCReSIS.m b/src/m/modeldata/interpGridsCReSIS.m index f9fe8b369..ea32957a9 100644 --- a/src/m/modeldata/interpGridsCReSIS.m +++ b/src/m/modeldata/interpGridsCReSIS.m @@ -9,7 +9,7 @@ error([filename ' does not exist']); end fid = fopen(filename); -for i=1:6, +for i=1:6 thisline = fgetl(fid); dummy = regexp(thisline,'(\S+)','match'); if strcmp(dummy{1},'ncols'), ncols=str2num(dummy{2}); end diff --git a/src/m/modeldata/interpGriggs2013.m b/src/m/modeldata/interpGriggs2013.m index d71b3a90d..4570f6987 100644 --- a/src/m/modeldata/interpGriggs2013.m +++ b/src/m/modeldata/interpGriggs2013.m @@ -9,7 +9,7 @@ griggs2013nc='/u/astrid-r1b/morlighe/issmjpl/proj-morlighem/DatasetGreenland/Data/Griggs2012/Greenland_bedrock_topography_and_geometry_062012_JGriggs.nc'; verbose = 0; -if nargout==2, +if nargout==2 string = 'BedrockElevation'; end diff --git a/src/m/modeldata/interpIBCSO.m b/src/m/modeldata/interpIBCSO.m index 3be6d5750..efec41621 100644 --- a/src/m/modeldata/interpIBCSO.m +++ b/src/m/modeldata/interpIBCSO.m @@ -24,7 +24,7 @@ disp(' -- IBCSO: interpolating bed'); bedout = InterpFromGrid(xdata,fliplr(ydata),data,double(X),double(Y)); -if nargout==2, +if nargout==2 disp(' -- IBCSO: bathymetry sid'); xdata = ncread(sidpath,'x'); ydata = ncread(sidpath,'y'); diff --git a/src/m/modeldata/interpIBCSO2.m b/src/m/modeldata/interpIBCSO2.m index 3ac6e6e2a..4a7dcbf05 100644 --- a/src/m/modeldata/interpIBCSO2.m +++ b/src/m/modeldata/interpIBCSO2.m @@ -37,7 +37,7 @@ disp(' -- IBCSOv2: interpolating bed'); bedout = InterpFromGrid(xdata,ydata,data,double(X),double(Y)); -if nargout==2, +if nargout==2 disp(' -- IBCSOv2: bathymetry sid'); data = ncread(sidpath,'tid')'; disp(' -- IBCSOv2: interpolating sids'); diff --git a/src/m/modeldata/interpJakobsson2012.m b/src/m/modeldata/interpJakobsson2012.m index 41b3d82fb..fab5565ef 100644 --- a/src/m/modeldata/interpJakobsson2012.m +++ b/src/m/modeldata/interpJakobsson2012.m @@ -23,7 +23,7 @@ bedout = InterpFromGrid(xdata,ydata,data,x0075,y0075); bedout = reshape(bedout,size(X,1),size(X,2)); -if nargout==2, +if nargout==2 ncpath ='/home/ModelData/Greenland/IBCAO/IBCAO_V3_SID_500m.grd'; disp(' -- Jakobsson2012: loading source'); xdata = double(ncread(ncpath,'x')); diff --git a/src/m/modeldata/interpJakobsson2020.m b/src/m/modeldata/interpJakobsson2020.m index dbfa0ad82..479b7dbb8 100644 --- a/src/m/modeldata/interpJakobsson2020.m +++ b/src/m/modeldata/interpJakobsson2020.m @@ -39,7 +39,7 @@ bedout = InterpFromGrid(xdata,ydata,data,x0075,y0075); bedout = reshape(bedout,size(X,1),size(X,2)); -if nargout==2, +if nargout==2 ncpath ='/totten_1/ModelData/Greenland/IBCAO/IBCAO_v4_200m_TID.nc'; disp(' -- Jakobsson2020: loading source'); data = double(ncread(ncpath,'z',[id1x id1y],[id2x-id1x+1 id2y-id1y+1],[1 1]))'; diff --git a/src/m/modeldata/interpJoughin.m b/src/m/modeldata/interpJoughin.m index c9afae924..af6b49ca9 100644 --- a/src/m/modeldata/interpJoughin.m +++ b/src/m/modeldata/interpJoughin.m @@ -4,7 +4,7 @@ switch oshostname(), case {'murdo','thwaites','astrid'} - if nargin==3, + if nargin==3 rootname = ['/u/astrid-r1b/morlighe/issmjpl/proj-morlighem/DatasetGreenland/Data/Vel/Joughin/' num2str(Date) '/']; else error('not supported'); @@ -16,7 +16,7 @@ end verbose = 1; -if ~exist(rootname,'dir'), +if ~exist(rootname,'dir') error(['file ' rootname ' not found']); end @@ -85,7 +85,7 @@ fid = fopen(filein,'r'); xgeo=zeros(3,2); i=1; -while ~feof(fid), +while ~feof(fid) line=fgets(fid); [A,count]=sscanf(line,'%f %f',[1 2]); if(count == 2) diff --git a/src/m/modeldata/interpMouginotAnt2016.m b/src/m/modeldata/interpMouginotAnt2016.m index 0dc73f2ba..09baa8933 100644 --- a/src/m/modeldata/interpMouginotAnt2016.m +++ b/src/m/modeldata/interpMouginotAnt2016.m @@ -41,6 +41,6 @@ vxout = InterpFromGrid(x,y,double(vx),X,Y); vyout = InterpFromGrid(x,y,double(vy),X,Y); -if nargout==1, +if nargout==1 vxout = sqrt(vxout.^2+vyout.^2); end diff --git a/src/m/modeldata/interpMouginotAnt2017.m b/src/m/modeldata/interpMouginotAnt2017.m index c2d6f3035..52d8bb16c 100644 --- a/src/m/modeldata/interpMouginotAnt2017.m +++ b/src/m/modeldata/interpMouginotAnt2017.m @@ -1,15 +1,19 @@ -function [vxout vyout]= interpMouginotAnt2017(X,Y), +function [vxout vyout]= interpMouginotAnt2017(X,Y,ncdata), %read data -switch (oshostname()), - case {'ronne'} - nc = '/home/ModelData/Antarctica/MouginotVel/vel_nsidc.CF16_2.nc'; - case {'totten'} - nc = '/totten_1/ModelData/Antarctica/MouginotVel/vel_nsidc.CF16_2.nc'; - case {'amundsen.thayer.dartmouth.edu'} - nc = '/local/ModelData/AntarcticVelocity/v_mix.v13Mar2019.nc'; - otherwise - error('hostname not supported yet'); +if nargin < 3 + switch (oshostname()), + case {'ronne'} + nc = '/home/ModelData/Antarctica/MouginotVel/vel_nsidc.CF16_2.nc'; + case {'totten'} + nc = '/totten_1/ModelData/Antarctica/MouginotVel/vel_nsidc.CF16_2.nc'; + case {'amundsen.thayer.dartmouth.edu'} + nc = '/local/ModelData/AntarcticVelocity/v_mix.v13Mar2019.nc'; + otherwise + error('hostname not supported yet'); + end +else + nc = ncdata; end xdata = double(ncread(nc,'x')); @@ -38,6 +42,6 @@ vyout = InterpFromGrid(xdata,ydata,vydata,double(X),double(Y)); %return vel if only one output is requested -if nargout==1, +if nargout==1 vxout = sqrt(vxout.^2+vyout.^2); end diff --git a/src/m/modeldata/interpMouginotAnt2019.m b/src/m/modeldata/interpMouginotAnt2019.m index 25f63cabb..91612ac0f 100644 --- a/src/m/modeldata/interpMouginotAnt2019.m +++ b/src/m/modeldata/interpMouginotAnt2019.m @@ -49,6 +49,6 @@ vyout = InterpFromGrid(xdata,ydata,vydata,double(X),double(Y)); %return vel if only one output is requested -if nargout==1, +if nargout==1 vxout = sqrt(vxout.^2+vyout.^2); end diff --git a/src/m/modeldata/interpMouginotAntTimeSeries1973to2018.m b/src/m/modeldata/interpMouginotAntTimeSeries1973to2018.m index a7349cc66..c066506aa 100644 --- a/src/m/modeldata/interpMouginotAntTimeSeries1973to2018.m +++ b/src/m/modeldata/interpMouginotAntTimeSeries1973to2018.m @@ -71,7 +71,7 @@ error('Size of input T not supported!'); end T=T(:); - if size(T,2)==1 & any(T(:,1)==1973), + if size(T,2)==1 & any(T(:,1)==1973) disp(' '); disp(' Found year=1973 in T (array). Please, specify the data series using a second index.'); disp(' Data available for 1973:'); @@ -85,7 +85,7 @@ error(' Change input T before continuing.'); end %}}} pos = []; - for i=1:size(T,1), + for i=1:size(T,1) flag = (T(i,1)==year1); if size(T,2)==2, % ok, check both indexes (year1 and year2) flag = (T(i,1)==year1).*(T(i,2)==year2); @@ -93,11 +93,11 @@ pos = [pos; find(flag)]; end % check again {{{ - if length(pos)~=size(T,1) | length(unique(pos))~=length(pos), + if length(pos)~=size(T,1) | length(unique(pos))~=length(pos) disp(' '); disp(' Time resquested does not exist in data set or is repeated!'); disp(' Data resquested:'); - for i=1:length(T(:,1)), + for i=1:length(T(:,1)) str = [' ' int2str(T(i,1)) ' ']; if size(T,2)==2, % ok, check both indexes (year1 and year2) str = [str int2str(T(i,2))]; @@ -106,7 +106,7 @@ end disp(' '); disp(' Data available (24 series):'); - for i=1:length(year1), + for i=1:length(year1) str = [' ' int2str(year1(i)) ' ' int2str(year2(i))]; disp(str); end @@ -118,7 +118,7 @@ disp(' '); error(' Change input T before continuing.'); end%}}} -elseif nargin<3, +elseif nargin<3 pos = 1:24; % all available data else error('nargin not supported yet!'); @@ -150,7 +150,7 @@ stdxdata = []; stdydata = []; end -for i=1:length(pos), +for i=1:length(pos) disp([' step = ' int2str(i) '/' int2str(length(pos)) ', position = ' int2str(pos(i)) ', year = ' int2str(year1(pos(i))) ' - ' int2str(year2(pos(i)))]); vx = double(ncread(nc,'VX',[id1x id1y pos(i)],[id2x-id1x+1 id2y-id1y+1 1],[1 1 1])); vy = double(ncread(nc,'VY',[id1x id1y pos(i)],[id2x-id1x+1 id2y-id1y+1 1],[1 1 1])); @@ -179,7 +179,7 @@ stdxout = []; stdyout = []; end -for i=1:length(pos), +for i=1:length(pos) disp([' step = ' int2str(i) '/' int2str(length(pos)) ', position = ' int2str(pos(i)) ', year = ' int2str(year1(pos(i))) ' - ' int2str(year2(pos(i)))]); vxout = [vxout InterpFromGrid(xdata,ydata,vxdata(:,:,i),double(X),double(Y))]; vyout = [vyout InterpFromGrid(xdata,ydata,vydata(:,:,i),double(X),double(Y))]; @@ -192,6 +192,6 @@ end %return vel if only one output is requested -if nargout==1, +if nargout==1 vxout = sqrt(vxout.^2+vyout.^2); end diff --git a/src/m/modeldata/interpPaolo2015.m b/src/m/modeldata/interpPaolo2015.m index 5c4e9ba9b..67e4e9244 100644 --- a/src/m/modeldata/interpPaolo2015.m +++ b/src/m/modeldata/interpPaolo2015.m @@ -118,7 +118,7 @@ % height_err : 2-standard-error time series [m] % -if nargin>4 | nargin<2, +if nargin>4 | nargin<2 error('nargin not supported yet!'); end @@ -138,16 +138,16 @@ dh_fil_data = h5read(h5,'/height_filt'); % set interpolation method -if nargin<4, +if nargin<4 method = 'linear'; % default method end % get the positions related to T -if nargin<3, +if nargin<3 pos = 1:length(t_data); % all available data else % initial check %{{{ - if size(T,2)>1 | size(T,1)<1 | size(T,2)<1, + if size(T,2)>1 | size(T,1)<1 | size(T,2)<1 error('Size of input T not supported!'); end if size(X,1)>1 & size(X,2)>1 @@ -157,10 +157,10 @@ % Loop over T pos = []; epsilon = 5e-4; - for i=1:length(T), + for i=1:length(T) % find specific time flag = (T(i)-epsilont_data); - if ~any(flag), + if ~any(flag) % ok, find the time related to the requested year flag = (T(i)==floor(t_data)); end @@ -171,7 +171,7 @@ end % Check if there is repeated positions posunique = unique(pos); - if length(posunique)~=length(pos), + if length(posunique)~=length(pos) disp(' WARNING: found repeated positions in requested time'); end end @@ -184,7 +184,7 @@ disp([' -- Paolo''s Time Series 1994 to 2012: interpolating in Lat/Long grid']); dh_raw_out = []; dh_fil_out = []; -for i=1:length(pos), +for i=1:length(pos) disp([' step = ' int2str(i) '/' int2str(length(pos)) ', position = ' int2str(pos(i)) ', year = ' num2str(t_data(pos(i)))]); dh_raw_out = [dh_raw_out InterpFromGrid(lat_data(1,:),lon_data(:,1),dh_raw_data(:,:,pos(i)),LAT,LON,method)]; dh_fil_out = [dh_fil_out InterpFromGrid(lat_data(1,:),lon_data(:,1),dh_fil_data(:,:,pos(i)),LAT,LON,method)]; diff --git a/src/m/modeldata/interpRACMOant.m b/src/m/modeldata/interpRACMOant.m index 4950adb93..d67d35fa3 100644 --- a/src/m/modeldata/interpRACMOant.m +++ b/src/m/modeldata/interpRACMOant.m @@ -1,18 +1,22 @@ -function smb = interpRACMOant(x,y); +function smb = interpRACMOant(x,y,ncdata); -switch oshostname(), - case {'ronne'} - smbfile = '/home/ModelData/Antarctica/RACMO2SMB/SMB_RACMO2.3_1979_2011.nc'; - case {'totten'} - smbfile = '/totten_1/ModelData/Antarctica/RACMO2SMB/SMB_RACMO2.3_1979_2011.nc'; - otherwise - error('machine not supported yet'); +if nargin < 3 + switch oshostname(), + case {'ronne'} + smbfile = '/home/ModelData/Antarctica/RACMO2SMB/SMB_RACMO2.3_1979_2011.nc'; + case {'totten'} + smbfile = '/totten_1/ModelData/Antarctica/RACMO2SMB/SMB_RACMO2.3_1979_2011.nc'; + otherwise + error('machine not supported yet'); + end +else + smbfile = ncdata; end - LAT=ncread(smbfile,'lat2d')'; - LON=ncread(smbfile,'lon2d')'; - SMB=ncread(smbfile,'SMB')'; - [X Y]=ll2xy(LAT,LON,-1,0,71); +LAT=ncread(smbfile,'lat2d')'; +LON=ncread(smbfile,'lon2d')'; +SMB=ncread(smbfile,'SMB')'; +[X Y]=ll2xy(LAT,LON,-1,0,71); - disp(' -- RACMO2.3 1979 - 2011: interpolating (assuming rho_ice = 917 kg/m^3)'); - rho_ice = 917; - smb = griddata(X,Y,SMB,x,y) / 917; +disp(' -- RACMO2.3 1979 - 2011: interpolating (assuming rho_ice = 917 kg/m^3)'); +rho_ice = 917; +smb = griddata(X,Y,SMB,x,y) / 917; diff --git a/src/m/modeldata/interpREMA.m b/src/m/modeldata/interpREMA.m index c0389c39b..18bd28118 100644 --- a/src/m/modeldata/interpREMA.m +++ b/src/m/modeldata/interpREMA.m @@ -10,7 +10,7 @@ end usemap = 0; -if license('test','map_toolbox')==0, +if license('test','map_toolbox')==0 disp('WARNING: map toolbox not installed, trying house code'); usemap = 0; elseif license('checkout','map_toolbox')==0 @@ -18,7 +18,7 @@ usemap = 0; end -if usemap, +if usemap [data,R] = geotiffread(remapath); data=double(flipud(data)); xdata=R.XLimWorld(1):R.DeltaX:R.XLimWorld(2); xdata=xdata(:); diff --git a/src/m/modeldata/interpRTopo2.m b/src/m/modeldata/interpRTopo2.m index 845440279..c33c51b56 100644 --- a/src/m/modeldata/interpRTopo2.m +++ b/src/m/modeldata/interpRTopo2.m @@ -17,16 +17,16 @@ end verbose = 1; -if nargin==3, +if nargin==3 hemisphere = varargin{1}; else hemisphere = +1; end -if abs(hemisphere)~=1, +if abs(hemisphere)~=1 error('hemisphere should be +/-1'); end -if hemisphere==+1, +if hemisphere==+1 if verbose, disp(' -- RTopo-2: convert to lat/lon using Greenland projection'); end [LAT, LON ] = xy2ll(double(X(:)),double(Y(:)),+1,45,70); else diff --git a/src/m/modeldata/interpRignot2012.m b/src/m/modeldata/interpRignot2012.m index 6ff2569e7..4faefac76 100644 --- a/src/m/modeldata/interpRignot2012.m +++ b/src/m/modeldata/interpRignot2012.m @@ -31,6 +31,6 @@ vxout = InterpFromGrid(x,y,double(vx),X,Y); vyout = InterpFromGrid(x,y,double(vy),X,Y); -if nargout==1, +if nargout==1 vxout = sqrt(vxout.^2+vyout.^2); end diff --git a/src/m/modeldata/interpRignotIceShelfMelt.m b/src/m/modeldata/interpRignotIceShelfMelt.m index 056fda19d..f69d9f79f 100644 --- a/src/m/modeldata/interpRignotIceShelfMelt.m +++ b/src/m/modeldata/interpRignotIceShelfMelt.m @@ -1,23 +1,27 @@ -function output = interpRignotIceShelfMelt(X,Y,string) +function output = interpRignotIceShelfMelt(X,Y,string,ncdata) %INTERPRIGNOTICESHELFMELT - interp melt rates from Rignot et al. 2013 % % Usage: % output = interpRignotIceShelfMelt(X,Y) -switch (oshostname()) - case {'ronne'} - rignotmelt='/home/ModelData/Antarctica/RignotMeltingrate/Ant_MeltingRate.nc'; - case {'totten'} - rignotmelt='/totten_1/ModelData/Antarctica/RignotMeltingrate/Ant_MeltingRate.nc'; - case {'amundsen.thayer.dartmouth.edu'} - rignotmelt='/local/ModelData/AntarcticMeltRignot/Ant_MeltingRate.nc'; - case {'thwaites','larsen','murdo','astrid','wilkins.jpl.nasa.gov'} - rignotmelt=['/u/astrid-r1b/ModelData/RignotAntarcticaMeltRates/Ant_MeltingRate.v2.nc']; - otherwise - error('hostname not supported yet'); +if nargin < 4 + switch (oshostname()) + case {'ronne'} + rignotmelt='/home/ModelData/Antarctica/RignotMeltingrate/Ant_MeltingRate.nc'; + case {'totten'} + rignotmelt='/totten_1/ModelData/Antarctica/RignotMeltingrate/Ant_MeltingRate.nc'; + case {'amundsen.thayer.dartmouth.edu'} + rignotmelt='/local/ModelData/AntarcticMeltRignot/Ant_MeltingRate.nc'; + case {'thwaites','larsen','murdo','astrid','wilkins.jpl.nasa.gov'} + rignotmelt=['/u/astrid-r1b/ModelData/RignotAntarcticaMeltRates/Ant_MeltingRate.v2.nc']; + otherwise + error('hostname not supported yet'); + end +else + rignotmelt = ncdata; end -if nargin==2, +if nargin==2 string = 'melt_actual'; end diff --git a/src/m/modeldata/interpSeaRISE.m b/src/m/modeldata/interpSeaRISE.m index c165debd5..ea9a31785 100644 --- a/src/m/modeldata/interpSeaRISE.m +++ b/src/m/modeldata/interpSeaRISE.m @@ -36,33 +36,33 @@ verbose=0; -if nargin==3, +if nargin==3 hemisphere = +1; else hemisphere = varargin{1}; end -if nargin==5, +if nargin==5 searisenc = varargin{2}; else %read data switch (oshostname()), case {'ronne'} - if hemisphere==1, + if hemisphere==1 searisenc='/home/ModelData/SeaRISE/Greenland_5km_dev1.2.nc'; - elseif hemisphere==-1, + elseif hemisphere==-1 searisenc='/home/ModelData/SeaRISE/Antarctica_5km_dev1.0.nc'; end case {'thwaites','larsen','murdo','astrid','wilkins.jpl.nasa.gov'} - if hemisphere==1, + if hemisphere==1 searisenc='/u/astrid-r1b/ModelData/SeaRISE/Greenland5km_v1.2/Greenland_5km_dev1.2.nc'; - elseif hemisphere==-1, + elseif hemisphere==-1 searisenc='/u/astrid-r1b/ModelData/SeaRISE/Antarctica5km_shelves_v1.0/Antarctica_5km_dev1.0.nc'; end case {'totten'} - if hemisphere==1, + if hemisphere==1 searisenc='/totten_1/ModelData/SeaRISE/Greenland_5km_dev1.2.nc'; - elseif hemisphere==-1, + elseif hemisphere==-1 searisenc='/totten_1/ModelData/SeaRISE/Antarctica_5km_dev1.0.nc'; end otherwise @@ -72,10 +72,10 @@ %convert coordinates to SeaRISE projection if verbose, disp(' -- SeaRISE: converting coordinates'); end -if hemisphere==1, +if hemisphere==1 [LAT, LON ] = xy2ll(double(X(:)),double(Y(:)),+1,45,70); [xproj,yproj] = ll2xy(LAT,LON ,+1,39,71); -elseif hemisphere==-1, +elseif hemisphere==-1 xproj=X; yproj=Y; end diff --git a/src/m/modeldata/interpShepherd2019.m b/src/m/modeldata/interpShepherd2019.m index 7823ee5ed..da1193c3c 100644 --- a/src/m/modeldata/interpShepherd2019.m +++ b/src/m/modeldata/interpShepherd2019.m @@ -40,7 +40,7 @@ error('machine not supported yet'); end -if nargin==3, +if nargin==3 method='linear';% default else method=varargin{1}; diff --git a/src/m/modules/ContourToMesh.m b/src/m/modules/ContourToMesh.m index 3b655c5c3..824cc381e 100644 --- a/src/m/modules/ContourToMesh.m +++ b/src/m/modules/ContourToMesh.m @@ -25,9 +25,9 @@ end %Some conversion of files: -if ischar(contourname), +if ischar(contourname) [path,name,ext]=fileparts(contourname); - if strcmpi(ext,'.shp'), + if strcmpi(ext,'.shp') %read contour from shapefile contourname=shpread(contourname); diff --git a/src/m/modules/ContourToNodes.m b/src/m/modules/ContourToNodes.m index 77d55ace3..d3b2bf01a 100644 --- a/src/m/modules/ContourToNodes.m +++ b/src/m/modules/ContourToNodes.m @@ -10,15 +10,15 @@ % flags: vector of flags (0 or 1), of size nodes %Check usage -if nargin~=4, +if nargin~=4 help ContourToNodes error('Wrong usage (see above)'); end %Some conversion of files: -if ischar(contourname), +if ischar(contourname) [path,name,ext]=fileparts(contourname); - if strcmpi(ext,'.shp'), + if strcmpi(ext,'.shp') %read contour from shapefile: contourname=shpread(contourname); diff --git a/src/m/modules/ExpToLevelSet.m b/src/m/modules/ExpToLevelSet.m index 37ebf6494..99a9d4fd1 100644 --- a/src/m/modules/ExpToLevelSet.m +++ b/src/m/modules/ExpToLevelSet.m @@ -23,9 +23,9 @@ multipleShp = 0; -if ischar(contourname), +if ischar(contourname) [path,name,ext]=fileparts(contourname); - if strcmpi(ext,'.shp'), + if strcmpi(ext,'.shp') %read contour from shapefile contourname=shpread(contourname); if isstruct(contourname) diff --git a/src/m/modules/MeshProfileIntersection.m b/src/m/modules/MeshProfileIntersection.m index 6867ed018..cbfc694e0 100644 --- a/src/m/modules/MeshProfileIntersection.m +++ b/src/m/modules/MeshProfileIntersection.m @@ -19,7 +19,7 @@ end [path,name,ext]=fileparts(filename); -if strcmpi(ext,'.shp'), +if strcmpi(ext,'.shp') %convert to expfile and store in a temporary directory: oldfilename=filename; diff --git a/src/m/netcdf/OLD/export_netCDF.m b/src/m/netcdf/OLD/export_netCDF.m new file mode 100644 index 000000000..ff94a69cb --- /dev/null +++ b/src/m/netcdf/OLD/export_netCDF.m @@ -0,0 +1,510 @@ +function export_netCDF(md,filename) +%verbosity of the code, 0 is no messages, 5 is chatty + verbose = 5; + if exist(filename), + delete(filename) + % disp(sprintf('File %s allready exist', filename)); + % prompt = 'Give a new name or "delete" to replace: '; + % newname = input(prompt,'s'); + % if strcmp(newname,'delete') + % delete(filename) + % else + % disp(sprintf('New file name is %s ', newname)); + % filename=newname + % end + end + %open file and write description + mode = netcdf.getConstant('NC_NETCDF4'); + mode = bitor(mode,netcdf.getConstant('NC_NOCLOBBER')); %NOCLOBBER to avoid overwrite + ncid = netcdf.create(filename,mode); + netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'description',['Results for run ' md.miscellaneous.name]); + netcdf.putAtt(ncid,netcdf.getConstant('NC_GLOBAL'),'history',['Created ' datestr(now)]); + + %gather geometry and timestepping as dimensions + if isempty(fieldnames(md.results)), + %results as no field so no time is present + Duration = 0; + else + resfields = fieldnames(md.results); + Duration = size(eval(['md.results. ' resfields{1} ]),2); + end + if Duration>0, + StepNum = Duration; + else + StepNum=1; + end + DimSize(1).index=netcdf.defDim(ncid,'Time',StepNum); %time is the first dimension + [DimSize(1).name,DimSize(1).value]=netcdf.inqDim(ncid,DimSize(1).index); + DimValue(1)=DimSize(1).value; + DimSize(2).index=netcdf.defDim(ncid,'UnLim',netcdf.getConstant('NC_UNLIMITED')); % we add an unlimited dimension if needed + [DimSize(2).name,DimSize(2).value]=netcdf.inqDim(ncid,DimSize(2).index); + DimValue(2)=DimSize(2).value; + % adding mesh related dimensions + dimlist=[2 40 md.mesh.numberofelements md.mesh.numberofvertices size(md.mesh.elements,2)]; + dimnames=["DictDummy" "StringLength" "EltNum" "VertNum" "VertPerElt"]; + if isprop(md.mesh, 'edges'), + dimlist(end+1)=md.mesh.numberofedges; + dimnames(end+1)="EdgeNum"; + else + dimlist(end+1)=0; + dimnames(end+1)="EdgeNum"; + end + if verbose > 0, + disp('===Creating dimensions ==='); + end + %define netcdf dimensions + for i=1:length(dimlist) + % do not add the dimension if it exists already + if sum(dimlist(i) == DimValue) == 0 + DimSize(i+2).index=netcdf.defDim(ncid,dimnames(i),dimlist(i)); + [DimSize(i+2).name,DimSize(i+2).value]=netcdf.inqDim(ncid,DimSize(i+2).index); + DimValue(i+2)=DimSize(i+2).value; + end + end + issmclasses = fieldnames(md)'; + typelist={'half', 'single','double','int8','int16'... + ,'int32','int64','uint8','uint16','uint32'... + ,'uint64','logical','char','string'}; %all malab types that are 0D + + for cl=1:length(issmclasses), + if isempty(md.(issmclasses{cl})), + disp(sprintf("md.%s is empty and will be left as default",issmclasses{cl})); + else + subclasses=fieldnames(md.(issmclasses{cl}))'; + for sc=1:length(subclasses), + if sum(strcmp(class(md.(issmclasses{cl}).(subclasses{sc})), typelist)) == 0, + issmclasses = [issmclasses class(md.(issmclasses{cl}).(subclasses{sc}))]; + end + end + end + end + %get all model classes and create respective groups + groups=fieldnames(md); + if verbose > 0, + disp('===Creating and populating groups==='); + end + for i=1:length(groups), + if verbose >1, + disp(sprintf('===Now treating %s===',groups{i})); + end + if strcmp(groups{i}, 'qmu'), + disp('qmu is skipped until it is more stable'); + continue + end + groupID=netcdf.defGrp(ncid,groups{i}); + %In each group gather the fields of the class + if isempty(md.(groups{i})), + disp(sprintf("WARNING: md.%s is empty, we skip it.",groups{i})) + continue + end + fields=fieldnames(md.(groups{i})); + if isempty(fields), + disp(sprintf("WARNING: md.%s as no fields, we skip it.",groups{i})) + continue + end + %looping on fields in each group + for j=1:length(fields), + Var=md.(groups{i}).(fields{j}); + %treatment for lists + if isa(Var,'cell') + Stdlist=false; %first assume it is not a standard list + if length(Var) == 0 + Stdlist=true; %It is empty and so standard (for us) + else + for k=1:length(typelist) + if isa(Var{1},typelist{k}) + Stdlist=true; %if the list is of a known type (to matlab) if not it is probably some exotic ISSM stuff + end + end + end + %print the issm class as a classtype attribute + klass = class(md.(groups{i})); + klasstring = strcat(klass, '.',klass); + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring); + if(Stdlist) % this is a standard or empty list just proceed + if verbose > 4, + disp(sprintf("=££=creating var for %s.%s with classtype : %s",groups{i}, fields{j}, klasstring)) + end + if ~isempty(Var) && isa(Var{1}, 'char'), % we have a char array, pad it to a given length + Var=char(Var)'; + end + [DimSize,DimValue,varid]=CreateVar(ncid,Var,groupID,fields{j},DimSize,DimValue); + if ~isempty(varid), + FillVar(Var,groupID,varid); + end + + else % this is a list of fields, specific treatment needed (perhaps) + if verbose > 4, + disp(sprintf("=??=we have a list of fields for %s.%s with classtype : %s",groups{i}, fields{j}, klasstring)); + end + if strcmp(groups{i}, 'outputdefinition'), + listsize=length(Var); + for k=1:listsize, + subgroupname=md.(groups{i}).(fields{j}){k}.definitionstring; + subgroupID=netcdf.defGrp(groupID,subgroupname); + klass=class(md.(groups{i}).(fields{j}){k}); + klasstring = strcat(klass, '.',klass); + netcdf.putAtt(subgroupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring); + subfields=fieldnames(md.(groups{i}).(fields{j}){k}); + for l=1:length(subfields) + if verbose > 4, + disp(sprintf("=--=creating var for %s.%s[%i].%s",groups{i}, fields{j}, k, subfields{l})); + end + Var = md.(groups{i}).(fields{j}){k}.(subfields{l}); + if sum(numel(Var) == size(Var)) == 0, %this is a 2D array or more (and not a vector with dimension 2 = 1) + Var = Var'; + end + [DimSize,DimValue,varid]=CreateVar(ncid,Var,subgroupID,subfields{l},DimSize,DimValue); + if ~isempty(varid), + FillVar(Var,subgroupID,varid); + end + end + end + else + disp(sprintf("WARNING: unknown treatment for md.%s",groups{i})); + end + end + elseif sum(strcmp(class(Var), typelist))==1, %this is a standard matlab class with no subgrouping + if verbose > 4, + disp(sprintf("====creating var for %s.%s", groups{i}, fields{j})) + end + klass=class(md.(groups{i})); + klasstring = strcat(klass, '.',klass); + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring); + if sum(numel(Var) == size(Var)) == 0, %this is a 2D array or more (and not a vector with dimension 2 = 1) + Var = Var'; + end + + [DimSize,DimValue,varid]=CreateVar(ncid,Var,groupID,fields{j},DimSize,DimValue); + if ~isempty(varid), + FillVar(Var,groupID,varid); + end + + + elseif isa(Var,'struct') % structures need special treatment + if strcmp(groups{i}, 'results'), + klasstring=strcat(groups{i} ,'.', groups{i}); + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring); + Listsize= length(md.(groups{i}).(fields{j})); + subgroupname=fields{j}; + subgroupID=netcdf.defGrp(groupID,subgroupname); + klasstring='results.solutionstep'; + netcdf.putAtt(subgroupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring); + subfields=fieldnames(md.(groups{i}).(fields{j})); + if isempty(subfields), + disp(sprintf("WARNING: md.%s.%s as no subfields, we skip it.",groups{i}, fields{j})); + continue + end + for k=1:length(subfields), + if ~ismember(subfields{k}, {'errlog', 'outlog', 'SolutionType'}) + StackedVar=restable(); + for l=1:Listsize, + Var = md.(groups{i}).(fields{j})(l).(subfields{k}); + if length(Var) == 0, + %Some variables only have data on the first step + break + end + lastindex=l; + StackedVar=StackedVar.update(Var); + end + if verbose > 4, + disp(sprintf("=$$=creating var for %s.%s.%s",groups{i}, fields{j}, subfields{k})); + disp(sprintf("last index on the list is %i",lastindex)); + end + StackedVar=StackedVar.finalize(lastindex); + [DimSize,DimValue,varid]=CreateVar(ncid,StackedVar,subgroupID,subfields{k},DimSize,DimValue); + if ~isempty(varid), + FillVar(StackedVar,subgroupID,varid); + end + elseif ismember(subfields{k}, {'SolutionType'}) + %We just add solution type once as an attribute + Var = md.(groups{i}).(fields{j})(1).(subfields{k}); + [DimSize,DimValue,varid]=CreateVar(ncid,Var,subgroupID,subfields{k},DimSize,DimValue); + if ~isempty(varid), + FillVar(Var,subgroupID,varid); + end + + end + end + elseif strcmp(groups{i}, 'toolkits'), + klasstring=strcat(groups{i} ,'.', groups{i}); + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring); + if verbose > 4, + disp(sprintf("=}{=creating var for %s.%s",groups{i}, fields{j})); + end + + [DimSize,DimValue,varid]=CreateVar(ncid,Var,groupID,fields{j},DimSize,DimValue); + if ~isempty(varid), + FillVar(Var,groupID,varid); + end + + elseif isempty(fieldnames(md.(groups{i}).(fields{j}))) % this is an empty struct, jus treat it as normal + klass=class(md.(groups{i})); + klasstring = strcat(klass, '.',klass); + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring); + if verbose > 4, + disp(sprintf("=[]=creating var for %s.%s",groups{i}, fields{j})); + end + + [DimSize,DimValue,varid]=CreateVar(ncid,Var,groupID,fields{j},DimSize,DimValue); + if ~isempty(varid), + FillVar(Var,groupID,varid); + end + + else + disp(sprintf("WARNING, md.%s.%s is not treated as it does not fall in one of the existing cases with class '%s'.",groups{i}, fields{j}, class(md.(groups{i}).(fields{j})))) + end + elseif sum(strcmp(class(Var), issmclasses)) == 1, % that is an issm class + if strcmp(class(Var), 'solution'), + if verbose > 4, + disp(sprintf("=$$=creating var for %s.%s",groups{i}, fields{j})) + disp("NEED treatment") + end + elseif strcmp(class(Var), 'dict'), %we have potential for a dict in py not to sure what it translates to here. + if verbose > 4, + disp(sprintf("=WW=creating var for %s.%s",groups{i}, fields{j})) + disp("NEED Treatment") + end + + else + klass=class(md.(groups{i})); + klasstring = strcat(klass, '.',klass); + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring); + subgroupID=netcdf.defGrp(groupID,fields{j}); + klass=class(md.(groups{i}).(fields{j})); + klasstring = strcat(klass, '.',klass); + netcdf.putAtt(subgroupID,netcdf.getConstant('NC_GLOBAL'),'classtype',klasstring); + subfields=fieldnames(Var); + for k=1:length(subfields), + if sum(strcmp(subfields{k},["outlog" "errlog"])) == 0, + if verbose > 4, + disp(sprintf("+==+creating var for %s.%s.%s",groups{i}, fields{j}, subfields{k})) + end + Var=md.(groups{i}).(fields{j}).(subfields{k}); + [DimSize,DimValue,varid]=CreateVar(ncid,Var,subgroupID,subfields{k},DimSize,DimValue); + if ~isempty(varid), + FillVar(Var,subgroupID,varid); + end + end + end + + end + else + disp(sprintf("WARNING, md.%s.%s is not treated as it does not fall in one of the existing cases with class '%s'.",groups{i}, fields{j}, class(Var))) + end + end + end + netcdf.close(ncid); +end + +function [DimSize,DimValue,varid]=CreateVar(ncid,Var,groupID,field,DimSize,DimValue) +% Grab dimensions + varsize=size(Var); + varlength=length(Var); + % treating scalar string or bool as atribute + if isa(Var,'logical'), + if Var, + LogicString='True'; + else, + LogicString='False'; + end + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),field,LogicString); + varid=[]; + + elseif isa(Var,'char'), + if strcmp(field,'name'), % it looks like netCDF does not like attributes that are called "name" + field = 'varname'; + end + if size(Var,1) <= 1 %that is a single string or empty + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),field,Var); + varid=[]; + else % that is a character array + [dims,DimSize,DimValue]=GetDims(ncid,Var,DimSize,DimValue); + varid = netcdf.defVar(groupID,field,'NC_CHAR',dims); + if numel(Var)>1 + netcdf.defVarDeflate(groupID,varid,true,true,4); + end + end + + elseif isa(Var,'double'), %dealing with arrays + if all(mod(Var, 1) == 0, 'all') %those are actually integers, + [dims,DimSize,DimValue]=GetDims(ncid,Var,DimSize,DimValue); + varid = netcdf.defVar(groupID,field,'NC_INT64',dims); + if numel(Var)>1 + netcdf.defVarDeflate(groupID,varid,true,true,4); + end + else + [dims,DimSize,DimValue]=GetDims(ncid,Var,DimSize,DimValue); + varid = netcdf.defVar(groupID,field,'NC_DOUBLE',dims); + if numel(Var)>1 + netcdf.defVarDeflate(groupID,varid,true,true,4); + end + end + elseif isa(Var,'cell'), + % cells can be a range of things, what are we dealing with here + if isempty(Var), + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),field,'emptycell'); + varid=[]; + else + [dims,DimSize,DimValue]=GetDims(ncid,Var,DimSize,DimValue); + if isa(Var{1}, 'double'), + varid = netcdf.defVar(groupID,field,'NC_DOUBLE',dims); + if numel(Var)>1 + netcdf.defVarDeflate(groupID,varid,true,true,4); + end + else + varid = netcdf.defVar(groupID,field,'NC_CHAR',dims); + if numel(Var)>1 + netcdf.defVarDeflate(groupID,varid,true,true,4); + end + end + end + elseif isa(Var,'struct'), + if isempty(fieldnames(Var)), + netcdf.putAtt(groupID,netcdf.getConstant('NC_GLOBAL'),field,'emptystruct'); + varid=[]; + else + %Start by getting the structure fields and size + [dims,DimSize,DimValue]=GetDims(ncid,Var,DimSize,DimValue); + varid = netcdf.defVar(groupID,field,'NC_CHAR',dims); + if numel(Var)>1 + netcdf.defVarDeflate(groupID,varid,true,true,4); + end + end + else + disp(sprintf('no support for class %s of field %s',class(Var),field)); + varid=[]; + end + return +end + + +function FillVar(Var,groupID,varid) +% Grab dimensions + varsize=size(Var); + varlength=length(Var); + % treating scalar string or bool as atribute + if isa(Var,'double'), %dealing with arrays + if all(mod(Var, 1) == 0, 'all') %those are actually integers, + Var = int64(Var); + end + if length(Var)==0, + netcdf.putVar(groupID,varid,NaN); + else + netcdf.putVar(groupID,varid,Var); + end + elseif isa(Var,'char'), % at this point this should be a character array + netcdf.putVar(groupID,varid,Var); + elseif isa(Var,'cell'), % there can be a number of things in a cell array + for i=1:length(Var), + if isa(Var{i},'char') %for characters we limit the size to 40 for now + if length(Var)>1, + count=[min(length(Var{i}),40), 1]; + startpoint=[0 i-1]; + else + count=min(length(Var{i}),40); + startpoint=0; + end + + if length(Var{i})>40, + netcdf.putVar(groupID,varid,startpoint,count,Var{i}(1:40)); + disp(sprintf('some variable have been truncated')); + else + netcdf.putVar(groupID,varid,startpoint,count,Var{i}); + end + elseif isa(Var{i},'double') + startpoint=[i-1]; + count=[1 length(Var{i}) ndims(Var{i})]; + for j=1:ndims(Var{i}), + startpoint=[startpoint 0]; + end + netcdf.putVar(groupID,varid,startpoint,count,Var{i}); + else + disp(sprintf("WARNING: cell of class %s is not supported.",class(Var{i}))) + end + end + elseif isa(Var,'struct'), + %Start by getting the structure fields and size + locfields=fieldnames(Var); + for i=1:length(locfields), + for j=1:2, + if j==1, + CharVar=locfields{i}'; + disp(size(CharVar)) + if length(CharVar)==0 + CharVar='emptystruct'; + end + startpoint=[0,0,i-1] + else + if isa(Var.(locfields{i}),'char'), + CharVar=Var.(locfields{i})'; + else + CharVar=num2str(Var.(locfields{i}))'; + end + if length(CharVar)==0 + CharVar='emptystruct'; + end + startpoint=[0,1,i-1] + end + + extent=[min(length(CharVar),40), 1, 1] + if length(CharVar)>40, + netcdf.putVar(groupID,varid,startpoint,extent,CharVar(1:40)); + disp(sprintf('some variable have been truncated')); + else + netcdf.putVar(groupID,varid,startpoint,extent,CharVar); + end + end + end + else + disp(sprintf('no support for class %s',class(Var))); + end + return +end + +function [dims,DimSize,DimValue]=GetDims(ncid,Var,DimSize,DimValue) + dims=[]; + celldims=[]; + dim=ndims(Var); + if isa(Var,'struct'), + varsize=length(fieldnames(Var)); + else + varsize=size(Var); + if isa(Var, 'cell') + %we add the dimension of the cells themselves, + %that will most probably fail if cells have different sizes + for i=1:dim, + newdim=size(Var{i}); + if ~ismember(newdim, celldims), + celldims=[celldims newdim]; + end + end + end + end + varsize=[varsize celldims]; + alldim=length(varsize); + if dim>0, + for i=1:alldim, + if size(Var, i)>1 || i>dim || isa(Var, 'struct'), %we skip dimensions with zero lenght but want to add dimensions from cells + indsize=find(varsize(i)==DimValue); + if length(indsize)>0 + dims=[dims DimSize(indsize).index]; + else + indsize=length(DimSize)+1; + DimSize(indsize).index=netcdf.defDim(ncid,['DimNum' num2str(indsize)],varsize(i)); + [DimSize(indsize).name,DimSize(indsize).value]=netcdf.inqDim(ncid,DimSize(indsize).index); + DimValue(indsize)=DimSize(indsize).value; + dims=[dims DimSize(indsize).index]; + end + end + end + end + if isa(Var, 'cell') && isa(Var{1}, 'char'), + %if we have an cell variable with strings we need to add a stringlength + dims=[dims DimSize(4).index]; + end + % struct also need an extra dimension 2, but only if non empty + if isa(Var,'struct'), + dims=[DimSize(4).index DimSize(3).index, dims]; + end +end diff --git a/src/m/netcdf/export_netCDF.py b/src/m/netcdf/OLD/export_netCDF.py similarity index 100% rename from src/m/netcdf/export_netCDF.py rename to src/m/netcdf/OLD/export_netCDF.py diff --git a/src/m/netcdf/OLD/restable.m b/src/m/netcdf/OLD/restable.m new file mode 100644 index 000000000..8fa8ec988 --- /dev/null +++ b/src/m/netcdf/OLD/restable.m @@ -0,0 +1,60 @@ +classdef restable + properties(SetAccess=public) + data=[]; + sizes=[]; + end + methods + function self = update(self, stepvar) + if length(stepvar) == 1 + %if we have a scalar we just add it to the end + %we save the size of the current step for further treatment + self.sizes=[self.sizes;1]; + self.data=[self.data;stepvar]; + else + % if it is an array we add the values one by one + %we save the size of the current step for further treatment + self.sizes=[self.sizes;fliplr(size(stepvar))]; + %we need to transpose to follow the indexing + flatdata=reshape(stepvar', 1, []); + self.data=[self.data,flatdata]; + end + end + function outdat = finalize(self, rows) + if length(self.data)>rows, + if size(self.sizes, 1)==1, + %just one step, data don't need treatment + outdat=self.data; + else, + %we have more scalars than steps, so we have an array + maxsize=[]; + for d=1:size(self.sizes,2) + maxsize=[maxsize,max(self.sizes(:,d))]; + end + findim=[maxsize, rows]; + %first check if all steps are the same size + SameSize = sum(self.sizes - self.sizes(1, :))==0; + if SameSize, + %same size for all steps, just reshape + outdat=reshape(self.data, findim); + else, + %different sizes at each steps, first create a table big enough for the biggest step + startpoint=1; + datadim=ndims(self.data); + outdat=nan(findim); + for r=1:rows + curlen = prod(self.sizes(r, :)); + outdat(1:self.sizes(r,1), 1:self.sizes(r,2), r) = reshape(self.data(startpoint:startpoint+ ... + curlen-1),self.sizes(r,:)); + startpoint = startpoint+curlen; + end + + end + end, + else, + %as much scalars as steps (or less) so just one value per step + outdat=self.data; + + end + end + end +end \ No newline at end of file diff --git a/src/m/netcdf/README.txt b/src/m/netcdf/README.txt index 606c5a962..928c7c76a 100644 --- a/src/m/netcdf/README.txt +++ b/src/m/netcdf/README.txt @@ -1,87 +1,114 @@ -The write_netCDF and read_netCDF modules provide a convenient way to save and restore the state of a model class instance -in binary format via NetCDF4. This allows users to store the class state on disk and retrieve it later, facilitating seamless -transitions between Python and MATLAB environments. - -To save a model, call either write_netCDF.py or write_netCDF.m depending on whether your class is in matlab or python. -To read a saved model, call either read_netCDF.py or read_netCDF.m depending on what language you prefer to use the model in. -If you would like to log the names and locations of variables being stored, add the argument verbose = True (verbose = true for matlab). - -Usage Instructions: - - Python: - - Saving a model: - from write_netCDF import write_netCDF - - md = bamg(model(), foo.csv, .01) - - write_netCDF(md, 'adress_to_save/../filename.nc') - - - Reading a model: - from read_netCDF import read_netCDF - - md = read_netCDF('adress_to_file/../filename.nc') - - Verbose examples: - write_netCDF(md, adress_to_save/../filename.nc, verbose = True) - md = read_netCDF(adress_to_file/../filename.nc, verbose = True) - - MATLAB: - - Saving a model: - - write_netCDF(md, adress_to_save/../filename.nc); - - - Reading a model: - - md = read_netCDF(adress_to_file/../filename.nc); - - Verbose examples: - write_netCDF(md, adress_to_save/../filename.nc, verbose = true); - - or: - - write_netCDF(md, adress_to_save/../filename.nc, verbose); - md = read_netCDF(adress_to_file/../filename.nc, verbose = true); - -Dependencies: - Python: - - NumPy - - NetCDF4 / NetCDF4.Dataset - - The model() class - - results.solution / results.solutionstep / results.resultsdakota - - inversion.inversion / inversion.m1qn3inversion / inversion.taoinversion - - MATLAB: - - The model() class - - inversion.inversion / inversion.m1qn3inversion / inversion.taoinversion - - -Additional Information: - -There are currently datatypes that both write_netCDF and read_netCDF modules may not be able to handle. These datatypes might -include lists with multiple datatypes (ie, ['number', 1, 'letter', a, 'color', 'blue']), lists of dicts ect. - -To add functionality for these additional cases, one must simply create a function to handle the case and call it using a -conditional case within the create_var() function. To read the data from the NetCDF4 file, add the case to the -copy_variable_data_to_new_model() function in read_netCDF so that the data can be added to a new model() instance. - -Known issues: - -Unlike Python, MATLAB doesn't utilize subclasses in its model class. This leads to a loss of certain subclass instances. -For instance, the results.solutionstep() class poses a known issue. In MATLAB, there's no direct equivalent. The fields in -'md.results' in MATLAB might correspond to instances of resultsdakota(), solution(), or solutionstep() in Python, but -because those classes don't exist in MATLAB, there is no way for python to know which instance it needs. - -The current workaround, while not theoretically sound, involves searching for the class name string in MATLAB's 'results' -field names. For instance, 'md.results.TransientSolution' is recorded as a solution() class instance. However, problems arise -in cases like 'md.results.StressbalanceSolution', where the code notes a solution() instance, while in Python, it should be a -solutionstep() instance. - -So far, there have been no recorded problems swapping a solutionstep() instance for a solution() instance. - -Potential solutions are: - - - Restructure both Python and MATLAB solve frameworks. In Python, when creating an md.results. instance, - embed 'solutionstep' in the class instance name. - >> This solution is very involved, and would include the tedious modification of >5 files in total - - Create a hash table linking solutions with their corresponding 'md.results.' for reference when saving models to - the netCDF file. +write_netCDF / read_netCDF – Cross-language ISSM model serialisation +====================================================================== + +These four files let you save an ISSM model (md) to NetCDF4 and reload it +in either MATLAB or Python, interchangeably. + + write_netCDF.m – save from MATLAB + read_netCDF.m – load into MATLAB + write_netCDF.py – save from Python + read_netCDF.py – load into Python + +Version: 2.0 + + +USAGE +----- + +Python: + from write_netCDF import write_netCDF + from read_netCDF import read_netCDF + + write_netCDF(md, 'model.nc') + write_netCDF(md, 'model.nc', verbose=True) + + md2 = read_netCDF('model.nc') + md2 = read_netCDF('model.nc', verbose=True) + +MATLAB: + write_netCDF(md, 'model.nc') + write_netCDF(md, 'model.nc', 'verbose', true) + + md2 = read_netCDF('model.nc') + md2 = read_netCDF('model.nc', 'verbose', true) + +Cross-language round-trip: + %% MATLAB → Python + write_netCDF(md, 'model.nc'); % MATLAB + md2 = read_netCDF('model.nc') # Python + + ## Python → MATLAB + write_netCDF(md, 'model.nc') # Python + md2 = read_netCDF('model.nc'); % MATLAB + + +DEPENDENCIES +------------ +Python: numpy, netCDF4, and the ISSM model() class (plus any sub-class + modules that your model uses, e.g. m1qn3inversion, SMBpdd, etc.) +MATLAB: built-in netcdf package (no extra toolboxes required), plus + the ISSM model() class and any sub-class .m files. + + +FILE FORMAT (ISSM-NetCDF-2.0) +------------------------------ +Global attributes: + Conventions = 'ISSM-NetCDF-2.0' + history = creation timestamp + +Layout: + /mesh/ ← group per top-level md field + classtype ← NC_GLOBAL attribute: Python/MATLAB class name + x ← variable + y ← variable + … + /geometry/ + … + /results/ + /TransientSolution/ ← sub-group (classtype='struct') + nsteps ← NC_GLOBAL attribute: number of steps + /step_1/ + Vel ← variable + … + /step_2/ + … + /inversion/ + classtype = 'm1qn3inversion' ← enables correct class reconstruction + … + +Key design decisions: + - Every group carries a 'classtype' global attribute so readers can + reconstruct the exact Python/MATLAB class without heuristics. + - Struct arrays (results.TransientSolution) are stored as step_1 … step_n + sub-groups, one per time step. + - The file is overwritten silently if it already exists (no interactive + prompts – safe for use in scripts and Jupyter notebooks). + - No module-level global state in Python (fully re-entrant; calling + read_netCDF twice returns two independent model objects). + - No MATLAB 'persistent' variable bugs (the old code skipped writing + inversion/smb/friction/hydrology class names on the second call). + + +KNOWN LIMITATIONS +----------------- +- md.qmu is not yet supported (complex OrderedDict-based structure). +- Cell arrays whose elements are themselves struct arrays are not yet + supported. +- MATLAB classes that have no Python equivalent (e.g. SMBgemb) can be + saved from MATLAB and round-tripped back to MATLAB, but the Python + reader will fall back to a plain dict for those fields. +- Very large arrays (> a few GB) work fine thanks to NetCDF4 chunking, + but you may want to increase the zlib compression level in write_netCDF.py + for highly compressible fields. + + +OTHER FILES IN THIS DIRECTORY +------------------------------ +export_netCDF.m / export_netCDF.py + An older, alternative serialisation that stacks results variables by + time dimension rather than using per-step sub-groups. It writes a + different file format and does not have a matching read_netCDF. + Kept for backward compatibility. + +restable.m + Helper used by export_netCDF.m. diff --git a/src/m/netcdf/read_netCDF.m b/src/m/netcdf/read_netCDF.m index 81cca0655..2d85a3d49 100644 --- a/src/m/netcdf/read_netCDF.m +++ b/src/m/netcdf/read_netCDF.m @@ -1,526 +1,478 @@ -%{ -Given a NetCDF4 file, this set of functions will perform the following: - 1. Enter each group of the file. - 2. For each variable in each group, update an empty model with the variable's data - 3. Enter nested groups and repeat - - -If the model you saved has subclass instances that are not in the standard model() class -you can: - 1. Copy lines 30-35, set the "results" string to the name of the subclass instance, - 2. Copy and modify the make_results_subclasses() function to create the new subclass - instances you need. -From there, the rest of this script will automatically create the new subclass -instance in the model you're writing to and store the data from the netcdf file there. -%} - - -function model_copy = read_netCDF(filename, varargin) - if nargin > 1 - verbose = true; +function md = read_netCDF(filename, varargin) +% READ_NETCDF - Load an ISSM model from a NetCDF4 file written by write_netCDF.m or write_netCDF.py. +% +% Usage: +% md = read_netCDF(filename) +% md = read_netCDF(filename, 'verbose', true) +% +% Inputs: +% filename - path to the .nc file +% +% Optional name-value pair: +% 'verbose' - true/false (default false) +% +% Returns: +% md - an ISSM model() object populated from the file + + % --- parse options ------------------------------------------------ + if nargin > 1 && islogical(varargin{1}) + verbose = varargin{1}; + elseif nargin > 1 + p = inputParser(); + p.addParameter('verbose', false, @islogical); + p.parse(varargin{:}); + verbose = p.Results.verbose; else verbose = false; end - + if verbose - fprintf('NetCDF42C v1.1.14\n'); + fprintf('read_netCDF v2.0 (MATLAB)\n'); end - % make a model framework to fill that is in the scope of this file - model_copy = model(); - - % Check if path exists - if exist(filename, 'file') - if verbose - fprintf('Opening %s for reading\n', filename); - end - - % Open the given netCDF4 file - NCData = netcdf.open(filename, 'NOWRITE'); - % Remove masks from netCDF data for easy conversion: NOT WORKING - %netcdf.setMask(NCData, 'NC_NOFILL'); - - % see if results is in there, if it is we have to instantiate some classes - try - results_group_id = netcdf.inqNcid(NCData, "results"); - model_copy = make_results_subclasses(model_copy, NCData, verbose); - catch - end % 'results' group doesn't exist - % see if inversion is in there, if it is we may have to instantiate some classes - try - inversion_group_id = netcdf.inqNcid(NCData, "inversion"); - model_copy = check_inversion_class(model_copy, NCData, verbose); - catch - end % 'inversion' group doesn't exist - - % loop over first layer of groups in netcdf file - for group = netcdf.inqGrps(NCData) - group_id = netcdf.inqNcid(NCData, netcdf.inqGrpName(group)); - %disp(netcdf.inqGrpNameFull(group_id)) - % hand off first level to recursive search - model_copy = walk_nested_groups(group_id, model_copy, NCData, verbose); - end - - % Close the netCDF file - netcdf.close(NCData); - if verbose - disp('Model Successfully Copied') - end - else - fprintf('File %s does not exist.\n', filename); + if ~exist(filename, 'file') + error('read_netCDF: file not found: %s', filename); end -end + % Start with a fully-initialised model + md = model(); -function model_copy = make_results_subclasses(model_copy, NCData, verbose) - resultsGroup = netcdf.inqNcid(NCData, "results"); - variables = netcdf.inqVarIDs(resultsGroup); - for name = variables - class_instance = netcdf.inqVar(resultsGroup, name); - class_instance_names_raw = netcdf.getVar(resultsGroup, name, 'char').'; - class_instance_names = cellstr(class_instance_names_raw); - for index = 1:numel(class_instance_names) - class_instance_name = class_instance_names{index}; - model_copy.results = setfield(model_copy.results, class_instance_name, struct()); - end - %model_copy.results = setfield(model_copy.results, class_instance, class_instance_name); + ncid = netcdf.open(filename, 'NOWRITE'); + try + md = read_all_groups(ncid, md, verbose); + catch ME + netcdf.close(ncid); + rethrow(ME); end - model_copy = model_copy; + netcdf.close(ncid); + if verbose - disp('Successfully recreated results structs:') - for fieldname = string(fieldnames(model_copy.results)) - disp(fieldname) - end + disp('Model successfully loaded from NetCDF4.'); end end +function md = read_all_groups(ncid, md, verbose) % {{{ +% ===================================================================== +% read_all_groups – iterate over every top-level group +% ===================================================================== + top_groups = netcdf.inqGrps(ncid); + for gi = 1:numel(top_groups) + gid = top_groups(gi); + gname = netcdf.inqGrpName(gid); -function model_copy = check_inversion_class(model_copy, NCData, verbose) - % get the name of the inversion class: either inversion or m1qn3inversion or taoinversion - inversionGroup = netcdf.inqNcid(NCData, "inversion"); - varid = netcdf.inqVarID(inversionGroup, 'inversion_class_name'); - inversion_class = convertCharsToStrings(netcdf.getVar(inversionGroup, varid,'char')); - if strcmp(inversion_class, 'm1qn3inversion') - model_copy.inversion = m1qn3inversion(); - if verbose - disp('Successfully created inversion class instance: m1qn3inversion') - end - elseif strcmp(inversion_class, 'taoinversion') - model_copy.inversion = taoinversion(); if verbose - disp('Successfully created inversion class instance: taoinversion') + fprintf(' Reading group: %s\n', gname); end - else - if verbose - disp('No inversion class was found') - end - end - model_copy = model_copy; -end + % Instantiate the right subclass based on the stored classtype attribute + md = instantiate_subclass(md, gname, gid, verbose); -function model_copy = walk_nested_groups(group_location_in_file, model_copy, NCData, verbose) - % we search the current group level for variables by getting this struct - variables = netcdf.inqVarIDs(group_location_in_file); - - % from the variables struct get the info related to the variables - for variable = variables - [varname, xtype, dimids, numatts] = netcdf.inqVar(group_location_in_file, variable); - - % keep an eye out for nested structs: - if strcmp(varname, 'this_is_a_nested') - is_object = true; - model_copy = copy_nested_struct(group_location_in_file, model_copy, NCData, verbose); - elseif strcmp(varname, 'name_of_cell_array') - is_object = true; - model_copy = copy_cell_array_of_objects(variables, group_location_in_file, model_copy, NCData, verbose); - elseif strcmp(varname, 'solution') - % band-aid pass.. - else - if logical(exist('is_object', 'var')) - % already handled - else - model_copy = copy_variable_data_to_new_model(group_location_in_file, varname, xtype, model_copy, NCData, verbose); - end - end + % Now populate all fields + md = read_group_into_model(gid, md, gname, verbose); + end +end % }}} +function md = instantiate_subclass(md, gname, gid, verbose) % {{{ +% ===================================================================== +% instantiate_subclass – create the right class for polymorphic fields +% ===================================================================== + % Read the classtype attribute from this group (written by write_netCDF) + ct = get_group_classtype(gid); + if isempty(ct) + return % no classtype stored, keep existing model default end - % try to find groups in current level, if it doesn't work it's because there is nothing there - %try - % if it's a nested struct the function copy_nested_struct has already been called - if logical(exist('is_object', 'var')) - % do nothing - else - % search for nested groups in the current level to feed back to this function - groups = netcdf.inqGrps(group_location_in_file); - if not(isempty(groups)) - for group = groups - group_id = netcdf.inqNcid(group_location_in_file, netcdf.inqGrpName(group)); - %disp(netcdf.inqGrpNameFull(group_id)) - model_copy = walk_nested_groups(group, model_copy, NCData, verbose); + % Only act for fields whose type can vary at runtime + switch gname + case 'inversion' + switch ct + case 'm1qn3inversion' + md.inversion = m1qn3inversion(); + case 'taoinversion' + md.inversion = taoinversion(); + % 'inversion' is already the default end - end + case 'smb' + md = instantiate_smb(md, ct, verbose); + case 'friction' + md = instantiate_friction(md, ct, verbose); + case 'hydrology' + md = instantiate_hydrology(md, ct, verbose); + case 'mesh' + switch ct + case 'mesh3dprisms' + md.mesh = mesh3dprisms(); + % mesh2d is the default + end + % All other groups keep their default instance; we just overwrite fields + end + if verbose && ~isempty(ct) + fprintf(' classtype = %s\n', ct); end - %catch % no nested groups here - %end end +% }}} +function md = read_group_into_model(gid, md, gname, verbose) % {{{ +% ===================================================================== +% read_group_into_model – populate md. from a NetCDF group +% ===================================================================== + % Skip empty/missing model fields gracefully + try + target = md.(gname); + catch + if verbose + fprintf(' [SKIP] md.%s does not exist in model()\n', gname); + end + return + end + % Read variables at this level + var_ids = netcdf.inqVarIDs(gid); + for vi = 1:numel(var_ids) + varid = var_ids(vi); + vname = netcdf.inqVar(gid, varid); + data = read_variable(gid, varid, verbose); + md.(gname) = set_field(md.(gname), vname, data, verbose); + end -% to read cell arrays with objects: -function model_copy = copy_cell_array_of_objects(variables, group_location_in_file, model_copy, NCData, verbose); - %{ - The structure in netcdf for groups with the name_of_cell_array variable is like: - - group: 2x6_cell_array_of_objects { - name_of_cell_array = - - group: Row_1_of_2 { - group: Col_1_of_6 { - ... other groups can be here that refer to objects - } // group Col_6_of_6 - } // group Row_1_of_2 - - group: Row_2_of_2 { - group: Col_1_of_6 { - ... other groups can be here that refer to objects - } // group Col_6_of_6 - } // group Row_2_of_2 - } // group 2x6_cell_array_of_objects - - We have to navigate this structure to extract all the data and recreate the - original structure when the model was saved - %} - - % get the name_of_cell_array, rows and cols vars - name_of_cell_array_varID = netcdf.inqVarID(group_location_in_file, 'name_of_cell_array'); - rows_varID = netcdf.inqVarID(group_location_in_file, 'rows'); - cols_varID = netcdf.inqVarID(group_location_in_file, 'cols'); - - name_of_cell_array = netcdf.getVar(group_location_in_file, name_of_cell_array_varID).'; % transpose - rows = netcdf.getVar(group_location_in_file, rows_varID); - cols = netcdf.getVar(group_location_in_file, cols_varID); - - % now we work backwards: make the cell array, fill it in, and assign it to the model - - % make the cell array - cell_array_placeholder = cell(rows, cols); - - % get subgroups which are elements of the cell array - subgroups = netcdf.inqGrps(group_location_in_file); % numerical cell array with ID's of subgroups - - % enter each subgroup, get the data, assign it to the corresponding index of cell array - if rows > 1 - % we go over rows - % set index for cell array rows - row_idx = 1; - for row = subgroups - % now columns - columns = netcdf.inqGrps(group_location_in_file); - - % set index for cell array cols - col_idx = 1; - for column = columns - % now variables - current_column_varids = netcdf.inqVarIDs(column); - - % if 'class_is_a' or 'this_is_a_nested' variables is present at this level we have to handle them accordingly - try - class_is_aID = netcdf.inqVarID(column, 'class_is_a'); - col_data = deserialize_class(column, NCData, verbose); - is_object = true; - catch - end - - try - this_is_a_nestedID = netcdf.inqVarID(column, 'this_is_a_nested'); - % functionality not supported - disp('Error: Cell Arrays of structs not yet supported!') - % copy_nested_struct(column, model_copy, NCData, verbose) - is_object = true; - catch - end + % Recurse into subgroups + sub_groups = netcdf.inqGrps(gid); + for si = 1:numel(sub_groups) + sub_gid = sub_groups(si); + sub_name = netcdf.inqGrpName(sub_gid); + ct = get_group_classtype(sub_gid); - if logical(exist('is_object', 'var')) - % already taken care of - else - % store the variables as normal -- to be added later - disp('Error: Cell Arrays of mixed objects not yet supported!') - for var = current_column_varids - % not supported - end - end + if strcmp(ct, 'struct') + % This is a struct array (e.g. results.TransientSolution) + n = get_group_int_att(sub_gid, 'nsteps', 1); + s = read_struct_array(sub_gid, n, verbose); + md.(gname) = set_field(md.(gname), sub_name, s, verbose); - cell_array_placeholder{row_idx, col_idx} = col_data; - col_idx = col_idx + 1; - end - row_idx = row_idx + 1; - end - else - % set index for cell array - col_idx = 1; - for column = subgroups - % now variables - current_column_varids = netcdf.inqVarIDs(column); + elseif strcmp(ct, 'cell_of_objects') + % Cell array of ISSM class instances + c = read_cell_of_objects(sub_gid, verbose); + md.(gname) = set_field(md.(gname), sub_name, c, verbose); - % if 'class_is_a' or 'this_is_a_nested' variables is present at this level we have to handle them accordingly + else + % Regular sub-class: read its variables into the existing sub-object try - classID = netcdf.inqVarID(column, 'class_is_a'); - col_data = deserialize_class(classID, column, NCData, verbose); - is_object = true; - catch ME - rethrow(ME) + sub_obj = md.(gname).(sub_name); + catch + % Field doesn't exist in the default model – create a struct + sub_obj = struct(); end - + + sub_obj = read_subgroup_into_obj(sub_gid, sub_obj, verbose); + md.(gname) = set_field(md.(gname), sub_name, sub_obj, verbose); + end + end +end +% }}} +function obj = read_subgroup_into_obj(gid, obj, verbose) % {{{ +% ===================================================================== +% read_subgroup_into_obj – generic recursive group reader +% ===================================================================== + % Variables + var_ids = netcdf.inqVarIDs(gid); + for vi = 1:numel(var_ids) + varid = var_ids(vi); + vname = netcdf.inqVar(gid, varid); + data = read_variable(gid, varid, verbose); + obj = set_field(obj, vname, data, verbose); + end + + % Child subgroups + sub_groups = netcdf.inqGrps(gid); + for si = 1:numel(sub_groups) + sub_gid = sub_groups(si); + sub_name = netcdf.inqGrpName(sub_gid); + ct = get_group_classtype(sub_gid); + + if strcmp(ct, 'struct') + n = get_group_int_att(sub_gid, 'nsteps', 1); + s = read_struct_array(sub_gid, n, verbose); + obj = set_field(obj, sub_name, s, verbose); + elseif strcmp(ct, 'cell_of_objects') + c = read_cell_of_objects(sub_gid, verbose); + obj = set_field(obj, sub_name, c, verbose); + else + % Try to get existing sub-object, fall back to empty struct try - this_is_a_nestedID = netcdf.inqVarID(column, 'this_is_a_nested'); - % functionality not supported - disp('Error: Cell Arrays of structs not yet supported!') - % col_data = copy_nested_struct(column, model_copy, NCData, verbose); - is_object = true; + sub_obj = obj.(sub_name); catch + sub_obj = struct(); end - if logical(exist('is_object', 'var')) - % already taken care of - else - % store the variables as normal -- to be added later - disp('Error: Cell Arrays of mixed objects not yet supported!') - for var = current_column_varids - % col_data = not supported - end - end - - cell_array_placeholder{col_idx} = col_data; - col_idx = col_idx + 1; + sub_obj = read_subgroup_into_obj(sub_gid, sub_obj, verbose); + obj = set_field(obj, sub_name, sub_obj, verbose); + end + end +end % }}} +function s = read_struct_array(gid, n, verbose) % {{{ +% ===================================================================== +% read_struct_array – reconstruct a 1×n struct array from step_k groups +% ===================================================================== + % Gather all step subgroups (step_1, step_2, …) + step_groups = netcdf.inqGrps(gid); + if isempty(step_groups) + s = struct(); + return + end - end + % Collect all field names from the first step + first_gid = step_groups(1); + first_varids = netcdf.inqVarIDs(first_gid); + fnames = {}; + for vi = 1:numel(first_varids) + fnames{end+1} = netcdf.inqVar(first_gid, first_varids(vi)); %#ok end - - % Like in copy_nested_struct, we can only handle things 1 layer deep. - % assign cell array to model - address_to_attr_list = split(netcdf.inqGrpNameFull(group_location_in_file), '/'); - address_to_attr = address_to_attr_list{2}; - if isprop(model_copy.(address_to_attr), name_of_cell_array); - model_copy.(address_to_attr).(name_of_cell_array) = cell_array_placeholder; + % Pre-allocate struct array + if ~isempty(fnames) + args = [fnames; repmat({[]}, 1, numel(fnames))]; + s = repmat(struct(args{:}), 1, numel(step_groups)); else - model_copy = addprop(model_copy.(address_to_attr), name_of_cell_array, cell_array_placeholder); + s = repmat(struct(), 1, numel(step_groups)); end + for ki = 1:numel(step_groups) + step_gid = step_groups(ki); + var_ids = netcdf.inqVarIDs(step_gid); + for vi = 1:numel(var_ids) + varid = var_ids(vi); + vname = netcdf.inqVar(step_gid, varid); + data = read_variable(step_gid, varid, verbose); + s(ki).(vname) = data; + end + % Recurse into any sub-subgroups (rare but possible) + sub_grps = netcdf.inqGrps(step_gid); + for si = 1:numel(sub_grps) + sg_name = netcdf.inqGrpName(sub_grps(si)); + sub_obj = read_subgroup_into_obj(sub_grps(si), struct(), verbose); + s(ki).(sg_name) = sub_obj; + end + end if verbose - fprintf("Successfully loaded cell array %s to %s\n", name_of_cell_array,address_to_attr_list{2}) + fprintf(' [struct] loaded 1x%d struct array\n', numel(step_groups)); end -end - - - - -function output = deserialize_class(classID, group, NCData, verbose) - %{ - This function will recreate a class - %} - - % get the name of the class - name = netcdf.getVar(group, classID).'; +end % }}} +function c = read_cell_of_objects(gid, verbose) % {{{ +% ===================================================================== +% read_cell_of_objects – reconstruct a cell array of ISSM objects +% ===================================================================== + nrows = get_group_int_att(gid, 'nrows', 1); + ncols = get_group_int_att(gid, 'ncols', 1); + c = cell(nrows, ncols); + + item_groups = netcdf.inqGrps(gid); + for gi = 1:numel(item_groups) + ig = item_groups(gi); + name = netcdf.inqGrpName(ig); % e.g. 'item_1_3' + ct = get_group_classtype(ig); + + % Parse row/col from name + tok = regexp(name, '^item_(\d+)_(\d+)$', 'tokens'); + if isempty(tok) + continue + end + r = str2double(tok{1}{1}); + col_idx = str2double(tok{1}{2}); - % instantiate it - class_instance = eval([name, '()']); + % Instantiate the object + try + obj = eval([ct '()']); + catch + obj = struct(); + end + obj = read_subgroup_into_obj(ig, obj, verbose); + c{r, col_idx} = obj; + end + if verbose + fprintf(' [cell] loaded %dx%d cell of objects\n', nrows, ncols); + end +end % }}} +function data = read_variable(gid, varid, verbose) % {{{ +% ===================================================================== +% read_variable – read one NetCDF variable and convert to MATLAB type +% ===================================================================== + [~, xtype, dimids, ~] = netcdf.inqVar(gid, varid); + + % Get type_is attribute if present + type_is = ''; + try + type_is = netcdf.getAtt(gid, varid, 'type_is'); + catch + end - % get and assign properties - subgroups = netcdf.inqGrps(group); % numerical cell array with ID's of subgroups + raw = netcdf.getVar(gid, varid); - if numel(subgroups) == 1 - % get properties - varIDs = netcdf.inqVarIDs(subgroups); - for varID = varIDs - % var metadata - [varname, xtype, dimids, numatts] = netcdf.inqVar(subgroups, varID); - % data - data = netcdf.getVar(subgroups, varID); + % Empty / NaN sentinel + if strcmp(type_is, 'empty') + data = []; + return + end - % netcdf uses Row Major Order but MATLAB uses Column Major Order so we need to transpose all arrays w/ more than 1 dim - if all(size(data)~=1) || xtype == 2 - data = data.'; - end + % Bool + if strcmp(type_is, 'bool') + data = logical(raw); + return + end - % some classes have permissions... so we skip those - try - % if property already exists, assign new value - if isprop(class_instance, varname) - class_instance.(varname) = data; - else - addprop(class_instance, varname, data); - end - catch - end + % String + if strcmp(type_is, 'string') || xtype == 2 % NC_CHAR = 2 + if strcmp(type_is, 'cell_of_strings') + % char matrix → cell array of strings (trim trailing spaces) + data = cellstr(raw.'); + else + data = char(raw.'); end - else - % not supported + return end - output = class_instance; -end + % Cell of strings (attribute check) + if strcmp(type_is, 'cell_of_strings') + data = cellstr(raw.'); + return + end -function model_copy = copy_nested_struct(group_location_in_file, model_copy, NCData, verbose) - %{ - A common multidimensional struct array is the 1xn md.results.TransientSolution struct. - The process to recreate is as follows: - 1. Get the name of the struct from group name - 2. Get the fieldnames from the subgroups - 3. Recreate the struct with fieldnames - 4. Populate the fields with their respective values - %} - - % step 1 - name_of_struct = netcdf.inqGrpName(group_location_in_file); - - % step 2 - subgroups = netcdf.inqGrps(group_location_in_file); % numerical cell array with ID's of subgroups - % get single subgroup's data - single_subgroup_ID = subgroups(1); - subgroup_varids = netcdf.inqVarIDs(single_subgroup_ID); - fieldnames = {}; - for variable = subgroup_varids - [varname, xtype, dimids, numatts] = netcdf.inqVar(single_subgroup_ID, variable); - fieldnames{end+1} = varname; - end - - % step 3 - address_in_model_raw = split(netcdf.inqGrpNameFull(group_location_in_file), '/'); - address_in_model = address_in_model_raw{2}; - - % we cannot assign a variable to represent this object as MATLAB treats all variables as copies - % and not pointers to the same memory address - % this means that if address_in_model has more than 1 layer, we need to modify the code. For now, - % we just hope this will do. An example of a no-solution would be model().abc.def.ghi.field whereas we're only assuming model().abc.field now - - model_copy.(address_in_model).(name_of_struct) = struct(); - % for every fieldname in the subgroup, create an empty field - for fieldname = string(fieldnames) - model_copy.(address_in_model).(name_of_struct).(fieldname) = {}; - end - - % use repmat to make the struct array multidimensional along the fields axis - number_of_dimensions = numel(subgroups); - model_copy.(address_in_model).(name_of_struct) = repmat(model_copy.(address_in_model).(name_of_struct), 1, number_of_dimensions); - - % step 4 - % for every layer of the multidimensional struct array, populate the fields - for current_layer = 1:number_of_dimensions - % choose subgroup - current_layer_subgroup_ID = subgroups(current_layer); - % get all vars - current_layer_subgroup_varids = netcdf.inqVarIDs(current_layer_subgroup_ID); - % get individual vars and set fields at layer current_layer - for varid = current_layer_subgroup_varids - [varname, xtype, dimids, numatts] = netcdf.inqVar(current_layer_subgroup_ID, varid); - data = netcdf.getVar(current_layer_subgroup_ID, varid); - - % netcdf uses Row Major Order but MATLAB uses Column Major Order so we need to transpose all arrays w/ more than 1 dim - if all(size(data)~=1) || xtype == 2 - data = data.'; + % Numeric: NetCDF is row-major, MATLAB is column-major → transpose 2-D arrays + data = double(raw); + if ndims(data) == 2 && ~any(size(data) == 1) + data = data.'; + elseif iscolumn(data) + % keep as column vector (MATLAB convention) + end +end % }}} +function obj = set_field(obj, fname, data, verbose) % {{{ +% ===================================================================== +% set_field – safely set a field on either a class or struct +% ===================================================================== + try + if isstruct(obj) + obj.(fname) = data; + elseif isobject(obj) + if isprop(obj, fname) || isfield(obj, fname) + obj.(fname) = data; + else + % Property not in the default class – try dynamic property + try + obj.(fname) = data; + catch + if verbose + fprintf(' [SKIP] cannot set property %s on %s\n', fname, class(obj)); + end + end end - - % set the field - model_copy.(address_in_model).(name_of_struct)(current_layer).(varname) = data; - %address_to_struct_in_model = setfield(address_to_struct_in_model(current_layer), varname, data) end - model_copy.(address_in_model).(name_of_struct)(current_layer); + catch ME if verbose - fprintf("Successfully loaded layer %s to multidimension struct array\n", num2str(current_layer)) + fprintf(' [WARN] set_field failed for %s: %s\n', fname, ME.message); end end - model_copy = model_copy; - if verbose - fprintf('Successfully recreated multidimensional structure array %s in md.%s\n', name_of_struct, address_in_model) - end end - - - - -%{ -Since there are two types of objects that MATLAB uses (classes and structs), we have to check -which object we're working with before we can set any fields/attributes of it. After this is completed, -we can write the data to that location in the model. -%} - -function model_copy = copy_variable_data_to_new_model(group_location_in_file, varname, xtype, model_copy, NCData, verbose) - %disp(varname) - % this is an inversion band-aid - if strcmp(varname, 'inversion_class_name') || strcmp(varname, 'name_of_struct') || strcmp(varname, 'solution') - % we don't need this - else - % putting try/catch here so that any errors generated while copying data are logged and not lost by the try/catch in walk_nested_groups function - try - %disp(netcdf.inqGrpNameFull(group_location_in_file)) - %disp(class(netcdf.inqGrpNameFull(group_location_in_file))) - address_to_attr = strrep(netcdf.inqGrpNameFull(group_location_in_file), '/', '.'); - varid = netcdf.inqVarID(group_location_in_file, varname); - data = netcdf.getVar(group_location_in_file, varid); - - - % if we have an empty string - if xtype == 2 && isempty(all(data)) - data = cell(char()); - % if we have an empty cell-char array - elseif numel(data) == 1 && xtype == 3 && data == -32767 - data = cell(char()); - elseif isempty(all(data)) - data = [] +% }}} +function md = instantiate_smb(md, ct, verbose) % {{{ +% ===================================================================== +% Subclass instantiation helpers +% ===================================================================== + switch ct + case 'SMBforcing', md.smb = SMBforcing(); + case 'SMBpdd', md.smb = SMBpdd(); + case 'SMBd18opdd', md.smb = SMBd18opdd(); + case 'SMBgradients', md.smb = SMBgradients(); + case 'SMBcomponents', md.smb = SMBcomponents(); + case 'SMBmeltcomponents', md.smb = SMBmeltcomponents(); + case 'SMBgradientscomponents' + if exist('SMBgradientscomponents','class') + md.smb = SMBgradientscomponents(); end - % band-aid for some cell-char-arrays: - if xtype == 2 && strcmp(data, 'default') - data = {'default'}; + case 'SMBgradientsela' + if exist('SMBgradientsela','class') + md.smb = SMBgradientsela(); end - - % netcdf uses Row Major Order but MATLAB uses Column Major Order so we need to transpose all arrays w/ more than 1 dim - if all(size(data)~=1) || xtype == 2 - data = data.'; + case 'SMBhenning' + if exist('SMBhenning','class') + md.smb = SMBhenning(); end - - % if we have a list of strings - if xtype == 2 - try - if strcmp(netcdf.getAtt(group_location_in_file, varid, "type_is"), 'cell_array_of_strings') - data = cellstr(data); - end - catch - % no attr found so we pass - end + case 'SMBgemb' + if exist('SMBgemb','class') + md.smb = SMBgemb(); end - - % the issm c compiler does not work with int64 datatypes, so we need to convert those to int16 - % reference this (very hard to find) link for netcdf4 datatypes: https://docs.unidata.ucar.edu/netcdf-c/current/netcdf_8h_source.html - %xtype - if xtype == 10 - arg_to_eval = ['model_copy', address_to_attr, '.', varname, ' = ' , 'double(data);']; - eval(arg_to_eval); - %disp('Loaded int64 as int16') - else - arg_to_eval = ['model_copy', address_to_attr, '.', varname, ' = data;']; - eval(arg_to_eval); + case 'SMBpddSicopolis' + if exist('SMBpddSicopolis','class') + md.smb = SMBpddSicopolis(); end - + case 'SMBsemic' + if exist('SMBsemic','class') + md.smb = SMBsemic(); + end + case 'SMBdebrisEvatt' + if exist('SMBdebrisEvatt','class') + md.smb = SMBdebrisEvatt(); + end + otherwise if verbose - full_addy = netcdf.inqGrpNameFull(group_location_in_file); - %disp(xtype) - %class(data) - fprintf('Successfully loaded %s to %s\n', varname, full_addy); + fprintf(' [WARN] unknown SMB class: %s\n', ct); end - - catch ME %ME is an MException struct - % Some error occurred if you get here. - fprintf(1,'There was an error with %s! \n', varname) - errorMessage = sprintf('Error in function %s() at line %d.\n\nError Message:\n%s', ME.stack.name, ME.stack.line, ME.message); - fprintf(1, '%s\n', errorMessage); - uiwait(warndlg(errorMessage)); - %line = ME.stack.line - %fprintf(1,'There was an error with %s! \n', varname) - %fprintf('The message was:\n%s\n',ME.message); - %fprintf(1,'The identifier was:\n%s\n',ME.identifier); - - % more error handling... - end end - model_copy = model_copy; +end % }}} +function md = instantiate_friction(md, ct, verbose) % {{{ + switch ct + case 'friction', md.friction = friction(); + case 'frictioncoulomb', md.friction = frictioncoulomb(); + case 'frictioncoulomb2', md.friction = frictioncoulomb2(); + case 'frictionhydro', md.friction = frictionhydro(); + case 'frictionjosh', md.friction = frictionjosh(); + case 'frictionpism', md.friction = frictionpism(); + case 'frictionregcoulomb', md.friction = frictionregcoulomb(); + case 'frictionregcoulomb2', md.friction = frictionregcoulomb2(); + case 'frictionschoof', md.friction = frictionschoof(); + case 'frictionshakti', md.friction = frictionshakti(); + case 'frictiontsai', md.friction = frictiontsai(); + case 'frictionwaterlayer', md.friction = frictionwaterlayer(); + case 'frictionweertman', md.friction = frictionweertman(); + case 'frictionweertmantemp', md.friction = frictionweertmantemp(); + otherwise + if verbose + fprintf(' [WARN] unknown friction class: %s\n', ct); + end + end +end +% }}} +function md = instantiate_hydrology(md, ct, verbose) % {{{ + switch ct + case 'hydrologyshreve', md.hydrology = hydrologyshreve(); + case 'hydrologydc', md.hydrology = hydrologydc(); + case 'hydrologyglads', md.hydrology = hydrologyglads(); + case 'hydrologypism', md.hydrology = hydrologypism(); + case 'hydrologyshakti', md.hydrology = hydrologyshakti(); + case 'hydrologytws' + if exist('hydrologytws','class') + md.hydrology = hydrologytws(); + end + case 'hydrologyarmapw' + if exist('hydrologyarmapw','class') + md.hydrology = hydrologyarmapw(); + end + otherwise + if verbose + fprintf(' [WARN] unknown hydrology class: %s\n', ct); + end + end +end % }}} +function ct = get_group_classtype(gid) % {{{ +% ===================================================================== +% Utility helpers +% ===================================================================== + ct = ''; + try + ct = netcdf.getAtt(gid, netcdf.getConstant('NC_GLOBAL'), 'classtype'); + catch + end +end +% }}} +function val = get_group_int_att(gid, att_name, default_val) % {{{ + try + val = double(netcdf.getAtt(gid, netcdf.getConstant('NC_GLOBAL'), att_name)); + catch + val = default_val; + end end +% }}} diff --git a/src/m/netcdf/read_netCDF.py b/src/m/netcdf/read_netCDF.py index f2d5001ca..a59f56c45 100644 --- a/src/m/netcdf/read_netCDF.py +++ b/src/m/netcdf/read_netCDF.py @@ -1,679 +1,501 @@ -# imports -from netCDF4 import Dataset -import numpy as np -import numpy.ma as ma -from os import path, remove -from model import * -import re -from results import * -from m1qn3inversion import m1qn3inversion -from taoinversion import taoinversion -from collections import OrderedDict -import sys -from massfluxatgate import massfluxatgate +""" +read_netCDF – Load an ISSM model from a NetCDF4 file written by + write_netCDF.py (Python) or write_netCDF.m (MATLAB). +Usage +----- + from read_netCDF import read_netCDF + md = read_netCDF('model.nc') + md = read_netCDF('model.nc', verbose=True) +Every call returns an independent model() instance (fully re-entrant, +no module-level global state). +""" -''' -Given a NetCDF4 file, this set of functions will perform the following: - 1. Enter each group of the file. - 2. For each variable in each group, update an empty model with the variable's data - 3. Enter nested groups and repeat -''' +import sys +from collections import OrderedDict +import numpy as np +from netCDF4 import Dataset +from model import model +from results import results, solution, solutionstep +from toolkits import toolkits -# make a model framework to fill that is in the scope of this file -model_copy = model() -# make a blank requested output for hydrology -hydro_rout_list = ['default'] +# --------------------------------------------------------------------------- +# Public entry point +# --------------------------------------------------------------------------- -def read_netCDF(filename, verbose = False): +def read_netCDF(filename: str, verbose: bool = False): + """Read *filename* and return a populated ISSM model object.""" if verbose: - print('NetCDF42C v1.2.0') + print('read_netCDF v2.0 (Python)') - ''' - filename = path and name to save file under - verbose = T/F = show or muted log statements. Naturally muted - ''' + from os.path import exists + if not exists(filename): + raise FileNotFoundError(f'read_netCDF: file not found: {filename}') - # this is a precaution so that data is not lost + md = model() + + nc = Dataset(filename, 'r') + nc.set_auto_mask(False) try: - # check if path exists - if path.exists(filename): - if verbose: - print('Opening {} for reading'.format(filename)) - else: pass - - # open the given netCDF4 file - NCData = Dataset(filename, 'r') - # remove masks from numpy arrays for easy conversion - NCData.set_auto_mask(False) - else: - return 'The file you entered does not exist or cannot be found in the current directory' - - # in order to handle some subclasses in the results class, we have to utilize this band-aid - # there will likely be more band-aids added unless a class name library is created with all class names that might be added to a md - try: - # if results has meaningful data, save the name of the subclass and class instance - NCData.groups['results'] - make_results_subclasses(NCData, verbose) - except: - pass - - # similarly, we need to check and see if we have an m1qn3inversion class instance - try: - NCData.groups['inversion'] - check_inversion_class(NCData, verbose) - except: - pass - - # check the smb class used - try: - NCData.groups['smb'] - check_smb_class(NCData, verbose) - except: - pass - - # check the friction class used - try: - NCData.groups['friction'] - check_friction_class(NCData, verbose) - except: - pass - - # check the hydrology class used + md = _read_all_groups(nc, md, verbose) + finally: + nc.close() + + if verbose: + print('Model successfully loaded from NetCDF4.') + return md + + +# --------------------------------------------------------------------------- +# Top-level group walk +# --------------------------------------------------------------------------- + +def _read_all_groups(nc, md, verbose: bool): + for gname, grp in nc.groups.items(): + if verbose: + print(f' Reading group: {gname}') + + ct = _get_classtype(grp) + + # results group: walk solution sub-groups and build results()/solution() objects + if gname == 'results': + md.results = _read_results_group(grp, verbose) + continue + + # toolkits group: each analysis sub-group holds an OrderedDict of solver options + if gname == 'toolkits': + md.toolkits = _read_toolkits_group(grp, verbose) + continue + + # Instantiate the correct sub-class for polymorphic model fields + md = _instantiate_subclass(md, gname, ct, verbose) + + # Populate all fields try: - NCData.groups['hydrology'] - hydro_rout_list = check_hydrology_class(NCData, verbose) - except: - pass - - - - # walk through each group looking for subgroups and variables - for group in NCData.groups.keys(): - if 'debris' in group: - pass + target = getattr(md, gname) + except AttributeError: + if verbose: + print(f' [SKIP] md.{gname} does not exist in model()') + continue + + target = _read_group_into_obj(grp, target, verbose) + setattr(md, gname, target) + + return md + + +# --------------------------------------------------------------------------- +# Results group reader – builds results() / solution() / solutionstep() +# --------------------------------------------------------------------------- + +def _read_results_group(grp, verbose: bool): + """Reconstruct md.results as a proper results()/solution()/solutionstep() + hierarchy, matching what loadresultsfromdisk produces.""" + res = results() + + for sol_name, sol_grp in grp.groups.items(): + ct = _get_classtype(sol_grp) + + if ct == 'struct': + # Each step_k sub-group → one solutionstep + steps = [] + for sg_name in sorted(sol_grp.groups.keys(), + key=lambda n: int(n.split('_')[-1]) + if n.startswith('step_') else 0): + sg = sol_grp.groups[sg_name] + step = solutionstep() + for vname, var in sg.variables.items(): + setattr(step, vname, _read_variable(sg, vname, var, verbose)) + # Recurse into any nested groups within a step (rare) + for sub_name, sub_sg in sg.groups.items(): + setattr(step, sub_name, _read_group_into_obj(sub_sg, {}, verbose)) + steps.append(step) + + if not steps: + # Empty struct – store as empty solution + setattr(res, sol_name, solution([])) + elif len(steps) == 1 and sol_name != 'TransientSolution': + # Single-step non-transient: store the solutionstep directly, + # wrapped in a solution so attribute access still works + sol_obj = solution(steps) + setattr(res, sol_name, sol_obj) else: - # have to send a custom name to this function: filename.groups['group'] - name = "NCData.groups['" + str(group) + "']" - walk_nested_groups(name, NCData, verbose) - model_copy.hydrology.requested_outputs = hydro_rout_list - - if verbose: - print("Model Successfully Loaded.") - - NCData.close() - - return model_copy + setattr(res, sol_name, solution(steps)) - # just in case something unexpected happens - except Exception as e: - if 'NCData' in locals(): - NCData.close() - raise e - -def make_results_subclasses(NCData, verbose = False): - ''' - There are 3 possible subclasses: solution, solutionstep, resultsdakota. - In the NetCDF file these are saved as a list of strings. Ie, say there are 2 - instances of solution under results, StressbalanceSolution and TransientSolution. - In the NetCDF file we would see solution = "StressbalanceSolution", "TransientSolution" - To deconstruct this, we need to iteratively assign md.results.StressbalanceSolution = solution() - and md.results.TransientSolution = solution() and whatever else. - ''' - # start with the subclasses - for subclass in NCData.groups['results'].variables.keys(): - class_instance = subclass + '()' - - # now handle the instances - for instance in NCData.groups['results'].variables[subclass][:]: - # this is an ndarray of numpy bytes_ that we have to convert to strings - class_instance_name = instance.tobytes().decode('utf-8').strip() - # from here we can make new subclasses named as they were in the model saved - setattr(model_copy.results, class_instance_name, eval(class_instance)) if verbose: - print(f'Successfully created results subclass instance {class_instance} named {class_instance_name}.') + print(f' [results] {sol_name}: {len(steps)}-step solution') + else: + # Unexpected sub-group inside results – fall back to dict + if verbose: + print(f' [results] {sol_name}: unrecognised classtype "{ct}", stored as dict') + setattr(res, sol_name, _read_group_into_obj(sol_grp, {}, verbose)) + return res -def check_inversion_class(NCData, verbose = False): - # get the name of the inversion class: either inversion or m1qn3inversion or taoinversion - inversion_class_is = NCData.groups['inversion'].variables['inversion_class_name'][:][...].tobytes().decode() - if inversion_class_is == 'm1qn3inversion': - # if it is m1qn3inversion we need to instantiate that class since it's not native to model() - model_copy.inversion = m1qn3inversion(model_copy.inversion) - if verbose: - print('Conversion successful') - elif inversion_class_is == 'taoinversion': - # if it is taoinversion we need to instantiate that class since it's not native to model() - model_copy.inversion = taoinverion() - if verbose: - print('Conversion successful') - else: pass - -def check_smb_class(NCData, verbose = False): - # get the name of the smb class, either: SMBforcing, SMB, SMBcomponents, SMBd18opdd, - # SMBdebrisEvatt, SMBgemb, SMBgradients, SMBgradientscomponents, SMBgradientsela, - # SMBhenning, SMBmeltcomponents, SMBpdd, SMBpddSicopolis, or SMBsemic - # - # Note: SMB, SMBdebrisEvatt, SMBgemb, SMBgradientscomponents, SMBgradientsela, SMBhenning, - # SMBpddSicopolis, and SMBsemic do not have python versions as of yet - smb_class_is = NCData.groups['smb'].variables['smb_class_name'][:][...].tobytes().decode() - if smb_class_is == 'SMBforcing': - # if it is SMBforcing there is no real need to do anything since that is the default, - # but I have done it anyway to match everything else - model_copy.smb = SMBforcing() - if verbose: - print('Conversion successful') - elif smb_class_is == 'SMBcomponents': - # if it is SMBcomponents load the SMBcomponents module - model_copy.smb = SMBcomponents() - if verbose: - print('Conversion successful') - elif smb_class_is == 'SMBd18opdd': - # if it is SMBd18opdd load the SMBd18opdd module - model_copy.smb = SMBd18opdd() - if verbose: - print('Conversion successful') - elif smb_class_is == 'SMBgradients': - # if it is SMBgradients load the SMBgradients module - model_copy.smb = SMBgradients() - if verbose: - print('Conversion successful') - elif smb_class_is == 'SMBmeltcomponents': - # you guessed it! if it is the SMBmeltcomponents module, load SMBmeltcomponents - model_copy.smb = SMBmeltcomponents() - if verbose: - print('Conversion successful') - elif smb_class_is == 'SMBpdd': - # one more for luck: if it is SMBpdd, load SMBpdd - model_copy.smb = SMBpdd() - if verbose: - print('Conversion successful') - else: - print('Conversion unsuccessful, SMB requested is not yet in Python!') - pass - -def check_friction_class(NCData, verbose = False): - # get the name of the friction class, either: friction(default), frictioncoulomb, frictioncoulomb2, - # frictionhydro, frictionjosh, frictionpism, frictionregcoulomb, frictionregcoulomb2,frictionschoof, - # frictionshakti, frictiontemp, frictiontsai, frictionwaterlayer, frictionweertman, or frictionweertmantemp - # - # Note: frictionregcoulomb, frictionregcoulomb, frictiontemp, frictiontsai, and frictionweertmantemp either - # are not present or tripped an error - friction_class_is = NCData.groups['friction'].variables['friction_class_name'][:][...].tobytes().decode() - if friction_class_is == 'friction': - # if it is friction, load friction (the default) - model_copy.friction = friction() - if verbose: - print('Conversion successful') - elif friction_class_is == 'frictioncoulomb': - # if it is frictioncoulomb, import the module, load frictioncoulomb - from frictioncoulomb import frictioncoulomb - model_copy.friction = frictioncoulomb() - if verbose: - print('Conversion successful') - elif friction_class_is == 'frictioncoulomb2': - # if it is frictioncoulomb2, import the module, load frictioncoulomb2 - from frictioncoulomb2 import frictioncoulomb2 - model_copy.friction = frictioncoulomb2() - if verbose: - print('Conversion successful') - elif friction_class_is == 'frictionhydro': - # if it is frictionhydro, import the module, load frictionhydro - from frictionhydro import frictionhydro - model_copy.friction = frictionhydro() - if verbose: - print('Conversion successful') - elif friction_class_is == 'frictionjosh': - # if it is frictionjosh, import the module, load frictionjosh - from frictionjosh import frictionjosh - model_copy.friction = frictionjosh() - if verbose: - print('Conversion successful') - elif friction_class_is == 'frictionpism': - # if it is frictionpism, import the module, load frictionpism - from frictionpism import frictionpism - model_copy.friction = frictionpism() - if verbose: - print('Conversion successful') - elif friction_class_is == 'frictionschoof': - # if it is frictionschoof, import the module, load frictionschoof - from frictionschoof import frictionschoof - model_copy.friction = frictionschoof() - if verbose: - print('Conversion successful') - elif friction_class_is == 'frictionshakti': - #if it is frictionshakti, import the module, load frictionshakti - from frictionshakti import frictionshakti - model_copy.friction = frictionshakti() - if verbose: - print('Conversion successful') - elif friction_class_is == 'frictionwaterlayer': - #if it is frictionwaterlayer, import the module, load frictionwaterlayer - from frictionwaterlayer import frictionwaterlayer - model_copy.friction = frictionwaterlayer() - if verbose: - print('Conversion successful') - elif friction_class_is == 'frictionweertman': - #if it is frictionweertman, import the module, load frictionweertman - from frictionweertman import frictionweertman - model_copy.friction = frictionweertman() - if verbose: - print('Conversion successful') - else: - print('Conversion unsuccessful, friction requested is not present and/or working yet in Python!') - pass - -def check_hydrology_class(NCData, verbose = False): - # get the name of the hydrology class, either: hydrologyshreve (default), hydrology, hydrologyarmapw, - # hydrologydc, hydrologyglads, hydrologypism, hydrologyshakti, hydrologtws - # - # Note: hydrology, hydrologyarmapw, hydrologytws do not have a python implementation - hydrology_class_is = NCData.groups['hydrology'].variables['hydrology_class_name'][:][...].tobytes().decode() - hydro_rout = NCData.groups['hydrology'].variables['requested_outputs'][:][...].tobytes().decode() - hydro_rout_list = hydro_rout.split() - model_copy.hydrology.requested_outputs = hydro_rout_list - if hydrology_class_is == 'hydrologyshreve': - #if it is hydrologyshreve, load hydrologyshreve - model_copy.hydrology = hydrologyshreve() - if verbose: - print('Conversion successful') - elif hydrology_class_is == 'hydrologydc': - #if it is hydrologydc, load hydrologydc - model_copy.hydrology = hydrologydc() - if verbose: - print('Conversion successful') - elif hydrology_class_is == 'hydrologyglads': - #if it is hydrologyglads, load hydrologyglads - model_copy.hydrology = hydrologyglads() - if verbose: - print('Conversion successful') - elif hydrology_class_is == 'hydrologypism': - #if it is hydrologypism, load hydrologypism - model_copy.hydrology = hydrologypism() - if verbose: - print('Conversion successful') - elif hydrology_class_is == 'hydrologyshakti': - #if it is hydrologyshakti, load hydrologyshakti - model_copy.hydrology = hydrologyshakti() - if verbose: - print('Conversion successful') - else: - print('Conversion unsuccessful, hydrology requested is not present and/or working yet in Python!') - pass - return hydro_rout_list - -def walk_nested_groups(group_location_in_file, NCData, verbose = False): - # first, we enter the group by: filename.groups['group_name'] - # second we search the current level for variables: filename.groups['group_name'].variables.keys() - # at this step we check for multidimensional structure arrays/ arrays of objects and filter them out - # third we get nested group keys by: filename.groups['group_name'].groups.keys() - # if a nested groups exist, repeat all - - for variable in eval(group_location_in_file + '.variables.keys()'): - if 'is_object' not in locals(): - if variable == 'this_is_a_nested' and 'results' in group_location_in_file and 'qmu' not in group_location_in_file: - # have to do some string deconstruction to get the name of the class instance/last group from 'NetCDF.groups['group1'].groups['group1.1']' - pattern = r"\['(.*?)'\]" - matches = re.findall(pattern, group_location_in_file) - name_of_struct = matches[-1] #eval(group_location_in_file + ".variables['solution']") - deserialize_nested_results_struct(group_location_in_file, name_of_struct, NCData) - is_object = True - - elif variable == 'name_of_cell_array': - # reconstruct an array of elements - deserialize_array_of_objects(group_location_in_file, model_copy, NCData, verbose) - is_object = True - - elif variable == 'this_is_a_nested' and 'qmu' in group_location_in_file: - if verbose: - print('encountered qmu structure that is not yet supported.') - else: pass - - is_object = True - - else: - location_of_variable_in_file = group_location_in_file + ".variables['" + str(variable) + "']" - # group_location_in_file is like filename.groups['group1'].groups['group1.1'].groups['group1.1.1'] - # Define the regex pattern to match the groups within brackets - pattern = r"\['(.*?)'\]" - # Use regex to find all matches and return something like 'group1.group1.1.group1.1.1 ...' where the last value is the name of the variable - matches = re.findall(pattern, location_of_variable_in_file) - variable_name = matches[-1] - location_of_variable_in_model = '.'.join(matches[:-1]) - deserialize_data(location_of_variable_in_file, location_of_variable_in_model, variable_name, NCData, verbose=verbose) - - # if one of the variables above was an object, further subclasses will be taken care of when reconstructing it - if 'is_object' in locals(): - pass - else: - for nested_group in eval(group_location_in_file + '.groups.keys()'): - new_nested_group = group_location_in_file + ".groups['" + str(nested_group) + "']" - walk_nested_groups(new_nested_group, NCData, verbose=verbose) - - - -''' - MATLAB has Multidimensional Structure Arrays in 2 known classes: results and qmu. - The python classes results.py and qmu.py emulate this MATLAB object in their own - unique ways. The functions in this script will assign data to either of these - classes such that the final structure is compatible with its parent class. -''' - -def deserialize_nested_results_struct(group_location_in_file, name_of_struct, NCData, verbose = False): - ''' - A common multidimensional array is the 1xn md.results.TransientSolution object. - - The way that this object emulates the MATLAB mutli-dim. struct. array is with - the solution().steps attr. which is a list of solutionstep() instances - The process to recreate is as follows: - 1. Get instance of solution() with solution variable (the instance is made in make_results_subclasses) - 2. For each subgroup, create a solutionstep() class instance - 2a. Populate the instance with the key:value pairs - 2b. Append the instance to the solution().steps list - ''' - # step 1 - class_instance_name = name_of_struct - - # for some reason steps is not already a list - setattr(model_copy.results.__dict__[class_instance_name], 'steps', list()) - - steps = model_copy.results.__dict__[class_instance_name].steps - - # step 2 - layer = 1 - for subgroup in eval(group_location_in_file + ".groups.keys()"): - solutionstep_instance = solutionstep() - # step 2a - subgroup_location_in_file = group_location_in_file + ".groups['" + subgroup + "']" - for key in eval(subgroup_location_in_file + ".variables.keys()"): - value = eval(subgroup_location_in_file + ".variables['" + str(key) + "'][:]") - setattr(solutionstep_instance, key, value) - # step 2b - steps.append(solutionstep_instance) + +# --------------------------------------------------------------------------- +# Toolkits group reader – rebuilds toolkits() with OrderedDict per analysis +# --------------------------------------------------------------------------- + +def _read_toolkits_group(grp, verbose: bool): + """Reconstruct md.toolkits as a toolkits() instance whose analysis + attributes are OrderedDicts of solver options (matching mumpsoptions() etc.)""" + tk = toolkits.__new__(toolkits) # bypass __init__ / setdefaultparameters + tk.DefaultAnalysis = None + tk.RecoveryAnalysis = None + + for aname, agrp in grp.groups.items(): + ct = _get_classtype(agrp) + opts = OrderedDict() + + if ct == 'struct': + # Variables are stored one level deeper in step_1 + step_grps = agrp.groups + src = step_grps.get('step_1', agrp) if step_grps else agrp + else: + src = agrp + + for vname, var in src.variables.items(): + opts[vname] = _read_variable(src, vname, var, verbose) + + setattr(tk, aname, opts) if verbose: - print('Succesfully loaded layer ' + str(layer) + ' to results.' + str(class_instance_name) + ' struct.') - else: pass - layer += 1 + print(f' [toolkits] {aname}: {list(opts.keys())}') - if verbose: - print('Successfully recreated results structure ' + str(class_instance_name)) - - - -def deserialize_array_of_objects(group_location_in_file, model_copy, NCData, verbose): - ''' - The structure in netcdf for groups with the name_of_cell_array variable is like: - - group: 2x6_cell_array_of_objects { - name_of_cell_array = - - group: Row_1_of_2 { - group: Col_1_of_6 { - ... other groups can be here that refer to objects - } // group Col_6_of_6 - } // group Row_1_of_2 - - group: Row_2_of_2 { - group: Col_1_of_6 { - ... other groups can be here that refer to objects - } // group Col_6_of_6 - } // group Row_2_of_2 - } // group 2x6_cell_array_of_objects - - We have to navigate this structure to extract all the data and recreate the - original structure when the model was saved - ''' - - if verbose: - print(f"Loading array of objects.") - - # get the name_of_cell_array, rows and cols vars - name_of_cell_array_varID = eval(group_location_in_file + ".variables['name_of_cell_array']") - rows_varID = eval(group_location_in_file + ".variables['rows']") - cols_varID = eval(group_location_in_file + ".variables['cols']") - - name_of_cell_array = name_of_cell_array_varID[:][...].tobytes().decode() - rows = rows_varID[:] - cols = cols_varID[:] - - # now we work backwards: make the array, fill it in, and assign it to the model - - # make the array - array = list() - - subgroups = eval(group_location_in_file + ".groups") #.keys()") - - # enter each subgroup, get the data, assign it to the corresponding index of cell array - if rows > 1: - # we go over rows - # set index for rows - row_idx = 0 - for row in list(subgroups): - # make list for each row - current_row = list() - columns = subgroups[str(row)].groups.keys() - - # set index for columns - col_idx = 0 - - # iterate over columns - for col in list(columns): - # now get the variables - current_col_vars = columns.groups[str(col)].variables - - # check for special datastructures - if "class_is_a" in current_col_vars: - class_name = subgroups[str(col)].variables['class_is_a'][:][...].tobytes().decode() - col_data = deserialize_class_instance(class_name, columns.groups[str(col)], NCData, verbose) - is_object = True - elif "this_is_a_nested" in current_col_vars: - # functionality not yet supported - print('Error: Cell Arrays of structs not yet supported!') - is_object = True - else: - if 'is_object_' in locals(): - pass - # already taken care of - else: - # store the variables as normal -- to be added later - print('Error: Arrays of mixed objects not yet supported!') - for var in current_col_vars: - # this is where that functionality would be handled - pass - col_idx += 1 - # add the entry to our row list - current_row.append(col_data) - - # add the list of columns to the array - array.append(current_row) - row_idx += 1 + return tk - else: - # set index for columns - col_idx = 0 - - # iterate over columns - for col in list(subgroups): - # now get the variables - current_col_vars = subgroups[str(col)].variables - - # check for special datastructures - if "class_is_a" in current_col_vars: - class_name = subgroups[str(col)].variables['class_is_a'][:][...].tobytes().decode() - col_data = deserialize_class_instance(class_name, subgroups[str(col)], NCData, verbose) - is_object = True - elif "this_is_a_nested" in current_col_vars: - # functionality not yet supported - print('Error: Cell Arrays of structs not yet supported!') - is_object = True - else: - if 'is_object_' in locals(): - pass - # already taken care of - else: - # store the variables as normal -- to be added later - print('Error: Arrays of mixed objects not yet supported!') - for var in current_col_vars: - # this is where that functionality would be handled - pass - col_idx += 1 - # add the list of columns to the array - array.append(col_data) - - # finally, add the attribute to the model - pattern = r"\['(.*?)'\]" - matches = re.findall(pattern, group_location_in_file) - variable_name = matches[0] - setattr(model_copy.__dict__[variable_name], name_of_cell_array, array) - if verbose: - print(f"Successfully loaded array of objects: {name_of_cell_array} to {variable_name}") +# --------------------------------------------------------------------------- +# Generic recursive group reader +# --------------------------------------------------------------------------- +def _read_group_into_obj(grp, obj, verbose: bool): + """Populate *obj* from the variables and sub-groups in *grp*.""" + # Read variables at this level + for vname, var in grp.variables.items(): + data = _read_variable(grp, vname, var, verbose) + obj = _set_attr(obj, vname, data, verbose) -def deserialize_class_instance(class_name, group, NCData, verbose=False): + # Recurse into sub-groups + for sg_name, sg in grp.groups.items(): + ct = _get_classtype(sg) - if verbose: - print(f"Loading class: {class_name}") + if ct == 'struct': + # Struct array (results.TransientSolution etc.) + nsteps = int(getattr(sg, 'nsteps', len(sg.groups))) + data = _read_struct_array(sg, nsteps, verbose) - # this function requires the class module to be imported into the namespace of this file. - # we make a custom error in case the class module is not in the list of imported classes. - # most ISSM classes are imported by from import - class ModuleError(Exception): - pass - - if class_name not in sys.modules: - raise ModuleError(str('Model requires the following class to be imported from a module: ' + class_name + ". Please add the import to read_netCDF.py in order to continue.")) - - # Instantiate the class - class_instance = eval(class_name + "()") - - # Get and assign properties - subgroups = list(group.groups.keys()) - - if len(subgroups) == 1: - # Get properties - subgroup = group[subgroups[0]] - varIDs = subgroup.variables.keys() - for varname in varIDs: - # Variable metadata - var = subgroup[varname] - - # Data - if 'char' in var.dimensions[0]: - data = var[:][...].tobytes().decode() - else: - data = var[:] + elif ct == 'cell_of_objects': + data = _read_cell_of_objects(sg, verbose) + + elif ct == 'dict': + data = _read_dict(sg, verbose) - # Some classes may have permissions, so we skip those + else: + # Regular sub-class or unknown: read into existing attr or new dict try: - setattr(class_instance, varname, data) - except: - pass - else: - # Not supported - pass + sub_obj = getattr(obj, sg_name) + except AttributeError: + sub_obj = {} + + # If the classtype tells us which class to instantiate + if ct and ct not in ('', 'struct', 'cell_of_objects', 'dict'): + sub_obj = _instantiate_class(ct, sub_obj, verbose) + + data = _read_group_into_obj(sg, sub_obj, verbose) + + obj = _set_attr(obj, sg_name, data, verbose) + + return obj + + +# --------------------------------------------------------------------------- +# Struct-array reader (results.TransientSolution etc.) +# --------------------------------------------------------------------------- + +def _read_struct_array(grp, nsteps: int, verbose: bool): + """Return a list of dicts (one per step_k sub-group).""" + steps = [] + for sg_name in sorted(grp.groups.keys(), + key=lambda n: int(n.split('_')[-1]) if n.startswith('step_') else 0): + sg = grp.groups[sg_name] + step = {} + for vname, var in sg.variables.items(): + step[vname] = _read_variable(sg, vname, var, verbose) + # Recurse into any nested groups within a step (rare) + for sub_name, sub_grp in sg.groups.items(): + step[sub_name] = _read_group_into_obj(sub_grp, {}, verbose) + steps.append(step) + + if verbose: + print(f' [struct] loaded {len(steps)}-step struct array') + return steps + + +# --------------------------------------------------------------------------- +# Cell-of-objects reader +# --------------------------------------------------------------------------- + +def _read_cell_of_objects(grp, verbose: bool): + nrows = int(getattr(grp, 'nrows', 1)) + ncols = int(getattr(grp, 'ncols', len(grp.groups))) + result = [[None] * ncols for _ in range(nrows)] + + for ig_name, ig in grp.groups.items(): + import re + m = re.match(r'^item_(\d+)_(\d+)$', ig_name) + if not m: + continue + r = int(m.group(1)) - 1 + c = int(m.group(2)) - 1 + ct = _get_classtype(ig) + obj = _instantiate_class(ct, {}, verbose) + obj = _read_group_into_obj(ig, obj, verbose) + result[r][c] = obj + + if nrows == 1: + result = result[0] # return flat list for 1-D case + if verbose: + print(f' [cell] loaded {nrows}x{ncols} cell of objects') + return result + + +# --------------------------------------------------------------------------- +# Dict reader +# --------------------------------------------------------------------------- + +def _read_dict(grp, verbose: bool) -> dict: + d = {} + for vname, var in grp.variables.items(): + d[vname] = _read_variable(grp, vname, var, verbose) + for sg_name, sg in grp.groups.items(): + d[sg_name] = _read_group_into_obj(sg, {}, verbose) + return d + - if verbose: - print(f"Successfully loaded class instance {class_name} to model") - return class_instance +# --------------------------------------------------------------------------- +# Variable reader +# --------------------------------------------------------------------------- +def _read_variable(grp, vname: str, var, verbose: bool): + """Read one NetCDF variable and convert to the appropriate Python type.""" + type_is = getattr(var, 'type_is', '') + # Empty sentinel + if type_is == 'empty': + return [] -def deserialize_data(location_of_variable_in_file, location_of_variable_in_model, variable_name, NCData, verbose = False): - # as simple as navigating to the location_of_variable_in_model and setting it equal to the location_of_variable_in_file - # NetCDF4 has a property called "_FillValue" that sometimes saves empty lists, so we have to catch those - FillValue = -9223372036854775806 + raw = var[:] + + # Bool + if type_is == 'bool': + return np.array(raw, dtype=bool) + + # String / cell-of-strings + if type_is == 'string' or (hasattr(var, 'dimensions') and + any('char' in d for d in var.dimensions)): + return _decode_string(raw) + + if type_is == 'cell_of_strings': + return _decode_cell_strings(raw) + + # Numpy array / scalar + data = np.array(raw) + + # Squeeze trailing size-1 dims + data = np.squeeze(data) + + # Single-element array → Python scalar + if data.ndim == 0: + v = data.item() + # Return int if value is a whole number (guard against nan/inf first) + if isinstance(v, float) and np.isfinite(v) and v == int(v): + return int(v) + return v + + return data + + +def _decode_string(raw) -> str: + """Convert raw NetCDF char data to a Python str.""" try: - # results band-aid... - if str(location_of_variable_in_model + '.' + variable_name) in ['results.solutionstep', 'results.solution', 'results.resultsdakota']: - pass - # qmu band-aid - elif 'qmu.statistics.method' in str(location_of_variable_in_model + '.' + variable_name): - pass - # handle any strings: - elif 'char' in eval(location_of_variable_in_file + '.dimensions[0]'): - setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, eval(location_of_variable_in_file + '[:][...].tobytes().decode()')) - # handle ndarrays + lists - elif len(eval(location_of_variable_in_file + '[:]'))>1: - # check for bool - try: # there is only one datatype assigned the attribute 'units' and that is bool, so anything else will go right to except - if eval(location_of_variable_in_file + '.units') == 'bool': - setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, np.array(eval(location_of_variable_in_file + '[:]'), dtype = bool)) - else: - setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, eval(location_of_variable_in_file + '[:]')) - except: - setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, eval(location_of_variable_in_file + '[:]')) - # catch everything else - else: - # check for FillValue. use try/except because try block will only work on datatypes like int64, float, single element lists/arrays ect and not nd-arrays/n-lists etc - try: - # this try block will only work on single ints/floats/doubles and will skip to the except block for all other cases - var_to_save = eval(location_of_variable_in_file + '[:][0]') # note the [0] on the end - if FillValue == var_to_save: - setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, []) - else: - if var_to_save.is_integer(): - setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, int(var_to_save)) - else: - # we have to convert numpy datatypes to native python types with .item() - setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, var_to_save.item()) - except: - setattr(eval('model_copy.' + location_of_variable_in_model), variable_name, eval(location_of_variable_in_file + '[:]')) - except AttributeError: - deserialize_dict(location_of_variable_in_file, location_of_variable_in_model, NCData, verbose=verbose) + return raw.tobytes().decode('utf-8').strip('\x00').strip() + except Exception: + try: + return ''.join(c.decode('utf-8') if isinstance(c, bytes) else c + for c in np.ndarray.flatten(raw)) + except Exception: + return str(raw) + + +def _decode_cell_strings(raw) -> list: + """Convert a 2-D char array to a list of strings.""" + if raw.ndim == 1: + return [_decode_string(raw)] + result = [] + for row in raw: + s = _decode_string(row) + result.append(s) + return result + + +# --------------------------------------------------------------------------- +# Subclass instantiation +# --------------------------------------------------------------------------- + +def _instantiate_subclass(md, gname: str, ct: str, verbose: bool): + """For polymorphic model fields, swap in the right class instance.""" + if not ct: + return md + + try: + if gname == 'inversion': + if ct == 'm1qn3inversion': + from m1qn3inversion import m1qn3inversion + md.inversion = m1qn3inversion() + elif ct == 'taoinversion': + from taoinversion import taoinversion + md.inversion = taoinversion() + elif gname == 'smb': + md = _instantiate_smb(md, ct, verbose) + + elif gname == 'friction': + md = _instantiate_friction(md, ct, verbose) + + elif gname == 'hydrology': + md = _instantiate_hydrology(md, ct, verbose) + + elif gname == 'mesh': + if ct == 'mesh3dprisms': + from mesh3dprisms import mesh3dprisms + md.mesh = mesh3dprisms() + + # All other groups: keep default instance, just overwrite fields below + + except Exception as e: + if verbose: + print(f' [WARN] could not instantiate {ct} for {gname}: {e}') + + return md + + +def _instantiate_class(ct: str, fallback, verbose: bool): + """Try to instantiate *ct* by importing it; return *fallback* on failure.""" + if not ct or ct in ('struct', 'cell_of_objects', 'dict', ''): + return fallback + try: + mod = __import__(ct, fromlist=[ct]) + cls = getattr(mod, ct) + return cls() + except Exception: + pass + # Try to find ct in already-imported modules + for mod_name, mod in list(sys.modules.items()): + if mod is not None and hasattr(mod, ct): + cls = getattr(mod, ct) + if isinstance(cls, type): + try: + return cls() + except Exception: + pass if verbose: - print('Successfully loaded ' + location_of_variable_in_model + '.' + variable_name + ' into model.') - - - -def deserialize_dict(location_of_variable_in_file, location_of_variable_in_model, NCData, verbose = False): - FillValue = -9223372036854775806 - - # the key will be the last item in the location - key = ''.join(location_of_variable_in_model.split('.')[-1]) - - # update the location to point to the dict instead of the dict key - location_of_variable_in_model = '.'.join(location_of_variable_in_model.split('.')[:-1]) - - # verify we're working with a dict: - if isinstance(eval('model_copy.' + location_of_variable_in_model), OrderedDict): - dict_object = eval('model_copy.' + location_of_variable_in_model) - - # handle any strings: - if 'char' in eval(location_of_variable_in_file + '.dimensions[0]'): - data = eval(location_of_variable_in_file + '[:][...].tobytes().decode()') - dict_object.update({key: data}) - - # handle ndarrays + lists - elif len(eval(location_of_variable_in_file + '[:]'))>1: - # check for bool - try: # there is only one datatype assigned the attribute 'units' and that is bool, so anything else will go right to except - if eval(location_of_variable_in_file + '.units') == 'bool': - data = np.array(eval(location_of_variable_in_file + '[:]'), dtype = bool) - dict_object.update({key: data}) - else: - data = eval(location_of_variable_in_file + '[:]') - dict_object.update({key: data}) - except: - data = eval(location_of_variable_in_file + '[:]') - dict_object.update({key: data}) - # catch everything else - else: - # check for FillValue. use try/except because try block will only work on datatypes like int64, float, single element lists/arrays ect and not nd-arrays/n-lists etc - try: - # this try block will only work on single ints/floats/doubles and will skip to the except block for all other cases - if FillValue == eval(location_of_variable_in_file + '[:][0]'): - dict_object.update({key: []}) - else: - # we have to convert numpy datatypes to native python types with .item() - var_to_save = eval(location_of_variable_in_file + '[:][0]') # note the [0] on the end - dict_object.update({key: var_to_save.item()}) - except: - data = eval(location_of_variable_in_file + '[:]') - dict_object.update({key: data}) + print(f' [WARN] could not instantiate class {ct}, using fallback') + return fallback + + +def _instantiate_smb(md, ct: str, verbose: bool): + mapping = { + 'SMBforcing': ('SMBforcing', 'SMBforcing'), + 'SMBpdd': ('SMBpdd', 'SMBpdd'), + 'SMBd18opdd': ('SMBd18opdd', 'SMBd18opdd'), + 'SMBgradients': ('SMBgradients', 'SMBgradients'), + 'SMBcomponents': ('SMBcomponents', 'SMBcomponents'), + 'SMBmeltcomponents': ('SMBmeltcomponents', 'SMBmeltcomponents'), + 'SMBgradientscomponents':('SMBgradientscomponents','SMBgradientscomponents'), + 'SMBgradientsela': ('SMBgradientsela', 'SMBgradientsela'), + 'SMBhenning': ('SMBhenning', 'SMBhenning'), + 'SMBgemb': ('SMBgemb', 'SMBgemb'), + 'SMBpddSicopolis': ('SMBpddSicopolis', 'SMBpddSicopolis'), + 'SMBsemic': ('SMBsemic', 'SMBsemic'), + 'SMBdebrisEvatt': ('SMBdebrisEvatt', 'SMBdebrisEvatt'), + } + if ct in mapping: + mod_name, cls_name = mapping[ct] + try: + mod = __import__(mod_name, fromlist=[cls_name]) + md.smb = getattr(mod, cls_name)() + except Exception as e: + if verbose: + print(f' [WARN] could not load SMB class {ct}: {e}') + else: + if verbose: + print(f' [WARN] unknown SMB class: {ct}') + return md + + +def _instantiate_friction(md, ct: str, verbose: bool): + known = [ + 'friction', 'frictioncoulomb', 'frictioncoulomb2', + 'frictionhydro', 'frictionjosh', 'frictionpism', + 'frictionregcoulomb', 'frictionregcoulomb2', 'frictionschoof', + 'frictionshakti', 'frictiontsai', 'frictionwaterlayer', + 'frictionweertman', 'frictionweertmantemp', + ] + if ct in known: + try: + mod = __import__(ct, fromlist=[ct]) + md.friction = getattr(mod, ct)() + except Exception as e: + if verbose: + print(f' [WARN] could not load friction class {ct}: {e}') + else: + if verbose: + print(f' [WARN] unknown friction class: {ct}') + return md + + +def _instantiate_hydrology(md, ct: str, verbose: bool): + known = [ + 'hydrologyshreve', 'hydrologydc', 'hydrologyglads', + 'hydrologypism', 'hydrologyshakti', 'hydrologytws', 'hydrologyarmapw', + ] + if ct in known: + try: + mod = __import__(ct, fromlist=[ct]) + md.hydrology = getattr(mod, ct)() + except Exception as e: + if verbose: + print(f' [WARN] could not load hydrology class {ct}: {e}') else: - print(f"Unrecognized object was saved to NetCDF file and cannot be reconstructed: {location_of_variable_in_model}") \ No newline at end of file + if verbose: + print(f' [WARN] unknown hydrology class: {ct}') + return md + + +# --------------------------------------------------------------------------- +# Attribute setter +# --------------------------------------------------------------------------- + +def _set_attr(obj, name: str, value, verbose: bool): + """Set attribute *name* on *obj* (works for class instances and dicts).""" + try: + if isinstance(obj, dict): + obj[name] = value + else: + setattr(obj, name, value) + except Exception as e: + if verbose: + print(f' [WARN] could not set {name}: {e}') + return obj + + +# --------------------------------------------------------------------------- +# Utility +# --------------------------------------------------------------------------- + +def _get_classtype(grp) -> str: + return getattr(grp, 'classtype', '') diff --git a/src/m/netcdf/write_netCDF.m b/src/m/netcdf/write_netCDF.m index 852d25b1e..97337c2d2 100644 --- a/src/m/netcdf/write_netCDF.m +++ b/src/m/netcdf/write_netCDF.m @@ -1,1012 +1,444 @@ -%{ -Given a model, this set of functions will perform the following: - 1. Enter each nested class of the model. - 2. View each attribute of each nested class. - 3. Compare state of attribute in the model to an empty model class. - 4. If states are identical, pass. - 5. Otherwise, create nested groups named after class structure. - 6. Create variable named after class attribute and assign value to it. -%} - - -function write_netCDF(model_var, filename, varargin) - if nargin > 2 - verbose = true; +function write_netCDF(md, filename, varargin) +%WRITE_NETCDF - Save an ISSM model to a NetCDF4 file. +% +% Usage: +% write_netCDF(md, filename) +% write_netCDF(md, filename, 'verbose', true) +% +% Inputs: +% md - ISSM model object +% filename - path/name for the output .nc file (overwritten if it exists) +% +% Optional name-value pair: +% 'verbose' - true/false (default false) +% +% The file can be read back by read_netCDF.m (MATLAB) or read_netCDF.py (Python). +% +%NetCDF group layout +%------------------- +%Each first-level field of md (mesh, mask, geometry, …) becomes a NetCDF +%group. Fields within those classes are stored as variables inside the +%group. Nested subclasses get nested subgroups. +% +%Class-type encoding +%------------------- +%For fields whose MATLAB class can vary at run-time (inversion, smb, +%friction, hydrology), the concrete class name is stored as a group +%attribute 'classtype' so that the reader can reconstruct the correct +%object. Every group also gets a 'classtype' attribute with the MATLAB +%class name of the object it represents (e.g. "mesh2d", "m1qn3inversion"). +% +%Results storage +%--------------- +%md.results. is a MATLAB struct array (1×n). Each element is +%stored as a subgroup named "step_" inside the solution subgroup. Every +%variable in every step is stored as a numeric or char variable. + % --- parse options ------------------------------------------------ + p = inputParser(); + p.addParameter('verbose', false, @islogical); + % also accept positional 'verbose' flag (legacy) + if nargin > 2 && islogical(varargin{1}) + verbose = varargin{1}; else - verbose = false; + p.parse(varargin{:}); + verbose = p.Results.verbose; end + if verbose - disp('MATLAB C2NetCDF4 v1.1.14'); - end - - % model_var = class object to be saved - % filename = path and name to save file under - - % Create a NetCDF file to write to - NetCDF = make_NetCDF(filename, verbose); - - % Create an instance of an empty model class to compare model_var against - empty_model = model(); - - % Walk through the model_var class and compare subclass states to empty_model - walk_through_model(model_var, empty_model, NetCDF, verbose); - - % in order to handle some subclasses in the results class, we have to utilize this band-aid - % there will likely be more band-aids added unless a class name library is created with all class names that might be added to a model - try - % if results had meaningful data, save the name of the subclass and class instance - netcdf.inqNcid(NetCDF,'results'); - results_subclasses_bandaid(model_var, NetCDF, verbose); - % otherwise, ignore - catch - end - - netcdf.close(NetCDF); - if verbose - disp('Model successfully saved as NetCDF4'); + disp('write_netCDF v2.0 (MATLAB)'); end -end - - -function NetCDF = make_NetCDF(filename, verbose) - % matlab can't handle input in the jupyter interface, so we just yell at the user to rename - % their file if needed - % If file already exists delete / rename it + % --- create / overwrite file -------------------------------------- if exist(filename, 'file') == 2 - fprintf('File %s already exists\n', filename); - disp('Please rename your file.') - return - - % If so, inquire for a new name or to delete the existing file - %newname = input('Give a new name or input "delete" to replace: ', 's'); - - %if strcmpi(newname, 'delete') - %delete filename; - %else - %fprintf('New file name is %s\n', newname); - %filename = newname; - %end - else - % Otherwise create the file and define it globally so other functions can call it - - NetCDF = netcdf.create(filename, 'NETCDF4'); - netcdf.putAtt(NetCDF, netcdf.getConstant('NC_GLOBAL'), 'history', ['Created ', datestr(now)]); - netcdf.defDim(NetCDF, 'Unlim', netcdf.getConstant('NC_UNLIMITED')); % unlimited dimension - netcdf.defDim(NetCDF, 'float', 1); % single integer dimension - netcdf.defDim(NetCDF, 'int', 1); % single float dimension - + delete(filename); if verbose - fprintf('Successfully created %s\n', filename); + fprintf('Existing file %s deleted.\n', filename); end + end - return + ncid = netcdf.create(filename, 'NETCDF4'); + netcdf.putAtt(ncid, netcdf.getConstant('NC_GLOBAL'), 'history', ... + ['Created by write_netCDF.m on ' datestr(now)]); + netcdf.putAtt(ncid, netcdf.getConstant('NC_GLOBAL'), 'Conventions', 'ISSM-NetCDF-2.0'); + + % Global dimensions reused throughout the file + netcdf.defDim(ncid, 'scalar', 1); % for single-value variables + netcdf.defDim(ncid, 'Unlim', netcdf.getConstant('NC_UNLIMITED')); + + if verbose + fprintf('Created %s\n', filename); end -end + % --- walk all top-level fields of md ------------------------------ + top_fields = fieldnames(md); + for fi = 1:numel(top_fields) + fname = top_fields{fi}; + val = md.(fname); -%{ - Since python uses subclass instances and MATLAB uses fields, we need to guess which subclass instance python will need - given the name of the sub-field in MATLAB. We make this guess based on the name of the MATLAB subfield that will contain - the name of the python subclass instance. For example, md.results.StressbalanceSolution is an subfield in MATLAB, - but a class instance of solution(). Notice that StressbalanceSolution contains the name "Solution" in it. This is what - we will save to the netCDF file for python to pick up. -%} - -function results_subclasses_bandaid(model_var, NetCDF, verbose) - - % The results class may have nested fields within it, so we need to record the name of - % the nested field as it appears in the model that we're trying to save - quality_control = {}; - - % Access the results subclass of model_var - results_var = model_var.results; - - % get the results group id so we can write to it - groupid = netcdf.inqNcid(NetCDF,'results'); - - % Loop through each class instance in results - class_instance_names = fieldnames(results_var); - - % we save lists of instances to the netcdf - solutions = {}; - solutionsteps = {}; - resultsdakotas = {}; - - for i = 1:numel(class_instance_names) - class_instance_name = class_instance_names{i}; - % there are often mutliple instances of the same class/struct so we have to number them - % Check to see if there is a solutionstep class instance - if contains(class_instance_name, 'solutionstep',IgnoreCase=true) - quality_control{end+1} = 1; - solutionsteps{end+1} = class_instance_name; - if verbose - disp('Successfully stored class python subclass instance: solutionstep') - end - end - - % Check to see if there is a solution class instance - if contains(class_instance_name, 'solution',IgnoreCase=true) - quality_control{end+1} = 1; - solutions{end+1} = class_instance_name; - if verbose - disp('Successfully stored class python subclass instance: solution') - end - end - - % Check to see if there is a resultsdakota class instance - if contains(class_instance_name, 'resultsdakota',IgnoreCase=true) - quality_control{end+1} = 1; - resultsdakotas{end+1} = class_instance_name; + if isempty(val) if verbose - disp('Successfully stored class python subclass instance: resultsdakota') + fprintf(' md.%s is empty – skipped\n', fname); end + continue end - end - if ~isempty(solutionsteps) - write_cell_with_strings('solutionstep', solutionsteps, groupid, NetCDF, verbose) - end - if ~isempty(solutions) - write_cell_with_strings('solution', solutions, groupid, NetCDF, verbose) - end - if ~isempty(resultsdakotas) - write_cell_with_strings('resultsdakota', resultsdakotas, groupid, NetCDF, verbose) - end - - - % Check if all class instances were processed correctly - if numel(quality_control) ~= numel(class_instance_names) - disp('Error: The class instance within your model.results class is not currently supported by this application'); - else - if verbose - disp('The results class was successfully stored on disk'); - end - end -end + gid = netcdf.defGrp(ncid, fname); + % Store the concrete class name so readers can reconstruct the right object + netcdf.putAtt(gid, netcdf.getConstant('NC_GLOBAL'), 'classtype', class(val)); + write_group(val, gid, ncid, fname, verbose); + end -function walk_through_model(model_var, empty_model, NetCDF, verbose) - % Iterate over first layer of model_var attributes and assume this first layer is only classes fundamental to the model() class - % note that groups are the same as class instances/subfields in this context - groups = fieldnames(model_var); - for group = 1:numel(groups) - % now this new variable takes the form model.mesh , model.damage etc. - model_subclass = model_var.(groups{group}); - empty_model_subclass = empty_model.(groups{group}); - % Now we can recursively walk through the remaining subclasses - list_of_layers = {groups{group}}; - walk_through_subclasses(model_subclass, empty_model_subclass, list_of_layers, empty_model, NetCDF, verbose); + netcdf.close(ncid); + if verbose + disp('Model successfully saved as NetCDF4.'); end end - - -function walk_through_subclasses(model_subclass, empty_model_subclass, given_list_of_layers, empty_model, NetCDF, verbose) - % Recursivley iterate over each subclass' attributes and look for more subclasses and variables with relevant data - % model_subclass is an object (ie, md.mesh.elements) - % list_of_layers is a cell array of subclasses/attributes/fields so that we can copy the structure into netcdf (ie, {'mesh', 'elements'}) - % need to check if inversion or m1qn3inversion or taoinversion class - if numel(given_list_of_layers) == 1 - if strcmp(given_list_of_layers{1}, 'inversion') - create_group(model_subclass, given_list_of_layers, NetCDF, verbose); - check_inversion_class(model_subclass, NetCDF, verbose); - - elseif strcmp(given_list_of_layers{1},'smb') - create_group(model_subclass, given_list_of_layers, NetCDF, verbose); - check_smb_class(model_subclass, NetCDF, verbose); - - elseif strcmp(given_list_of_layers{1},'friction') - create_group(model_subclass, given_list_of_layers, NetCDF, verbose); - check_friction_class(model_subclass, NetCDF, verbose); - - elseif strcmp(given_list_of_layers{1},'hydrology') - create_group(model_subclass, given_list_of_layers, NetCDF, verbose); - check_hydrology_class(model_subclass, NetCDF, verbose); - end - end - - % Use try/except since model_subclass is either a subclass/struct w/ props/fields or it's not, no unknown exceptions - try - % look for children - this is where the catch would be called - children = fieldnames(model_subclass); - - % if there are children, loop through them and see if we need to save any data - for child = 1:numel(children) - % record our current location - list_of_layers = given_list_of_layers; - current_child = children{child}; - list_of_layers{end+1} = current_child; - - % this is the value of the current location in the model (ie, md.mesh.elements) - location_of_child = model_subclass.(current_child); - - % if the empty model does not have this attribute, it's because it's new so we save it to netcdf - % there are 2 cases: the location is a struct, the location is a class - if isstruct(model_subclass) - % if the current field is a nested struct assume it has valuable data that needs to be saved - if isstruct(location_of_child) && any(size(location_of_child) > 1) - create_group(location_of_child, list_of_layers, NetCDF, verbose); - - % this would mean that the layer above the layer we're interested in is a struct, so - % we can navigate our empty model as such - elseif isfield(empty_model_subclass, current_child) - % the layer we're interested in does exist, we just need to compare states - location_of_child_in_empty_model = empty_model_subclass.(current_child); - - % if the current attribute is a numerical array assume it has valuable data that needs to be saved - if isnumeric(location_of_child) && logical(numel(location_of_child) > 1) - create_group(location_of_child, list_of_layers, NetCDF, verbose); - % if the attributes are identical we don't need to save anything - elseif (all(isnan(location_of_child)) && all(isnan(location_of_child_in_empty_model))) || isempty(setxor(location_of_child, location_of_child_in_empty_model)) - walk_through_subclasses(location_of_child, location_of_child_in_empty_model, list_of_layers, empty_model, NetCDF, verbose); - % if the attributes are not the same we need to save ours - else - % THE ORDER OF THESE LINES IS CRITICAL - walk_through_subclasses(location_of_child, location_of_child_in_empty_model, list_of_layers, empty_model, NetCDF, verbose); - create_group(location_of_child, list_of_layers, NetCDF, verbose); - end - % this would mean that the layer we're interested in is not fundamental to the model architecture - % and thus needs to be saved to the netcdf - else - walk_through_subclasses(location_of_child, empty_model_subclass, list_of_layers, empty_model, NetCDF, verbose); - create_group(location_of_child, list_of_layers, NetCDF, verbose); - end - % this would mean it's not a struct, and must be a class/subclass - % we now check the state of the class property - else - try - if isprop(empty_model_subclass, current_child) - % the layer we're interested in does exist, we just need to compare states - location_of_child_in_empty_model = empty_model_subclass.(current_child); - % if the current attribute is a numerical array assume it has valuable data that needs to be saved - if isnumeric(location_of_child) && logical(numel(location_of_child) > 1) - create_group(location_of_child, list_of_layers, NetCDF, verbose); - - elseif iscell(location_of_child) - % if the attributes are identical we don't need to save anything - if isempty(setxor(location_of_child, location_of_child_in_empty_model)) - % pass - else - % otherwise we need to save - walk_through_subclasses(location_of_child, empty_model_subclass, list_of_layers, empty_model, NetCDF, verbose); - create_group(location_of_child, list_of_layers, NetCDF, verbose); - end - elseif (all(isnan(location_of_child)) && all(isnan(location_of_child_in_empty_model))) - walk_through_subclasses(location_of_child, location_of_child_in_empty_model, list_of_layers, empty_model, NetCDF, verbose); - % if the attributes are not the same we need to save ours - else - % THE ORDER OF THESE LINES IS CRITICAL - walk_through_subclasses(location_of_child, location_of_child_in_empty_model, list_of_layers, empty_model, NetCDF, verbose); - create_group(location_of_child, list_of_layers, NetCDF, verbose); - end - else - walk_through_subclasses(location_of_child, empty_model_subclass, list_of_layers, empty_model, NetCDF, verbose); - create_group(location_of_child, list_of_layers, NetCDF, verbose); - end - catch - walk_through_subclasses(location_of_child, empty_model_subclass, list_of_layers, empty_model, NetCDF, verbose); - create_group(location_of_child, list_of_layers, NetCDF, verbose); - end - end - end - catch ME - % If the caught error is a fieldname error, it's just saying that a variable has no fields and thus can be ignored - if strcmp(ME.identifier, 'MATLAB:fieldnames:InvalidInput') - % do nothing - % this is if we come accross instances/subfields in our model that are not fundamental to the model class (ie, taoinversion) - elseif strcmp(ME.identifier, 'MATLAB:UndefinedFunction') - walk_through_subclasses(location_of_child, empty_model_subclass, given_list_of_layers, empty_model, NetCDF, verbose); - create_group(location_of_child, list_of_layers, NetCDF, verbose); - % If it's a different error, rethrow it to MATLAB's default error handling - else - disp(ME.identifier) - disp(given_list_of_layers) - rethrow(ME); - end - end -end - - -function create_group(location_of_child, list_of_layers, NetCDF, verbose) - %disp(list_of_layers) - % location_of_child is an object - % list_of_layers is a list like {'inversion', 'StressbalanceSolution','cost_functions_coefficients'} - % first we make the group at the highest level (ie, inversion) - group_name = list_of_layers{1}; - variable_name = list_of_layers{end}; - - % if the group is already made, get it's ID instead of creating it again - try % group hasn't been made - group = netcdf.defGrp(NetCDF, group_name); - catch % group was already made - group = netcdf.inqNcid(NetCDF, group_name); - end - - % if the data is nested, create nested groups to match class structure - if numel(list_of_layers) > 2 - % the string() method is really important here since matlab apparently can't handle the infinite complexity of a string without the string method. - for name = string(list_of_layers(2:end-1)) - % the group levels may have already been made - try % group hasn't been made - group = netcdf.defGrp(group, name); - catch % group was already made - group = netcdf.inqNcid(group, name); - end - end - end - % sometimes objects are passed through twice so we account for that with this try/catch + + +% ===================================================================== +% write_group – write all fields of a class/struct into a group +% ===================================================================== +function write_group(obj, gid, root_ncid, path_str, verbose) + % Get field names (works for both classes and structs) try - % we may be dealing with an object - % first we screen for structs - if isstruct(location_of_child) % && any(size(location_of_child) > 1) -- this is being tested - % we have a struct - copy_nested_struct(variable_name, location_of_child, group, NetCDF, verbose); - - % now for cell arrays of datastructures: - elseif logical(~isstruct(location_of_child) && iscell(location_of_child) && isobject(location_of_child{1})) - copy_cell_array_of_objects(variable_name, location_of_child, group, NetCDF, verbose); - else - if ~isobject(location_of_child) && ~isstruct(location_of_child) - % we're dealing with raw data - create_var(variable_name, location_of_child, group, NetCDF, verbose); - end - end + fields = fieldnames(obj); catch - % do nothing + % obj has no fields (e.g. a raw value that slipped through) – ignore + return end -end + for fi = 1:numel(fields) + fname = fields{fi}; + val = obj.(fname); + child_path = [path_str '.' fname]; + + % Skip log fields + if ismember(fname, {'errlog','outlog'}) + continue + end + write_value(val, fname, gid, root_ncid, child_path, verbose); + end +end -function copy_cell_array_of_objects(variable_name, address_of_child, group, NetCDF, verbose) - % make subgroup to represent the array - [rows, cols] = size(address_of_child); - name_of_subgroup = [num2str(rows), 'x', num2str(cols), '_cell_array_of_objects']; - subgroup = netcdf.defGrp(group, name_of_subgroup); - % save the name of the cell array - write_string_to_netcdf('name_of_cell_array', variable_name, subgroup, NetCDF, verbose); +% ===================================================================== +% write_value – dispatch a single value to the right writer +% ===================================================================== +function write_value(val, vname, gid, root_ncid, path_str, verbose) - % save the dimensions of the cell array - create_var('rows', rows, subgroup, NetCDF, verbose); - create_var('cols', cols, subgroup, NetCDF, verbose); + % ---- empty ------------------------------------------------------- + if isempty(val) + % Store as scalar NaN so the variable exists and readers know it was empty + write_scalar_nan(vname, gid, root_ncid); + if verbose, fprintf(' [empty] %s\n', path_str); end + return + end - % if this is a multidimensional cell array, iterate over rows here and cols in copy_objects - if rows>1 - for row = 1:rows - % make a subgroup for each row - name_of_subgroup = ['Row_', num2str(row), '_of_', num2str(rows)]; - subgroup = netcdf.defGrp(group, name_of_subgroup); - copy_objects(address_of_child, subgroup, NetCDF, cols, verbose); - end - else - copy_objects(address_of_child, subgroup, NetCDF, cols, verbose); + % ---- struct (e.g. md.results.TransientSolution which is 1xN) ----- + if isstruct(val) + write_struct_value(val, vname, gid, root_ncid, path_str, verbose); + return end -end + % ---- ISSM sub-class (has its own fieldnames) ---------------------- + if isobject(val) + sub_gid = get_or_create_group(gid, vname); + netcdf.putAtt(sub_gid, netcdf.getConstant('NC_GLOBAL'), 'classtype', class(val)); + write_group(val, sub_gid, root_ncid, path_str, verbose); + return + end + % ---- cell array of ISSM objects (e.g. outputdefinition list) ------ + if iscell(val) && ~isempty(val) && isobject(val{1}) + write_cell_of_objects(val, vname, gid, root_ncid, path_str, verbose); + return + end -function copy_objects(address_of_child, group, NetCDF, cols, verbose) - for col = 1:cols - % make subgroup to contain each col of array - name_of_subgroup = ['Col_', num2str(col), '_of_', num2str(cols)]; - subgroup = netcdf.defGrp(group, name_of_subgroup); + % ---- cell array of strings --------------------------------------- + if iscellstr(val) || (iscell(val) && ~isempty(val) && ischar(val{1})) + write_cell_strings(val, vname, gid, root_ncid, path_str, verbose); + if verbose, fprintf(' [cellstr] %s\n', path_str); end + return + end - % get the kind of object we're working with: - if isstruct(address_of_child{col}) - % handle structs - name_raw = fields(address_of_child{col}); - variable_name = name_raw{1}; - copy_nested_struct(variable_name, address_of_child, subgroup, NetCDF, verbose); - - elseif numel(properties(address_of_child{col})) > 0 - % handle class instances - copy_class_instance(address_of_child{col}, subgroup, NetCDF, verbose); - else - disp('ERROR: Cell arrays of mixed types are not yet supported in read_netCDF!\n Deserialization will not be able to complete!') - % handle regular datastructures that are already supported - name_raw = fields(address_of_child); - variable_name = name_raw{col}; - create_var(variable_name, address_of_child, subgroup, NetCDF, verbose); + % ---- plain cell array (numbers etc.) ----------------------------- + if iscell(val) + % Try to convert to numeric matrix; if not, skip with warning + try + mat = cell2mat(val); + write_numeric(mat, vname, gid, root_ncid, path_str, verbose); + catch + if verbose + fprintf(' [SKIP] %s – cell array of mixed/unsupported types\n', path_str); + end end + return end -end - -function copy_class_instance(address_of_child, subgroup, NetCDF, verbose) - % get parent class name - name = class(address_of_child); - - % save the name of the class - write_string_to_netcdf('class_is_a', name, subgroup, NetCDF, verbose); - - % make subgroup to contain properties - name_of_subgroup = ['Properties_of_', name]; - subgroup = netcdf.defGrp(subgroup, name_of_subgroup); + % ---- logical (bool) ---------------------------------------------- + if islogical(val) + write_bool(val, vname, gid, root_ncid, path_str, verbose); + if verbose, fprintf(' [bool] %s\n', path_str); end + return + end - % get properties - props = properties(address_of_child); + % ---- char / string ----------------------------------------------- + if ischar(val) || isstring(val) + write_string(char(val), vname, gid, root_ncid, path_str, verbose); + if verbose, fprintf(' [string] %s\n', path_str); end + return + end - for property = 1:length(props) - variable_name = props{property}; - create_var(variable_name, address_of_child.(variable_name), subgroup, NetCDF, verbose); + % ---- numeric (scalar, vector, matrix, ND) ------------------------ + if isnumeric(val) + write_numeric(val, vname, gid, root_ncid, path_str, verbose); + if verbose, fprintf(' [numeric] %s %s\n', path_str, mat2str(size(val))); end + return end + % ---- fallback: skip with warning --------------------------------- + if verbose + fprintf(' [SKIP] %s – unsupported type %s\n', path_str, class(val)); + end end -function copy_nested_struct(parent_struct_name, address_of_struct, group, NetCDF, verbose) - %{ - This function takes a struct of structs and saves them to netcdf. - - It also works with single structs. - - To do this, we get the number of dimensions (substructs) of the parent struct. - Next, we iterate through each substruct and record the data. - For each substruct, we create a subgroup of the main struct. - For each variable, we create dimensions that are assigned to each subgroup uniquely. - %} - - % make a new subgroup to contain all the others: - group = netcdf.defGrp(group, parent_struct_name); - - % make sure other systems can flag the nested struct type - dimID = netcdf.defDim(group, 'struct', 6); - string_var = netcdf.defVar(group, 'this_is_a_nested', "NC_CHAR", dimID); - uint_method=uint8('struct').'; - method_ID = char(uint_method); - netcdf.putVar(group, string_var, method_ID); - - % other systems know the name of the parent struct because it's covered by the results/qmu functions above - - % 'a' will always be 1 and is not useful to us - [a, no_of_dims] = size(address_of_struct); - - for substruct = 1:no_of_dims - % we start by making subgroups with nice names like "TransientSolution_substruct_44" - name_of_subgroup = ['1x', num2str(substruct)]; - subgroup = netcdf.defGrp(group, name_of_subgroup); - - % do some housekeeping to keep track of the current layer - current_substruct = address_of_struct(substruct); - substruct_fields = fieldnames(current_substruct)'; % transpose because matlab only interates over n x 1 arrays - - % now we need to iterate over each variable of the nested struct and save it to this new subgroup - for variable_name = string(substruct_fields) - address_of_child = current_substruct.(variable_name); - create_var(variable_name, address_of_child, subgroup, NetCDF, verbose); +% ===================================================================== +% write_struct_value – handle a struct field (scalar or 1-D array) +% ===================================================================== +function write_struct_value(val, vname, gid, root_ncid, path_str, verbose) + n = numel(val); + if n == 0 + write_scalar_nan(vname, gid, root_ncid); + return + end + + sub_gid = get_or_create_group(gid, vname); + netcdf.putAtt(sub_gid, netcdf.getConstant('NC_GLOBAL'), 'classtype', 'struct'); + netcdf.putAtt(sub_gid, netcdf.getConstant('NC_GLOBAL'), 'nsteps', int32(n)); + + for k = 1:n + step_name = sprintf('step_%d', k); + step_gid = netcdf.defGrp(sub_gid, step_name); + step_fields = fieldnames(val(k)); + for fi = 1:numel(step_fields) + sfield = step_fields{fi}; + if ismember(sfield, {'errlog','outlog'}), continue; end + sval = val(k).(sfield); + write_value(sval, sfield, step_gid, root_ncid, [path_str '.' step_name '.' sfield], verbose); end end if verbose - fprintf(["Succesfully transferred nested MATLAB struct ", parent_struct_name, " to the NetCDF\n"]) + fprintf(' [struct] %s (1x%d)\n', path_str, n); end end - -% ironically inversion does not have the same problem as results as inversion subfields -% are actually subclasses and not fields -function check_inversion_class(model_var, NetCDF, verbose) - - % Define a persistent variable to ensure this function is only run once - persistent executed; - % Check if the function has already been executed - if isempty(executed) - if verbose - disp('Deconstructing Inversion class instance') - end - % Need to make sure that we have the right inversion class: inversion, m1qn3inversion, taoinversion - groupid = netcdf.inqNcid(NetCDF,'inversion'); - - if isa(model_var, 'm1qn3inversion') - write_string_to_netcdf('inversion_class_name', 'm1qn3inversion', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved inversion class instance m1qn3inversion') - end - elseif isa(model_var, 'taoinversion') - write_string_to_netcdf('inversion_class_name', 'taoinversion', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved inversion class instance taoinversion') - end - else - write_string_to_netcdf('inversion_class_name', 'inversion', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved inversion class instance inversion') +% ===================================================================== +% write_cell_of_objects – cell array whose elements are ISSM classes +% ===================================================================== +function write_cell_of_objects(val, vname, gid, root_ncid, path_str, verbose) + [rows, cols] = size(val); + sub_gid = get_or_create_group(gid, vname); + netcdf.putAtt(sub_gid, netcdf.getConstant('NC_GLOBAL'), 'classtype', 'cell_of_objects'); + netcdf.putAtt(sub_gid, netcdf.getConstant('NC_GLOBAL'), 'nrows', int32(rows)); + netcdf.putAtt(sub_gid, netcdf.getConstant('NC_GLOBAL'), 'ncols', int32(cols)); + + for r = 1:rows + for c = 1:cols + elem = val{r, c}; + elem_name = sprintf('item_%d_%d', r, c); + elem_gid = netcdf.defGrp(sub_gid, elem_name); + netcdf.putAtt(elem_gid, netcdf.getConstant('NC_GLOBAL'), 'classtype', class(elem)); + if isstruct(elem) + write_group(elem, elem_gid, root_ncid, [path_str '.' elem_name], verbose); + elseif isobject(elem) + write_group(elem, elem_gid, root_ncid, [path_str '.' elem_name], verbose); end end - % Set the persistent variable to indicate that the function has been executed - executed = true; + end + if verbose + fprintf(' [cell] %s (%dx%d objects)\n', path_str, rows, cols); end end -%Write a name for the smb class -function check_smb_class(model_var, NetCDF, verbose) -% Define a persistent variable to ensure this function is only run once -persistent executed; -% Check if the function has already been executed -if isempty(executed) - if verbose - disp('Deconstructing smb class instance') - end - % Need to make sure that we have the right smb class - groupid = netcdf.inqNcid(NetCDF,'smb'); +% ===================================================================== +% Leaf writers +% ===================================================================== - if isa(model_var, 'SMBforcing') - write_string_to_netcdf('smb_class_name', 'SMBforcing', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBforcing') - end - elseif isa(model_var, 'SMB') - write_string_to_netcdf('smb_class_name', 'SMB', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMB') - end - elseif isa(model_var, 'SMBcomponents') - write_string_to_netcdf('smb_class_name', 'SMBcomponents', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBcomponents') - end - elseif isa(model_var, 'SMBd18opdd') - write_string_to_netcdf('smb_class_name', 'SMBd18opdd', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBd18opdd') - end - elseif isa(model_var, 'SMBdebrisEvatt') - write_string_to_netcdf('smb_class_name', 'SMBdebrisEvatt', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBdebrisEvatt') - end - elseif isa(model_var, 'SMBgemb') - write_string_to_netcdf('smb_class_name', 'SMBgemb', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBgemb') - end - elseif isa(model_var, 'SMBgradients') - write_string_to_netcdf('smb_class_name', 'SMBgradients', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBgradients') - end - elseif isa(model_var, 'SMBgradientscomponents') - write_string_to_netcdf('smb_class_name', 'SMBgradientscomponents', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBgradientscomponents') - end - elseif isa(model_var, 'SMBgradientsela') - write_string_to_netcdf('smb_class_name', 'SMBgradientsela', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBgradientsela') - end - elseif isa(model_var, 'SMBhenning') - write_string_to_netcdf('smb_class_name', 'SMBhenning', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBhenning') - end - elseif isa(model_var, 'SMBmeltcomponents') - write_string_to_netcdf('smb_class_name', 'SMBmeltcomponents', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBmeltcomponents') - end - elseif isa(model_var, 'SMBpdd') - write_string_to_netcdf('smb_class_name', 'SMBpdd', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBpdd') - end - elseif isa(model_var, 'SMBpddSicopolis') - write_string_to_netcdf('smb_class_name', 'SMBpddSicopolis', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBpddSicopolis') - end - elseif isa(model_var, 'SMBsemic') - write_string_to_netcdf('smb_class_name', 'SMBsemic', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved smb class instance SMBsemic') - end +function write_numeric(val, vname, gid, root_ncid, path_str, verbose) + % MATLAB stores data in column-major order; NetCDF uses row-major. + % We transpose so Python reads the same shape as MATLAB. + if isempty(val) + write_scalar_nan(vname, gid, root_ncid); + return end - % Set the persistent variable to indicate that the function has been executed - executed = true; -end -end + data = double(val); -function check_friction_class(model_var, NetCDF, verbose) -% Define a persistent variable to ensure this function is only run once -persistent executed; -% Check if the function has already been executed -if isempty(executed) - if verbose - disp('Deconstructing friction class instance') - end - % Need to make sure that we have the right friction class - groupid = netcdf.inqNcid(NetCDF,'friction'); - if isa(model_var, 'friction') - write_string_to_netcdf('friction_class_name', 'friction', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance friction') - end - elseif isa(model_var, 'frictioncoulomb') - write_string_to_netcdf('friction_class_name', 'frictioncoulomb', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictioncoulomb') - end - elseif isa(model_var, 'frictioncoulomb2') - write_string_to_netcdf('friction_class_name', 'frictioncoulomb2', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictioncoulomb2') - end - elseif isa(model_var, 'frictionhydro') - write_string_to_netcdf('friction_class_name', 'frictionhydro', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionhydro') - end - elseif isa(model_var, 'frictionjosh') - write_string_to_netcdf('friction_class_name', 'frictionjosh', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionjosh') - end - elseif isa(model_var, 'frictionpism') - write_string_to_netcdf('friction_class_name', 'frictionpism', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionpism') - end - elseif isa(model_var, 'frictionregcoulomb') - write_string_to_netcdf('friction_class_name', 'frictionregcoulomb', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionregcoulomb') - end - elseif isa(model_var, 'frictionregcoulomb2') - write_string_to_netcdf('friction_class_name', 'frictionregcoulomb2', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionregcoulomb2') - end - elseif isa(model_var, 'frictionschoof') - write_string_to_netcdf('friction_class_name', 'frictionschoof', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionschoof') - end - elseif isa(model_var, 'frictionshakti') - write_string_to_netcdf('friction_class_name', 'frictionshakti', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionshakti') - end - elseif isa(model_var, 'frictiontsai') - write_string_to_netcdf('friction_class_name', 'frictiontsai', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictiontsai') - end - elseif isa(model_var, 'frictionwaterlayer') - write_string_to_netcdf('friction_class_name', 'frictionwaterlayer', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionwaterlayer') - end - elseif isa(model_var, 'frictionweertman') - write_string_to_netcdf('friction_class_name', 'frictionweertman', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionweertman') - end - elseif isa(model_var, 'frictionweertmantemp') - write_string_to_netcdf('friction_class_name', 'frictionweertmantemp', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved friction class instance frictionweertmantemp') - end + % Flatten trailing singleton dimensions (keep at least 2 dims for reshape) + sz = size(data); + while numel(sz) > 2 && sz(end) == 1 + sz = sz(1:end-1); end - % Set the persistent variable to indicate that the function has been executed - executed = true; -end -end + data = reshape(data, sz); -function check_hydrology_class(model_var, NetCDF, verbose) -% Define a persistent variable to ensure this function is only run once -persistent executed; -% Check if the function has already been executed -if isempty(executed) - if verbose - disp('Deconstructing hydrology class instance') + % Transpose for row-major storage (only for 2D) + if ndims(data) == 2 && ~any(sz == 1) + data = data.'; + sz = size(data); + elseif any(sz == 1) && numel(sz) == 2 + % Vector: store as 1-D + data = data(:); + sz = numel(data); end - % Need to make sure that we have the right hydrology class - groupid = netcdf.inqNcid(NetCDF,'hydrology'); - if isa(model_var, 'hydrologyshreve') - write_string_to_netcdf('hydrology_class_name', 'hydrologyshreve', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved hydrology class instance hydrologyshreve') - end - elseif isa(model_var, 'hydrology') - write_string_to_netcdf('hydrology_class_name', 'hydrology', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved hydrology class instance hydrology') - end - elseif isa(model_var, 'hydrologyarmapw') - write_string_to_netcdf('hydrology_class_name', 'hydrologyarmapw', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved hydrology class instance hydrologyarmapw') - end - elseif isa(model_var, 'hydrologydc') - write_string_to_netcdf('hydrology_class_name', 'hydrologydc', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved hydrology class instance hydrologydc') - end - elseif isa(model_var, 'hydrologyglads') - write_string_to_netcdf('hydrology_class_name', 'hydrologyglads', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved hydrology class instance hydrologyglads') - end - elseif isa(model_var, 'hydrologypism') - write_string_to_netcdf('hydrology_class_name', 'hydrologypism', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved hydrology class instance hydrologypism') - end - elseif isa(model_var, 'hydrologyshakti') - write_string_to_netcdf('hydrology_class_name', 'hydrologyshakti', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved hydrology class instance hydrologyshakti') - end - elseif isa(model_var, 'hydrologytws') - write_string_to_netcdf('hydrology_class_name', 'hydrologytws', groupid, NetCDF, verbose); - if verbose - disp('Successfully saved hydrology class instance hydrologytws') - end + dim_ids = make_dims(sz, gid, root_ncid); + + varid = netcdf.defVar(gid, vname, 'NC_DOUBLE', dim_ids); + if numel(data) > 1 + netcdf.defVarDeflate(gid, varid, true, true, 4); end - % Set the persistent variable to indicate that the function has been executed - executed = true; -end + netcdf.putVar(gid, varid, data); end -function create_var(variable_name, address_of_child, group, NetCDF, verbose) - % There are lots of different variable types that we need to handle from the model class - - % get the dimensions we'll need - intdim = netcdf.inqDimID(NetCDF,'int'); - floatdim = netcdf.inqDimID(NetCDF,'float'); - unlimdim = netcdf.inqDimID(NetCDF,'Unlim'); - - % This first conditional statement will catch numeric arrays (matrices) of any dimension and save them - if any(size(address_of_child)>1) && ~iscellstr(address_of_child) && ~ischar(address_of_child) - write_numeric_array_to_netcdf(variable_name, address_of_child, group, NetCDF, verbose); - - % check if it's a string - elseif ischar(address_of_child) - write_string_to_netcdf(variable_name, address_of_child, group, NetCDF, verbose); - - % or an empty variable - elseif isempty(address_of_child) - variable = netcdf.defVar(group, variable_name, "NC_DOUBLE", intdim); - - % or a list of strings - elseif iscellstr(address_of_child) || iscell(address_of_child) && ischar(address_of_child{1}) - write_cell_with_strings(variable_name, address_of_child, group, NetCDF, verbose) - - % or an empty list - elseif iscell(address_of_child) && isempty(address_of_child) || isa(address_of_child, 'double') && isempty(address_of_child) - variable = netcdf.defVar(group, variable_name, "NC_INT", intdim); - netcdf.putVar(group,variable, -32767); - - % or a bool - elseif islogical(address_of_child) - % netcdf4 can't handle bool types like true/false so we convert all to int 1/0 and add an attribute named units with value 'bool' - variable = netcdf.defVar(group, variable_name, 'NC_SHORT', intdim); - netcdf.putVar(group,variable,int8(address_of_child)); - % make sure other systems can flag the bool type - netcdf.putAtt(group,variable,'units','bool'); - - % or a regular list - elseif iscell(address_of_child) - disp('made list w/ unlim dim') - variable = netcdf.defVar(group, variable_name, "NC_DOUBLE", unlimdim); - netcdf.putVar(group,variable,address_of_child); - - % or a float - elseif isfloat(address_of_child) && numel(address_of_child) == 1 - variable = netcdf.defVar(group, variable_name, "NC_DOUBLE", floatdim); - netcdf.putVar(group,variable,address_of_child); - - % or a int - elseif mod(address_of_child,1) == 0 || isinteger(address_of_child) && numel(address_of_child) == 1 - variable = netcdf.defVar(group, variable_name, "NC_SHORT", intdim); - netcdf.putVar(group,variable,address_of_child); - - % anything else... (will likely need to add more cases; ie dict) - else + +function write_string(str, vname, gid, root_ncid, path_str, verbose) + if isempty(str) + % Zero-length string: store empty char variable + dim_name = 'char0'; try - variable = netcdf.defVar(group, variable_name, "NC_DOUBLE", unlimdim); - netcdf.putVar(group,variable,address_of_child); - catch ME - disp(ME.message); - disp(['Datatype given: ', class(address_of_child)]); + dimid = netcdf.defDim(gid, dim_name, 0); + catch + dimid = netcdf.inqDimID(gid, dim_name); end + netcdf.defVar(gid, vname, 'NC_CHAR', dimid); + return end - if verbose - fprintf('Successfully transferred data from %s to the NetCDF\n', variable_name); + n = numel(str); + dim_name = sprintf('char%d', n); + try + dimid = netcdf.defDim(gid, dim_name, n); + catch + dimid = netcdf.inqDimID(gid, dim_name); end + varid = netcdf.defVar(gid, vname, 'NC_CHAR', dimid); + netcdf.putVar(gid, varid, str); + netcdf.putAtt(gid, varid, 'type_is', 'string'); end -function write_cell_with_strings(variable_name, address_of_child, group, NetCDF, verbose) - %{ - Write cell array (ie {'one' 'two' 'three'}) to netcdf - %} - - if isempty(address_of_child) - % if the char array is empty, save an empty char - name_of_dimension = ['char', num2str(0)]; +function write_cell_strings(val, vname, gid, root_ncid, path_str, verbose) + if isempty(val) + dim_name = 'char0'; try - dimID = netcdf.defDim(group, name_of_dimension, 0); + dimid = netcdf.defDim(gid, dim_name, 0); catch - dimID = netcdf.inqDimID(group, name_of_dimension); + dimid = netcdf.inqDimID(gid, dim_name); end - % Now we can make a variable in this dimension: - string_var = netcdf.defVar(group, variable_name, "NC_CHAR", [dimID]); - % we leave empty now - else - % covert data to char array - method_ID = char(address_of_child); - - % make dimensions - [rows, cols] = size(method_ID); - - IDDim1 = netcdf.defDim(group,'cols',cols); - IDDim2 = netcdf.defDim(group,'rows',rows); - - % create the variable slot - IDVarId = netcdf.defVar(group,variable_name,'NC_CHAR', [IDDim1 IDDim2]); - - % save the variable - netcdf.putVar(group, IDVarId, method_ID'); %transpose - - % tell other platforms that this is a cell of strings - netcdf.putAtt(group, IDVarId, 'type_is','cell_array_of_strings'); + varid = netcdf.defVar(gid, vname, 'NC_CHAR', dimid); + netcdf.putAtt(gid, varid, 'type_is', 'cell_of_strings'); + return end -end + % Pad all strings to the same length, store as NC_CHAR rows×cols + strs = cellstr(val); + nrows = numel(strs); + max_len = max(cellfun(@numel, strs)); + if max_len == 0, max_len = 1; end + char_mat = repmat(' ', nrows, max_len); + for k = 1:nrows + s = strs{k}; + char_mat(k, 1:numel(s)) = s; + end -function write_string_to_netcdf(variable_name, address_of_child, group, NetCDF, verbose) - % netcdf and strings don't get along.. we have to do it 'custom': + % NC dims: [cols rows] because netcdf.putVar transposes + try + dim_cols = netcdf.defDim(gid, sprintf('strcols_%s', vname), max_len); + catch + dim_cols = netcdf.inqDimID(gid, sprintf('strcols_%s', vname)); + end + try + dim_rows = netcdf.defDim(gid, sprintf('strrows_%s', vname), nrows); + catch + dim_rows = netcdf.inqDimID(gid, sprintf('strrows_%s', vname)); + end - the_string_to_save = address_of_child; + varid = netcdf.defVar(gid, vname, 'NC_CHAR', [dim_cols dim_rows]); + netcdf.putVar(gid, varid, char_mat.'); % transpose for MATLAB→NetCDF + netcdf.putAtt(gid, varid, 'type_is', 'cell_of_strings'); +end - if isempty(the_string_to_save) - % if the char array is empty, save an empty char - name_of_dimension = ['char', num2str(0)]; - try - dimID = netcdf.defDim(group, name_of_dimension, 0); - catch - dimID = netcdf.inqDimID(group, name_of_dimension); - end - % Now we can make a variable in this dimension: - string_var = netcdf.defVar(group, variable_name, "NC_CHAR", [dimID]); - % we leave empty now + +function write_bool(val, vname, gid, root_ncid, path_str, verbose) + if isscalar(val) + scalardim = netcdf.inqDimID(root_ncid, 'scalar'); + varid = netcdf.defVar(gid, vname, 'NC_SHORT', scalardim); + netcdf.putVar(gid, varid, int16(val)); else - % convert string to - uint_method=uint8(the_string_to_save).'; - method_ID = char(uint_method); - length_of_the_string = numel(method_ID); - - % Convert the string to character data using string array - %str_out = char(the_string_to_save) - - % Determine the length of the string - %length_of_the_string = numel(str_out) - - % Check if the dimension already exists, and if not, create it - name_of_dimension = ['char', num2str(length_of_the_string)]; + data = int16(val(:)); + n = numel(data); try - dimID = netcdf.defDim(group, name_of_dimension, length_of_the_string); + dimid = netcdf.defDim(gid, sprintf('booldim%d', n), n); catch - dimID = netcdf.inqDimID(group, name_of_dimension); + dimid = netcdf.inqDimID(gid, sprintf('booldim%d', n)); end - % Now we can make a variable in this dimension: - string_var = netcdf.defVar(group, variable_name, "NC_CHAR", [dimID]); - % Finally, we can write the variable (always transpose for matlab): - netcdf.putVar(group, string_var, method_ID); + varid = netcdf.defVar(gid, vname, 'NC_SHORT', dimid); + netcdf.putVar(gid, varid, data); end + netcdf.putAtt(gid, varid, 'type_is', 'bool'); +end - if verbose - disp(['Successfully transferred data from ', variable_name, ' to the NetCDF']); - end + +function write_scalar_nan(vname, gid, root_ncid) + scalardim = netcdf.inqDimID(root_ncid, 'scalar'); + varid = netcdf.defVar(gid, vname, 'NC_DOUBLE', scalardim); + netcdf.putVar(gid, varid, NaN); + netcdf.putAtt(gid, varid, 'type_is', 'empty'); end -function write_numeric_array_to_netcdf(variable_name, address_of_child, group, NetCDF, verbose) - - % get the dimensions we'll need - intdim = netcdf.inqDimID(NetCDF,'int'); - floatdim = netcdf.inqDimID(NetCDF,'float'); - unlimdim = netcdf.inqDimID(NetCDF,'Unlim'); - - typeis = class(address_of_child); - - if isa(typeis, 'logical') - % because matlab transposes all data into and out of netcdf and because we want cross-platform-compat - % we need to transpose data before it goes into netcdf - data = address_of_child.'; - - % make the dimensions - dimensions = []; - for dimension = size(data) - dim_name = ['dim',int2str(dimension)]; - % if the dimension already exists we can't have a duplicate +% ===================================================================== +% Helpers +% ===================================================================== + +function dim_ids = make_dims(sz, gid, root_ncid) + % Create or reuse dimensions for an array of size sz. + % sz must be a row vector of positive integers. + dim_ids = zeros(1, numel(sz)); + for k = 1:numel(sz) + n = sz(k); + if n == 1 + dim_ids(k) = netcdf.inqDimID(root_ncid, 'scalar'); + else + dim_name = sprintf('dim%d', n); + % Try in the local group first, then root + try + dim_ids(k) = netcdf.defDim(gid, dim_name, n); + catch try - dimID = netcdf.defDim(group, dim_name, dimension); + dim_ids(k) = netcdf.inqDimID(gid, dim_name); catch - dimID = netcdf.inqDimID(group, dim_name); - end - % record the dimension for the variable - dimensions(end+1) = dimID; - end - - % write the variable - netcdf.putVar(group,variable,data); - - % make sure other systems can flag the bool type - netcdf.putAtt(group,variable,'units','bool'); - - % handle all other datatypes here - else - % sometimes an array has just 1 element in it, we account for those cases here: - if numel(address_of_child) == 1 - if isinteger(address_of_child) - variable = netcdf.defVar(group, variable_name, "NC_SHORT", intdim); - netcdf.putVar(group,variable,address_of_child); - elseif isa(address_of_child, 'double') || isa(address_of_child, 'float') - variable = netcdf.defVar(group, variable_name, "NC_DOUBLE", floatdim); - netcdf.putVar(group,variable,address_of_child); - else - disp('Encountered single datatype that was not float64 or int64, saving under unlimited dimension, may cause errors.') - variable = netcdf.defVar(group, variable_name, "NC_DOUBLE", unlimdim); - netcdf.putVar(group,variable,address_of_child); - end - % this is in case of lists so that python doesn't get a (nx1) numpy array and instead gets an n-element list - elseif any(size(address_of_child)==1) - % because matlab transposes all data into and out of netcdf and because we want cross-platform-compat - % we need to transpose data before it goes into netcdf - data = address_of_child.'; - - % make the dimensions - dimensions = []; - for dimension = size(data) - if dimension ~= 1 - dim_name = ['dim',int2str(dimension)]; - % if the dimension already exists we can't have a duplicate try - dimID = netcdf.defDim(group, dim_name, dimension); + dim_ids(k) = netcdf.defDim(root_ncid, dim_name, n); catch - dimID = netcdf.inqDimID(group, dim_name); + dim_ids(k) = netcdf.inqDimID(root_ncid, dim_name); end - % record the dimension for the variable - dimensions(end+1) = dimID; - end - end - % create the variable - variable = netcdf.defVar(group, variable_name, "NC_DOUBLE",dimensions); - - % write the variable - netcdf.putVar(group,variable,data); - - % This catches all remaining arrays: - else - % because matlab transposes all data into and out of netcdf and because we want cross-platform-compat - % we need to transpose data before it goes into netcdf - data = address_of_child.'; - - % make the dimensions - dimensions = []; - for dimension = size(data) - dim_name = ['dim',int2str(dimension)]; - % if the dimension already exists we can't have a duplicate - try - dimID = netcdf.defDim(group, dim_name, dimension); - catch - dimID = netcdf.inqDimID(group, dim_name); end - % record the dimension for the variable - dimensions(end+1) = dimID; end - % create the variable - variable = netcdf.defVar(group, variable_name, "NC_DOUBLE",dimensions); - - % write the variable - netcdf.putVar(group,variable,data); end end end + + +function gid = get_or_create_group(parent_gid, name) + try + gid = netcdf.defGrp(parent_gid, name); + catch + gid = netcdf.inqNcid(parent_gid, name); + end +end diff --git a/src/m/netcdf/write_netCDF.py b/src/m/netcdf/write_netCDF.py index f3817e0c2..25c0d8552 100644 --- a/src/m/netcdf/write_netCDF.py +++ b/src/m/netcdf/write_netCDF.py @@ -1,595 +1,405 @@ -# imports -import netCDF4 -from netCDF4 import Dataset -import numpy as np -import numpy.ma as ma -import time +""" +write_netCDF – Save an ISSM model to a NetCDF4 file. + +Usage +----- + from write_netCDF import write_netCDF + write_netCDF(md, 'model.nc') + write_netCDF(md, 'model.nc', verbose=True) + +The file can be read back with read_netCDF.py (Python) or read_netCDF.m (MATLAB). + +NetCDF layout +------------- +Each attribute of md (mesh, mask, geometry, …) becomes a NetCDF group. +Attributes within those objects are stored as variables inside the group. +Nested sub-classes get nested sub-groups. + +Every group carries a 'classtype' global attribute with the Python class name +so that read_netCDF can reconstruct the correct object on load. + +Results storage +--------------- +md.results. is a solution() instance whose .steps list holds +solutionstep() objects. Each step is stored as a sub-group named 'step_' +inside the solution sub-group. +""" + import os -from model import * -from results import * -from m1qn3inversion import m1qn3inversion -from taoinversion import taoinversion -#import OrderedStruct +import time +import numpy as np +from netCDF4 import Dataset + + +def write_netCDF(md, filename: str, verbose: bool = False) -> None: + """Save model *md* to *filename* (NetCDF4). Overwrites silently.""" + if verbose: + print('write_netCDF v2.0 (Python)') + + # Overwrite silently + if os.path.exists(filename): + os.remove(filename) + if verbose: + print(f'Existing file {filename} deleted.') + + nc = Dataset(filename, 'w', format='NETCDF4') + try: + nc.history = 'Created by write_netCDF.py on ' + time.ctime() + nc.Conventions = 'ISSM-NetCDF-2.0' + + # Global dimensions reused throughout the file + nc.createDimension('scalar', 1) + nc.createDimension('Unlim', None) # unlimited + + # Walk every top-level attribute of the model + for gname, val in md.__dict__.items(): + if val is None: + if verbose: + print(f' md.{gname} is None – skipped') + continue + grp = nc.createGroup(gname) + grp.classtype = type(val).__name__ -''' -Given a md, this set of functions will perform the following: - 1. View each attribute of each nested class. - 2. Compare state of attribute in the model to an empty model. - 3. If states are identical, pass. (except for np arrays which will always be saved) - 4. Otherwise, create nested groups named after class structure. - 5. Create variable named after class attribute and assign value to it. -''' + _write_obj(val, grp, nc, f'md.{gname}', verbose) + except Exception: + nc.close() + raise -def write_netCDF(md, filename: str, verbose = False): + nc.close() if verbose: - print('Python C2NetCDF4 v1.2.0') - else: pass - ''' - md = model class instance to be saved - filename = path and name to save file under - verbose = T/F = show or muted log statements. Naturally muted - ''' - # this is a precaution so that data is not lost + print('Model successfully saved as NetCDF4.') + + +# ===================================================================== +# _write_obj – write all attributes of a Python object into a group +# ===================================================================== +def _write_obj(obj, grp, root_nc, path: str, verbose: bool) -> None: + """Iterate over obj.__dict__ and write each attribute into *grp*.""" try: - # Create a NCData file to write to - NCData = create_NetCDF(filename, verbose) - - # Create an instance of an empty md class to compare md_var against - empty_model = model() - - # Walk through the md class and compare subclass states to empty_model - walk_through_model(md, empty_model, NCData, verbose) - - # in order to handle some subclasses in the results class, we have to utilize this band-aid - # there will likely be more band-aids added unless a class name library is created with all class names that might be added to a md - try: - # if results has meaningful data, save the name of the subclass and class instance - NCData.groups['results'] - results_subclasses_bandaid(md, NCData, verbose) - # otherwise, ignore - except KeyError: - pass - - NCData.close() - if verbose: - print('Model successfully saved as NetCDF4') - else: pass - - # just in case something unexpected happens - except Exception as e: - if 'NCData' in locals(): - NCData.close() - raise e - - -def results_subclasses_bandaid(md, NCData, verbose = False): - # since the results class may have nested classes within it, we need to record the name of the - # nested class instance variable as it appears in the md that we're trying to save - quality_control = [] - - # we save lists of instances to the NCData - solutions = [] - solutionsteps = [] - resultsdakotas = [] - - for class_instance_name in md.results.__dict__.keys(): + items = obj.__dict__.items() + except AttributeError: + return # not an object with attributes + + for fname, val in items: + if fname in ('errlog', 'outlog'): + continue + _write_value(val, fname, grp, root_nc, f'{path}.{fname}', verbose) + + +# ===================================================================== +# _write_value – dispatch a single value to the right writer +# ===================================================================== +def _write_value(val, vname: str, grp, root_nc, path: str, verbose: bool) -> None: + + # ---- None / empty ----------------------------------------------- + if val is None: + _write_scalar_nan(vname, grp, root_nc) if verbose: - print(class_instance_name) - # for each class instance in results, see which class its from and record that info in the NCData to recreate structure later - # check to see if there is a solutionstep class instance - if isinstance(md.results.__dict__[class_instance_name],solutionstep): - quality_control.append(1) - solutionsteps.append(class_instance_name) - - # check to see if there is a solution class instance - if isinstance(md.results.__dict__[class_instance_name],solution): - quality_control.append(1) - solutions.append(class_instance_name) - - # check to see if there is a resultsdakota class instance - if isinstance(md.results.__dict__[class_instance_name],resultsdakota): - quality_control.append(1) - resultsdakotas.append(class_instance_name) - - if solutionsteps != []: - serialize_string(variable_name=str('solutionstep'), address_of_child=solutionsteps, group=NCData.groups['results'], list=True, NCData=NCData, verbose=verbose) - - if solutions != []: - serialize_string(variable_name=str('solution'), address_of_child=solutions, group=NCData.groups['results'], list=True, NCData=NCData, verbose=verbose) - - if resultsdakotas != []: - serialize_string(variable_name=str('resultsdakota'), address_of_child=resultsdakotas, group=NCData.groups['results'], list=True, NCData=NCData, verbose=verbose) - - - if len(quality_control) != len(md.results.__dict__.keys()): - print('Error: The class instance within your md.results class is not currently supported by this application') - print(type(md.results.__dict__[class_instance_name])) - else: + print(f' [None] {path}') + return + + # ---- numpy ndarray ---------------------------------------------- + if isinstance(val, np.ndarray): + _write_numpy(val, vname, grp, root_nc, path, verbose) + return + + # ---- bool (must come before int because bool is a subclass of int) + if isinstance(val, (bool, np.bool_)): + _write_bool(np.array([int(val)], dtype=np.int16), vname, grp, root_nc) if verbose: - print('The results class was successfully stored on disk') - else: pass + print(f' [bool] {path}') + return + # ---- int / float scalars ---------------------------------------- + if isinstance(val, (int, np.integer)): + _write_scalar(int(val), vname, 'i8', grp, root_nc) + if verbose: + print(f' [int] {path}') + return -def create_NetCDF(filename: str, verbose = False): - # If file already exists delete / rename it - if os.path.exists(filename): - print('File {} allready exist'.format(filename)) - - # If so, inqure for a new name or to do delete the existing file - newname = input('Give a new name or "delete" to replace: ') + if isinstance(val, (float, np.floating)): + _write_scalar(float(val), vname, 'f8', grp, root_nc) + if verbose: + print(f' [float] {path}') + return - if newname == 'delete': - os.remove(filename) - else: - print(('New file name is {}'.format(newname))) - filename = newname - else: - # Otherwise create the file and define it globally so other functions can call it - NCData = Dataset(filename, 'w', format='NETCDF4') - NCData.history = 'Created ' + time.ctime(time.time()) - NCData.createDimension('Unlim', None) # unlimited dimension - NCData.createDimension('float', 1) # single integer dimension - NCData.createDimension('int', 1) # single float dimension - + # ---- str -------------------------------------------------------- + if isinstance(val, str): + _write_string(val, vname, grp) + if verbose: + print(f' [string] {path}') + return + + # ---- list ------------------------------------------------------- + if isinstance(val, list): + _write_list(val, vname, grp, root_nc, path, verbose) + return + + # ---- dict / OrderedDict ----------------------------------------- + if isinstance(val, dict): + _write_dict(val, vname, grp, root_nc, path, verbose) + return + + # ---- ISSM sub-class (has __dict__) ------------------------------ + if hasattr(val, '__dict__'): + sub_grp = grp.createGroup(vname) + sub_grp.classtype = type(val).__name__ + _write_obj(val, sub_grp, root_nc, path, verbose) + return + + # ---- fallback --------------------------------------------------- if verbose: - print('Successfully created ' + filename) + print(f' [SKIP] {path} – unsupported type {type(val).__name__}') - return NCData +# ===================================================================== +# _write_list – dispatch a Python list +# ===================================================================== +def _write_list(val: list, vname: str, grp, root_nc, path: str, verbose: bool) -> None: + if len(val) == 0: + # Empty list: store as a scalar NaN sentinel + _write_scalar_nan(vname, grp, root_nc) + return -def walk_through_model(md, empty_model, NCData, verbose= False): - # Iterate over first layer of md attributes and assume this first layer is only classes - for group in md.__dict__.keys(): - address = md.__dict__[group] - empty_address = empty_model.__dict__[group] - # we need to record the layers of the md so we can save them to the NCData file - layers = [group] + first = val[0] - # Recursively walk through subclasses - walk_through_subclasses(address, empty_address, layers, NCData, empty_model, verbose) + # list of ISSM objects → cell_of_objects group + if hasattr(first, '__dict__') and not isinstance(first, dict): + _write_cell_of_objects(val, vname, grp, root_nc, path, verbose) + return + # list of str + if isinstance(first, str): + _write_cell_strings(val, vname, grp) + if verbose: + print(f' [cellstr] {path}') + return -def walk_through_subclasses(address, empty_address, layers: list, NCData, empty_model, verbose = False): - # See if we have an object with keys or a not - try: - address.__dict__.keys() - is_object = True - except: is_object = False # this is not an object with keys - - if is_object: - # enter the subclass, see if it has nested classes and/or attributes - # then compare attributes between mds and write to NCData if they differ - # if subclass found, walk through it and repeat - for child in address.__dict__.keys(): - # record the current location - current_layer = layers.copy() - current_layer.append(child) - - # navigate to child in each md - address_of_child = address.__dict__[child] - - # if the current object is a results. object and has nonzero steps attr it needs special treatment - if isinstance(address_of_child, solution) and len(address_of_child.steps) != 0: - create_group(address_of_child, current_layer, is_struct = True, is_special_list = False, NCData=NCData, verbose = verbose) - - # if the current object is a list of objects (currently only filters for lists/arrays of classes) - elif isinstance(address_of_child, list) and len(address_of_child) > 0 and hasattr(address_of_child[0], '__dict__'): - create_group(address_of_child, current_layer, is_struct = False, is_special_list = True, NCData=NCData, verbose = verbose) - - # if the variable is an array, assume it has relevant data (this is because the next line cannot evaluate "==" with an array) - elif isinstance(address_of_child, np.ndarray): - create_group(address_of_child, current_layer, is_struct = False, is_special_list = False, NCData=NCData, verbose = verbose) - - # see if the child exists in the empty md. If not, record it in the NCData - else: - try: - address_of_child_in_empty_class = empty_address.__dict__[child] - # if that line worked, we can see how the mds' attributes at this layer compare: - - # if the attributes are identical we don't need to save anything - if address_of_child == address_of_child_in_empty_class: - walk_through_subclasses(address_of_child, address_of_child_in_empty_class, current_layer, NCData, empty_model, verbose) - - # If it has been modified, record it in the NCData file - else: - create_group(address_of_child, current_layer, is_struct = False, is_special_list = False, NCData=NCData, verbose = verbose) - walk_through_subclasses(address_of_child, address_of_child_in_empty_class, current_layer, NCData, empty_model, verbose) - - except KeyError: # record in NCData and continue to walk thru md - walk_through_subclasses(address_of_child, empty_address, current_layer, NCData, empty_model, verbose) - create_group(address_of_child, current_layer, is_struct = False, is_special_list = False, NCData=NCData, verbose = verbose) - else: pass - - -def create_group(address_of_child, layers, is_struct = False, is_special_list = False, NCData=None, verbose = False): - - # Handle the first layer of the group(s) - group_name = layers[0] - - # try to make a group unless the group is already made + # list of solution-step objects (results.solution.steps) + # This is handled by _write_solution_steps when the parent is a solution(); + # if we land here generically, treat as cell_of_objects + if hasattr(first, '__dict__'): + _write_cell_of_objects(val, vname, grp, root_nc, path, verbose) + return + + # Plain numeric list → convert to numpy array try: - group = NCData.createGroup(str(group_name)) - except: - group = NCData.groups[str(group_name)] - - # need to check if inversion or m1qn3inversion class - if group_name == 'inversion': - check_inversion_class(address_of_child, NCData, verbose) - else: pass - - # if the data is nested in md, create nested groups to match class structure - if len(layers) > 2: - for name in layers[1:-1]: - try: - group = group.createGroup(str(name)) - except: - group = NCData.groups[str(name)] - else: pass - - # Lastly, handle the variable(s) - if is_struct: - parent_struct_name = layers[-1] - serialize_nested_results_struct(parent_struct_name, address_of_child, group, NCData, verbose) - - elif is_special_list: - list_name = layers[-1] - serialize_array_of_objects(list_name, address_of_child, group, NCData, verbose) - - else: - variable_name = layers[-1] - serialize_var(variable_name, address_of_child, group, NCData, verbose) - - -def singleton(func): - """ - A decorator to ensure a function is only executed once. - """ - def wrapper(*args, **kwargs): - if not wrapper.has_run: - wrapper.result = func(*args, **kwargs) - wrapper.has_run = True - return wrapper.result - wrapper.has_run = False - wrapper.result = None - return wrapper - - -@singleton -def check_inversion_class(address_of_child, NCData, verbose = False): - # need to make sure that we have the right inversion class: inversion, m1qn3inversion, taoinversion - if isinstance(address_of_child, m1qn3inversion): - serialize_string(variable_name=str('inversion_class_name'), address_of_child=str('m1qn3inversion'), group=NCData.groups['inversion'], NCData=NCData, verbose = verbose) + arr = np.array(val) + _write_numpy(arr, vname, grp, root_nc, path, verbose) + except Exception: if verbose: - print('Successfully saved inversion class instance ' + 'm1qn3inversion') - elif isinstance(address_of_child, taoinversion): - serialize_string(variable_name=str('inversion_class_name'), address_of_child=str('taoinversion'), group=NCData.groups['inversion'], NCData=NCData, verbose = verbose) - if verbose: - print('Successfully saved inversion class instance ' + 'taoinversion') - else: - serialize_string(variable_name=str('inversion_class_name'), address_of_child=str('inversion'), group=NCData.groups['inversion'], NCData=NCData, verbose = verbose) - if verbose: - print('Successfully saved inversion class instance ' + 'inversion') + print(f' [SKIP] {path} – list of mixed/unsupported types') -def serialize_nested_results_struct(parent_struct_name, address_of_struct, group, NCData, verbose = False): - ''' - This function takes a results.solution class instance and saves the solutionstep instances from .steps to the NCData. +# ===================================================================== +# Solution / solutionstep special handling +# ===================================================================== +def _write_obj_with_results(obj, grp, root_nc, path: str, verbose: bool) -> None: + """Like _write_obj but handles solution().steps lists as step_k subgroups.""" + try: + items = obj.__dict__.items() + except AttributeError: + return + + for fname, val in items: + if fname in ('errlog', 'outlog'): + continue + + # Detect a list of solutionstep-like objects + if (isinstance(val, list) and len(val) > 0 + and hasattr(val[0], '__dict__') + and not isinstance(val[0], dict)): + _write_solution_steps(val, fname, grp, root_nc, path, verbose) + else: + _write_value(val, fname, grp, root_nc, f'{path}.{fname}', verbose) - To do this, we get the number of dimensions (substructs) of the parent struct (list). - Next, we iterate through each substruct and record the data. - For each substruct, we create a subgroup of the main struct. - For each variable, we create dimensions that are assigned to each subgroup uniquely. - ''' - if verbose: - print("Beginning transfer of nested MATLAB struct to the NCData") - - # make a new subgroup to contain all the others: - group = group.createGroup(str(parent_struct_name)) - - # make sure other systems can flag the nested struct type - serialize_string('this_is_a_nested', 'struct', group, list=False, NCData=NCData, verbose = verbose) - - # other systems know the name of the parent struct because it's covered by the results/qmu functions above - no_of_dims = len(address_of_struct) - for substruct in range(0, no_of_dims): - # we start by making subgroups with nice names like "1x4" - name_of_subgroup = '1x' + str(substruct) - subgroup = group.createGroup(str(name_of_subgroup)) - - # do some housekeeping to keep track of the current layer - current_substruct = address_of_struct[substruct] - substruct_fields = current_substruct.__dict__.keys() - - # now we need to iterate over each variable of the nested struct and save it to this new subgroup - for variable in substruct_fields: - address_of_child = current_substruct.__dict__[variable] - serialize_var(variable, address_of_child, subgroup, NCData, verbose = verbose) - - if verbose: - print(f'Successfully transferred struct {parent_struct_name} to the NCData\n') +def _write_solution_steps(steps: list, vname: str, grp, root_nc, path: str, verbose: bool) -> None: + """Write a list of solutionstep objects as step_1, step_2, … sub-groups.""" + sub_grp = grp.createGroup(vname) + sub_grp.classtype = 'struct' # MATLAB struct array convention + sub_grp.nsteps = len(steps) + for k, step in enumerate(steps, start=1): + sg = sub_grp.createGroup(f'step_{k}') + for sfield, sval in step.__dict__.items(): + if sfield in ('errlog', 'outlog'): + continue + _write_value(sval, sfield, sg, root_nc, f'{path}.step_{k}.{sfield}', verbose) + if verbose: + print(f' [struct] {path}.{vname} ({len(steps)} steps)') -def serialize_array_of_objects(list_name, address_of_child, group, NCData, verbose): - if verbose: - print(f"Serializing array of objects.") - - # Get the dimensions of the cell array - if len(np.shape(address_of_child)) > 1: - rows, cols = np.shape(address_of_child) - else: rows, cols = 1, np.shape(address_of_child)[0] - # Make subgroup to represent the array - name_of_subgroup = f"{str(rows)}x{str(cols)}_cell_array_of_objects" - subgroup = group.createGroup(name_of_subgroup) +# ===================================================================== +# Leaf writers +# ===================================================================== - # Save the name of the cell array - serialize_string('name_of_cell_array', list_name, subgroup, NCData, verbose) +def _write_numpy(arr: np.ndarray, vname: str, grp, root_nc, path: str, verbose: bool) -> None: + if arr.size == 0: + _write_scalar_nan(vname, grp, root_nc) + return - # Save the dimensions of the cell array - rowsID = subgroup.createVariable('rows', int, ('int',)) - colsID = subgroup.createVariable('cols', int, ('int',)) - rowsID[:] = rows - colsID[:] = cols + # Booleans → int16 + if arr.dtype == bool: + arr = arr.astype(np.int16) + is_bool = True + else: + is_bool = False + # Squeeze trailing size-1 dimensions; keep 0-d as scalar + arr = np.squeeze(arr) + if arr.ndim == 0: + arr = arr.reshape(1) - # If this is a multidimensional cell array, iterate over rows here and cols in serialize_objects - if rows > 1: - for row in range(rows): - # Make a subgroup for each row - name_of_subgroup = f"Row_{row+1}_of_{rows}" - subgroup = group.createGroup(name_of_subgroup) - serialize_objects(address_of_child, subgroup, NCData, cols, verbose) + # Determine NetCDF dtype + if np.issubdtype(arr.dtype, np.integer): + nc_dtype = 'i8' else: - serialize_objects(address_of_child, subgroup, NCData, cols, verbose) - + nc_dtype = 'f8' + arr = arr.astype(np.float64) + + dims = _make_dims(arr.shape, grp, root_nc) + + var = grp.createVariable(vname, nc_dtype, dims, zlib=(arr.size > 1)) + if is_bool: + var.type_is = 'bool' + var[:] = arr + if verbose: - print(f"Successfully serialized array of objects: {list_name}") + print(f' [numeric] {path} shape={arr.shape} dtype={arr.dtype}') -def serialize_objects(address_of_child, group, NCData, cols, verbose): - for col in range(cols): - # Make subgroup to contain each col of array - name_of_subgroup = f'Col_{col+1}_of_{cols}' - subgroup = group.createGroup(name_of_subgroup) +def _write_scalar(val, vname: str, nc_dtype: str, grp, root_nc) -> None: + var = grp.createVariable(vname, nc_dtype, ('scalar',)) + var[:] = val - # index the current item - variable = address_of_child[col] - # Get the kind of object we're working with: - # see if it's a solution instance - if isinstance(variable, solution) and len(variable.steps) != 0: - pass - # this needs more work... - - # see if it's a general class -- assume ISSM classes all have __dict__ - elif hasattr(variable, '__dict__'): - # Handle class instances - serialize_class_instance(variable, subgroup, NCData, verbose) - else: - print('ERROR: Cell arrays of mixed types are not yet supported in read_NCData!') - print('Deserialization will not be able to complete!') - # Handle regular data structures that are already supported - serialize_var(variable_name, variable, subgroup, NCData, verbose) - - -def serialize_class_instance(instance, group, NCData, verbose): - # get parent class name: - name = instance.__class__.__name__ - - # save the name of the class - serialize_string(variable_name='class_is_a', address_of_child=name, group=group, NCData=NCData, verbose = verbose) - - # make subgroup to contain attributes - name_of_subgroup = 'Properties_of_' + name - subgroup = group.createGroup(name_of_subgroup) - - # get attributes - keys = instance.__dict__.keys() - - for name in keys: - serialize_var(name, instance.__dict__[name], subgroup, NCData, verbose) - - - - -def serialize_var(variable_name, address_of_child, group, NCData, verbose = False): - # There are lots of different variable types that we need to handle from the md class - - # This first conditional statement will catch numpy arrays of any dimension and save them - if isinstance(address_of_child, np.ndarray): - serialize_numpy_array(variable_name, address_of_child, group, NCData, verbose=verbose) - - # check if it's an int - elif isinstance(address_of_child, int) or isinstance(address_of_child, np.integer): - variable = group.createVariable(variable_name, int, ('int',)) - variable[:] = address_of_child - - # or a float - elif isinstance(address_of_child, float) or isinstance(address_of_child, np.floating): - variable = group.createVariable(variable_name, float, ('float',)) - variable[:] = address_of_child - - # or a string - elif isinstance(address_of_child, str): - serialize_string(variable_name, address_of_child, group, NCData, verbose=verbose) - - #or a bool - elif isinstance(address_of_child, bool) or isinstance(address_of_child, np.bool_): - # NetCDF can't handle bool types like True/False so we convert all to int 1/0 and add an attribute named units with value 'bool' - variable = group.createVariable(variable_name, int, ('int',)) - variable[:] = int(address_of_child) - variable.units = "bool" - - # or an empty list - elif isinstance(address_of_child, list) and len(address_of_child)==0: - variable = group.createVariable(variable_name, int, ('int',)) - - # or a list of strings -- this needs work as it can only handle a list of 1 string - elif isinstance(address_of_child,list) and isinstance(address_of_child[0],str): - for string in address_of_child: - serialize_string(variable_name, string, group, list=True, NCData=NCData, verbose=verbose) - - # or a regular list - elif isinstance(address_of_child, list): - variable = group.createVariable(variable_name, type(address_of_child[0]), ('Unlim',)) - variable[:] = address_of_child - - # anything else... (will likely need to add more cases; ie helpers.OrderedStruct) - else: +def _write_scalar_nan(vname: str, grp, root_nc) -> None: + var = grp.createVariable(vname, 'f8', ('scalar',)) + var[:] = np.nan + var.type_is = 'empty' + + +def _write_string(s: str, vname: str, grp) -> None: + if len(s) == 0: + dim_name = 'char0' try: - variable = group.createVariable(variable_name, type(address_of_child), ('Unlim',)) - variable[:] = address_of_child - print(f'Unrecognized variable was saved {variable_name}') - except TypeError: pass # this would mean that we have an object, so we just let this continue to feed thru the recursive function above - except Exception as e: - print(f'There was error with {variable_name} in {group}') - print("The error message is:") - print(e) - print('Datatype given: ' + str(type(address_of_child))) - - if verbose: - print(f'Successfully transferred data from {variable_name} to the NCData') - - -def serialize_string(variable_name, address_of_child, group, list=False, NCData=None, verbose = False): - # NCData and strings dont get along.. we have to do it 'custom': - # if we hand it an address we need to do it this way: - if list: - """ - Convert a list of strings to a numpy.char_array with utf-8 encoded elements - and size rows x cols with each row the same # of cols and save to NCData - as char array. - """ + grp.createDimension(dim_name, 0) + except Exception: + pass + v = grp.createVariable(vname, 'S1', (dim_name,)) + v.type_is = 'string' + return + n = len(s) + dim_name = f'char{n}' + try: + grp.createDimension(dim_name, n) + except Exception: + pass + v = grp.createVariable(vname, 'S1', (dim_name,)) + from netCDF4 import stringtochar + v[:] = stringtochar(np.array([s], dtype=f'S{n}')) + v.type_is = 'string' + + +def _write_cell_strings(strings: list, vname: str, grp) -> None: + if not strings: + dim_name = 'char0' try: - strings = address_of_child - # get dims of array to save - rows = len(strings) - cols = len(max(strings, key = len)) - - # Define dimensions for the strings - rows_name = 'rows' + str(rows) - cols_name = 'cols' + str(cols) - try: - group.createDimension(rows_name, rows) - except: pass - - try: - group.createDimension(cols_name, cols) - except: pass - - # Create a variable to store the strings - string_var = group.createVariable(str(variable_name), 'S1', (rows_name, cols_name)) - - # break the list into a list of lists of words with the same length as the longest word: - # make words same sizes by adding spaces - modded_strings = [word + ' ' * (len(max(strings, key=len)) - len(word)) for word in strings] - # encoded words into list of encoded lists - new_list = [[s.encode('utf-8') for s in word] for word in modded_strings] - - # make numpy char array with dims rows x cols - arr = np.chararray((rows, cols)) - - # fill array with list of encoded lists - for i in range(len(new_list)): - arr[i] = new_list[i] - - # save array to NCData file - string_var[:] = arr - - if verbose: - print(f'Saved {len(modded_strings)} strings to {variable_name}') - - except Exception as e: - print(f'Error: {e}') - + grp.createDimension(dim_name, 0) + except Exception: + pass + v = grp.createVariable(vname, 'S1', (dim_name,)) + v.type_is = 'cell_of_strings' + return + + nrows = len(strings) + max_len = max(len(s) for s in strings) + if max_len == 0: + max_len = 1 + + rows_name = f'strrows_{vname}' + cols_name = f'strcols_{vname}' + try: + grp.createDimension(rows_name, nrows) + except Exception: + pass + try: + grp.createDimension(cols_name, max_len) + except Exception: + pass + + v = grp.createVariable(vname, 'S1', (rows_name, cols_name)) + v.type_is = 'cell_of_strings' + + arr = np.chararray((nrows, max_len)) + for i, s in enumerate(strings): + padded = s.ljust(max_len) + arr[i] = list(padded.encode('utf-8')) + v[:] = arr + + +def _write_bool(arr: np.ndarray, vname: str, grp, root_nc) -> None: + if arr.size == 1: + v = grp.createVariable(vname, 'i2', ('scalar',)) + v[:] = arr[0] else: - the_string_to_save = address_of_child - length_of_the_string = len(the_string_to_save) - numpy_datatype = 'S' + str(length_of_the_string) - str_out = netCDF4.stringtochar(np.array([the_string_to_save], dtype=numpy_datatype)) - - # we'll need to make a new dimension for the string if it doesn't already exist - name_of_dimension = 'char' + str(length_of_the_string) - try: - group.createDimension(name_of_dimension, length_of_the_string) - except: pass - # this is another band-aid to the results sub classes... + n = arr.size + dim_name = f'booldim{n}' try: - # now we can make a variable in this dimension: - string = group.createVariable(variable_name, 'S1', (name_of_dimension)) - #finally we can write the variable: - string[:] = str_out - #except RuntimeError: pass - except Exception as e: - print(f'There was an error saving a string from {variable_name}') - print(e) - - -def serialize_numpy_array(variable_name, address_of_child, group, NCData, verbose = False): - # to make a nested array in NCData, we have to get the dimensions of the array, - # create corresponding dimensions in the NCData file, then we can make a variable - # in the NCData with dimensions identical to those in the original array - - # start by getting the data type at the lowest level in the array: - typeis = address_of_child.dtype - - # catch boolean arrays here - if typeis == bool: - # sometimes an array has just 1 element in it, we account for those cases here: - if len(address_of_child) == 1: - variable = group.createVariable(variable_name, int, ('int',)) - variable[:] = int(address_of_child) - variable.units = "bool" - else: - # make the dimensions - dimensions = [] - for dimension in np.shape(address_of_child): - dimensions.append(str('dim' + str(dimension))) - # if the dimension already exists we can't have a duplicate - try: - group.createDimension(str('dim' + str(dimension)), dimension) - except: pass # this would mean that the dimension already exists - - # create the variable: - variable = group.createVariable(variable_name, int, tuple(dimensions)) - # write the variable: - variable[:] = address_of_child.astype(int) - variable.units = "bool" - - # handle all other datatypes here - else: - # sometimes an array has just 1 element in it, we account for those cases here: - if len(address_of_child) == 1: - if typeis is np.dtype('float64'): - variable = group.createVariable(variable_name, typeis, ('float',)) - variable[:] = address_of_child[0] - elif typeis is np.dtype('int64'): - variable = group.createVariable(variable_name, typeis, ('int',)) - variable[:] = address_of_child[0] - else: - print(f'Encountered single datatype from {variable_name} that was not float64 or int64, saving under unlimited dimension, may cause errors.') - variable = group.createVariable(variable_name, typeis, ('Unlim',)) - variable[:] = address_of_child[0] - - # This catches all arrays/lists: + grp.createDimension(dim_name, n) + except Exception: + pass + v = grp.createVariable(vname, 'i2', (dim_name,)) + v[:] = arr.flatten() + v.type_is = 'bool' + + +def _write_cell_of_objects(val: list, vname: str, grp, root_nc, path: str, verbose: bool) -> None: + sub_grp = grp.createGroup(vname) + sub_grp.classtype = 'cell_of_objects' + sub_grp.nrows = 1 + sub_grp.ncols = len(val) + + for c, elem in enumerate(val, start=1): + eg = sub_grp.createGroup(f'item_1_{c}') + eg.classtype = type(elem).__name__ + if hasattr(elem, '__dict__'): + _write_obj(elem, eg, root_nc, f'{path}[{c}]', verbose) + + if verbose: + print(f' [cell] {path} ({len(val)} objects)') + + +def _write_dict(val: dict, vname: str, grp, root_nc, path: str, verbose: bool) -> None: + """Store a dict as a sub-group with one string variable per key.""" + sub_grp = grp.createGroup(vname) + sub_grp.classtype = 'dict' + for k, v in val.items(): + _write_value(v, str(k), sub_grp, root_nc, f'{path}.{k}', verbose) + + +# ===================================================================== +# Dimension helper +# ===================================================================== + +def _make_dims(shape: tuple, grp, root_nc) -> tuple: + """Return a tuple of dimension-name strings, creating dims as needed.""" + dim_names = [] + for n in shape: + if n == 1: + dim_names.append('scalar') else: - # make the dimensions - dimensions = [] - for dimension in np.shape(address_of_child): - dimensions.append(str('dim' + str(dimension))) - # if the dimension already exists we can't have a duplicate + dname = f'dim{n}' + # Try to create in local group; if it exists anywhere, reuse it + for target in (grp, root_nc): try: - group.createDimension(str('dim' + str(dimension)), dimension) - except: pass # this would mean that the dimension already exists - - # create the variable: - variable = group.createVariable(variable_name, typeis, tuple(dimensions)) - - # write the variable: - variable[:] = address_of_child - - \ No newline at end of file + target.createDimension(dname, n) + break + except Exception: + pass # already exists – that's fine + dim_names.append(dname) + return tuple(dim_names) diff --git a/src/m/os/issmdir.m b/src/m/os/issmdir.m index 3caa6458d..9d32fa49e 100644 --- a/src/m/os/issmdir.m +++ b/src/m/os/issmdir.m @@ -13,15 +13,15 @@ %issmdir might be in bin, slash = filesep(); pos = strfind(path,['bin' slash 'issmdir']); -if ~isempty(pos), +if ~isempty(pos) ISSM_DIR=path(1:pos-1); else pos=strfind(path,['src' slash 'm' slash 'os' slash 'issmdir']); - if ~isempty(pos), + if ~isempty(pos) ISSM_DIR=path(1:pos-1); end end -if isempty(ISSM_DIR), +if isempty(ISSM_DIR) error('Could not determine the location of ISSM...'); end diff --git a/src/m/os/issmscpin.m b/src/m/os/issmscpin.m index aa2c2057d..f12a11125 100644 --- a/src/m/os/issmscpin.m +++ b/src/m/os/issmscpin.m @@ -1,8 +1,8 @@ -function issmscpin(host, login, port, path, packages, bracketstyle) -%ISSMSCPIN get packages from host +function issmscpin(host, login, port, path, filelist, bracketstyle) +%ISSMSCPIN get filelist from host % % usage: -% issmscpin(host,packages,path,bracketstyle) +% issmscpin(host,filelist,path,bracketstyle) % % bracketstyle: 1 - \{\} (escaped; default) % 2 - {} (not escaped) @@ -17,18 +17,19 @@ function issmscpin(host, login, port, path, packages, bracketstyle) %if hostname and host are the same, do a simple copy if strcmpi(hostname,host) - for i=1:numel(packages) - system(['cp ' path '/' packages{i} ' .']); + for i=1:numel(filelist) + status = copyfile([path '/' filelist{i} ], '.'); + if(~status) warning(['Could not copy ' path '/' filelist{i} ]); end end else - if numel(packages)==1 - fileliststr=packages{1}; + if numel(filelist)==1 + fileliststr=filelist{1}; else fileliststr='\{'; - for i=1:numel(packages)-1 - fileliststr=[fileliststr packages{i} ',']; + for i=1:numel(filelist)-1 + fileliststr=[fileliststr filelist{i} ',']; end - fileliststr=[fileliststr packages{end} '\}']; + fileliststr=[fileliststr filelist{end} '\}']; %remove \ if bracketstyle is 2 if bracketstyle==2 @@ -55,9 +56,9 @@ function issmscpin(host, login, port, path, packages, bracketstyle) if status ~= 0 error(['scp error message: ' cmdout]) end - for i=1:numel(packages), - if ~exist(['./' packages{i}]), - warning(['issmscpin error message: could not scp ' packages{i}]); + for i=1:numel(filelist) + if ~exist(['./' filelist{i}]) + warning(['issmscpin error message: could not scp ' filelist{i}]); end end end diff --git a/src/m/os/issmscpin.py b/src/m/os/issmscpin.py index 9838b38dd..034cdf3db 100644 --- a/src/m/os/issmscpin.py +++ b/src/m/os/issmscpin.py @@ -1,14 +1,15 @@ import os import shutil import subprocess +import warnings from MatlabFuncs import * -def issmscpin(host, login, port, path, packages=1): +def issmscpin(host, login, port, path, filelist=1, bracketstyle=1): """issmscpin get files from host Usage: - issmscpin(host, packages, path) + issmscpin(host, filelist, path) bracketstyle: 1 - \\{\\} (escaped; default) 2 - {} (not escaped) @@ -19,44 +20,46 @@ def issmscpin(host, login, port, path, packages=1): # If hostname and host are the same, do a simple copy if strcmpi(hostname, host): - for package in packages: + for file in filelist: try: - shutil.copy(os.path.join(path, package), os.getcwd()) # keep going, even if success == 0 + shutil.copy(os.path.join(path, file), os.getcwd()) # keep going, even if success == 0 except OSError as e: + warnings.warn('Could not copy ' + os.path.join(path, file)) pass else: - if len(packages) == 1: - fileliststr = packages[0] + if len(filelist) == 1: + fileliststr = filelist[0] else: fileliststr = r'\{' - fileliststr += ','.join([package for package in packages]) + fileliststr += ','.join([file for file in filelist]) fileliststr += r'\}' # Remove backslashes if bracketstyle is 2 if bracketstyle == 2: fileliststr = fileliststr[1:-2] + fileliststr[-1] + if port: - subproc_cmd = 'scp -P {} {}@localhost:{} {}'.format(port, login, fileliststr, os.getcwd()) + subproc_cmd = 'scp -P {} {}@localhost:{}/{} {}'.format(port, login, path, fileliststr, os.getcwd()) subproc = subprocess.Popen(subproc_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) outs, errs = subproc.communicate() if errs != '': # List expansion is a bashism. Try again with '-OT'. - subproc_cmd = 'scp -OT -P {} {}@localhost:{} {}'.format(port, login, fileliststr, os.getcwd()) + subproc_cmd = 'scp -OT -P {} {}@localhost:{}/{} {}'.format(port, login, path, fileliststr, os.getcwd()) subproc = subprocess.Popen(subproc_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) outs, errs = subproc.communicate() else: - subproc_cmd = 'scp {}@{}:{} {}'.format(login, host, fileliststr, os.getcwd()) + subproc_cmd = 'scp {}@{}:{}/{} {}'.format(login, host, path, fileliststr, os.getcwd()) subproc = subprocess.Popen(subproc_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) outs, errs = subproc.communicate() if errs != '': # List expansion is a bashism. Try again with '-OT'. - subproc_cmd = 'scp -OT {}@{}:{} {}'.format(login, host, fileliststr, os.getcwd()) + subproc_cmd = 'scp -OT {}@{}:{}/{} {}'.format(login, host, path, fileliststr, os.getcwd()) subproc = subprocess.Popen(subproc_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) outs, errs = subproc.communicate() # Check scp worked if errs != '': raise OSError('issmscpin error message: {}'.format(errs)) - for package in packages: - if not os.path.exists(os.path.join('.', package)): - raise OSError('issmscpin error message: could not scp {}'.format(package)) + for file in filelist: + if not os.path.exists(os.path.join('.', file)): + raise OSError('issmscpin error message: could not scp {}'.format(file)) diff --git a/src/m/os/issmscpout.m b/src/m/os/issmscpout.m index 008faab4c..de3c686fb 100644 --- a/src/m/os/issmscpout.m +++ b/src/m/os/issmscpout.m @@ -33,7 +33,7 @@ function issmscpout(host, path, login, port, packages, bracketstyle) fileliststr=packages{1}; else fileliststr='\{'; - for i=1:numel(packages)-1, + for i=1:numel(packages)-1 fileliststr=[fileliststr packages{i} ',']; end fileliststr=[fileliststr packages{end} '\}']; diff --git a/src/m/os/issmssh.m b/src/m/os/issmssh.m index f9b966112..ec83abeb1 100644 --- a/src/m/os/issmssh.m +++ b/src/m/os/issmssh.m @@ -8,15 +8,15 @@ function issmssh(host,login,port,command) hostname=oshostname(); %if same as host, just run the command. -if strcmpi(host,hostname), +if strcmpi(host,hostname) system(command); else - if ispc & ~ismingw, + if ispc & ~ismingw %use the putty project plink.exe: it should be in the path. %get ISSM_DIR variable [status,ISSM_DIR]=system('echo [%ISSM_DIR_WIN%]'); - if status, + if status error('issmssh error message: could not find ISSM_DIR_WIN environment variable'); end ISSM_DIR=ISSM_DIR(2:end-2); @@ -28,7 +28,7 @@ function issmssh(host,login,port,command) else %just use standard unix ssh - if port, + if port eval(['!ssh -l ' login ' -p ' num2str(port) ' localhost "' command '"']); else eval(['!ssh -l ' login ' ' host ' "' command '"']); diff --git a/src/m/os/issmstscpin.m b/src/m/os/issmstscpin.m index 98099694f..888aeb07b 100644 --- a/src/m/os/issmstscpin.m +++ b/src/m/os/issmstscpin.m @@ -8,7 +8,7 @@ function issmstscpin(host, login,path, packages) state=warning('query', 'all'); %remove warnings in case the files do not exist warning off -for i=1:numel(packages), +for i=1:numel(packages) delete(packages{i}); end %back to initial warning state @@ -16,11 +16,11 @@ function issmstscpin(host, login,path, packages) %use starcluster to scp %string to copy multiple files using scp: -if numel(packages)==1, +if numel(packages)==1 string=packages{1}; else string=''; - for i=1:numel(packages)-1, + for i=1:numel(packages)-1 string=[string ' ' path packages{i} ' ']; end string=[string path packages{end}]; @@ -29,8 +29,8 @@ function issmstscpin(host, login,path, packages) system([starcluster() ' get ' host ' -u ' login ' ' string ' ./']); %check starcluster get worked -for i=1:numel(packages), - if ~exist(['./' packages{i}]), +for i=1:numel(packages) + if ~exist(['./' packages{i}]) error('issmstscpin error message: could not call scp on *nix system'); end end diff --git a/src/m/os/issmstscpout.m b/src/m/os/issmstscpout.m index d891948d1..1dc43a41a 100644 --- a/src/m/os/issmstscpout.m +++ b/src/m/os/issmstscpout.m @@ -7,7 +7,7 @@ function issmstscpout(host,path,login,packages) %create string of packages being sent string=''; -for i=1:numel(packages), +for i=1:numel(packages) string=[string ' ' packages{i}]; end string=[string ' ']; diff --git a/src/m/os/jplsvn.m b/src/m/os/jplsvn.m index 6dbc63b68..09cc7a236 100644 --- a/src/m/os/jplsvn.m +++ b/src/m/os/jplsvn.m @@ -4,12 +4,12 @@ % Usage: % JPL_SVN=jplsvn() -if ~ispc(), +if ~ispc() JPL_SVN =getenv('JPL_SVN'); else JPL_SVN =getenv('JPL_SVN_WIN'); end -if (isempty(JPL_SVN)), +if (isempty(JPL_SVN)) error('jplsvn error message: ''JPL_SVN'' environment variable is empty! You should define JPL_SVN in your .cshrc or .bashrc'); end diff --git a/src/m/os/listfiles.m b/src/m/os/listfiles.m index 214e90fa5..17f065ca7 100644 --- a/src/m/os/listfiles.m +++ b/src/m/os/listfiles.m @@ -12,7 +12,7 @@ first_list=dir; list={}; -for i=1:numel(first_list), +for i=1:numel(first_list) if ( ~strcmpi(first_list(i).name,'.') &... ~strcmpi(first_list(i).name,'..') &... ~strcmpi(first_list(i).name,'NightlyRun') &... diff --git a/src/m/os/oshostname.m b/src/m/os/oshostname.m index 332966a44..35b241b51 100644 --- a/src/m/os/oshostname.m +++ b/src/m/os/oshostname.m @@ -8,19 +8,19 @@ hostname = ''; %First try using java (most stable way) -if usejava('jvm'), +if usejava('jvm') hostname = char(getHostName(java.net.InetAddress.getLocalHost)); end %Method 2: use system command (MATLAB bug includes what's in the clipboard) -if isempty(hostname), +if isempty(hostname) %See http://www.mathworks.com/help/matlab/ref/system.html "tips" section %We need to add < /dev/null otherwise what is in the clipboard is added [status,hostname]=system('hostname < /dev/null'); end %Method 3, last chance -if isempty(hostname), +if isempty(hostname) if ispc % If OS is MinGW, $COMPUTERNAME and $HOSTNAME are identical hostname = getenv('COMPUTERNAME'); else @@ -35,6 +35,6 @@ hostname = strtrim(lower(hostname)); % Check that machine name is not empty -if isempty(hostname), +if isempty(hostname) error('Cannot determine machine name'); end diff --git a/src/m/os/sessionname.m b/src/m/os/sessionname.m index f0aa37901..f63378187 100755 --- a/src/m/os/sessionname.m +++ b/src/m/os/sessionname.m @@ -8,7 +8,7 @@ [status,styname]=system('export | grep STY'); sessionname=styname(17:end-2); - if isempty(sessionname), + if isempty(sessionname) name='none'; return; end diff --git a/src/m/parameterization/contourenvelope.m b/src/m/parameterization/contourenvelope.m index 71ae67d72..4c807485c 100644 --- a/src/m/parameterization/contourenvelope.m +++ b/src/m/parameterization/contourenvelope.m @@ -9,20 +9,20 @@ % segments=contourenvelope(mh); %some checks -if nargin>2, +if nargin>2 help contourenvelope error('contourenvelope error message: bad usage'); end -if nargin==2, +if nargin==2 flags=varargin{1}; - if ischar(flags), + if ischar(flags) file=flags; - if ~exist(file), + if ~exist(file) error(['contourenvelope error message: file ' file ' not found']); end isfile=1; - elseif isnumeric(flags), + elseif isnumeric(flags) %do nothing for now isfile=0; else @@ -32,16 +32,16 @@ %Now, build the connectivity tables for this mesh. %Computing connectivity -if isnan(mh.vertexconnectivity), +if isnan(mh.vertexconnectivity) mh.vertexconnectivity=NodeConnectivity(mh.elements,mh.numberofvertices); end -if isnan(mh.elementconnectivity), +if isnan(mh.elementconnectivity) mh.elementconnectivity=ElementConnectivity(mh.elements,mh.vertexconnectivity); end %get nodes inside profile mesh.elementconnectivity=mh.elementconnectivity; -if dimension(mh)==2, +if dimension(mh)==2 mesh.elements=mh.elements; mesh.x=mh.x; mesh.y=mh.y; @@ -55,9 +55,9 @@ mesh.numberofelements=mh.numberofelements2d; end -if nargin==2, +if nargin==2 - if isfile, + if isfile %get flag list of elements and nodes inside the contour nodein=ContourToMesh(mesh.elements,mesh.x,mesh.y,file,'node',1); elemin=(sum(nodein(mesh.elements),2)==size(mesh.elements,2)); @@ -84,7 +84,7 @@ %Find element on boundary %First: find elements on the boundary of the domain flag=mesh.elementconnectivity; -if nargin==2, +if nargin==2 flag(find(flag))=elemin(flag(find(flag))); end elementonboundary=double(prod(flag,2)==0 & sum(flag,2)>0); @@ -95,10 +95,10 @@ segments=zeros(num_segments*3,3); count=1; -for i=1:num_segments, +for i=1:num_segments el1=pos(i); els2=mesh.elementconnectivity(el1,find(mesh.elementconnectivity(el1,:))); - if length(els2)>1, + if length(els2)>1 flag=intersect(intersect(mesh.elements(els2(1),:),mesh.elements(els2(2),:)),mesh.elements(el1,:)); nods1=mesh.elements(el1,:); nods1(find(nods1==flag))=[]; @@ -108,7 +108,7 @@ ord2=find(nods1(2)==mesh.elements(el1,:)); %swap segment nodes if necessary - if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ), + if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ) temp=segments(count,1); segments(count,1)=segments(count,2); segments(count,2)=temp; @@ -118,13 +118,13 @@ else nods1=mesh.elements(el1,:); flag=setdiff(nods1,mesh.elements(els2,:)); - for j=1:3, + for j=1:3 nods=nods1; nods(j)=[]; - if any(ismember(flag,nods)), + if any(ismember(flag,nods)) segments(count,:)=[nods el1]; ord1=find(nods(1)==mesh.elements(el1,:)); ord2=find(nods(2)==mesh.elements(el1,:)); - if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ), + if ( (ord1==1 & ord2==2) | (ord1==2 & ord2==3) | (ord1==3 & ord2==1) ) temp=segments(count,1); segments(count,1)=segments(count,2); segments(count,2)=temp; diff --git a/src/m/parameterization/parameterize.m b/src/m/parameterization/parameterize.m index 32437a4ca..3677881be 100644 --- a/src/m/parameterization/parameterize.m +++ b/src/m/parameterization/parameterize.m @@ -12,7 +12,7 @@ % md=parameterize(md,'Square.par'); %some checks -if ~exist(parametername), +if ~exist(parametername) error(['parameterize error message: file ' parametername ' not found!']); end @@ -35,12 +35,12 @@ me2=struct('message',me.message,'stack',me.stack); %rename parameter file - for i=1:length(me2.stack)-1, + for i=1:length(me2.stack)-1 if strcmp(me2.stack(i).name,temporaryname) me2.stack(i).file = strrep(me2.stack(i).file,temporaryname,parametername); me2.stack(i).name = parametername; end - if strcmp(me2.stack(i).name,'parameterize'), + if strcmp(me2.stack(i).name,'parameterize') %remove error (eval(temporaryname);) misleading me2.stack(i)=[]; end @@ -51,10 +51,10 @@ end %Name and notes -if isempty(md.miscellaneous.name), +if isempty(md.miscellaneous.name) [path,root,ext]=fileparts(parametername); md.miscellaneous.name=root; end -if isempty(md.miscellaneous.notes), +if isempty(md.miscellaneous.notes) md.miscellaneous.notes=['Model created by using parameter file: ' parametername ' on: ' datestr(now)]; end diff --git a/src/m/parameterization/reinitializelevelset.m b/src/m/parameterization/reinitializelevelset.m index 00fc8a4a1..414d2fac2 100644 --- a/src/m/parameterization/reinitializelevelset.m +++ b/src/m/parameterization/reinitializelevelset.m @@ -10,7 +10,7 @@ % if md is 3d, levelset should be projected on a 2d mesh if isempty(levelset), error('levelset provided is empty'); end -if dimension(md.mesh)==3, +if dimension(md.mesh)==3 if length(levelset)~=md.mesh.numberofvertices2d, error('levelset provided should be specified at the 2d vertices of the mesh'); end else if length(levelset)~=md.mesh.numberofvertices, error('levelset provided should be specified at the vertices of the mesh'); end diff --git a/src/m/parameterization/setflowequation.m b/src/m/parameterization/setflowequation.m index 57ab35ac5..6198b0002 100644 --- a/src/m/parameterization/setflowequation.m +++ b/src/m/parameterization/setflowequation.m @@ -19,7 +19,7 @@ % md=setflowequation(md,'HO','HO.exp',fill','SIA','coupling','tiling'); %some checks on list of arguments -if ((nargin<2) | (nargout~=1)), +if ((nargin<2) | (nargout~=1)) error('setflowequation error message'); end @@ -29,7 +29,7 @@ %Find_out what kind of coupling to use coupling_method=getfieldvalue(options,'coupling','tiling'); -if (~strcmpi(coupling_method,'tiling') & ~strcmpi(coupling_method,'penalties')), +if (~strcmpi(coupling_method,'tiling') & ~strcmpi(coupling_method,'penalties')) error('coupling type can only be: tiling or penalties'); end @@ -44,21 +44,21 @@ displayunused(options); %Flag the elements that have not been flagged as filltype -if strcmpi(filltype,'SIA'), +if strcmpi(filltype,'SIA') SIAflag(find(~(SSAflag | HOflag)))=1; -elseif strcmpi(filltype,'SSA'), +elseif strcmpi(filltype,'SSA') SSAflag(find(~(SIAflag | HOflag | FSflag)))=1; -elseif strcmpi(filltype,'HO'), +elseif strcmpi(filltype,'HO') HOflag(find(~(SIAflag | SSAflag | FSflag)))=1; end %check that each element has at least one flag -if any(SIAflag+SSAflag+HOflag+L1L2flag+MOLHOflag+FSflag==0), +if any(SIAflag+SSAflag+HOflag+L1L2flag+MOLHOflag+FSflag==0) error('elements type not assigned, supported models are ''SIA'',''SSA'',''HO'',''MOLHO'' and ''FS''') end %check that each element has only one flag -if any(SIAflag+SSAflag+HOflag+L1L2flag+MOLHOflag+FSflag>1), +if any(SIAflag+SSAflag+HOflag+L1L2flag+MOLHOflag+FSflag>1) disp('setflowequation.m: Warning: some elements have several types, higher order type is used for them') SIAflag(find(SIAflag & SSAflag))=0; SIAflag(find(SIAflag & HOflag))=0; @@ -81,7 +81,7 @@ end %FS can only be used alone for now: -if any(FSflag) &any(SIAflag), +if any(FSflag) &any(SIAflag) error('FS cannot be used with any other model for now, put FS everywhere') end @@ -95,7 +95,7 @@ noneflag=zeros(md.mesh.numberofelements,1); %First modify FSflag to get rid of elements contrained everywhere (spc + border with HO or SSA) -if any(FSflag), +if any(FSflag) fullspcnodes=double((~isnan(md.stressbalance.spcvx)+~isnan(md.stressbalance.spcvy)+~isnan(md.stressbalance.spcvz))==3 | (nodeonHO & nodeonFS)); %find all the nodes on the boundary of the domain without icefront fullspcelems=double(sum(fullspcnodes(md.mesh.elements),2)==6); %find all the nodes on the boundary of the domain without icefront FSflag(find(fullspcelems))=0; @@ -103,7 +103,7 @@ end %Then complete with NoneApproximation or the other model used if there is no FS -if any(FSflag), +if any(FSflag) if any(HOflag), %fill with HO HOflag(~FSflag)=1; nodeonHO(md.mesh.elements(find(HOflag),:))=1; @@ -116,7 +116,7 @@ end %Now take care of the coupling between SSA and HO -if strcmpi(coupling_method,'penalties'), +if strcmpi(coupling_method,'penalties') md.stressbalance.vertex_pairing=[]; end nodeonSSAHO=zeros(md.mesh.numberofvertices,1); @@ -125,21 +125,21 @@ SSAHOflag=zeros(md.mesh.numberofelements,1); SSAFSflag=zeros(md.mesh.numberofelements,1); HOFSflag=zeros(md.mesh.numberofelements,1); -if strcmpi(coupling_method,'penalties'), +if strcmpi(coupling_method,'penalties') %Create the border nodes between HO and SSA and extrude them numnodes2d=md.mesh.numberofvertices2d; numlayers=md.mesh.numberoflayers; bordernodes2d=find(nodeonHO(1:numnodes2d) & nodeonSSA(1:numnodes2d)); %Nodes connected to two different types of elements %initialize and fill in penalties structure - if ~isnan(bordernodes2d), + if ~isnan(bordernodes2d) penalties=[]; - for i=1:numlayers-1, + for i=1:numlayers-1 penalties=[penalties; [bordernodes2d bordernodes2d+md.mesh.numberofvertices2d*(i)]]; end md.stressbalance.vertex_pairing=penalties; end -elseif strcmpi(coupling_method,'tiling'), +elseif strcmpi(coupling_method,'tiling') if any(SSAflag) & any(HOflag), %coupling SSA HO %Find node at the border nodeonSSAHO(find(nodeonSSA & nodeonHO))=1; @@ -204,7 +204,7 @@ nodeonHOFS(:)=0; nodeonHOFS(md.mesh.elements(find(HOFSflag),:))=1; - elseif any(FSflag) & any(SSAflag), + elseif any(FSflag) & any(SSAflag) %Find node at the border nodeonSSAFS(find(nodeonSSA & nodeonFS))=1; %FS elements in contact with this layer become SSAFS elements @@ -236,7 +236,7 @@ nodeonSSAFS(:)=0; nodeonSSAFS(md.mesh.elements(find(SSAFSflag),:))=1; - elseif any(FSflag) & any(SIAflag), + elseif any(FSflag) & any(SIAflag) error('type of coupling not supported yet'); end end @@ -269,7 +269,7 @@ %DO SIA LAST! Otherwise spcs might not be set up correctly (SIA should have priority) pos=find(nodeonSIA); md.flowequation.vertex_equation(pos)=1; -if any(FSflag), +if any(FSflag) pos=find(~nodeonFS); if(~any(HOflag) & ~any(SSAflag)), md.flowequation.vertex_equation(pos)=0; @@ -293,12 +293,12 @@ return %Check that tiling can work: -if any(md.flowequation.borderSSA) & any(md.flowequation.borderHO) & any(md.flowequation.borderHO + md.flowequation.borderSSA ~=1), +if any(md.flowequation.borderSSA) & any(md.flowequation.borderHO) & any(md.flowequation.borderHO + md.flowequation.borderSSA ~=1) error('error coupling domain too irregular'); end -if any(md.flowequation.borderSSA) & any(md.flowequation.borderFS) & any(md.flowequation.borderFS + md.flowequation.borderSSA ~=1), +if any(md.flowequation.borderSSA) & any(md.flowequation.borderFS) & any(md.flowequation.borderFS + md.flowequation.borderSSA ~=1) error('error coupling domain too irregular'); end -if any(md.flowequation.borderFS) & any(md.flowequation.borderHO) & any(md.flowequation.borderHO + md.flowequation.borderFS~=1), +if any(md.flowequation.borderFS) & any(md.flowequation.borderHO) & any(md.flowequation.borderHO + md.flowequation.borderFS~=1) error('error coupling domain too irregular'); end diff --git a/src/m/parameterization/setmask.m b/src/m/parameterization/setmask.m index e527f7f6b..7d7b2a620 100644 --- a/src/m/parameterization/setmask.m +++ b/src/m/parameterization/setmask.m @@ -14,7 +14,7 @@ % md=setmask(md,'Iceshelves.exp','Islands.exp'); %some checks on list of arguments -if ((mod(nargin,2)==0) | (nargout~=1)), +if ((mod(nargin,2)==0) | (nargout~=1)) help mask error('mask error message'); end @@ -25,7 +25,7 @@ else error('mask error message: wrong field specified. Only icedomain allowed for now.'); end - if ~exist(icedomainname), + if ~exist(icedomainname) error(['setmask error message: file ' icedomainname ' not found!']); end end diff --git a/src/m/parameterization/setmask2.m b/src/m/parameterization/setmask2.m index d53027e15..9cc54ccf5 100644 --- a/src/m/parameterization/setmask2.m +++ b/src/m/parameterization/setmask2.m @@ -13,10 +13,10 @@ elements=md.mesh.elements; %recover elements and nodes on land. -if ischar(landname), +if ischar(landname) [vertexonland,elementonland]=ContourToMesh(elements,x,y,landname,'element and node',2); -elseif isfloat(landname), - if size(landname,1)~=md.mesh.numberofelements, +elseif isfloat(landname) + if size(landname,1)~=md.mesh.numberofelements error('Landname for area must be of same size as number of elements in model'); end elementonland=landname; @@ -27,10 +27,10 @@ end %Now, build the connectivity tables for this mesh. -if size(md.mesh.vertexconnectivity,1)~=md.mesh.numberofvertices, +if size(md.mesh.vertexconnectivity,1)~=md.mesh.numberofvertices md.mesh.vertexconnectivity=NodeConnectivity(md.mesh.elements,md.mesh.numberofvertices); end -if size(md.mesh.elementconnectivity,1)~=md.mesh.numberofelements, +if size(md.mesh.elementconnectivity,1)~=md.mesh.numberofelements md.mesh.elementconnectivity=ElementConnectivity(md.mesh.elements,md.mesh.vertexconnectivity); end @@ -41,9 +41,9 @@ elementonland(wrongelements)=1; %any element with its barycentre on land should be on land: (only if landname is an expfile) -if ischar(landname), +if ischar(landname) weights={[1;1;1],[2;1;1],[1;2;1],[1;1;2]}; - for i=1:length(weights), + for i=1:length(weights) xelem=x(md.mesh.elements)*weights{i}/sum(weights{i}); yelem=y(md.mesh.elements)*weights{i}/sum(weights{i}); end diff --git a/src/m/paraview/exportVTK.m b/src/m/paraview/exportVTK.m index 2a4010e8d..c16196226 100644 --- a/src/m/paraview/exportVTK.m +++ b/src/m/paraview/exportVTK.m @@ -19,7 +19,7 @@ function exportVTK(filename,model,varargin) mkdir(filename); %get the element related variables -if dimension(model.mesh)==2, +if dimension(model.mesh)==2 points=[model.mesh.x model.mesh.y zeros(model.mesh.numberofvertices,1)]; else points=[model.mesh.x model.mesh.y model.mesh.z]; @@ -153,7 +153,7 @@ function exportVTK(filename,model,varargin) %also checking for verry small value that mess up smallval=(abs(res_struct.(fieldnames{k}))<1.0e-20); res_struct.(fieldnames{k})(smallval)=0.0; - if (size(res_struct.(fieldnames{k}),2)==num_of_timesteps), + if (size(res_struct.(fieldnames{k}),2)==num_of_timesteps) fprintf(fid,'SCALARS %s float 1 \n',fieldnames{k}); fprintf(fid,'LOOKUP_TABLE default\n'); s='%e\n'; @@ -180,9 +180,9 @@ function exportVTK(filename,model,varargin) end lowtime=res_struct.(fieldnames{k})(end,index); lowlim=res_struct.(fieldnames{k})(1:end-1,index); - if uptime==currenttime, + if uptime==currenttime interp=uplim; - elseif lowtime==currenttime, + elseif lowtime==currenttime interp=lowlim; else interp=lowlim+(uplim-lowlim)*((currenttime-lowtime)/(uptime-lowtime)); diff --git a/src/m/paraview/exportVTK.py b/src/m/paraview/exportVTK.py index 86df88e22..207416fc3 100644 --- a/src/m/paraview/exportVTK.py +++ b/src/m/paraview/exportVTK.py @@ -488,7 +488,7 @@ def exportVTK(filename, md, *args, enveloppe=False, **kwargs): print("format for field {}.{} is not suported, field is skipped".format(other, field)) continue # }}} - # Now writting cell variables {{{ + # Now writing cell variables {{{ if np.size(list(saved_cells.keys())) > 0: fid.write('CELL_DATA {:d} \n'.format(num_of_elt + num_of_edges)) for key in list(saved_cells.keys()): @@ -500,7 +500,7 @@ def exportVTK(filename, md, *args, enveloppe=False, **kwargs): for edge in range(0, num_of_edges): fid.write('{:f}\n'.format(-9999.999)) # }}} - # Now writting edge variables {{{ + # Now writing edge variables {{{ if np.size(list(saved_edges.keys())) > 0: for key in list(saved_edges.keys()): fid.write('SCALARS {} float 1 \n'.format(key)) diff --git a/src/m/paraview/exportVTU.py b/src/m/paraview/exportVTU.py index e8a0c4c72..e3ac06337 100644 --- a/src/m/paraview/exportVTU.py +++ b/src/m/paraview/exportVTU.py @@ -441,7 +441,7 @@ def exportVTU(filename, md, *args, enveloppe=False, fmtout="binary", **kwargs): print("format for field {}.{} is not suported, field is skipped".format(other, field)) fid.write(' \n') # }}} - # Now writting cell variables {{{ + # Now writing cell variables {{{ if np.size(list(saved_cells.keys())) > 0 or np.size(list(saved_edges.keys())) > 0: cellkeys = list(saved_cells.keys()) edgekeys = list(saved_edges.keys()) @@ -472,7 +472,7 @@ def exportVTU(filename, md, *args, enveloppe=False, fmtout="binary", **kwargs): fid.write(' \n') # }}} - # Now writting edge variables {{{ + # Now writing edge variables {{{ if np.size(list(saved_edges.keys())) > 0: for key in list(saved_edges.keys()): if fmtout == "binary": @@ -487,7 +487,7 @@ def exportVTU(filename, md, *args, enveloppe=False, fmtout="binary", **kwargs): fid.write(' \n') # }}} - # Now writting constants # {{{ + # Now writing constants # {{{ if np.size(list(saved_const.keys())) > 0: fid.write(' \n') for key in list(saved_const.keys()): diff --git a/src/m/partition/AreaAverageOntoPartition.m b/src/m/partition/AreaAverageOntoPartition.m index 3f86c1cc2..68b8a7808 100644 --- a/src/m/partition/AreaAverageOntoPartition.m +++ b/src/m/partition/AreaAverageOntoPartition.m @@ -8,8 +8,8 @@ % average=AreaAverageOntoPartition(md,vector,layer) %if in 3D, chose which layer is partitioned %some checks -if dimension(md.mesh)==3, - if nargin~=3, +if dimension(md.mesh)==3 + if nargin~=3 error('layer should be provided onto which Area Averaging occurs'); end %save 3D model @@ -36,7 +36,7 @@ %some check: npart=qmupart2npart(partition); -if npart~=max(part), +if npart~=max(part) error('AreaAverageOntoPartition error message: ''npart'' should be equal to max(partition)'); end @@ -45,12 +45,12 @@ %start weight average weightedvector=vector.*md.qmu.vertex_weight; -for i=1:max(part), +for i=1:max(part) pos=find(part==i); partvector(i)=sum(weightedvector(pos))/sum(md.qmu.vertex_weight(pos)); end %in 3D, restore 3D model: -if dimension(md.mesh)==3, +if dimension(md.mesh)==3 md=md3d; end diff --git a/src/m/partition/flagedges.m b/src/m/partition/flagedges.m index f55b0ef40..772f8f144 100644 --- a/src/m/partition/flagedges.m +++ b/src/m/partition/flagedges.m @@ -7,7 +7,7 @@ xsegments=[]; ysegments=[]; -for i=1:size(elements,1), +for i=1:size(elements,1) m1=partition(elements(i,1)); m2=partition(elements(i,2)); m3=partition(elements(i,3)); @@ -18,7 +18,7 @@ y2=y(elements(i,2)); y3=y(elements(i,3)); - if (m1~=m2) & (m1~=m3) & (m2~=m3), + if (m1~=m2) & (m1~=m3) & (m2~=m3) xmiddle=(x1+x2+x3)/3; ymiddle=(y1+y2+y3)/3; xsegments=[xsegments; (x1+x2)/2 xmiddle]; @@ -29,16 +29,16 @@ ysegments=[ysegments; (y2+y3)/2 ymiddle]; end - if (m1==m2) & (m1~=m3), + if (m1==m2) & (m1~=m3) xsegments=[xsegments; (x1+x3)/2 (x2+x3)/2]; ysegments=[ysegments; (y1+y3)/2 (y2+y3)/2]; end - if (m1==m3) & (m2~=m3), + if (m1==m3) & (m2~=m3) xsegments=[xsegments; (x1+x2)/2 (x2+x3)/2]; ysegments=[ysegments; (y1+y2)/2 (y2+y3)/2]; end - if (m2==m3) & (m1~=m3), + if (m2==m3) & (m1~=m3) xsegments=[xsegments; (x1+x2)/2 (x1+x3)/2]; ysegments=[ysegments; (y1+y2)/2 (y1+y3)/2]; end diff --git a/src/m/partition/partitioner.m b/src/m/partition/partitioner.m index 2e5cb6fb2..0f81d071a 100644 --- a/src/m/partition/partitioner.m +++ b/src/m/partition/partitioner.m @@ -48,13 +48,13 @@ end %adjacency matrix if needed: -if strcmpi(recomputeadjacency,'on'), +if strcmpi(recomputeadjacency,'on') md=adjacency(md); else disp('skipping adjacency matrix computation as requested in the options'); end -if strcmpi(package,'chaco'), +if strcmpi(package,'chaco') if strcmpi(vectortype,'element') error(['partitioner error message: package ' package ' does not allow element partitions.']); @@ -69,7 +69,7 @@ method(6)=getfieldvalue(options,'section');% ndims (1=bisection, 2=quadrisection, 3=octasection) %are we using weights? - if strcmpi(getfieldvalue(options,'weighting'),'on'), + if strcmpi(getfieldvalue(options,'weighting'),'on') weights=floor(md.qmu.vertex_weight/min(md.qmu.vertex_weight)); method(3)=1; else @@ -77,7 +77,7 @@ end % partition into nparts - if isa(md.mesh,'mesh2d'), + if isa(md.mesh,'mesh2d') part=Chaco(md.qmu.adjacency,weights,[],md.mesh.x,md.mesh.y,zeros(md.mesh.numberofvertices,1),method,npart,[])'+1; %index partitions from 1 up. like metis. else part=Chaco(md.qmu.adjacency,weights,[],md.mesh.x, md.mesh.y,md.mesh.z,method,npart,[])'+1; %index partitions from 1 up. like metis. @@ -85,13 +85,13 @@ end -elseif strcmpi(package,'scotch'), +elseif strcmpi(package,'scotch') if strcmpi(vectortype,'element') error(['partitioner error message: package ' package ' does not allow element partitions.']); else %are we using weights? - if strcmpi(getfieldvalue(options,'weighting'),'on'), + if strcmpi(getfieldvalue(options,'weighting'),'on') weights=floor(md.qmu.vertex_weight/min(md.qmu.vertex_weight)); else weights=[]; @@ -101,7 +101,7 @@ part=maptab(:,2)+1;%index partitions from 1 up. like metis. end -elseif strcmpi(package,'linear'), +elseif strcmpi(package,'linear') if strcmpi(vectortype,'element') part=1:1:md.mesh.numberofelements; @@ -110,7 +110,7 @@ part=1:1:md.mesh.numberofvertices; end -elseif strcmpi(package,'metis'), +elseif strcmpi(package,'metis') if strcmpi(vectortype,'element') error(['partitioner error message: package ' package ' does not allow element partitions.']); @@ -125,7 +125,7 @@ end %extrude if we are in 3D: -if dimension(md.mesh)==3, +if dimension(md.mesh)==3 md3d.qmu.vertex_weight=md.qmu.vertex_weight; md3d.qmu.adjacency=md.qmu.adjacency; md=md3d; diff --git a/src/m/plot/applyoptions.m b/src/m/plot/applyoptions.m index ed34dc28f..26ed7cad2 100644 --- a/src/m/plot/applyoptions.m +++ b/src/m/plot/applyoptions.m @@ -15,10 +15,10 @@ function applyoptions(md,data,options) %title if exist(options,'title') titlevalue=getfieldvalue(options,'title'); - if iscell(titlevalue), + if iscell(titlevalue) title(titlevalue,'FontSize',fontsize,'FontWeight',fontweight); else - if ~isnan(titlevalue), + if ~isnan(titlevalue) title(titlevalue,'FontSize',fontsize,'FontWeight',fontweight); end end @@ -58,18 +58,18 @@ function applyoptions(md,data,options) axis(axisopts); end else - if strcmp(domaintype(md.mesh),'3D'), + if strcmp(domaintype(md.mesh),'3D') if ~(exist(options,'layer') || exist(options,'depthaverage')) axis auto tight else axis tight equal end - elseif strcmp(domaintype(md.mesh),'2Dvertical'), + elseif strcmp(domaintype(md.mesh),'2Dvertical') axis auto tight - elseif strcmp(domaintype(md.mesh),'3Dsurface'), + elseif strcmp(domaintype(md.mesh),'3Dsurface') axis auto tight - elseif strcmp(domaintype(md.mesh),'2Dhorizontal'), + elseif strcmp(domaintype(md.mesh),'2Dhorizontal') axis tight equal; else error('type of domain not supported'); @@ -115,18 +115,18 @@ function applyoptions(md,data,options) end %Caxis -if exist(options,'caxis'), +if exist(options,'caxis') caxis(getfieldvalue(options,'caxis')); end %shading -if exist(options,'shading'), +if exist(options,'shading') shading(getfieldvalue(options,'shading')); end %grid -if exist(options,'grid'), - if strcmpi(getfieldvalue(options,'grid'),'on'), +if exist(options,'grid') + if strcmpi(getfieldvalue(options,'grid'),'on') grid on; end end @@ -136,18 +136,18 @@ function applyoptions(md,data,options) h = colormap(gca,c); %wrapping -if exist(options,'wrapping'), - if ~exist(options,'colormap'), +if exist(options,'wrapping') + if ~exist(options,'colormap') h=turbo(); end colormap(repmat(h,getfieldvalue(options,'wrapping',1),1)); end %colorbar -if getfieldvalue(options,'colorbar',1)==1, - if exist(options,'colorbarcornerposition'), +if getfieldvalue(options,'colorbar',1)==1 + if exist(options,'colorbarcornerposition') c=colorbar(getfieldvalue(options,'colorbarcornerposition'),'peer',gca); - elseif exist(options,'colorbarpos') & ischar(getfieldvalue(options,'colorbarpos')), + elseif exist(options,'colorbarpos') & ischar(getfieldvalue(options,'colorbarpos')) c=colorbar(getfieldvalue(options,'colorbarpos')); else c=colorbar('peer',gca); @@ -158,10 +158,10 @@ function applyoptions(md,data,options) lim=[lim(1) lim(1)+(lim(2)-lim(1))/getfieldvalue(options,'wrapping')]; set(c,'Ylim',lim); end - if exist(options,'colorbarpos') & isnumeric(getfieldvalue(options,'colorbarpos')), + if exist(options,'colorbarpos') & isnumeric(getfieldvalue(options,'colorbarpos')) set(c,'Position',getfieldvalue(options,'colorbarpos')); end - if exist(options,'log'), + if exist(options,'log') nlab=length(get(c,'YTick')); logvalue=getfieldvalue(options,'log'); @@ -185,15 +185,15 @@ function applyoptions(md,data,options) if exist(options,'cbYLim'); set(c,'YLim',getfieldvalue(options,'cbYLim')); end - if exist(options,'colorbartitle'), + if exist(options,'colorbartitle') set(get(c,'title'),'FontSize',getfieldvalue(options,'colorbarfontsize',fontsize),'String',getfieldvalue(options,'colorbartitle'),... 'Color',getfieldvalue(options,'FontColor','k')); end - if exist(options,'colorbarYLabel'), + if exist(options,'colorbarYLabel') set(get(c,'Ylabel'),'FontSize',getfieldvalue(options,'colorbarfontsize',fontsize),'String',getfieldvalue(options,'colorbarYLabel'),... 'Color',getfieldvalue(options,'FontColor','k')); end - if exist(options,'colorbarwidth'), + if exist(options,'colorbarwidth') posaxes=get(gca,'Position'); alpha=getfieldvalue(options,'colorbarwidth',1); position=get(c,'Position'); @@ -204,7 +204,7 @@ function applyoptions(md,data,options) set(c,'Position',position); set(gca,'Position',posaxes); end - if exist(options,'colorbarheight'), + if exist(options,'colorbarheight') posaxes=get(gca,'Position'); alpha=getfieldvalue(options,'colorbarheight',1); position=get(c,'Position'); @@ -244,26 +244,26 @@ function applyoptions(md,data,options) set(c,'YTickLabel',labels); end -elseif getfieldvalue(options,'colorbar',1)==0, +elseif getfieldvalue(options,'colorbar',1)==0 colorbar('off'); else %do nothing end %area -if exist(options,'area'), +if exist(options,'area') antzoom(getfieldvalue(options,'area')); end %expdisp -if exist(options,'expdisp'), +if exist(options,'expdisp') filename=(getfieldvalue(options,'expdisp')); style=(getfieldvalue(options,'expstyle')); linewidth=(getfieldvalue(options,'linewidth',1)); - for i=1:length(getfieldvalue(options,'expdisp')), + for i=1:length(getfieldvalue(options,'expdisp')) filenamei=filename{i}; stylei=style{i}; - if length(linewidth)==1, + if length(linewidth)==1 linewidthi=linewidth; else linewidthi=linewidth{i}; @@ -273,14 +273,14 @@ function applyoptions(md,data,options) end %shpdisp -if exist(options,'shpdisp'), +if exist(options,'shpdisp') filename=(getfieldvalue(options,'shpdisp')); style=(getfieldvalue(options,'shpstyle',{'r.-'})); linewidth=(getfieldvalue(options,'linewidth',1)); - for i=1:length(getfieldvalue(options,'shpdisp')), + for i=1:length(getfieldvalue(options,'shpdisp')) filenamei=filename{i}; stylei=style{i}; - if length(linewidth)==1, + if length(linewidth)==1 linewidthi=linewidth; else linewidthi=linewidth{i}; @@ -289,7 +289,7 @@ function applyoptions(md,data,options) shpdisp(filenamei,1,stylei,linewidthi,getfieldvalue(options,'unit',1)); end end -if exist(options,'contours'), +if exist(options,'contours') hold on; contours=getfieldvalue(options,'contours'); @@ -302,7 +302,7 @@ function applyoptions(md,data,options) ratio=1+(contourheight*1000/radius); - if ~isa(contours,'cell'), + if ~isa(contours,'cell') contours={contours}; end nc=length(contours); @@ -310,13 +310,13 @@ function applyoptions(md,data,options) if ~isa(linewidth,'cell'), error('contour line width should be a cell array'); end if ~isa(color,'cell'), error('contour color should be a cell array'); end - for i=1:length(contours), + for i=1:length(contours) ci=contours{i}; if length(style)==1, sti=style{1}; else sti=style{i}; end if length(color)==1, coli=color{1}; else coli=color{i}; end if length(linewidth)==1, li=linewidth{1}; else li=linewidth{i}; end - for j=1:length(ci), + for j=1:length(ci) cijx=ci(j).x*ratio; cijy=ci(j).y*ratio; cijz=ci(j).z*ratio; @@ -328,14 +328,14 @@ function applyoptions(md,data,options) end %shpdisp3d -if exist(options,'shpdisp3d'), +if exist(options,'shpdisp3d') filename=(getfieldvalue(options,'shpdisp3d')); style=(getfieldvalue(options,'shpstyle',{'r.-'})); linewidth=(getfieldvalue(options,'linewidth',1)); - for i=1:length(getfieldvalue(options,'shpdisp3d')), + for i=1:length(getfieldvalue(options,'shpdisp3d')) filenamei=filename{i}; stylei=style{i}; - if length(linewidth)==1, + if length(linewidth)==1 linewidthi=linewidth; else linewidthi=linewidth{i}; @@ -360,40 +360,40 @@ function applyoptions(md,data,options) textcolori=textcolor{i}; textpositioni=textposition{i}; textrotationi=textrotation{i}; - if ~text3d, + if ~text3d h=text(textpositioni(1),textpositioni(2),textstringi,'FontSize',textsizei,'FontWeight',textweighti,'Color',textcolori,'Rotation',textrotationi); else h=text(textpositioni(1),textpositioni(2),textpositioni(3),textstringi,'FontSize',textsizei,'FontWeight',textweighti,'Color',textcolori,'Rotation',textrotationi); end - if strcmpi(getfieldvalue(options,'textclip','on'),'on'), + if strcmpi(getfieldvalue(options,'textclip','on'),'on') set(h,'Clipping','on'); %prevent text from appearing outside of the box end end end %north arrow -if exist(options,'northarrow'), +if exist(options,'northarrow') northarrow(getfieldvalue(options,'northarrow')); end %curved arrow -if exist(options,'curvedarrow'), +if exist(options,'curvedarrow') curvedoptions=getfieldvalue(options,'curvedarrow'); curvedarrow(curvedoptions{:}); end %Scale ruler -if exist(options,'scaleruler'), +if exist(options,'scaleruler') scaleruler(options); end %streamlines -if exist(options,'streamlines'), +if exist(options,'streamlines') plot_streamlines(md,options); end %contours -if exist(options,'contourlevels'), +if exist(options,'contourlevels') plot_contour(md,data,options); end @@ -404,27 +404,27 @@ function applyoptions(md,data,options) end %YTickLabel -if exist(options,'yticklabel'), +if exist(options,'yticklabel') set(gca,'YTickLabel',getfieldvalue(options,'YTickLabel')); end %XTickLabel -if exist(options,'xticklabel'), +if exist(options,'xticklabel') set(gca,'XTickLabel',getfieldvalue(options,'XTickLabel')); end %xtick -if exist(options,'xtick'), +if exist(options,'xtick') set(gca,'xtick',getfieldvalue(options,'xtick')); end %ytick -if exist(options,'ytick'), +if exist(options,'ytick') set(gca,'ytick',getfieldvalue(options,'ytick')); end %Axis positions -if exist(options,'offsetaxispos'), +if exist(options,'offsetaxispos') offset=getfieldvalue(options,'offsetaxispos'); P=get(gca,'pos'); P(1)=P(1)+offset(1); @@ -433,13 +433,13 @@ function applyoptions(md,data,options) P(3)=P(4)+offset(4); set(gca,'pos',P); end -if exist(options,'axispos'), +if exist(options,'axispos') Axis=getfieldvalue(options,'axispos'); hold on set(gca,'pos',Axis); end -if exist(options,'datatip'), +if exist(options,'datatip') datatip = getfieldvalue(options, 'datatip'); dcm = datacursormode(gcf); set(dcm, 'Enable', 'on'); @@ -447,7 +447,7 @@ function applyoptions(md,data,options) end %showregion -if strcmpi(getfieldvalue(options,'showregion','off'),'on'), +if strcmpi(getfieldvalue(options,'showregion','off'),'on') %Keep pointer of main axis maingca=gca; %get inset relative position (x,y,width,height) @@ -459,12 +459,12 @@ function applyoptions(md,data,options) axes('pos',PosInset); axis equal off %box off - if md.mesh.epsg==3413, + if md.mesh.epsg==3413 A=expread('/u/astrid-r1b/ModelData/Exp/GreenlandBoxFront.exp'); [A.x A.y]=ll2xy(A.x,A.y,+1,45,70); A.x = A.x(1:30:end); A.y = A.y(1:30:end); - elseif md.mesh.epsg==3031, + elseif md.mesh.epsg==3031 A=expread('/u/astrid-r1b/ModelData/Exp/Antarctica.exp'); else error('applyoptions error message: md.mesh.epsg not defined'); @@ -473,9 +473,9 @@ function applyoptions(md,data,options) Ax=[min(A.x)-offset max(A.x)+offset]; Ay=[min(A.y)-offset max(A.y)+offset]; %if we are zooming on a basin, don't take the mesh for the boundaries! - if exist(options,'basin'), + if exist(options,'basin') [mdx mdy]=basinzoom(options); - elseif exist(options,'xlim') | exist(options,'ylim'), + elseif exist(options,'xlim') | exist(options,'ylim') mdx=getfieldvalue(options,'xlim'); mdy=getfieldvalue(options,'ylim'); else @@ -518,7 +518,7 @@ function applyoptions(md,data,options) color=getfieldvalue(options,'partitionedgescolor','r-'); linewidth=getfieldvalue(options,'linewidth',1); hold on; - for i=1:length(xsegments), + for i=1:length(xsegments) if (isnumeric(color)) h=plot(xsegments(i,:),ysegments(i,:),'Color',color,'LineWidth',linewidth); else @@ -538,18 +538,18 @@ function applyoptions(md,data,options) set(gca,'color',getfieldvalue(options,'backgroundcolor','none')); %lighting -if strcmpi(getfieldvalue(options,'light','off'),'on'), +if strcmpi(getfieldvalue(options,'light','off'),'on') set(gca,'FaceLighting','gouraud','FaceColor','interp','AmbientStrength',0.5); light('Position',[0 0.1 0.1],'Style','infinite'); end %cloud of points: -if exist(options,'cloud'), +if exist(options,'cloud') field=getfieldvalue(options,'cloud'); x=field(:,1); y=field(:,2); %unit multiplier: - if exist(options,'unit'), + if exist(options,'unit') unit=getfieldvalue(options,'unit'); x=x*unit; y=y*unit; @@ -564,7 +564,7 @@ function applyoptions(md,data,options) %========================% %OK VERY LAST STEP: INSET| %========================% -if exist(options,'inset'), +if exist(options,'inset') %Keep pointer of main axis maingca=gca; @@ -576,20 +576,20 @@ function applyoptions(md,data,options) X1=getfieldvalue(options,'insetx',xlim); Y1=getfieldvalue(options,'insety',ylim); - for i=1:length(getfieldvalue(options,'insetx')), - if length(insetpos)==4, + for i=1:length(getfieldvalue(options,'insetx')) + if length(insetpos)==4 insetposi=insetpos; else insetposi=insetpos{i}; end PosInseti=[cplotpos(1)+insetposi(1)*cplotpos(3),cplotpos(2)+insetposi(2)*cplotpos(4), insetposi(3)*cplotpos(3), insetposi(4)*cplotpos(4)]; %show pos - if iscell(X1), + if iscell(X1) X1i=X1{i}; else X1i=X1; end - if iscell(Y1), + if iscell(Y1) Y1i=Y1{i}; else Y1i=Y1; diff --git a/src/m/plot/checkplotoptions.m b/src/m/plot/checkplotoptions.m index d606a0638..1c2ba9cbf 100644 --- a/src/m/plot/checkplotoptions.m +++ b/src/m/plot/checkplotoptions.m @@ -7,7 +7,7 @@ % See also: PLOTMODEL %units -if exist(options,'unit'), +if exist(options,'unit') if strcmpi(getfieldvalue(options,'unit'),'km') options=changefieldvalue(options,'unit',10^-3); end @@ -18,34 +18,34 @@ end %density -if exist(options,'density'), +if exist(options,'density') density=getfieldvalue(options,'density'); options=changefieldvalue(options,'density',abs(ceil(density))); end %Show section -if exist(options,'showsection'), +if exist(options,'showsection') if strcmpi(getfieldvalue(options,'showsection'),'on') options=changefieldvalue(options,'showsection',4); end end %smooth values -if exist(options,'smooth'), +if exist(options,'smooth') if strcmpi(getfieldvalue(options,'smooth'),'on') options=changefieldvalue(options,'smooth',0); end end %contouronly values -if exist(options,'contouronly'), +if exist(options,'contouronly') if strcmpi(getfieldvalue(options,'contouronly'),'on') options=changefieldvalue(options,'contouronly',1); end end %Colorbar; -if exist(options,'colorbar'), +if exist(options,'colorbar') if strcmpi(getfieldvalue(options,'colorbar'),'on') options=changefieldvalue(options,'colorbar',1); elseif strcmpi(getfieldvalue(options,'colorbar'),'off') @@ -54,24 +54,24 @@ end %text -if exist(options,'text'), +if exist(options,'text') %1: textvalue textvalues=getfieldvalue(options,'text'); %ischar if only one expstyle -> create a cell - if ischar(textvalues), + if ischar(textvalues) textvalues={textvalues}; numtext=1; - elseif iscell(textvalues), + elseif iscell(textvalues) numtext=length(textvalues); else error('plot error message: ''text'' option should be either a string or a cell'); end %2: textweight - if exist(options,'textweight'), + if exist(options,'textweight') textweightvalues=getfieldvalue(options,'textweight'); %ischar if only one textweight -> create a cell - if ischar(textweightvalues), + if ischar(textweightvalues) textweightvalues={textweightvalues}; elseif ~iscell(textweightvalues); error('plot error message: ''textweight'' option should be either a string or a cell'); @@ -82,10 +82,10 @@ textweightvalues=repmat(textweightvalues,1,numtext); textweightvalues(numtext+1:end)=[]; %3: textsize - if exist(options,'textsize'), + if exist(options,'textsize') textsizevalues=getfieldvalue(options,'textsize'); %ischar if only one textsize -> create a cell - if isnumeric(textsizevalues), + if isnumeric(textsizevalues) textsizevalues={textsizevalues}; elseif ~iscell(textsizevalues); error('plot error message: ''textsize'' option should be either a number or a cell'); @@ -95,10 +95,10 @@ end textsizevalues=repmat(textsizevalues,1,numtext); textsizevalues(numtext+1:end)=[]; %4: textcolor - if exist(options,'textcolor'), + if exist(options,'textcolor') textcolorvalues=getfieldvalue(options,'textcolor'); %ischar if only one textcolor -> create a cell - if ischar(textcolorvalues), + if ischar(textcolorvalues) textcolorvalues={textcolorvalues}; elseif ~iscell(textcolorvalues); error('plot error message: ''textcolor'' option should be either a string or a cell'); @@ -108,10 +108,10 @@ end textcolorvalues=repmat(textcolorvalues,1,numtext); textcolorvalues(numtext+1:end)=[]; %5: textposition - if exist(options,'textposition'), + if exist(options,'textposition') textpositionvalues=getfieldvalue(options,'textposition'); %ischar if only one textposition -> create a cell - if isnumeric(textpositionvalues), + if isnumeric(textpositionvalues) textpositionvalues={textpositionvalues}; elseif ~iscell(textpositionvalues); error('plot error message: ''textposition'' option should be either a string or a cell'); @@ -120,10 +120,10 @@ error('plot error message: ''textposition'' option is missing'); end %6: textrotation - if exist(options,'textrotation'), + if exist(options,'textrotation') textrotationvalues=getfieldvalue(options,'textrotation'); %ischar if only one textsize -> create a cell - if isnumeric(textrotationvalues), + if isnumeric(textrotationvalues) textrotationvalues={textrotationvalues}; elseif ~iscell(textrotationvalues); error('plot error message: ''textrotation'' option should be either a number or a cell'); @@ -144,22 +144,22 @@ expdispvaluesarray=cell(0,0); expstylevaluesarray=cell(0,0); expstylevalues=cell(0,0); -if exist(options,'expstyle'), +if exist(options,'expstyle') expstylevalues=getfieldvalue(options,'expstyle'); %ischar if only one expstyle -> create a cell - if ischar(expstylevalues), + if ischar(expstylevalues) expstylevalues={expstylevalues}; end end -if exist(options,'expdisp'), +if exist(options,'expdisp') expdispvalues=getfieldvalue(options,'expdisp'); %ischar if only one expstyle -> create a cell - if ischar(expdispvalues), + if ischar(expdispvalues) expdispvalues={expdispvalues}; end for i=1:length(expdispvalues) expdispvaluesarray{end+1}=expdispvalues{i}; - if (length(expstylevalues)>=i), + if (length(expstylevalues)>=i) expstylevaluesarray{end+1}=expstylevalues{i}; else expstylevaluesarray{end+1}='g-'; @@ -170,14 +170,14 @@ options=changefieldvalue(options,'expdisp',expdispvaluesarray); %latlonnumbering -if exist(options,'latlonclick'), +if exist(options,'latlonclick') if strcmpi(getfieldvalue(options,'latlonclick'),'on') options=changefieldvalue(options,'latlonclick',1); end end %north arrow -if exist(options,'northarrow'), +if exist(options,'northarrow') if strcmpi(getfieldvalue(options,'northarrow'),'on') %default values Lx=max(md.mesh.y)-min(md.mesh.y); @@ -188,7 +188,7 @@ end %scale ruler -if exist(options,'scaleruler'), +if exist(options,'scaleruler') if strcmpi(getfieldvalue(options,'scaleruler'),'on') %default values Lx=max(md.mesh.x)-min(md.mesh.x); @@ -199,7 +199,7 @@ end %Log scale (LOTS of changes to be performed -if exist(options,'log'), +if exist(options,'log') if exist(options,'caxis') options=addfield(options,'caxis_pre',getfieldvalue(options,'caxis')); options=changefieldvalue(options,'caxis',log(getfieldvalue(options,'caxis'))/log(getfieldvalue(options,'log'))); diff --git a/src/m/plot/colormaps/cmaptools.py b/src/m/plot/colormaps/cmaptools.py index b39448746..8ee028c9a 100644 --- a/src/m/plot/colormaps/cmaptools.py +++ b/src/m/plot/colormaps/cmaptools.py @@ -30,7 +30,7 @@ def getcolormap(options): if type(map_name) == mpl.colors.ListedColormap: return map_name elif map_name in plt.colormaps(): - return map_name + return plt.get_cmap(map_name) # return object, not name string elif map_name == '': return cmap diff --git a/src/m/plot/colormaps/demmap.m b/src/m/plot/colormaps/demmap.m index 2bf425fcc..f7a4a362a 100644 --- a/src/m/plot/colormaps/demmap.m +++ b/src/m/plot/colormaps/demmap.m @@ -10,15 +10,15 @@ % cmap = demmap(50,-300,1200,'ibcao'); %Input checks -if nargin<3, +if nargin<3 help demmap error('3 or 4 arguments necessary'); -elseif nargin>4, +elseif nargin>4 help demmap error('3 or 4 arguments necessary'); end -if nargin==4, +if nargin==4 colorscheme = varargin{1}; if ~ischar(colorscheme), error('color scheme should be a string'); end else @@ -72,7 +72,7 @@ clim = [cmn cmx]; -if strcmpi(colorscheme,'dem'), +if strcmpi(colorscheme,'dem') cmap = [seacolor(nsea);landcolor(nland).^1.3]; elseif strcmpi(colorscheme,'ibcao'); cmap = ibcao(nsea,nland); diff --git a/src/m/plot/colormaps/demmap.py b/src/m/plot/colormaps/demmap.py index 4da9a3cf4..e6a420806 100755 --- a/src/m/plot/colormaps/demmap.py +++ b/src/m/plot/colormaps/demmap.py @@ -49,8 +49,8 @@ def demmap(ncolors, minZ, maxZ, colorscheme='dem'): ratio = land / sea errors = abs(ratio - maxminratio) / maxminratio indx = np.where(errors == min(errors)) - nsea = sea[indx] - nland = land[indx] + nsea = int(sea[indx][0]) + nland = int(land[indx][0]) # determine color limits seaint = abs(minZ) / nsea diff --git a/src/m/plot/colormaps/distinguishable_colors.m b/src/m/plot/colormaps/distinguishable_colors.m index f9e9e2567..6887b1cc9 100644 --- a/src/m/plot/colormaps/distinguishable_colors.m +++ b/src/m/plot/colormaps/distinguishable_colors.m @@ -61,7 +61,7 @@ bg = [1 1 1]; % default white background else if iscell(bg) - % User specified a list of colors as a cell aray + % User specified a list of colors as a cell array bgc = bg; for i = 1:length(bgc) bgc{i} = parsecolor(bgc{i}); @@ -138,9 +138,9 @@ if isempty(k) error('MATLAB:InvalidColorString','Unknown color string.'); end - if k~=3 || length(c)==1, + if k~=3 || length(c)==1 c = rgbspec(k,:); - elseif length(c)>2, + elseif length(c)>2 if strcmpi(c(1:3),'bla') c = [0 0 0]; elseif strcmpi(c(1:3),'blu') diff --git a/src/m/plot/colormaps/getcolormap.m b/src/m/plot/colormaps/getcolormap.m index fd62cd34f..f5567e532 100644 --- a/src/m/plot/colormaps/getcolormap.m +++ b/src/m/plot/colormaps/getcolormap.m @@ -5,7 +5,7 @@ % map = getcolormap(options) %default is turbo -if ~exist(options,'colormap'), +if ~exist(options,'colormap') map = turbo(); return end @@ -19,39 +19,39 @@ %OK this is an in-house colormap if ~ischar(map), error('colormap format not supported'); end -if strcmpi(map,'Ala'), +if strcmpi(map,'Ala') map = jet(256); map = map(128:end,:); -elseif strcmpi(map,'damage'), +elseif strcmpi(map,'damage') v=ver; - if any(strcmp('Image Processing Toolbox',{v.Name})), + if any(strcmp('Image Processing Toolbox',{v.Name})) map = color_scale(256,0,70,'ccw'); map = flipud(map); map(1:2,:)=[0.7476 1.0000 1.0000; 0.7476 1.0000 1.0000]; else error('damage colormap requires Image Processing Toolbox, please try another colormap'); end -elseif strcmpi(map,'redblue'), +elseif strcmpi(map,'redblue') map = hsv(128); map = rgb2hsv(map); map(:,2) = max(min( abs(map(:,1)-0.5)/0.5 ,1),0); map(1:64,1) = 0.7; map(65:end,1) = 1; map = hsv2rgb(map); -elseif strcmpi(map,'Rignot'), +elseif strcmpi(map,'Rignot') alpha=getfieldvalue(options,'alpha',1); map = hsv(128); map = rgb2hsv(map); map(:,2) = max(min( (0.1+map(:,1)).^(1/alpha) ,1),0); map = hsv2rgb(map); -elseif strcmpi(map,'Rignot2'), +elseif strcmpi(map,'Rignot2') alpha=getfieldvalue(options,'alpha',1); map = hsv; map = rgb2hsv(map); map(:,2) = max(min( (0.1+map(:,1)).^(1/alpha) ,1),0); map = hsv2rgb(map); map=flipud(map); -elseif strcmpi(map,'Seroussi'), +elseif strcmpi(map,'Seroussi') alpha=getfieldvalue(options,'alpha',1); map = hsv; map = flipud(map); diff --git a/src/m/plot/curvedarrow.m b/src/m/plot/curvedarrow.m index cdb6f2e28..4c260c988 100644 --- a/src/m/plot/curvedarrow.m +++ b/src/m/plot/curvedarrow.m @@ -24,7 +24,7 @@ function curvedarrow(centerx,centery,distance,angle,secondangle,varargin) %compute some values out of (x1,y1) and (x2,y2) length=distance*angle; - if exist(options,'widthratio'), + if exist(options,'widthratio') widthratio=getfieldvalue(options,'widthratio'); width=length*widthratio; else if exist(options,'width'), @@ -57,7 +57,7 @@ function curvedarrow(centerx,centery,distance,angle,secondangle,varargin) m=-m; end - if exist(options,'arrowlength'), + if exist(options,'arrowlength') d=arrowlength; else d=abs((distance*angle)*ratio); diff --git a/src/m/plot/export_gl.m b/src/m/plot/export_gl.m index dc16b3f70..af7d70bd7 100644 --- a/src/m/plot/export_gl.m +++ b/src/m/plot/export_gl.m @@ -78,33 +78,33 @@ function export_gl(md,varargin) %Deal with data: results=struct([]); - for i=1:length(optionslist), + for i=1:length(optionslist) options=optionslist{i}; options=checkplotoptions(md,options); data=getfieldvalue(options,'data'); results(i).data=data; results(i).caxis=getfieldvalue(options,'caxis',[min(data(:)) max(data(:))]); label=getfieldvalue(options,'label',''); - if strcmpi(label,''), + if strcmpi(label,'') %create generic label: label=['data' num2str(i)]; end results(i).label=label; shortlabel=getfieldvalue(options,'shortlabel',''); - if strcmpi(shortlabel,''), + if strcmpi(shortlabel,'') %create generic short label: shortlabel=['data' num2str(i)]; end results(i).shortlabel=shortlabel; - if size(data,2)>1, + if size(data,2)>1 time_range=getfieldvalue(options,'time_range',[0 100]); results(i).time_range=time_range; end unit=getfieldvalue(options,'unit',''); - if strcmpi(unit,''), + if strcmpi(unit,'') %create generic unit: unit='SI'; end diff --git a/src/m/plot/googlemaps.m b/src/m/plot/googlemaps.m index c9cfdddc2..f728172cd 100644 --- a/src/m/plot/googlemaps.m +++ b/src/m/plot/googlemaps.m @@ -14,40 +14,40 @@ % - zoomlevel: between 1 and 21 (default dynamically calculated) %Parse inputs -if nargin<=5, +if nargin<=5 options=pairoptions; else options=varargin{:}; - if ~isa(options,'pairoptions'), + if ~isa(options,'pairoptions') options=pairoptions(varargin{:}); end end %Check that no temp.* exists -if exist('temp.tiff','file'), +if exist('temp.tiff','file') error('File temp.tiff already exists, remove first'); end -if exist('temp.png','file'), +if exist('temp.png','file') error('File temp.png already exists, remove first'); end -if nargin==2, +if nargin==2 options=addfielddefault(options,'zoomlevel',ullat); end -if md.mesh.epsg==0, +if md.mesh.epsg==0 error('md.mesh.epsg not defined'); end -if nargin<3, +if nargin<3 %Get xlim and ylim (used to extract Google maps image) xlim=getfieldvalue(options,'xlim',[min(md.mesh.x) max(md.mesh.x)]); ylim=getfieldvalue(options,'ylim',[min(md.mesh.y) max(md.mesh.y)]); - if md.mesh.epsg==3413, + if md.mesh.epsg==3413 [latlist lonlist]= xy2ll(... [linspace(xlim(1),xlim(2),100) linspace(xlim(2),xlim(2),100) linspace(xlim(2),xlim(1),100) linspace(xlim(1),xlim(1),100)],... [linspace(ylim(1),ylim(1),100) linspace(ylim(1),ylim(2),100) linspace(ylim(2),ylim(2),100) linspace(ylim(2),ylim(1),100)],... +1,45,70); - elseif md.mesh.epsg==3031, + elseif md.mesh.epsg==3031 [latlist lonlist]= xy2ll(... [linspace(xlim(1),xlim(2),100) linspace(xlim(2),xlim(2),100) linspace(xlim(2),xlim(1),100) linspace(xlim(1),xlim(1),100)],... [linspace(ylim(1),ylim(1),100) linspace(ylim(1),ylim(2),100) linspace(ylim(2),ylim(2),100) linspace(ylim(2),ylim(1),100)],... @@ -57,7 +57,7 @@ [linspace(xlim(1),xlim(2),100) linspace(xlim(2),xlim(2),100) linspace(xlim(2),xlim(1),100) linspace(xlim(1),xlim(1),100)],... [linspace(ylim(1),ylim(1),100) linspace(ylim(1),ylim(2),100) linspace(ylim(2),ylim(2),100) linspace(ylim(2),ylim(1),100)],... 6); - elseif numel(md.mesh.lat)==numel(md.mesh.x), + elseif numel(md.mesh.lat)==numel(md.mesh.x) latlist = md.mesh.lat; %That might work? lonlist = md.mesh.long; else @@ -67,7 +67,7 @@ %Image corners in lat/long ullat = max(latlist); ullon = min(lonlist); lrlat = min(latlist); lrlon = max(lonlist); -elseif nargin>1 & nargin<5, +elseif nargin>1 & nargin<5 help googlemaps error('Wrong usage'); end @@ -77,7 +77,7 @@ EPSGlocal = ['EPSG:' num2str(md.mesh.epsg)]; %Find optimal zoomlevel -if exist(options,'zoomlevel'), +if exist(options,'zoomlevel') zoomlevel = getfieldvalue(options,'zoomlevel'); else zoomlevel = optimalzoomlevel(ullat,ullon,lrlat,lrlon); @@ -120,8 +120,8 @@ %Initialize final image final = zeros(floor(dy),floor(dx),3);%RGB image - for x=0:cols-1, - for y=0:rows-1, + for x=0:cols-1 + for y=0:rows-1 dxn = width * (0.5 + x); dyn = height * (0.5 + y); [latn, lonn] = pixelstolatlon(ulx + dxn, uly - dyn - bottom/2, zoomlevel); @@ -137,7 +137,7 @@ '&maptype=satellite'... '&sensor=false'... '&scale=' num2str(scale)]; - if iskey, + if iskey params = [params,'&key=' key]; end url = ['http://maps.google.com/maps/api/staticmap?' params]; @@ -151,7 +151,7 @@ disp(['Failed, trying again... (' num2str(countmax-count) ' more attempts)']); count = count+1; pause(.3); - if count>countmax, + if count>countmax disp('Giving up...'); rethrow(me); end @@ -214,7 +214,7 @@ delete('temp.png'); %If not GDAL, exit -if status~=0, +if status~=0 disp(result); disp('googlemaps info: GDAL not found or not working properly, the Google image will not be transformed'); md.radaroverlay.pwr=final; @@ -228,7 +228,7 @@ delete('temp.tiff','temp.tfw'); %If previous command failed, exit -if ~isempty(strfind(result,'ERROR')), +if ~isempty(strfind(result,'ERROR')) disp(result); disp(' ');disp('googlemaps info: GDAL not working properly (missing PROJ.4 library?), Google image will not be transformed'); disp(result); diff --git a/src/m/plot/kmlgridded.m b/src/m/plot/kmlgridded.m index fab779b32..dea808550 100644 --- a/src/m/plot/kmlgridded.m +++ b/src/m/plot/kmlgridded.m @@ -11,7 +11,7 @@ function kmlgridded(md,data,varargin) [data datatype]=processdata(md,data,options); %check is2d -if ~is2d, +if ~is2d error('buildgridded error message: gridded not supported for 3d meshes, project on a layer'); end @@ -27,11 +27,11 @@ function kmlgridded(md,data,varargin) x_m = xlim(1):post:xlim(2); y_m = ylim(1):post:ylim(2); data_grid=InterpFromMeshToGrid(elements,x,y,data,x_m,y_m,NaN); -if size(data_grid,1)<3 | size(data_grid,2)<3, +if size(data_grid,1)<3 | size(data_grid,2)<3 error('data_grid size too small, check posting and units'); end pos=find(isinf(data_grid)); -if ~isempty(pos), +if ~isempty(pos) disp('Warning: removing Infs from vector (probably log(0)?)'); data_grid(pos)=NaN; end @@ -40,7 +40,7 @@ function kmlgridded(md,data,varargin) data_nan=find(isnan(data_grid)); data_min=min(data_grid(:)); data_max=max(data_grid(:)); -if exist(options,'caxis'), +if exist(options,'caxis') caxis_opt=getfieldvalue(options,'caxis'); data_grid(find(data_gridcaxis_opt(2)))=caxis_opt(2); @@ -81,7 +81,7 @@ function kmlgridded(md,data,varargin) %prepare colorbar iscolorbar=0; -if strcmpi(getfieldvalue(options,'colorbar','on'),'on'), +if strcmpi(getfieldvalue(options,'colorbar','on'),'on') X = linspace(0,1,len)'; Xlab = round(linspace(data_min,data_max,len+1)); html = ['',10]; @@ -116,7 +116,7 @@ function kmlgridded(md,data,varargin) fprintf(fid,'%s\n',''); fprintf(fid,'%s\n',''); fprintf(fid,'%s%s%s\n','',kmlfilename,''); -if iscolorbar, +if iscolorbar fprintf(fid,'\n'); fprintf(fid,'%s%s%s\n','','click the icon to see the colorbar',''); fprintf(fid,'%s%s%s\n','','Ground overlay colorbar',''); diff --git a/src/m/plot/kmlgroundoverlay.m b/src/m/plot/kmlgroundoverlay.m index b6f0512b3..55606f454 100644 --- a/src/m/plot/kmlgroundoverlay.m +++ b/src/m/plot/kmlgroundoverlay.m @@ -11,7 +11,7 @@ function kmlgroundoverlay(md,options) % %first figure out if lat and long were computed! -if (isempty(md.mesh.lat) | isempty(md.mesh.long)), +if (isempty(md.mesh.lat) | isempty(md.mesh.long)) error('kmlgroundoverlay error message: project x,y onto lat,long fields of model!'); end @@ -27,7 +27,7 @@ function kmlgroundoverlay(md,options) kmlgroundoverlaydescription=getfieldvalue(options,'kmlgroundoverlaydescription',''); %figure out min and max for lat and long of this image: -if strcmpi(getfieldvalue(options,'coord',''),'latlon'), +if strcmpi(getfieldvalue(options,'coord',''),'latlon') %need to plot with option 'coord','latlon' XLIM=xlim(); YLIM=ylim(); diff --git a/src/m/plot/landsatmap.m b/src/m/plot/landsatmap.m index b2e38412a..2233d1e0a 100644 --- a/src/m/plot/landsatmap.m +++ b/src/m/plot/landsatmap.m @@ -17,7 +17,7 @@ [x y z elements is2d isplanet]=processmesh(md,[],options); %check is2d -if ~is2d, +if ~is2d error('buildgridded error message: gridded not supported for 3d meshes, project on a layer'); end @@ -65,7 +65,7 @@ if exist(limapath{ii}), pos(ii) = 1; end end - if sum(pos) == 0, + if sum(pos) == 0 fprintf('download website : https://lima.usgs.gov/fullcontinent.php\n'); error('Landsat image at Antarctic region should be downloaded at above website'); end @@ -102,7 +102,7 @@ if exist(limapath{ii}), pos(ii) = 1; end end - if sum(pos) == 0, + if sum(pos) == 0 fprintf('download website : https://lima.usgs.gov/fullcontinent.php\n'); error('Landsat image at Antarctic region should be downloaded at above website'); end diff --git a/src/m/plot/latlonoverlay.m b/src/m/plot/latlonoverlay.m index 025e9b327..087749cc5 100644 --- a/src/m/plot/latlonoverlay.m +++ b/src/m/plot/latlonoverlay.m @@ -17,8 +17,8 @@ function latlonoverlay(md,options) %recover arguments (set default parameters if needed) %1: latlon -if ~iscell(latlon), - if ischar(latlon) & strcmpi(latlon,'on'), +if ~iscell(latlon) + if ischar(latlon) & strcmpi(latlon,'on') %defaults latstep=3; lonstep=3; resolution=0.1; @@ -35,11 +35,11 @@ function latlonoverlay(md,options) end %2: numbering -if ~iscell(numbering) & isnan(numbering), +if ~iscell(numbering) & isnan(numbering) numbering=false; else - if ~iscell(numbering), - if strcmpi(char(numbering),'on'), + if ~iscell(numbering) + if strcmpi(char(numbering),'on') %defaults latgap=2; longap=2; colornumber=color; @@ -65,10 +65,10 @@ function latlonoverlay(md,options) longitudes=0:resolution:360; latitudes =lat*ones(size(longitudes)); - if md.mesh.epsg==3413, + if md.mesh.epsg==3413 if lat<0, continue; end [x,y]=ll2xy(latitudes,longitudes,+1,45,70); - elseif md.mesh.epsg==3031, + elseif md.mesh.epsg==3031 if lat>0, continue; end [x,y]=ll2xy(latitudes,longitudes,-1, 0,71); else error('field md.mesh.epsg not supported yet'); end @@ -84,7 +84,7 @@ function latlonoverlay(md,options) xcorner=x(ind); ycorner=y(ind); xcorner2=x(max(ind-10,1)); ycorner2=y(max(ind-10,1)); - if (xcorner>xlimits(1) & xcornerylimits(1) & ycornerxlimits(1) & xcornerylimits(1) & ycornerxlimits(1) & xcornerylimits(1) & ycornerxlimits(1) & xcornerylimits(1) & ycornerzmax, +if zmin>zmax error('zmin should be smaller than zmax'); end @@ -31,7 +31,7 @@ %process options options = pairoptions(varargin{:}); -if exist(options,'tick') & exist(options,'ticksep'), +if exist(options,'tick') & exist(options,'ticksep') error('only one of tick or ticksep can be specified'); end fontsize = getfieldvalue(options,'fontsize',12); @@ -39,7 +39,7 @@ smallbars = getfieldvalue(options,'smallbars',false); %Colorbar position -if ~exist(options,'position'), +if ~exist(options,'position') position = plotboxpos; xstart = position(1)+position(3)+0.01; ystart = position(2); @@ -57,10 +57,10 @@ ylim([0 1]); %Prepare ticks -if ~exist(options,'log'), +if ~exist(options,'log') deltaz = getfieldvalue(options,'ticksep',dtick(zmax-zmin)); ztick = getfieldvalue(options,'tick',(deltaz*ceil(zmin/deltaz)):deltaz:zmax); - if (any(ztick>zmax) | any(ztickzmax) | any(ztick take average data=averaging(md,data,0); -elseif datatype==2, +elseif datatype==2 %nodes -> do nothing -elseif datatype==3, +elseif datatype==3 %quiver -> take norm data=sqrt(sum(datain.*datain,2)); else @@ -40,7 +40,7 @@ function plot_contour(md,datain,options) %get contours levels contourlevels=getfieldvalue(options,'contourlevels'); -if isnumeric(contourlevels), +if isnumeric(contourlevels) levels=round_ice(linspace(max(data),min(data),contourlevels),2); else levels=[]; @@ -105,7 +105,7 @@ function plot_contour(md,datain,options) numelems=length(poselem); %if no element has been flagged, skip to the next level - if numelems==0, + if numelems==0 continue, end @@ -119,7 +119,7 @@ function plot_contour(md,datain,options) edge_l=zeros(numelems,2); - for j=1:numelems, + for j=1:numelems weight1=(level-Data1(poselem(j),1))/(Data1(poselem(j),2)-Data1(poselem(j),1)); weight2=(level-Data2(poselem(j),1))/(Data2(poselem(j),2)-Data2(poselem(j),1)); @@ -136,7 +136,7 @@ function plot_contour(md,datain,options) edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg2_num(poselem(j)); - elseif poselem13(poselem(j)), + elseif poselem13(poselem(j)) x1(j)=x(Seg1(poselem(j),1))+weight1*(x(Seg1(poselem(j),2))-x(Seg1(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -148,7 +148,7 @@ function plot_contour(md,datain,options) edge_l(j,1)=Seg1_num(poselem(j)); edge_l(j,2)=Seg3_num(poselem(j)); - elseif poselem23(poselem(j)), + elseif poselem23(poselem(j)) x1(j)=x(Seg2(poselem(j),1))+weight2*(x(Seg2(poselem(j),2))-x(Seg2(poselem(j),1))); x2(j)=x(Seg3(poselem(j),1))+weight3*(x(Seg3(poselem(j),2))-x(Seg3(poselem(j),1))); @@ -166,7 +166,7 @@ function plot_contour(md,datain,options) %now that we have the segments, we must try to connect them... %loop over the subcontours - while ~isempty(edge_l), + while ~isempty(edge_l) %take the right edge of the second segment and connect it to the next segments if any e1=edge_l(1,1); e2=edge_l(1,2); @@ -182,7 +182,7 @@ function plot_contour(md,datain,options) while ~isempty(ro1) - if co1==1, + if co1==1 xc=[x2(ro1);xc]; yc=[y2(ro1);yc]; zc=[z2(ro1);zc]; %next edge: @@ -210,7 +210,7 @@ function plot_contour(md,datain,options) while ~isempty(ro2) - if co2==1, + if co2==1 xc=[xc;x2(ro2)]; yc=[yc;y2(ro2)]; zc=[zc;z2(ro2)]; %next edge: @@ -233,8 +233,8 @@ function plot_contour(md,datain,options) end %we now have one subcontour ready to be plotted - if getfieldvalue(options,'contouronly',0), - if isplanet, + if getfieldvalue(options,'contouronly',0) + if isplanet h=[h;patch('Xdata',[xc;NaN],'Ydata',[yc;NaN],'Zdata',[zc;NaN],'facecolor','none','linewidth',linewidth)]; else h=[h;patch('Xdata',[xc;NaN],'Ydata',[yc;NaN],'Zdata',zc,'Cdata',zc,'facecolor','none','edgecolor','flat','linewidth',linewidth)]; @@ -243,7 +243,7 @@ function plot_contour(md,datain,options) else %dist = 5000; dist = 0; - if isplanet, + if isplanet if (max(xc)-min(xc)+max(yc)-min(yc)+max(zc)-min(zc))caxis_opt(2)))=caxis_opt(2); @@ -84,7 +84,7 @@ function plot_googlemaps(md,data,options,plotlines,plotcols,i) colorm = getcolormap(options); image_rgb = ind2rgb(uint16((data_grid - data_min)*(length(colorm)/(data_max-data_min))),colorm); -if exist(options,'shaded'), +if exist(options,'shaded') a = -45; scut = 0.2; c = 1; @@ -118,13 +118,13 @@ function plot_googlemaps(md,data,options,plotlines,plotcols,i) h=imagesc(x_m*getfieldvalue(options,'unit',1),y_m*getfieldvalue(options,'unit',1),final); %last step: mesh gridded? -if exist(options,'edgecolor'), +if exist(options,'edgecolor') A=elements(:,1); B=elements(:,2); C=elements(:,3); patch('Faces',[A B C],'Vertices', [x y z],'FaceVertexCData',data_grid(1)*ones(size(x)),'FaceColor','none','EdgeColor',getfieldvalue(options,'edgecolor')); end %Apply options -if ~isnan(data_min), +if ~isnan(data_min) options=changefieldvalue(options,'caxis',[data_min data_max]); % force caxis so that the colorbar is ready end options=addfielddefault(options,'axis','xy equal off'); % default axis diff --git a/src/m/plot/plot_gridded.m b/src/m/plot/plot_gridded.m index 4e28acd37..91c980adf 100644 --- a/src/m/plot/plot_gridded.m +++ b/src/m/plot/plot_gridded.m @@ -20,7 +20,7 @@ function plot_gridded(md,data,options,plotlines,plotcols,i) end %check is2d -if ~is2d, +if ~is2d error('buildgridded error message: gridded not supported for 3d meshes, project on a layer'); end @@ -45,7 +45,7 @@ function plot_gridded(md,data,options,plotlines,plotcols,i) y_m = ylim(1):posty:ylim(2); data_grid=InterpFromMeshToGrid(elements,x,y,data,x_m,y_m,NaN); data_grid_save = data_grid; -if size(data_grid,1)<3 | size(data_grid,2)<3, +if size(data_grid,1)<3 | size(data_grid,2)<3 error('data_grid size too small in plot_gridded, check posting and units'); end @@ -57,7 +57,7 @@ function plot_gridded(md,data,options,plotlines,plotcols,i) %Process data_grid: add white in NaN and correct caxis accordingly [data_nani data_nanj]=find(isnan(data_grid) | data_grid==-9999); -if exist(options,'caxis'), +if exist(options,'caxis') caxis_opt=getfieldvalue(options,'caxis'); data_grid(find(data_gridcaxis_opt(2)))=caxis_opt(2); @@ -74,9 +74,9 @@ function plot_gridded(md,data,options,plotlines,plotcols,i) %shading interp; map = getcolormap(options); image_rgb = ind2rgb(uint16((data_grid - data_min)*(length(map)/(data_max-data_min))),map); -if exist(options,'shaded'), +if exist(options,'shaded') - if exist(options,'dem'), + if exist(options,'dem') dem_grid=InterpFromMeshToGrid(elements,x,y,getfieldvalue(options,'dem'),x_m,y_m,NaN); else dem_grid=data_grid_save; @@ -113,13 +113,13 @@ function plot_gridded(md,data,options,plotlines,plotcols,i) axis xy %last step: mesh gridded? -if exist(options,'edgecolor'), +if exist(options,'edgecolor') A=elements(:,1); B=elements(:,2); C=elements(:,3); patch('Faces',[A B C],'Vertices', [x y z],'FaceVertexCData',data_grid(1)*ones(size(x)),'FaceColor','none','EdgeColor',getfieldvalue(options,'edgecolor')); end %Apply options -if ~isnan(data_min) & ~isinf(data_min), +if ~isnan(data_min) & ~isinf(data_min) options=changefieldvalue(options,'caxis',[data_min data_max]); % force caxis so that the colorbar is ready end options=addfielddefault(options,'axis','xy equal'); % default axis diff --git a/src/m/plot/plot_gridded.py b/src/m/plot/plot_gridded.py index 2c5383e44..906b6cb45 100644 --- a/src/m/plot/plot_gridded.py +++ b/src/m/plot/plot_gridded.py @@ -96,6 +96,8 @@ def plot_gridded(md,data,options,fig,axgrid,gridindex): options.addfielddefault('colormap',plt.cm.turbo) #options.addfielddefault('colormap',plt.cm.viridis) cmap = getcolormap(copy.deepcopy(options)) + if isinstance(cmap, str): # getcolormap may return a name string; convert + cmap = plt.get_cmap(cmap) #TODO: Matlab version #image_rgb = ind2rgb(uint16((data_grid - data_min)*(length(map)/(data_max-data_min))),cmap); #NOTE: Python version @@ -155,8 +157,6 @@ def plot_gridded(md,data,options,fig,axgrid,gridindex): #last step: mesh gridded? if options.exist('edgecolor'): - #A=elements[:,0]; B=elements[:,1]; C=elements[:,2] - #patch('Faces',[A B C],'Vertices', [x y z],'FaceVertexCData',data_grid(1)*ones(size(x)),'FaceColor','none','EdgeColor',getfieldvalue(options,'edgecolor')); ax.triplot(x,y,triangles=elements, color=options.getfieldvalue('edgecolor'), linewidth=options.getfieldvalue('linewidth',1), diff --git a/src/m/plot/plot_icefront.m b/src/m/plot/plot_icefront.m index 912ffa134..b56c1aaa7 100644 --- a/src/m/plot/plot_icefront.m +++ b/src/m/plot/plot_icefront.m @@ -18,7 +18,7 @@ elementnoice=sum(noice(md.mesh.elements),2); elementzeroice=sum(zeroice(md.mesh.elements),2); -if is2d, +if is2d icefront=(elementice & elementnoice) & ~(elementice==2 & elementzeroice); %plot mesh diff --git a/src/m/plot/plot_importancefactors.m b/src/m/plot/plot_importancefactors.m index 60a1c2493..fb7176211 100644 --- a/src/m/plot/plot_importancefactors.m +++ b/src/m/plot/plot_importancefactors.m @@ -7,7 +7,7 @@ function plot_importancefactors(md,options,width,ii) % See also: PLOTMODEL %first recover design variable descriptor -if exist(options,'designvariable'), +if exist(options,'designvariable') descriptor=getfieldvalue(options,'designvariable'); else error('plot_importancefactors error message: Need to supply design variable descriptor'); @@ -15,7 +15,7 @@ function plot_importancefactors(md,options,width,ii) descriptorlength=length(descriptor); %then recover responsfunction name -if exist(options,'responsefunction'), +if exist(options,'responsefunction') responsefunctiondescriptor=getfieldvalue(options,'responsefunction'); else error('plot_importancefactors error message: Need to supply response function descriptor'); @@ -24,13 +24,13 @@ function plot_importancefactors(md,options,width,ii) %go through all response functions and find the one corresponding to the correct responsefunctiondescriptor responsefunctions=md.qmu.results{2}; found=0; -for i=1:length(responsefunctions), - if strcmpi(responsefunctions(i).descriptor,responsefunctiondescriptor), +for i=1:length(responsefunctions) + if strcmpi(responsefunctions(i).descriptor,responsefunctiondescriptor) found=i; break; end end -if ~found, +if ~found error('plot_importancefactors error message: could not find correct response function'); end responsefunctions=responsefunctions(found); @@ -39,19 +39,19 @@ function plot_importancefactors(md,options,width,ii) %Now recover response to the correct desgin variable importancefactors=zeros(md.qmu.numberofpartitions,1); count=0; -for i=1:nfun, +for i=1:nfun desvar=responsefunctions.desvar{i}; - if strncmpi(desvar,descriptor,descriptorlength), + if strncmpi(desvar,descriptor,descriptorlength) count=count+1; importancefactors(count)=responsefunctions.impfac(i); end end -if count==0, +if count==0 error('plot_importancefactors error message: could not find to response functions with corresponding design variable'); end %log? -if exist(options,'log'), +if exist(options,'log') logvalue=getfieldvalue(options,'log'); importancefactors=log(importancefactors)/log(logvalue); end @@ -72,7 +72,7 @@ function plot_importancefactors(md,options,width,ii) subplot(width,width,ii); %ok, plot nodeimportance now. -if is2d, +if is2d A=elements(:,1); B=elements(:,2); C=elements(:,3); patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', nodeimportance,'FaceColor','interp','EdgeColor',edgecolor); else diff --git a/src/m/plot/plot_landsat.m b/src/m/plot/plot_landsat.m index 147f6fabd..50c3255be 100644 --- a/src/m/plot/plot_landsat.m +++ b/src/m/plot/plot_landsat.m @@ -11,7 +11,7 @@ function plot_landsat(md,data,options,plotlines,plotcols,i), [data datatype]=processdata(md,data,options); %check is2d - if ~is2d, + if ~is2d error('buildgridded error message: gridded not supported for 3d meshes, project on a layer'); end @@ -30,7 +30,7 @@ function plot_landsat(md,data,options,plotlines,plotcols,i), ny = numel(ym); if md.mesh.epsg == 3031 & (isempty(md.radaroverlay.pwr) | isempty(md.radaroverlay.x) | isempty(md.radaroverlay.y) | length(size(md.radaroverlay.pwr)) < 3), % Antarctica region {{{ - if highres, + if highres disp(' LIMA with geotiff'), % {{{ disp('WARNING : this image shoud be collected with geocoded tif file'); % find merged mosaic landsat image {{{ @@ -65,7 +65,7 @@ function plot_landsat(md,data,options,plotlines,plotcols,i), if exist(limapath{ii}), pos(ii) = 1; end end - if sum(pos) == 0, + if sum(pos) == 0 fprintf('download website : https://lima.usgs.gov/fullcontinent.php\n'); error('Landsat image at Antarctic region should be downloaded at above website'); end @@ -119,7 +119,7 @@ function plot_landsat(md,data,options,plotlines,plotcols,i), final = double(pwr)/double(max(md.radaroverlay.pwr(:))); %rescale between 0 and 1 %Prepare grid - if size(md.radaroverlay.x,1)==1 | size(md.radaroverlay.x,2)==1, + if size(md.radaroverlay.x,1)==1 | size(md.radaroverlay.x,2)==1 data_grid=InterpFromMeshToGrid(elements2d,x2d/getfieldvalue(options,'unit',1),y2d/getfieldvalue(options,'unit',1),data,xm,ym,NaN); %data_grid=InterpFromMeshToGrid(md.mesh.elements,md.mesh.x/getfieldvalue(options,'unit',1),md.mesh.y/getfieldvalue(options,'unit',1),data,x_m,y_m,NaN); else @@ -131,7 +131,7 @@ function plot_landsat(md,data,options,plotlines,plotcols,i), end data_nan=isnan(data_grid); - if exist(options,'caxis'), + if exist(options,'caxis') caxis_opt=getfieldvalue(options,'caxis'); data_grid(find(data_gridcaxis_opt(2)))=caxis_opt(2); @@ -156,13 +156,13 @@ function plot_landsat(md,data,options,plotlines,plotcols,i), h=imagesc(xm*getfieldvalue(options,'unit',1),ym*getfieldvalue(options,'unit',1),final); %last step: mesh gridded? - if exist(options,'edgecolor'), + if exist(options,'edgecolor') A=elements(:,1); B=elements(:,2); C=elements(:,3); patch('Faces',[A B C],'Vertices', [x y z],'FaceVertexCData',data_grid(1)*ones(size(x)),'FaceColor','none','EdgeColor',getfieldvalue(options,'edgecolor')); end %Apply options - if ~isnan(data_min), + if ~isnan(data_min) options=changefieldvalue(options,'caxis',[data_min data_max]); % force caxis so that the colorbar is ready end options=addfielddefault(options,'axis','xy equal off'); % default axis diff --git a/src/m/plot/plot_manager.m b/src/m/plot/plot_manager.m index 3e19fe46c..db3a85d41 100755 --- a/src/m/plot/plot_manager.m +++ b/src/m/plot/plot_manager.m @@ -13,7 +13,7 @@ function plot_manager(md,options,subplotwidth,nlines,ncols,i) data=getfieldvalue(options,'data'); %figure out if this is a special plot -if ischar(data), +if ischar(data) switch data, case 'boundaries', plot_boundaries(md,options,subplotwidth,i); @@ -70,7 +70,7 @@ function plot_manager(md,options,subplotwidth,nlines,ncols,i) plot_mesh(md,options,nlines,ncols,i); return; case 'none', - if ~exist(options,'overlay'), + if ~exist(options,'overlay') plot_none(md,options,nlines,ncols,i); return; end @@ -136,7 +136,7 @@ function plot_manager(md,options,subplotwidth,nlines,ncols,i) if isfield(md.results,'TransientSolution') && isfield(md.results.TransientSolution,data) plot_transient_movie(md,options,subplotwidth,i); return - elseif ismember(data,properties('model')), + elseif ismember(data,properties('model')) data=eval(['md.' data ';']); else error('plot error message: data provided not supported yet. Type plotdoc for help'); @@ -145,25 +145,25 @@ function plot_manager(md,options,subplotwidth,nlines,ncols,i) end %Figure out if this is a semi-transparent plot. -if exist(options,'overlay'), +if exist(options,'overlay') plot_overlay(md,data,options,nlines,ncols,i); return; end %Figure out if this is a Google Maps plot. -if exist(options,'googlemaps'), +if exist(options,'googlemaps') plot_googlemaps(md,data,options,nlines,ncols,i); return; end %Figure out if this is a landsat plot. -if getfieldvalue(options,'landsat',0), +if getfieldvalue(options,'landsat',0) plot_landsat(md,data,options,nlines,ncols,i); return; end %Figure out if this is a gridded plot. -if exist(options,'gridded'), +if exist(options,'gridded') plot_gridded(md,data,options,nlines,ncols,i); return; end @@ -201,9 +201,9 @@ function plot_manager(md,options,subplotwidth,nlines,ncols,i) plot_unit(x,y,z,elements,data2,is2d,isplanet,datatype,options); %apply all options -if datatype==3, +if datatype==3 options=changefieldvalue(options,'colorbar',2); - if exist(options,'contourlevels'), + if exist(options,'contourlevels') data2=data; end end @@ -211,8 +211,8 @@ function plot_manager(md,options,subplotwidth,nlines,ncols,i) applyoptions(md,data2,options); %do ground overlay on kml plot_unit? -if (strcmpi(getfieldvalue(options,'kmlgroundoverlay','off'),'on')), - if ((nlines*ncols~=1) | (i~=1)), +if (strcmpi(getfieldvalue(options,'kmlgroundoverlay','off'),'on')) + if ((nlines*ncols~=1) | (i~=1)) error('cannot kmlgroundoverlay on multi-plots'); end diff --git a/src/m/plot/plot_none.m b/src/m/plot/plot_none.m index f9c08df74..cd65f7730 100644 --- a/src/m/plot/plot_none.m +++ b/src/m/plot/plot_none.m @@ -11,7 +11,7 @@ function plot_none(md,options,nlines,ncols,i) options=addfielddefault(options,'map','none'); options=addfielddefault(options,'axis','equal'); -if exist(options,'overlay'), +if exist(options,'overlay') plot_overlay(md,'none',options,nlines,ncols,i); return; end diff --git a/src/m/plot/plot_overlay.m b/src/m/plot/plot_overlay.m index adfffb237..637bbcbcd 100644 --- a/src/m/plot/plot_overlay.m +++ b/src/m/plot/plot_overlay.m @@ -8,7 +8,7 @@ function plot_overlay(md,data,options,plotlines,plotcols,i) %process mesh and data [x y z elements is2d isplanet]=processmesh(md,[],options); -if strcmpi(data,'none'), +if strcmpi(data,'none') radaronly=1; data=NaN*ones(md.mesh.numberofvertices,1); datatype=1; @@ -24,15 +24,15 @@ function plot_overlay(md,data,options,plotlines,plotcols,i) end %check is2d -if ~is2d, +if ~is2d error('buildoverlay error message: overlay not supported for 3d meshes, project on a layer'); end -if datatype==3, +if datatype==3 error('buildoverlay error message: overlay not supported for quiver plots'); end %radar power -if ~any(isnan(md.radaroverlay.x)) & ~any(isnan(md.radaroverlay.y)) & ~any(isnan(md.radaroverlay.pwr)), +if ~any(isnan(md.radaroverlay.x)) & ~any(isnan(md.radaroverlay.y)) & ~any(isnan(md.radaroverlay.pwr)) disp('plot_overlay info: the radar image held by the model is being used'); xlim=[min(md.radaroverlay.x) max(md.radaroverlay.x)]; ylim=[min(md.radaroverlay.y) max(md.radaroverlay.y)]; @@ -54,9 +54,9 @@ function plot_overlay(md,data,options,plotlines,plotcols,i) radar = md.radaroverlay.pwr; if ~radaronly - if size(radar,3)>1, + if size(radar,3)>1 disp('WARNING: color image converted to greyscale intensity image'); - if strcmp(class(radar),'uint8'), + if strcmp(class(radar),'uint8') radar=double(sum(radar,3))/(255*3); else radar=sum(radar,3)/3; @@ -77,7 +77,7 @@ function plot_overlay(md,data,options,plotlines,plotcols,i) disp('Interpolating data on grid...'); x_m = md.radaroverlay.x; y_m = md.radaroverlay.y; -if radaronly, +if radaronly data_grid=NaN(size(radar)); else data_grid=InterpFromMeshToGrid(elements,x/getfieldvalue(options,'unit',1),y/getfieldvalue(options,'unit',1),data,x_m,y_m,NaN); @@ -90,11 +90,11 @@ function plot_overlay(md,data,options,plotlines,plotcols,i) %Process data_grid (For processing, it is better not to have nan) pos=find(isinf(data_grid)); -if ~isempty(pos), +if ~isempty(pos) disp('Warning: removing Infs from vector (probably log(0)?)'); data_grid(pos)=NaN; end -if exist(options,'caxis'), +if exist(options,'caxis') caxis_opt=getfieldvalue(options,'caxis'); data_grid(find(data_gridcaxis_opt(2)))=caxis_opt(2); @@ -110,12 +110,12 @@ function plot_overlay(md,data,options,plotlines,plotcols,i) %Special colormaps that require hsv treatment colorm=getfieldvalue(options,'colormap','parula'); if strcmpi(colorm,'Rignot') | strcmpi(colorm,'Seroussi') | strcmpi(colorm,'redblue') - if strcmpi(colorm,'Rignot'), + if strcmpi(colorm,'Rignot') transparency=getfieldvalue(options,'alpha',1); h=(data_grid-data_min)/(data_max-data_min+eps); if radaronly, h(:)=0; end s=max(min((0.1+h).^(1/transparency),1),0); - elseif strcmpi(colorm,'Seroussi'), + elseif strcmpi(colorm,'Seroussi') transparency=getfieldvalue(options,'alpha',1); h=1-(data_grid-data_min)/(data_max-data_min+eps)*0.7; if radaronly, h(:)=0; end @@ -168,7 +168,7 @@ function plot_overlay(md,data,options,plotlines,plotcols,i) imagesc(x_m*getfieldvalue(options,'unit',1),y_m*getfieldvalue(options,'unit',1),image_rgb);set(gca,'YDir','normal'); %last step: mesh overlay? -if exist(options,'edgecolor'), +if exist(options,'edgecolor') hold on A=elements(:,1); B=elements(:,2); C=elements(:,3); patch('Faces',[A B C],'Vertices', [x y z],'FaceVertexCData',zeros(size(x)),'FaceColor','none',... @@ -177,7 +177,7 @@ function plot_overlay(md,data,options,plotlines,plotcols,i) %Apply options, without colorbar and without grid options=changefieldvalue(options,'colormap',colorm); % We used an HSV colorbar -if ~isnan(data_min), +if ~isnan(data_min) options=changefieldvalue(options,'caxis',[data_min data_max]); % force caxis so that the colorbar is ready end options=addfielddefault(options,'xlim',xlim); % default xlim diff --git a/src/m/plot/plot_penalties.m b/src/m/plot/plot_penalties.m index ff70d1239..67c6f0794 100644 --- a/src/m/plot/plot_penalties.m +++ b/src/m/plot/plot_penalties.m @@ -13,16 +13,16 @@ function plot_penalties(md,options,width,i) subplot(width,width,i); %units -if exist(options,'unit'), +if exist(options,'unit') unit=getfieldvalue(options,'unit'); x=x*unit; y=y*unit; z=z*unit; end -if dimension(md.mesh)~=3, +if dimension(md.mesh)~=3 error('no penalties to plot for ''2d'' model'); -elseif isempty(md.penalties), +elseif isempty(md.penalties) disp('no penalty applied in this model'); return; else @@ -35,7 +35,7 @@ function plot_penalties(md,options,width,i) patch( 'Faces', [C A D F],'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black'); hold on; - for (i=1:size(md.penalties,1)), + for (i=1:size(md.penalties,1)) P1=plot3(x(md.penalties(i,1)),y(md.penalties(i,1)),z(md.penalties(i,1)),'ro','MarkerSize',15,'MarkerFaceColor','r'); P2=plot3(x(md.penalties(i,:)),y(md.penalties(i,:)),z(md.penalties(i,:)),'bo-','LineWidth',2,'MarkerSize',8,'MarkerFaceColor','b'); end diff --git a/src/m/plot/plot_profile.m b/src/m/plot/plot_profile.m index c97d2a8bb..124feaa9a 100644 --- a/src/m/plot/plot_profile.m +++ b/src/m/plot/plot_profile.m @@ -18,20 +18,20 @@ function plot_profile(md,data,options,nlines,ncols,ii) %Get coordinates location=getfieldvalue(options,'profile'); -if ~isnumeric(location) | numel(location)~=2, +if ~isnumeric(location) | numel(location)~=2 error('location provided not supported (should be [x y])'); end xprof=location(1); yprof=location(2); %Loop over number of curves -for i=1:numcurves, +for i=1:numcurves %Process data [datai datatype]=processdata(md,data(:,i),options); %resolution[z,data_interp]=ProfileValues(md,datai,xprof,yprof,resolution); - if exist(options,'resolution'), + if exist(options,'resolution') resolution=getfieldvalue(options,'resolution'); else %Default resolution resolution=[100]; diff --git a/src/m/plot/plot_qmu_mass_flux_segments.m b/src/m/plot/plot_qmu_mass_flux_segments.m index 3b59358aa..02dbeb149 100644 --- a/src/m/plot/plot_qmu_mass_flux_segments.m +++ b/src/m/plot/plot_qmu_mass_flux_segments.m @@ -12,22 +12,22 @@ function plot_qmu_mass_flux_segments(md,options,nlines,ncols,i) allsegments=md.qmu.mass_flux_segments; -if dimension(md.mesh)==2, +if dimension(md.mesh)==2 %recover segments hold on - for i=1:length(allsegments), + for i=1:length(allsegments) segments=allsegments{i}; %plot semgnets - for j=1:length(segments), + for j=1:length(segments) plot([segments(j,1) segments(j,3)],[segments(j,2) segments(j,4)]); end text(segments(j,1),segments(j,2),['Profile #' num2str(i)]); %plot normals - for j=1:length(segments), + for j=1:length(segments) xstart=mean([segments(j,1) segments(j,3)]); ystart=mean([segments(j,2) segments(j,4)]); length1=sqrt((segments(j,1)-segments(j,3)).^2 + (segments(j,2)-segments(j,4)).^2); diff --git a/src/m/plot/plot_qmumean.m b/src/m/plot/plot_qmumean.m index 54cc4400a..12cf8c8b7 100644 --- a/src/m/plot/plot_qmumean.m +++ b/src/m/plot/plot_qmumean.m @@ -16,9 +16,9 @@ function plot_qmumean(md,options,nlines,ncols,i) [x y z elements is2d isplanet]=processmesh(md,[],options); %find response function -if exist(options,'qmudata'), +if exist(options,'qmudata') descriptor=getfieldvalue(options,'qmudata'); - if ~ischar(descriptor), + if ~ischar(descriptor) error('plot_qmumean error message: descriptor should be a string'); end else @@ -30,11 +30,11 @@ function plot_qmumean(md,options,nlines,ncols,i) responses=zeros(md.qmu.numberofpartitions,1); count=1; -for i=1:length(allresponses), +for i=1:length(allresponses) d=allresponses(i).descriptor; - if strncmpi(d,'scaled_',7), + if strncmpi(d,'scaled_',7) d=d(8:end); - if strncmpi(d,descriptor,length(descriptor)), + if strncmpi(d,descriptor,length(descriptor)) responses(count)=allresponses(i).mean; count=count+1; end @@ -42,7 +42,7 @@ function plot_qmumean(md,options,nlines,ncols,i) end %log? -if exist(options,'log'), +if exist(options,'log') responses=log(responses)/log(getfieldvalue(options,'log')); end diff --git a/src/m/plot/plot_qmustddev.m b/src/m/plot/plot_qmustddev.m index fa496b6af..a5a15fc74 100644 --- a/src/m/plot/plot_qmustddev.m +++ b/src/m/plot/plot_qmustddev.m @@ -16,9 +16,9 @@ function plot_qmustddev(md,options,nlines,ncols,i) [x y z elements is2d isplanet]=processmesh(md,[],options); %find response function -if exist(options,'qmudata'), +if exist(options,'qmudata') descriptor=getfieldvalue(options,'qmudata'); - if ~ischar(descriptor), + if ~ischar(descriptor) error('plot_qmustddev error message: descriptor should be a string'); end else @@ -30,11 +30,11 @@ function plot_qmustddev(md,options,nlines,ncols,i) responses=zeros(md.qmu.numberofpartitions,1); count=1; -for i=1:length(allresponses), +for i=1:length(allresponses) d=allresponses(i).descriptor; - if strncmpi(d,'scaled_',7), + if strncmpi(d,'scaled_',7) d=d(8:end); - if strncmpi(d,descriptor,length(descriptor)), + if strncmpi(d,descriptor,length(descriptor)) responses(count)=allresponses(i).stddev/allresponses(i).mean*100; count=count+1; end @@ -42,7 +42,7 @@ function plot_qmustddev(md,options,nlines,ncols,i) end %log? -if exist(options,'log'), +if exist(options,'log') responses=log(responses)/log(getfieldvalue(options,'log')); end diff --git a/src/m/plot/plot_quiver.m b/src/m/plot/plot_quiver.m index 378a72961..51d9447a8 100644 --- a/src/m/plot/plot_quiver.m +++ b/src/m/plot/plot_quiver.m @@ -17,7 +17,7 @@ function plot_quiver(x,y,u,v,options), h=[]; for i=1:quivers.numcolors pos=find(quivers.colorind==i); - if ~isempty(pos), + if ~isempty(pos) hprime=quiver(quivers.x(pos),quivers.y(pos),quivers.u(pos),quivers.v(pos),... 'Color',palette(i,:),'ShowArrowHead','on','AutoScale','off'); h=[h;hprime]; diff --git a/src/m/plot/plot_quiver3.m b/src/m/plot/plot_quiver3.m index ead2a7a41..baba3aeef 100644 --- a/src/m/plot/plot_quiver3.m +++ b/src/m/plot/plot_quiver3.m @@ -24,8 +24,8 @@ function plot_quiver3(x,y,z,u,v,w,options), %number of colors? colorlevels=getfieldvalue(options,'colorlevels',NaN); -if isnumeric(colorlevels), - if isnan(colorlevels), +if isnumeric(colorlevels) + if isnan(colorlevels) numcolors=30; else numcolors=colorlevels; @@ -46,7 +46,7 @@ function plot_quiver3(x,y,z,u,v,w,options), if numcolors==2; %blue and red c=[0 0 1;1 0 0]; -elseif numcolors==3, +elseif numcolors==3 %blue yellow and red c=[0 0 1;1 1 0;1 0 0]; else @@ -55,7 +55,7 @@ function plot_quiver3(x,y,z,u,v,w,options), end %Scale data -if strcmpi(getfieldvalue(options,'autoscale','on'),'off'), +if strcmpi(getfieldvalue(options,'autoscale','on'),'off') delta=((min(x)-max(x))^2+(min(y)-max(y))^2)/numel(x); u=scalingfactor*sqrt(delta)*u./Norm; v=scalingfactor*sqrt(delta)*v./Norm; @@ -75,19 +75,19 @@ function plot_quiver3(x,y,z,u,v,w,options), end %take care of colorbar -if ~strcmpi(getfieldvalue(options,'colorbar','on'),'off'), +if ~strcmpi(getfieldvalue(options,'colorbar','on'),'off') %build ticks hcb=colorbar('peer',gca,'location','EastOutside'); ticklabel=cell(1,length(levels)); - for i=1:length(levels), + for i=1:length(levels) ticklabel{i}=num2str(round_ice(levels(i),3)); end tickpos=1:numcolors+1; %remove ticks if to many have been created proportion=round(length(levels)/10); - if proportion>1, + if proportion>1 ticklabel=ticklabel(1:proportion:end); tickpos=tickpos(1:proportion:end); end @@ -95,7 +95,7 @@ function plot_quiver3(x,y,z,u,v,w,options), %draw colorbar set(hcb,'YTickLabel',ticklabel,'YTick',tickpos); %position - if exist(options,'colorbarpos'), + if exist(options,'colorbarpos') set(hcb,'Position',getfieldvalue(options,'colorbarpos')); end %fontsize diff --git a/src/m/plot/plot_referential.m b/src/m/plot/plot_referential.m index 6df5a6e8d..4bb8c27a9 100644 --- a/src/m/plot/plot_referential.m +++ b/src/m/plot/plot_referential.m @@ -27,7 +27,7 @@ function plot_referential(md,options,width,i,data) Yhat=cross(Zhat,Xhat); -if dimension(md.mesh)==2, +if dimension(md.mesh)==2 %plot mesh A=elements(:,1); B=elements(:,2); C=elements(:,3); diff --git a/src/m/plot/plot_riftfraction.m b/src/m/plot/plot_riftfraction.m index fa73e0a7d..c450191bd 100644 --- a/src/m/plot/plot_riftfraction.m +++ b/src/m/plot/plot_riftfraction.m @@ -7,7 +7,7 @@ function plot_riftfraction(md,options,nlines,ncols,index) % See also: PLOTMODEL %check that there is something in riftproperties -if isnan(md.rifts.riftstruct.riftproperties), +if isnan(md.rifts.riftstruct.riftproperties) error('plot_riftfraction error message: field riftproperies is empty, run the model first') end @@ -18,7 +18,7 @@ function plot_riftfraction(md,options,nlines,ncols,index) hold on %plot mesh boundaries -for i=1:size(md.mesh.segments,1), +for i=1:size(md.mesh.segments,1) h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k.-'); end @@ -26,13 +26,13 @@ function plot_riftfraction(md,options,nlines,ncols,index) fractions=zeros(md.mesh.numberofvertices,1); %complete the tips. -for i=1:length(md.rifts.riftstruct), +for i=1:length(md.rifts.riftstruct) tips=md.rifts.riftstruct(i).tips; fractions(tips)=1; end hold on; -for i=1:length(md.rifts.riftstruct), +for i=1:length(md.rifts.riftstruct) segments=md.rifts.riftstruct(i).segments(:,1:2)'; xc=x(segments(:)); yc=y(segments(:)); diff --git a/src/m/plot/plot_riftnumbering.m b/src/m/plot/plot_riftnumbering.m index 1ee8945e2..3c70f2e50 100644 --- a/src/m/plot/plot_riftnumbering.m +++ b/src/m/plot/plot_riftnumbering.m @@ -14,28 +14,28 @@ function plot_riftnumbering(md,options,nlines,ncols,index) hold on %plot mesh boundaries -for i=1:size(md.mesh.segments,1), +for i=1:size(md.mesh.segments,1) plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k.-'); end isp1=0; isp2=0; -if isstruct(md.rifts.riftstruct), +if isstruct(md.rifts.riftstruct) %plot mesh boundaries - for i=1:size(md.mesh.segments,1), + for i=1:size(md.mesh.segments,1) h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'b-'); end - for i=1:size(md.rifts.riftstruct,1), + for i=1:size(md.rifts.riftstruct,1) penaltypairs=md.rifts.riftstruct(i).penaltypairs; segments=md.rifts.riftstruct(i).segments; - for j=1:size(segments,1), + for j=1:size(segments,1) plot(x(segments(j,1:2)),y(segments(j,1:2)),'b-'); end normal=zeros(2,1); - for j=1:size(penaltypairs,1), + for j=1:size(penaltypairs,1) normal(1)=penaltypairs(j,5); normal(2)=penaltypairs(j,6); @@ -60,7 +60,7 @@ function plot_riftnumbering(md,options,nlines,ncols,index) h2=plot(x(md.rifts.riftstruct(i).tips(1)),y(md.rifts.riftstruct(i).tips(1)),'g*'); plot(x(md.rifts.riftstruct(i).tips(2)),y(md.rifts.riftstruct(i).tips(2)),'g*'); end - if strcmpi(getfieldvalue(options,'legend','on'),'on'), + if strcmpi(getfieldvalue(options,'legend','on'),'on') if isp1 & isp2 l=legend([h1,h2,p1,p2],'mesh boundaries','crack tips','faults','rifts'); elseif isp1 @@ -77,10 +77,10 @@ function plot_riftnumbering(md,options,nlines,ncols,index) end %Now, plot rift vertices numbers. -for i=1:size(md.rifts.riftstruct,1), +for i=1:size(md.rifts.riftstruct,1) penaltypairs=md.rifts.riftstruct(i).penaltypairs; - for j=1:size(penaltypairs,1), + for j=1:size(penaltypairs,1) node=penaltypairs(j,1); t=text(x(node),y(node),[num2str(i) '.' num2str(j)]); set(t,'FontSize',fontsize); diff --git a/src/m/plot/plot_riftpenetration.m b/src/m/plot/plot_riftpenetration.m index 0ed08598e..7ba68b755 100644 --- a/src/m/plot/plot_riftpenetration.m +++ b/src/m/plot/plot_riftpenetration.m @@ -13,28 +13,28 @@ function plot_rifpenetration(md,options,nlines,ncols,index) hold on %plot mesh boundaries -for i=1:size(md.mesh.segments,1), +for i=1:size(md.mesh.segments,1) plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k-'); end isp1=0; isp2=0; -if isstruct(md.rifts.riftstruct), +if isstruct(md.rifts.riftstruct) %plot mesh boundaries - for i=1:size(md.mesh.segments,1), + for i=1:size(md.mesh.segments,1) h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'b-'); end - for i=1:size(md.rifts.riftstruct,1), + for i=1:size(md.rifts.riftstruct,1) penaltypairs=md.rifts.riftstruct(i).penaltypairs; segments=md.rifts.riftstruct(i).segments; - for j=1:size(segments,1), + for j=1:size(segments,1) plot(x(segments(j,1:2)),y(segments(j,1:2)),'b-'); end normal=zeros(2,1); - for j=1:size(penaltypairs,1), + for j=1:size(penaltypairs,1) normal(1)=penaltypairs(j,5); normal(2)=penaltypairs(j,6); @@ -59,7 +59,7 @@ function plot_rifpenetration(md,options,nlines,ncols,index) h2=plot(x(md.rifts.riftstruct(i).tips(1)),y(md.rifts.riftstruct(i).tips(1)),'g*'); plot(x(md.rifts.riftstruct(i).tips(2)),y(md.rifts.riftstruct(i).tips(2)),'g*'); end - if strcmpi(getfieldvalue(options,'legend','on'),'on'), + if strcmpi(getfieldvalue(options,'legend','on'),'on') if isp1 & isp2 l=legend([h1,h2,p1,p2],'mesh boundaries','crack tips','faults','rifts'); elseif isp1 diff --git a/src/m/plot/plot_riftrelvel.m b/src/m/plot/plot_riftrelvel.m index 0c6ea54a1..47a706609 100644 --- a/src/m/plot/plot_riftrelvel.m +++ b/src/m/plot/plot_riftrelvel.m @@ -7,10 +7,10 @@ function plot_riftrelvel(md,options,nlines,ncols,index) % See also: PLOTMODEL %some checks -if (length(md.initialization.vx)~=md.mesh.numberofvertices | length(md.initialization.vy)~=md.mesh.numberofvertices), +if (length(md.initialization.vx)~=md.mesh.numberofvertices | length(md.initialization.vy)~=md.mesh.numberofvertices) error('plot_riftvel error message: vx and vy do not have the right size'), end -if ~isstruct(md.rifts.riftstruct), +if ~isstruct(md.rifts.riftstruct) error('plot error message: no rifts available!'); end options=addfielddefault(options,'scaling',2); @@ -25,7 +25,7 @@ function plot_riftrelvel(md,options,nlines,ncols,index) %set as NaN all velocities not on rifts u=NaN*ones(md.mesh.numberofvertices,1); v=NaN*ones(md.mesh.numberofvertices,1); -for i=1:size(md.rifts.riftstruct,1), +for i=1:size(md.rifts.riftstruct,1) penaltypairs=md.rifts.riftstruct(i).penaltypairs(:,[1 2]); u(md.rifts.riftstruct(i).penaltypairs(:,1))=vx(penaltypairs(:,1))-vx(penaltypairs(:,2)); v(md.rifts.riftstruct(i).penaltypairs(:,1))=vy(penaltypairs(:,1))-vy(penaltypairs(:,2)); @@ -56,21 +56,21 @@ function plot_riftrelvel(md,options,nlines,ncols,index) isp2=0; %plot mesh boundaries -for i=1:size(md.mesh.segments,1), +for i=1:size(md.mesh.segments,1) h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'b-'); end -for i=1:size(md.rifts.riftstruct,1), +for i=1:size(md.rifts.riftstruct,1) %get nodes on rift penaltypairs=md.rifts.riftstruct(i).penaltypairs; segments=md.rifts.riftstruct(i).segments; - for j=1:size(segments,1), + for j=1:size(segments,1) plot(x(segments(j,1:2)),y(segments(j,1:2)),'k-'); end normal=zeros(2,1); - for j=1:size(penaltypairs,1), + for j=1:size(penaltypairs,1) normal(1)=penaltypairs(j,5); normal(2)=penaltypairs(j,6); @@ -95,7 +95,7 @@ function plot_riftrelvel(md,options,nlines,ncols,index) faulttitle=getfieldvalue(options','faulttitle','faults'); rifttitle=getfieldvalue(options','rifttitle','rifts'); %legend -if strcmpi(getfieldvalue(options,'legend','on'),'on'), +if strcmpi(getfieldvalue(options,'legend','on'),'on') if isp1 & isp2 l=legend([h1,h2,p1,p2],'mesh boundaries','crack tips',faulttitle,rifttitle); elseif isp1 diff --git a/src/m/plot/plot_rifts.m b/src/m/plot/plot_rifts.m index e1e0ac485..bafe078b4 100644 --- a/src/m/plot/plot_rifts.m +++ b/src/m/plot/plot_rifts.m @@ -14,41 +14,41 @@ function plot_rifts(md,options,nlines,ncols,index) %offset to separate rift flanks. offset=getfieldvalue(options,'offset',500); -if isstruct(md.rifts.riftstruct), +if isstruct(md.rifts.riftstruct) - for i=1:size(md.rifts.riftstruct,1), + for i=1:size(md.rifts.riftstruct,1) penaltypairs=md.rifts.riftstruct(i).penaltypairs; normal=zeros(2,1); - for j=1:size(penaltypairs,1), + for j=1:size(penaltypairs,1) normal(1)=penaltypairs(j,5); normal(2)=penaltypairs(j,6); x(penaltypairs(j,1))=x(penaltypairs(j,1))-normal(1)*offset; y(penaltypairs(j,1))=y(penaltypairs(j,1))-normal(2)*offset; end - if length(md.rifts.riftstruct(i).tips)==3, + if length(md.rifts.riftstruct(i).tips)==3 tip=md.rifts.riftstruct(i).tips(3); %who is tip connected to? - if isconnected(md.mesh.elements,penaltypairs(1,1),tip), + if isconnected(md.mesh.elements,penaltypairs(1,1),tip) normal(1)=penaltypairs(1,5); normal(2)=penaltypairs(1,6); x(tip)=x(tip)-normal(1)*offset; y(tip)=y(tip)-normal(2)*offset; end - if isconnected(md.mesh.elements,penaltypairs(1,2),tip), + if isconnected(md.mesh.elements,penaltypairs(1,2),tip) normal(1)=penaltypairs(1,5); normal(2)=penaltypairs(1,6); x(tip)=x(tip)+normal(1)*offset; y(tip)=y(tip)+normal(2)*offset; end - if isconnected(md.mesh.elements,penaltypairs(end,1),tip), + if isconnected(md.mesh.elements,penaltypairs(end,1),tip) normal(1)=penaltypairs(end,5); normal(2)=penaltypairs(end,6); x(tip)=x(tip)-normal(1)*offset; y(tip)=y(tip)-normal(2)*offset; end - if isconnected(md.mesh.elements,penaltypairs(end,2),tip), + if isconnected(md.mesh.elements,penaltypairs(end,2),tip) normal(1)=penaltypairs(end,5); normal(2)=penaltypairs(end,6); x(tip)=x(tip)+normal(1)*offset; @@ -62,7 +62,7 @@ function plot_rifts(md,options,nlines,ncols,index) if is2d A=elements(:,1); B=elements(:,2); C=elements(:,3); patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black'); -elseif isplanet, +elseif isplanet A=elements(:,1); B=elements(:,2); C=elements(:,3); patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black'); else diff --git a/src/m/plot/plot_riftvel.m b/src/m/plot/plot_riftvel.m index 237a53341..7d230af7c 100644 --- a/src/m/plot/plot_riftvel.m +++ b/src/m/plot/plot_riftvel.m @@ -7,10 +7,10 @@ function plot_riftvel(md,options,nlines,ncols,index) % See also: PLOTMODEL %some checks -if (length(md.initialization.vx)~=md.mesh.numberofvertices | length(md.initialization.vy)~=md.mesh.numberofvertices), +if (length(md.initialization.vx)~=md.mesh.numberofvertices | length(md.initialization.vy)~=md.mesh.numberofvertices) error('plot_riftvel error message: vx and vy do not have the right size'), end -if ~isstruct(md.rifts.riftstruct), +if ~isstruct(md.rifts.riftstruct) error('plot error message: no rifts available!'); end options=addfielddefault(options,'scaling',2); @@ -18,7 +18,7 @@ function plot_riftvel(md,options,nlines,ncols,index) %set as NaN all velocities not on rifts u=NaN*ones(md.mesh.numberofvertices,1); v=NaN*ones(md.mesh.numberofvertices,1); -for i=1:size(md.rifts.riftstruct,1), +for i=1:size(md.rifts.riftstruct,1) penaltypairs=md.rifts.riftstruct(i).penaltypairs(:,[1 2]); u(penaltypairs(:))=md.initialization.vx(penaltypairs(:)); v(penaltypairs(:))=md.initialization.vy(penaltypairs(:)); @@ -34,7 +34,7 @@ function plot_riftvel(md,options,nlines,ncols,index) hold on %plot mesh boundaries -for i=1:size(md.mesh.segments,1), +for i=1:size(md.mesh.segments,1) plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'k.-'); end @@ -52,21 +52,21 @@ function plot_riftvel(md,options,nlines,ncols,index) isp2=0; %plot mesh boundaries -for i=1:size(md.mesh.segments,1), +for i=1:size(md.mesh.segments,1) h1=plot(x(md.mesh.segments(i,1:2)),y(md.mesh.segments(i,1:2)),'b-'); end -for i=1:size(md.rifts.riftstruct,1), +for i=1:size(md.rifts.riftstruct,1) %get nodes on rift penaltypairs=md.rifts.riftstruct(i).penaltypairs; segments=md.rifts.riftstruct(i).segments; - for j=1:size(segments,1), + for j=1:size(segments,1) plot(x(segments(j,1:2)),y(segments(j,1:2)),'b-'); end normal=zeros(2,1); - for j=1:size(penaltypairs,1), + for j=1:size(penaltypairs,1) normal(1)=penaltypairs(j,5); normal(2)=penaltypairs(j,6); diff --git a/src/m/plot/plot_sarpwr.m b/src/m/plot/plot_sarpwr.m index 4d3d654dc..b7b1495a2 100644 --- a/src/m/plot/plot_sarpwr.m +++ b/src/m/plot/plot_sarpwr.m @@ -10,7 +10,7 @@ function plot_sarpwr(md,options,width,i) subplot(width,width,i); %units -if exist(options,'unit'), +if exist(options,'unit') unit=getfieldvalue(options,'unit'); md.mesh.x=md.mesh.x*unit; md.mesh.y=md.mesh.y*unit; diff --git a/src/m/plot/plot_scatter.m b/src/m/plot/plot_scatter.m index 0f21eb3a7..f9cb5b2a8 100644 --- a/src/m/plot/plot_scatter.m +++ b/src/m/plot/plot_scatter.m @@ -12,18 +12,18 @@ function plot_scatter(x,y,level,varargin), % 'Cutoff' : cut the line if the distance between 2 points is % greater than Cutoff (default is 1000) -if nargin == 4, +if nargin == 4 options = varargin{1}; else options=pairoptions(varargin{:}); end %check input -if numel(x)~=numel(y) | numel(x)~=numel(level), +if numel(x)~=numel(y) | numel(x)~=numel(level) error('x, y and data should have the same size'); end -if exist(options,'subset'), +if exist(options,'subset') pos=getfieldvalue(options,'subset'); x=x(pos); y=y(pos); @@ -44,16 +44,16 @@ function plot_scatter(x,y,level,varargin), %Max=1300; %OK, should we create a new colorbar for the occasion? -if isempty(findobj(gcf,'tag','TMW_COLORBAR')) && isempty(findobj(gcf,'Type','Colorbar')), +if isempty(findobj(gcf,'tag','TMW_COLORBAR')) && isempty(findobj(gcf,'Type','Colorbar')) alreadyplot=false; else alreadyplot=true; end %generate levels -if (alreadyplot), +if (alreadyplot) phch = get(findall(gcf,'type','image','tag','TMW_COLORBAR'),{'parent'}); - if ~isempty(phch), + if ~isempty(phch) h = phch{1}; ylim=get(h,'YLim'); else @@ -61,14 +61,10 @@ function plot_scatter(x,y,level,varargin), h = findobj(gcf,'Type','Colorbar'); ylim = h.Limits; end - palette=turbo();%colormap(); + %palette=turbo();%colormap(); + palette=colormap(); numcolors=size(palette,1); levels=round_ice(linspace(ylim(1),ylim(2),numcolors+1),2); -else - palette=getcolormap(options); - colormap(palette); - numcolors=size(palette,1); - levels=round_ice(linspace(Min,Max,numcolors+1),3); end colorind=ones(Siz,1); @@ -81,7 +77,7 @@ function plot_scatter(x,y,level,varargin), %loop over the number of colors hold on hp=[]; -if ~exist(options,'line'), +if ~exist(options,'line') for i=1:numcolors pos=find(colorind==i); % hprime=plot3(x(pos),y(pos),ones(size(x(pos))),... @@ -98,7 +94,7 @@ function plot_scatter(x,y,level,varargin), for j=1:numcolors; pos=find(colorind==j); if(~isempty(pos) & pos(1)==1), pos(1)=[]; end - if ~isempty(pos), + if ~isempty(pos) tempx = [x(pos-1) x(pos) NaN(size(pos))]'; tempy = [y(pos-1) y(pos) NaN(size(pos))]'; line(tempx(1:end-1),tempy(1:end-1),'color',palette(j,:),'linewidth',getfieldvalue(options,'LineWidth',2)); @@ -109,7 +105,7 @@ function plot_scatter(x,y,level,varargin), %Stop MATLAB's default interactivity disableDefaultInteractivity(gca); -if ~alreadyplot, +if ~alreadyplot % format the colorbar h = colorbar; caxis([min(levels) max(levels)]); diff --git a/src/m/plot/plot_section.m b/src/m/plot/plot_section.m index ae9f3e722..e65cf6fdd 100644 --- a/src/m/plot/plot_section.m +++ b/src/m/plot/plot_section.m @@ -40,19 +40,19 @@ function plot_section(md,data,options,nlines,ncols,i) numprofiles=length(profiles); %Loop over number of profiles: -for profile_i=1:numprofiles, +for profile_i=1:numprofiles profile=profiles(profile_i); %Loop over number of curves - for i=1:numcurves, + for i=1:numcurves [datai datatype]=processdata(md3d,data(:,i),options); %resolution - if exist(options,'resolution'), + if exist(options,'resolution') resolution=getfieldvalue(options,'resolution'); else %Default resolution - if is2d, + if is2d resolution=[1000 1]; else resolution=[1000 10*md.mesh.numberoflayers]; @@ -63,14 +63,14 @@ function plot_section(md,data,options,nlines,ncols,i) %Compute section value [elements,x,y,z,s,data_s]=SectionValues(md,datai,profile,resolution); - if getfieldvalue(options,'sectionmean',0)==1, + if getfieldvalue(options,'sectionmean',0)==1 disp(['Mean value of data along section: ' num2str(mean(data_s))]) disp(['Median value of data along section: ' num2str(median(data_s))]) disp(['Standard deviation of data along section: ' num2str(std(data_s))]) end %units - if exist(options,'unit'), + if exist(options,'unit') unit=getfieldvalue(options,'unit'); x=x*unit; y=y*unit; @@ -79,7 +79,7 @@ function plot_section(md,data,options,nlines,ncols,i) end %2D - if is2d, + if is2d % %plot section value % hold on; % subplot(nlines,ncols,index1) diff --git a/src/m/plot/plot_segments.m b/src/m/plot/plot_segments.m index d90efbdf0..790c07322 100644 --- a/src/m/plot/plot_segments.m +++ b/src/m/plot/plot_segments.m @@ -13,7 +13,7 @@ function plot_segments(md,options,width,i,datai) [x y z elements is2d isplanet]=processmesh(md,[],options); segments=md.mesh.segments; -if dimension(md.mesh)==2, +if dimension(md.mesh)==2 %plot mesh A=elements(:,1); B=elements(:,2); C=elements(:,3); h1=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','none','EdgeColor','black'); @@ -24,7 +24,7 @@ function plot_segments(md,options,width,i,datai) A=elements(pos,1); B=elements(pos,2); C=elements(pos,3); h2=patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceVertexCData', [1 1 1],'FaceColor','green','EdgeColor','black'); - if strcmpi(getfieldvalue(options,'segmentnumbering','off'),'on'), + if strcmpi(getfieldvalue(options,'segmentnumbering','off'),'on') text(sum(x(segments(:,1:2)),2)/2,sum(y(segments(:,1:2)),2)/2,sum(z(segments(:,1:2)),2)/2+1,... num2str(md.mesh.segmentmarkers),... 'backgroundcolor',[0.8 0.9 0.8],'HorizontalAlignment','center','VerticalAlignment','middle'); diff --git a/src/m/plot/plot_streamlines.m b/src/m/plot/plot_streamlines.m index 7e4ca4e06..a830a406e 100644 --- a/src/m/plot/plot_streamlines.m +++ b/src/m/plot/plot_streamlines.m @@ -10,7 +10,7 @@ function plot_streamlines(md,options) [v datatype]=processdata(md,md.initialization.vy,options); %some checks -if ~is2d, +if ~is2d disp('plot_streamlines error: streamlines option not supported for 3d plots. Project on a layer') return end diff --git a/src/m/plot/plot_tensor.m b/src/m/plot/plot_tensor.m index 4ea256630..c00278322 100644 --- a/src/m/plot/plot_tensor.m +++ b/src/m/plot/plot_tensor.m @@ -15,24 +15,24 @@ function plot_tensor(md,options,width,i,type) %Figure out tensor type: %FIXME does not work anymore -if strncmpi(type,'strain',6), +if strncmpi(type,'strain',6) tensor=md.results.strainrate; -elseif strncmpi(type,'stress',6), +elseif strncmpi(type,'stress',6) tensor=md.results.stress; -elseif strncmpi(type,'deviatoricstress',16), +elseif strncmpi(type,'deviatoricstress',16) tensor=md.results.deviatoricstress; else error('plot_tensor error message: unsupported type of tensor'); end %Figure out type of plot being requested -if strncmpi(fliplr(type),fliplr('tensor'),6) | strcmpi(type,'strainrate') | strcmpi(type,'deviatoricstress') | strcmpi(type,'stress'), +if strncmpi(fliplr(type),fliplr('tensor'),6) | strcmpi(type,'strainrate') | strcmpi(type,'deviatoricstress') | strcmpi(type,'stress') plot_tensor_components(md,options,width,i,tensor,type,plot_options); return; -elseif strncmpi(fliplr(type),fliplr('principal'),9), +elseif strncmpi(fliplr(type),fliplr('principal'),9) plot_tensor_principal(md,options,width,i,tensor,type,plot_options); return; -elseif strncmpi(fliplr(type(1:end-1)),fliplr('principalaxis'),13), +elseif strncmpi(fliplr(type(1:end-1)),fliplr('principalaxis'),13) plot_tensor_principalaxis(md,options,width,i,tensor,type,plot_options); return; else diff --git a/src/m/plot/plot_tensor_components.m b/src/m/plot/plot_tensor_components.m index cf86a0187..cbfbfd6ea 100644 --- a/src/m/plot/plot_tensor_components.m +++ b/src/m/plot/plot_tensor_components.m @@ -33,7 +33,7 @@ function plot_tensor_components(md,options,width,i,tensor,type,plot_options) [tensor.zz datatype]=processdata(md,tensor.zz,options); end -if dimension(md.mesh)==2, +if dimension(md.mesh)==2 subplot(2*width,2*width,index1), plot_unit(x,y,z,elements,tensor.xx,is2d,isplanet,datatype,options) Apply_options_tensor(md,options,type,'xx') diff --git a/src/m/plot/plot_tensor_principal.m b/src/m/plot/plot_tensor_principal.m index 9168ec598..56d5c7629 100644 --- a/src/m/plot/plot_tensor_principal.m +++ b/src/m/plot/plot_tensor_principal.m @@ -43,7 +43,7 @@ function plot_tensor_principal(md,options,width,i,tensor,type,plot_options) [tensor.principalvalue3 datatype]=processdata(md,tensor.principalvalue3,options); end -if dimension(md.mesh)==2, +if dimension(md.mesh)==2 subplot(2*width,2*width,index3) plot_unit(x,y,z,elements,tensor.principalvalue1,is2d,isplanet,datatype,options) Apply_options_tensor(md,options,type,'principal value 1') diff --git a/src/m/plot/plot_tensor_principalaxis.m b/src/m/plot/plot_tensor_principalaxis.m index cba588cc2..327cf41ea 100644 --- a/src/m/plot/plot_tensor_principalaxis.m +++ b/src/m/plot/plot_tensor_principalaxis.m @@ -12,7 +12,7 @@ function plot_tensor_principalaxis(md,options,width,i,tensor,type,plot_options) %process data and model [x y z elements is2d isplanet]=processmesh(md,[],options); -if dimension(md.mesh)==2, +if dimension(md.mesh)==2 eval(['Vx=tensor.principalaxis' type(end) '(:,1); Vy=tensor.principalaxis' type(end) '(:,2);']) eval(['value=tensor.principalvalue' type(end) ';']); [Vx datatype]=processdata(md,Vx,options); @@ -27,12 +27,12 @@ function plot_tensor_principalaxis(md,options,width,i,tensor,type,plot_options) end %take the center of each element if ~isonnode -if datatype==1, +if datatype==1 x=mean(x(elements'))'; y=mean(y(elements'))'; z=mean(z(elements'))'; end %plot quivers -if dimension(md.mesh)==2, +if dimension(md.mesh)==2 %density if exist(options,'density') diff --git a/src/m/plot/plot_thermaltransient_results.m b/src/m/plot/plot_thermaltransient_results.m index 641e54493..6d94287da 100644 --- a/src/m/plot/plot_thermaltransient_results.m +++ b/src/m/plot/plot_thermaltransient_results.m @@ -7,7 +7,7 @@ function plot_thermaltransient_results(md,options,width,i) % See also: PLOTMODEL string='plot(md'; -for i=1:length(md.thermaltransient_results), +for i=1:length(md.thermaltransient_results) string=[string ',''data'',''thermaltransient_results(' num2str(i) ').temperature'',''view'',3,''title'',''Temperature at time ' num2str(md.thermaltransient_results(i).time) ' a''']; end string=[string ',''figure'',1,''colorbar#all'',''on'',''view'',3,''fontsize'',' num2str(options.fontsize) ',''fontweight'',' options.fontweight ');']; @@ -15,7 +15,7 @@ function plot_thermaltransient_results(md,options,width,i) clear string; string='plot(md'; -for i=2:length(md.thermaltransient_results), +for i=2:length(md.thermaltransient_results) string=[string ',''data'',md.thermaltransient_results(' num2str(i) ').temperature-md.thermaltransient_results(' num2str(i-1) ').temperature,''view'',3,''title'',''Delta temperature at time ' num2str(md.thermaltransient_results(i).time) ' a''']; end string=[string ',''figure'',2,''colorbar#all'',''on'',''fontsize'',' num2str(options.fontsize) ',''fontweight'',' options.fontweight ');']; diff --git a/src/m/plot/plot_transient_field.m b/src/m/plot/plot_transient_field.m index 9faf3525b..11cb79254 100644 --- a/src/m/plot/plot_transient_field.m +++ b/src/m/plot/plot_transient_field.m @@ -7,7 +7,7 @@ function plot_transient_field(md,options,width,i,data) % See also: PLOTMODEL %Check that they are transient results -if (~isfield(md.results,'TransientSolution')), +if (~isfield(md.results,'TransientSolution')) error('plot_transient_field error message: no transient results in the model'); end @@ -16,7 +16,7 @@ function plot_transient_field(md,options,width,i,data) maxiteration=size(transient,2); steps=getfieldvalue(options,'steps',1:1:maxiteration); -if max(steps)>maxiteration | min(steps)<1, +if max(steps)>maxiteration | min(steps)<1 error(['plot_transient_field error message: problem with the steps requested, must be an interger between 0 and ' num2str(maxiteration)]); end subplotwidth=ceil(sqrt(length(steps))); @@ -29,7 +29,7 @@ function plot_transient_field(md,options,width,i,data) [x y z elements is2d isplanet]=processmesh(md,[],options); %plot data for all steps -for i=1:length(steps), +for i=1:length(steps) %process data and change title if needed [data datatype]=processdata(md,transient(steps(i)).(field),options); diff --git a/src/m/plot/plot_transient_movie.m b/src/m/plot/plot_transient_movie.m index 2aed5bc4e..59aa7d4a2 100644 --- a/src/m/plot/plot_transient_movie.m +++ b/src/m/plot/plot_transient_movie.m @@ -9,7 +9,7 @@ function plot_transient_movie(md,options,width,i) subplot(width,width,i); %xlim - if exist(options,'transient_movie_field'), + if exist(options,'transient_movie_field') field=getfieldvalue(options,'transient_movie_field'); elseif ischar(getfieldvalue(options,'data')) && ~strcmp(getfieldvalue(options,'data'),'transient_movie') field=getfieldvalue(options,'data'); @@ -17,7 +17,7 @@ function plot_transient_movie(md,options,width,i) disp('List of available fields:'); F=fieldnames(md.results.TransientSolution(1)); num = []; - for i=1:numel(F), + for i=1:numel(F) if ~strcmp(F{i},'time') & ... ~strcmp(F{i},'step') & ... ~strcmp(F{i},'errlog') & ... @@ -34,15 +34,15 @@ function plot_transient_movie(md,options,width,i) results=md.results.TransientSolution; %loop over the time steps - if exist(options,'transient_movie_limit'), + if exist(options,'transient_movie_limit') limit=getfieldvalue(options,'transient_movie_limit'); steps=[limit(1):limit(end)]; - elseif exist(options,'transient_movie_steps'), + elseif exist(options,'transient_movie_steps') warning('option ''transient_movie_steps'' is now ''steps'', please update your script'); steps = getfieldvalue(options,'transient_movie_steps'); - elseif exist(options,'steps'), + elseif exist(options,'steps') steps = getfieldvalue(options,'steps'); - elseif exist(options,'step'), + elseif exist(options,'step') steps = getfieldvalue(options,'step'); else steps=1:length(results); @@ -52,7 +52,7 @@ function plot_transient_movie(md,options,width,i) isavi = 0; isgif = 0; ismp4 = 0; - if exist(options,'transient_movie_output'), + if exist(options,'transient_movie_output') filename=getfieldvalue(options,'transient_movie_output'); [pathstr,name,ext] = fileparts(filename); if strcmp(ext,'.gif') @@ -70,7 +70,7 @@ function plot_transient_movie(md,options,width,i) end %calculate caxis - if ~exist(options,'caxis'), + if ~exist(options,'caxis') range = [Inf -Inf]; for i=steps if isfield(results(i), 'MeshElements') @@ -91,7 +91,7 @@ function plot_transient_movie(md,options,width,i) deltat = getfieldvalue(options,'pause',.5); for i=steps - if ~isempty(results(i).(field)), + if ~isempty(results(i).(field)) %Process mesh if necessary if isfield(results(i), 'MeshElements') options=changefieldvalue(options,'amr', i); @@ -150,7 +150,7 @@ function plot_transient_movie(md,options,width,i) if exist(options,'transient_movie_output') %set(gcf,'Renderer','zbuffer','color','white'); %fixes a bug on Mac OS X (not needed in future Matlab version) - if nstep==1, + if nstep==1 %initialize images and frame frame=getframe(gcf); [images,map]=rgb2ind(frame.cdata,256,'nodither'); diff --git a/src/m/plot/plot_transient_results.m b/src/m/plot/plot_transient_results.m index f91166499..b04f0a274 100644 --- a/src/m/plot/plot_transient_results.m +++ b/src/m/plot/plot_transient_results.m @@ -25,7 +25,7 @@ function plot_transient_results(md,options,width,i) figure('Position',pos1); figure('Position',pos2);figure('Position',pos3);figure('Position',pos4);figure('Position',pos5);figure('Position',pos6); string='plotmodel(md'; -for i=1:length(md.results.transient), +for i=1:length(md.results.transient) string=[string ',''data'',md.results.transient(' num2str(i) ').thickness,''title'',''Thickness at time ' num2str(md.results.transient(i).time) ' a''']; end string=[string ',''figure'',1,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight ''');']; @@ -33,16 +33,16 @@ function plot_transient_results(md,options,width,i) clear string; string='plotmodel(md'; -for i=1:length(md.results.transient), +for i=1:length(md.results.transient) string=[string ',''data'',md.results.transient(' num2str(i) ').vel,''view'',3,''title'',''Velocity at time ' num2str(md.results.transient(i).time) ' a''']; end string=[string ',''figure'',2,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight ''');']; eval(string); clear string; -if dimension(md.mesh)==3, +if dimension(md.mesh)==3 string='plotmodel(md'; - for i=1:length(md.results.transient), + for i=1:length(md.results.transient) string=[string ',''data'',md.results.transient(' num2str(i) ').temperature,''view'',3,''title'',''Temperature at time ' num2str(md.results.transient(i).time) ' a''']; end string=[string ',''figure'',3,''colorbar#all'',''on'',''view'',3,''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight ''');']; @@ -51,7 +51,7 @@ function plot_transient_results(md,options,width,i) end string='plotmodel(md'; -for i=2:length(md.results.transient), +for i=2:length(md.results.transient) string=[string ',''data'',md.results.transient(' num2str(i) ').thickness-md.results.transient(' num2str(i-1) ').thickness,''title'',''Delta thickness at time ' num2str(md.results.transient(i).time) ' a''']; end string=[string ',''figure'',4,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight ''');']; @@ -59,16 +59,16 @@ function plot_transient_results(md,options,width,i) clear string; string='plotmodel(md'; -for i=2:length(md.results.transient), +for i=2:length(md.results.transient) string=[string ',''data'',md.results.transient(' num2str(i) ').vel-md.results.transient(' num2str(i-1) ').vel,''view'',3,''title'',''Delta velocity at time ' num2str(md.results.transient(i).time) ' a''']; end string=[string ',''figure'',5,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight ''');']; eval(string); clear string; -if dimension(md.mesh)==3, +if dimension(md.mesh)==3 string='plotmodel(md'; - for i=2:length(md.results.transient), + for i=2:length(md.results.transient) string=[string ',''data'',md.results.transient(' num2str(i) ').temperature-md.results.transient(' num2str(i-1) ').temperature,''view'',3,''title'',''Delta temperature at time ' num2str(md.results.transient(i).time) ' a''']; end string=[string ',''figure'',6,''colorbar#all'',''on'',''fontsize'',' num2str(fontsize) ',''fontweight'',''' fontweight ''');']; diff --git a/src/m/plot/plot_unit.m b/src/m/plot/plot_unit.m index c63932bb1..3a77cbb7b 100644 --- a/src/m/plot/plot_unit.m +++ b/src/m/plot/plot_unit.m @@ -33,16 +33,16 @@ function plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options) patch( 'Faces', [A B C], 'Vertices', [x y z],'CData', data,'FaceColor','flat','EdgeColor',edgecolor); %mask value NaN, plot white faces. - if getfieldvalue(options,'maskwhite',0), + if getfieldvalue(options,'maskwhite',0) pos2=find(data==getfieldvalue(options,'maskvalue',NaN)); - if ~isempty(pos2), + if ~isempty(pos2) A=elements(pos(pos2),1); B=elements(pos(pos2),2); C=elements(pos(pos2),3); data=data(pos2); patch( 'Faces', [A B C], 'Vertices', [x y z],'FaceColor','w','EdgeColor',edgecolor); end end end - if is2d, + if is2d end %node plot @@ -69,7 +69,7 @@ function plot_unit(x,y,z,elements,data,is2d,isplanet,datatype,options) %quiver plot case 3, - if is2d, + if is2d plot_quiver(x,y,data(:,1),data(:,2),options); else plot_quiver3(x,y,z,data(:,1),data(:,2),data(:,3),options); diff --git a/src/m/plot/plot_vstime.m b/src/m/plot/plot_vstime.m index 0cdbff5cf..424d888e0 100644 --- a/src/m/plot/plot_vstime.m +++ b/src/m/plot/plot_vstime.m @@ -9,7 +9,7 @@ function plot_vstime(md,options,nlines,ncols,i) %getting the position of the to be ploted point location=getfieldvalue(options,'position'); -if ~isnumeric(location) | numel(location)~=2, +if ~isnumeric(location) | numel(location)~=2 error('location provided not supported (should be [x y])'); end xpoint=location(1); @@ -23,7 +23,7 @@ function plot_vstime(md,options,nlines,ncols,i) %Constructiion of the result structure(one step above variable in %the structure tree) solstruct = md; -for i=2:numel(structnames)-1, +for i=2:numel(structnames)-1 solstruct=solstruct.(char(structnames(i))); end @@ -32,7 +32,7 @@ function plot_vstime(md,options,nlines,ncols,i) Value(1:timesteps)=NaN*ones(timesteps,1); time(1:timesteps)=NaN*ones(timesteps,1); -for t=1:timesteps, +for t=1:timesteps data=solstruct(t).(char(structnames(numel(structnames)))); diff --git a/src/m/plot/plotdoc.m b/src/m/plot/plotdoc.m index cc931fee5..425194b23 100644 --- a/src/m/plot/plotdoc.m +++ b/src/m/plot/plotdoc.m @@ -51,7 +51,7 @@ function plotdoc() disp(' ''backgroundcolor'': plot background color. (default is ''w'')'); disp(' ''figurebackgroundcolor'': figure background color. (default is ''none'')'); disp(' ''coord'': ''xy'' (default) or ''latlon'''); -disp(' ''colorlevels'': N or {value1,valu2,value3,...} used if quiver, use different colors for the given number of colors or limits'); +disp(' ''colorlevels'': N or {value1,value2,value3,...} used if quiver, use different colors for the given number of colors or limits'); disp(' ''colorbar'': add colorbar (string ''on'' or ''off'')'); disp(' ''colorbartitle'': colorbar title (string)'); disp(' ''colorbarYlabel'': colorbar Y label (string)'); @@ -62,7 +62,7 @@ function plotdoc() disp(' ''colorbarwidth'': multiplier (default 1) to the default width colorbar'); disp(' ''colorbarheight'': multiplier (default 1) to the default height colorbar'); disp(' ''colormap'': same as standard matlab option (''jet'',''hsv'',''cool'',''spring'',''gray'',''Ala'',''Rignot'',...)'); -disp(' ''contourlevels'': N or {value1,valu2,value3,...} add the contours of the specified values or N contours'); +disp(' ''contourlevels'': N or {value1,value2,value3,...} add the contours of the specified values or N contours'); disp(' ''contourticks'': ''on'' or ''off'' to display the ticks of the contours'); disp(' ''contouronly'': ''on'' or ''off'' to display the contours on a white background'); disp(' ''contourcolor'': ticks and contour color'); diff --git a/src/m/plot/plotgemb.m b/src/m/plot/plotgemb.m index 3e1b17b73..1c95ad0da 100644 --- a/src/m/plot/plotgemb.m +++ b/src/m/plot/plotgemb.m @@ -10,13 +10,13 @@ %number of results: nt=length(results); - for i=1:nt, + for i=1:nt z0=zerolevel; %retrieve time, and delta around time: time=results(i).time; - if i=maxstep, + if i>=maxstep break; end end diff --git a/src/m/plot/plotmodel.m b/src/m/plot/plotmodel.m index 770478d16..5a2c1fd32 100644 --- a/src/m/plot/plotmodel.m +++ b/src/m/plot/plotmodel.m @@ -43,7 +43,7 @@ function plotmodel(md,varargin) end %go through subplots -if numberofplots, +if numberofplots %Create figure if (strcmpi(getfieldvalue(options.list{1},'figurestatement','on'),'on')) @@ -51,45 +51,45 @@ function plotmodel(md,varargin) else f=gcf; end - if strcmpi(getfieldvalue(options.list{1},'clf','on'),'on'), + if strcmpi(getfieldvalue(options.list{1},'clf','on'),'on') clf; end - if strcmpi(getfieldvalue(options.list{1},'visible','on'),'off'), + if strcmpi(getfieldvalue(options.list{1},'visible','on'),'off') set(f,'Visible','Off'); end if exist(options.list{1},'figposition'), % {{{ figposition=getfieldvalue(options.list{1},'figposition'); - if ischar(figposition), - if strcmpi(figposition,'larour'), + if ischar(figposition) + if strcmpi(figposition,'larour') set(gcf,'Position',[1604 4 1594 1177]); - elseif strcmpi(figposition,'larour2'), + elseif strcmpi(figposition,'larour2') set(gcf,'Position',[756 62 827 504]); - elseif strcmpi(figposition,'mathieu'), + elseif strcmpi(figposition,'mathieu') set(gcf,'Position',[300 1 1580 1150]); - elseif strcmpi(figposition,'byron'), + elseif strcmpi(figposition,'byron') set(gcf,'Position',[40 1580 560*1.25 420*1.25]); %left, bottom, width, height; W=560 H=420 is default - elseif strcmpi(figposition,'fullscreen'), + elseif strcmpi(figposition,'fullscreen') set(gcf,'Position',get(0,'ScreenSize')); - elseif strcmpi(figposition,'halfright'), + elseif strcmpi(figposition,'halfright') screen=get(0,'ScreenSize'); left=screen(1); bott=screen(2); widt=screen(3); heig=screen(4)-25; set(gcf,'Position',fix([left+widt/2 bott widt/2 heig])); - elseif strcmpi(figposition,'halfleft'), + elseif strcmpi(figposition,'halfleft') screen=get(0,'ScreenSize'); left=screen(1); bott=screen(2); widt=screen(3); heig=screen(4)-25; set(gcf,'Position',fix([left bott widt/2 heig])); - elseif strcmpi(figposition,'square'), + elseif strcmpi(figposition,'square') screen=get(0,'ScreenSize'); left=screen(1); bott=screen(2); widt=min(screen(3)-25,screen(4)-25); set(gcf,'Position',fix([left+(screen(3)-widt) bott widt widt])); - elseif strcmpi(figposition,'portrait'), + elseif strcmpi(figposition,'portrait') %reformat with letter paper size (8.5" x 11") screen=get(0,'ScreenSize'); left=screen(1); bott=screen(2); widt=screen(3); heig=screen(4)-25; portrait=fix([left+widt-(heig*8.5/11) bott heig*8.5/11 heig]); set(gcf,'Position',portrait) - elseif strcmpi(figposition,'landscape'), + elseif strcmpi(figposition,'landscape') %reformat with letter paper size (8.5" x 11") screen=get(0,'ScreenSize'); left=screen(1); bott=screen(2); widt=screen(3); heig=screen(4)-25; @@ -110,14 +110,14 @@ function plotmodel(md,varargin) %Go through all data plottable and close window if an error occurs try, - for i=1:numberofplots, + for i=1:numberofplots if subindex plot_manager(getfieldvalue(options.list{i},'model',md),options.list{i},subplotwidth,nlines,ncols,subindex); else plot_manager(getfieldvalue(options.list{i},'model',md),options.list{i},subplotwidth,nlines,ncols,i); end %List all unused options - if getfieldvalue(options.list{i},'displayunused',1), + if getfieldvalue(options.list{i},'displayunused',1) displayunused(options.list{i}) end end diff --git a/src/m/plot/plotmodel.py b/src/m/plot/plotmodel.py index 5dd64101d..dfc04493f 100644 --- a/src/m/plot/plotmodel.py +++ b/src/m/plot/plotmodel.py @@ -91,6 +91,12 @@ def plotmodel(md, *args): axgrid = [axgrid] # make axgrid iterable contents. axgrid = axgrid.flatten() # flattening... + # Control axes vertical and horizontal spaces. + if options.list[0].exist('axes_pad'): + axes_pad = options.list[0].getfieldvalue('axes_pad', 0.25) + if len(axes_pad) == 1: axes_pad = 2*axes_pad + fig.subplots_adjust(wspace=axes_pad[0],hspace=axes_pad[1]) + for ax in axgrid: ax.set_aspect('equal') diff --git a/src/m/plot/processdata.m b/src/m/plot/processdata.m index 906f7c4dc..eab15e14d 100644 --- a/src/m/plot/processdata.m +++ b/src/m/plot/processdata.m @@ -12,15 +12,15 @@ % See also: PLOTMODEL, PROCESSMESH %check format -if (iscell(data) | isempty(data) | length(data)==0 | (length(data)==1 & ~isstruct(data) & isnan(data))), +if (iscell(data) | isempty(data) | length(data)==0 | (length(data)==1 & ~isstruct(data) & isnan(data))) error('plotmodel error message: data provided is empty'); end %specials for struct -if isstruct(data), +if isstruct(data) disp('data provided is a struct with the following fields:'); F=fieldnames(data); - for i=1:numel(F), + for i=1:numel(F) disp([' ' num2str(i) ': ' F{i} ]); end choice=input(['please enter the field number? (between 1 and ' num2str(numel(F)) ') ']); @@ -36,19 +36,19 @@ end %special case for mesh 2dvertical -if strcmp(domaintype(md.mesh),'2Dvertical'), +if strcmp(domaintype(md.mesh),'2Dvertical') [data datatype] = processdata(md.mesh,md,data,options); return; end %special case for coord latlong: -if strcmpi(getfieldvalue(options,'coord','xy'),'latlon') | strcmpi(getfieldvalue(options,'coord','xy'),'latlong'), +if strcmpi(getfieldvalue(options,'coord','xy'),'latlon') | strcmpi(getfieldvalue(options,'coord','xy'),'latlong') [data datatype] = processdatalatlong(md,data,options); return; end %needed later on -if isprop(md.mesh,'numberofvertices2d'), +if isprop(md.mesh,'numberofvertices2d') numberofvertices2d=md.mesh.numberofvertices2d; numberofelements2d=md.mesh.numberofelements2d; else @@ -57,7 +57,7 @@ end numberofvertices = md.mesh.numberofvertices; numberofelements = md.mesh.numberofelements; -if exist(options,'amr'), +if exist(options,'amr') step = getfieldvalue(options,'amr'); numberofvertices = numel(md.results.TransientSolution(step).MeshX); numberofelements = numel(md.results.TransientSolution(step).MeshElements); @@ -70,7 +70,7 @@ datasize=size(data); %transpose data if necessary -if (size(data,2) > size(data,1)), +if (size(data,2) > size(data,1)) data=data'; end datasize=size(data); @@ -92,9 +92,9 @@ datatype=3; %check number of columns, add zeros if necessary, if (dimension(md.mesh)==3) - if datasize(2)==2, + if datasize(2)==2 data=[data, zeros(datasize(1),1)]; - elseif datasize(2)~=3, + elseif datasize(2)~=3 error('plotmodel error message: data provided should have 2 or 3 columns for quiver plot, and 1 for regular plot'); end end @@ -124,14 +124,14 @@ end %treat the case datasize(1)=nodes2d -if (dimension(md.mesh)==3 & datasize(1)==numberofvertices2d), +if (dimension(md.mesh)==3 & datasize(1)==numberofvertices2d) data=project3d(md,'vector',data,'type','node'); datasize(1)=numberofvertices; %---> go to node data end %treat the case datasize(1)=nodes2d -if (dimension(md.mesh)==3 & datasize(1)==numberofelements2d), +if (dimension(md.mesh)==3 & datasize(1)==numberofelements2d) data=project3d(md,'vector',data,'type','element'); datasize(1)=numberofelements; %---> go to node data @@ -145,19 +145,19 @@ end %element data -if (datasize(1)==numberofelements & datasize(2)==1), +if (datasize(1)==numberofelements & datasize(2)==1) %Initialize datatype if non patch - if datatype~=4 & datatype~=5, + if datatype~=4 & datatype~=5 datatype=1; end %Mask? - if exist(options,'mask'), + if exist(options,'mask') flags=getfieldvalue(options,'mask'); maskvalue=getfieldvalue(options,'maskvalue',NaN); pos=find(~flags); - if length(flags)==numberofvertices, + if length(flags)==numberofvertices [pos2 dummy]=find(ismember(md.mesh.elements,pos)); data(pos2,:)=maskvalue; elseif length(flags)==numberofelements @@ -168,10 +168,10 @@ end %log? - if exist(options,'log'), + if exist(options,'log') bounds=getfieldvalue(options,'caxis',[min(data(:)) max(data(:))]); data(find(data0); x(pos)=-360+x(pos); end elements=delaunay(x,y); @@ -45,14 +45,14 @@ if isprop(md.mesh,'elements2d'), elements2d=md.mesh.elements2d; end -if exist(options,'amr'), +if exist(options,'amr') step = getfieldvalue(options,'amr'); x = md.results.TransientSolution(step).MeshX; y = md.results.TransientSolution(step).MeshY; elements = md.results.TransientSolution(step).MeshElements; else elements=md.mesh.elements; - if ~strcmpi(getfieldvalue(options,'coord','xy'),'latlon') & ~strcmpi(getfieldvalue(options,'coord','xy'),'latlong') , + if ~strcmpi(getfieldvalue(options,'coord','xy'),'latlon') & ~strcmpi(getfieldvalue(options,'coord','xy'),'latlong') x=md.mesh.x; if isprop(md.mesh,'x2d'), x2d=md.mesh.x2d; end y=md.mesh.y; @@ -60,19 +60,19 @@ else x=md.mesh.long; y=md.mesh.lat; - if strcmpi(getfieldvalue(options,'coordcent','atlantic'),'pacific'), + if strcmpi(getfieldvalue(options,'coordcent','atlantic'),'pacific') pos=find(x>0); x(pos)-360+x(pos); end end end -if isprop(md.mesh,'z'), +if isprop(md.mesh,'z') z=md.mesh.z; else z=zeros(size(x)); end z=getfieldvalue(options,'z',z); -if ischar(z), +if ischar(z) z=md.(z); end @@ -85,7 +85,7 @@ %layer projection? if getfieldvalue(options,'layer',0)>=1 || getfieldvalue(options,'depthaverage',0) - if strcmpi(getfieldvalue(options,'coord','xy'),'latlon'), + if strcmpi(getfieldvalue(options,'coord','xy'),'latlon') error('processmesh error message: cannot work with 3D meshes for now'); end %we modify the mesh temporarily to a 2d mesh from which the 3d mesh was extruded @@ -96,7 +96,7 @@ end %units -if exist(options,'unit'), +if exist(options,'unit') unit=getfieldvalue(options,'unit'); x=x*unit; y=y*unit; @@ -109,7 +109,7 @@ y = mean(y(elements),2); end -if isa(md,'planet'), +if isa(md,'planet') isplanet=1; else isplanet=0; diff --git a/src/m/plot/quiver_colorbar.m b/src/m/plot/quiver_colorbar.m index 0fe7bc2ac..5a3d515c0 100644 --- a/src/m/plot/quiver_colorbar.m +++ b/src/m/plot/quiver_colorbar.m @@ -4,7 +4,7 @@ function quiver_colorbar(quivers,options) % Usage: % quiver_colorbar(quivers,options) -if strcmpi(getfieldvalue(options,'colorbar','on'),'on'), +if strcmpi(getfieldvalue(options,'colorbar','on'),'on') %Create colorbar hcb=colorbar('peer',gca,'location','EastOutside'); @@ -12,14 +12,14 @@ function quiver_colorbar(quivers,options) %build ticks ticklabel=cell(1,length(quivers.levels)); - for i=1:length(quivers.levels), + for i=1:length(quivers.levels) ticklabel{i}=num2str(round_ice(quivers.levels(i),3)); end tickpos=1:quivers.numcolors+1; %remove ticks if to many have been created proportion=round(length(quivers.levels)/4); - if proportion>1, + if proportion>1 ticklabel=ticklabel(1:proportion:end); tickpos=tickpos(1:proportion:end); end @@ -28,14 +28,14 @@ function quiver_colorbar(quivers,options) set(hcb,'YTickLabel',ticklabel,'YTick',tickpos); %position - if exist(options,'colorbarpos'), + if exist(options,'colorbarpos') set(hcb,'Position',getfieldvalue(options,'colorbarpos')); end %fontsize fontsize=getfieldvalue(options,'fontsize',14); set(hcb,'FontSize',fontsize); - if exist(options,'colorbartitle'), + if exist(options,'colorbartitle') backup=gca; axes(hcb);lab=title(getfieldvalue(options,'colorbartitle')); set(lab,'Rotation',getfieldvalue(options,'colorbartitlerotation',0)); diff --git a/src/m/plot/quiver_process.m b/src/m/plot/quiver_process.m index 1792339d5..2d852b270 100644 --- a/src/m/plot/quiver_process.m +++ b/src/m/plot/quiver_process.m @@ -16,7 +16,7 @@ %Scale data scalingfactor=getfieldvalue(options,'scaling',0.40); -if strcmpi(getfieldvalue(options,'autoscale','on'),'off'), +if strcmpi(getfieldvalue(options,'autoscale','on'),'off') delta=((min(x)-max(x))^2+(min(y)-max(y))^2)/numel(x); u=scalingfactor*sqrt(delta)*u./Norm; v=scalingfactor*sqrt(delta)*v./Norm; @@ -28,8 +28,8 @@ %number of colors? colorlevels=getfieldvalue(options,'colorlevels',30); -if isnumeric(colorlevels), - if isnan(colorlevels), +if isnumeric(colorlevels) + if isnan(colorlevels) numcolors=30; else numcolors=colorlevels; @@ -61,7 +61,7 @@ if numcolors==2; %blue and red palette=colormap([0 0 1;1 0 0]); -elseif numcolors==3, +elseif numcolors==3 %blue yellow and red palette=colormap([0 0 1;1 1 0;1 0 0]); else diff --git a/src/m/plot/radarpower.m b/src/m/plot/radarpower.m index d0275c90f..47ec2bc02 100644 --- a/src/m/plot/radarpower.m +++ b/src/m/plot/radarpower.m @@ -14,7 +14,7 @@ options=pairoptions; else options=varargin{:}; - if ~isa(options,'pairoptions'), + if ~isa(options,'pairoptions') options=pairoptions(varargin{:}); end end @@ -43,10 +43,10 @@ end if ~exist(options,'overlay_image'), % no image provided, go look into ModelData for one - if exist(options,'geotiff_name'), + if exist(options,'geotiff_name') paths = {getfieldvalue(options,'geotiff_name')}; elseif md.mesh.epsg==3031, %Antarctica - if highres, + if highres paths = {'/Users/larour/ModelData/MosaicTiffRsat/amm125m_v2_200m.tif',... '/home/ModelData/Antarctica/MosaicTiffRsat/amm125m_v2_200m.tif',... '/totten_1/ModelData/Antarctica/MosaicTiffRsat/amm125m_v2_200m.tif',... @@ -60,7 +60,7 @@ }; end elseif md.mesh.epsg==3413, %Greenland - if highres, + if highres paths = {'/u/astrid-r1b/ModelData/MOG/mog100_r2_hp1.tif',... '/home/ModelData/Greenland/MOG/mog100_r2_hp1.tif',... '/totten_1/ModelData/Greenland/MOG/mog100_r2_hp1.tif',... @@ -80,12 +80,12 @@ %Find file from list found = false; - for i=1:numel(paths), - if exist(paths{i},'file'), + for i=1:numel(paths) + if exist(paths{i},'file') geotiff_name = paths{i}; found = true; end end - if ~found, + if ~found error('could not find radar image'); end @@ -106,7 +106,7 @@ md.radaroverlay.y=(y0:(y1-y0)/(size(md.radaroverlay.pwr,1)-1):y1); %Erase image or keep it? - if ~getfieldvalue(options,'keep_image',0), + if ~getfieldvalue(options,'keep_image',0) system('rm -rf ./temp.tif'); end else %user provided image @@ -136,11 +136,11 @@ md.radaroverlay.y=y1:-(y1-y0)/(size(md.radaroverlay.pwr,1)-1):y0; %Erase image or keep it? - if ~getfieldvalue(options,'keep_image',0), + if ~getfieldvalue(options,'keep_image',0) delete(tempfilename); end else - if (~exist(options,'overlay_xlim') | ~exist(options,'overlay_xlim')| ~exist(options,'overlay_xposting')| ~exist(options,'overlay_yposting')), + if (~exist(options,'overlay_xlim') | ~exist(options,'overlay_xlim')| ~exist(options,'overlay_xposting')| ~exist(options,'overlay_yposting')) error('radarpower error message: please provide overlay_xlim, overlay_ylim, overlay_xposting and overlay_yposting options together with overlay_image option'); end overlay_xlim=getfieldvalue(options,'overlay_xlim'); @@ -167,7 +167,7 @@ end %Was a triangulation requested for the area of the image that is not covered by the mesh? -if strcmpi(getfieldvalue(options,'outertriangulation','no'),'yes'), +if strcmpi(getfieldvalue(options,'outertriangulation','no'),'yes') %create expfile that is a box controlled by xlim and ylim, with a hole defined by the mesh outer segments. box.name=''; @@ -183,7 +183,7 @@ box(2).y=md.mesh.y(md.mesh.segments(:,1)); box(2).y=[box(2).y; box(2).y(1)]; - if strcmpi(getfieldvalue(options,'outertriangulationflip','no'),'yes'), + if strcmpi(getfieldvalue(options,'outertriangulationflip','no'),'yes') box(2).x=flipud(box(2).x); box(2).y=flipud(box(2).y); end diff --git a/src/m/plot/scaleruler.m b/src/m/plot/scaleruler.m index 2bcb64177..68c384bb8 100644 --- a/src/m/plot/scaleruler.m +++ b/src/m/plot/scaleruler.m @@ -25,7 +25,7 @@ function scaleruler(options) numberofticks = double(structure(5)); %If only one tick, just draw a rectangle -if numberofticks==1, +if numberofticks==1 t=text(x0+lengthscale/2,y0+2*widthscale,2,[num2str(lengthscale*unitscale/1000) ' km'],... 'FontSize',fontsize,'FontWeight',fontweight,'Color',fontcolor,'HorizontalAlignment','center','VerticalAlignment','bottom'); if ~verLessThan('matlab', '8.4') @@ -47,7 +47,7 @@ function scaleruler(options) text(xt,yt,2,num2str(Tick),'FontSize',fontsize,'FontWeight',fontweight,'Color',fontcolor,'HorizontalAlignment','center','VerticalAlignment','bottom'); %loope over the patches - for i=1:numberofticks-1, + for i=1:numberofticks-1 Au=Bu; Ad=Bd; Bu=[Au(1)+unitlength Ad(2)+widthscale]; @@ -67,14 +67,14 @@ function scaleruler(options) %Text xt=Bu(1); yt=Bu(2)+widthscale; - if i~=numberofticks-1, + if i~=numberofticks-1 text(xt,yt,2,num2str(round_ice(Tick/1000,3)),'FontSize',fontsize,'FontWeight',fontweight,'Color',fontcolor,'HorizontalAlignment','center','VerticalAlignment','bottom'); end end text(xt,yt,2,num2str(round_ice(Tick/1000,3)),'FontSize',fontsize,'FontWeight',fontweight,'Color',fontcolor,'HorizontalAlignment','center','VerticalAlignment','bottom'); % add leading spaces depending on length of label string str=' km'; - for i=1:numel(num2str(round_ice(Tick/1000,3))), + for i=1:numel(num2str(round_ice(Tick/1000,3))) str=[' ' str]; end text(xt,yt,2,str,'FontSize',fontsize,'FontWeight',fontweight,'Color',fontcolor,'HorizontalAlignment','left','VerticalAlignment','bottom'); diff --git a/src/m/plot/showregion.m b/src/m/plot/showregion.m index a07e2a706..7c9414b3c 100644 --- a/src/m/plot/showregion.m +++ b/src/m/plot/showregion.m @@ -14,9 +14,9 @@ function showregion(md,insetpos) axes('pos',PosInset); axis equal off %box off -if md.mesh.epsg==3413, +if md.mesh.epsg==3413 A=expread(['/u/astrid-r1b/ModelData/Exp/Greenland.exp']); -elseif md.mesh.epsg==3031, +elseif md.mesh.epsg==3031 A=expread(['/u/astrid-r1b/ModelData/Exp/Antarctica.exp']); else error('md.mesh.epsg not supported yet'); diff --git a/src/m/plot/squarezoom.m b/src/m/plot/squarezoom.m index 3f9d01eb9..3367c6fab 100644 --- a/src/m/plot/squarezoom.m +++ b/src/m/plot/squarezoom.m @@ -9,7 +9,7 @@ function squarezoom() dx=x(2)-x(1); dy=y(1)-y(2); -if dx>dy, +if dx>dy delta=dx-dy; xlim([x(1) x(2)]); ylim([y(2)-delta/2 y(1)+delta/2]); diff --git a/src/m/plot/subplotmodel.m b/src/m/plot/subplotmodel.m index f13b45c1d..9d5555987 100644 --- a/src/m/plot/subplotmodel.m +++ b/src/m/plot/subplotmodel.m @@ -5,7 +5,7 @@ % h=subplotmodel(nlines,ncols,i,options) box=getfieldvalue(options,'box','off'); -if strcmpi(box,'on'), +if strcmpi(box,'on') visible='on'; else visible='off'; diff --git a/src/m/plot/writejsfield.m b/src/m/plot/writejsfield.m index 186ac1a2f..bff6bd6d7 100644 --- a/src/m/plot/writejsfield.m +++ b/src/m/plot/writejsfield.m @@ -6,10 +6,10 @@ function writejsfield(fid,name,variable,nods) % %write array: - if size(variable,2)==1, + if size(variable,2)==1 fprintf(fid,'\n',name); fprintf(fid,'%s=[',name); - for i=1:nods-1, + for i=1:nods-1 fprintf(fid,'%g,',variable(i)); end fprintf(fid,'%g];\n',variable(end)); @@ -18,9 +18,9 @@ function writejsfield(fid,name,variable,nods) %multi-sized array: fprintf(fid,'\n',name); fprintf(fid,'%s=[]\n',name); - for i=1:size(variable,2), + for i=1:size(variable,2) fprintf(fid,'%s["%i"]=[',name,i); - for j=1:nods-1, + for j=1:nods-1 fprintf(fid,'%g,',variable(j,i)); end fprintf(fid,'%g];\n',variable(end,i)); diff --git a/src/m/plot/writejsfile.m b/src/m/plot/writejsfile.m index 10d923fab..c05dec994 100644 --- a/src/m/plot/writejsfile.m +++ b/src/m/plot/writejsfile.m @@ -18,7 +18,7 @@ function writejsfile(filename,model,keyname) %write index: fprintf(fid,'\n'); fprintf(fid,'model["index"]=['); - for i=1:nel-1, + for i=1:nel-1 fprintf(fid,'[%i, %i, %i],',model.index(i,1),model.index(i,2),model.index(i,3)); end fprintf(fid,'[%i, %i, %i]];\n',model.index(end,1),model.index(end,2),model.index(end,3)); @@ -39,7 +39,7 @@ function writejsfile(filename,model,keyname) results=model.results; fprintf(fid,'results={};\n'); - for i=1:length(results), + for i=1:length(results) fprintf(fid,'result={};\n'); writejsfield(fid,'result["data"]',results(i).data,nods); fprintf(fid,'\n'); @@ -47,7 +47,7 @@ function writejsfile(filename,model,keyname) fprintf(fid,'result["label"]="%s";\n',results(i).label); fprintf(fid,'result["shortlabel"]="%s";\n',results(i).shortlabel); fprintf(fid,'result["unit"]="%s";\n',results(i).unit); - if size(results(i).data,2)>1, + if size(results(i).data,2)>1 fprintf(fid,'result["time_range"]=[%g,%g];\n',results(i).time_range(1),results(i).time_range(2)); end fprintf(fid,'results["%i"]=result;\n',i); diff --git a/src/m/qmu/dakota_in_write.m b/src/m/qmu/dakota_in_write.m index 1eac09abe..f66520d20 100755 --- a/src/m/qmu/dakota_in_write.m +++ b/src/m/qmu/dakota_in_write.m @@ -77,7 +77,7 @@ % write the strategy section -if IssmConfig('_DAKOTA_VERSION_') < 6, +if IssmConfig('_DAKOTA_VERSION_') < 6 strategy_write(fidi,params); else environment_write(fidi,params); @@ -195,10 +195,10 @@ end % write correlation matrix: -if ~isempty(corrin), +if ~isempty(corrin) fprintf(fidi,'uncertain_correlation_matrix\n'); - for i=1:size(corrin,1), - for j=1:size(corrin,2), + for i=1:size(corrin,1) + for j=1:size(corrin,2) fprintf(fidi,'%g ',corrin(i,j)); end fprintf(fidi,'\n'); @@ -257,7 +257,7 @@ param_write(fidi,'\t','algebraic_mappings',' = ','\n',params); param_write(fidi,'\t','direct','','\n',params); param_write(fidi,'\t ','analysis_driver',' = ''','''\n',params); - if IssmConfig('_DAKOTA_VERSION_') < 6, + if IssmConfig('_DAKOTA_VERSION_') < 6 param_write(fidi,'\t ','evaluation_static_scheduling','','\n',params); else param_write(fidi,'\t ','evaluation_scheduling',' ','\n',params); diff --git a/src/m/qmu/dakota_m_write.m b/src/m/qmu/dakota_m_write.m index c52c80ea1..b407eb1bd 100755 --- a/src/m/qmu/dakota_m_write.m +++ b/src/m/qmu/dakota_m_write.m @@ -175,7 +175,7 @@ descriptor=discardnum(dvar(i).descriptor); %is there a lock on this variable? We don't want to update the variable twice! - if exist([descriptor '_lock'],'var'), + if exist([descriptor '_lock'],'var') %lock is in place, do not update! continue; continue; else diff --git a/src/m/qmu/importancefactors.m b/src/m/qmu/importancefactors.m index 0c5d4b976..1e697578c 100644 --- a/src/m/qmu/importancefactors.m +++ b/src/m/qmu/importancefactors.m @@ -13,13 +13,13 @@ %go through all response functions and find the one corresponding to the correct responsename responsefunctions=md.qmu.results.dresp_out; found=0; -for i=1:length(responsefunctions), - if strcmpi(responsefunctions(i).descriptor,responsename), +for i=1:length(responsefunctions) + if strcmpi(responsefunctions(i).descriptor,responsename) found=i; break; end end -if ~found, +if ~found error('importancefactors error message: could not find correct response function'); end responsefunctions=responsefunctions(found); @@ -28,15 +28,15 @@ %Now recover response to the correct design variable importancefactors=zeros(1,0); count=0; -for i=1:nfun, +for i=1:nfun desvar=responsefunctions.var{i}; - if strncmpi(desvar,variablename,variablenamelength), + if strncmpi(desvar,variablename,variablenamelength) importancefactors(end+1)=responsefunctions.impfac(i); count=count+1; end end -if count==0, +if count==0 error('importancefactors error message: either response does not exist, or importancefactors are empty'); end diff --git a/src/m/qmu/plot/plot_hist_norm.m b/src/m/qmu/plot/plot_hist_norm.m index f3bdbf5b6..b19327ead 100755 --- a/src/m/qmu/plot/plot_hist_norm.m +++ b/src/m/qmu/plot/plot_hist_norm.m @@ -328,14 +328,14 @@ end ylim(ylims) -if exist('FontSize','var'), +if exist('FontSize','var') fontsize=FontSize; else fontsize=12; end % add the annotation -if exist('titleplt','var'), +if exist('titleplt','var') title(titleplt,'FontSize',fontsize); else if exist('cdfplt','var') && ... @@ -346,18 +346,18 @@ end end -if exist('xlabelplt','var'), +if exist('xlabelplt','var') xlabel(xlabelplt,'FontSize',fontsize); else xlabel('Interval Edge Value'); end -if exist('ylabelplt','var'), +if exist('ylabelplt','var') ylabel(ylabelplt,'FontSize',fontsize); else ylabel('Relative Frequency'); end if exist('descr','var') - if ~strncmpi(cdfleg,'off',3), + if ~strncmpi(cdfleg,'off',3) hleg1=legend(ax1,descr(1:length(hl1)),'Location','Best','Color','none','Interpreter','none'); end else diff --git a/src/m/qmu/postqmu.m b/src/m/qmu/postqmu.m index c1950b390..16fc75891 100644 --- a/src/m/qmu/postqmu.m +++ b/src/m/qmu/postqmu.m @@ -35,22 +35,22 @@ dakotaresults.dresp_dat=dresp_dat; end -if md.qmu.output & strcmpi(md.qmu.statistics.method(1).name,'None'), - if strcmpi(md.qmu.method.method,'nond_sampling'), +if md.qmu.output & strcmpi(md.qmu.statistics.method(1).name,'None') + if strcmpi(md.qmu.method.method,'nond_sampling') dakotaresults.modelresults={}; md2=md; md2.qmu.isdakota=0; - for i=1:md2.qmu.method.params.samples, + for i=1:md2.qmu.method.params.samples disp(['Reading qmu file ' md2.miscellaneous.name '.outbin.' num2str(i)]); md2=loadresultsfromdisk(md2,[md2.miscellaneous.name '.outbin.' num2str(i)]); dakotaresults.modelresults{end+1}=md2.results; end end - if strcmpi(md.qmu.method.method,'list_parameter_study'), + if strcmpi(md.qmu.method.method,'list_parameter_study') dakotaresults.modelresults={}; md2=md; md2.qmu.isdakota=0; - for i=md.qmu.method.params.list_of_points, + for i=md.qmu.method.params.list_of_points disp(['Reading qmu file ' md2.miscellaneous.name '.outbin.' num2str(i)]); md2=loadresultsfromdisk(md2,[md2.miscellaneous.name '.outbin.' num2str(i)]); dakotaresults.modelresults{end+1}=md2.results; @@ -58,7 +58,7 @@ end end -if ~strcmpi(md.qmu.statistics.method(1).name,'None'), +if ~strcmpi(md.qmu.statistics.method(1).name,'None') md.qmu.isdakota=0; md=loadresultsfromdisk(md,[md.miscellaneous.name,'.stats']); md.qmu.isdakota=1; @@ -68,7 +68,7 @@ md.results.dakota=dakotaresults; % move all the individual function evalutations into zip files -if ~md.qmu.isdakota, +if ~md.qmu.isdakota system('zip -mq params.in.zip params.in.[1-9]*'); system('zip -mq results.out.zip results.out.[1-9]*'); system('zip -mq matlab.out.zip matlab*.out.[1-9]*'); diff --git a/src/m/qmu/preqmu.m b/src/m/qmu/preqmu.m index 7d7f8c6fc..af0b5c5a4 100644 --- a/src/m/qmu/preqmu.m +++ b/src/m/qmu/preqmu.m @@ -1,6 +1,6 @@ function md=preqmu(md,options) -%QMU - apply Quantification of Margins and Uncertainties techniques -% to a solution sequence (like stressbalance.m, progonstic.m, etc ...), +%QMU - apply Quantification of Margins and Uncertainties techniques +% to a solution sequence (like stressbalance.m, progonstic.m, etc ...), % using the Dakota software from Sandia. % % options come from the solve.m routine. They can include Dakota options: @@ -32,15 +32,15 @@ %go through variables and responses, and check they don't have more than the number of partitions. Also determine numvariables and numresponses numvariables=0; variable_fieldnames=fieldnames(variables); -for i=1:length(variable_fieldnames), +for i=1:length(variable_fieldnames) field_name=variable_fieldnames{i}; fieldvariables=variables.(field_name); for j=1:numel(fieldvariables) - if strncmpi(fieldvariables(j).descriptor,'scaled_',7), + if strncmpi(fieldvariables(j).descriptor,'scaled_',7) npart=qmupart2npart(fieldvariables(j).partition); nt=fieldvariables(j).nsteps; - if nt==1, - if str2int(fieldvariables(j).descriptor,'last')>npart, + if nt==1 + if str2int(fieldvariables(j).descriptor,'last')>npart error('preqmu error message: one of the expanded variables has more values than the number of partitions '); end end @@ -51,13 +51,13 @@ numresponses=0; response_fieldnames=fieldnames(responses); -for i=1:length(response_fieldnames), +for i=1:length(response_fieldnames) field_name=response_fieldnames{i}; fieldresponses=responses.(field_name); for j=1:numel(fieldresponses) - if strncmpi(fieldresponses(j).descriptor,'scaled_',7), + if strncmpi(fieldresponses(j).descriptor,'scaled_',7) npart=partition_npart(fieldresponses(j).partition); - if str2int(fieldresponses(j).descriptor,'last')>npart, + if str2int(fieldresponses(j).descriptor,'last')>npart error('preqmu error message: one of the expanded responses has more values than the number of partitions'); end end @@ -71,7 +71,7 @@ %build a list of variables and responses descriptors. the list is not expanded. variabledescriptors={}; variable_fieldnames=fieldnames(md.qmu.variables(ivar)); -for i=1:length(variable_fieldnames), +for i=1:length(variable_fieldnames) field_name=variable_fieldnames{i}; fieldvariables=md.qmu.variables(ivar).(field_name); for j=1:numel(fieldvariables) @@ -81,7 +81,7 @@ responsedescriptors={}; response_fieldnames=fieldnames(md.qmu.responses(iresp)); -for i=1:length(response_fieldnames), +for i=1:length(response_fieldnames) field_name=response_fieldnames{i}; fieldresponses=md.qmu.responses(iresp).(field_name); for j=1:numel(fieldresponses) @@ -94,13 +94,13 @@ variablepartitions_npart=[]; variablepartitions_nt=[]; variable_fieldnames=fieldnames(md.qmu.variables(ivar)); -for i=1:length(variable_fieldnames), +for i=1:length(variable_fieldnames) field_name=variable_fieldnames{i}; fieldvariable=md.qmu.variables(ivar).(field_name); if fieldvariable.isscaled() | fieldvariable.isdistributed(); variablepartitions{end+1}=fieldvariable.partition; variablepartitions_npart(end+1)=qmupart2npart(fieldvariable.partition); - if isprop(fieldvariable,'nsteps'), + if isprop(fieldvariable,'nsteps') variablepartitions_nt(end+1)=fieldvariable.nsteps; else variablepartitions_nt(end+1)=1; @@ -116,7 +116,7 @@ responsepartitions={}; responsepartitions_npart=[]; response_fieldnames=fieldnames(md.qmu.responses(iresp)); -for i=1:length(response_fieldnames), +for i=1:length(response_fieldnames) field_name=response_fieldnames{i}; fieldresponse=md.qmu.responses(iresp).(field_name); if fieldresponse.isscaled(); diff --git a/src/m/qmu/process_qmu_response_data.m b/src/m/qmu/process_qmu_response_data.m index c062c18be..35c60061d 100644 --- a/src/m/qmu/process_qmu_response_data.m +++ b/src/m/qmu/process_qmu_response_data.m @@ -11,38 +11,38 @@ num_mass_flux=0; %loop through response descriptors, and act accordingly -for i=1:numel(md.qmu.responsedescriptors), +for i=1:numel(md.qmu.responsedescriptors) %Do we have to process mass flux profiles? - if strncmpi(md.qmu.responsedescriptors{i},'indexed_MassFlux',16), + if strncmpi(md.qmu.responsedescriptors{i},'indexed_MassFlux',16) num_mass_flux=num_mass_flux+1; process_mass_flux_profiles=1; end end %deal with mass flux profiles -if process_mass_flux_profiles, +if process_mass_flux_profiles %we need a profile of points on which to compute the mass_flux, is it here? - if isnans(md.qmu.mass_flux_profiles), + if isnans(md.qmu.mass_flux_profiles) error('process_qmu_response_data error message: could not find a mass_flux exp profile!'); end - if ~iscell(md.qmu.mass_flux_profiles), + if ~iscell(md.qmu.mass_flux_profiles) error('process_qmu_response_data error message: qmu_mass_flux_profiles field should be a cell array of domain outline names'); end - if isempty(md.qmu.mass_flux_profiles), + if isempty(md.qmu.mass_flux_profiles) error('process_qmu_response_data error message: qmu_mass_flux_profiles cannot be empty!'); end - if num_mass_flux~=numel(md.qmu.mass_flux_profiles), + if num_mass_flux~=numel(md.qmu.mass_flux_profiles) error('process_qmu_response_data error message: qmu_mass_flux_profiles should be of the same size as the number of MassFlux responses asked for in the Qmu analysis'); end %ok, process the domains named in qmu_mass_flux_profiles, to build a list of segments (MatArray) md.qmu.mass_flux_segments=cell(num_mass_flux,1); - for i=1:num_mass_flux, + for i=1:num_mass_flux md.qmu.mass_flux_segments{i}=MeshProfileIntersection(md.mesh.elements,md.mesh.x,md.mesh.y,[md.qmu.mass_flux_profile_directory '/' md.qmu.mass_flux_profiles{i}]); end end diff --git a/src/m/qmu/qmu_correlation.m b/src/m/qmu/qmu_correlation.m index 502cde901..405dd58cf 100644 --- a/src/m/qmu/qmu_correlation.m +++ b/src/m/qmu/qmu_correlation.m @@ -8,7 +8,7 @@ % Example: % mass_flux_drag_correlation=qmu_correlation(md,'drag','mass_flux'); -if ~isfield(md.qmu.results,'dresp_dat'), +if ~isfield(md.qmu.results,'dresp_dat') error('qmu_correlation error message: could not find dresp_dat field in dakota results. you need to run montecarlo before computing correlations'); end @@ -16,13 +16,13 @@ %go through all the rows and figure which one we are interested in. found=0; -for i=1:numel(data), - if strcmpi(data(i).descriptor,responsename), +for i=1:numel(data) + if strcmpi(data(i).descriptor,responsename) found=i; break; end end -if found==0, +if found==0 error(['qmu_correlation error message: could not find data descriptor for response ' responsename]); end @@ -32,19 +32,19 @@ %now go through variables, and compute correlation coefficient each time: variablenamelength=length(variablename); index=[]; -for i=1:numel(data), - if strncmpi(variablename,data(i).descriptor,variablenamelength), +for i=1:numel(data) + if strncmpi(variablename,data(i).descriptor,variablenamelength) %this observation is one we are looking for. index=[index;i]; end end -if isempty(index), +if isempty(index) error(['qmu_correlation error message: could not find correlation descriptor for variable ' variablename]); end factors=zeros(numel(index),1); -for i=1:numel(index), +for i=1:numel(index) matrix=corrcoef(data(index(i)).sample,response_samples); factors(i)=matrix(2,1); end diff --git a/src/m/qmu/qmuisdistributed.m b/src/m/qmu/qmuisdistributed.m index eb2e2d283..64ae148c9 100644 --- a/src/m/qmu/qmuisdistributed.m +++ b/src/m/qmu/qmuisdistributed.m @@ -4,7 +4,7 @@ %just take last string element, and see if it is numeric. last=string(end); -if ((double(last)<=57) & (double(last)>=48)), +if ((double(last)<=57) & (double(last)>=48)) found=1; else found=0; diff --git a/src/m/qmu/qmuname.m b/src/m/qmu/qmuname.m index fecdd41c9..865cbacbd 100755 --- a/src/m/qmu/qmuname.m +++ b/src/m/qmu/qmuname.m @@ -3,7 +3,7 @@ %Pick up the number from a file, or get it directly from the Dakota structure. Then modify the name of this %model to reflect this new number. -if nargin==1, +if nargin==1 fid=fopen('number','r'); number=fscanf(fid,'%i',1) fclose(fid); diff --git a/src/m/qmu/qmuresponse.m b/src/m/qmu/qmuresponse.m index 54c7a889d..6caa59c72 100644 --- a/src/m/qmu/qmuresponse.m +++ b/src/m/qmu/qmuresponse.m @@ -1,23 +1,23 @@ function response=qmuresponse(models,results,processedresults,descriptor) %QMURESPONSE - compute response function from model results. -if strcmpi(descriptor,'max_vel'), +if strcmpi(descriptor,'max_vel') response=max(processedresults.vel); -elseif strcmpi(descriptor,'min_vel'), +elseif strcmpi(descriptor,'min_vel') response=min(processedresults.vel); -elseif strcmpi(descriptor,'max_vx'), +elseif strcmpi(descriptor,'max_vx') response=max(processedresults.vx); -elseif strcmpi(descriptor,'max_abs_vx'), +elseif strcmpi(descriptor,'max_abs_vx') response=max(abs(processedresults.vx)); -elseif strcmpi(descriptor,'min_vx'), +elseif strcmpi(descriptor,'min_vx') response=min(processedresults.vx); -elseif strcmpi(descriptor,'max_vy'), +elseif strcmpi(descriptor,'max_vy') response=max(processedresults.vy); -elseif strcmpi(descriptor,'max_abs_vy'), +elseif strcmpi(descriptor,'max_abs_vy') response=max(abs(processedresults.vy)); -elseif strcmpi(descriptor,'min_vy'), +elseif strcmpi(descriptor,'min_vy') response=min(processedresults.vy); -elseif strncmpi(descriptor,'mass_flux',9), +elseif strncmpi(descriptor,'mass_flux',9) indx=str2int(descriptor(10:end)); if isempty(indx) || ~indx indx=1; @@ -31,7 +31,7 @@ isSSA=m_dh.parameters.isSSA; isHO=m_dh.parameters.isHO; isFS=m_ds.parameters.isFS; - if isSIA, + if isSIA % for now, separate all segments from double array for parallel to make cells if (length(m_dhu.parameters.qmu_mass_flux_num_segments) > 1) @@ -57,7 +57,7 @@ clear save end - elseif isSSA || isHO, + elseif isSSA || isHO % for now, separate all segments from double array for parallel to make cells if (length(m_dh.parameters.qmu_mass_flux_num_segments) > 1) @@ -83,7 +83,7 @@ clear save end - elseif isFS, + elseif isFS % for now, separate all segments from double array for parallel to make cells if (length(m_ds.parameters.qmu_mass_flux_num_segments) > 1) diff --git a/src/m/qmu/qmuroot.m b/src/m/qmu/qmuroot.m index d99432141..cc183680e 100644 --- a/src/m/qmu/qmuroot.m +++ b/src/m/qmu/qmuroot.m @@ -3,7 +3,7 @@ root=''; found=0; -for i=1:length(string), +for i=1:length(string) if ((49<=double(string(i))) && (double(string(i)<=57))) break; else diff --git a/src/m/qmu/recover_qmu_options.m b/src/m/qmu/recover_qmu_options.m index 804df2c63..96c6d3484 100644 --- a/src/m/qmu/recover_qmu_options.m +++ b/src/m/qmu/recover_qmu_options.m @@ -10,12 +10,12 @@ options=cell(0,2); %make sure length(varargin) is even, ie options come in pairs. -if mod(length(varargin),2), +if mod(length(varargin),2) error('recover_qmu_options error message: an even number of options is necessary'); end %go through varargin, extract options -for i=1:length(varargin)/2, +for i=1:length(varargin)/2 options(end+1,:)={varargin{2*i-1} varargin{2*i}}; diff --git a/src/m/qmu/sensitivities.m b/src/m/qmu/sensitivities.m index fdd135f97..574d66dae 100644 --- a/src/m/qmu/sensitivities.m +++ b/src/m/qmu/sensitivities.m @@ -13,13 +13,13 @@ %go through all response functions and find the one corresponding to the correct responsename responsefunctions=md.qmu.results.dresp_out; found=0; -for i=1:length(responsefunctions), - if strcmpi(responsefunctions(i).descriptor,responsename), +for i=1:length(responsefunctions) + if strcmpi(responsefunctions(i).descriptor,responsename) found=i; break; end end -if ~found, +if ~found error('importancefactors error message: could not find correct response function'); end responsefunctions=responsefunctions(found); @@ -28,16 +28,16 @@ %Now recover response to the correct design variable rawsens=zeros(0,1); count=0; -for i=1:nfun, +for i=1:nfun desvar=responsefunctions.var{i}; - if strncmpi(desvar,variablename,variablenamelength), + if strncmpi(desvar,variablename,variablenamelength) rawsens(end+1,1)=responsefunctions.sens(i); count=count+1; end end %Now, if this was a distributed variable, the sensitivities need to be scaled by means of the input variable. -if IsScaled(variablename), +if IsScaled(variablename) %ipick up the variable in the model switch variablename, @@ -49,13 +49,13 @@ average_variable=AreaAverageOntoPartition(md,variable); %scale the sensitivities: only where the average_variable is not 0 - if ~isempty(rawsens), + if ~isempty(rawsens) pos=find(average_variable); rawsens(pos)=rawsens(pos)./average_variable(pos); end end -if count==0, +if count==0 error('sensitivities error message: either response does not exist, or sensitivities are empty'); end diff --git a/src/m/qmu/setupdesign/QmuSetupResponses.m b/src/m/qmu/setupdesign/QmuSetupResponses.m index d078e3686..d2005f4b5 100755 --- a/src/m/qmu/setupdesign/QmuSetupResponses.m +++ b/src/m/qmu/setupdesign/QmuSetupResponses.m @@ -7,14 +7,14 @@ %or if we just carry it forward as is. %ok, key off according to type of descriptor: -if strncmp(descriptor,'scaled_',7), +if strncmp(descriptor,'scaled_',7) %we have a scaled response, expand it over the partition. %ok, dealing with semi-discrete distributed response. Distribute according to how many %partitions we want npart=qmupart2npart(responses.partition); - for j=1:npart, + for j=1:npart dresp(end+1) =responses; dresp(end ).descriptor=sprintf('%s_%d',responses.descriptor,j); end diff --git a/src/m/qmu/setupdesign/QmuSetupVariables.m b/src/m/qmu/setupdesign/QmuSetupVariables.m index 217a5dd43..d4c312efd 100755 --- a/src/m/qmu/setupdesign/QmuSetupVariables.m +++ b/src/m/qmu/setupdesign/QmuSetupVariables.m @@ -7,7 +7,7 @@ %or if we just carry it forward as is. %ok, key off according to type of descriptor: -if strncmp(descriptor,'scaled_',7), +if strncmp(descriptor,'scaled_',7) %we have a scaled variable, expand it over the partition. First recover the partition: partition=variables.partition; %figure out number of partitions: @@ -15,71 +15,71 @@ %figure out number of time steps: nt=variables.nsteps; - if isa(variables,'uniform_uncertain'), + if isa(variables,'uniform_uncertain') nlower=size(variables.lower,1); nupper=size(variables.upper,1); - if (nlower ~= npart || nupper ~=npart), + if (nlower ~= npart || nupper ~=npart) error('QmuSetupVariables error message: upper and lower fields should have the same number of rows as the number of partitions'); end nlower=size(variables.lower,2); nupper=size(variables.upper,2); - if (nlower ~= nt || nupper ~= nt), + if (nlower ~= nt || nupper ~= nt) error('QmuSetupVariables error message: upper and lower fields should have the same number of cols as the number of time steps'); end - elseif isa(variables,'normal_uncertain'), + elseif isa(variables,'normal_uncertain') nstddev=size(variables.stddev,1); nmean=size(variables.mean,1); - if (nstddev ~= npart || nmean ~=npart), + if (nstddev ~= npart || nmean ~=npart) error('QmuSetupVariables error message: stddev and mean fields should have the same number of rows as the number of partitions'); end nstddev=size(variables.stddev,2); nmean=size(variables.mean,2); - if (nstddev ~= nt || nmean ~=nt), + if (nstddev ~= nt || nmean ~=nt) error('QmuSetupVariables error message: stddev and mean fields should have the same number of cols as the number of time steps'); end - elseif isa(variables,'continuous_design'), + elseif isa(variables,'continuous_design') nupper=size(variables.upper,1); nlower=size(variables.lower,1); - if (nupper ~= npart || nlower ~=npart), + if (nupper ~= npart || nlower ~=npart) error('QmuSetupVariables error message: upper and lower fields should have the same number of rows as the number of partitions'); end nupper=size(variables.upper,2); nlower=size(variables.lower,2); - if (nupper ~= nt || nlower ~=nt), + if (nupper ~= nt || nlower ~=nt) error('QmuSetupVariables error message: upper and lower fields should have the same number of cols as the number of time steps'); end end %ok, dealing with semi-discrete distributed variable. Distribute according to how many %partitions we want, and number of time steps: - if nt==1, - for j=1:npart, + if nt==1 + for j=1:npart dvar(end+1) =variables; dvar(end ).descriptor=sprintf('%s_%d',variables.descriptor,j); - if isa(variables,'uniform_uncertain'), + if isa(variables,'uniform_uncertain') dvar(end ).lower=variables.lower(j); dvar(end ).upper=variables.upper(j); - elseif isa(variables,'normal_uncertain'), + elseif isa(variables,'normal_uncertain') dvar(end ).stddev=variables.stddev(j); dvar(end ).mean=variables.mean(j); - elseif isa(variables,'continuous_design'), + elseif isa(variables,'continuous_design') dvar(end ).upper=variables.upper(j); dvar(end ).lower=variables.lower(j); dvar(end ).initpt=variables.initpt(j); end end else - for j=1:npart, - for k=1:nt, + for j=1:npart + for k=1:nt dvar(end+1) =variables; dvar(end ).descriptor=sprintf('%s_%d_%d',variables.descriptor,j,k); - if isa(variables,'uniform_uncertain'), + if isa(variables,'uniform_uncertain') dvar(end ).lower=variables.lower(j,k); dvar(end ).upper=variables.upper(j,k); - elseif isa(variables,'normal_uncertain'), + elseif isa(variables,'normal_uncertain') dvar(end ).stddev=variables.stddev(j,k); dvar(end ).mean=variables.mean(j,k); - elseif isa(variables,'continuous_design'), + elseif isa(variables,'continuous_design') dvar(end ).upper=variables.upper(j,k); dvar(end ).lower=variables.lower(j,k); dvar(end ).initpt=variables.initpt(j,k); @@ -89,65 +89,65 @@ end -elseif strncmp(descriptor,'distributed_',12), +elseif strncmp(descriptor,'distributed_',12) %we have a distributed variable, expand it over the partition. First recover the partition: partition=variables.partition; %figure out number of partitions: npart=qmupart2npart(partition); - if isa(variables,'uniform_uncertain'), + if isa(variables,'uniform_uncertain') nlower=size(variables.lower,1); nupper=size(variables.upper,1); - if (nlower ~= npart || nupper ~=npart), + if (nlower ~= npart || nupper ~=npart) error('QmuSetupVariables error message: upper and lower fields should have the same number of rows as the number of partitions'); end - elseif isa(variables,'normal_uncertain'), + elseif isa(variables,'normal_uncertain') nstddev=size(variables.stddev,1); nmean=size(variables.mean,1); - if (nstddev ~= npart || nmean ~=npart), + if (nstddev ~= npart || nmean ~=npart) error('QmuSetupVariables error message: stddev and mean fields should have the same number of rows as the number of partitions'); end - elseif isa(variables,'continuous_design'), + elseif isa(variables,'continuous_design') nupper=size(variables.upper,1); nlower=size(variables.lower,1); - if (nupper ~= npart || nlower ~=npart), + if (nupper ~= npart || nlower ~=npart) error('QmuSetupVariables error message: upper and lower fields should have the same number of rows as the number of partitions'); end - elseif isa(variables,'histogram_bin_uncertain'), + elseif isa(variables,'histogram_bin_uncertain') ncounts=length(variables.counts); npairs=length(variables.pairs_per_variable); nabs=length(variables.abscissas); - if (ncounts ~= npart), + if (ncounts ~= npart) error(sprintf('QmuSetupVariables error message: counts size (%i) should be equal to the number of partitions (%i)',ncounts,npart)); end - if (npairs ~= npart), + if (npairs ~= npart) error(sprintf('QmuSetupVariables error message: pairs_per_variable size (%i) should be equal to the number of partitions (%i)',npairs,npart)); end - if (nabs ~= npart), + if (nabs ~= npart) error(sprintf('QmuSetupVariables error message: abscissas size (%i) should be equal to the number of partitions (%i)',nabs,npart)); end end %ok, dealing with distributed variable. Distribute according to how many %partitions we want. - for j=1:npart, + for j=1:npart dvar(end+1) =variables; dvar(end).descriptor=sprintf('%s_%d',variables.descriptor,j); - if isa(variables,'uniform_uncertain'), + if isa(variables,'uniform_uncertain') dvar(end ).lower=variables.lower(j); dvar(end ).upper=variables.upper(j); dvar(end ).partition=[]; - elseif isa(variables,'normal_uncertain'), + elseif isa(variables,'normal_uncertain') dvar(end ).stddev=variables.stddev(j); dvar(end ).mean=variables.mean(j); dvar(end ).partition=[]; - elseif isa(variables,'continuous_design'), + elseif isa(variables,'continuous_design') dvar(end ).upper=variables.upper(j); dvar(end ).lower=variables.lower(j); dvar(end ).initpt=variables.initpt(j); dvar(end ).partition=[]; - elseif isa(variables,'histogram_bin_uncertain'), + elseif isa(variables,'histogram_bin_uncertain') dvar(end).pairs_per_variable=variables.pairs_per_variable(j); dvar(end).abscissas=variables.abscissas{j}; dvar(end).counts=variables.counts{j}; diff --git a/src/m/shp/isshp.m b/src/m/shp/isshp.m index a1fb64a29..2f8aa12d7 100755 --- a/src/m/shp/isshp.m +++ b/src/m/shp/isshp.m @@ -7,7 +7,7 @@ % See also SHPREAD, SHPDOC [path,name,ext]=fileparts(filename); -if strcmpi(ext,'.shp'), +if strcmpi(ext,'.shp') bool=1; else bool=0; diff --git a/src/m/shp/projectedges.m b/src/m/shp/projectedges.m index 34522785a..65870d79a 100644 --- a/src/m/shp/projectedges.m +++ b/src/m/shp/projectedges.m @@ -1,10 +1,10 @@ function edges=projectedges(edges,shppath,epsg) %Gothrough edges (shapefiles), and project them in the epsg reference frame. -for i=1:length(edges)/3, +for i=1:length(edges)/3 shpname=[shppath '/' edges{3*(i-1)+1}]; shpepsg=edges{3*(i-1)+2}; - if shpepsg==epsg, + if shpepsg==epsg %do nothing; else %use CoordTransform to reproject the shp file: and give it another name. diff --git a/src/m/shp/shp2exp.m b/src/m/shp/shp2exp.m index 2b88e764e..ed434a5ef 100644 --- a/src/m/shp/shp2exp.m +++ b/src/m/shp/shp2exp.m @@ -11,23 +11,23 @@ function shp2exp(shpfilename,expfilename) %check file extensions [pathstr,name,ext] = fileparts(shpfilename); -if ~strcmp(ext,'.shp'), +if ~strcmp(ext,'.shp') error(['Shapefile ' shpfilename ' does not have an extension .shp']); end [pathstr,name,ext] = fileparts(expfilename); -if ~strcmp(ext,'.exp'), +if ~strcmp(ext,'.exp') error(['Exp file ' expfilename ' does not have an extension .exp']); end -if ~exist(shpfilename,'file'), +if ~exist(shpfilename,'file') error(['Shapefile ' shpfilename ' does not exist']); end shp=shaperead(shpfilename); expstruct=struct([]); -for i=1:length(shp), - if strcmpi(shp(i).Geometry,'Polygon'), +for i=1:length(shp) + if strcmpi(shp(i).Geometry,'Polygon') x=shp(i).X; y=shp(i).Y; ids=find(isnan(x)); x(ids)=[]; y(ids)=[]; @@ -36,16 +36,16 @@ function shp2exp(shpfilename,expfilename) expstruct(end).nods=length(x); expstruct(end).density=1; expstruct(end).closed=1; - if isfield(shp(i),'id'), + if isfield(shp(i),'id') expstruct(end).name=num2str(shp(i).id); - elseif isfield(shp(i),'NAME'), + elseif isfield(shp(i),'NAME') expstruct(end).name=num2str(shp(i).NAME); - elseif isfield(shp(i),'SUBREGION1'), + elseif isfield(shp(i),'SUBREGION1') expstruct(end).name=num2str(shp(i).SUBREGION1); else expstruct(end).name='unknown'; end - elseif strcmpi(shp(i).Geometry,'Point'), + elseif strcmpi(shp(i).Geometry,'Point') x=shp(i).X; y=shp(i).Y; if ~isnan(x) && ~isnan(y) expstruct(end+1).x=x; @@ -55,9 +55,9 @@ function shp2exp(shpfilename,expfilename) expstruct(end).closed=0; %exp(end).name=num2str(shp(i).id); end - elseif strcmpi(shp(i).Geometry,'PointZ'), + elseif strcmpi(shp(i).Geometry,'PointZ') shp(i) - elseif strcmpi(shp(i).Geometry,'Line'), + elseif strcmpi(shp(i).Geometry,'Line') x=shp(i).X(:); y=shp(i).Y(:); pos = find(~isnan(x) & ~isnan(y)); idx=find(diff(pos)~=1); diff --git a/src/m/shp/shp2js.m b/src/m/shp/shp2js.m index 0aebc86ed..3b500e967 100644 --- a/src/m/shp/shp2js.m +++ b/src/m/shp/shp2js.m @@ -5,7 +5,7 @@ function shp2js(jsname,shpname,domainname) fid=fopen(jsname,'w'); fprintf(fid,'var %s={}\n',domainname); - for i=1:length(shp), + for i=1:length(shp) fprintf(fid,'%s[%i]={}\n',domainname,i-1); @@ -16,13 +16,13 @@ function shp2js(jsname,shpname,domainname) fprintf(fid,'\n',domainname,i-1); fprintf(fid,'%s[%i][''x'']=[',domainname,i-1); - for j=1:nods-1, + for j=1:nods-1 fprintf(fid,'%g,',x(j)); end fprintf(fid,'%g];\n',x(end)); fprintf(fid,'%s[%i][''y'']=[',domainname,i-1); - for j=1:nods-1, + for j=1:nods-1 fprintf(fid,'%g,',y(j)); end fprintf(fid,'%g];\n',y(end)); diff --git a/src/m/shp/shpcoarsen.m b/src/m/shp/shpcoarsen.m index e828d2353..080b66e3a 100644 --- a/src/m/shp/shpcoarsen.m +++ b/src/m/shp/shpcoarsen.m @@ -15,7 +15,7 @@ function shpcoarsen(newfile,oldfile,resolution) error('shpcoarsen usage: shpcoarsen(newfile,oldfile,resolution)') elseif ~exist(oldfile) error(['shpcoarsen error message: the file ' oldfile ' does not exist']) -elseif exist(newfile), +elseif exist(newfile) %choice=input(['A file ' newfile ' already exists, do you want to modify it? (y/n)'],'s'); %if ~strcmpi(choice,'y'), % disp('no modification done ... exiting'); @@ -29,14 +29,14 @@ function shpcoarsen(newfile,oldfile,resolution) %Go through the profiles count=1; -while count<=numprofiles, +while count<=numprofiles %get number of points and initialize j numpoints=length(A(count).x); j=1; %stop if we have reached end of profile (always keep the last point) - while j=2, + if division>=2 x=linspace(A(count).x(j),A(count).x(j+1),division)'; y=linspace(A(count).y(j),A(count).y(j+1),division)'; A(count).x=[A(count).x(1:j);x(2:end-1); A(count).x(j+1:end)]; @@ -61,7 +61,7 @@ function shpcoarsen(newfile,oldfile,resolution) end end end - if length(A(count).x)<=1, + if length(A(count).x)<=1 A(count)=[]; numprofiles=numprofiles-1; else diff --git a/src/m/shp/shpconcat.m b/src/m/shp/shpconcat.m index 3cb8e815f..aaf7bb008 100644 --- a/src/m/shp/shpconcat.m +++ b/src/m/shp/shpconcat.m @@ -13,7 +13,7 @@ function shpconcat(domain,holes,filename) merged=domain; merged.Geometry='Polygon'; - for i=1:length(holes), + for i=1:length(holes) merged(end+1)=struct('x',holes(i).x,'y',holes(i).y,'Geometry','Polygon'); end diff --git a/src/m/shp/shpdisp.m b/src/m/shp/shpdisp.m index 5f73eb174..77fd7dc75 100644 --- a/src/m/shp/shpdisp.m +++ b/src/m/shp/shpdisp.m @@ -19,7 +19,7 @@ function shpdisp(domainoutline,varargin) end %parse input -if nargin<=1, +if nargin<=1 figurenumber=1; else figurenumber=varargin{1}; @@ -43,7 +43,7 @@ function shpdisp(domainoutline,varargin) domain=shpread(domainoutline); figure(figurenumber),hold on -for i=1:length(domain), +for i=1:length(domain) if(isfield(domain,'nods')) if (isnumeric(linestyle)) plot(domain(i).x*unitmultiplier,domain(i).y*unitmultiplier,'Color',linestyle,'linewidth',linewidth); diff --git a/src/m/shp/shpdisp3d.m b/src/m/shp/shpdisp3d.m index 30be4e8d2..9f5fe4e7c 100644 --- a/src/m/shp/shpdisp3d.m +++ b/src/m/shp/shpdisp3d.m @@ -27,18 +27,18 @@ function shpdisp3d(domainoutline,varargin) %read domain: domain=shpread(domainoutline); -if epsg~=4326, +if epsg~=4326 %transform to lat,long: - for i=1:length(domain), + for i=1:length(domain) [x,y] = CoordTransform(domain(i).x,domain(i).y,'EPSG:4326',sprintf('EPSG:%i',epsg)); domain(i).x=x; domain(i).y=y; end end -for i=1:length(domain), +for i=1:length(domain) %make sure lat,long are what they are supposed to be: - if any(domain(i).x>90 | domain(i).x<-90), + if any(domain(i).x>90 | domain(i).x<-90) long=domain(i).x; lat=domain(i).y; else long=domain(i).y; lat=domain(i).x; diff --git a/src/m/shp/shpread.m b/src/m/shp/shpread.m index 4898aaf09..c205a12e1 100644 --- a/src/m/shp/shpread.m +++ b/src/m/shp/shpread.m @@ -22,7 +22,7 @@ invert=getfieldvalue(options,'invert',0); %some checks -if ~exist(filename), +if ~exist(filename) error(['shpread error message: file ' filename ' not found!']); end @@ -31,8 +31,8 @@ Struct=struct([]); fields=fieldnames(shp); -for i=1:length(shp), - if strcmpi(shp(i).Geometry,'Point'), +for i=1:length(shp) + if strcmpi(shp(i).Geometry,'Point') x=shp(i).X'; y=shp(i).Y'; ids=find(isnan(x)); x(ids)=[]; y(ids)=[]; @@ -40,18 +40,18 @@ Struct(end+1).x=x; Struct(end).y=y; Struct(end).density=1; - if isfield(shp,'id'), + if isfield(shp,'id') Struct(end).name=num2str(shp(i).id); else Struct(end).name=''; end - for j=1:length(fields), + for j=1:length(fields) field=fields{j}; - if ~(strcmpi(field,'X') | strcmpi(field,'Y') | strcmpi(field,'id')), + if ~(strcmpi(field,'X') | strcmpi(field,'Y') | strcmpi(field,'id')) Struct(end).(field)=shp(i).(field); end end - elseif strcmpi(shp(i).Geometry,'Line'), + elseif strcmpi(shp(i).Geometry,'Line') x=shp(i).X'; y=shp(i).Y'; ids=find(isnan(x)); x(ids)=[]; y(ids)=[]; @@ -61,18 +61,18 @@ Struct(end).nods=length(x); Struct(end).density=1; Struct(end).closed=1; - if isfield(shp,'id'), + if isfield(shp,'id') Struct(end).name=num2str(shp(i).id); else Struct(end).name=''; end - for j=1:length(fields), + for j=1:length(fields) field=fields{j}; - if ~(strcmpi(field,'X') | strcmpi(field,'Y') | strcmpi(field,'id')), + if ~(strcmpi(field,'X') | strcmpi(field,'Y') | strcmpi(field,'id')) Struct(end).(field)=shp(i).(field); end end - elseif strcmpi(shp(i).Geometry,'Polygon'), + elseif strcmpi(shp(i).Geometry,'Polygon') x=shp(i).X'; y=shp(i).Y'; ids=find(isnan(x)); x(ids)=[]; y(ids)=[]; @@ -82,22 +82,22 @@ Struct(end).nods=length(x); Struct(end).density=1; Struct(end).closed=1; - if isfield(shp,'id'), + if isfield(shp,'id') Struct(end).name=num2str(shp(i).id); else Struct(end).name=''; end - for j=1:length(fields), + for j=1:length(fields) field=fields{j}; - if ~(strcmpi(field,'X') | strcmpi(field,'Y') | strcmpi(field,'id')), + if ~(strcmpi(field,'X') | strcmpi(field,'Y') | strcmpi(field,'id')) Struct(end).(field)=shp(i).(field); end end end end -if invert, - for i=1:length(Struct), +if invert + for i=1:length(Struct) Struct(i).x=flipud(Struct(i).x); Struct(i).y=flipud(Struct(i).y); end diff --git a/src/m/shp/shpwrite.m b/src/m/shp/shpwrite.m index e3246e504..f90acbc65 100644 --- a/src/m/shp/shpwrite.m +++ b/src/m/shp/shpwrite.m @@ -10,12 +10,12 @@ function shpwrite(shp,filename) % See also SHPREAD contours=struct([]); -for i=1:length(shp), - if strcmpi(shp(i).Geometry,'Point'), +for i=1:length(shp) + if strcmpi(shp(i).Geometry,'Point') contours(i).Geometry='Point'; - elseif strcmpi(shp(i).Geometry,'Polygon'), + elseif strcmpi(shp(i).Geometry,'Polygon') contours(i).Geometry='Polygon'; - elseif strcmpi(shp(i).Geometry,'Line'), + elseif strcmpi(shp(i).Geometry,'Line') contours(i).Geometry='Line'; else, error(['shpwrite error: geometry ' shp(i).Geometry ' not currently supported']); diff --git a/src/m/solve/BinRead.m b/src/m/solve/BinRead.m index 43f684b39..527e6a569 100644 --- a/src/m/solve/BinRead.m +++ b/src/m/solve/BinRead.m @@ -129,25 +129,25 @@ case FormatToCode('DoubleMat') %This routine takes the format string, and hardcodes it into an integer, which %is passed along the record, in order to identify the nature of the dataset being %sent. - if strcmpi(format,'Boolean'), + if strcmpi(format,'Boolean') code=1; - elseif strcmpi(format,'Integer'), + elseif strcmpi(format,'Integer') code=2; - elseif strcmpi(format,'Double'), + elseif strcmpi(format,'Double') code=3; - elseif strcmpi(format,'String'), + elseif strcmpi(format,'String') code=4; - elseif strcmpi(format,'BooleanMat'), + elseif strcmpi(format,'BooleanMat') code=5; - elseif strcmpi(format,'IntMat'), + elseif strcmpi(format,'IntMat') code=6; - elseif strcmpi(format,'DoubleMat'), + elseif strcmpi(format,'DoubleMat') code=7; - elseif strcmpi(format,'MatArray'), + elseif strcmpi(format,'MatArray') code=8; - elseif strcmpi(format,'StringArray'), + elseif strcmpi(format,'StringArray') code=9; - elseif strcmpi(format,'CompressedMat'), + elseif strcmpi(format,'CompressedMat') code=10; else error('FormatToCode error message: data type not supported yet!'); diff --git a/src/m/solve/WriteData.m b/src/m/solve/WriteData.m index e68a6648e..0f0275112 100644 --- a/src/m/solve/WriteData.m +++ b/src/m/solve/WriteData.m @@ -13,7 +13,7 @@ function WriteData(fid,prefix,varargin) fieldname = getfieldvalue(options,'fieldname'); classname = getfieldvalue(options,'class',class(obj)); name = getfieldvalue(options,'name',[prefix '.' fieldname ]); - if exist(options,'data'), + if exist(options,'data') data = getfieldvalue(options,'data'); else data = obj.(fieldname); @@ -34,15 +34,15 @@ function WriteData(fid,prefix,varargin) %Scale data if necessary if strcmpi(format,'MatArray') for i=1:numel(data) - if exist(options,'scale'), + if exist(options,'scale') scale = getfieldvalue(options,'scale'); - if size(data{i},1)==timeserieslength, + if size(data{i},1)==timeserieslength data{i}(1:end-1,:) = scale.*data{i}(1:end-1,:); else data{i} = scale.*data{i}; end end - if size(data{i},1)==timeserieslength, + if size(data{i},1)==timeserieslength yts = getfieldvalue(options,'yts'); data{i}(end,:) = data{i}(end,:)*yts; end @@ -50,7 +50,7 @@ function WriteData(fid,prefix,varargin) else if exist(options,'scale') scale = getfieldvalue(options,'scale'); - if size(data,1)==timeserieslength, + if size(data,1)==timeserieslength data(1:end-1,:) = scale.*data(1:end-1,:); else data = scale.*data; @@ -119,7 +119,7 @@ function WriteData(fid,prefix,varargin) %Get size s=size(data); %if matrix = NaN, then do not write anything - if (s(1)==1 & s(2)==1 & isnan(data)), + if (s(1)==1 & s(2)==1 & isnan(data)) s(1)=0; s(2)=0; end @@ -133,7 +133,7 @@ function WriteData(fid,prefix,varargin) %now write matrix fwrite(fid,s(1),'int'); fwrite(fid,s(2),'int'); - if s(1)*s(2), + if s(1)*s(2) fwrite(fid,data','double'); %get to the "c" convention, hence the transpose end % }}} @@ -142,7 +142,7 @@ function WriteData(fid,prefix,varargin) %Get size s=size(data); %if matrix = NaN, then do not write anything - if (s(1)==1 & s(2)==1 & isnan(data)), + if (s(1)==1 & s(2)==1 & isnan(data)) s(1)=0; s(2)=0; end @@ -156,7 +156,7 @@ function WriteData(fid,prefix,varargin) %now write matrix fwrite(fid,s(1),'int'); fwrite(fid,s(2),'int'); - if s(1)*s(2), + if s(1)*s(2) fwrite(fid,data','double'); %get to the "c" convention, hence the transpose end % }}} @@ -170,7 +170,7 @@ function WriteData(fid,prefix,varargin) end %if matrix = NaN, then do not write anything - if (s(1)==1 & s(2)==1 & isnan(data)), + if (s(1)==1 & s(2)==1 & isnan(data)) s(1)=0; s(2)=0; end @@ -186,7 +186,7 @@ function WriteData(fid,prefix,varargin) %now write matrix fwrite(fid,s(1),'int'); fwrite(fid,s(2),'int'); - if s(1)*s(2), + if s(1)*s(2) fwrite(fid,data','double'); %get to the "c" convention, hence the transpose end % }}} @@ -195,7 +195,7 @@ function WriteData(fid,prefix,varargin) %Get size s=size(data); - if (s(1)==1 & s(2)==1 & isnan(data)), + if (s(1)==1 & s(2)==1 & isnan(data)) s(1)=0; s(2)=0; end @@ -212,7 +212,7 @@ function WriteData(fid,prefix,varargin) fwrite(fid,s(1),'int'); fwrite(fid,s(2),'int'); - if s(1)*s(2), + if s(1)*s(2) %Write offset and range A = data(1:end-1,:); @@ -240,7 +240,7 @@ function WriteData(fid,prefix,varargin) %first get length of record recordlength=4+4; %number of records + code - for i=1:numrecords, + for i=1:numrecords matrix=data{i}; s=size(matrix); recordlength=recordlength+4*2+... %row and col of matrix @@ -257,7 +257,7 @@ function WriteData(fid,prefix,varargin) fwrite(fid,numrecords,'int'); %write each matrix: - for i=1:numrecords, + for i=1:numrecords matrix=data{i}; s=size(matrix); fwrite(fid,s(1),'int'); @@ -269,13 +269,13 @@ function WriteData(fid,prefix,varargin) %first get length of string array: num=numel(data); - if isnumeric(data) & num==1 & isnan(data), + if isnumeric(data) & num==1 & isnan(data) num = 0; end %now get length of record: recordlength=4+4; %for length of array + code - for i=1:num, + for i=1:num string=data{i}; recordlength=recordlength+4+length(string); %for each string end @@ -290,7 +290,7 @@ function WriteData(fid,prefix,varargin) fwrite(fid,num,'int'); %now write the strings - for i=1:num, + for i=1:num string=data{i}; fwrite(fid,length(string),'int'); fwrite(fid,string,'char'); @@ -305,25 +305,25 @@ function WriteData(fid,prefix,varargin) %This routine takes the format string, and hardcodes it into an integer, which %is passed along the record, in order to identify the nature of the dataset being %sent. - if strcmpi(format,'Boolean'), + if strcmpi(format,'Boolean') code=1; - elseif strcmpi(format,'Integer'), + elseif strcmpi(format,'Integer') code=2; - elseif strcmpi(format,'Double'), + elseif strcmpi(format,'Double') code=3; - elseif strcmpi(format,'String'), + elseif strcmpi(format,'String') code=4; - elseif strcmpi(format,'BooleanMat'), + elseif strcmpi(format,'BooleanMat') code=5; - elseif strcmpi(format,'IntMat'), + elseif strcmpi(format,'IntMat') code=6; - elseif strcmpi(format,'DoubleMat'), + elseif strcmpi(format,'DoubleMat') code=7; - elseif strcmpi(format,'MatArray'), + elseif strcmpi(format,'MatArray') code=8; - elseif strcmpi(format,'StringArray'), + elseif strcmpi(format,'StringArray') code=9; - elseif strcmpi(format,'CompressedMat'), + elseif strcmpi(format,'CompressedMat') code=10; else error('FormatToCode error message: data type not supported yet!'); diff --git a/src/m/solve/WriteData.py b/src/m/solve/WriteData.py index 7076a34eb..7072c1b20 100644 --- a/src/m/solve/WriteData.py +++ b/src/m/solve/WriteData.py @@ -39,7 +39,7 @@ def WriteData(fid, prefix, *args): # data = full(data) # end - # Make a copy of the the data so that we do not accidentally overwrite any + # Make a copy of the data so that we do not accidentally overwrite any # model fields. # data = copy(data) diff --git a/src/m/solve/convert2str.m b/src/m/solve/convert2str.m index 48429618f..83c1da31d 100644 --- a/src/m/solve/convert2str.m +++ b/src/m/solve/convert2str.m @@ -7,7 +7,7 @@ function str = parsedisplay(field) % {{{ %string - if ischar(field), + if ischar(field) if length(field)>30; %str = displayunit('not displayed'); @@ -17,11 +17,11 @@ end %cell - elseif iscell(field), + elseif iscell(field) str = cell_display(field), %structure - elseif isstruct(field), + elseif isstruct(field) str = struct_display(field), %numeric @@ -31,7 +31,7 @@ fieldsize=size(field); %double - if max(fieldsize)==1, + if max(fieldsize)==1 str = displayunit(num2str(field)), %matrix else @@ -45,7 +45,7 @@ fieldsize=size(field); %single value - if max(fieldsize)==1, + if max(fieldsize)==1 if (field) str = displayunit('true'); else @@ -67,10 +67,10 @@ function str = displayunit(characterization)% {{{ %take care of characterization - if (strcmp(characterization,['''' '''']) || strcmp(characterization,'NaN')), + if (strcmp(characterization,['''' '''']) || strcmp(characterization,'NaN')) characterization='N/A'; end - if length(characterization)>15, + if length(characterization)>15 characterization=[characterization(1:12) '...']; end @@ -85,8 +85,8 @@ %go through the cell and fill string if length(field)<5; - for i=1:length(field), - if ischar(field{i}), + for i=1:length(field) + if ischar(field{i}) string=[string '''' field{i} ''',']; elseif (isnumeric(field{i}) & length(field{i})==1) string=[string num2str(field{i}) ',' ]; @@ -96,7 +96,7 @@ end end end - if strcmp(string,'{'), + if strcmp(string,'{') string=['(' num2str(size(field,1)) 'x' num2str(size(field,2)) ')']; else string=[string(1:end-1) '}']; @@ -113,7 +113,7 @@ structure_fields=fieldnames(field); - for i=1:length(structure_fields), + for i=1:length(structure_fields) %get current field sfield=field.(structure_fields{i}); diff --git a/src/m/solve/listoutputs.m b/src/m/solve/listoutputs.m index 1721d0903..a99b88200 100644 --- a/src/m/solve/listoutputs.m +++ b/src/m/solve/listoutputs.m @@ -51,6 +51,7 @@ BasalforcingsIsmip6Tf BasalforcingsIsmip6TfShelf BasalforcingsIsmip6MeltAnomaly +BasalforcingsIsmip7BasinId BasalforcingsIsmip7Tf BasalforcingsIsmip7TfShelf BasalforcingsIsmip7Salinity @@ -448,7 +449,10 @@ SmbHSnowInit SmbHref SmbIsInitialized +SmbLat +SmbLon SmbMAdd +SmbMappedforcingneighbors SmbMappedforcingpoint SmbMappedforcingprecipscaling SmbMassBalance @@ -457,12 +461,16 @@ SmbMassBalanceSubstep SmbMassBalanceTransient SmbMask +SmbMaxX +SmbMaxY SmbMeanLHF SmbMeanSHF SmbMeanULW SmbMeanTemperature SmbMelt SmbMeltSubstep +SmbMinX +SmbMinY SmbMonthlytemperatures SmbMonthlydsradiation SmbMonthlydlradiation @@ -479,6 +487,7 @@ SmbPrecipitation SmbPrecipitationSubstep SmbPrecipitationsAnomaly +SmbQinterp SmbDsradiationAnomaly SmbDlradiationAnomaly SmbWindspeedAnomaly @@ -535,6 +544,17 @@ SmbZMin SmbZTop SmbZY +MariaSmb +MariaElev +MariaAl +MariaSt +MariaTt +MariaSwd +MariaLwd +MariaSwu +MariaLwu +MariaShf +MariaLhf SolidearthExternalDisplacementEastRate SolidearthExternalDisplacementNorthRate SolidearthExternalDisplacementUpRate diff --git a/src/m/solve/loadmultipleresultsfromcluster.m b/src/m/solve/loadmultipleresultsfromcluster.m index 1de64cc14..75ea09ee0 100644 --- a/src/m/solve/loadmultipleresultsfromcluster.m +++ b/src/m/solve/loadmultipleresultsfromcluster.m @@ -23,7 +23,7 @@ !tar -zxvf ModelResults.tar.gz %ok, go through list and load results from disk: -for i=1:nummodels, +for i=1:nummodels %load results for this model md_list{i}=loadresultsfromdisk(md_list{i},[md_list{i}.name '.outbin']); diff --git a/src/m/solve/loadresultfromdisk.m b/src/m/solve/loadresultfromdisk.m index 5dcce7254..a944f53fe 100644 --- a/src/m/solve/loadresultfromdisk.m +++ b/src/m/solve/loadresultfromdisk.m @@ -10,19 +10,19 @@ error(['loadresultsfromdisk error message: could not open ',filename,' for binary reading']); end - if nargin==4, + if nargin==4 %Put the pointer on the right position in the file: fpos=varargin{1}; fseek(fid,fpos,'bof'); end - while 1, + while 1 %read field fpos=ftell(fid); [length,count]=fread(fid,1,'int'); - if count==0, + if count==0 break; %we are done, break; else @@ -33,22 +33,22 @@ rstep=fread(fid,1,'int'); %check on field: - if ((step==rstep) & (strcmpi(name,fieldname))), + if ((step==rstep) & (strcmpi(name,fieldname))) %ok, go read the result really: type=fread(fid,1,'int'); M=fread(fid,1,'int'); - if type==1, + if type==1 field=fread(fid,M,'double'); - elseif type==2, + elseif type==2 field=fread(fid,M,'char'); field=char(field(1:end-1)'); - elseif type==3, + elseif type==3 N=fread(fid,1,'int'); field=fread(fid,[N M],'double')'; - elseif type==4, + elseif type==4 N=fread(fid,1,'int'); field=fread(fid,[N M],'int')'; - elseif type==5, + elseif type==5 N=fread(fid,1,'int'); fieldr=fread(fid,[N M],'double')'; fieldi=fread(fid,[N M],'double')'; @@ -62,14 +62,14 @@ %just skim to next results. type=fread(fid,1,'int'); M=fread(fid,1,'int'); - if type==1, + if type==1 fseek(fid,8*M,'cof'); - elseif type==2, + elseif type==2 fseek(fid,M,'cof'); - elseif type==3, + elseif type==3 N=fread(fid,1,'int'); fseek(fid,M*N*8,'cof'); - elseif type==4, + elseif type==4 N=fread(fid,1,'int'); fseek(fid,M*N*4,cof); else diff --git a/src/m/solve/loadresultsfromcluster.m b/src/m/solve/loadresultsfromcluster.m index 2376bbe7b..0283a3a0e 100644 --- a/src/m/solve/loadresultsfromcluster.m +++ b/src/m/solve/loadresultsfromcluster.m @@ -10,8 +10,8 @@ % md=loadresultsfromcluster(md,'runtimename','test101-06-15-2021-13-24-18-4883'); %process options: -options=pairoptions(varargin{:}); -nolog=getfieldvalue(options,'nolog',0); +options = pairoptions(varargin{:}); +nolog = getfieldvalue(options,'nolog',0); md.private.runtimename = getfieldvalue(options,'runtimename',md.private.runtimename); %retrieve cluster, to be able to call its methods @@ -26,19 +26,17 @@ if md.qmu.isdakota filelist{end+1}=[md.miscellaneous.name '.qmu.err']; filelist{end+1}=[md.miscellaneous.name '.qmu.out']; - if isfield(md.qmu.params,'tabular_graphics_data'), - if md.qmu.params.tabular_graphics_data==true, - filelist{end+1}='dakota_tabular.dat'; - end + if isfield(md.qmu.params,'tabular_graphics_data') + filelist{end+1}='dakota_tabular.dat'; end - if md.qmu.output & strcmpi(md.qmu.statistics.method(1).name,'None'), - if strcmpi(md.qmu.method.method,'nond_sampling'), + if md.qmu.output & strcmpi(md.qmu.statistics.method(1).name,'None') + if strcmpi(md.qmu.method.method,'nond_sampling') for i=1:md.qmu.method.params.samples filelist{end+1}=[md.miscellaneous.name '.outbin.' num2str(i)]; end end end - if ~strcmpi(md.qmu.statistics.method(1).name,'None'), + if ~strcmpi(md.qmu.statistics.method(1).name,'None') filelist{end+1}=[md.miscellaneous.name '.stats']; end else @@ -56,21 +54,3 @@ delete(filename) end end -if exist([md.private.runtimename '.tar.gz']) & ~ispc() - delete([md.private.runtimename '.tar.gz']); -end - -%erase input file if run was carried out on same platform. -hostname=oshostname(); -if strcmpi(hostname,cluster.name), - delete([md.miscellaneous.name '.bin']); - delete([md.miscellaneous.name '.toolkits']); - if md.qmu.isdakota - delete([md.miscellaneous.name '.qmu.in']); - end - if ~ispc() - delete([md.miscellaneous.name '.queue']); - else - delete([md.miscellaneous.name '.bat']); - end -end diff --git a/src/m/solve/loadresultsfromcluster.py b/src/m/solve/loadresultsfromcluster.py index 71f552614..f042b3d88 100644 --- a/src/m/solve/loadresultsfromcluster.py +++ b/src/m/solve/loadresultsfromcluster.py @@ -6,7 +6,6 @@ from MatlabFuncs import * from pairoptions import pairoptions - def remove(filename): #{{{ try: os.remove(filename) @@ -14,7 +13,6 @@ def remove(filename): #{{{ print(('WARNING: ' + filename + ' does not exist')) # }}} - def loadresultsfromcluster(md, *args): #{{{ """loadresultsfromcluster - load results of solution sequence from cluster @@ -64,20 +62,6 @@ def loadresultsfromcluster(md, *args): #{{{ for i in range(len(filelist)): filename = filelist[i] remove(filename) - if not ispc(): - remove(md.private.runtimename + '.tar.gz') - - # Erase input file if run was carried out on same platform - hostname = oshostname() - if hostname == cluster.name: - remove(md.miscellaneous.name + '.bin') - remove(md.miscellaneous.name + '.toolkits') - if md.qmu.isdakota: - remove(md.miscellaneous.name + '.qmu.in') - if not ispc(): - remove(md.miscellaneous.name + '.queue') - else: - remove(md.miscellaneous.name + '.bat') return md # }}} diff --git a/src/m/solve/loadresultsfromclusterslm.m b/src/m/solve/loadresultsfromclusterslm.m index 9b72e1991..08e66d48b 100644 --- a/src/m/solve/loadresultsfromclusterslm.m +++ b/src/m/solve/loadresultsfromclusterslm.m @@ -8,7 +8,7 @@ % slm=loadresultsfromclusterslm(slm); %go through icecaps and download results - for i=1:length(slm.icecaps), + for i=1:length(slm.icecaps) slm.icecaps{i}=loadresultsfromcluster(slm.icecaps{i},'nolog',1); end slm.earth=loadresultsfromcluster(slm.earth,'nolog',1); diff --git a/src/m/solve/loadresultsfromdisk.m b/src/m/solve/loadresultsfromdisk.m index a90a5a8df..32e5b0482 100644 --- a/src/m/solve/loadresultsfromdisk.m +++ b/src/m/solve/loadresultsfromdisk.m @@ -12,7 +12,7 @@ % md the returned model() object with the results loaded into md.results %check number of inputs/outputs -if ((nargin~=2) | (nargout~=1)), +if ((nargin~=2) | (nargout~=1)) help loadresultsfromdisk; error('loadresultsfromdisk: nargin and nargout strictly enforced. See ''Useage'' above.'); end @@ -41,7 +41,7 @@ if isempty(fieldnames(structure)) error(['No result found in binary file ' filename '. Check for solution crash.']); end - if isempty(structure(1).SolutionType), + if isempty(structure(1).SolutionType) if ~isempty(structure(end).SolutionType) structure(1).SolutionType=structure(end).SolutionType; else diff --git a/src/m/solve/marshall.m b/src/m/solve/marshall.m index d7518aaf4..63372abfa 100644 --- a/src/m/solve/marshall.m +++ b/src/m/solve/marshall.m @@ -22,7 +22,7 @@ function marshall(md, filename) field=fields{i}; %Some properties do not need to be marshalled - if ismember(field,{'results' 'radaroverlay' 'toolkits' 'cluster' 'private'}), + if ismember(field,{'results' 'radaroverlay' 'toolkits' 'cluster' 'private'}) continue; end diff --git a/src/m/solve/outbinread.m b/src/m/solve/outbinread.m index 83d268c1a..3515d5421 100644 --- a/src/m/solve/outbinread.m +++ b/src/m/solve/outbinread.m @@ -7,7 +7,7 @@ % Example: % results = outbinread(md,'dir/test.outbin',1:10) -if ~exist(filename,'file'), +if ~exist(filename,'file') error(['Binary file ' filename ' not found']); end @@ -26,11 +26,11 @@ check_nomoresteps=0; counter = 1; step = result.step; -while ~isempty(result), +while ~isempty(result) - if check_nomoresteps, + if check_nomoresteps %check that the new result does not add a step, which would be an error: - if result.step>=1, + if result.step>=1 error('parsing results for a steady-state core, which incorporates transient results!'); end end @@ -52,7 +52,7 @@ index = counter; end pos=find(result.step==steps); - if ~isempty(pos), + if ~isempty(pos) results(pos).(result.fieldname)=result.field; if(result.step~=-9999), results(pos).step=result.step; @@ -61,7 +61,7 @@ results(pos).time=result.time; end end - if result.step>max(steps(:)), + if result.step>max(steps(:)) %we are done! return; end @@ -83,7 +83,7 @@ %read field [length,count]=fread(fid,1,'int'); -if count==0, +if count==0 result=struct([]); else fieldname=fread(fid,length,'char'); @@ -94,12 +94,12 @@ type=fread(fid,1,'int'); M=fread(fid,1,'int'); - if type==1, + if type==1 field=fread(fid,M,'double'); - elseif type==2, + elseif type==2 field=fread(fid,M,'char'); field=char(field(1:end-1)'); - elseif type==3, + elseif type==3 N=fread(fid,1,'int'); field=transpose(fread(fid,[N M],'double')); else @@ -108,53 +108,53 @@ %Process units here FIXME: this should not be done here! yts=md.constants.yts; - if strcmp(fieldname,'BalancethicknessThickeningRate'), + if strcmp(fieldname,'BalancethicknessThickeningRate') field = field*yts; - elseif strcmp(fieldname,'HydrologyWaterVx'), + elseif strcmp(fieldname,'HydrologyWaterVx') field = field*yts; - elseif strcmp(fieldname,'HydrologyWaterVy'), + elseif strcmp(fieldname,'HydrologyWaterVy') field = field*yts; - elseif strcmp(fieldname,'Vx'), + elseif strcmp(fieldname,'Vx') field = field*yts; - elseif strcmp(fieldname,'Vy'), + elseif strcmp(fieldname,'Vy') field = field*yts; - elseif strcmp(fieldname,'Vz'), + elseif strcmp(fieldname,'Vz') field = field*yts; - elseif strcmp(fieldname,'Vel'), + elseif strcmp(fieldname,'Vel') field = field*yts; - elseif strcmp(fieldname,'BasalforcingsGroundediceMeltingRate'), + elseif strcmp(fieldname,'BasalforcingsGroundediceMeltingRate') field = field*yts; - elseif strcmp(fieldname,'BasalforcingsFloatingiceMeltingRate'), + elseif strcmp(fieldname,'BasalforcingsFloatingiceMeltingRate') field = field*yts; - elseif strcmp(fieldname,'TotalFloatingBmb'), + elseif strcmp(fieldname,'TotalFloatingBmb') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalGroundedBmb'), + elseif strcmp(fieldname,'TotalGroundedBmb') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalSmb'), + elseif strcmp(fieldname,'TotalSmb') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalMelt'), + elseif strcmp(fieldname,'TotalMelt') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalRefreeze'), + elseif strcmp(fieldname,'TotalRefreeze') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'SmbMassBalance'), + elseif strcmp(fieldname,'SmbMassBalance') field = field*yts; - elseif strcmp(fieldname,'SmbPrecipitation'), + elseif strcmp(fieldname,'SmbPrecipitation') field = field*yts; - elseif strcmp(fieldname,'SmbRunoff'), + elseif strcmp(fieldname,'SmbRunoff') field = field*yts; - elseif strcmp(fieldname,'SmbCondensation'), + elseif strcmp(fieldname,'SmbCondensation') field = field*yts; - elseif strcmp(fieldname,'SmbAccumulation'), + elseif strcmp(fieldname,'SmbAccumulation') field = field*yts; - elseif strcmp(fieldname,'SmbMelt'), + elseif strcmp(fieldname,'SmbMelt') field = field*yts; - elseif strcmp(fieldname,'CalvingCalvingrate'), + elseif strcmp(fieldname,'CalvingCalvingrate') field = field*yts; end result.fieldname=fieldname; result.time=time; - if result.time~=-9999, + if result.time~=-9999 result.time=time/yts; end result.step=step; diff --git a/src/m/solve/parseresultsfromdisk.m b/src/m/solve/parseresultsfromdisk.m index 67b84309e..e182f7dce 100644 --- a/src/m/solve/parseresultsfromdisk.m +++ b/src/m/solve/parseresultsfromdisk.m @@ -1,6 +1,6 @@ function results=parseresultsfromdisk(md,filename,iosplit) % {{{ -if iosplit, +if iosplit results=parseresultsfromdiskiosplit(md,filename); else results=parseresultsfromdiskioserial(md,filename); @@ -19,11 +19,11 @@ %if we have done split I/O, ie, we have results that are fragmented across patches, %do a first pass, and figure out the structure of results result=ReadDataDimensions(fid); -while ~isempty(result), +while ~isempty(result) %Get time and step results(result.step).step=result.step; - if result.time~=-9999, + if result.time~=-9999 results(result.step).time=result.time; end @@ -37,7 +37,7 @@ %do a second pass, and figure out the size of the patches fseek(fid,0,-1); %rewind result=ReadDataDimensions(fid); -while ~isempty(result), +while ~isempty(result) %read next result result=ReadDataDimensions(fid); end @@ -45,11 +45,11 @@ %third pass, this time to read the real information fseek(fid,0,-1); %rewind result=ReadData(fid,md); -while ~isempty(result), +while ~isempty(result) %Get time and step results(result.step).step=result.step; - if result.time~=-9999, + if result.time~=-9999 results(result.step).time=result.time; end @@ -91,7 +91,7 @@ end %Have we reached the end of the file? - if isempty(result), + if isempty(result) if counter==1 error(['no results found in binary file ' filename]); else @@ -139,12 +139,12 @@ %first pass to figure out the steps we have: steps=[]; -while 1, +while 1 result = ReadDataDimensions(fid); - if isempty(result), + if isempty(result) break; end - if result.step~=-9999, + if result.step~=-9999 steps=[steps result.step]; end end @@ -156,18 +156,18 @@ %second pass to fill the steps we have: fseek(fid,0,-1); %rewind -while 1, +while 1 result = ReadData(fid,md); - if isempty(result), + if isempty(result) break; end - if result.step==-9999, + if result.step==-9999 result.step=1; result.time=0; end %find where we are putting this step: ind=find(steps==result.step); - if isempty(ind), + if isempty(ind) error('could not find a step in our pre-structure! Something is very off!'); end @@ -182,7 +182,7 @@ %read field [length,count]=fread(fid,1,'int'); -if count==0, +if count==0 result=struct([]); else fieldname=fread(fid,length,'char'); @@ -193,15 +193,15 @@ type=fread(fid,1,'int'); M=fread(fid,1,'int'); - if type==1, + if type==1 field=fread(fid,M,'double'); - elseif type==2, + elseif type==2 field=fread(fid,M,'char'); field=char(field(1:end-1)'); - elseif type==3, + elseif type==3 N=fread(fid,1,'int'); field=fread(fid,[N M],'double')'; - elseif type==4, + elseif type==4 N=fread(fid,1,'int'); field=fread(fid,[N M],'int')'; else @@ -210,103 +210,103 @@ %Process units here FIXME: this should not be done here! yts=md.constants.yts; - if strcmp(fieldname,'BalancethicknessThickeningRate'), + if strcmp(fieldname,'BalancethicknessThickeningRate') field = field*yts; - elseif strcmp(fieldname,'HydrologyWaterVx'), + elseif strcmp(fieldname,'HydrologyWaterVx') field = field*yts; - elseif strcmp(fieldname,'HydrologyWaterVy'), + elseif strcmp(fieldname,'HydrologyWaterVy') field = field*yts; - elseif strcmp(fieldname,'Vx'), + elseif strcmp(fieldname,'Vx') field = field*yts; - elseif strcmp(fieldname,'Vy'), + elseif strcmp(fieldname,'Vy') field = field*yts; - elseif strcmp(fieldname,'Vz'), + elseif strcmp(fieldname,'Vz') field = field*yts; - elseif strcmp(fieldname,'Vel'), + elseif strcmp(fieldname,'Vel') field = field*yts; - elseif strcmp(fieldname,'VxShear'), + elseif strcmp(fieldname,'VxShear') field = field*yts; - elseif strcmp(fieldname,'VyShear'), + elseif strcmp(fieldname,'VyShear') field = field*yts; - elseif strcmp(fieldname,'VxBase'), + elseif strcmp(fieldname,'VxBase') field = field*yts; - elseif strcmp(fieldname,'VyBase'), + elseif strcmp(fieldname,'VyBase') field = field*yts; - elseif strcmp(fieldname,'VxSurface'), + elseif strcmp(fieldname,'VxSurface') field = field*yts; - elseif strcmp(fieldname,'VySurface'), + elseif strcmp(fieldname,'VySurface') field = field*yts; - elseif strcmp(fieldname,'VxAverage'), + elseif strcmp(fieldname,'VxAverage') field = field*yts; - elseif strcmp(fieldname,'VyAverage'), + elseif strcmp(fieldname,'VyAverage') field = field*yts; - elseif strcmp(fieldname,'VxDebris'), + elseif strcmp(fieldname,'VxDebris') field = field*yts; - elseif strcmp(fieldname,'VyDebris'), + elseif strcmp(fieldname,'VyDebris') field = field*yts; - elseif strcmp(fieldname,'BasalforcingsGroundediceMeltingRate'), + elseif strcmp(fieldname,'BasalforcingsGroundediceMeltingRate') field = field*yts; - elseif strcmp(fieldname,'BasalforcingsFloatingiceMeltingRate'), + elseif strcmp(fieldname,'BasalforcingsFloatingiceMeltingRate') field = field*yts; - elseif strcmp(fieldname,'BasalforcingsSpatialDeepwaterMeltingRate'), + elseif strcmp(fieldname,'BasalforcingsSpatialDeepwaterMeltingRate') field = field*yts; - elseif strcmp(fieldname,'BasalforcingsSpatialUpperwaterMeltingRate'), + elseif strcmp(fieldname,'BasalforcingsSpatialUpperwaterMeltingRate') field = field*yts; - elseif strcmp(fieldname,'TotalFloatingBmb'), + elseif strcmp(fieldname,'TotalFloatingBmb') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalFloatingBmbScaled'), + elseif strcmp(fieldname,'TotalFloatingBmbScaled') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalGroundedBmb'), + elseif strcmp(fieldname,'TotalGroundedBmb') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalGroundedBmbScaled'), + elseif strcmp(fieldname,'TotalGroundedBmbScaled') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalSmb'), + elseif strcmp(fieldname,'TotalSmb') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalSmbScaled'), + elseif strcmp(fieldname,'TotalSmbScaled') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalSmbMelt'), + elseif strcmp(fieldname,'TotalSmbMelt') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'TotalSmbRefreeze'), + elseif strcmp(fieldname,'TotalSmbRefreeze') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'GroundinglineMassFlux'), + elseif strcmp(fieldname,'GroundinglineMassFlux') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'IcefrontMassFlux'), + elseif strcmp(fieldname,'IcefrontMassFlux') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'IcefrontMassFluxLevelset'), + elseif strcmp(fieldname,'IcefrontMassFluxLevelset') field = field/10.^12*yts; %(GigaTon/year) - elseif strcmp(fieldname,'SmbMassBalance'), - field = field*yts; - elseif strcmp(fieldname,'SmbPrecipitation'), + elseif strcmp(fieldname,'TotalHydrologyBasalFlux') + field = field/10.^12*yts; %(GigaTon/year) + elseif strcmp(fieldname,'SmbMassBalance') field = field*yts; - elseif strcmp(fieldname,'SmbRain'), + elseif strcmp(fieldname,'SmbPrecipitation') field = field*yts; - elseif strcmp(fieldname,'SmbRunoff'), + elseif strcmp(fieldname,'SmbRain') field = field*yts; - elseif strcmp(fieldname,'SmbRunoffSubstep'), + elseif strcmp(fieldname,'SmbRunoff') field = field*yts; - elseif strcmp(fieldname,'SmbEvaporation'), + elseif strcmp(fieldname,'SmbRunoffSubstep') field = field*yts; - elseif strcmp(fieldname,'SmbRefreeze'), + elseif strcmp(fieldname,'SmbEvaporation') field = field*yts; - elseif strcmp(fieldname,'SmbEC'), + elseif strcmp(fieldname,'SmbRefreeze') field = field*yts; - elseif strcmp(fieldname,'SmbAccumulation'), + elseif strcmp(fieldname,'SmbEC') field = field*yts; - elseif strcmp(fieldname,'SmbMelt'), + elseif strcmp(fieldname,'SmbAccumulation') field = field*yts; - elseif strcmp(fieldname,'SmbMAdd'), + elseif strcmp(fieldname,'SmbMelt') field = field*yts; - elseif strcmp(fieldname,'SmbWAdd'), + elseif strcmp(fieldname,'SmbMAdd') field = field*yts; - elseif strcmp(fieldname,'CalvingCalvingrate'), + elseif strcmp(fieldname,'SmbWAdd') field = field*yts; - elseif strcmp(fieldname,'Calvingratex'), + elseif strcmp(fieldname,'CalvingCalvingrate') field = field*yts; - elseif strcmp(fieldname,'Calvingratey'), + elseif strncmp(fieldname,'Calvingrate',11) field = field*yts; - elseif strcmp(fieldname,'CalvingMeltingrate'), + elseif strcmp(fieldname,'CalvingMeltingrate') field = field*yts; - elseif (strcmp(fieldname,'LoveKernelsReal') | strcmp(fieldname,'LoveKernelsImag')), + elseif (strcmp(fieldname,'LoveKernelsReal') | strcmp(fieldname,'LoveKernelsImag')) nlayer = md.materials.numlayers; degmax = md.love.sh_nmax; nfreq = md.love.nfreq; @@ -349,7 +349,7 @@ field=temp_field; end - if time~=-9999, + if time~=-9999 time=time/yts; end @@ -368,7 +368,7 @@ %read field [length,count]=fread(fid,1,'int'); -if count==0, +if count==0 result=struct([]); else fieldname=fread(fid,length,'char'); @@ -380,11 +380,11 @@ type=fread(fid,1,'int'); M=fread(fid,1,'int'); N=1; %default - if type==1, + if type==1 fseek(fid,M*8,0); - elseif type==2, + elseif type==2 fseek(fid,M,0); - elseif type==3, + elseif type==3 N=fread(fid,1,'int'); fseek(fid,N*M*8,0); else diff --git a/src/m/solve/parseresultsfromdisk.py b/src/m/solve/parseresultsfromdisk.py index fe3b5ba25..764431dc8 100644 --- a/src/m/solve/parseresultsfromdisk.py +++ b/src/m/solve/parseresultsfromdisk.py @@ -225,6 +225,8 @@ def ReadData(fid, md): # {{{ field = field / pow(10.0, 12) * yts # (GigaTon/year) elif fieldname == 'IcefrontMassFluxLevelset': field = field / pow(10.0, 12) * yts # (GigaTon/year) + elif fieldname == 'TotalHydrologyBasalFlux': + field = field / pow(10.0, 12) * yts # (GigaTon/year) elif fieldname == 'SmbMassBalance': field = field * yts elif fieldname == 'SmbPrecipitation': diff --git a/src/m/solve/retrievesamples.m b/src/m/solve/retrievesamples.m index c540776ec..cf339b0f8 100644 --- a/src/m/solve/retrievesamples.m +++ b/src/m/solve/retrievesamples.m @@ -8,12 +8,12 @@ step=getfieldvalue(options,'step'); fields=getfieldvalue(options,'fields'); - if ~isa(fields,'cell'), + if ~isa(fields,'cell') error('retrievesamples error message: ''fields'' should be a cell array of field names'); end nout=length(fields); - for n=1:nout, + for n=1:nout field=fields{n}; [sample,fpos]=loadresultfromdisk(sprintf('%s/%s.outbin.%i',directory,name,1),step,field); @@ -23,7 +23,7 @@ samples=zeros(nv,nsamples); samples(:,1)=sample; - for i=2:nsamples, + for i=2:nsamples if mod(i,10)==0, disp(i/nsamples*100); end samples(:,i)=loadresultfromdisk(sprintf('%s/%s.outbin.%i',directory,name,i),step,field,fpos); end diff --git a/src/m/solve/solve.m b/src/m/solve/solve.m index 4312e35ca..e3606c0a8 100644 --- a/src/m/solve/solve.m +++ b/src/m/solve/solve.m @@ -29,6 +29,7 @@ % Extra options: % - loadonly : do not solve, only load results % - runtimename : true or false (default is true); makes name unique +% - batch : create input files but do not submit job % - checkconsistency : 'yes' or 'no' (default is 'yes'); checks consistency of model % - restart : directory name (relative to the execution directory) % where the restart file is located @@ -121,34 +122,59 @@ ismodelselfconsistent(md); end -%if running QMU analysis, some preprocessing of Dakota files using model fields needs to be carried out. +%Prepare directory in execution +if strcmpi(cluster.name, oshostname()) + localexecdir = cluster.executionpath; +else + localexecdir = [issmdir() '/execution/']; +end +if ~exist(localexecdir, 'dir') + error(['Could not find directory ' issmdir() '/execution/']); +elseif numel(dir(localexecdir))>200 + warning([localexecdir ' has more than 200 subdirectories. Consider cleaning up your execution directory']) +end +root = [localexecdir '/' md.private.runtimename]; +if exist(root, 'dir') + rmdir(root, 's'); +end +mkdir(root); + +%Figure out executable +executable = 'issm.exe'; if md.qmu.isdakota md=preqmu(md,options); + movefile([md.miscellaneous.name '.qmu.in'], [root '/' md.miscellaneous.name '.qmu.in']); + dakota_version_str = IssmConfig('_DAKOTA_VERSION_'); dakota_ver = str2num(dakota_version_str(1:3)); + if(dakota_ver >= 6), executable = 'issm_dakota.exe'; end end -%Prepare directory in execution - %Write all input files -marshall(md, [md.miscellaneous.name '.bin']); % bin file -ToolkitsFile(md.toolkits,[md.miscellaneous.name '.toolkits']); % toolkits file -BuildQueueScript(cluster, md, [md.miscellaneous.name '.queue']); % queue file +basename = [root '/' md.miscellaneous.name]; +marshall(md, [basename '.bin']); % bin file +ToolkitsFile(md.toolkits, [basename '.toolkits']); % toolkits file +BuildQueueScript(cluster, md, [basename '.queue'], executable);% queue file -%Upload all required files -modelname = md.miscellaneous.name; -filelist = {[modelname '.bin'] [modelname '.toolkits']}; +%List all required files +filelist = {[basename '.bin'] [basename '.toolkits']}; if ispc - filelist{end+1}=[modelname '.bat']; + filelist{end+1} = [basename '.bat']; else - filelist{end+1}=[modelname '.queue']; + filelist{end+1} = [basename '.queue']; end - -if md.qmu.isdakota, - filelist{end+1} = [modelname '.qmu.in']; +if md.qmu.isdakota + filelist{end+1} = [basename '.qmu.in']; +end +if isprop(cluster, 'interactive') && cluster.interactive + fid=fopen([basename '.errlog'],'w'); fclose(fid); + fid=fopen([basename '.outlog'],'w'); fclose(fid); + filelist{end+1} = [basename '.outlog']; + filelist{end+1} = [basename '.errlog']; end -if isempty(restart) - disp('uploading input files') - UploadQueueJob(cluster,md.miscellaneous.name,md.private.runtimename,filelist); +%Upload input files if necessary +if isempty(restart) && ~strcmpi(cluster.name, oshostname()) + disp('uploading input files') + UploadQueueJob(cluster, md.miscellaneous.name, md.private.runtimename, filelist); end %launch queue job: diff --git a/src/m/solve/solve.py b/src/m/solve/solve.py index 95951db19..d76333cf5 100644 --- a/src/m/solve/solve.py +++ b/src/m/solve/solve.py @@ -1,7 +1,11 @@ from datetime import datetime import os +import shutil +import warnings +from IssmConfig import IssmConfig from ismodelselfconsistent import ismodelselfconsistent +from issmdir import issmdir from loadresultsfromcluster import loadresultsfromcluster from marshall import marshall from pairoptions import pairoptions @@ -39,6 +43,7 @@ def solve(md, solutionstring, *args): Extra options: - loadonly : do not solve, only load results - runtimename : true or false (default is true); makes name unique +% - batch : create input files but do not submit job - checkconsistency : 'yes' or 'no' (default is 'yes'); checks consistency of model - restart : directory name (relative to the execution directory) @@ -119,30 +124,53 @@ def solve(md, solutionstring, *args): print('checking model consistency') ismodelselfconsistent(md) - - # If running QMU analysis, some preprocessing of Dakota files using model - # fields needs to be carried out + # Prepare directory in execution + if cluster.name == oshostname(): + localexecdir = cluster.executionpath + else: + localexecdir = issmdir() + '/execution' + if not os.path.isdir(localexecdir): + raise RuntimeError('Could not find directory ' + localexecdir) + elif len(os.listdir(localexecdir)) > 200: + warnings.warn(localexecdir + ' has more than 200 subdirectories. Consider cleaning up your execution directory') + root = localexecdir + '/' + md.private.runtimename + if os.path.isdir(root): + shutil.rmtree(root) + os.mkdir(root) + + # Figure out executable + executable = 'issm.exe' if md.qmu.isdakota: md = preqmu(md, options) + os.rename(md.miscellaneous.name + '.qmu.in', root + '/' + md.miscellaneous.name + '.qmu.in') + if float(IssmConfig('_DAKOTA_VERSION_')[0]) >= 6: + executable = 'issm_dakota.exe' # Write all input files - marshall(md, md.miscellaneous.name + '.bin') # bin file - md.toolkits.ToolkitsFile(md.miscellaneous.name + '.toolkits') # toolkits file - cluster.BuildQueueScript(md, md.miscellaneous.name + '.queue') # queue file + basename = root + '/' + md.miscellaneous.name + marshall(md, basename + '.bin') # bin file + md.toolkits.ToolkitsFile(basename + '.toolkits') # toolkits file + cluster.BuildQueueScript(md, basename + '.queue', executable) # queue file - # Upload all required files - modelname = md.miscellaneous.name - filelist = [modelname + '.bin', modelname + '.toolkits'] + # List all required files + filelist = [basename + '.bin', basename + '.toolkits'] if ispc(): - filelist.append(modelname + '.bat') + filelist.append(basename + '.bat') else: - filelist.append(modelname + '.queue') + filelist.append(basename + '.queue') if md.qmu.isdakota: - filelist.append(modelname + '.qmu.in') + filelist.append(basename + '.qmu.in') + + if hasattr(cluster, 'interactive') and cluster.interactive: + open(basename + '.errlog', 'w').close() + open(basename + '.outlog', 'w').close() + filelist.append(basename + '.outlog') + filelist.append(basename + '.errlog') - if isempty(restart): + # Upload input files if necessary + if isempty(restart) and cluster.name != oshostname(): print('uploading input files') cluster.UploadQueueJob(md.miscellaneous.name, md.private.runtimename, filelist) diff --git a/src/m/solve/solveiceocean.m b/src/m/solve/solveiceocean.m index 34991f13d..d8dc8ff14 100644 --- a/src/m/solve/solveiceocean.m +++ b/src/m/solve/solveiceocean.m @@ -47,7 +47,7 @@ %check model consistency if strcmpi(getfieldvalue(options,'checkconsistency','yes'),'yes') - if md.verbose.solution, + if md.verbose.solution disp('checking model consistency'); end ismodelselfconsistent(md), @@ -76,7 +76,7 @@ end %Do we load results only? -if getfieldvalue(options,'loadonly',false), +if getfieldvalue(options,'loadonly',false) md=loadresultsfromcluster(md); return; end @@ -84,7 +84,7 @@ %Write all input files marshall(md); % bin file ToolkitsFile(md.toolkits,[md.miscellaneous.name '.toolkits']); % toolkits file -BuildQueueScriptIceOcean(cluster,md.private.runtimename,md.miscellaneous.name,md.private.solution,md.settings.io_gather,md.debug.valgrind,md.debug.gprof,md.qmu.isdakota); % queue file +BuildQueueScript(cluster, md, [md.miscellaneous.name '.queue'], 'issm_ocean.exe'); % queue file %Upload all required files modelname = md.miscellaneous.name; @@ -95,7 +95,7 @@ filelist{end+1}=[modelname '.queue']; end -if md.qmu.isdakota, +if md.qmu.isdakota filelist{end+1} = [modelname '.qmu.in']; end @@ -105,11 +105,11 @@ %launch queue job: disp('launching solution sequence') -LaunchQueueJobIceOcean(cluster,md.miscellaneous.name,md.private.runtimename,filelist,restart,batch); +LaunchQueueJob(cluster,md.miscellaneous.name,md.private.runtimename,filelist,restart,batch); %return if batch: -if batch, - if md.verbose.solution, +if batch + if md.verbose.solution disp('batch mode requested: not launching job interactively'); disp('launch solution sequence on remote cluster by hand'); end @@ -120,7 +120,7 @@ %load when user enters 'y' disp('solution launched on remote cluster. log in to detect job completion.'); choice=input('Is the job successfully completed? (y/n)','s'); - if ~strcmp(choice,'y'), + if ~strcmp(choice,'y') disp('Results not loaded... exiting'); else md=loadresultsfromcluster(md); @@ -128,7 +128,7 @@ elseif md.settings.waitonlock>0 %we wait for the done file done=waitonlock(md); - if md.verbose.solution, + if md.verbose.solution disp('loading results from cluster'); end md=loadresultsfromcluster(md,'runtimename',''); diff --git a/src/m/solve/solveslm.m b/src/m/solve/solveslm.m index 7e3c6073d..897315f91 100644 --- a/src/m/solve/solveslm.m +++ b/src/m/solve/solveslm.m @@ -34,7 +34,7 @@ totalnp=0; for i=1:length(slm.icecaps), totalnp=totalnp+slm.icecaps{i}.cluster.np; end totalnp=totalnp+slm.earth.cluster.np; -if totalnp~=slm.cluster.np, +if totalnp~=slm.cluster.np error('sum of all icecaps and earch cluster processors requestes should be equal to slm.cluster.np'); end @@ -44,7 +44,7 @@ batch=0; %now, go through icecaps, glaciers and earth, and upload all the data independently: disp('solving ice caps first'); -for i=1:length(slm.icecaps), +for i=1:length(slm.icecaps) slm.icecaps{i}=solve(slm.icecaps{i},solutionstringi,'batch','yes'); end disp('solving earth now'); @@ -58,7 +58,7 @@ privateruntimenames={}; miscellaneousnames={}; nps={}; -for i=1:length(slm.icecaps), +for i=1:length(slm.icecaps) privateruntimenames{end+1}=slm.icecaps{i}.private.runtimename; miscellaneousnames{end+1}=slm.icecaps{i}.miscellaneous.name; nps{end+1}=slm.icecaps{i}.cluster.np; @@ -78,22 +78,22 @@ LaunchQueueJob(cluster,slm.miscellaneous.name,slm.private.runtimename,filelist,'',batch); %wait on lock -if isnan(slm.settings.waitonlock), +if isnan(slm.settings.waitonlock) %load when user enters 'y' disp('solution launched on remote cluster. log in to detect job completion.'); choice=input('Is the job successfully completed? (y/n)','s'); - if ~strcmp(choice,'y'), + if ~strcmp(choice,'y') disp('Results not loaded... exiting'); else for i=1:length(slm.icecaps), slm.icecaps{i}=loadresultsfromcluster(slm.icecaps{i});end; slm.earth=loadresultsfromcluster(slm.earth); end -elseif slm.settings.waitonlock>0, +elseif slm.settings.waitonlock>0 %we wait for the done file done=waitonlock(slm); disp('loading results from cluster'); for i=1:length(slm.icecaps), slm.icecaps{i}=loadresultsfromcluster(slm.icecaps{i});end; slm.earth=loadresultsfromcluster(slm.earth); -elseif slm.settings.waitonlock==0, +elseif slm.settings.waitonlock==0 disp('Model results must be loaded manually with slm=loadresultsfromcluster(slm);'); end diff --git a/src/m/solve/waitonlock.m b/src/m/solve/waitonlock.m index 5435f78ef..8d2d65f0c 100644 --- a/src/m/solve/waitonlock.m +++ b/src/m/solve/waitonlock.m @@ -20,7 +20,7 @@ if isa(cluster,'pfe') && cluster.interactive>0 lockfilename = [executionpath '/Interactive' num2str(cluster.interactive) '/' md.miscellaneous.name '.lock']; logfilename = [executionpath '/Interactive' num2str(cluster.interactive) '/' md.miscellaneous.name '.outlog']; -elseif isa(cluster,'localpfe'), +elseif isa(cluster,'localpfe') lockfilename = [executionpath '/' md.miscellaneous.name '.lock']; logfilename = [executionpath '/' md.miscellaneous.name '.outlog']; else @@ -29,7 +29,7 @@ end %If we are using the generic cluster in interactive mode, job is already complete -if (isa(cluster,'generic') & cluster.interactive) | isa(cluster,'generic_static'), +if (isa(cluster,'generic') & cluster.interactive) %We are in interactive mode, no need to check for job completion ispresent=1; return; @@ -40,16 +40,16 @@ disp(['waiting for ' lockfilename ' hold on... (Ctrl+C to exit)']) %prepare command if the job is not running on the local machine -if ~strcmpi(oshostname(),cluster.name), - if isa(cluster,'cloud'), +if ~strcmpi(oshostname(),cluster.name) + if isa(cluster,'cloud') command = [' [ -f ' lockfilename ' ] && [ -f ' logfilename ' ] 2>/dev/null']; command = [starcluster() ' sshmaster ' cluster.name ' --user ' cluster.login ' ''' command '''']; else command = ['ssh -l ' cluster.login]; - if isprop(cluster,'idfile') && ~strcmp(cluster.idfile,''), + if isprop(cluster,'idfile') && ~strcmp(cluster.idfile,'') command = [command ' -i ' cluster.idfile]; end - if isprop(cluster,'port') && cluster.port, + if isprop(cluster,'port') && cluster.port command = [command ' -p ' num2str(cluster.port) ' localhost']; else, command = [command ' ' cluster.name]; @@ -60,7 +60,7 @@ %loop till file .lock exist or time is up while (ispresent==0 & elapsedtimetimelimit), +if (elapsedtime>timelimit) disp('Time limit exceeded. Increase md.settings.waitonlock'); disp('The results must be loaded manually with md=loadresultsfromcluster(md).'); error(['waitonlock error message: time limit exceeded']); diff --git a/src/m/solve/waitonlock.py b/src/m/solve/waitonlock.py index 03c3024dc..321325eab 100644 --- a/src/m/solve/waitonlock.py +++ b/src/m/solve/waitonlock.py @@ -2,7 +2,6 @@ import sys import time from generic import * -from generic_static import * # from localpfe import * from MatlabFuncs import * from pfe import * @@ -40,7 +39,7 @@ def waitonlock(md): logfilename = '{}/{}/{}.outlog'.format(executionpath, md.private.runtimename, md.miscellaneous.name) # If we are using the generic cluster in interactive mode, job is already complete - if (isa(cluster, generic) and cluster.interactive) or (isa(cluster, generic_static)): + if (isa(cluster, generic) and cluster.interactive): # We are in interactive mode, no need to check for job completion return 1 diff --git a/src/m/solvers/mumpsnoneoptions.m b/src/m/solvers/mumpsnoneoptions.m index 32337efb8..959c1a1f1 100644 --- a/src/m/solvers/mumpsnoneoptions.m +++ b/src/m/solvers/mumpsnoneoptions.m @@ -11,7 +11,7 @@ %default mumps options PETSC_MAJOR=IssmConfig('_PETSC_MAJOR_'); PETSC_MINOR=IssmConfig('_PETSC_MINOR_'); -if PETSC_MAJOR==2., +if PETSC_MAJOR==2. mumps.toolkit='petsc'; mumps.mat_type=getfieldvalue(options,'mat_type','aijmumps'); mumps.ksp_type=getfieldvalue(options,'ksp_type','preonly'); @@ -19,7 +19,7 @@ mumps.mat_mumps_icntl_14=getfieldvalue(options,'mat_mumps_icntl_14',120); end -if PETSC_MAJOR==3., +if PETSC_MAJOR==3. mumps.toolkit='petsc'; mumps.mat_type=getfieldvalue(options,'mat_type','mpiaij'); mumps.ksp_type=getfieldvalue(options,'ksp_type','preonly'); diff --git a/src/m/solvers/mumpsoptions.m b/src/m/solvers/mumpsoptions.m index df8dbd7a8..ed65a8dda 100644 --- a/src/m/solvers/mumpsoptions.m +++ b/src/m/solvers/mumpsoptions.m @@ -11,7 +11,7 @@ %default mumps options PETSC_MAJOR=IssmConfig('_PETSC_MAJOR_'); PETSC_MINOR=IssmConfig('_PETSC_MINOR_'); -if PETSC_MAJOR==2., +if PETSC_MAJOR==2. mumps.toolkit='petsc'; mumps.mat_type=getfieldvalue(options,'mat_type','aijmumps'); mumps.ksp_type=getfieldvalue(options,'ksp_type','preonly'); @@ -19,7 +19,7 @@ mumps.mat_mumps_icntl_14=getfieldvalue(options,'mat_mumps_icntl_14',120); end -if PETSC_MAJOR==3., +if PETSC_MAJOR==3. mumps.toolkit='petsc'; mumps.mat_type=getfieldvalue(options,'mat_type','mpiaij'); mumps.ksp_type=getfieldvalue(options,'ksp_type','preonly'); diff --git a/src/m/string/discardnum.m b/src/m/string/discardnum.m index 62aa0ab81..20b069c7d 100644 --- a/src/m/string/discardnum.m +++ b/src/m/string/discardnum.m @@ -6,8 +6,8 @@ string2=string; -for i=1:length(string), - if (((string(i)-0) <=57) & ((string(i)-0) >=48)), +for i=1:length(string) + if (((string(i)-0) <=57) & ((string(i)-0) >=48)) string2=string(1:i-1); break; end diff --git a/src/m/string/ismemberi.m b/src/m/string/ismemberi.m index 83109a427..c41d64725 100644 --- a/src/m/string/ismemberi.m +++ b/src/m/string/ismemberi.m @@ -18,8 +18,8 @@ flag=0; %go through the list -for i=1:length(list), - if strcmpi(string,list{i}), +for i=1:length(list) + if strcmpi(string,list{i}) flag=i; return end diff --git a/src/wrappers/IssmConfig/IssmConfig.cpp b/src/wrappers/IssmConfig/IssmConfig.cpp index 4604d87a0..9c7a94b70 100644 --- a/src/wrappers/IssmConfig/IssmConfig.cpp +++ b/src/wrappers/IssmConfig/IssmConfig.cpp @@ -63,11 +63,6 @@ WRAPPER(IssmConfig_python){ value = 1.; #endif } - else if(strcmp(name,"_HAVE_M1QN3_")==0){ - #ifdef _HAVE_M1QN3_ - value = 1.; - #endif - } else if(strcmp(name,"_HAVE_ADOLC_")==0){ #ifdef _HAVE_ADOLC_ value = 1.; diff --git a/src/wrappers/javascript/Makefile.am b/src/wrappers/javascript/Makefile.am index d35024708..61102ce26 100644 --- a/src/wrappers/javascript/Makefile.am +++ b/src/wrappers/javascript/Makefile.am @@ -77,7 +77,7 @@ if !MSYS2 libISSMJavascript_la_LDFLAGS += -static libISSMApi_javascript_la_LDFLAGS += -static endif -deps += $(DAKOTALIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(TAOLIB) $(M1QN3LIB) $(SEMICLIB) $(PLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(TRIANGLELIB) $(BLACSLIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MPILIB) $(NEOPZLIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(ADOLCLIB) $(AMPILIB) $(PROJLIB) $(OSLIBS) +deps += $(DAKOTALIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(TAOLIB) $(SEMICLIB) $(PLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(TRIANGLELIB) $(BLACSLIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MPILIB) $(NEOPZLIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(ADOLCLIB) $(AMPILIB) $(PROJLIB) $(OSLIBS) endif libISSMApi_javascript_la_LIBADD = $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(MPILIB) $(NEOPZLIB) $(GSLLIB) $(PROJLIB) $(MATHLIB) diff --git a/src/wrappers/matlab/Makefile.am b/src/wrappers/matlab/Makefile.am index be0e6b836..8c8ea228d 100644 --- a/src/wrappers/matlab/Makefile.am +++ b/src/wrappers/matlab/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = @NEOPZINCL@ @DAKOTAINCL@ @BOOSTINCL@ @MATLABINCL@ @PETSCINCL@ @MPIINCL@ @SPOOLESINCL@ @PARMETISINCL@ @METISINCL@ @TRIANGLEINCL@ @CHACOINCL@ @AMPIINCL@ @MEDIPACKINCL@ @ADJOINTPETSCINCL@ @CODIPACKINCL@ @PROJINCL@ +AM_CPPFLAGS = @NEOPZINCL@ @DAKOTAINCL@ @BOOSTINCL@ @MATLABINCL@ @PETSCINCL@ @MPIINCL@ @SPOOLESINCL@ @PARMETISINCL@ @METISINCL@ @TRIANGLEINCL@ @CHACOINCL@ @AMPIINCL@ @MEDIPACKINCL@ @ADJOINTPETSCINCL@ @CODIPACKINCL@ @PROJINCL@ @PyBind11INCL@ AUTOMAKE_OPTIONS = subdir-objects EXEEXT=$(MATLABWRAPPEREXT) @@ -174,7 +174,7 @@ if !MSYS2 libISSMMatlab_la_LDFLAGS += -static libISSMApi_matlab_la_LDFLAGS += -static endif -deps += $(DAKOTALIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(TAOLIB) $(M1QN3LIB) $(SEMICLIB) $(PLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(TRIANGLELIB) $(BLACSLIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MPILIB) $(NEOPZLIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(ADOLCLIB) $(AMPILIB) $(OSLIBS) ${LIBADD_FOR_MEX} +deps += $(DAKOTALIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(TAOLIB) $(SEMICLIB) $(PLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(TRIANGLELIB) $(BLACSLIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MPILIB) $(NEOPZLIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(ADOLCLIB) $(AMPILIB) $(OSLIBS) ${LIBADD_FOR_MEX} endif libISSMApi_matlab_la_LIBADD = $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(MPILIB) $(NEOPZLIB) $(GSLLIB) $(MATHLIB) $(MEXLIB) diff --git a/src/wrappers/matlab/io/ApiPrintf.cpp b/src/wrappers/matlab/io/ApiPrintf.cpp index 8c634da85..9e40084fa 100644 --- a/src/wrappers/matlab/io/ApiPrintf.cpp +++ b/src/wrappers/matlab/io/ApiPrintf.cpp @@ -14,7 +14,7 @@ void ApiPrintf(const char* string){ /*use mexPrintf in matlab: */ - mexPrintf(string); /*Messes up percentages (like "interpolation progress: 100.00%")*/ + mexPrintf("%s", string); /*WARNING: MATLAB's MEX API is not thread-safe, do not use with pthread*/ //printf("%s",string); return; } diff --git a/src/wrappers/python/Makefile.am b/src/wrappers/python/Makefile.am index a68663dcc..2232f5d8e 100644 --- a/src/wrappers/python/Makefile.am +++ b/src/wrappers/python/Makefile.am @@ -1,4 +1,4 @@ -AM_CPPFLAGS = @NEOPZINCL@ @DAKOTAINCL@ @BOOSTINCL@ @PYTHONINCL@ @PYTHON_NUMPYINCL@ @PETSCINCL@ @MPIINCL@ @SPOOLESINCL@ @PARMETISINCL@ @METISINCL@ @TRIANGLEINCL@ @CHACOINCL@ @AMPIINCL@ @MEDIPACKINCL@ @ADJOINTPETSCINCL@ @CODIPACKINCL@ @PROJINCL@ +AM_CPPFLAGS = @NEOPZINCL@ @DAKOTAINCL@ @BOOSTINCL@ @PYTHONINCL@ @PYTHON_NUMPYINCL@ @PETSCINCL@ @MPIINCL@ @SPOOLESINCL@ @PARMETISINCL@ @METISINCL@ @TRIANGLEINCL@ @CHACOINCL@ @AMPIINCL@ @MEDIPACKINCL@ @ADJOINTPETSCINCL@ @CODIPACKINCL@ @PROJINCL@ @PyBind11INCL@ AUTOMAKE_OPTIONS = subdir-objects #define prefix (from http://www.gnu.org/software/autoconf/manual/autoconf-2.67/html_node/Defining-Directories.html) @@ -157,7 +157,7 @@ if !MSYS2 libISSMPython_la_LDFLAGS = -static libISSMApi_python_la_LDFLAGS = -static endif -deps += $(DAKOTALIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(TAOLIB) $(M1QN3LIB) $(SEMICLIB) $(PLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(TRIANGLELIB) $(BLACSLIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MPILIB) $(NEOPZLIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(ADOLCLIB) $(AMPILIB) $(OSLIBS) $(PYTHONLIB) +deps += $(DAKOTALIB) $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(TAOLIB) $(SEMICLIB) $(PLAPACKLIB) $(SUPERLULIB) $(SPOOLESLIB) $(TRIANGLELIB) $(BLACSLIB) $(HYPRELIB) $(SPAILIB) $(PROMETHEUSLIB) $(PASTIXLIB) $(MLLIB) $(MKLLIB) $(MPILIB) $(NEOPZLIB) $(MATHLIB) $(GRAPHICSLIB) $(MULTITHREADINGLIB) $(GSLLIB) $(ADOLCLIB) $(AMPILIB) $(OSLIBS) $(PYTHONLIB) endif libISSMApi_python_la_LIBADD = $(PETSCLIB) $(MUMPSLIB) $(SCALAPACKLIB) $(BLASLAPACKLIB) $(PARMETISLIB) $(METISLIB) $(HDF5LIB) $(MPILIB) $(NEOPZLIB) $(GSLLIB) $(MATHLIB) diff --git a/test/Archives/Archive119.arch b/test/Archives/Archive119.arch index 2a5e872e5..40aa3fbb6 100644 Binary files a/test/Archives/Archive119.arch and b/test/Archives/Archive119.arch differ diff --git a/test/Archives/Archive2002.arch b/test/Archives/Archive2002.arch index facecd4ca..a7e3cd336 100644 Binary files a/test/Archives/Archive2002.arch and b/test/Archives/Archive2002.arch differ diff --git a/test/Archives/Archive2005.arch b/test/Archives/Archive2005.arch index 774bdde52..02481c52c 100644 Binary files a/test/Archives/Archive2005.arch and b/test/Archives/Archive2005.arch differ diff --git a/test/Archives/Archive2008.arch b/test/Archives/Archive2008.arch index 920b72d09..396f0ff1d 100644 Binary files a/test/Archives/Archive2008.arch and b/test/Archives/Archive2008.arch differ diff --git a/test/Archives/Archive2011.arch b/test/Archives/Archive2011.arch index f45e8107b..cd0913c42 100644 Binary files a/test/Archives/Archive2011.arch and b/test/Archives/Archive2011.arch differ diff --git a/test/Archives/Archive2090.arch b/test/Archives/Archive2090.arch index f5c7a217d..23b10e68b 100644 Binary files a/test/Archives/Archive2090.arch and b/test/Archives/Archive2090.arch differ diff --git a/test/Archives/Archive2091.arch b/test/Archives/Archive2091.arch index 61863f447..7f513fec5 100644 Binary files a/test/Archives/Archive2091.arch and b/test/Archives/Archive2091.arch differ diff --git a/test/Archives/Archive2092.arch b/test/Archives/Archive2092.arch index 14e47845a..6e01c0ef0 100644 Binary files a/test/Archives/Archive2092.arch and b/test/Archives/Archive2092.arch differ diff --git a/test/Archives/Archive243.arch b/test/Archives/Archive243.arch index 81e50d962..d1595863d 100644 Binary files a/test/Archives/Archive243.arch and b/test/Archives/Archive243.arch differ diff --git a/test/Archives/Archive244.arch b/test/Archives/Archive244.arch index 1ce1454a8..b45122155 100644 Binary files a/test/Archives/Archive244.arch and b/test/Archives/Archive244.arch differ diff --git a/test/Archives/Archive252.arch b/test/Archives/Archive252.arch index a3f55ec94..951422608 100644 Binary files a/test/Archives/Archive252.arch and b/test/Archives/Archive252.arch differ diff --git a/test/Archives/Archive253.arch b/test/Archives/Archive253.arch index bc61ae88e..c985f4b78 100644 Binary files a/test/Archives/Archive253.arch and b/test/Archives/Archive253.arch differ diff --git a/test/Archives/Archive258.arch b/test/Archives/Archive258.arch index bcb71f605..852f84faa 100644 Binary files a/test/Archives/Archive258.arch and b/test/Archives/Archive258.arch differ diff --git a/test/Archives/Archive259.arch b/test/Archives/Archive259.arch index 52c8af74f..fd8df5f00 100644 Binary files a/test/Archives/Archive259.arch and b/test/Archives/Archive259.arch differ diff --git a/test/Archives/Archive462.arch b/test/Archives/Archive462.arch index 224f0d67f..09069e289 100644 Binary files a/test/Archives/Archive462.arch and b/test/Archives/Archive462.arch differ diff --git a/test/Archives/Archive464.arch b/test/Archives/Archive464.arch index 00c726a11..0b30e35e7 100644 Binary files a/test/Archives/Archive464.arch and b/test/Archives/Archive464.arch differ diff --git a/test/Data/friction_emulator/friction_emulator.pt b/test/Data/friction_emulator/friction_emulator.pt new file mode 100644 index 000000000..3e2fcd3c3 Binary files /dev/null and b/test/Data/friction_emulator/friction_emulator.pt differ diff --git a/test/Data/friction_emulator/friction_emulator.py b/test/Data/friction_emulator/friction_emulator.py new file mode 100644 index 000000000..13632e73c --- /dev/null +++ b/test/Data/friction_emulator/friction_emulator.py @@ -0,0 +1,84 @@ +from __future__ import annotations +from pathlib import Path +import numpy as np +import torch +import torch.nn as nn + +DEFAULT_WEIGHTS_PATH = ( + "/home1/10783/yinmin/work/Applications/ISSM/src/c/modules/" + "FrictionEmulator/trained_models/friction_emulator.pt" +) + +FIXED_X_MEAN = np.array([9.05e6, 2.08e-5], dtype=np.float32) +FIXED_X_STD = np.array([6.61e6, 4.67e-5], dtype=np.float32) +FIXED_Y_MEAN = np.array([2.09e11], dtype=np.float32) +FIXED_Y_STD = np.array([1.18e12], dtype=np.float32) + +_MODEL = None +_DEVICE = None +_X_MEAN_T = None +_X_STD_T = None +_Y_MEAN_T = None +_Y_STD_T = None + +class FrictionMLP(nn.Module):# {{{ + def __init__(self, in_dim: int = 2, h1: int = 64, h2: int = 64, out_dim: int = 1): + super().__init__() + self.net = nn.Sequential( + nn.Linear(in_dim, h1), + nn.ReLU(), + nn.Linear(h1, h2), + nn.ReLU(), + nn.Linear(h2, out_dim), + ) + + def forward(self, x: torch.Tensor) -> torch.Tensor: + return self.net(x)# }}} +def init_model(weights_path: str = DEFAULT_WEIGHTS_PATH, device: str = "auto") -> None:# {{{ + global _MODEL, _DEVICE, _X_MEAN_T, _X_STD_T, _Y_MEAN_T, _Y_STD_T + + ckpt_path = Path(weights_path) + if not ckpt_path.exists(): + raise FileNotFoundError(f"Friction emulator checkpoint not found: {ckpt_path}") + + checkpoint = torch.load(str(ckpt_path), map_location="cpu", weights_only=False) + in_dim = int(checkpoint["in_dim"]) + h1 = int(checkpoint["h1"]) + h2 = int(checkpoint["h2"]) + out_dim = int(checkpoint["out_dim"]) + + if device == "auto": + resolved_device = "cuda" if torch.cuda.is_available() else "cpu" + else: + resolved_device = device + + model = FrictionMLP(in_dim=in_dim, h1=h1, h2=h2, out_dim=out_dim) + model.load_state_dict(checkpoint["state_dict"]) + model.to(resolved_device) + model.eval() + + _MODEL = model + _DEVICE = resolved_device + _X_MEAN_T = torch.as_tensor(FIXED_X_MEAN, dtype=torch.float32, device=resolved_device) + _X_STD_T = torch.as_tensor(FIXED_X_STD, dtype=torch.float32, device=resolved_device) + _Y_MEAN_T = torch.as_tensor(FIXED_Y_MEAN, dtype=torch.float32, device=resolved_device) + _Y_STD_T = torch.as_tensor(FIXED_Y_STD, dtype=torch.float32, device=resolved_device) + print(f"Friction emulator initialized on device: {resolved_device}")# }}} +@torch.no_grad() +def predict_alpha2_np(feats, *, dtype="float64"):# {{{ + if _MODEL is None: + raise RuntimeError("Friction emulator is not initialized") + + feats_np = np.asarray(feats, dtype=np.float32) + if feats_np.ndim == 1: + feats_np = feats_np.reshape(1, -1) + if feats_np.shape[1] != 2: + raise ValueError(f"Expected input shape (*, 2), got {feats_np.shape}") + + feats_t = torch.as_tensor(feats_np, dtype=torch.float32, device=_DEVICE) + feats_norm = (feats_t - _X_MEAN_T) / _X_STD_T + pred_norm = _MODEL(feats_norm) + pred_raw = pred_norm * _Y_STD_T + _Y_MEAN_T + pred_raw = pred_raw.detach().cpu().contiguous() + pred_raw = pred_raw.to(getattr(torch, dtype)) if isinstance(dtype, str) else pred_raw.to(dtype) + return pred_raw.numpy().copy()# }}} diff --git a/test/NightlyRun/test2011.m b/test/NightlyRun/test2011.m index 10b360f95..3d7983a0a 100644 --- a/test/NightlyRun/test2011.m +++ b/test/NightlyRun/test2011.m @@ -80,6 +80,8 @@ md.solidearth.settings.isgrd=1; md.solidearth.settings.ocean_area_scaling=0; md.solidearth.settings.grdmodel=1; +md.solidearth.settings.maxiter=6; + %Physics: md.transient.issmb=0; @@ -95,6 +97,8 @@ md.solidearth.settings.elastic=1; md.solidearth.settings.rotation=0; md.solidearth.settings.viscous=0; + +md.verbose.convergence = 1; md=solve(md,'tr'); %recover barystatic: diff --git a/test/NightlyRun/test2090.m b/test/NightlyRun/test2090.m index 9faf48ea1..3a1e9aa4f 100644 --- a/test/NightlyRun/test2090.m +++ b/test/NightlyRun/test2090.m @@ -103,6 +103,7 @@ md.solidearth.settings.grdmodel=1; md.solidearth.settings.timeacc=md.timestepping.time_step; md.solidearth.settings.degacc=.1; +md.solidearth.settings.viscoussampling=20; %Physics: md.transient.issmb=0; diff --git a/test/NightlyRun/test2091.m b/test/NightlyRun/test2091.m index afdf3c701..3d9a90823 100644 --- a/test/NightlyRun/test2091.m +++ b/test/NightlyRun/test2091.m @@ -153,6 +153,7 @@ md.solidearth.settings.grdmodel=1; md.solidearth.settings.timeacc=md.timestepping.time_step; md.solidearth.settings.degacc=.01; +md.solidearth.settings.viscoussampling=20; %Physics: md.transient.issmb=0; diff --git a/test/NightlyRun/test2092.m b/test/NightlyRun/test2092.m index db9988574..03dd3aa97 100644 --- a/test/NightlyRun/test2092.m +++ b/test/NightlyRun/test2092.m @@ -176,6 +176,7 @@ md.solidearth.settings.grdmodel=1; md.solidearth.settings.timeacc=md.timestepping.time_step; md.solidearth.settings.degacc=.1; +md.solidearth.settings.viscoussampling=20; %Physics: md.transient.issmb=0; diff --git a/test/NightlyRun/test221.js b/test/NightlyRun/test221.js index 9355635c1..dc90222b0 100644 --- a/test/NightlyRun/test221.js +++ b/test/NightlyRun/test221.js @@ -10,7 +10,7 @@ md=solve(md,'Stressbalance'); //Fields and tolerances to track changes field_names =['Vx','Vy','Vz','Vel']; -field_tolerances=[1e-09,1e-09,5e-06,1e-09]; +field_tolerances=[1e-09,1e-09,7e-06,1e-09]; field_values=[ (md.results.StressbalanceSolution[0].Vx), (md.results.StressbalanceSolution[0].Vy), diff --git a/test/NightlyRun/test221.m b/test/NightlyRun/test221.m index 979f7d246..cb0c82105 100644 --- a/test/NightlyRun/test221.m +++ b/test/NightlyRun/test221.m @@ -9,7 +9,7 @@ %Fields and tolerances to track changes field_names ={'Vx','Vy','Vz','Vel'}; -field_tolerances={1e-09,1e-09,5e-06,1e-09}; +field_tolerances={1e-09,1e-09,7e-06,1e-09}; field_values={... (md.results.StressbalanceSolution.Vx),... (md.results.StressbalanceSolution.Vy),... diff --git a/test/NightlyRun/test221.py b/test/NightlyRun/test221.py index 2d0e26e2e..be4b2f595 100644 --- a/test/NightlyRun/test221.py +++ b/test/NightlyRun/test221.py @@ -18,7 +18,7 @@ #Fields and tolerances to track changes field_names = ['Vx', 'Vy', 'Vz', 'Vel'] -field_tolerances = [1e-09, 1e-09, 5e-06, 1e-09] +field_tolerances = [1e-09, 1e-09, 7e-06, 1e-09] field_values = [md.results.StressbalanceSolution.Vx, md.results.StressbalanceSolution.Vy, md.results.StressbalanceSolution.Vz, diff --git a/test/NightlyRun/test252.m b/test/NightlyRun/test252.m index 2251bdb24..46b7623ca 100644 --- a/test/NightlyRun/test252.m +++ b/test/NightlyRun/test252.m @@ -68,7 +68,7 @@ field_tolerances ={1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,7e-12,1e-12,1e-12,1e-12,... 1e-12,4e-12,1e-11,1e-10,2e-11,1e-11,1e-12,2e-11,1e-12,1e-12,1e-12,1e-11,... 1e-12,4e-12,2e-12,2e-11,4e-11,1e-11,1e-12,4e-11,4e-11,1e-12,1e-12,1e-11,... - 1e-11,1e-11,9e-11,4e-11,4e-11,4e-11,1e-12,5e-12,1e-10,1e-12,1e-12,2e-11}; + 1e-11,1e-11,9e-11,4e-11,4e-11,4e-11,1e-12,7e-12,1e-10,1e-12,1e-12,2e-11}; field_values={... (nlayers)... diff --git a/test/NightlyRun/test252.py b/test/NightlyRun/test252.py index 27915c36c..dc88e4c18 100644 --- a/test/NightlyRun/test252.py +++ b/test/NightlyRun/test252.py @@ -83,7 +83,7 @@ field_tolerances = [1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 1e-12, 7e-12, 1e-12, 1e-12, 1e-12, 1e-12, 4e-12, 1e-11, 1e-10, 2e-11, 1e-11, 1e-12, 2e-11, 1e-12, 1e-12, 1e-12, 1e-11, 1e-12, 4e-12, 2e-12, 2e-11, 4e-11, 1e-11, 1e-12, 4e-11, 4e-11, 1e-12, 1e-12, 1e-11, - 1e-11, 1e-11, 9e-11, 4e-11, 4e-11, 4e-11, 1e-12, 5e-12, 1e-10, 1e-12, 1e-12, 2e-11] + 1e-11, 1e-11, 9e-11, 4e-11, 4e-11, 4e-11, 1e-12, 7e-12, 1e-10, 1e-12, 1e-12, 2e-11] # Shape is different in python solution (fixed using reshape) which can cause test failure field_values = [nlayers, md.results.TransientSolution[0].SmbDz[0, 0:nlayers].reshape(1, -1), diff --git a/test/NightlyRun/test258.m b/test/NightlyRun/test258.m index 27eaab87b..188dbc796 100644 --- a/test/NightlyRun/test258.m +++ b/test/NightlyRun/test258.m @@ -1,4 +1,4 @@ -%Test Name: SquareShelfSMBGembMapping +%Test Name: SquareShelfSMBGembPrecipMapping md=triangle(model(),'../Exp/Square.exp',350000/2.); md=setmask(md,'all',''); md=parameterize(md,'../Par/SquareShelf.par'); @@ -14,6 +14,8 @@ md.smb = SMBgemb(md.mesh); md.smb.dsnowIdx = 1; md.smb.swIdx = 1; +md.smb.teThresh = 2; +md.smb.teValue(:) = .95; %load hourly surface forcing date from 1979 to 2009: inputs=load('../Data/gemb_input.mat'); @@ -37,6 +39,7 @@ xe2=mean(md2.mesh.x(md2.mesh.elements),2); ye2=mean(md2.mesh.y(md2.mesh.elements),2); mpoints=1:md2.mesh.numberofelements; +[md.smb.lat_mappedforcing md.smb.lon_mappedforcing]=xy2ll(xe2,ye2,+1); md.smb.ismappedforcing=1; md.smb.isprecipforcingremapped=1; @@ -75,7 +78,7 @@ %Fields and tolerances to track changes field_names ={'Layers','SmbDz','SmbT','SmbD','SmbRe','SmbGdn','SmbGsp','SmbA' ,'SmbEC','SmbMassBalance','SmbMAdd','SmbDzAdd','SmbFAC','SmbMeanSHF','SmbMeanLHF','SmbMeanULW','SmbNetLW','SmbNetSW','SmbTs','SmbT10','SmbT30','SmbT50','SmbAccumulatedMassBalance','SmbAccumulatedRunoff','SmbAccumulatedMelt','SmbAccumulatedEC','SmbAccumulatedPrecipitation','SmbAccumulatedRain','SmbAccumulatedRefreeze','SmbRunoff','SmbMelt','SmbEC','SmbPrecipitation','SmbRain','SmbRefreeze','SmbWAdd'}; -field_tolerances ={1e-12,4e-11,2e-11,3e-11,6e-11,8e-11,8e-11,1e-12,5e-11,3e-12,1e-12,1e-12,4e-11,2e-11,5e-11,1e-11,9e-10,2e-11,2e-11,2e-11,2e-11,2e-11,1e-11,9e-10,2e-11,2e-09,1e-11,1e-11,1e-11,8e-10,2e-11,2e-11,1e-11,1e-11,2e-11,1e-11}; +field_tolerances ={1e-12,4e-11,2e-11,3e-11,6e-11,8e-11,8e-11,1e-12,5e-11,6e-12,1e-12,1e-12,4e-11,2e-11,5e-11,1e-11,9e-10,2e-11,2e-11,2e-11,2e-11,2e-11,1e-11,9e-10,2e-11,2e-09,1e-11,1e-11,1e-11,8e-10,2e-11,2e-11,1e-11,1e-11,2e-11,1e-11}; field_values={... (nlayers),... diff --git a/test/NightlyRun/test258.py b/test/NightlyRun/test258.py index 629cccb2b..d13d5f4a9 100644 --- a/test/NightlyRun/test258.py +++ b/test/NightlyRun/test258.py @@ -1,4 +1,4 @@ -#Test Name: SquareShelfSMBGembMapping +#Test Name: SquareShelfSMBGembPrecipMapping from socket import gethostname import sys import numpy as np @@ -9,6 +9,7 @@ from SMBgemb import * from solve import * from triangle import * +from xy2ll import * from scipy.interpolate import NearestNDInterpolator @@ -27,6 +28,8 @@ md.smb = SMBgemb(md.mesh) md.smb.dsnowIdx = 1 md.smb.swIdx = 1 +md.smb.teThresh = 2 +md.smb.teValue[:] = .95 #load hourly surface forcing date from 1979 to 2009: if sys.version_info.major == 2: @@ -52,6 +55,7 @@ ye=np.mean(md.mesh.y[md.mesh.elements-1],axis=1) xe2=np.mean(md2.mesh.x[md2.mesh.elements-1],axis=1) ye2=np.mean(md2.mesh.y[md2.mesh.elements-1],axis=1) +[md.smb.lat_mappedforcing, md.smb.lon_mappedforcing]=xy2ll(xe2,ye2,+1) mpoints=np.arange(1,md2.mesh.numberofelements+1) @@ -92,7 +96,7 @@ #Fields and tolerances to track changes field_names = ['Layers', 'SmbDz', 'SmbT', 'SmbD', 'SmbRe', 'SmbGdn', 'SmbGsp', 'SmbA', 'SmbEC', 'SmbMassBalance', 'SmbMAdd', 'SmbDzAdd', 'SmbFAC', 'SmbMeanSHF', 'SmbMeanLHF', 'SmbMeanULW', 'SmbNetLW', 'SmbNetSW', 'SmbTs', 'SmbT10', 'SmbT30', 'SmbT50', 'SmbAccumulatedMassBalance', 'SmbAccumulatedRunoff', 'SmbAccumulatedMelt', 'SmbAccumulatedEC', 'SmbAccumulatedPrecipitation', 'SmbAccumulatedRain', 'SmbAccumulatedRefreeze', 'SmbRunoff', 'SmbMelt', 'SmbEC', 'SmbPrecipitation', 'SmbRain', 'SmbRefreeze', 'SmbWAdd'] -field_tolerances = [1e-12, 4e-11, 2e-11, 3e-11, 6e-11, 8e-11, 8e-11, 1e-12, 5e-11, 3e-12, 1e-12, 1e-12, 4e-11, 2e-11, 5e-11, 1e-11, 9e-10, 2e-11, 2e-11, 2e-11, 2e-11, 2e-11, 1e-11, 9e-10, 2e-11, 2e-09, 1e-11, 1e-11, 1e-11, 8e-10, 2e-11, 2e-11, 1e-11, 1e-11, 2e-11, 1e-11] +field_tolerances = [1e-12, 4e-11, 2e-11, 3e-11, 6e-11, 8e-11, 8e-11, 1e-12, 5e-11, 6e-12, 1e-12, 1e-12, 4e-11, 2e-11, 5e-11, 1e-11, 9e-10, 2e-11, 2e-11, 2e-11, 2e-11, 2e-11, 1e-11, 9e-10, 2e-11, 2e-09, 1e-11, 1e-11, 1e-11, 8e-10, 2e-11, 2e-11, 1e-11, 1e-11, 2e-11, 1e-11] # Shape is different in python solution (fixed using reshape) which can cause test failure field_values = [ diff --git a/test/NightlyRun/test259.m b/test/NightlyRun/test259.m index 0a504ee1b..0eb449c03 100644 --- a/test/NightlyRun/test259.m +++ b/test/NightlyRun/test259.m @@ -14,6 +14,10 @@ md.smb = SMBgemb(md.mesh); md.smb.dsnowIdx = 1; md.smb.swIdx = 1; +md.smb.aIdx = 0; +md.smb.eIdx = 3; +md.smb.teValue(:) = 0.95; +md.smb.teDefault = 0.97; %load hourly surface forcing date from 1979 to 2009: inputs=load('../Data/gemb_input.mat'); @@ -37,6 +41,7 @@ xe2=mean(md2.mesh.x(md2.mesh.elements),2); ye2=mean(md2.mesh.y(md2.mesh.elements),2); mpoints=1:md2.mesh.numberofelements; +[md.smb.lat_mappedforcing md.smb.lon_mappedforcing]=xy2ll(xe2,ye2,+1); md.smb.ismappedforcing=1; md.smb.isprecipforcingremapped=0; @@ -75,7 +80,7 @@ %Fields and tolerances to track changes field_names ={'Layers','SmbDz','SmbT','SmbD','SmbRe','SmbGdn','SmbGsp','SmbA' ,'SmbEC','SmbMassBalance','SmbMAdd','SmbDzAdd','SmbFAC','SmbMeanSHF','SmbMeanLHF','SmbMeanULW','SmbNetLW','SmbNetSW','SmbAccumulatedMassBalance','SmbAccumulatedRunoff','SmbAccumulatedMelt','SmbAccumulatedEC','SmbAccumulatedPrecipitation','SmbAccumulatedRain','SmbAccumulatedRefreeze','SmbRunoff','SmbMelt','SmbEC','SmbPrecipitation','SmbRain','SmbRefreeze','SmbWAdd'}; -field_tolerances ={1e-12,4e-11,2e-11,3e-11,6e-11,8e-11,8e-11,1e-12,5e-11,2e-12,1e-12,1e-12,4e-11,2e-11,5e-11,1e-11,9e-10,2e-11,1e-11,9e-10,2e-11,2e-09,1e-11,1e-11,1e-11,8e-10,2e-11,2e-11,1e-11,1e-11,2e-11,1e-11}; +field_tolerances ={1e-12,4e-11,2e-11,4e-11,6e-11,8e-11,8e-11,1e-12,5e-11,2e-12,1e-12,1e-12,4e-11,6e-11,5e-11,1e-11,9e-10,2e-11,1e-11,9e-10,2e-11,2e-09,1e-11,1e-11,1e-11,8e-10,2e-11,2e-11,1e-11,1e-11,2e-11,1e-11}; field_values={... (nlayers),... diff --git a/test/NightlyRun/test259.py b/test/NightlyRun/test259.py index bb113bc1d..571ba73ec 100644 --- a/test/NightlyRun/test259.py +++ b/test/NightlyRun/test259.py @@ -9,6 +9,7 @@ from SMBgemb import * from solve import * from triangle import * +from xy2ll import * from scipy.interpolate import NearestNDInterpolator @@ -27,6 +28,10 @@ md.smb = SMBgemb(md.mesh) md.smb.dsnowIdx = 1 md.smb.swIdx = 1 +md.smb.aIdx = 0 +md.smb.eIdx = 3 +md.smb.teValue[:] = 0.95 +md.smb.teDefault = 0.97 #load hourly surface forcing date from 1979 to 2009: if sys.version_info.major == 2: @@ -52,6 +57,7 @@ ye=np.mean(md.mesh.y[md.mesh.elements-1],axis=1) xe2=np.mean(md2.mesh.x[md2.mesh.elements-1],axis=1) ye2=np.mean(md2.mesh.y[md2.mesh.elements-1],axis=1) +[md.smb.lat_mappedforcing, md.smb.lon_mappedforcing]=xy2ll(xe2,ye2,+1) mpoints=np.arange(1,md2.mesh.numberofelements+1) @@ -92,7 +98,7 @@ #Fields and tolerances to track changes field_names = ['Layers', 'SmbDz', 'SmbT', 'SmbD', 'SmbRe', 'SmbGdn', 'SmbGsp', 'SmbA', 'SmbEC', 'SmbMassBalance', 'SmbMAdd', 'SmbDzAdd', 'SmbFAC', 'SmbMeanSHF', 'SmbMeanLHF', 'SmbMeanULW', 'SmbNetLW', 'SmbNetSW', 'SmbAccumulatedMassBalance', 'SmbAccumulatedRunoff', 'SmbAccumulatedMelt', 'SmbAccumulatedEC', 'SmbAccumulatedPrecipitation', 'SmbAccumulatedRain', 'SmbAccumulatedRefreeze', 'SmbRunoff', 'SmbMelt', 'SmbEC', 'SmbPrecipitation', 'SmbRain', 'SmbRefreeze', 'SmbWAdd'] -field_tolerances = [1e-12, 4e-11, 2e-11, 3e-11, 6e-11, 8e-11, 8e-11, 1e-12, 5e-11, 2e-12, 1e-12, 1e-12, 4e-11, 2e-11, 5e-11, 1e-11, 9e-10, 2e-11, 1e-11, 9e-10, 2e-11, 2e-09, 1e-11, 1e-11, 1e-11, 8e-10, 2e-11, 2e-11, 1e-11, 1e-11, 2e-11, 1e-11] +field_tolerances = [1e-12, 4e-11, 2e-11, 4e-11, 6e-11, 8e-11, 8e-11, 1e-12, 5e-11, 2e-12, 1e-12, 1e-12, 4e-11, 6e-11, 5e-11, 1e-11, 9e-10, 2e-11, 1e-11, 9e-10, 2e-11, 2e-09, 1e-11, 1e-11, 1e-11, 8e-10, 2e-11, 2e-11, 1e-11, 1e-11, 2e-11, 1e-11] # Shape is different in python solution (fixed using reshape) which can cause test failure field_values = [ diff --git a/test/NightlyRun/test541.m b/test/NightlyRun/test541.m index b22dc422d..58da73fe1 100644 --- a/test/NightlyRun/test541.m +++ b/test/NightlyRun/test541.m @@ -37,7 +37,7 @@ 1e-11,2e-11,2e-11,3e-9,2e-11,... 2e-11,1e-11,1e-11,9e-12,3e-11,3e-11,2e-11,1e-11,... 1e-11,2e-11,2e-11,8e-08,2e-11,... - 2e-10,1e-10,1e-10,1e-10,1e-10,1e-10,1e-10,1e-9,... + 3e-10,1e-10,1e-10,1e-10,1e-10,1e-10,1e-10,1e-9,... 1e-11,2e-11,2e-11,8e-08,2e-11,... }; field_values={... diff --git a/test/NightlyRun/test541.py b/test/NightlyRun/test541.py index 386b53599..8114b1873 100644 --- a/test/NightlyRun/test541.py +++ b/test/NightlyRun/test541.py @@ -44,7 +44,7 @@ 1e-11, 2e-11, 2e-11, 3e-9, 2e-11, 2e-11, 1e-11, 1e-11, 9e-12, 3e-11, 3e-11, 2e-11, 1e-11, 1e-11, 2e-11, 2e-11, 8e-08, 2e-11, - 2e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-9, + 3e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-10, 1e-9, 1e-11, 2e-11, 2e-11, 8e-08, 2e-11] field_values = [md.results.TransientSolution[0].Vx, md.results.TransientSolution[0].Vy,