def _stage_runtime_inputs(build_dir, no_pnetcdf): """Stage CTSM and LILAC runtime inputs Args: build_dir (str): path to build directory no_pnetcdf (bool): if True, use netcdf rather than pnetcdf """ os.makedirs(os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME)) inputdata_dir = _xmlquery('DIN_LOC_ROOT', build_dir) fill_template_file(path_to_template=os.path.join(_PATH_TO_TEMPLATES, 'ctsm_template.cfg'), path_to_final=os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'ctsm.cfg'), substitutions={'INPUTDATA': inputdata_dir}) fill_template_file(path_to_template=os.path.join(_PATH_TO_TEMPLATES, 'lilac_in_template'), path_to_final=os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'lilac_in'), substitutions={'INPUTDATA': inputdata_dir}) pio_stride = _xmlquery('MAX_MPITASKS_PER_NODE', build_dir) if no_pnetcdf: pio_typename = 'netcdf' # pio_rearranger = 1 is generally more efficient with netcdf (see # https://github.com/ESMCI/cime/pull/3732#discussion_r508954806 and the following # discussion) pio_rearranger = 1 else: pio_typename = 'pnetcdf' pio_rearranger = 2 fill_template_file(path_to_template=os.path.join( _PATH_TO_TEMPLATES, 'lnd_modelio_template.nml'), path_to_final=os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'lnd_modelio.nml'), substitutions={ 'PIO_REARRANGER': pio_rearranger, 'PIO_STRIDE': pio_stride, 'PIO_TYPENAME': pio_typename }) shutil.copyfile(src=os.path.join(path_to_ctsm_root(), 'cime_config', 'usermods_dirs', 'lilac', 'user_nl_ctsm'), dst=os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'user_nl_ctsm')) make_link( _PATH_TO_MAKE_RUNTIME_INPUTS, os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'make_runtime_inputs')) make_link( _PATH_TO_DOWNLOAD_INPUT_DATA, os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'download_input_data'))
def _make_testroot(testroot, testid_base, dry_run): """Make the testroot directory at the given location, as well as a link in the current directory """ if os.path.exists(testroot): raise RuntimeError("{} already exists".format(testroot)) logger.info("Making directory: %s", testroot) if not dry_run: os.makedirs(testroot) make_link(testroot, _get_testdir_name(testid_base))
def _stage_runtime_inputs(build_dir, no_pnetcdf): """Stage CTSM and LILAC runtime inputs Args: build_dir (str): path to build directory no_pnetcdf (bool): if True, use netcdf rather than pnetcdf """ os.makedirs(os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME)) inputdata_dir = _xmlquery('DIN_LOC_ROOT', build_dir) fill_template_file(path_to_template=os.path.join(_PATH_TO_TEMPLATES, 'ctsm_template.cfg'), path_to_final=os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'ctsm.cfg'), substitutions={'INPUTDATA': inputdata_dir}) fill_template_file(path_to_template=os.path.join(_PATH_TO_TEMPLATES, 'lilac_in_template'), path_to_final=os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'lilac_in'), substitutions={'INPUTDATA': inputdata_dir}) pio_stride = _xmlquery('MAX_MPITASKS_PER_NODE', build_dir) if no_pnetcdf: pio_typename = 'netcdf' else: pio_typename = 'pnetcdf' fill_template_file(path_to_template=os.path.join( _PATH_TO_TEMPLATES, 'lnd_modelio_template.nml'), path_to_final=os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'lnd_modelio.nml'), substitutions={ 'PIO_STRIDE': pio_stride, 'PIO_TYPENAME': pio_typename }) shutil.copyfile(src=os.path.join(path_to_ctsm_root(), 'cime_config', 'usermods_dirs', 'lilac', 'user_nl_ctsm'), dst=os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'user_nl_ctsm')) make_link( _PATH_TO_MAKE_RUNTIME_INPUTS, os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'make_runtime_inputs')) make_link( _PATH_TO_DOWNLOAD_INPUT_DATA, os.path.join(build_dir, _RUNTIME_INPUTS_DIRNAME, 'download_input_data'))
def _build_case(build_dir): """Build the CTSM library and its dependencies Args: build_dir (str): path to build directory """ # We want user to see output from the build command, so we use subprocess.check_call # rather than run_cmd_output_on_error. # See comment in _create_case for why we use case_dir in both the path to the command # and in the cwd argument to check_call. case_dir = _get_case_dir(build_dir) try: subprocess.check_call( [os.path.join(case_dir, 'case.build'), '--sharedlib-only'], cwd=case_dir) except subprocess.CalledProcessError: abort( 'ERROR building CTSM or its dependencies - see above for details') make_link(os.path.join(case_dir, 'bld', 'ctsm.mk'), os.path.join(build_dir, 'ctsm.mk'))
def _create_case(cime_path, build_dir, compiler, machine=None, build_debug=False, build_with_openmp=False, inputdata_path=None): """Create a case that can later be used to build the CTSM library and its dependencies Args: cime_path (str): path to root of cime build_dir (str): path to build directory compiler (str): compiler to use machine (str or None): name of machine or None If None, we assume we're using an on-the-fly machine port Otherwise, machine should be the name of a machine known to cime build_debug (bool): if True, build with flags for debugging build_with_openmp (bool): if True, build with OpenMP support inputdata_path (str or None): path to existing inputdata directory on this machine If None, we use the machine's default DIN_LOC_ROOT """ # Note that, for some commands, we want to suppress output, only showing the output if # the command fails; for these we use run_cmd_output_on_error. For other commands, # there should be no output in general; for these, we directly use # subprocess.check_call or similar. # Also note that, for commands executed from the case directory, we specify the path # to the case directory both in the command itself and in the cwd argument. We do the # former in case dot isn't in the user's path; we do the latter in case the commands # require you to be in the case directory when you execute them. case_dir = _get_case_dir(build_dir) xmlchange = os.path.join(case_dir, 'xmlchange') if machine is None: machine_args = [ '--machine', _MACH_NAME, '--extra-machines-dir', os.path.join(build_dir, _MACHINE_CONFIG_DIRNAME) ] else: machine_args = ['--machine', machine] create_newcase_cmd = [ os.path.join(cime_path, 'scripts', 'create_newcase'), '--output-root', build_dir, '--case', case_dir, '--compset', _COMPSET, '--res', _RES, '--compiler', compiler, '--driver', 'nuopc', # Project isn't used for anything in the LILAC workflow, but it # still needs to be specified on machines that expect it. '--project', 'UNSET', '--run-unsupported' ] create_newcase_cmd.extend(machine_args) if inputdata_path: create_newcase_cmd.extend(['--input-dir', inputdata_path]) run_cmd_output_on_error(create_newcase_cmd, errmsg='Problem creating CTSM case directory') subprocess.check_call([xmlchange, 'LILAC_MODE=on'], cwd=case_dir) if build_debug: subprocess.check_call([xmlchange, 'DEBUG=TRUE'], cwd=case_dir) if build_with_openmp: subprocess.check_call([xmlchange, 'FORCE_BUILD_SMP=TRUE'], cwd=case_dir) run_cmd_output_on_error([os.path.join(case_dir, 'case.setup')], errmsg='Problem setting up CTSM case directory', cwd=case_dir) make_link(os.path.join(case_dir, 'bld'), os.path.join(build_dir, 'bld')) if machine is not None: # For a pre-existing machine, the .env_mach_specific files are likely useful to # the user. Make sym links to these with more intuitive names. for extension in ('sh', 'csh'): make_link( os.path.join(case_dir, '.env_mach_specific.{}'.format(extension)), os.path.join(build_dir, 'ctsm_build_environment.{}'.format(extension)))