From 881ff92fb8bbae8f430fb3ba017da950a2a59e48 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 24 Jan 2025 15:46:51 -0700 Subject: [PATCH 01/22] update atmos tag --- .dockerignore | 21 +++++------ .gitmodules | 2 +- README.md | 2 +- docker/Dockerfile | 12 ++++--- docker/Dockerfile.esmf | 3 +- docker/Dockerfile.musica | 35 ++++++++++++------- .../utils/musica_ccpp_dependencies.meta | 2 +- 7 files changed, 42 insertions(+), 35 deletions(-) diff --git a/.dockerignore b/.dockerignore index 12b85fe8..e365f129 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,14 +1,9 @@ -# ignore all -* +.github/ + +# Ignore editor temporaries and backups +*.swp +*~ +.#* +\#*# +**/.vscode/ -# include things to copy -!Externals* -!src/ -!cime_config/ -!manage_externals/ -!test/ -!.config_files.xml -!docker -!bin/ -!.lib/ -!.gitmodules diff --git a/.gitmodules b/.gitmodules index ae8c3a76..c2d84576 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,7 +20,7 @@ [submodule "ncar-physics"] path = src/physics/ncar_ccpp url = https://github.com/ESCOMP/atmospheric_physics - fxtag = 74e905b7a0ee5b2d2bfc3e3dd942eb9963398373 + fxtag = e8a29b37fb86af36035d585c6c87dd815e007927 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics [submodule "ccs_config"] diff --git a/README.md b/README.md index 35b3bcbb..6358f935 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ cd CAM-SIMA ## NOTE: This is **unsupported** development code and is subject to the [CESM developer's agreement](http://www.cgd.ucar.edu/cseg/development-code.html). ``` git checkout development -./manage_externals/checkout_externals +./bin/git-fleximod update ``` Good luck, and have a great day! diff --git a/docker/Dockerfile b/docker/Dockerfile index 098db37d..fe8684b5 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,6 +1,7 @@ # parts of CAM require x86 architecture (gptl, which relies on the rdtsc x86 assembly instruction) # esmf is am image you are expected to have built. Read the README file for instructions -FROM --platform=linux/amd64 esmf:latest +# FROM --platform=linux/amd64 esmf:latest +FROM esmf:latest ################################################### ## Install necessary packages @@ -19,7 +20,8 @@ RUN dnf -y update \ vim \ && dnf clean all -RUN ln -s $(which python3) /usr/bin/python && \ +RUN rm -f /usr/bin/python && \ + ln -s $(which python3) /usr/bin/python && \ pip install --upgrade pip && \ pip install --upgrade setuptools @@ -85,6 +87,6 @@ RUN chmod +x /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh RUN /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh # add the snapshot file -RUN echo "ncdata='/home/cam_sima_user/run_heldsuarez_cam6_nt2_bigg_try005.cam.h5.0001-01-01-00000.nc'" >> user_nl_cam - -RUN ./case.build \ No newline at end of file +# RUN echo "ncdata='/home/cam_sima_user/run_heldsuarez_cam6_nt2_bigg_try005.cam.h5.0001-01-01-00000.nc'" >> user_nl_cam +# RUN sed -i '5191s/^/\/\//g' /home/cam_sima_user/CAM-SIMA/cime/CIME/non_py/src/timing/gptl.c +# RUN ./case.build \ No newline at end of file diff --git a/docker/Dockerfile.esmf b/docker/Dockerfile.esmf index 4a678b32..882ac673 100644 --- a/docker/Dockerfile.esmf +++ b/docker/Dockerfile.esmf @@ -1,5 +1,6 @@ # parts of CAM require x86 architecture (gptl, which relies on the rdtsc x86 assembly instruction) -FROM --platform=linux/amd64 fedora:latest +# FROM --platform=linux/amd64 fedora:latest +FROM fedora:latest ################################################### ## Install necessary packages diff --git a/docker/Dockerfile.musica b/docker/Dockerfile.musica index 0f59f21d..1e435ed5 100644 --- a/docker/Dockerfile.musica +++ b/docker/Dockerfile.musica @@ -1,6 +1,10 @@ # parts of CAM require x86 architecture (gptl, which relies on the rdtsc x86 assembly instruction) # esmf is am image you are expected to have built. Read the README file for instructions -FROM --platform=linux/amd64 esmf:latest +# FROM --platform=linux/amd64 esmf:latest +FROM esmf:latest + +ARG MUSICA_GIT_TAG=326b5119768d5be9654baf96ae3bd6a1b757fdc8 +ARG BUILD_TYPE=Debug ################################################### ## Install necessary packages @@ -19,7 +23,8 @@ RUN dnf -y update \ vim \ && dnf clean all -RUN ln -s $(which python3) /usr/bin/python && \ +RUN rm -f /usr/bin/python && \ + ln -s $(which python3) /usr/bin/python && \ pip install --upgrade pip && \ pip install --upgrade setuptools @@ -39,23 +44,24 @@ RUN cd pnetcdf-1.12.3 && \ make -j 8 install && \ ldconfig -ENV FC=gfortran - ################################################### ## Build and install MUSICA ################################################### RUN git clone https://github.com/NCAR/musica.git \ && cd musica \ - && git checkout 2a5eeaac982a3eb80b96d1e2087b91b301d1e748 - -RUN mkdir /musica/build \ - && cd /musica/build \ - && cmake \ - -D ENABLE_TESTS=OFF \ + && git checkout ${MUSICA_GIT_TAG} \ + && cmake -S . -B build \ + -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ + -D MUSICA_ENABLE_TESTS=OFF \ -D MUSICA_BUILD_FORTRAN_INTERFACE=ON \ - .. \ - && make install -j 8 + -D MUSICA_ENABLE_MICM=ON \ + -D MUSICA_ENABLE_TUVX=ON \ + -D CMAKE_Fortran_COMPILER=mpif90 \ + -D CMAKE_C_COMPILER=mpicc \ + -D CMAKE_CXX_COMPILER=mpicxx \ + && cd build \ + && make install -j 8 ################################################### ## Build CAM-SIMA @@ -98,6 +104,7 @@ RUN ./xmlchange CAM_LINKED_LIBS="-lmusica-fortran -lmusica -lyaml-cpp" RUN ./xmlchange ROF_NCPL=48 RUN ./xmlchange STOP_OPTION=nsteps RUN ./xmlchange STOP_N=5 +# RUN ./xmlchange PIO_CONFIG_OPTS="--enable-timing=no" # Copy in the grid files and a snapshot file RUN chmod +x /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh @@ -106,4 +113,6 @@ RUN /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh # # add the snapshot file RUN echo "ncdata='/home/cam_sima_user/run_heldsuarez_cam6_nt2_bigg_try005.cam.h5.0001-01-01-00000.nc'" >> user_nl_cam -RUN ./case.build +# RUN sed -i '5191s/^/\/\//g' /home/cam_sima_user/CAM-SIMA/cime/CIME/non_py/src/timing/gptl.c + +# RUN ./case.build diff --git a/src/physics/utils/musica_ccpp_dependencies.meta b/src/physics/utils/musica_ccpp_dependencies.meta index 0d14908e..3bace688 100644 --- a/src/physics/utils/musica_ccpp_dependencies.meta +++ b/src/physics/utils/musica_ccpp_dependencies.meta @@ -30,7 +30,7 @@ protected = True [ surface_albedo ] standard_name = surface_albedo_due_to_UV_and_VIS_direct - units = none + units = fraction type = real | kind = kind_phys dimensions = (horizontal_dimension) protected = True From 50b0e6cfee02e930db50d0ba4eff891e850428a7 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 6 Feb 2025 14:05:06 -0700 Subject: [PATCH 02/22] add install musica function to buildlb --- .gitmodules | 2 +- cime_config/buildlib | 116 ++++++++++++++++++++++++++++++++++- cime_config/musica_config.py | 9 +++ 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 cime_config/musica_config.py diff --git a/.gitmodules b/.gitmodules index c2d84576..bf3a6bc5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,7 +20,7 @@ [submodule "ncar-physics"] path = src/physics/ncar_ccpp url = https://github.com/ESCOMP/atmospheric_physics - fxtag = e8a29b37fb86af36035d585c6c87dd815e007927 + fxtag = 60b71f3fd9f10b362caf64afffce12de10854d4d fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics [submodule "ccs_config"] diff --git a/cime_config/buildlib b/cime_config/buildlib index 33f1d3ec..a6e6e1c1 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -8,9 +8,12 @@ import sys import os import filecmp import shutil +import subprocess import logging from cam_config import ConfigCAM # CAM's configure structure +from musica_config import musica_repo_url, musica_tag +from musica_config import chemistry_data_repo_url, chemistry_data_tag # Check for the CIME library, and add it # to the python path: @@ -22,7 +25,7 @@ sys.path.append(os.path.join(__CIMEROOT, "CIME", "Tools")) #pylint: disable=wrong-import-position # CIME imports from CIME.case import Case -from CIME.utils import run_cmd, expect +from CIME.utils import run_cmd, expect, symlink_force from CIME.utils import stop_buffering_output from CIME.buildlib import parse_input from CIME.build import get_standard_makefile_args @@ -76,6 +79,7 @@ def _build_cam(): config.generate_cam_src(gen_indent) dycore = config.get_value('dyn') + physics_suites = config.get_value('physics_suites') reg_dir = config.get_value('reg_dir') init_dir = config.get_value('init_dir') phys_dirs_str = config.get_value('phys_dirs') @@ -150,6 +154,10 @@ def _build_cam(): if dycore == "mpas": _setup_mpas(case) + if physics_suites == "musica": + _build_musica_library(case) + _download_musica_configuration(case) + complib = os.path.join(libroot, "libatm.a") makefile = os.path.join(casetools, "Makefile") @@ -213,6 +221,112 @@ def _copy2_as_needed(src: str, dst: str) -> None: # Example scenario: User added some new source code files. shutil.copy2(src, dst) +def _build_musica_library(case: Case) -> None: + + install_dir_name = "install" + build_type = "Release" + + clone_dest = os.path.normpath(case.get_value("CASEROOT")) + _clone_and_checkout(musica_repo_url, musica_tag, clone_dest) + + bld_path = os.path.normpath(os.path.join(clone_dest, "musica", "build")) + # Ensure the build directory is clean + if os.path.exists(bld_path): + print(f"Removing existing build directory: {bld_path}") + shutil.rmtree(bld_path) + + os.makedirs(bld_path) + os.chdir(bld_path) + + # Run cmake to configure the project + print("Configuring the project with CMake...") + command = [ + "cmake", + f"-DCMAKE_INSTALL_PREFIX={install_dir_name}", + f"-DCMAKE_BUILD_TYPE={build_type}", + f"-DMUSICA_ENABLE_TESTS=OFF", + f"-DMUSICA_BUILD_FORTRAN_INTERFACE=ON", + ".." + ] + print(f"Running command: {' '.join(command)}") + result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + if result.returncode != 0: + raise Exception(f"Unable to configure the MUSICA CMake project. Error: {result.stderr}") + + # Build the project + print("Building the project...") + command = ["cmake", "--build", ".", "--target", "install"] + result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + if result.returncode != 0: + raise Exception(f"Unable to build the MUSICA library. Error: {result.stderr}") + + print(f"MUSICA installed to {install_dir_name}") + + atm_bld_root = os.path.normpath(os.path.join(case.get_value("EXEROOT"), "atm", "obj")) + musica_lib_root = os.path.join(atm_bld_root, "musica") + os.makedirs(musica_lib_root, exist_ok=True) + musica_install_path = os.path.join(bld_path, install_dir_name, "lib64") + + root, _, files = next(os.walk(musica_install_path, topdown=True)) + for f in files: + symlink_force(os.path.join(root, f), os.path.join(musica_lib_root, f)) + +def _download_musica_configuration(case: Case) -> None: + """_summary_ + + """ + case_root = os.path.normpath(case.get_value("CASEROOT")) + musica_config_dir_name = "musica_configurations" + _clone_and_checkout(chemistry_data_repo_url, chemistry_data_tag, case_root) + + original_config_dir = os.path.join(case_root, "cam-sima-chemistry-data", "mechanisms") + renamed_config_dir = os.path.join(case_root, "cam-sima-chemistry-data", musica_config_dir_name) + try: + os.rename(original_config_dir, renamed_config_dir) + except FileNotFoundError: + raise Exception(f"The directory {original_config_dir} was not found.") + except Exception as e: + raise Exception(f"An error occurred while renaming: {e}") + + musica_config_path = os.path.join(case_root, musica_config_dir_name) + if os.path.exists(musica_config_path): + shutil.rmtree(musica_config_path) + + shutil.move(renamed_config_dir, case_root) + + +def _clone_and_checkout(repo_url, tag_name, clone_dest): + """ + Clones a Git repository from the provided URL and checks out a specific branch. + + Args: + repo_url (str): The URL of the Git repository to clone + tag_name (str): The tag name to check out + clone_dest (str): destination where the repository will be cloned + + Raises: + Exception: If the `git clone` or `git checkout` commands fail, + an exception is raised with the error message. + """ + repo_name = repo_url.split("/")[-1].replace(".git", "") + repo_path = os.path.normpath(os.path.join(clone_dest, repo_name)) + + # Run the git clone command + os.chdir(os.path.normpath(clone_dest)) + if os.path.exists(repo_path): + shutil.rmtree(repo_path) + + result = subprocess.run(["git", "clone", repo_url], stderr=subprocess.PIPE, text=True) + if result.returncode != 0: + raise Exception(f"Unable to clone the repository: {repo_url}. Error: {result.stderr}") + + # Run the git checkout command + os.chdir(repo_path) + result = subprocess.run(["git", "checkout", tag_name], stderr=subprocess.PIPE, text=True) + if result.returncode != 0: + raise Exception(f"Unable to checkout the branch: {tag_name}. Error: {result.stderr}") + + ############################################################################### if __name__ == "__main__": diff --git a/cime_config/musica_config.py b/cime_config/musica_config.py new file mode 100644 index 00000000..dbfa85de --- /dev/null +++ b/cime_config/musica_config.py @@ -0,0 +1,9 @@ +""" +The URLs and tags provided in this script are read by buildlib.py to build +and install the MUSICA library, as well as to download the MUSICA configuration." +""" + +musica_repo_url = "https://github.com/NCAR/musica.git" +musica_tag = "e0c3d219fc8bbfd388cd3c95a3646d2e3aa1e288" # main +chemistry_data_repo_url = "https://github.com/NCAR/cam-sima-chemistry-data.git" +chemistry_data_tag = "b81cbc2e61c41ecd2d09167d6736daf1bf1be149" \ No newline at end of file From 82637d4fbb52b871fbdc485cad8142feca31910a Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 7 Feb 2025 12:56:17 -0700 Subject: [PATCH 03/22] add building musica lib functions --- ...{musica_config.py => atm_musica_config.py} | 0 cime_config/buildlib | 73 +++++++++++++++---- docker/Dockerfile.esmf | 7 +- docker/Dockerfile.musica | 10 +-- 4 files changed, 66 insertions(+), 24 deletions(-) rename cime_config/{musica_config.py => atm_musica_config.py} (100%) diff --git a/cime_config/musica_config.py b/cime_config/atm_musica_config.py similarity index 100% rename from cime_config/musica_config.py rename to cime_config/atm_musica_config.py diff --git a/cime_config/buildlib b/cime_config/buildlib index a6e6e1c1..1ffc32d5 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -12,8 +12,8 @@ import subprocess import logging from cam_config import ConfigCAM # CAM's configure structure -from musica_config import musica_repo_url, musica_tag -from musica_config import chemistry_data_repo_url, chemistry_data_tag +from atm_musica_config import musica_repo_url, musica_tag +from atm_musica_config import chemistry_data_repo_url, chemistry_data_tag # Check for the CIME library, and add it # to the python path: @@ -157,6 +157,9 @@ def _build_cam(): if physics_suites == "musica": _build_musica_library(case) _download_musica_configuration(case) + # clone_dest = os.path.normpath(case.get_value("CASEROOT")) + # bld_path = os.path.normpath(os.path.join(clone_dest, "musica", "build", "install", "include")) + # paths.append(bld_path) complib = os.path.join(libroot, "libatm.a") makefile = os.path.join(casetools, "Makefile") @@ -172,6 +175,24 @@ def _build_cam(): retcode, out, err = run_cmd(cmd) _LOGGER.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n", cmd, out, err) expect(retcode == 0, f"Command {cmd} failed with rc={retcode}") + + + # JIWON + if physics_suites == "musica": + clone_dest = os.path.normpath(case.get_value("CASEROOT")) + # bld_path = os.path.normpath(os.path.join(clone_dest, "musica", "build", "install", "include")) + bld_path = os.path.normpath(os.path.join(case.get_value("EXEROOT"), "atm", "obj", "musica", "include")) + cmd = f"{gmake} complib -j {gmake_j} MODEL=cam USER_INCLDIR={bld_path}" + cmd += f" -f {makefile} {get_standard_makefile_args(case)} " + + # Add C Pre-Processor (CPP) definitions, if present: + if config.cpp_defs: + ccpp_defs_str = ' '.join(config.cpp_defs) + cmd += f" USER_CPPDEFS='{ccpp_defs_str}'" + + retcode, out, err = run_cmd(cmd) + _LOGGER.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n", cmd, out, err) + expect(retcode == 0, f"Command {cmd} failed with rc={retcode}") def _setup_mpas(case: Case) -> None: """ @@ -263,7 +284,7 @@ def _build_musica_library(case: Case) -> None: print(f"MUSICA installed to {install_dir_name}") atm_bld_root = os.path.normpath(os.path.join(case.get_value("EXEROOT"), "atm", "obj")) - musica_lib_root = os.path.join(atm_bld_root, "musica") + musica_lib_root = os.path.join(atm_bld_root, "musica", "lib") os.makedirs(musica_lib_root, exist_ok=True) musica_install_path = os.path.join(bld_path, install_dir_name, "lib64") @@ -271,12 +292,43 @@ def _build_musica_library(case: Case) -> None: for f in files: symlink_force(os.path.join(root, f), os.path.join(musica_lib_root, f)) + src_dir = os.path.join(bld_path, install_dir_name, "include") + dest_dir = os.path.join(atm_bld_root, "musica", "include") + # os.makedirs(dest_dir, exist_ok=True) + # Walk through the source directory + # for root, dirs, files in os.walk(src_dir): + # # Calculate the relative path from the source directory + # rel_path = os.path.relpath(root, src_dir) + # # Define the corresponding path in the destination + # dest_root = os.path.join(dest_dir, rel_path) + + # # Create the destination directory structure if it doesn't exist + # os.makedirs(dest_root, exist_ok=True) + + # # Create symlinks for all files in the current directory + # for file in files: + # src_file = os.path.join(root, file) + # dest_file = os.path.join(dest_root, file) + + # # Create a symlink if it doesn't already exist + # if not os.path.exists(dest_file): + # os.symlink(src_file, dest_file) + # try: + # os.symlink(src_file, dest_file) + # print(f"Created symlink: {dest_file} -> {src_file}") + # except OSError as e: + # print(f"Error creating symlink for {src_file}: {e}") + # else: + # print(f"Symlink already exists: {dest_file}") + + def _download_musica_configuration(case: Case) -> None: """_summary_ """ - case_root = os.path.normpath(case.get_value("CASEROOT")) musica_config_dir_name = "musica_configurations" + + case_root = os.path.normpath(case.get_value("CASEROOT")) _clone_and_checkout(chemistry_data_repo_url, chemistry_data_tag, case_root) original_config_dir = os.path.join(case_root, "cam-sima-chemistry-data", "mechanisms") @@ -302,31 +354,26 @@ def _clone_and_checkout(repo_url, tag_name, clone_dest): Args: repo_url (str): The URL of the Git repository to clone tag_name (str): The tag name to check out - clone_dest (str): destination where the repository will be cloned + clone_dest (str): destination where the repository will be cloned. (absolute path) Raises: Exception: If the `git clone` or `git checkout` commands fail, an exception is raised with the error message. """ repo_name = repo_url.split("/")[-1].replace(".git", "") - repo_path = os.path.normpath(os.path.join(clone_dest, repo_name)) + repo_path = os.path.join(clone_dest, repo_name) - # Run the git clone command - os.chdir(os.path.normpath(clone_dest)) if os.path.exists(repo_path): shutil.rmtree(repo_path) - result = subprocess.run(["git", "clone", repo_url], stderr=subprocess.PIPE, text=True) + result = subprocess.run(["git", "clone", repo_url, repo_path], stderr=subprocess.PIPE, text=True) if result.returncode != 0: raise Exception(f"Unable to clone the repository: {repo_url}. Error: {result.stderr}") - # Run the git checkout command - os.chdir(repo_path) - result = subprocess.run(["git", "checkout", tag_name], stderr=subprocess.PIPE, text=True) + result = subprocess.run(["git", "-C", repo_path, "checkout", tag_name], stderr=subprocess.PIPE, text=True) if result.returncode != 0: raise Exception(f"Unable to checkout the branch: {tag_name}. Error: {result.stderr}") - ############################################################################### if __name__ == "__main__": diff --git a/docker/Dockerfile.esmf b/docker/Dockerfile.esmf index 882ac673..ff6976b2 100644 --- a/docker/Dockerfile.esmf +++ b/docker/Dockerfile.esmf @@ -1,6 +1,5 @@ # parts of CAM require x86 architecture (gptl, which relies on the rdtsc x86 assembly instruction) -# FROM --platform=linux/amd64 fedora:latest -FROM fedora:latest +FROM --platform=linux/amd64 fedora:latest ################################################### ## Install necessary packages @@ -30,7 +29,7 @@ ENV OMP_NUM_THREADS=5 ## Build and install ESMF ################################################### -ENV ESMF_TAG="8.4.2" +ENV ESMF_TAG="8.6.0" # set necessary environment variables ENV ESMF_DIR=/esmf-${ESMF_TAG} @@ -52,4 +51,4 @@ RUN wget -q https://github.com/esmf-org/esmf/archive/refs/tags/v${ESMF_TAG}.tar. # This command lets you see what esmf thinks its build options are but may not necessary to build, not sure make info && \ make -j 8 && \ - make install + make install \ No newline at end of file diff --git a/docker/Dockerfile.musica b/docker/Dockerfile.musica index 1e435ed5..6d96d7b6 100644 --- a/docker/Dockerfile.musica +++ b/docker/Dockerfile.musica @@ -1,9 +1,8 @@ # parts of CAM require x86 architecture (gptl, which relies on the rdtsc x86 assembly instruction) # esmf is am image you are expected to have built. Read the README file for instructions -# FROM --platform=linux/amd64 esmf:latest -FROM esmf:latest +FROM --platform=linux/amd64 esmf:latest -ARG MUSICA_GIT_TAG=326b5119768d5be9654baf96ae3bd6a1b757fdc8 +ARG MUSICA_GIT_TAG=e0c3d219fc8bbfd388cd3c95a3646d2e3aa1e288 ARG BUILD_TYPE=Debug ################################################### @@ -104,7 +103,6 @@ RUN ./xmlchange CAM_LINKED_LIBS="-lmusica-fortran -lmusica -lyaml-cpp" RUN ./xmlchange ROF_NCPL=48 RUN ./xmlchange STOP_OPTION=nsteps RUN ./xmlchange STOP_N=5 -# RUN ./xmlchange PIO_CONFIG_OPTS="--enable-timing=no" # Copy in the grid files and a snapshot file RUN chmod +x /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh @@ -113,6 +111,4 @@ RUN /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh # # add the snapshot file RUN echo "ncdata='/home/cam_sima_user/run_heldsuarez_cam6_nt2_bigg_try005.cam.h5.0001-01-01-00000.nc'" >> user_nl_cam -# RUN sed -i '5191s/^/\/\//g' /home/cam_sima_user/CAM-SIMA/cime/CIME/non_py/src/timing/gptl.c - -# RUN ./case.build +RUN ./case.build From 7e02d9045b36c5ee1fd5d006f7cce54681b2c354 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 19 Feb 2025 19:30:08 -0700 Subject: [PATCH 04/22] update docker to build case --- cime_config/atm_musica_config.py | 4 +- cime_config/buildlib | 194 +++++++++++++++---------------- docker/Dockerfile.musica | 39 ++----- 3 files changed, 106 insertions(+), 131 deletions(-) diff --git a/cime_config/atm_musica_config.py b/cime_config/atm_musica_config.py index dbfa85de..a63bcabc 100644 --- a/cime_config/atm_musica_config.py +++ b/cime_config/atm_musica_config.py @@ -1,9 +1,9 @@ """ -The URLs and tags provided in this script are read by buildlib.py to build +The URLs and tags provided in this script are read by buildlib to build and install the MUSICA library, as well as to download the MUSICA configuration." """ musica_repo_url = "https://github.com/NCAR/musica.git" -musica_tag = "e0c3d219fc8bbfd388cd3c95a3646d2e3aa1e288" # main +musica_tag = "802bc9041f964a7edd5ec896bec8cdc0c90de50b" chemistry_data_repo_url = "https://github.com/NCAR/cam-sima-chemistry-data.git" chemistry_data_tag = "b81cbc2e61c41ecd2d09167d6736daf1bf1be149" \ No newline at end of file diff --git a/cime_config/buildlib b/cime_config/buildlib index 1ffc32d5..93d5f584 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -79,7 +79,7 @@ def _build_cam(): config.generate_cam_src(gen_indent) dycore = config.get_value('dyn') - physics_suites = config.get_value('physics_suites') + phys_suites = config.get_value('physics_suites') reg_dir = config.get_value('reg_dir') init_dir = config.get_value('init_dir') phys_dirs_str = config.get_value('phys_dirs') @@ -125,6 +125,7 @@ def _build_cam(): paths.append(os.path.join(atm_root, "src", "dynamics", "tests", "initial_conditions")) + # TODO(jiwon); this path is not found # If using the CMEPS/NUOPC coupler, then add additional path: if case.get_value("COMP_INTERFACE") == "nuopc": paths.append(os.path.join(__CIMEROOT, "src", "drivers", @@ -135,7 +136,7 @@ def _build_cam(): with open(filepath_src, "w", encoding='utf-8') as filepath: filepath.write("\n".join(paths)) filepath.write("\n") - # End with + # End if # Move Filepath to the bld directory unless it has not changed if os.path.isfile(filepath_dst): @@ -154,17 +155,25 @@ def _build_cam(): if dycore == "mpas": _setup_mpas(case) - if physics_suites == "musica": + # If the physics suite is MUSICA, build the MUSICA library and configuration + if phys_suites == "musica": _build_musica_library(case) - _download_musica_configuration(case) - # clone_dest = os.path.normpath(case.get_value("CASEROOT")) - # bld_path = os.path.normpath(os.path.join(clone_dest, "musica", "build", "install", "include")) - # paths.append(bld_path) + _download_musica_configuration(caseroot) complib = os.path.join(libroot, "libatm.a") makefile = os.path.join(casetools, "Makefile") cmd = f"{gmake} complib -j {gmake_j} MODEL=cam COMPLIB={complib}" + + if phys_suites == "musica": + cmd += ' USER_INCLDIR="'\ + f'-I{os.path.join(bldroot, "musica", "include", "micm")} '\ + f'-I{os.path.join(bldroot, "musica", "include", "musica")} '\ + f'-I{os.path.join(bldroot, "musica", "include", "musica", "micm")} '\ + f'-I{os.path.join(bldroot, "musica", "include", "musica", "tuvx")} '\ + f'-I{os.path.join(bldroot, "musica", "include", "musica", "fortran")} '\ + '"' + cmd += f" -f {makefile} {get_standard_makefile_args(case)} " # Add C Pre-Processor (CPP) definitions, if present: @@ -175,26 +184,10 @@ def _build_cam(): retcode, out, err = run_cmd(cmd) _LOGGER.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n", cmd, out, err) expect(retcode == 0, f"Command {cmd} failed with rc={retcode}") - - - # JIWON - if physics_suites == "musica": - clone_dest = os.path.normpath(case.get_value("CASEROOT")) - # bld_path = os.path.normpath(os.path.join(clone_dest, "musica", "build", "install", "include")) - bld_path = os.path.normpath(os.path.join(case.get_value("EXEROOT"), "atm", "obj", "musica", "include")) - cmd = f"{gmake} complib -j {gmake_j} MODEL=cam USER_INCLDIR={bld_path}" - cmd += f" -f {makefile} {get_standard_makefile_args(case)} " - - # Add C Pre-Processor (CPP) definitions, if present: - if config.cpp_defs: - ccpp_defs_str = ' '.join(config.cpp_defs) - cmd += f" USER_CPPDEFS='{ccpp_defs_str}'" - - retcode, out, err = run_cmd(cmd) - _LOGGER.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n", cmd, out, err) - expect(retcode == 0, f"Command {cmd} failed with rc={retcode}") +############################################################################### def _setup_mpas(case: Case) -> None: +############################################################################### """ Setup MPAS build infrastructure. """ @@ -222,7 +215,9 @@ def _setup_mpas(case: Case) -> None: shutil.copytree(os.path.normpath(os.path.join(mpas_dycore_src_root, os.pardir, os.pardir, "assets")), mpas_dycore_bld_root, copy_function=_copy2_as_needed, dirs_exist_ok=True) shutil.copytree(os.path.normpath(os.path.join(mpas_dycore_src_root, os.pardir, os.pardir, "driver")), os.path.join(mpas_dycore_bld_root, "driver"), copy_function=_copy2_as_needed, dirs_exist_ok=True) +############################################################################### def _copy2_as_needed(src: str, dst: str) -> None: +############################################################################### """ Wrapper around `shutil.copy2`. Copy the file `src` to the file or directory `dst` as needed. """ @@ -242,25 +237,34 @@ def _copy2_as_needed(src: str, dst: str) -> None: # Example scenario: User added some new source code files. shutil.copy2(src, dst) +############################################################################### def _build_musica_library(case: Case) -> None: +############################################################################### + """ + Builds and installs the MUSICA library. + + Args: + case (Case) + Raises: + Exception: If configuring the CMake MUSICA project fails or + the MUSICA library build fails, an exception is raised. + + """ install_dir_name = "install" build_type = "Release" + caseroot = os.path.normpath(case.get_value("CASEROOT")) + _clone_and_checkout(musica_repo_url, musica_tag, caseroot) - clone_dest = os.path.normpath(case.get_value("CASEROOT")) - _clone_and_checkout(musica_repo_url, musica_tag, clone_dest) - - bld_path = os.path.normpath(os.path.join(clone_dest, "musica", "build")) - # Ensure the build directory is clean + bld_path = os.path.join(caseroot, "musica", "build") if os.path.exists(bld_path): - print(f"Removing existing build directory: {bld_path}") shutil.rmtree(bld_path) - os.makedirs(bld_path) + + # To install the target, the working directory must be the build directory. + current_dir = os.getcwd() os.chdir(bld_path) - # Run cmake to configure the project - print("Configuring the project with CMake...") command = [ "cmake", f"-DCMAKE_INSTALL_PREFIX={install_dir_name}", @@ -269,92 +273,84 @@ def _build_musica_library(case: Case) -> None: f"-DMUSICA_BUILD_FORTRAN_INTERFACE=ON", ".." ] - print(f"Running command: {' '.join(command)}") result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) if result.returncode != 0: raise Exception(f"Unable to configure the MUSICA CMake project. Error: {result.stderr}") - # Build the project - print("Building the project...") command = ["cmake", "--build", ".", "--target", "install"] result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) if result.returncode != 0: raise Exception(f"Unable to build the MUSICA library. Error: {result.stderr}") - - print(f"MUSICA installed to {install_dir_name}") - atm_bld_root = os.path.normpath(os.path.join(case.get_value("EXEROOT"), "atm", "obj")) + # Create symlinks pointing to the MUSICA libraries in the ATM build directory + atm_bld_root = os.path.join(case.get_value("EXEROOT"), "atm", "obj") musica_lib_root = os.path.join(atm_bld_root, "musica", "lib") os.makedirs(musica_lib_root, exist_ok=True) - musica_install_path = os.path.join(bld_path, install_dir_name, "lib64") - - root, _, files = next(os.walk(musica_install_path, topdown=True)) - for f in files: - symlink_force(os.path.join(root, f), os.path.join(musica_lib_root, f)) - - src_dir = os.path.join(bld_path, install_dir_name, "include") - dest_dir = os.path.join(atm_bld_root, "musica", "include") - # os.makedirs(dest_dir, exist_ok=True) - # Walk through the source directory - # for root, dirs, files in os.walk(src_dir): - # # Calculate the relative path from the source directory - # rel_path = os.path.relpath(root, src_dir) - # # Define the corresponding path in the destination - # dest_root = os.path.join(dest_dir, rel_path) - - # # Create the destination directory structure if it doesn't exist - # os.makedirs(dest_root, exist_ok=True) - - # # Create symlinks for all files in the current directory - # for file in files: - # src_file = os.path.join(root, file) - # dest_file = os.path.join(dest_root, file) - - # # Create a symlink if it doesn't already exist - # if not os.path.exists(dest_file): - # os.symlink(src_file, dest_file) - # try: - # os.symlink(src_file, dest_file) - # print(f"Created symlink: {dest_file} -> {src_file}") - # except OSError as e: - # print(f"Error creating symlink for {src_file}: {e}") - # else: - # print(f"Symlink already exists: {dest_file}") - - -def _download_musica_configuration(case: Case) -> None: - """_summary_ + installed_lib_path = os.path.join(bld_path, install_dir_name, "lib64") + root, _, files = next(os.walk(installed_lib_path, topdown=True)) + for file in files: + symlink_force(os.path.join(root, file), os.path.join(musica_lib_root, file)) + + # Create symlinks pointing to the MUSICA include files in the ATM build directory + musica_include_root = os.path.join(atm_bld_root, "musica", "include") + os.makedirs(musica_include_root, exist_ok=True) + + installed_include_path = os.path.join(bld_path, install_dir_name, "include") + for root, _, files in os.walk(installed_include_path): + rel_path = os.path.relpath(root, installed_include_path) + dest_dir = os.path.join(musica_include_root, rel_path) + + os.makedirs(dest_dir, exist_ok=True) + for file in files: + symlink_force(os.path.join(root, file), os.path.join(dest_dir, file)) + + os.chdir(current_dir) + +############################################################################### +def _download_musica_configuration(download_dest: str) -> None: +############################################################################### + """ + Downloads the MUSICA configuration and renames the configuration + directory to match the name in the MUSICA-CCPP configuration. + + Args: + download_dest: destination where configuration will be downloaded. + + Raises: + Exception: If the directory to be renamed is not found or + any other exceptions occur during the renaming process, + an exception is raised with the error message. """ musica_config_dir_name = "musica_configurations" - case_root = os.path.normpath(case.get_value("CASEROOT")) - _clone_and_checkout(chemistry_data_repo_url, chemistry_data_tag, case_root) + _clone_and_checkout(chemistry_data_repo_url, chemistry_data_tag, download_dest) - original_config_dir = os.path.join(case_root, "cam-sima-chemistry-data", "mechanisms") - renamed_config_dir = os.path.join(case_root, "cam-sima-chemistry-data", musica_config_dir_name) + original_dir = os.path.join(download_dest, "cam-sima-chemistry-data", "mechanisms") + renamed_dir = os.path.join(download_dest, "cam-sima-chemistry-data", musica_config_dir_name) try: - os.rename(original_config_dir, renamed_config_dir) + os.rename(original_dir, renamed_dir) except FileNotFoundError: - raise Exception(f"The directory {original_config_dir} was not found.") + raise Exception(f"The directory {original_dir} was not found.") except Exception as e: raise Exception(f"An error occurred while renaming: {e}") - musica_config_path = os.path.join(case_root, musica_config_dir_name) + musica_config_path = os.path.join(download_dest, musica_config_dir_name) if os.path.exists(musica_config_path): shutil.rmtree(musica_config_path) - shutil.move(renamed_config_dir, case_root) - + shutil.move(renamed_dir, download_dest) -def _clone_and_checkout(repo_url, tag_name, clone_dest): +############################################################################### +def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str): +############################################################################### """ - Clones a Git repository from the provided URL and checks out a specific branch. + Clones a Git repository from the URL and checks out a specific branch. Args: - repo_url (str): The URL of the Git repository to clone - tag_name (str): The tag name to check out - clone_dest (str): destination where the repository will be cloned. (absolute path) + repo_url: The URL of the Git repository to clone + tag_name: The tag name to check out + clone_dest: destination where the repository will be cloned. Raises: Exception: If the `git clone` or `git checkout` commands fail, @@ -366,15 +362,19 @@ def _clone_and_checkout(repo_url, tag_name, clone_dest): if os.path.exists(repo_path): shutil.rmtree(repo_path) - result = subprocess.run(["git", "clone", repo_url, repo_path], stderr=subprocess.PIPE, text=True) + result = subprocess.run(["git", "clone", repo_url, repo_path], + stderr=subprocess.PIPE, text=True) if result.returncode != 0: - raise Exception(f"Unable to clone the repository: {repo_url}. Error: {result.stderr}") + raise Exception(f"Unable to clone the repository: {repo_url}. \ + Error: {result.stderr}") - result = subprocess.run(["git", "-C", repo_path, "checkout", tag_name], stderr=subprocess.PIPE, text=True) + result = subprocess.run(["git", "-C", repo_path, "checkout", tag_name], + stderr=subprocess.PIPE, text=True) if result.returncode != 0: - raise Exception(f"Unable to checkout the branch: {tag_name}. Error: {result.stderr}") + raise Exception(f"Unable to checkout the branch: {tag_name}. \ + Error: {result.stderr}") ############################################################################### if __name__ == "__main__": - _build_cam() + _build_cam() \ No newline at end of file diff --git a/docker/Dockerfile.musica b/docker/Dockerfile.musica index 6d96d7b6..810927e2 100644 --- a/docker/Dockerfile.musica +++ b/docker/Dockerfile.musica @@ -2,7 +2,6 @@ # esmf is am image you are expected to have built. Read the README file for instructions FROM --platform=linux/amd64 esmf:latest -ARG MUSICA_GIT_TAG=e0c3d219fc8bbfd388cd3c95a3646d2e3aa1e288 ARG BUILD_TYPE=Debug ################################################### @@ -43,41 +42,22 @@ RUN cd pnetcdf-1.12.3 && \ make -j 8 install && \ ldconfig -################################################### -## Build and install MUSICA -################################################### - -RUN git clone https://github.com/NCAR/musica.git \ - && cd musica \ - && git checkout ${MUSICA_GIT_TAG} \ - && cmake -S . -B build \ - -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ - -D MUSICA_ENABLE_TESTS=OFF \ - -D MUSICA_BUILD_FORTRAN_INTERFACE=ON \ - -D MUSICA_ENABLE_MICM=ON \ - -D MUSICA_ENABLE_TUVX=ON \ - -D CMAKE_Fortran_COMPILER=mpif90 \ - -D CMAKE_C_COMPILER=mpicc \ - -D CMAKE_CXX_COMPILER=mpicxx \ - && cd build \ - && make install -j 8 - ################################################### ## Build CAM-SIMA ################################################### -# create a user to run the case +# Create a user to run the case RUN adduser cam_sima_user \ && echo "cam_sima_user ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/cam_sima_user \ && chmod 0440 /etc/sudoers.d/cam_sima_user -# copy in the CAM-SIMA code and give the proper user permissions +# Copy in the CAM-SIMA code and give the proper user permissions COPY --chown=cam_sima_user . /home/cam_sima_user/CAM-SIMA USER cam_sima_user WORKDIR /home/cam_sima_user/CAM-SIMA -# pull the dependencies +# Pull the dependencies RUN ./bin/git-fleximod update # Copy in the machine information for the container @@ -85,14 +65,15 @@ RUN cp /home/cam_sima_user/CAM-SIMA/docker/config_machines.xml /home/cam_sima_us # Set environment variables needed to create and build the case ENV USER=$(whoami) -ENV CASE_NAME=/home/cam_sima_user/case_name +ENV CASE_NAME=/home/cam_sima_user/case_name/test-case ENV CESMDATAROOT=/home/cam_sima_user/cesm_data ENV CIME_MACHINE=container ENV CIME_MODEL=cesm ENV ESMFMKFILE=/usr/local/lib/esmf.mk # Create a case -RUN ./cime/scripts/create_newcase --case $CASE_NAME --compset FPHYStest --res ne5_ne5_mg37 --run-unsupported +RUN /home/cam_sima_user/CAM-SIMA/cime/scripts/create_newcase --case $CASE_NAME \ + --compset FPHYStest --res ne5_ne5_mg37 --run-unsupported WORKDIR $CASE_NAME @@ -100,15 +81,9 @@ RUN ./case.setup RUN ./xmlchange CAM_CONFIG_OPTS="--dyn none --physics-suites musica" RUN ./xmlchange CAM_LINKED_LIBS="-lmusica-fortran -lmusica -lyaml-cpp" +RUN ./xmlchange CAM_LINKED_LIBS="-L/home/cam_sima_user/scratch/test-case/bld/atm/obj/musica/lib -lmusica-fortran -lmusica -lyaml-cpp" RUN ./xmlchange ROF_NCPL=48 RUN ./xmlchange STOP_OPTION=nsteps RUN ./xmlchange STOP_N=5 -# Copy in the grid files and a snapshot file -RUN chmod +x /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh -RUN /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh - -# # add the snapshot file -RUN echo "ncdata='/home/cam_sima_user/run_heldsuarez_cam6_nt2_bigg_try005.cam.h5.0001-01-01-00000.nc'" >> user_nl_cam - RUN ./case.build From 0ea6fcaf996939b88b559707a29be318212aa061 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 19 Feb 2025 19:57:12 -0700 Subject: [PATCH 05/22] code clean up --- cime_config/buildlib | 5 ++--- docker/Dockerfile | 9 ++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index a8f2823e..6001174b 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -126,12 +126,11 @@ def _build_cam(): paths.append(os.path.join(atm_root, "src", "dynamics", "tests", "initial_conditions")) - # TODO(jiwon); this path is not found # If using the CMEPS/NUOPC coupler, then add additional path: if case.get_value("COMP_INTERFACE") == "nuopc": paths.append(os.path.join(__CIMEROOT, "src", "drivers", "nuopc", "nuopc_cap_share")) - # End if + # End with # Write Filepath text file with open(filepath_src, "w", encoding='utf-8') as filepath: @@ -156,7 +155,7 @@ def _build_cam(): if dycore == "mpas": _setup_mpas(case) - # If the physics suite is MUSICA, build the MUSICA library and configuration + # If the physics suite is MUSICA, build the MUSICA library and get configuration if phys_suites == "musica": _build_musica_library(case) _download_musica_configuration(caseroot) diff --git a/docker/Dockerfile b/docker/Dockerfile index fe8684b5..5e3e33e5 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,7 +1,6 @@ # parts of CAM require x86 architecture (gptl, which relies on the rdtsc x86 assembly instruction) # esmf is am image you are expected to have built. Read the README file for instructions -# FROM --platform=linux/amd64 esmf:latest -FROM esmf:latest +FROM --platform=linux/amd64 esmf:latest ################################################### ## Install necessary packages @@ -87,6 +86,6 @@ RUN chmod +x /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh RUN /home/cam_sima_user/CAM-SIMA/docker/ftp_download.sh # add the snapshot file -# RUN echo "ncdata='/home/cam_sima_user/run_heldsuarez_cam6_nt2_bigg_try005.cam.h5.0001-01-01-00000.nc'" >> user_nl_cam -# RUN sed -i '5191s/^/\/\//g' /home/cam_sima_user/CAM-SIMA/cime/CIME/non_py/src/timing/gptl.c -# RUN ./case.build \ No newline at end of file +RUN echo "ncdata='/home/cam_sima_user/run_heldsuarez_cam6_nt2_bigg_try005.cam.h5.0001-01-01-00000.nc'" >> user_nl_cam + +RUN ./case.build \ No newline at end of file From 2adcbf6d77b90ad962bc07c1ee96fd17aa9035da Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 19 Feb 2025 20:00:29 -0700 Subject: [PATCH 06/22] fix an error --- cime_config/buildlib | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index 6001174b..f5160b26 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -130,13 +130,13 @@ def _build_cam(): if case.get_value("COMP_INTERFACE") == "nuopc": paths.append(os.path.join(__CIMEROOT, "src", "drivers", "nuopc", "nuopc_cap_share")) - # End with + # End if # Write Filepath text file with open(filepath_src, "w", encoding='utf-8') as filepath: filepath.write("\n".join(paths)) filepath.write("\n") - # End if + # End with # Move Filepath to the bld directory unless it has not changed if os.path.isfile(filepath_dst): From 28261e5848bbd927c349b0ccff65177278b11285 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 19 Feb 2025 20:14:16 -0700 Subject: [PATCH 07/22] update docker ignore file --- .dockerignore | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.dockerignore b/.dockerignore index e365f129..45066338 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,9 +1,11 @@ .github/ +.gitignore +LICENSE +README.md # Ignore editor temporaries and backups *.swp *~ .#* \#*# -**/.vscode/ - +**/.vscode/ \ No newline at end of file From 0d12ce42c19b2f4f2addd575ba77323cb11718be Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 19 Feb 2025 20:33:26 -0700 Subject: [PATCH 08/22] fix pylint errors --- cime_config/atm_musica_config.py | 8 ++++---- cime_config/buildlib | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cime_config/atm_musica_config.py b/cime_config/atm_musica_config.py index a63bcabc..6e571c4a 100644 --- a/cime_config/atm_musica_config.py +++ b/cime_config/atm_musica_config.py @@ -3,7 +3,7 @@ and install the MUSICA library, as well as to download the MUSICA configuration." """ -musica_repo_url = "https://github.com/NCAR/musica.git" -musica_tag = "802bc9041f964a7edd5ec896bec8cdc0c90de50b" -chemistry_data_repo_url = "https://github.com/NCAR/cam-sima-chemistry-data.git" -chemistry_data_tag = "b81cbc2e61c41ecd2d09167d6736daf1bf1be149" \ No newline at end of file +MUSICA_REPO_URL = "https://github.com/NCAR/musica.git" +MUSICA_TAG = "802bc9041f964a7edd5ec896bec8cdc0c90de50b" +CHEMISTRY_DATA_REPO_URL = "https://github.com/NCAR/cam-sima-chemistry-data.git" +CHEMISTRY_DATA_TAG = "b81cbc2e61c41ecd2d09167d6736daf1bf1be149" \ No newline at end of file diff --git a/cime_config/buildlib b/cime_config/buildlib index f5160b26..d974265e 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -12,8 +12,8 @@ import subprocess import logging from cam_config import ConfigCAM # CAM's configure structure -from atm_musica_config import musica_repo_url, musica_tag -from atm_musica_config import chemistry_data_repo_url, chemistry_data_tag +from atm_musica_config import MUSICA_REPO_URL, MUSICA_TAG +from atm_musica_config import CHEMISTRY_DATA_REPO_URL, CHEMISTRY_DATA_TAG # Check for the CIME library, and add it # to the python path: @@ -254,7 +254,7 @@ def _build_musica_library(case: Case) -> None: install_dir_name = "install" build_type = "Release" caseroot = os.path.normpath(case.get_value("CASEROOT")) - _clone_and_checkout(musica_repo_url, musica_tag, caseroot) + _clone_and_checkout(MUSICA_REPO_URL, MUSICA_TAG, caseroot) bld_path = os.path.join(caseroot, "musica", "build") if os.path.exists(bld_path): @@ -269,8 +269,8 @@ def _build_musica_library(case: Case) -> None: "cmake", f"-DCMAKE_INSTALL_PREFIX={install_dir_name}", f"-DCMAKE_BUILD_TYPE={build_type}", - f"-DMUSICA_ENABLE_TESTS=OFF", - f"-DMUSICA_BUILD_FORTRAN_INTERFACE=ON", + "-DMUSICA_ENABLE_TESTS=OFF", + "-DMUSICA_BUILD_FORTRAN_INTERFACE=ON", ".." ] result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) @@ -324,7 +324,7 @@ def _download_musica_configuration(download_dest: str) -> None: """ musica_config_dir_name = "musica_configurations" - _clone_and_checkout(chemistry_data_repo_url, chemistry_data_tag, download_dest) + _clone_and_checkout(CHEMISTRY_DATA_REPO_URL, CHEMISTRY_DATA_TAG, download_dest) original_dir = os.path.join(download_dest, "cam-sima-chemistry-data", "mechanisms") renamed_dir = os.path.join(download_dest, "cam-sima-chemistry-data", musica_config_dir_name) @@ -377,4 +377,4 @@ def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str): ############################################################################### if __name__ == "__main__": - _build_cam() \ No newline at end of file + _build_cam() From 4a227977e1bfe64ee2883b408a95ebe1b7994f12 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 20 Feb 2025 13:26:17 -0700 Subject: [PATCH 09/22] remove nuopc_cap_share path --- cime_config/buildlib | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index d974265e..e20f2686 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -126,12 +126,6 @@ def _build_cam(): paths.append(os.path.join(atm_root, "src", "dynamics", "tests", "initial_conditions")) - # If using the CMEPS/NUOPC coupler, then add additional path: - if case.get_value("COMP_INTERFACE") == "nuopc": - paths.append(os.path.join(__CIMEROOT, "src", "drivers", - "nuopc", "nuopc_cap_share")) - # End if - # Write Filepath text file with open(filepath_src, "w", encoding='utf-8') as filepath: filepath.write("\n".join(paths)) @@ -273,12 +267,12 @@ def _build_musica_library(case: Case) -> None: "-DMUSICA_BUILD_FORTRAN_INTERFACE=ON", ".." ] - result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) if result.returncode != 0: raise Exception(f"Unable to configure the MUSICA CMake project. Error: {result.stderr}") command = ["cmake", "--build", ".", "--target", "install"] - result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) if result.returncode != 0: raise Exception(f"Unable to build the MUSICA library. Error: {result.stderr}") @@ -331,8 +325,12 @@ def _download_musica_configuration(download_dest: str) -> None: try: os.rename(original_dir, renamed_dir) except FileNotFoundError: - raise Exception(f"The directory {original_dir} was not found.") - except Exception as e: + raise Exception(f"The directory '{original_dir}' was not found.") + except FileExistsError: + raise Exception(f"The destination directory '{renamed_dir}' already exists.") + except PermissionError: + raise Exception(f"Permission denied to rename '{original_dir}'.") + except OSError as e: raise Exception(f"An error occurred while renaming: {e}") musica_config_path = os.path.join(download_dest, musica_config_dir_name) @@ -363,13 +361,13 @@ def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str): shutil.rmtree(repo_path) result = subprocess.run(["git", "clone", repo_url, repo_path], - stderr=subprocess.PIPE, text=True) + stderr=subprocess.PIPE, text=True, check=False) if result.returncode != 0: raise Exception(f"Unable to clone the repository: {repo_url}. \ Error: {result.stderr}") result = subprocess.run(["git", "-C", repo_path, "checkout", tag_name], - stderr=subprocess.PIPE, text=True) + stderr=subprocess.PIPE, text=True, check=False) if result.returncode != 0: raise Exception(f"Unable to checkout the branch: {tag_name}. \ Error: {result.stderr}") From 2d75b094e37901337f7c15b42ae47866fdcc3074 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 20 Feb 2025 14:01:33 -0700 Subject: [PATCH 10/22] fix pylint complaints on exceptions --- cime_config/buildlib | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index 18781735..4fd0c517 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -335,13 +335,13 @@ def _download_musica_configuration(download_dest: str) -> None: try: os.rename(original_dir, renamed_dir) except FileNotFoundError: - raise Exception(f"The directory '{original_dir}' was not found.") + raise FileNotFoundError(f"The directory '{original_dir}' was not found.") except FileExistsError: - raise Exception(f"The destination directory '{renamed_dir}' already exists.") + raise FileExistsError(f"The destination directory '{renamed_dir}' already exists.") except PermissionError: - raise Exception(f"Permission denied to rename '{original_dir}'.") + raise PermissionError(f"Permission denied to rename '{original_dir}'.") except OSError as e: - raise Exception(f"An error occurred while renaming: {e}") + raise OSError(f"An error occurred while renaming: {e}") musica_config_path = os.path.join(download_dest, musica_config_dir_name) if os.path.exists(musica_config_path): From 403168530a5d0f76ec6af728614a864f33e3c427 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 20 Feb 2025 14:06:51 -0700 Subject: [PATCH 11/22] add a new line for pylint --- cime_config/atm_musica_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cime_config/atm_musica_config.py b/cime_config/atm_musica_config.py index 6e571c4a..6bbf1b5c 100644 --- a/cime_config/atm_musica_config.py +++ b/cime_config/atm_musica_config.py @@ -6,4 +6,4 @@ MUSICA_REPO_URL = "https://github.com/NCAR/musica.git" MUSICA_TAG = "802bc9041f964a7edd5ec896bec8cdc0c90de50b" CHEMISTRY_DATA_REPO_URL = "https://github.com/NCAR/cam-sima-chemistry-data.git" -CHEMISTRY_DATA_TAG = "b81cbc2e61c41ecd2d09167d6736daf1bf1be149" \ No newline at end of file +CHEMISTRY_DATA_TAG = "b81cbc2e61c41ecd2d09167d6736daf1bf1be149" From e8ae65b5cfc15fafc91bf15e08c4e08d192f920b Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 25 Feb 2025 18:14:20 -0700 Subject: [PATCH 12/22] update the git tag for ncar physics --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 257ce8a2..8345ca7c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,7 +20,7 @@ [submodule "ncar-physics"] path = src/physics/ncar_ccpp url = https://github.com/ESCOMP/atmospheric_physics - fxtag = 252b500a93c89f36ece7d8ba08fd8eb025279eaa + fxtag = 37224423f62d9a71922cb6fe9beca1516d9403a4 fxrequired = AlwaysRequired fxDONOTUSEurl = https://github.com/ESCOMP/atmospheric_physics [submodule "ccs_config"] From 92f749babe33d351c319274de185e6a2534c497d Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 25 Feb 2025 18:18:09 -0700 Subject: [PATCH 13/22] update musica tag --- cime_config/atm_musica_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cime_config/atm_musica_config.py b/cime_config/atm_musica_config.py index 6bbf1b5c..9c023f04 100644 --- a/cime_config/atm_musica_config.py +++ b/cime_config/atm_musica_config.py @@ -4,6 +4,6 @@ """ MUSICA_REPO_URL = "https://github.com/NCAR/musica.git" -MUSICA_TAG = "802bc9041f964a7edd5ec896bec8cdc0c90de50b" +MUSICA_TAG = "cc39bb00d2220fc81c85b22d3ceea4a39bd2bacf" CHEMISTRY_DATA_REPO_URL = "https://github.com/NCAR/cam-sima-chemistry-data.git" CHEMISTRY_DATA_TAG = "b81cbc2e61c41ecd2d09167d6736daf1bf1be149" From f2174c98b10fe894269ed04915c1a72dcce8d4a0 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 26 Feb 2025 12:47:20 -0700 Subject: [PATCH 14/22] remove incorrect lib path in musica dockerfile --- docker/Dockerfile.musica | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/Dockerfile.musica b/docker/Dockerfile.musica index 810927e2..2c7800b7 100644 --- a/docker/Dockerfile.musica +++ b/docker/Dockerfile.musica @@ -80,7 +80,6 @@ WORKDIR $CASE_NAME RUN ./case.setup RUN ./xmlchange CAM_CONFIG_OPTS="--dyn none --physics-suites musica" -RUN ./xmlchange CAM_LINKED_LIBS="-lmusica-fortran -lmusica -lyaml-cpp" RUN ./xmlchange CAM_LINKED_LIBS="-L/home/cam_sima_user/scratch/test-case/bld/atm/obj/musica/lib -lmusica-fortran -lmusica -lyaml-cpp" RUN ./xmlchange ROF_NCPL=48 RUN ./xmlchange STOP_OPTION=nsteps From f12572e7701843637d82d044725daed53023835f Mon Sep 17 00:00:00 2001 From: Jesse Nusbaumer Date: Wed, 5 Mar 2025 16:11:55 -0700 Subject: [PATCH 15/22] Have the MUSICA build key off the presences of the 'musica_ccpp' scheme in the SDF. --- cime_config/atm_musica_config.py | 1 + cime_config/buildlib | 5 +++-- cime_config/buildnml | 2 +- cime_config/cam_autogen.py | 5 ++++- cime_config/cam_config.py | 5 ++++- src/physics/ncar_ccpp | 2 +- test/unit/python/test_cam_autogen.py | 2 +- 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/cime_config/atm_musica_config.py b/cime_config/atm_musica_config.py index 9c023f04..ae467294 100644 --- a/cime_config/atm_musica_config.py +++ b/cime_config/atm_musica_config.py @@ -3,6 +3,7 @@ and install the MUSICA library, as well as to download the MUSICA configuration." """ +MUSICA_CCPP_SCHEME_NAME = "musica_ccpp" MUSICA_REPO_URL = "https://github.com/NCAR/musica.git" MUSICA_TAG = "cc39bb00d2220fc81c85b22d3ceea4a39bd2bacf" CHEMISTRY_DATA_REPO_URL = "https://github.com/NCAR/cam-sima-chemistry-data.git" diff --git a/cime_config/buildlib b/cime_config/buildlib index 4fd0c517..ce1aa363 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -12,6 +12,7 @@ import subprocess import logging from cam_config import ConfigCAM # CAM's configure structure +from atm_musica_config import MUSICA_CCPP_SCHEME_NAME from atm_musica_config import MUSICA_REPO_URL, MUSICA_TAG from atm_musica_config import CHEMISTRY_DATA_REPO_URL, CHEMISTRY_DATA_TAG @@ -76,7 +77,7 @@ def _build_cam(): # Re-run source generator in case registry, CCPP suites, or # generator scripts have been modified, and # to extract required source code paths: - config.generate_cam_src(gen_indent) + scheme_names = config.generate_cam_src(gen_indent) dycore = config.get_value('dyn') phys_suites = config.get_value('physics_suites') @@ -173,7 +174,7 @@ def _build_cam(): cmd += " OPTIONAL_MPAS_FEATURES=\"" + " ".join(optional_mpas_features) + "\"" # If the physics suite is MUSICA, build the MUSICA library and get configuration - if phys_suites == "musica": + if MUSICA_CCPP_SCHEME_NAME in scheme_names: _build_musica_library(case) _download_musica_configuration(caseroot) diff --git a/cime_config/buildnml b/cime_config/buildnml index c00131e3..32aa01a2 100755 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -166,7 +166,7 @@ def buildnml(case, caseroot, compname): gen_indent = 3 #Generate model code and meta-data: - config.generate_cam_src(gen_indent) + _ = config.generate_cam_src(gen_indent) #---------------------------------------------------------------- # Create namelist attribute dictionary (to set namelist defaults): diff --git a/cime_config/cam_autogen.py b/cime_config/cam_autogen.py index 50b77ca4..0ebf9e01 100644 --- a/cime_config/cam_autogen.py +++ b/cime_config/cam_autogen.py @@ -452,6 +452,7 @@ def generate_physics_suites(build_cache, preproc_defs, host_name, # Find the SDFs specified for this model build sdfs = [] scheme_files = [] + scheme_names = set() xml_files = {} # key is scheme, value is xml file path for sdf in phys_suites_str.split(';'): sdf_path = _find_file(f"suite_{sdf}.xml", suite_search) @@ -467,6 +468,8 @@ def generate_physics_suites(build_cache, preproc_defs, host_name, # Given an SDF, find all the schemes it calls _, suite = read_xml_file(sdf_path) sdf_schemes = _find_schemes_in_sdf(suite) + #Add schemes to set of all scheme names: + scheme_names.update(sdf_schemes) # For each scheme, find its metadata file for scheme in sdf_schemes: if scheme in all_scheme_files: @@ -655,7 +658,7 @@ def generate_physics_suites(build_cache, preproc_defs, host_name, # End if return [physics_blddir, genccpp_dir], do_gen_ccpp, cap_output_file, \ - xml_files.values(), capgen_db + xml_files.values(), capgen_db, scheme_names ############################################################################### def generate_init_routines(build_cache, bldroot, force_ccpp, force_init, diff --git a/cime_config/cam_config.py b/cime_config/cam_config.py index f47fdbee..20e3b3f5 100644 --- a/cime_config/cam_config.py +++ b/cime_config/cam_config.py @@ -868,7 +868,7 @@ def generate_cam_src(self, gen_fort_indent): self.__atm_root, self.__bldroot, reg_dir, reg_files, source_mods_dir, force_ccpp) - phys_dirs, force_init, _, nml_fils, capgen_db = retvals + phys_dirs, force_init, _, nml_fils, capgen_db, scheme_names = retvals # Add namelist definition files to dictionary: for nml_fil in nml_fils: @@ -899,6 +899,9 @@ def generate_cam_src(self, gen_fort_indent): #-------------------------------------------------------------- build_cache.write() + #Return the set of all scheme names present in the SDFs: + return scheme_names + #++++++++++++++++++++++++ def ccpp_phys_set(self, cam_nml_attr_dict, phys_nl_pg_dict): diff --git a/src/physics/ncar_ccpp b/src/physics/ncar_ccpp index 252b500a..37224423 160000 --- a/src/physics/ncar_ccpp +++ b/src/physics/ncar_ccpp @@ -1 +1 @@ -Subproject commit 252b500a93c89f36ece7d8ba08fd8eb025279eaa +Subproject commit 37224423f62d9a71922cb6fe9beca1516d9403a4 diff --git a/test/unit/python/test_cam_autogen.py b/test/unit/python/test_cam_autogen.py index e199bd02..48fd3223 100644 --- a/test/unit/python/test_cam_autogen.py +++ b/test/unit/python/test_cam_autogen.py @@ -580,7 +580,7 @@ def test_generate_physics_suites(self): expected_results = ([f'{self.test_bldroot}'+os.sep+'ccpp_physics', f'{self.test_bldroot}'+os.sep+'ccpp'], False, f'{self.test_bldroot}'+os.sep+'ccpp'+os.sep+'ccpp_datatable.xml', - [], None) + [], None, {"temp_adjust"}) #Run physics suite generation function: gen_results = generate_physics_suites(self.test_cache, "UNSET", "cam", "simple", From 2965f952b08ecdf4515abd1d9368a7ef9b55f3a1 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 5 Mar 2025 20:45:38 -0700 Subject: [PATCH 16/22] remove symlink --- cime_config/atm_musica_config.py | 4 +- cime_config/buildlib | 71 ++++++++++++-------------------- docker/Dockerfile.musica | 6 +-- 3 files changed, 31 insertions(+), 50 deletions(-) diff --git a/cime_config/atm_musica_config.py b/cime_config/atm_musica_config.py index ae467294..79cfa0bc 100644 --- a/cime_config/atm_musica_config.py +++ b/cime_config/atm_musica_config.py @@ -1,10 +1,10 @@ """ The URLs and tags provided in this script are read by buildlib to build -and install the MUSICA library, as well as to download the MUSICA configuration." +and install the MUSICA library, as well as to download the MUSICA configuration. """ MUSICA_CCPP_SCHEME_NAME = "musica_ccpp" MUSICA_REPO_URL = "https://github.com/NCAR/musica.git" MUSICA_TAG = "cc39bb00d2220fc81c85b22d3ceea4a39bd2bacf" CHEMISTRY_DATA_REPO_URL = "https://github.com/NCAR/cam-sima-chemistry-data.git" -CHEMISTRY_DATA_TAG = "b81cbc2e61c41ecd2d09167d6736daf1bf1be149" +CHEMISTRY_DATA_TAG = "2b58f2410ec7a565bcf80dee16ec20f6bc35d78b" diff --git a/cime_config/buildlib b/cime_config/buildlib index ce1aa363..2780c676 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -80,7 +80,6 @@ def _build_cam(): scheme_names = config.generate_cam_src(gen_indent) dycore = config.get_value('dyn') - phys_suites = config.get_value('physics_suites') reg_dir = config.get_value('reg_dir') init_dir = config.get_value('init_dir') phys_dirs_str = config.get_value('phys_dirs') @@ -173,17 +172,18 @@ def _build_cam(): if len(optional_mpas_features) > 0: cmd += " OPTIONAL_MPAS_FEATURES=\"" + " ".join(optional_mpas_features) + "\"" - # If the physics suite is MUSICA, build the MUSICA library and get configuration + # If MUSICA-CCPP scheme is used in a suite, download + # the MUSICA configuration and build the MUSICA library if MUSICA_CCPP_SCHEME_NAME in scheme_names: - _build_musica_library(case) _download_musica_configuration(caseroot) + musica_install_path = _build_musica_library(caseroot) cmd += ' USER_INCLDIR="'\ - f'-I{os.path.join(bldroot, "musica", "include", "micm")} '\ - f'-I{os.path.join(bldroot, "musica", "include", "musica")} '\ - f'-I{os.path.join(bldroot, "musica", "include", "musica", "micm")} '\ - f'-I{os.path.join(bldroot, "musica", "include", "musica", "tuvx")} '\ - f'-I{os.path.join(bldroot, "musica", "include", "musica", "fortran")} '\ + f'-I{os.path.join(musica_install_path, "include", "micm")} '\ + f'-I{os.path.join(musica_install_path, "include", "musica")} '\ + f'-I{os.path.join(musica_install_path, "include", "musica", "micm")} '\ + f'-I{os.path.join(musica_install_path, "include", "musica", "tuvx")} '\ + f'-I{os.path.join(musica_install_path, "include", "musica", "fortran")} '\ '"' retcode, out, err = run_cmd(cmd) @@ -243,39 +243,39 @@ def _copy2_as_needed(src: str, dst: str) -> None: shutil.copy2(src, dst) ############################################################################### -def _build_musica_library(case: Case) -> None: +def _build_musica_library(clone_dest: str) -> str: ############################################################################### """ Builds and installs the MUSICA library. Args: - case (Case) + clone_dest: destination where the repository will be cloned Raises: Exception: If configuring the CMake MUSICA project fails or the MUSICA library build fails, an exception is raised. + Returns: + str: path to the MUSICA installation directory """ - install_dir_name = "install" - build_type = "Release" - caseroot = os.path.normpath(case.get_value("CASEROOT")) - _clone_and_checkout(MUSICA_REPO_URL, MUSICA_TAG, caseroot) + _clone_and_checkout(MUSICA_REPO_URL, MUSICA_TAG, clone_dest) - bld_path = os.path.join(caseroot, "musica", "build") + bld_path = os.path.join(clone_dest, "musica", "build") if os.path.exists(bld_path): shutil.rmtree(bld_path) os.makedirs(bld_path) - # To install the target, the working directory must be the build directory. + # To install the target, the working directory must be the build (CMake binary) directory. current_dir = os.getcwd() os.chdir(bld_path) + install_dir = "install" command = [ "cmake", - f"-DCMAKE_INSTALL_PREFIX={install_dir_name}", - f"-DCMAKE_BUILD_TYPE={build_type}", - "-DMUSICA_ENABLE_TESTS=OFF", - "-DMUSICA_BUILD_FORTRAN_INTERFACE=ON", + f"-D CMAKE_INSTALL_PREFIX={install_dir}", + "-D CMAKE_BUILD_TYPE=Release", + "-D MUSICA_ENABLE_TESTS=OFF", + "-D MUSICA_BUILD_FORTRAN_INTERFACE=ON", ".." ] result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) @@ -287,30 +287,11 @@ def _build_musica_library(case: Case) -> None: if result.returncode != 0: raise Exception(f"Unable to build the MUSICA library. Error: {result.stderr}") - # Create symlinks pointing to the MUSICA libraries in the ATM build directory - atm_bld_root = os.path.join(case.get_value("EXEROOT"), "atm", "obj") - musica_lib_root = os.path.join(atm_bld_root, "musica", "lib") - os.makedirs(musica_lib_root, exist_ok=True) - - installed_lib_path = os.path.join(bld_path, install_dir_name, "lib64") - root, _, files = next(os.walk(installed_lib_path, topdown=True)) - for file in files: - symlink_force(os.path.join(root, file), os.path.join(musica_lib_root, file)) - - # Create symlinks pointing to the MUSICA include files in the ATM build directory - musica_include_root = os.path.join(atm_bld_root, "musica", "include") - os.makedirs(musica_include_root, exist_ok=True) - - installed_include_path = os.path.join(bld_path, install_dir_name, "include") - for root, _, files in os.walk(installed_include_path): - rel_path = os.path.relpath(root, installed_include_path) - dest_dir = os.path.join(musica_include_root, rel_path) + os.chdir(current_dir) - os.makedirs(dest_dir, exist_ok=True) - for file in files: - symlink_force(os.path.join(root, file), os.path.join(dest_dir, file)) + musica_install_path = os.path.join(bld_path, install_dir) - os.chdir(current_dir) + return musica_install_path ############################################################################### def _download_musica_configuration(download_dest: str) -> None: @@ -320,7 +301,7 @@ def _download_musica_configuration(download_dest: str) -> None: directory to match the name in the MUSICA-CCPP configuration. Args: - download_dest: destination where configuration will be downloaded. + download_dest: destination where configuration will be downloaded Raises: Exception: If the directory to be renamed is not found or @@ -351,7 +332,7 @@ def _download_musica_configuration(download_dest: str) -> None: shutil.move(renamed_dir, download_dest) ############################################################################### -def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str): +def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str) -> None: ############################################################################### """ Clones a Git repository from the URL and checks out a specific branch. @@ -359,7 +340,7 @@ def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str): Args: repo_url: The URL of the Git repository to clone tag_name: The tag name to check out - clone_dest: destination where the repository will be cloned. + clone_dest: destination where the repository will be cloned Raises: Exception: If the `git clone` or `git checkout` commands fail, diff --git a/docker/Dockerfile.musica b/docker/Dockerfile.musica index 2c7800b7..e1e5c805 100644 --- a/docker/Dockerfile.musica +++ b/docker/Dockerfile.musica @@ -75,14 +75,14 @@ ENV ESMFMKFILE=/usr/local/lib/esmf.mk RUN /home/cam_sima_user/CAM-SIMA/cime/scripts/create_newcase --case $CASE_NAME \ --compset FPHYStest --res ne5_ne5_mg37 --run-unsupported -WORKDIR $CASE_NAME +WORKDIR $CASE_NAME RUN ./case.setup RUN ./xmlchange CAM_CONFIG_OPTS="--dyn none --physics-suites musica" -RUN ./xmlchange CAM_LINKED_LIBS="-L/home/cam_sima_user/scratch/test-case/bld/atm/obj/musica/lib -lmusica-fortran -lmusica -lyaml-cpp" +RUN ./xmlchange CAM_LINKED_LIBS="-L/home/cam_sima_user/case_name/test-case/musica/build/install/lib64 -lmusica-fortran -lmusica -lyaml-cpp" RUN ./xmlchange ROF_NCPL=48 RUN ./xmlchange STOP_OPTION=nsteps RUN ./xmlchange STOP_N=5 -RUN ./case.build +RUN ./case.build \ No newline at end of file From 211111ed48242c188d4d17c1e3dc3e2ca11f3ee9 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 7 Mar 2025 09:17:16 -0700 Subject: [PATCH 17/22] remove symlink and add musica lib to CAM_LINKED_LIBS --- cime_config/buildlib | 69 ++++++++++++++++++++++++++++++++-------- docker/Dockerfile.musica | 1 - 2 files changed, 56 insertions(+), 14 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index 2780c676..715d160a 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -26,7 +26,7 @@ sys.path.append(os.path.join(__CIMEROOT, "CIME", "Tools")) #pylint: disable=wrong-import-position # CIME imports from CIME.case import Case -from CIME.utils import run_cmd, expect, symlink_force +from CIME.utils import run_cmd, expect from CIME.utils import stop_buffering_output from CIME.buildlib import parse_input from CIME.build import get_standard_makefile_args @@ -176,7 +176,12 @@ def _build_cam(): # the MUSICA configuration and build the MUSICA library if MUSICA_CCPP_SCHEME_NAME in scheme_names: _download_musica_configuration(caseroot) - musica_install_path = _build_musica_library(caseroot) + musica_install_path = _build_musica(caseroot) + + cam_linked_libs = case.get_value("CAM_LINKED_LIBS") + musica_libs = "-lmusica-fortran -lmusica -lyaml-cpp" + if not musica_libs in cam_linked_libs: + _set_musica_lib_path(musica_install_path, caseroot) cmd += ' USER_INCLDIR="'\ f'-I{os.path.join(musica_install_path, "include", "micm")} '\ @@ -243,7 +248,7 @@ def _copy2_as_needed(src: str, dst: str) -> None: shutil.copy2(src, dst) ############################################################################### -def _build_musica_library(clone_dest: str) -> str: +def _build_musica(clone_dest: str) -> str: ############################################################################### """ Builds and installs the MUSICA library. @@ -256,7 +261,7 @@ def _build_musica_library(clone_dest: str) -> str: the MUSICA library build fails, an exception is raised. Returns: - str: path to the MUSICA installation directory + musica_install_path: path to the MUSICA installation directory """ _clone_and_checkout(MUSICA_REPO_URL, MUSICA_TAG, clone_dest) @@ -288,7 +293,6 @@ def _build_musica_library(clone_dest: str) -> str: raise Exception(f"Unable to build the MUSICA library. Error: {result.stderr}") os.chdir(current_dir) - musica_install_path = os.path.join(bld_path, install_dir) return musica_install_path @@ -316,12 +320,12 @@ def _download_musica_configuration(download_dest: str) -> None: renamed_dir = os.path.join(download_dest, "cam-sima-chemistry-data", musica_config_dir_name) try: os.rename(original_dir, renamed_dir) - except FileNotFoundError: - raise FileNotFoundError(f"The directory '{original_dir}' was not found.") - except FileExistsError: - raise FileExistsError(f"The destination directory '{renamed_dir}' already exists.") - except PermissionError: - raise PermissionError(f"Permission denied to rename '{original_dir}'.") + except FileNotFoundError as e: + raise FileNotFoundError(f"The directory '{original_dir}' was not found. Error: {e}") + except FileExistsError as e: + raise FileExistsError(f"The destination directory '{renamed_dir}' already exists. Error: {e}") + except PermissionError as e: + raise PermissionError(f"Permission denied to rename '{original_dir}'. Error: {e}") except OSError as e: raise OSError(f"An error occurred while renaming: {e}") @@ -331,6 +335,45 @@ def _download_musica_configuration(download_dest: str) -> None: shutil.move(renamed_dir, download_dest) +############################################################################### +def _set_musica_lib_path(musica_install_path: str, caseroot: str) -> None: +############################################################################### + """ + Sets the MUSICA libraries path to CAM_LINKED_LIBS, allowing the libraries + to be linked during the CESM build process. + + Args: + musica_install_path: path to the MUSICA installation directory + caseroot: CASEROOT where the xmlchange command is located + + Raises: + Exception: If the subprocess for the xmlchange command fails, + an exception is raised with the error message. + """ + + current_dir = os.getcwd() + os.chdir(caseroot) + + command = [ + "./xmlchange", + "--append", + # The libraries must be on the same line because CIME flags an + # error for multi-character arguments preceded by a single dash + f"CAM_LINKED_LIBS=-L{os.path.join(musica_install_path, 'lib64')} -lmusica-fortran -lmusica -lyaml-cpp" + ] + try: + subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + text=True, check=False) + except subprocess.CalledProcessError as e: + raise subprocess.CalledProcessError(f"The subprocess for xmlchange \ + to set the MUSICA library path failed with an error.: {e}") + except FileNotFoundError as e: + raise FileNotFoundError(f"The 'xmlchange' command was not found: {e}") + except OSError as e: + raise OSError(f"An error occurred while running 'xmlchange' command: {e}") + + os.chdir(current_dir) + ############################################################################### def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str) -> None: ############################################################################### @@ -338,8 +381,8 @@ def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str) -> None: Clones a Git repository from the URL and checks out a specific branch. Args: - repo_url: The URL of the Git repository to clone - tag_name: The tag name to check out + repo_url: URL of the Git repository to clone + tag_name: tag name to check out clone_dest: destination where the repository will be cloned Raises: diff --git a/docker/Dockerfile.musica b/docker/Dockerfile.musica index e1e5c805..f5deedbc 100644 --- a/docker/Dockerfile.musica +++ b/docker/Dockerfile.musica @@ -80,7 +80,6 @@ WORKDIR $CASE_NAME RUN ./case.setup RUN ./xmlchange CAM_CONFIG_OPTS="--dyn none --physics-suites musica" -RUN ./xmlchange CAM_LINKED_LIBS="-L/home/cam_sima_user/case_name/test-case/musica/build/install/lib64 -lmusica-fortran -lmusica -lyaml-cpp" RUN ./xmlchange ROF_NCPL=48 RUN ./xmlchange STOP_OPTION=nsteps RUN ./xmlchange STOP_N=5 From f4e51321625814fb47a929723091508c910ac1f1 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 7 Mar 2025 10:19:09 -0700 Subject: [PATCH 18/22] rework exceptions for pylint --- cime_config/buildlib | 72 +++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 24 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index 715d160a..8c5725bb 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -283,14 +283,28 @@ def _build_musica(clone_dest: str) -> str: "-D MUSICA_BUILD_FORTRAN_INTERFACE=ON", ".." ] - result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) - if result.returncode != 0: - raise Exception(f"Unable to configure the MUSICA CMake project. Error: {result.stderr}") + try: + subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + text=True, check=False) + except subprocess.CalledProcessError as e: + raise subprocess.CalledProcessError(f"The subprocess for cmake \ + to configure the MUSICA CMake project failed.") from e + except FileNotFoundError as e: + raise FileNotFoundError(f"The 'cmake' command was not found.") from e + except OSError as e: + raise OSError(f"An error occurred while executing the 'cmake' command.") from e command = ["cmake", "--build", ".", "--target", "install"] - result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) - if result.returncode != 0: - raise Exception(f"Unable to build the MUSICA library. Error: {result.stderr}") + try: + subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + text=True, check=False) + except subprocess.CalledProcessError as e: + raise subprocess.CalledProcessError(f"The subprocess for cmake \ + to build the MUSICA library failed.") from e + except FileNotFoundError as e: + raise FileNotFoundError(f"The 'cmake' command was not found.") from e + except OSError as e: + raise OSError(f"An error occurred while executing the 'cmake' command.") from e os.chdir(current_dir) musica_install_path = os.path.join(bld_path, install_dir) @@ -321,13 +335,13 @@ def _download_musica_configuration(download_dest: str) -> None: try: os.rename(original_dir, renamed_dir) except FileNotFoundError as e: - raise FileNotFoundError(f"The directory '{original_dir}' was not found. Error: {e}") + raise FileNotFoundError(f"The directory '{original_dir}' was not found.") from e except FileExistsError as e: - raise FileExistsError(f"The destination directory '{renamed_dir}' already exists. Error: {e}") + raise FileExistsError(f"The destination directory '{renamed_dir}' already exists.") from e except PermissionError as e: - raise PermissionError(f"Permission denied to rename '{original_dir}'. Error: {e}") + raise PermissionError(f"Permission denied to rename '{original_dir}'.") from e except OSError as e: - raise OSError(f"An error occurred while renaming: {e}") + raise OSError(f"An error occurred while renaming.") from e musica_config_path = os.path.join(download_dest, musica_config_dir_name) if os.path.exists(musica_config_path): @@ -366,11 +380,11 @@ def _set_musica_lib_path(musica_install_path: str, caseroot: str) -> None: text=True, check=False) except subprocess.CalledProcessError as e: raise subprocess.CalledProcessError(f"The subprocess for xmlchange \ - to set the MUSICA library path failed with an error.: {e}") + to set the MUSICA library path failed.") from e except FileNotFoundError as e: - raise FileNotFoundError(f"The 'xmlchange' command was not found: {e}") + raise FileNotFoundError(f"The 'xmlchange' command was not found.") from e except OSError as e: - raise OSError(f"An error occurred while running 'xmlchange' command: {e}") + raise OSError(f"An error occurred while executing the 'xmlchange' command.") from e os.chdir(current_dir) @@ -395,17 +409,27 @@ def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str) -> None: if os.path.exists(repo_path): shutil.rmtree(repo_path) - result = subprocess.run(["git", "clone", repo_url, repo_path], - stderr=subprocess.PIPE, text=True, check=False) - if result.returncode != 0: - raise Exception(f"Unable to clone the repository: {repo_url}. \ - Error: {result.stderr}") - - result = subprocess.run(["git", "-C", repo_path, "checkout", tag_name], - stderr=subprocess.PIPE, text=True, check=False) - if result.returncode != 0: - raise Exception(f"Unable to checkout the branch: {tag_name}. \ - Error: {result.stderr}") + try: + subprocess.run(["git", "clone", repo_url, repo_path], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) + except subprocess.CalledProcessError as e: + raise subprocess.CalledProcessError(f"The subprocess for git \ + to clone the repository {repo_url} failed.") from e + except FileNotFoundError as e: + raise FileNotFoundError(f"The 'git' command was not found.") from e + except OSError as e: + raise OSError(f"An error occurred while executing the 'git' command.") from e + + try: + subprocess.run(["git", "-C", repo_path, "checkout", tag_name], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) + except subprocess.CalledProcessError as e: + raise subprocess.CalledProcessError(f"The subprocess for git \ + to checkout the branch {tag_name} failed.") from e + except FileNotFoundError as e: + raise FileNotFoundError(f"The 'git' command was not found.") from e + except OSError as e: + raise OSError(f"An error occurred while executing the 'git' command.") from e ############################################################################### From da5a12194be98919bdfa3131e642af1f4e2c249f Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 7 Mar 2025 10:23:43 -0700 Subject: [PATCH 19/22] remove f string --- cime_config/buildlib | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index 8c5725bb..a2b65f96 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -287,24 +287,24 @@ def _build_musica(clone_dest: str) -> str: subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: - raise subprocess.CalledProcessError(f"The subprocess for cmake \ + raise subprocess.CalledProcessError("The subprocess for cmake \ to configure the MUSICA CMake project failed.") from e except FileNotFoundError as e: - raise FileNotFoundError(f"The 'cmake' command was not found.") from e + raise FileNotFoundError("The 'cmake' command was not found.") from e except OSError as e: - raise OSError(f"An error occurred while executing the 'cmake' command.") from e + raise OSError("An error occurred while executing the 'cmake' command.") from e command = ["cmake", "--build", ".", "--target", "install"] try: subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: - raise subprocess.CalledProcessError(f"The subprocess for cmake \ + raise subprocess.CalledProcessError("The subprocess for cmake \ to build the MUSICA library failed.") from e except FileNotFoundError as e: - raise FileNotFoundError(f"The 'cmake' command was not found.") from e + raise FileNotFoundError("The 'cmake' command was not found.") from e except OSError as e: - raise OSError(f"An error occurred while executing the 'cmake' command.") from e + raise OSError("An error occurred while executing the 'cmake' command.") from e os.chdir(current_dir) musica_install_path = os.path.join(bld_path, install_dir) @@ -341,7 +341,7 @@ def _download_musica_configuration(download_dest: str) -> None: except PermissionError as e: raise PermissionError(f"Permission denied to rename '{original_dir}'.") from e except OSError as e: - raise OSError(f"An error occurred while renaming.") from e + raise OSError("An error occurred while renaming.") from e musica_config_path = os.path.join(download_dest, musica_config_dir_name) if os.path.exists(musica_config_path): @@ -379,12 +379,12 @@ def _set_musica_lib_path(musica_install_path: str, caseroot: str) -> None: subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: - raise subprocess.CalledProcessError(f"The subprocess for xmlchange \ + raise subprocess.CalledProcessError("The subprocess for xmlchange \ to set the MUSICA library path failed.") from e except FileNotFoundError as e: - raise FileNotFoundError(f"The 'xmlchange' command was not found.") from e + raise FileNotFoundError("The 'xmlchange' command was not found.") from e except OSError as e: - raise OSError(f"An error occurred while executing the 'xmlchange' command.") from e + raise OSError("An error occurred while executing the 'xmlchange' command.") from e os.chdir(current_dir) @@ -416,9 +416,9 @@ def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str) -> None: raise subprocess.CalledProcessError(f"The subprocess for git \ to clone the repository {repo_url} failed.") from e except FileNotFoundError as e: - raise FileNotFoundError(f"The 'git' command was not found.") from e + raise FileNotFoundError("The 'git' command was not found.") from e except OSError as e: - raise OSError(f"An error occurred while executing the 'git' command.") from e + raise OSError("An error occurred while executing the 'git' command.") from e try: subprocess.run(["git", "-C", repo_path, "checkout", tag_name], @@ -427,9 +427,9 @@ def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str) -> None: raise subprocess.CalledProcessError(f"The subprocess for git \ to checkout the branch {tag_name} failed.") from e except FileNotFoundError as e: - raise FileNotFoundError(f"The 'git' command was not found.") from e + raise FileNotFoundError("The 'git' command was not found.") from e except OSError as e: - raise OSError(f"An error occurred while executing the 'git' command.") from e + raise OSError("An error occurred while executing the 'git' command.") from e ############################################################################### From 409053cc0e78fcd9e9129c2eb7d84f388c069363 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 7 Mar 2025 10:32:57 -0700 Subject: [PATCH 20/22] reworked on the subprocess error that pylint complains --- cime_config/buildlib | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index a2b65f96..dedf8390 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -287,8 +287,8 @@ def _build_musica(clone_dest: str) -> str: subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: - raise subprocess.CalledProcessError("The subprocess for cmake \ - to configure the MUSICA CMake project failed.") from e + raise subprocess.CalledProcessError(e.returncode, e.cmd, "The subprocess \ + for cmake to configure the MUSICA CMake project failed.") from e except FileNotFoundError as e: raise FileNotFoundError("The 'cmake' command was not found.") from e except OSError as e: @@ -299,8 +299,8 @@ def _build_musica(clone_dest: str) -> str: subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: - raise subprocess.CalledProcessError("The subprocess for cmake \ - to build the MUSICA library failed.") from e + raise subprocess.CalledProcessError(e.returncode, e.cmd, "The subprocess \ + for cmake to build the MUSICA library failed.") from e except FileNotFoundError as e: raise FileNotFoundError("The 'cmake' command was not found.") from e except OSError as e: @@ -379,8 +379,8 @@ def _set_musica_lib_path(musica_install_path: str, caseroot: str) -> None: subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: - raise subprocess.CalledProcessError("The subprocess for xmlchange \ - to set the MUSICA library path failed.") from e + raise subprocess.CalledProcessError(e.returncode, e.cmd, "The subprocess \ + for xmlchange to set the MUSICA library path failed.") from e except FileNotFoundError as e: raise FileNotFoundError("The 'xmlchange' command was not found.") from e except OSError as e: @@ -413,8 +413,8 @@ def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str) -> None: subprocess.run(["git", "clone", repo_url, repo_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: - raise subprocess.CalledProcessError(f"The subprocess for git \ - to clone the repository {repo_url} failed.") from e + raise subprocess.CalledProcessError(e.returncode, e.cmd, f"The subprocess \ + for git to clone the repository {repo_url} failed.") from e except FileNotFoundError as e: raise FileNotFoundError("The 'git' command was not found.") from e except OSError as e: @@ -424,8 +424,8 @@ def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str) -> None: subprocess.run(["git", "-C", repo_path, "checkout", tag_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: - raise subprocess.CalledProcessError(f"The subprocess for git \ - to checkout the branch {tag_name} failed.") from e + raise subprocess.CalledProcessError(e.returncode, e.cmd, f"The subprocess \ + for git to checkout the branch {tag_name} failed.") from e except FileNotFoundError as e: raise FileNotFoundError("The 'git' command was not found.") from e except OSError as e: From 91414fdb25b2231fe70ad413d8d363ceb71b030b Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 7 Mar 2025 11:41:19 -0700 Subject: [PATCH 21/22] add unlock and lock files to write --- cime_config/buildlib | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cime_config/buildlib b/cime_config/buildlib index dedf8390..481c8d58 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -31,6 +31,7 @@ from CIME.utils import stop_buffering_output from CIME.buildlib import parse_input from CIME.build import get_standard_makefile_args from CIME.Tools.standard_script_setup import check_minimum_python_version +from CIME.locked_files import lock_file, unlock_file #pylint: enable=wrong-import-position check_minimum_python_version(3, 7) #CAM requires version 3.7 or greater @@ -368,6 +369,8 @@ def _set_musica_lib_path(musica_install_path: str, caseroot: str) -> None: current_dir = os.getcwd() os.chdir(caseroot) + unlock_file("env_build.xml", caseroot) + command = [ "./xmlchange", "--append", @@ -388,6 +391,8 @@ def _set_musica_lib_path(musica_install_path: str, caseroot: str) -> None: os.chdir(current_dir) + lock_file("env_build.xml", caseroot) + ############################################################################### def _clone_and_checkout(repo_url: str, tag_name: str, clone_dest: str) -> None: ############################################################################### From 29d81c04015ac7e2055042bbe60fd5f787151d1c Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 7 Mar 2025 15:00:48 -0700 Subject: [PATCH 22/22] remove chdir and update subprocess command to add cwd --- cime_config/buildlib | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/cime_config/buildlib b/cime_config/buildlib index 481c8d58..1aa4e2af 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -271,10 +271,6 @@ def _build_musica(clone_dest: str) -> str: shutil.rmtree(bld_path) os.makedirs(bld_path) - # To install the target, the working directory must be the build (CMake binary) directory. - current_dir = os.getcwd() - os.chdir(bld_path) - install_dir = "install" command = [ "cmake", @@ -285,8 +281,8 @@ def _build_musica(clone_dest: str) -> str: ".." ] try: - subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - text=True, check=False) + subprocess.run(command, cwd=bld_path, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: raise subprocess.CalledProcessError(e.returncode, e.cmd, "The subprocess \ for cmake to configure the MUSICA CMake project failed.") from e @@ -297,8 +293,8 @@ def _build_musica(clone_dest: str) -> str: command = ["cmake", "--build", ".", "--target", "install"] try: - subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - text=True, check=False) + subprocess.run(command, cwd=bld_path, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: raise subprocess.CalledProcessError(e.returncode, e.cmd, "The subprocess \ for cmake to build the MUSICA library failed.") from e @@ -307,7 +303,6 @@ def _build_musica(clone_dest: str) -> str: except OSError as e: raise OSError("An error occurred while executing the 'cmake' command.") from e - os.chdir(current_dir) musica_install_path = os.path.join(bld_path, install_dir) return musica_install_path @@ -366,9 +361,6 @@ def _set_musica_lib_path(musica_install_path: str, caseroot: str) -> None: an exception is raised with the error message. """ - current_dir = os.getcwd() - os.chdir(caseroot) - unlock_file("env_build.xml", caseroot) command = [ @@ -379,8 +371,8 @@ def _set_musica_lib_path(musica_install_path: str, caseroot: str) -> None: f"CAM_LINKED_LIBS=-L{os.path.join(musica_install_path, 'lib64')} -lmusica-fortran -lmusica -lyaml-cpp" ] try: - subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - text=True, check=False) + subprocess.run(command, cwd=caseroot, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, text=True, check=False) except subprocess.CalledProcessError as e: raise subprocess.CalledProcessError(e.returncode, e.cmd, "The subprocess \ for xmlchange to set the MUSICA library path failed.") from e @@ -389,8 +381,6 @@ def _set_musica_lib_path(musica_install_path: str, caseroot: str) -> None: except OSError as e: raise OSError("An error occurred while executing the 'xmlchange' command.") from e - os.chdir(current_dir) - lock_file("env_build.xml", caseroot) ###############################################################################