import os
import shutil
import subprocess
from logging import debug, error
[docs]
def make_command(self):
args = [
"make",
f"DIM={self.domain.nlon-1}x{self.domain.nlat-1}x{self.domain.nlev}",
f"MODE={getattr(self, 'compile-mode')}",
f"TARGET={getattr(self, 'compile-acc-target')}"
]
if hasattr(self, 'compiler'):
args.append(f"FC={self.compiler}")
if hasattr(self, 'netcdf_inc'):
args.append(f"NETCDF_INC={self.netcdf_inc}")
if hasattr(self, 'netcdf_lib'):
args.append(f"NETCDF_LIB={self.netcdf_lib}")
if hasattr(self, 'compile-clean'):
args.extend(["clean", "all"])
return args
[docs]
def compile(self):
comp_dir = os.path.join(self.workdir, "model")
# Copying the executables
if not getattr(self, "force-recompile"):
# copying the executable
try:
shutil.copy(self.fileexec, os.path.join(comp_dir, "dispersion.e"))
with open(os.path.join(comp_dir, "README.txt"), "w") as f:
f.write(f"'dispersion.e' was copied from '{self.fileexec}'")
return
except IOError as e:
if not getattr(self, "auto-recompile"):
raise RuntimeError(
f"LMDZ could not find executables '{self.fileexec}' "
"and was not asked to compile them; "
"specify 'auto-recompile = True' in the YAML file to do so"
) from e
# Otherwise, re-compile
# Copying sources locally; overwrite folder if exists
src_dir = os.path.join(comp_dir, "sources")
shutil.rmtree(src_dir, ignore_errors=True)
from_dir = self.dir_sources if self.dir_sources else \
os.path.dirname(self.fileexec)
shutil.copytree(os.path.join(from_dir, "libf"),
os.path.join(src_dir, "libf"))
shutil.copy(os.path.join(from_dir, "makefile"), src_dir)
if hasattr(self, 'modules'):
# Writting a script that load the modules and compile LMDZ
compile_script = os.path.join(src_dir, "compile.sh")
lines = [
"#!/usr/bin/bash",
"",
"module purge",
f"module load {' '.join(self.modules)}",
"module list",
"",
' '.join(make_command(self)),
""
]
with open(compile_script, 'w') as f:
f.write('\n'.join(lines))
args = ["bash", compile_script]
else:
# Directly calling make with the same environment as PyCIF
args = make_command(self)
# Now compile LMDZ
logfile_path = os.path.join(comp_dir, "compile.log")
debug("Compiling LMDZ")
with open(logfile_path, "w") as logfile:
process = subprocess.Popen(
args,
cwd=src_dir,
stdout=logfile,
stderr=subprocess.PIPE
)
_, stderr = process.communicate()
exec_file = os.path.join(src_dir, "dispersion.e")
if not os.path.isfile(exec_file) or process.returncode != 0:
error(f"Error while compiling LMDZ:\n{stderr.decode('utf-8')}")
raise RuntimeError("Error while compiling LMDZ")
if getattr(self, "force-compile-stderr"):
debug(f"LMDZ compilation stderr:\n{stderr.decode('utf-8')}")
# Copy executable at model root directory
shutil.copy(exec_file, comp_dir)