diff --git a/.gitignore b/.gitignore index 2b8f29291046e0741acbe422a81ab0bfb306c969..d9c2eab0c84fe46503c4e4193f8584b8b0b6b0ce 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,17 @@ work_* sources/oasis3-mct/generated __pycache__ +tests/data// tests/.coverage* tests/data/primavera/ tests/htmlcov +tests/.gitignore +tests/amip.yaml.sh +tests/data/areas-amip.nc +tests/data/bak/ +tests/data/ece3-toy-model/ +tests/data/grids-amip.nc +tests/data/masks-amip.nc +tests/data/test_word_break.sh +tests/data/tmp1.nc sources/oasis3-mct/util/make_dir/make.inc diff --git a/sources/data-coupler/AMIPDataCoupler.py b/sources/data-coupler/AMIPDataCoupler.py deleted file mode 100644 index a456ff7eef14e786e6e1c18908ef6bc061c87da0..0000000000000000000000000000000000000000 --- a/sources/data-coupler/AMIPDataCoupler.py +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2022 - Barcelona Supercomputing Center -# Authors: Etienne Tourigny, Rodrigo Martín Posada -# MIT License - -from DataCoupler import DataCoupler - -# Constants -NAMELIST_FILE_NAME = 'namelist.amip' -NAMELIST_SECTION = 'NAMAMIP' -LOG_FILE_NAME = 'amip.log' -CPLNG_COMP_NAME = 'AMIPFORC' - -if __name__ == '__main__': - # Setup - amip = DataCoupler(NAMELIST_FILE_NAME, NAMELIST_SECTION, LOG_FILE_NAME) - amip.setup_data_coupler() - amip.setup_oasis(CPLNG_COMP_NAME, write_grid=True, write_grid_mask=True, - write_grid_corners= True, write_grid_areas = True) - # Time loop - amip.run_time_loop() - # Finalize - amip.finalise_data_coupler() - diff --git a/sources/data-coupler/DataCoupler.py b/sources/data-coupler/DataCoupler.py index 854e2a5fb7fd8144551a53433f10f8674b8f3c85..cf8156bcfe5467a7b64cadf6ef79e5be054ec9f1 100644 --- a/sources/data-coupler/DataCoupler.py +++ b/sources/data-coupler/DataCoupler.py @@ -9,20 +9,25 @@ import numpy as np import os import logging import math +import sys +import argparse from DataCouplerUtils import read_namelist, days_since_refyear, is_leap, earth_area +from DataCouplerUtils import read_DataCoupler_yaml_input + from DataCouplerFileVar import FileInputVar from DataCouplerOasisVar import OasisOutputVar class DataCoupler: - def __init__(self, NAMELIST_FILE_NAME, NAMELIST_SECTION, LOG_FILE_NAME): + def __init__(self,yaml_conf_file): + + ModelNameSend, ModelNameReceive, LogFileName, RunLengthSec, TimeStepSec, StartYear, StartMonth, \ + StartDay, FixYear, GridInfo, LDebug, fileIn_vars_config, oasisOut_vars_config, OasisOutputVars_readin , \ + = read_DataCoupler_yaml_input(yaml_conf_file) - # Read RunLengthSec,TimeStepSec, config, etc. from namelist - RunLengthSec, TimeStepSec, StartYear, StartMonth, \ - StartDay, FixYear, LDebug, fileIn_vars_config, oasisOut_vars_config = read_namelist(NAMELIST_FILE_NAME, NAMELIST_SECTION) if LDebug: - logging.basicConfig(filename=LOG_FILE_NAME, format='%(message)s', level=logging.DEBUG) + logging.basicConfig(filename=LogFileName, format='%(message)s', level=logging.DEBUG) date_yref_min = max([conf['yref_min'] for conf in fileIn_vars_config]) date_yref_max = min([conf['yref_max'] for conf in fileIn_vars_config]) @@ -38,6 +43,9 @@ class DataCoupler: if ((StartYear < date_yref_min) and (RunLengthSec > (date_yref_min-StartYear+1)*3600*24*365)): raise Exception("RunLengthSec is too long for StartYear less than date_yref_min") + # Oasis Compiler description + self.OasisCPLNG = ModelNameSend + # time axis unit = days self.delta_t = TimeStepSec/86400. self.fix_year = FixYear @@ -58,11 +66,13 @@ class DataCoupler: for conf in fileIn_vars_config: self.fileIn_vars[conf['id']] = FileInputVar(conf, self.fix_year, self.start_year) logging.debug('fileIn_vars: {}'.format(self.fileIn_vars.keys())) + - def setup_oasis(self, CPLNG_COMP_NAME, write_grid=True, write_grid_mask=True, write_grid_corners= True, write_grid_areas = True): + + def setup_oasis(self, write_grid=True, write_grid_mask=True, write_grid_corners= True, write_grid_areas = True): # OASIS init - self.oasis_comp = pyoasis.Component(CPLNG_COMP_NAME) + self.oasis_comp = pyoasis.Component(self.OasisCPLNG) self.oasisOut_vars = {} # Setup grids and write if requested @@ -113,23 +123,26 @@ class DataCoupler: for v in grid_vars: # look for this oasis var in OasisVars config configs = self._oasisOut_vars_config - config = list(filter(lambda configs: configs['id'] == v.oasis_name, configs)) + config = list(filter(lambda configs: configs['send_id'] == v.oasis_name, configs)) if len(config)!=1: raise Exception("oasis var {} not defined in OasisOutputVars".format(v.oasis_name)) if not v.oasis_name in self.oasisOut_vars: logging.debug('creating oasis var {} with grid {} and fileIn_var {}'.format(v.oasis_name, grid_name,v.id)) self.oasisOut_vars[v.oasis_name] = OasisOutputVar(config[0], partition, v.grid_lon.shape, {v.id:v}) + else: logging.debug('adding to oasis var {} with grid {} fileIn_var {}'.format(v.oasis_name, grid_name,v.id)) self.oasisOut_vars[v.oasis_name].add_file_input_var(v.id,v) + logging.debug('oasisOut_vars: {}'.format(str(self.oasisOut_vars.keys()))) for var_name, oasisOut_var in self.oasisOut_vars.items(): logging.debug('oasisOut_var {} is linked to fileIn vars {}'.format(var_name, oasisOut_var.file_input_vars() )) + print('oasisOut_var {} is linked to fileIn vars {}'.format(var_name, oasisOut_var.file_input_vars() ),file=sys.stderr) # check that all OasisVars are actually defined for config in self._oasisOut_vars_config: - if not config['id'] in self.oasisOut_vars: - raise Exception("oasis var {} in OasisOutputVars not defined in FileInputVars".format(config['id'])) + if not config['send_id'] in self.oasisOut_vars: + raise Exception("oasis var {} in OasisOutputVars not defined in FileInputVars".format(config['send_id'])) self.oasis_comp.enddef() @@ -260,3 +273,27 @@ class DataCoupler: 'T' if self.lleapfx2 else 'F')) logging.debug('UPDATED DataCoupler INIT - tnewyear: {}'.format(self.tnewyear)) logging.debug('DataCoupler INIT - tlastfeb: {}'.format(self.tlastfeb)) + + + +if __name__ == '__main__': + # receive the yaml experiment input file is it exists , otherwise pass + try: + parser=argparse.ArgumentParser() + parser.add_argument("--conf",type=str) + args = parser.parse_args() + yaml_conf_file = args.conf + except: + print("NOTE: Could note read in the input yaml file : {}".format(yaml_conf_file), file=sys.stderr) + else: + print("NOTE: input yaml file is : {}".format(yaml_conf_file), file=sys.stderr) + + # Setup + datacoupler = DataCoupler(yaml_conf_file) + datacoupler.setup_data_coupler() + datacoupler.setup_oasis(write_grid=True, write_grid_mask=True, + write_grid_corners= True, write_grid_areas = True) + # Time loop + datacoupler.run_time_loop() + # Finalize + datacoupler.finalise_data_coupler() \ No newline at end of file diff --git a/sources/data-coupler/DataCouplerOasisVar.py b/sources/data-coupler/DataCouplerOasisVar.py index d7ff6280edb09931422886366497ab72cb077cc1..7b27d0be54b50cf83992b88e41c5036d61532ce6 100644 --- a/sources/data-coupler/DataCouplerOasisVar.py +++ b/sources/data-coupler/DataCouplerOasisVar.py @@ -12,7 +12,7 @@ from DataCouplerUtils import scale_factor_from_str class OasisOutputVar: def __init__(self, conf, partition, grid_shape, fileIn_vars ): self._conf = conf - self._id = conf['id'] + self._id = conf['send_id'] self._reset = conf['reset'] self._scale_factor = scale_factor_from_str(conf['scale_factor']) if type(conf['scale_factor']) == str else conf['scale_factor'] self._offset = np.float64(conf['offset']) diff --git a/sources/data-coupler/DataCouplerPreprocessor.py b/sources/data-coupler/DataCouplerPreprocessor.py new file mode 100644 index 0000000000000000000000000000000000000000..855c906578f1434fd4385be026a8e5edc03de6dc --- /dev/null +++ b/sources/data-coupler/DataCouplerPreprocessor.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +# Copyright 2023 - Barcelona Supercomputing Center +# Authors: Amirpasha Mozaffari +# MIT License + +import yaml +from yaml.loader import SafeLoader +import os +import argparse +import sys + +from DataCouplerUtils import read_DataCoupler_yaml_input + +# It will readin the YAML file that is generated by the RunExample and generate a namcouple list before + + +def append_multiple_lines_to_file(file_path, lines_to_append): + with open(file_path, 'a') as file: + # for line in lines_to_append: + file.write(lines_to_append + '\n') + + +def add_field_to_namcouple(send_id, receive_id, timestepsec,send_grid_name, receive_grid): + lines_to_append = str(send_id) + " " + str(receive_id) + " 1 " + str(timestepsec) + " 1 rstas.nc EXPOUT \n" + \ + str(send_grid_name) + " " + str(receive_grid) + " LAG=0 \n" + \ + "P 0 P 0\n" + \ + "SCRIPR \n" + \ + "GAUSWGT LR SCALAR LATITUDE 1 9 2.0" + + return lines_to_append + + + +def create_empty_file(filename): + try: + with open(filename, 'w') as file: + pass # The file is created but remains empty + print(f"Empty file '{filename}' created successfully.") + except Exception as e: + print(f"An error occurred: {e}") + + +def add_begin_to_namecouple(nfields,runtime): + lines_to_append = """# ================================================================================================= +# General OASIS configuration +# ================================================================================================= + $NFIELDS + {nfields} + $END +# ------------------------------------------------------------------------------------------------- + $RUNTIME + {runtime} + $END +# ------------------------------------------------------------------------------------------------- + $NLOGPRT + 0 0 + $END +# ------------------------------------------------------------------------------------------------- + $STRINGS +# ================================================================================================= +# Fields send from AMIP to IFS +# ================================================================================================= +# --- AMIP forcing data --- [ifs amip]""" + + return(lines_to_append.format(nfields=nfields,runtime=runtime)) + + +def add_end_to_namecouple(): + lines_to_append = """# ------------------------------------------------------------------------------------------------- +$END +# =================================================================================================""" + + return lines_to_append + + +def create_yaml_conf_name_ifs_toy_model(filename,ModelName,run_length_sec,coupling_interval,nx,OasisOutputVars_readin): + + coupling_out_vars=[] + + coupling_in_vars = [] + for v in OasisOutputVars_readin.keys() : + coupling_in_vars.append(OasisOutputVars_readin[v]['receive_id']) + + create_empty_file(filename) + lines_to_append =""" # Copyright 2023 - Barcelona Supercomputing Center +# Author: Amirpasha Mozaffari +# TBD +--- + +# yaml metadata +model: + ModelName : {ModelName} + +simulation: + coupling_interval : {coupling_interval} + run_length_sec : {run_length_sec} + # Definition of the local partition grid cell + # L080_NX = 35718 # number of LAND grid cells at T159 resolution + # L128_NX = 88838 # number of LAND grid cells at T255 resolution + # L256_NX = 348528 # number of LAND grid cells at T511 resolution + nx : {nx} + +coupling: + out_vars : {out_vars} + in_vars : {in_vars} + restart_file : /path/ + """ + append_multiple_lines_to_file(filename, lines_to_append.format(ModelName=ModelName,coupling_interval=coupling_interval,run_length_sec=run_length_sec,nx=nx,out_vars=coupling_out_vars,in_vars=coupling_in_vars )) + + +if __name__ == '__main__': + + parser=argparse.ArgumentParser() + parser.add_argument("--conf",type=str) + parser.add_argument("--namcouple_output",type=str) + parser.add_argument("--toy_model_yaml_conf_output",type=str) + args = parser.parse_args() + yaml_conf_file = args.conf + namcouple_output = args.namcouple_output + toy_model_yaml_conf_output = args.toy_model_yaml_conf_output + + + # Read the yaml file + + ModelNameSend, ModelNameReceive, LogFileName, RunLengthSec, TimeStepSec, StartYear, StartMonth, \ + StartDay, FixYear, GridInfo, LDebug, fileIn_vars_config, oasisOut_vars_config, OasisOutputVars_readin = read_DataCoupler_yaml_input(yaml_conf_file) + + number_of_fields = len(OasisOutputVars_readin) + + # Creating the namcouple file amd insert the read-in data from YAML file + create_empty_file(namcouple_output) + lines=add_begin_to_namecouple(number_of_fields,RunLengthSec) + append_multiple_lines_to_file(namcouple_output, lines) + + for v in OasisOutputVars_readin.keys() : + lines = add_field_to_namcouple(OasisOutputVars_readin[v]['send_id'], OasisOutputVars_readin[v]['receive_id'], \ + TimeStepSec,OasisOutputVars_readin[v]['send_grid_name'], OasisOutputVars_readin[v]['receive_grid_name']) + append_multiple_lines_to_file(namcouple_output, lines) + + lines = add_end_to_namecouple() + append_multiple_lines_to_file(namcouple_output, lines) + + # Creating the yaml_conf_name_ifs_toy_model + + ifs_conf_yaml = toy_model_yaml_conf_output + create_yaml_conf_name_ifs_toy_model(ifs_conf_yaml,ModelNameReceive, RunLengthSec, TimeStepSec,GridInfo,OasisOutputVars_readin) diff --git a/sources/data-coupler/DataCouplerUtils.py b/sources/data-coupler/DataCouplerUtils.py index d84fdc89842e25fb9abf634df5472b48ec28dd9e..bac601bcdde13a09a1a21a114283541c1579d423 100644 --- a/sources/data-coupler/DataCouplerUtils.py +++ b/sources/data-coupler/DataCouplerUtils.py @@ -5,6 +5,12 @@ from datetime import date import re import f90nml import numpy as np +import yaml +from yaml.loader import SafeLoader +import sys +import os +import collections + # constants earth_area = 6371000.**2 @@ -216,6 +222,59 @@ def read_namelist(NAMELIST_FILE_NAME,NAMELIST_SECTION): raise Exception('DataCoupler: Invalid configuration ids, all ids must be unique') else: oasisOut_vars_config = None + return RunLengthSec, TimeStepSec, StartYear, StartMonth, StartDay, FixYear, LDebug, fileIn_vars_config, oasisOut_vars_config - return RunLengthSec, TimeStepSec, StartYear, StartMonth, StartDay, FixYear, LDebug, fileIn_vars_config, oasisOut_vars_config +## YAMLUtil + +# Read the DataCoupler YAML + +def read_DataCoupler_yaml_input(yaml_file): + ''' + Reads the experiment yaml file + ''' + + with open(yaml_file) as file: + read_in = yaml.load(file, Loader=SafeLoader) + file.close() + + # Model Information + ModelNameSend = read_in.get('ModelNameSend') + ModelNameReceive = read_in.get('ModelNameReceive') + LogFileName = read_in.get('LogFileName') + + ## Run Information + + RunLengthSec = read_in.get('RunLengthSec') + TimeStepSec = read_in.get('TimeStepSec') + StartYear = read_in.get('StartYear') + StartMonth = read_in.get('StartMonth') + StartDay = read_in.get('StartDay') + FixYear = read_in.get('FixYear') + GridInfo = read_in.get('GridInfo') + LDebug = read_in.get('LDebug') + + # Create the log_file name and sanity-check + + # Check the type of input in yaml file + if "FileInputVars" in read_in : + FileInputVars_readin = {} + FileInputVars_readin = read_in.get('FileInputVars') + # Name of the Variable for this experiment + FileInputVarNames = list(FileInputVars_readin.keys()) + # Variable configuration for this experiment + FileInputVarFields_conf = list(FileInputVars_readin.values()) + + if "OasisOutputVars" in read_in : + OasisOutputVars_readin = {} + OasisOutputVars_readin = read_in.get('OasisOutputVars') + print("NOTE: OasisOutputVars_readin : {}".format(OasisOutputVars_readin), file=sys.stderr) + # Name of the Variable for this experiment + OasisOutputVarsNames = list(OasisOutputVars_readin.keys()) + + # Variable configuration for this experiment + OasisOutputVars_conf = list(OasisOutputVars_readin.values()) + + return ModelNameSend, ModelNameReceive, LogFileName, RunLengthSec, TimeStepSec, StartYear, StartMonth,\ + StartDay, FixYear, GridInfo, LDebug, FileInputVarFields_conf, OasisOutputVars_conf, OasisOutputVars_readin + diff --git a/sources/data-coupler/how_to_run_mn4.ipynb b/sources/data-coupler/how_to_run_mn4.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..48b592b992123719e7c42dc609966458de2150ea --- /dev/null +++ b/sources/data-coupler/how_to_run_mn4.ipynb @@ -0,0 +1,171 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "# Introduction \n", + "The Data Coupler is being developed at the BSC to implement a CO2 box model for EC-Earth3 and to read and interpolate CO2 anthropogenic emissions (from e.g. CMIP6 input4MIPS) and CO2 surface fluxes (from e.g. vegetation+fire+ocean fluxes from SiB4). \n", + "\n", + "## Getting the model \n", + "The model can be cloned from (BSC-ES gitlab repository)[https://earth.bsc.es/gitlab/es/python-amip-reader] \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "git clone https://earth.bsc.es/gitlab/es/python-amip-reader.git\n", + "cd python-amip-reader\n", + "git checkout data-coupler" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setting up the model\n", + "First copy the datasets from Etienne's directory ```/gpfs/scratch/bsc32/bsc32051/git/python-amip-reader/tests/data/```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "datadir=/gpfs/scratch/bsc32/bsc32051/git/python-amip-reader/tests/data/\n", + "cd /python-amip-reader\n", + "cp -r $datadir/forcing/* tests/data/forcing\n", + "cp -r $datadir/co2/* tests/data/co2" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To build oasis and the optional fortran amip-forcing follow the instructions in https://earth.bsc.es/gitlab/es/python-amip-reader/-/blob/data-coupler/README.md#compile" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cd /sources/oasis3-mct/util/make_dir\n", + "cp make.templ.inc make.inc" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Please chnage the path of the make file to include MN4, and then complie the as follows: " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "include $(curr_path)/make.mn4\n", + "\n", + " \n", + "cd ../sources/amip-forcing/src/fortran\n", + " \n", + "module load impi/2017.4\n", + "module load mkl/2017.4\n", + "module load intel/2021.4\n", + "module load python/3.6.1\n", + "module load netcdf/4.2\n", + "module load cdo/1.9.3\n", + "\n", + "make realclean && make oasis && make" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Running the model\n", + "To run the model you need to edit file $HPCPERM/work/python-amip-reader/tests/launch-hpc2020.cmd and make sure the proper configuration is un-commented at the end, for example\n", + "\n", + "For a simple AMIP run using the classic fortran amip-forcing: \n", + "\n", + "bash ./run_example.sh fortran forcing 4 2005-01-01 2005-03-01 0 128 true false\n", + "\n", + "For the CO2 box model :\n", + "\n", + "bash ./run_example.sh co2box co2 4 2005-01-01 2005-05-01 0 128 true false\n", + "\n", + "The following lines hard-coded in run_example.sh control the options of the CO2 box model\n", + "\n", + " CO2_CMODE=true # set to false to disable co2 concentrations reading\n", + " CO2_EMODE=true # set to false to disable emissions reading\n", + "\n", + "\n", + "\n", + "There are 2 ways to run the model: \n", + "\n", + "1) run an interactive session and launch the job with bash (for short runs and debugging)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ecinteractive -c6 -t 12:00:00 -m 32GB\n", + "cd $HPCPERM/work/python-amip-reader/tests/\n", + "bash launch-hpc2020.cmd" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2) launch the job with sbatch (for longer runs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cd $HPCPERM/work/python-amip-reader/tests/\n", + "sbatch launch-hpc2020.cmd" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the run is successful, output will be present in a folder representing the run you made e.g. work_fortran_forcing_4_2005-01-01_2005-03-01_0_128_true\n", + "\n", + "Some files are post-processed with proper grid and time metadata applied." + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/sources/ece3-toy-model/ifs_toy_model.yaml b/sources/ece3-toy-model/ifs_toy_model.yaml index fcf56ff0ff71e81f472e0b6d910b6f1d1a951ba4..0beb1dbe9a634df7be7ad0cd195c627c7e3bc473 100644 --- a/sources/ece3-toy-model/ifs_toy_model.yaml +++ b/sources/ece3-toy-model/ifs_toy_model.yaml @@ -3,8 +3,10 @@ # TBD --- +# yaml metadata + model: - model_name: IFS_TOY + ModelName : IFS_TOY simulation: coupling_interval : 2700 diff --git a/sources/ece3-toy-model/nemo_toy_model.yaml b/sources/ece3-toy-model/nemo_toy_model.yaml index 22aa85040450133d480a59eb42af21680e1b40fd..16201ec95efdf27b1249f0a4c4e627dee62426ea 100644 --- a/sources/ece3-toy-model/nemo_toy_model.yaml +++ b/sources/ece3-toy-model/nemo_toy_model.yaml @@ -3,8 +3,10 @@ # TBD --- +# yaml metadata + model: - model_name: NEMO_TOY + ModelName : NEMO_TOY simulation: coupling_interval : 2700 diff --git a/sources/ece3-toy-model/runoff_toy_model.yaml b/sources/ece3-toy-model/runoff_toy_model.yaml index 308d1609527dbd90b5a47be841faa74801e66eb6..e78f53ba63c066d551e1a94227edcd33ee68161d 100644 --- a/sources/ece3-toy-model/runoff_toy_model.yaml +++ b/sources/ece3-toy-model/runoff_toy_model.yaml @@ -3,8 +3,10 @@ # TBD --- +# yaml metadata + model: - model_name: RUNOFF_TOY + ModelName : RUNOFF_TOY simulation: coupling_interval : 2700 diff --git a/sources/ece3-toy-model/toy_model.py b/sources/ece3-toy-model/toy_model.py index 5eada789db26b4b41669ce6c7d9c06ac3a14d1c5..3937b7ef38992aeea78399032fdad7eb6006613d 100644 --- a/sources/ece3-toy-model/toy_model.py +++ b/sources/ece3-toy-model/toy_model.py @@ -8,20 +8,30 @@ from yaml.loader import SafeLoader import logging import argparse import os - -import f90nml import pyoasis from pyoasis import OASIS # pylint: disable=no-name-in-module import numpy as np -if __name__ == '__main__': +def def_local_partition(nx, npes, mype): + il_size = nx // npes + il_offset = mype * il_size + if (npes-mype) <= nx % npes: + il_size += 1 + il_offset += (nx % npes) - (npes-mype) + return il_size, il_offset + + +if __name__ == '__main__': + ### Read in YAML file current_path = os.getcwd() parser=argparse.ArgumentParser() - parser.add_argument("--yaml_file_path",type=str) - args = parser.parse_args() - yamel_file_path = os.path.join(current_path,args.yaml_file_path) + #parser.add_argument("--run_dir",type=str) + parser.add_argument("--conf",type=str) + args = parser.parse_args() + yamel_file_path = os.path.join(current_path,args.conf) + if os.path.isfile(yamel_file_path) == False: print("YAML file does not exist. Aborted") raise NameError("YAML file does not exist.") @@ -34,7 +44,7 @@ if __name__ == '__main__': ### Read in file #read_yaml(read_in_data) model = read_in_data.get("model") - model_name = model.get("model_name") + model_name = model.get("ModelName") # Read in Simulation information simulation = read_in_data.get("simulation") @@ -46,7 +56,7 @@ if __name__ == '__main__': coupling = read_in_data.get("coupling") coupling_out_vars = coupling.get("out_vars") coupling_in_vars = coupling.get("in_vars") - restart_file = coupling.get("restart_file") + restart_file = coupling.get("restart_file") # This feature is not used for now. TODO ### Pass the values to original code @@ -72,28 +82,42 @@ if __name__ == '__main__': # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # PARTITION DEFINITION # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - # Definition of the local partition - partition = pyoasis.SerialPartition(simulation_nx) - + # for more than one processor is using a parallel partition and for single processor a serial + + if npes > 1: + il_size, il_offset = def_local_partition(simulation_nx, npes, mype) + logging.debug('Local partition definition') + logging.debug('il_size = {} il_offset = {} mype = {}'.format(il_size, il_offset, mype)) + partition = pyoasis.ApplePartition(il_offset, il_size) + field_data_size = il_size + logging.debug('Grid points in the current Apple - partition is: {},'.format(field_data_size)) + else: + partition = pyoasis.SerialPartition(simulation_nx) + field_data_size = simulation_nx + logging.debug('Grid points in the current Serial - partition is: {},'.format(field_data_size)) + + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # DECLARATION OF THE COUPLING FIELDS # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - + out_field_data = pyoasis.asarray(np.full(field_data_size, -1.0)) out_coupling_fields={} - - for v in coupling_out_vars: - out_coupling_fields[v] = pyoasis.Var(v, partition, OASIS.OUT) - logging.warning('var_id {}, added as OASIS_OUT var'.format(v)) - - - in_coupling_fields={} - - for v in coupling_in_vars: - in_coupling_fields[v] = pyoasis.Var(v, partition, OASIS.IN) - logging.info('var_id {}, added as OASIS_IN var'.format(v)) - - + + in_coupling_fields = {} # Create a dictionary to store the variables + in_field_data={} + + for name in coupling_out_vars: + var = pyoasis.Var(name, partition, OASIS.OUT) + out_coupling_fields[name] = var + logging.debug('var_id {}, added as OASIS_OUT var'.format(name)) + + for name in coupling_in_vars: + var = pyoasis.Var(name, partition, OASIS.IN) + in_coupling_fields[name] = var + in_field_data[name] = pyoasis.asarray(np.full(field_data_size, -1.0)) + logging.debug('var_id {}, added as OASIS_IN var'.format(name)) + + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # TERMINATION OF DEFINITION PHASE # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -106,32 +130,30 @@ if __name__ == '__main__': # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ logging.debug('Timestep, field min, mean and max value') - field_data = pyoasis.asarray(np.full(simulation_nx, -1.0)) for itap_sec in range(0, simulation_run_length_sec, simulation_coupling_interval): - logging.debug('ITAP_SEC: {} receiving fields'.format(itap_sec)) logging.debug(str(in_coupling_fields.keys())) + + for id, field in in_coupling_fields.items(): - field.get(itap_sec, field_data) - logging.debug('{} -> {:.3e} {:.3e} {:.3e}'.format( id, np.min(field_data), np.mean(field_data), np.max(field_data))) - logging.debug('--------------------------------------\n') + field.get(itap_sec, in_field_data[id]) + logging.debug('{} -> {:.3e} {:.3e} {:.3e}'.format( id, np.min(in_field_data[id]), np.mean(in_field_data[id]), np.max(in_field_data[id]))) - logging.debug('ITAP_SEC: {} sending fields'.format(itap_sec)) - logging.debug(str(out_coupling_fields.keys())) for id, field in out_coupling_fields.items(): sigma=1 mu=1 # send dummy data (100 for runoff, random for other variables) #TODO send dummy data read from oasis restart file + if id == "A_Runoff": - field_data[:]=1.4658e-06 - field_data[:]=100 + out_field_data[:]=1.4658e-06 + out_field_data[:]=100 else: - field_data[:]=sigma * np.random.randn(simulation_nx) + mu - field.put(itap_sec, field_data) - logging.debug('{} put -> {:.3e} {:.3e} {:.3e}'.format( id, np.min(field_data), np.mean(field_data), np.max(field_data))) - logging.debug('--------------------------------------\n') + out_field_data[:]=sigma * np.random.randn(field_data_size) + mu + field.put(itap_sec, out_field_data) + logging.debug('{} put -> {:.3e} {:.3e} {:.3e}'.format( id, np.min(out_field_data), np.mean(out_field_data), np.max(out_field_data))) + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # TERMINATION diff --git a/tests/IFS_toy.py b/tests/data/IFS_toy.py old mode 100755 new mode 100644 similarity index 100% rename from tests/IFS_toy.py rename to tests/data/IFS_toy.py diff --git a/tests/data/namelist_python.amip.sh b/tests/data/namelist_python.amip.sh deleted file mode 100755 index d135769bff1573f82255294dfc44c4cb636bc738..0000000000000000000000000000000000000000 --- a/tests/data/namelist_python.amip.sh +++ /dev/null @@ -1,18 +0,0 @@ -cat << EOF -!----------------------------------------------------------------------- -&NAMAMIP -!----------------------------------------------------------------------- - RunLengthSec = ${leg_length_sec} - TimeStepSec = ${cpl_freq_amip_sec} - StartYear = ${leg_start_date_yyyymmdd:0:4} - StartMonth = ${leg_start_date_yyyymmdd:4:2} - StartDay = ${leg_start_date_yyyymmdd:6:2} - FixYear = ${ifs_cmip_fixyear} -${sst_conf_var} -${sic_conf_var} -${co2_conf_var} -${oasis_conf_var} - LDebug = false -!----------------------------------------------------------------------- -/ -EOF diff --git a/tests/data/template_conf_datacoupler_co2.yaml b/tests/data/template_conf_datacoupler_co2.yaml new file mode 100755 index 0000000000000000000000000000000000000000..750011d01fce92fcebcb7e3e08f5fe62664c3cc2 --- /dev/null +++ b/tests/data/template_conf_datacoupler_co2.yaml @@ -0,0 +1,37 @@ +cat << EOF +# YAML input file for DataCoupler, It will be ingested and turn to Experiment YAML file + +## Model Information +OasisModel : IFS_TOY +OasisCPLNG : AMIPFORC +LogFileName : amip.log +YamlConfName : ${yaml_conf_name} +PartitionType : ApplePartition + +## Run Information +RunLengthSec : ${leg_length_sec} +TimeStepSec : ${cpl_freq_amip_sec} +StartYear : ${leg_start_date_yyyymmdd:0:4} +StartMonth : ${leg_start_date_yyyymmdd:4:2} +StartDay : ${leg_start_date_yyyymmdd:6:2} +FixYear : ${ifs_cmip_fixyear} +GridInfo : TBD_VALUE + +## Coupling Information +FileInputVars: + AMIP_sst_monthly : { id : AMIP_sst_monthly, grid_name: AMIP, oasis_name: AMIP_sst, file_pattern: tosbcs_input4MIPs_SSTsAndSeaIce_CMIP_PCMDI-AMIP-1-1-3_gn_187001-201706.nc, netcdf_variable: tosbcs, yref_min : 1870, yref_max: 2016, timestep: monthly, interpolate : true, scale_factor: 1, offset: 273.15, min: 271.38, max: , update: true, accum: true} + AMIP_sic_monthly : { id : AMIP_sic_monthly, grid_name: AMIP, oasis_name: AMIP_sic, file_pattern: siconcbcs_input4MIPs_SSTsAndSeaIce_CMIP_PCMDI-AMIP-1-1-3_gn_187001-201706.nc, netcdf_variable: siconcbcs, yref_min : 1870, yref_max: 2016, timestep: monthly, interpolate : true, scale_factor: 0.01, offset: 0, min: 0, max: 1, update: true, accum: true} + CO2_em_monthly : { id : CO2_em_monthly, grid_name: CO2_emis, oasis_name: AMIP_CO2_emis, file_pattern: CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412.nc, netcdf_variable: CO2_em_anthro, yref_min : 1750, yref_max: 2018, timestep: monthly, interpolate : false, scale_factor: 0.01, offset: 1, min: 0, max: , update: true, accum: true} + CO2_land_monthly: { id : CO2_land_monthly, grid_name: CO2_emis, oasis_name: AMIP_CO2_land, file_pattern: CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412.nc, netcdf_variable: CO2_em_anthro, yref_min : 1750, yref_max: 2018, timestep: monthly, interpolate : false, scale_factor: 0.01, offset: 0.5, min: 0, max: , update: true, accum: true} + CO2_ocean_monthly: { id : CO2_ocean_monthly, grid_name: CO2_emis, oasis_name: AMIP_CO2_ocean, file_pattern: CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412.nc, netcdf_variable: CO2_em_anthro, yref_min : 1750, yref_max: 2018, timestep: monthly, interpolate : false, scale_factor: 0.01, offset: 0.1, min: 0, max: , update: true, accum: true} + +OasisOutputVars: + AMIP_sst : { send_id: AMIP_sst, receive_id: A_SST, send_grid_name: 'AMIP', receive_grid_name: L128, timestep: 'daily', scale_factor: 1, offset: 0, reset: true } + AMIP_sic : { send_id: AMIP_sic, receive_id: A_Ice_frac, send_grid_name: 'AMIP', receive_grid_name: L128, timestep: 'daily', scale_factor: 1, offset: 0, reset: true } + AMIP_CO2_emis : { send_id: AMIP_CO2_emis, receive_id: A_CO2_emis, send_grid_name: 'CO2_emis', receive_grid_name: B128, timestep: 'daily', scale_factor: 1, offset: 0, reset: true } + AMIP_CO2_land : { send_id: AMIP_CO2_land, receive_id: A_CO2_land, send_grid_name: 'CO2_emis', receive_grid_name: B128, timestep: 'daily', scale_factor: 1, offset: 0, reset: true } + AMIP_CO2_ocean : { send_id: AMIP_CO2_ocean, receive_id: A_CO2_ocean, send_grid_name: 'CO2_emis', receive_grid_name: B128, timestep: 'daily', scale_factor: 1, offset: 0, reset: true } + +LDebug : false +EOF + diff --git a/tests/data/template_conf_datacoupler_forcing.yaml b/tests/data/template_conf_datacoupler_forcing.yaml new file mode 100755 index 0000000000000000000000000000000000000000..23e89c710c3721ed01ef3ba0b8b00f8e2d4743f8 --- /dev/null +++ b/tests/data/template_conf_datacoupler_forcing.yaml @@ -0,0 +1,36 @@ +cat << EOF +# YAML input file for DataCoupler, It will be ingested and turn to Experiment YAML file + +# yaml metadata +type : 1 # DataCoupler is 1, ToyModel is 2 + +## Model Information +ModelNameSend : AMIPFORC +ModelNameReceive : IFS_TOY +LogFileName : amip.log +YamlConfName : ${yaml_conf_file} + +## Run Information +RunLengthSec : ${leg_length_sec} +TimeStepSec : ${cpl_freq_amip_sec} +StartYear : ${leg_start_date_yyyymmdd:0:4} +StartMonth : ${leg_start_date_yyyymmdd:4:2} +StartDay : ${leg_start_date_yyyymmdd:6:2} +FixYear : ${ifs_cmip_fixyear} +GridInfo : 88838 # number of grid cells : L080_NX = 35718 @ T159 resolution / L128_NX = 88838 @ T255 resolution / L256_NX = 348528 @ T511 resolution + + + + +## Coupling Information +FileInputVars: + AMIP_sst_monthly : { id : AMIP_sst_monthly, grid_name: AMIP, oasis_name: AMIP_sst, file_pattern: tosbcs_input4MIPs_SSTsAndSeaIce_CMIP_PCMDI-AMIP-1-1-3_gn_187001-201706.nc, netcdf_variable: tosbcs, yref_min : 1870, yref_max: 2016, timestep: monthly, interpolate : true, scale_factor: 1, offset: 273.15, min: 271.38, max: , update: true, accum: true} + AMIP_sic_monthly : { id : AMIP_sic_monthly, grid_name: AMIP, oasis_name: AMIP_sic, file_pattern: siconcbcs_input4MIPs_SSTsAndSeaIce_CMIP_PCMDI-AMIP-1-1-3_gn_187001-201706.nc, netcdf_variable: siconcbcs, yref_min : 1870, yref_max: 2016, timestep: monthly, interpolate : true, scale_factor: 0.01, offset: 0, min: 0, max: 1, update: true, accum: true} + +OasisOutputVars: + AMIP_sst : { send_id: AMIP_sst, receive_id: A_SST, send_grid_name: 'AMIP', receive_grid_name: L128, timestep: 'daily', scale_factor: 1, offset: 0, reset: true } + AMIP_sic : { send_id: AMIP_sic, receive_id: A_Ice_frac, send_grid_name: 'AMIP', receive_grid_name: L128, timestep: 'daily', scale_factor: 1, offset: 0, reset: true } + +LDebug : false +EOF + diff --git a/tests/launch-mn4.cmd b/tests/launch-mn4.cmd deleted file mode 100644 index 51b57a7af2c29d8ba49594402a9ec714e5898a54..0000000000000000000000000000000000000000 --- a/tests/launch-mn4.cmd +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -#SBATCH --qos=debug -#SBATCH -N 1 -#SBATCH -n 5 -#SBATCH -c 1 -#SBATCH -t 1:00:00 -#SBATCH --exclusive - -module load python/3.6.1 -module load netcdf/4.2 -module load CDO/1.9.3 -module list -export MPIRUN="mpirun" - -source ../sources/oasis3-mct/generated/python/init.sh - -#bash ./run_example.sh pythoncompat forcing 4 2005-01-01 2005-03-01 0 128 true -#bash ./run_example.sh fortran forcing 4 2005-01-01 2005-03-01 0 128 true -#bash ./run_example-t1279.sh python forcing 4 2010-01-01 2010-03-01 0 128 true - -#bash ./run_example.sh datacoupler co2 4 2005-01-01 2005-03-01 0 128 true false -#bash ./run_example.sh co2box co2 4 2005-01-01 2005-03-01 0 128 true false - -bash ./run_example.sh datacoupler forcing 4 2005-01-01 2005-03-01 0 128 true false -#bash ./run_example.sh python co2 4 2005-01-01 2005-03-01 0 128 true -#bash ./run_example.sh co2box co2 4 2005-01-01 2005-03-01 0 128 true -#bash ./run_example.sh co2box co2 4 2005-01-01 2005-03-01 0 128 true false -#bash ./run_example.sh co2box co2 4 2005-01-01 2005-05-01 0 128 true false diff --git a/tests/launch_ece3_data_coupler_mn4.cmd b/tests/launch_ece3_data_coupler_mn4.cmd new file mode 100644 index 0000000000000000000000000000000000000000..7a8948dee71e6f12fc650aa9e82189254fea3848 --- /dev/null +++ b/tests/launch_ece3_data_coupler_mn4.cmd @@ -0,0 +1,46 @@ +#!/bin/bash +# slurm specific options for MN4 +#SBATCH --qos=debug +#SBATCH -N 1 +#SBATCH -n 5 +#SBATCH -c 1 +#SBATCH -t 0:05:00 +#SBATCH --exclusive +# Please indicate the machine that is in use. for now only includes "BSC_MN4" & "EC_HPC2020" +platform="BSC_MN4" + +if [ $platform = BSC_MN4 ]; then + # Environment for MN4 + module load python/3.6.1 + module load netcdf/4.2 + module load CDO/1.9.3 + module list + export MPIRUN="mpirun" + +elif [ $platform = EC_HPC2020 ] ; then + + module reset + #module load python3/3.8.8-01 prgenv/intel intel/2021.4.0 intel-mkl/19.0.5 hpcx-openmpi/2.9.0 hdf5-parallel/1.10.6 netcdf4-parallel/4.7.4 cdo + module load python3/3.10.10-01 prgenv/intel intel/2021.4.0 hpcx-openmpi/2.9.0 hdf5-parallel/1.12.2 netcdf4-parallel/4.9.1 cdo + module list + export MPIRUN="mpirun -oversubscribe" + source ../sources/oasis3-mct/generated/python/init.sh + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${NETCDF4_PARALLEL_DIR}/lib:${ECCODES_DIR}/lib:${HDF5_DIR}/lib" + echo LD_LIBRARY_PATH: $LD_LIBRARY_PATH + +fi + +source ../sources/oasis3-mct/generated/python/init.sh + +#bash ./run_example.sh pythoncompat forcing 4 2005-01-01 2005-03-01 0 128 true +#bash ./run_example.sh fortran forcing 4 2005-01-01 2005-03-01 0 128 true +#bash ./run_example-t1279.sh python forcing 4 2010-01-01 2010-03-01 0 128 true + +#bash ./run_example.sh datacoupler co2 4 2005-01-01 2005-03-01 0 128 true false template_conf_datacoupler_co2.yaml +#bash ./run_example.sh co2box co2 4 2005-01-01 2005-03-01 0 128 true false + +bash ./run_example.sh datacoupler forcing 4 2005-01-01 2005-03-01 0 128 true false template_conf_datacoupler_forcing.yaml +#bash ./run_example.sh python co2 4 2005-01-01 2005-03-01 0 128 true +#bash ./run_example.sh co2box co2 4 2005-01-01 2005-03-01 0 128 true +#bash ./run_example.sh co2box co2 4 2005-01-01 2005-03-01 0 128 true false +#bash ./run_example.sh co2box co2 4 2005-01-01 2005-05-01 0 128 true false diff --git a/sources/ece3-toy-model/launch_yaml_mn4.cmd b/tests/launch_ece3_toy_model_mn4.cmd old mode 100644 new mode 100755 similarity index 56% rename from sources/ece3-toy-model/launch_yaml_mn4.cmd rename to tests/launch_ece3_toy_model_mn4.cmd index 764fe7ec27617a0447dc2b2263f9c9a1bf5cfef4..8ed9b73933229abbfad8c736b7dd76eaf9e81808 --- a/sources/ece3-toy-model/launch_yaml_mn4.cmd +++ b/tests/launch_ece3_toy_model_mn4.cmd @@ -5,7 +5,7 @@ #SBATCH -N 1 #SBATCH -n 3 #SBATCH -c 1 -#SBATCH -t 1:00:00 +#SBATCH -t 0:05:00 #SBATCH --exclusive #load python and netcdf modules @@ -16,15 +16,18 @@ module load netcdf/4.2 set -xuve # setup pyOasis environment -export PYOASIS_ROOT=/gpfs/scratch/bsc32/bsc32051/git/python-amip-reader/sources/oasis3-mct/generated -export LD_LIBRARY_PATH=${PYOASIS_ROOT}/lib:${LD_LIBRARY_PATH} -export PYTHONPATH=${PYOASIS_ROOT}/python:${PYTHONPATH} -export MPIRUN4PY="mpirun" +source ../sources/oasis3-mct/generated/python/init.sh + +## +timestamp=$(date +%Y%m%d_%H%M%S) + # prepare rundir -rundir=run/ -srcdir=`pwd` datadir=/gpfs/scratch/bsc32/bsc32051/git/python-amip-reader/tests/data/ece3-toy-model +testdir=`pwd` +srcdir=$testdir/../sources/ece3-toy-model + +rundir=${testdir}/work_ece3_toy_model_${timestamp} rm -rf $rundir mkdir -p $rundir @@ -37,8 +40,12 @@ cp -f $srcdir/*.py $rundir cp -f $srcdir/namcouple $rundir cp -f $srcdir/*.yaml $rundir +toy_model="toy_model.py" + +echo "prep is finished" cd $rundir # run IFS+NEMO+runoff toy model -mpirun -np 1 python3 $srcdir/toy_model.py --yaml_file_path ifs_toy_model.yaml : -np 1 python3 $srcdir/toy_model.py --yaml_file_path nemo_toy_model.yaml : -np 1 python3 $srcdir/toy_model.py --yaml_file_path runoff_toy_model.yaml +mpirun -np 1 python3 ${rundir}/${toy_model} --conf ifs_toy_model.yaml : -np 1 python3 ${rundir}/${toy_model} --conf nemo_toy_model.yaml : -np 1 python3 ${rundir}/${toy_model} --conf runoff_toy_model.yaml + diff --git a/tests/run_example.sh b/tests/run_example.sh index dcb068fd03959014aaf2c3d83bea966e69a1b303..596a25982c8351a8087dec6442049de017ecd886 100755 --- a/tests/run_example.sh +++ b/tests/run_example.sh @@ -1,9 +1,10 @@ #!/bin/bash ## Usage -if [ $# -ne 9 ]; then + +if [ $# -ne 10 ]; then echo 'Invalid args.' - echo 'Usage ./run_example.sh ' - echo 'Try ./run_example.sh python forcing 4 1990-01-01 1991-01-01 0 L128 true' + echo 'Usage ./run_example.sh ' + echo 'Try .bash ./run_example.sh datacoupler forcing 4 2005-01-01 2005-03-01 0 128 true false template_conf_datacoupler_forcing.yaml' exit 1 fi @@ -21,6 +22,7 @@ ifs_cmip_fixyear=$6 ifs_grid=$7 amip_interpolate=$8 co2_interpolate=$9 +yaml_conf_template=${10} host=`uname -n` user=`whoami` @@ -28,9 +30,10 @@ user=`whoami` srcdir=`pwd` datadir=$srcdir/data +# ece_3_toy_model as exe1 +exe1='python3 toy_model.py' +source_exe1=/../$srcdir/../sources/ece3-toy-model/toy_model.py -exe1='python3 IFS_toy.py' -source_exe1=$srcdir/IFS_toy.py if [ $model = fortran ]; then exe2='./amip-forcing' @@ -41,19 +44,13 @@ if [ $model = fortran ]; then fi elif [ $model = python ] || [ $model = pythoncompat ]; then exe2='python3 amip_forcing.py' - # exe2='coverage run -p --branch --include=*/amip-forcing/src/python/* amip_forcing.py' - # exe2='python3 -m cProfile -s cumtime amip_forcing.py' + source_exe2=$srcdir/../sources/amip-forcing/src/python/*.py elif [ $model = datacoupler ] ; then - exe2='python3 AMIPDataCoupler.py' - # exe2='coverage run -p --branch --include=*/amip-forcing/src/python/* amip_forcing.py' - # exe2='python3 -m cProfile -s cumtime amip_forcing.py' - source_exe2=$srcdir/../sources/data-coupler/*.py -elif [ $model = co2box ] ; then - exe2='python3 CO2BoxDataCoupler.py' - # exe2='coverage run -p --branch --include=*/amip-forcing/src/python/* amip_forcing.py' - # exe2='python3 -m cProfile -s cumtime amip_forcing.py' + exe2='python3 DataCoupler.py' + source_exe2=$srcdir/../sources/data-coupler/*.py + else echo 'Invalid args. You must specify a language for the AMIP reader: | ' exit 1 @@ -64,7 +61,7 @@ CO2_EMODE=false # - Define rundir rundir=${srcdir}/work_${model}_${amip_mode}_${nproc_exe1}_${leg_start_date}_${leg_end_date}_${ifs_cmip_fixyear}_${ifs_grid}_${amip_interpolate} -# export COVERAGE_FILE=${rundir}/../.coverage + echo '*****************************************************************' #echo '*** '$casename' : '$run @@ -85,17 +82,14 @@ mkdir -p $rundir ln -sf $datadir/ICMGGa22e+000000 $rundir/. ln -sf $datadir/*.txt $rundir/. # Get SST and SIC -#if [ $amip_mode = forcing ] || [ $amip_mode = co2 ]; then -if [ $amip_mode = forcing ] || [ $amip_mode = co2 ] ; then +if [ $amip_mode = forcing ] || [ $amip_mode = co2 ] || [ $model=datacoupler ]; then ln -sf $datadir/forcing/siconcbcs*.nc $rundir/. ln -sf $datadir/forcing/tosbcs*.nc $rundir/. ln -sf $datadir/forcing/rmp_AMIP_to_L${ifs_grid}_GAUSWGT*.nc $rundir/. - if [ $amip_mode = co2 ]; then - ln -sf $datadir/co2/CO2-em-anthro_*.nc $rundir/. - ln -sf $datadir/co2/CO2-em-AIR-anthro_*.nc $rundir/. - ln -sf $datadir/co2/mole-fraction-of-carbon-dioxide-in-air_*.nc* $rundir/. - ln -sf $datadir/co2/rmp_CO2_emis_to_B${ifs_grid}_GAUSWGT*.nc $rundir/. - fi + ln -sf $datadir/co2/CO2-em-anthro_*.nc $rundir/. + ln -sf $datadir/co2/CO2-em-AIR-anthro_*.nc $rundir/. + ln -sf $datadir/co2/mole-fraction-of-carbon-dioxide-in-air_*.nc* $rundir/. + ln -sf $datadir/co2/rmp_CO2_emis_to_B${ifs_grid}_GAUSWGT*.nc $rundir/. else ln -sf $datadir/$amip_mode/HadI*.nc $rundir/. ln -sf $datadir/$amip_mode/rmp_PSIC_to_${ifs_grid}_GAUSWGT.nc $rundir/. @@ -112,10 +106,13 @@ else cp -f $datadir/areas-noamip.nc $rundir/areas.nc fi cp -f $datadir/*.sh $rundir/. -cp -f $source_exe1 $rundir/. +cp -f $datadir/*.yaml $rundir/. +ln -sf $source_exe1 $rundir/. ln -sf $source_exe2 $rundir/. +cp -f $srcdir/*.py $rundir/. cd $rundir +###################################################################### ### Generate namelist leg_length_sec=$(( $(date -u -d "${leg_end_date}" +%s) - $(date -u -d "${leg_start_date}" +%s) )) cpl_freq_amip_sec=86400 # Always @@ -124,98 +121,51 @@ leg_start_date_yyyymmdd=$(date -u -d "${leg_start_date}" +%Y%m%d) if [ $model = fortran ] || [ $model = pythoncompat ]; then if [ $amip_mode = forcing ]; then . ./namelist.amip.sh > ./namelist.amip - else + . ./namcouple.sh > ./namcouple + + elif [ $amip_mode = primavera ]; then . ./namelist_primavera.amip.sh > ./namelist.amip - fi -else - #if [ $amip_mode = forcing ] || [ $amip_mode = co2 ]; then - if [ $amip_mode = forcing ] || [ $amip_mode = co2 ]; then - i=1 - if [ $model = co2box ] || [ $model = datacoupler ]; then - var=FileInputVars - else - var=Vars - fi - sst_conf_var=${var}"("$((i++))",:) = 'AMIP_sst_monthly', 'AMIP', 'AMIP_sst', 'tosbcs_input4MIPs_SSTsAndSeaIce_CMIP_PCMDI-AMIP-1-1-3_gn_187001-201706.nc', 'tosbcs', 1870, 2016, 'monthly', ${amip_interpolate}, 1, 273.15, 271.38, ,true,true," - sic_conf_var=${var}"("$((i++))",:) = 'AMIP_sic_monthly', 'AMIP', 'AMIP_sic', 'siconcbcs_input4MIPs_SSTsAndSeaIce_CMIP_PCMDI-AMIP-1-1-3_gn_187001-201706.nc', 'siconcbcs', 1870, 2016, 'monthly', ${amip_interpolate}, 0.01, 0, 0, 1,true,true," - - j=1 - oasis_conf_var="!OasisOutputVars(j,:) = , , , , , \n" - oasis_conf_var=$'\n'"OasisOutputVars("$((j++))",:) = 'AMIP_sst', 'AMIP', 'daily', 1, 0, true," - oasis_conf_var+=$'\n'"OasisOutputVars("$((j++))",:) = 'AMIP_sic', 'AMIP', 'daily', 1, 0, true," - if [ $amip_mode = co2 ]; then - co2_conf_var="" - co2_conf_var+="!FileInputVars(i,:) = "$'\n' - #[ $model = co2box ] && mod=CO2BOX || mod=AMIP - if [ $model = co2box ] ; then - mod=CO2BOX - CO2_CMODE=true # set to false to disable co2 concentrations reading - CO2_EMODE=true # set to false to disable emissions reading - else - mod=AMIP - CO2_CMODE=false # don't change this! - CO2_EMODE=true # don't change this! - fi - #this fix is required to correctly read the co2 files which havereftime 0-1-1, which isn't supported by python netcdf4 - #cdo -R -setreftime,1849-01-01,00:00 mole-fraction-of-carbon-dioxide-in-air_input4MIPs_GHGConcentrations_CMIP_UoM-CMIP-1-2-0_gr1-GMNHSH_184901-201412.nc mole-fraction-of-carbon-dioxide-in-air_input4MIPs_GHGConcentrations_CMIP_UoM-CMIP-1-2-0_gr1-GMNHSH_184901-201412.nc.mod - #this fix is required to correctly read the CO2_em_monthly files which have a 365day calendar and also to convert from a grid point/sectors fields to a global one - #cdo -L -setcalendar,gregorian -fldsum -vertsum -mul CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412.nc co2-area.nc CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412-global.nc - if [ ${CO2_CMODE} == true ] ; then - co2_conf_var+=${var}"("$((i++))",:) = 'CO2_cconc_monthly', 'GLOBAL', '"$mod"_CO2_cconc', 'mole-fraction-of-carbon-dioxide-in-air_input4MIPs_GHGConcentrations_CMIP_UoM-CMIP-1-2-0_gr1-GMNHSH_184901-201412.nc.mod', 'mole_fraction_of_carbon_dioxide_in_air', 1849, 2014, 'monthly', ${co2_interpolate}, 1, 0, , ,true,true,"$'\n' - co2_conf_var+=${var}"("$((i++))",:) = 'CO2_econc_monthly', 'GLOBAL', '"$mod"_CO2_econc', 'mole-fraction-of-carbon-dioxide-in-air_input4MIPs_GHGConcentrations_CMIP_UoM-CMIP-1-2-0_gr1-GMNHSH_184901-201412.nc.mod', 'mole_fraction_of_carbon_dioxide_in_air', 1849, 2014, 'monthly', ${co2_interpolate}, 'co2_ppm_to_mass', 0, , ,false,false,"$'\n' - co2_conf_var+=${var}"("$((i++))",:) = 'CO2_em_monthly_GLOBAL', 'GLOBAL', '"$mod"_CO2_econc', 'CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412-global.nc', 'CO2_em_anthro', 1750, 2018, 'monthly', ${co2_interpolate}, 86400, 0, , ,true,true,"$'\n' - # add land/ocean fluxes equal to 0.5/0.1 that of emissions, for demonstration purposes - co2_conf_var+=${var}"("$((i++))",:) = 'CO2_land_monthly_GLOBAL', 'GLOBAL', '"$mod"_CO2_econc', 'CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412-global.nc', 'CO2_em_anthro', 1750, 2018, 'monthly', ${co2_interpolate}, 43200, 0, , ,true,true,"$'\n' - co2_conf_var+=${var}"("$((i++))",:) = 'CO2_ocean_monthly_GLOBAL', 'GLOBAL', '"$mod"_CO2_econc', 'CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412-global.nc', 'CO2_em_anthro', 1750, 2018, 'monthly', ${co2_interpolate}, 8640, 0, , ,true,true,"$'\n' - fi - if [ ${CO2_EMODE} == true ] ; then - # this is the 3D monthly emissions used for ECE4, the calendar fix mentionned below is probably required - co2_conf_var+=${var}"("$((i++))",:) = 'CO2_em_monthly', 'CO2_emis', '"$mod"_CO2_emis', 'CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412.nc', 'CO2_em_anthro', 1750, 2018, 'monthly', ${co2_interpolate}, 1, 0, , ,true,true,"$'\n' - # add land/ocean fluxes equal to 0.5/0.1 that of emissions, for demonstration purposes - co2_conf_var+=${var}"("$((i++))",:) = 'CO2_land_monthly', 'CO2_emis', '"$mod"_CO2_land', 'CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412.nc', 'CO2_em_anthro', 1750, 2018, 'monthly', ${co2_interpolate}, 0.5, 0, , ,true,true,"$'\n' - co2_conf_var+=${var}"("$((i++))",:) = 'CO2_ocean_monthly', 'CO2_emis', '"$mod"_CO2_ocean', 'CO2-em-anthro_input4MIPs_emissions_CMIP_CEDS-2017-05-18_gn_200001-201412.nc', 'CO2_em_anthro', 1750, 2018, 'monthly', ${co2_interpolate}, 0.1, 0, , ,true,true,"$'\n' - fi - #OasisOutputVars(i,:) = - if [ ${CO2_CMODE} == true ] ; then - oasis_conf_var+=$'\n'"OasisOutputVars("$((j++))",:) = '"$mod"_CO2_cconc', 'GLOBAL', 'daily', 1, 0, true," - oasis_conf_var+=$'\n'"OasisOutputVars("$((j++))",:) = '"$mod"_CO2_econc', 'GLOBAL', 'daily', 'co2_mass_to_ppm', 0, false," - fi - if [ ${CO2_EMODE} == true ] ; then - # this is the 3D monthly emissions used for ECE4 - oasis_conf_var+=$'\n'"OasisOutputVars("$((j++))",:) = '"$mod"_CO2_emis', 'CO2_emis', 'daily', 1, 0, true," - oasis_conf_var+=$'\n'"OasisOutputVars("$((j++))",:) = '"$mod"_CO2_land', 'CO2_emis', 'daily', 1, 0, true," - oasis_conf_var+=$'\n'"OasisOutputVars("$((j++))",:) = '"$mod"_CO2_ocean', 'CO2_emis', 'daily', 1, 0, true," - fi - else - co2_conf_var="" - fi + . ./namcouple_primavera.sh > ./namcouple else - sst_conf_var="Vars(1,:) = 'AMIP_sst_daily', 'PSST', 'AMIP_sst', 'HadISST2_prelim_0to360_alldays_sst_[year].nc', 'sst', 1850, 2016, 'daily', false, 1, 0, , ," - sic_conf_var="Vars(2,:) = 'AMIP_sic_daily', 'PSIC', 'AMIP_sic', 'HadISST2_prelim_0to360_alldays_sic_[year].nc', 'sic', 1850, 2016, 'daily', false, 1, 0, , ," - co2_conf_var="" - oasis_conf_var="" + echo 'Error: for fortran or pythoncompat models, Only forcing or primavera is valid for amip_mode.' + exit 9 fi - . ./namelist_python.amip.sh > ./namelist.amip - [ $model = co2box ] && . ./namelist.co2box.sh > ./namelist.co2box -fi -if [ $amip_mode = forcing ]; then - . ./namcouple.sh > ./namcouple -elif [ $amip_mode = co2 ]; then - [ $model = co2box ] && . ./namcouple_co2box.sh > ./namcouple || . ./namcouple_co2.sh > ./namcouple else - . ./namcouple_primavera.sh > ./namcouple + + # Comleting the YAML template that user has provided and store it (yaml_conf_file) + + # TODO: dynamically genarte YAML file name based on the exp. + #yaml_conf_file=$(grep -F "ModelNameReceive" "$yaml_conf_template" | awk '{print $3}')'_exp_conf.yaml' + yaml_conf_file='DataCoupler_exp_conf.yaml' + . ./$yaml_conf_template > $yaml_conf_file + + # Generating a namcouple based on the input on the YAML file above to be used by OASIS + namcouple_output="namcouple" + toy_model_yaml_conf_output="yaml_conf_file_ifs_toy_model.yaml" + + # Run the py namcouple creator + namlist_yaml_conf_creator_script='python3 DataCouplerPreprocessor.py' + $namlist_yaml_conf_creator_script --conf $yaml_conf_file --namcouple_output $namcouple_output --toy_model_yaml_conf_output $toy_model_yaml_conf_output fi ###################################################################### ### Definition of mpirun command and batch script echo 'Executing the model using mpirun : ${MPIRUN}' -${MPIRUN} -np $nproc_exe1 $exe1 : -np $nproc_exe2 $exe2 + +# To seprate the DataCoupler with YAML input file from legecy codes +if [ $model = datacoupler ] ; then + ${MPIRUN} -np $nproc_exe1 $exe1 --conf $toy_model_yaml_conf_output : -np $nproc_exe2 $exe2 --conf $yaml_conf_file +else + ${MPIRUN} -np $nproc_exe1 $exe1 : -np $nproc_exe2 $exe2 +fi + # convert output . convert-ece4pyreader-grids.sh ${leg_start_date} #echo $casename 'is executed or submitted to queue.' echo 'Results are found in rundir : '$rundir +echo 'Run Example is successfully executed' ######################################################################