From 944dd5d3e28efbac763495b6001fde985c315b17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Oriol=20Tint=C3=B3?= <oriol.tinto@lmu.de>
Date: Wed, 22 Mar 2023 16:34:32 +0100
Subject: [PATCH] Adding spack repository with icon templates and modify build
 icon to add the repository

---
 spack_repo/packages/dwd-icon-tools/package.py |  87 ++++++++
 spack_repo/packages/icon-nwp/package.py       | 199 ++++++++++++++++++
 spack_repo/repo.yaml                          |   2 +
 templates/common/build_icon.sh                |   1 +
 4 files changed, 289 insertions(+)
 create mode 100644 spack_repo/packages/dwd-icon-tools/package.py
 create mode 100644 spack_repo/packages/icon-nwp/package.py
 create mode 100644 spack_repo/repo.yaml

diff --git a/spack_repo/packages/dwd-icon-tools/package.py b/spack_repo/packages/dwd-icon-tools/package.py
new file mode 100644
index 0000000..7614cd5
--- /dev/null
+++ b/spack_repo/packages/dwd-icon-tools/package.py
@@ -0,0 +1,87 @@
+# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+# ----------------------------------------------------------------------------
+# If you submit this package back to Spack as a pull request,
+# please first remove this boilerplate and all FIXME comments.
+#
+# This is a template package file for Spack.  We've put "FIXME"
+# next to all the things you'll want to change. Once you've handled
+# them, you can save this file and test your package like this:
+#
+#     spack install dwd-icon-tools
+#
+# You can edit this file again by typing:
+#
+#     spack edit dwd-icon-tools
+#
+# See the Spack documentation for more information on packaging.
+# ----------------------------------------------------------------------------
+
+from spack.package import *
+from pathlib import Path
+
+
+class DwdIconTools(Package):
+    """DWD Icon Tools"""
+
+    homepage = "https://www.example.com"
+    git = "ssh://git@gitlab.lrz.de/dkrz-mirror/dwd_icon_tools.git"
+
+    version("2.5.2", branch="icontools-2.5.2")
+
+    depends_on("netcdf-c")
+    depends_on("eccodes")
+
+    def patch(self):
+        """
+        Because of the lack of access rights to the original submodule repositories,
+        we patch the gitmodules file to point to a different mirror.
+        """
+        git_submodules_file = Path().cwd() / ".gitmodules"
+        git_mirror = "git@gitlab.lrz.de:dkrz-mirror"
+        git_modules_patch = f"""
+        [submodule "externals/libcdi"]
+        path = externals/libcdi
+        url = {git_mirror}/libcdi.git
+        """
+
+        # Replace the content of the original file with the patch
+        with git_submodules_file.open("w") as out_f:
+            out_f.write(git_modules_patch)
+
+        # Run git submodule update
+        git = which("git")
+        git("submodule", "update", "--init", "--recursive")
+
+
+    def setup_build_environment(self, env):
+        spec = self.spec
+        # Some environment variables to set
+        env_variables_to_set = {
+#           "CC": spec["mpi"].mpicc,
+#           "FC": spec["mpi"].mpifc,
+#           "F77": spec["mpi"].mpif77,
+            "CXXFLAGS": "-O2 -g -fopenmp -Wunused -DNOMPI",
+            "FCFLAGS": "-I/usr/include --std=f2008 -O2 -g -cpp -fopenmp -fbounds-check -Wunused -DNOMPI",
+            "LIBS": "-leccodes -lgfortran -lhdf5 -lxml2",
+        }
+        for variable, value in env_variables_to_set.items():
+                env.set(variable, value)
+
+
+
+    def install(self, spec, prefix):
+        options = [
+            f"--prefix={prefix}",
+            "--enable-grib2",
+            "--enable-iso-c-interface",
+            f"--with-netcdf={spec['netcdf-c'].prefix}"
+        ]
+
+        configure(*options)
+        make()
+        make("install")
+
diff --git a/spack_repo/packages/icon-nwp/package.py b/spack_repo/packages/icon-nwp/package.py
new file mode 100644
index 0000000..72e9a89
--- /dev/null
+++ b/spack_repo/packages/icon-nwp/package.py
@@ -0,0 +1,199 @@
+# Copyright 2013-2022 Lawrence Livermore National Security, LLC and other
+# Spack Project Developers. See the top-level COPYRIGHT file for details.
+#
+# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+
+from spack.package import *
+from pathlib import Path
+
+
+class IconNwp(Package):
+    """
+    Recipe to build ICON-NWP using the LMU gitlab repository.
+    """
+
+    homepage = "https://code.mpimet.mpg.de/projects/iconpublic"
+    
+    # Main repository (pointing to LMU's gitlab)
+    git = "ssh://git@gitlab.physik.uni-muenchen.de/w2w/icon.git"
+
+    # Version w2w-B6 points to a different repository and branch)
+    version("w2w-B6", git="ssh://git@gitlab.physik.uni-muenchen.de/w2w/icon-w2w.git", branch="icon-w2w/icon-nwp-B6")
+    # FIXME: The ugly configuration system in older icon versions prevents us from using this package with it.
+    # version("2.5.0-nwp3", branch="icon-nwp/op-release-2.5.0-nwp3")
+    version("2.6.4-nwp3", branch="icon-nwp/op-release-2.6.4-nwp3")
+    version("2.6.5-nwp0", branch="icon-nwp/op-release-2.6.5-nwp0")
+    version("master", branch="master")
+    version("psp", branch="icon-nwp/icon-nwp-psp")
+
+
+    # Dependencies
+    depends_on("mpi")
+    depends_on("netcdf-c")
+    depends_on("netcdf-fortran")
+    depends_on("eccodes")
+    depends_on("libxml2")
+
+    # Extra dependencies for B6, including yaml, and the hdf5 filters for compression.
+    depends_on("libyaml", when="@w2w-B6")
+    depends_on("hdf5-blosc", when="@w2w-B6")
+    depends_on("h5z-zfp", when="@w2w-B6")
+    depends_on("sz~hdf5", when="@w2w-B6")
+    depends_on("sz3~hdf5", when="@w2w-B6")
+
+    phases = ["configure", "build", "install"]
+
+    def patch(self):
+        """
+        Because of the lack of access rights to the original submodule repositories,
+        we patch the gitmodules file to point to a different mirror.
+        """
+        git_submodules_file = Path().cwd() / ".gitmodules"
+
+        git_mirror = "git@gitlab.lrz.de:dkrz-mirror"
+
+        git_modules_patch = f"""
+        [submodule "externals/mtime"]
+                path = externals/mtime
+                url = {git_mirror}/libmtime.git
+        [submodule "externals/jsbach"]
+                path = externals/jsbach
+                url = {git_mirror}/jsbach.git
+        [submodule "externals/yac"]
+                path = externals/yac
+                url = {git_mirror}/YAC.git
+        [submodule "externals/self"]
+                path = externals/self
+                url = {git_mirror}/libself.git
+        [submodule "externals/tixi"]
+                path = externals/tixi
+                url = {git_mirror}/libtixi.git
+        [submodule "externals/yaxt"]
+                path = externals/yaxt
+                url = {git_mirror}/yaxt.git
+        [submodule "externals/rte-rrtmgp"]
+                path = externals/rte-rrtmgp
+                url = https://github.com/earth-system-radiation/rte-rrtmgp.git
+        [submodule "externals/cub"]
+                path = externals/cub
+                url = https://github.com/NVlabs/cub.git
+        [submodule "externals/omni-xmod-pool"]
+                path = externals/omni-xmod-pool
+                url = https://github.com/claw-project/omni-xmod-pool.git
+        [submodule "externals/cdi"]
+                path = externals/cdi
+                url = {git_mirror}/libcdi.git
+        [submodule "externals/sct"]
+                path = externals/sct
+                url = {git_mirror}/sct.git
+        [submodule "externals/ecrad"]
+                path = externals/ecrad
+                url = {git_mirror}/libecrad.git
+        [submodule "externals/dace_icon"]
+                path = externals/dace_icon
+                url = {git_mirror}/dace-icon-interface.git
+        [submodule "externals/emvorado"]
+                path = externals/emvorado
+                url = {git_mirror}/emvorado-for-icon.git
+        [submodule "utils/mkexp"]
+                path = utils/mkexp
+                url = https://git.mpimet.mpg.de/public/mkexp
+        [submodule "externals/art"]
+                path = externals/art
+                url = {git_mirror}/art.git
+        [submodule "externals/ppm"]
+                path = externals/ppm
+                url = https://gitlab.dkrz.de/jahns/ppm.git
+        [submodule "externals/probtest"]
+                path = externals/probtest
+                url = {git_mirror}/cscs-sw_probtest.git
+        """
+
+        # Replace the content of the original file with the patch
+        with git_submodules_file.open("w") as out_f:
+            out_f.write(git_modules_patch)
+
+        # Run git submodule update
+        git = which("git")
+        git("submodule", "update", "--init", "--recursive")
+
+    def setup_build_environment(self, env):
+
+        spec = self.spec
+
+        # Some environment variables to set
+        env_variables_to_set = {
+            "CC": spec["mpi"].mpicc,
+            "FC": spec["mpi"].mpifc,
+            "F77": spec["mpi"].mpif77,
+        }
+        for variable, value in env_variables_to_set.items():
+                env.set(variable, value)
+
+    def configure(self, spec, prefix):
+        spec = self.spec
+        print(spec['mpi'].mpifc)
+
+        libs = [
+            f"-L{spec['netcdf-c'].prefix.lib} -lnetcdf ",  # netcdf-c libs
+            f"-L{spec['netcdf-fortran'].prefix.lib} -lnetcdff",  # netcdf-fortran libs
+            "-lopenblas",  # OpenBlas
+            f"-L{spec['eccodes'].prefix.lib} -leccodes_f90 -leccodes",
+            f"-L{spec['libxml2'].prefix.lib} -lxml2",  # XML2 libs
+        ]
+
+        if self.spec.version == Version("w2w-B6"):
+            libs.append("-lyaml")
+
+        mtune = "generic"
+        INCLUDES = f"-I{spec['libxml2'].prefix}/include/libxml2"
+        options = [
+            f"CC={spec['mpi'].mpicc}",
+            f"FC={spec['mpi'].mpifc}",
+            f"CFLAGS=-g -mpc64 {INCLUDES}",
+            f"ICON_CFLAGS=-O3 -g -mtune={mtune}",
+            f"ICON_BUNDLED_CFLAGS=-O3 -mtune={mtune}",
+            "FCFLAGS=-std=legacy -fmodule-private -fimplicit-none -fmax-identifier-length=63 -Wall -Wcharacter-truncation -Wconversion -Wunderflow -Wunused-parameter -Wno-surprising -fall-intrinsics -g -mpc64 -w",
+            "ICON_FCFLAGS=-fbacktrace -fbounds-check -fstack-protector-all -finit-real=nan -finit-integer=-2147483648 -finit-character=127 -w -O2",
+            f"ICON_OCEAN_FCFLAGS=-O3 -mtune={mtune}",
+            f"LDFLAGS={' '.join(libs)}",
+            f"LIBS={' '.join(libs)}",
+            f"--prefix={prefix}",
+            f"--enable-grib2",
+        ]
+
+        # For some reason there's a problem with OpenMPI with gcc@11.3.0 which makes the configuration fail.
+        if self.spec.compiler.name == "gcc" and self.spec.compiler.version == Version("11.3.0"):
+            options.append("--enable-mpi-checks=no")
+        configure(*options)
+
+    def build(self, spec, prefix):
+        make()
+
+    def install(self, spec, prefix):
+        make("install")
+
+        # Create extra folders with the data and the docs
+        self.make_extra_folders(prefix)
+
+    def setup_run_environment(self, env):
+        env.set("ICON_BASE_PATH", self.spec.prefix)
+        env.set("ICON_DATA_PATH", self.spec.prefix.join("data"))
+        env.set("ICON_DOCS_PATH", self.spec.prefix.join("doc"))
+
+
+    def make_extra_folders(self, prefix):
+        mkdir = which("mkdir")
+        rsync = which("rsync")
+        curl = which("curl")
+
+        # copy executables and documentation
+        mkdir("-p", f"{prefix}/data")
+        mkdir("-p", f"{prefix}/doc")
+        mkdir("-p", f"{prefix}/run")
+        rsync("-av", "data/", f"{prefix}/data")
+        rsync("-av", "run/", f"{prefix}/run")
+        rsync("-av", "--include='*.pdf'", "--exclude='*.*'", "doc/", f"{prefix}/doc/")
+        curl("https://code.mpimet.mpg.de/attachments/download/19568/ICON_tutorial_2019.pdf", "--output", f"{prefix}/doc/ICON_tutorial_2019.pdf")
+        curl("http://www.cosmo-model.org/content/model/documentation/core/emvorado_userguide.pdf", "--output", f"{prefix}/doc/emvorado_userguide.pdf")
+
diff --git a/spack_repo/repo.yaml b/spack_repo/repo.yaml
new file mode 100644
index 0000000..332f5cb
--- /dev/null
+++ b/spack_repo/repo.yaml
@@ -0,0 +1,2 @@
+repo:
+  namespace: 'autosubmit-icon-repository'
diff --git a/templates/common/build_icon.sh b/templates/common/build_icon.sh
index 65b6386..75789e7 100644
--- a/templates/common/build_icon.sh
+++ b/templates/common/build_icon.sh
@@ -18,6 +18,7 @@ SPACK_BUILD_ICON=%icon.spack_cmd%
 if [ ! -z $SPACK_BUILD_ICON ]; then
   echo "Installing ICON with spack!"
   echo "cmd=$SPACK_BUILD_ICON"
+  spack repo add ${WORKDIR}/proj/spack_repo
   spack install $SPACK_BUILD_ICON
   spack load $SPACK_BUILD_ICON
 fi
-- 
GitLab