Ignore:
Timestamp:
Feb 12, 2026, 9:09:12 AM (2 weeks ago)
Author:
jbclement
Message:

PEM:
Major refactor following the previous ones (r3989 and r3991) completing the large structural reorganization and cleanup of the PEM codebase. This revision introduces newly designed modules, standardizes interfaces with explicit ini/end APIs and adds native NetCDF I/O together with explicit PCM/PEM adapters. In detail:

  • Some PEM models were corrected or improved:
    • Frost/perennial ice semantics are clarified via renaming;
    • Soil temperature remapping clarified, notably by removing the rescaling of temperature deviation;
    • Geothermal flux for the PCM is computed based on the PEM state;
  • New explicit PEM/PCM adapters ("set_*"/"build4PCM_*") to decouple PEM internal representation from PCM file layouts and reconstruct consistent fields returned to the PCM;
  • New explicit build/teardown routines that centralize allocation and initialization ordering, reducing accidental use of uninitialized data and making the model lifecycle explicit;
  • Add native read/write helpers for NetCDF that centralize all low-level NetCDF interactions with major improvements (and more simplicity) compared to legacy PEM/PCM I/O (see the modules "io_netcdf" and "output"). They support reading, creation and writing of "diagevol.nc" (renamed from "diagpem.nc") and start/restart files;
  • Provide well-focused modules ("numerics"/"maths"/"utility"/"display") to host commonly-used primitives:
    • "numerics" defines numerical types and constants for reproducibility, portability across compilers and future transitions (e.g. quadruple precision experiments);
    • "display" provides a single controlled interface for runtime messages, status output and diagnostics, avoiding direct 'print'/'write' to enable silent mode, log redirection, and MPI-safe output in the future.
    • "utility" (new module) hosts generic helpers used throughout the code (e.g. "int2str" or "real2str");
  • Add modules "clim_state_init"/"clim_state_rec" which provide robust read/write logic for "start/startfi/startpem", including 1D fallbacks, mesh conversions and dimension checks. NetCDF file creation is centralized and explicit. Restart files are now self-consistent and future-proof, requiring changes only to affected variables;
  • Add module "atmosphere" which computes pressure fields, reconstructs potential temperature and air mass. It also holds the whole logic to define sigma or hybrid coordinates for altitudes;
  • Add module "geometry" to centrilize dimensions logic and grid conversions routines (including 2 new ones "dyngrd2vect"/"vect2dyngrd");
  • Add module "slopes" to isolate slopes handling;
  • Add module "surface" to isolate surface management. Notably, albedo and emissivity are now fully reconstructed following the PCM settings;
  • Add module "allocation" to check the dimension initialization and centrilize allocation/deallocation;
  • Finalize module decomposition and renaming to consolidate domain-based modules, purpose-based routines and physics/process-based variables;
  • The main program now drives a clearer sequence of conceptual steps (initialization / reading / evolution / update / build / writing) and fails explicitly instead of silently defaulting;
  • Ice table logic is made restart-safe;
  • 'Open'/'read' intrinsic logic is made safe and automatic;
  • Improve discoverability and standardize the data handling (private vs protected vs public);
  • Apply consistent documentation/header style already introduced;
  • Update deftank scripts to reflect new names and launch wrappers;

This revision is a structural milestone aiming to be behavior-preserving where possible. It has been tested via compilation and short integration runs. However, due to extensive renames, moves, and API changes, full validation is still ongoing.
Note: the revision includes one (possibly two) easter egg hidden in the code for future archaeologists of the PEM. No physics were harmed.
JBC

Location:
trunk/LMDZ.COMMON/libf/evolution/deftank
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LMDZ.COMMON/libf/evolution/deftank/PCMrun.job

    r3981 r4065  
    3434
    3535# Running the PCM
    36 read i_myear n_myear convert_years iPCM iPEM nPCM nPCM_ini < launchPEM.info
     36read i_year n_year r_plnt2earth_yr iPCM iPEM nPCM nPCM_ini < launchPEM.info
    3737echo "Run \"PCM $iPCM\" is starting."
    3838cp run_PCM.def run.def
     
    7474fi
    7575((iPCM++))
    76 sed -i "1s/.*/$i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
     76sed -i "1s/.*/$i_year $n_year $r_plnt2earth_yr $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
  • trunk/LMDZ.COMMON/libf/evolution/deftank/PEMrun.job

    r3980 r4065  
    3131
    3232# Running the PEM
    33 read i_myear n_myear convert_years iPCM iPEM nPCM nPCM_ini < launchPEM.info
     33read i_year n_year r_plnt2earth_yr iPCM iPEM nPCM nPCM_ini < launchPEM.info
    3434echo "Run \"PEM $iPEM\" is starting."
    3535cp run_PEM.def run.def
     
    4242# Copy data files and prepare the next run
    4343mv run.log logs/runPEM${iPEM}.log
    44 if [ -f "diagpem.nc" ]; then
    45     mv diagpem.nc diags/diagpem${iPEM}.nc
     44if [ -f "diagevol.nc" ]; then
     45    mv diagevol.nc diags/diagevol${iPEM}.nc
    4646fi
    47 if [ -f "diagsoilpem.nc" ]; then
    48     mv diagsoilpem.nc diags/diagsoilpem${iPEM}.nc
     47if [ -f "diagevol_soil.nc" ]; then
     48    mv diagevol_soil.nc diags/diagevol_soil${iPEM}.nc
    4949fi
    5050cp restartpem.nc starts/restartpem${iPEM}.nc
     
    6262# Launch the next cycle
    6363#if [ "$(awk 'END{print $NF}' launchPEM.info)" -eq 7 ]; then
    64 #    read i_myear n_myear convert_years iPCM iPEM nPCM nPCM_ini < launchPEM.info
     64#    read i_year n_year r_plnt2earth_yr iPCM iPEM nPCM nPCM_ini < launchPEM.info
    6565#    ./launchPEM.sh cont # Continue the PEM run if it stopped because of job time limit
    6666#else
  • trunk/LMDZ.COMMON/libf/evolution/deftank/README

    r3981 r4065  
    4747    > the starting files you want to run the PCM: "startfi.nc", "start.nc"/"start1D.txt"/profiles;
    4848    > the necessary PEM files: "launchPEM.sh", "lib_launchPEM.sh", "PCMrun.job", "PEMrun.job", "run_PEM.def" and "obl_ecc_lsp.asc";
    49     > the optional PEM files: "diagpem.def" to define the PEM variables to be ouputted and "startpem.nc" to set the initial state of the PEM.
     49    > the optional PEM files: "diagevol.def" to define the PEM variables to be ouputted and "startpem.nc" to set the initial state of the PEM.
    5050
    5151The PEM files can be found in the deftank folder.
     
    6464    > the XIOS outputs of the PCM: "Xoutdaily4pem*.nc"/"Xoutyearly4pem*.nc";
    6565    > the outputs of the chained simulation: "launchPEM.log", "launchPEM.info" and possibly "kill_launchPEM.sh";
    66     > the usual outputs of the PEM: "restartfi.nc", "restart.nc"/"restart1D.txt" and "diagpem.nc".
     66    > the usual outputs of the PEM: "restartfi.nc", "restart.nc"/"restart1D.txt" and "diagevol.nc".
    6767During the simulation, the PCM/PEM run files are renamed conveniently and stored in the sub-directories "logs" (log files), "starts" (starting files) and "diags" (diagnostic files).
    6868If you run a simulation by submitting jobs, the script "kill_launchPEM.sh" is automatically generated. It can be used to kill in the queue of the job scheduler the jobs related to your chained simulation.
     
    114114
    115115# inipem_orbit.sh:
    116   Bash script file to set the orbital parameters of a file "startfi.nc" from Laskar's data contained in "obl_ecc_lsp.asc" according to the initial date 'year_earth_bp_ini' defined in "run_PEM.def". See also "modify_startfi_orbit.sh".
     116  Bash script file to set the orbital parameters of a file "startfi.nc" from Laskar's data contained in "obl_ecc_lsp.asc" according to the initial date 'pem_ini_earth_date' defined in "run_PEM.def". See also "modify_startfi_orbit.sh".
    117117
    118118# concat_pem.py:
  • trunk/LMDZ.COMMON/libf/evolution/deftank/concat_pem.py

    r3883 r4065  
    3535    parser.add_argument(
    3636        "--basename", type=str,
    37         help="Base name of the files, e.g., 'diagpem' for files like diagpem1.nc"
     37        help="Base name of the files, e.g., 'diagevol' for files like diagevol1.nc"
    3838    )
    3939    parser.add_argument(
     
    8888    # Defaults
    8989    default_folder = args.folder or "diags"
    90     default_basename = args.basename or "diagpem"
     90    default_basename = args.basename or "diagevol"
    9191
    9292    # Prompt for folder and basename with defaults
  • trunk/LMDZ.COMMON/libf/evolution/deftank/inipem_orbit.sh

    r3666 r4065  
    3636
    3737# Get the number of Earth years before present to start the PEM run
    38 eyears_bp_ini=$(grep 'year_earth_bp_ini=' $date_file | cut -d '=' -f 2 | tr -d '[:space:]')
     38eyears_bp_ini=$(grep 'pem_ini_earth_date=' $date_file | cut -d '=' -f 2 | tr -d '[:space:]')
    3939echo "In \"$date_file\":"
    4040echo "The starting date is $eyears_bp_ini Earth years."
  • trunk/LMDZ.COMMON/libf/evolution/deftank/launchPEM.sh

    r3981 r4065  
    1414# Modify here the parameters for the simulation
    1515###############################################
    16 # Set the number of years to be simulated, either Martian or Earth years (> 0):
    17 n_mars_years=100.
     16# Set the number of years to be simulated, either Planetary or Earth years (> 0):
     17n_planetary_years=100.
    1818#n_earth_years=300.
    1919
     
    6565            fi
    6666        fi
    67         read i_myear n_myear convert_years iPCM iPEM nPCM nPCM_ini < launchPEM.info
     67        read i_year n_year r_plnt2earth_yr iPCM iPEM nPCM nPCM_ini < launchPEM.info
    6868        cyclelaunch $mode $nPCM
    6969
     
    8585            fi
    8686        done
    87         read i_myear n_myear_old convert_years iPCM iPEM nPCM_old nPCM_ini_old < launchPEM.info
     87        read i_year n_year_old r_plnt2earth_yr iPCM iPEM nPCM_old nPCM_ini_old < launchPEM.info
    8888        while true; do
    8989            if [ $relaunch = "PCM" ]; then
     
    119119            echo "The number of PCM years between each PEM run has been modified from $nPCM_old to $nPCM."
    120120        fi
    121         if [ "$(echo "$n_myear != $n_myear_old" | bc)" -eq 1 ]; then
    122             echo "The number of initial PCM years has been modified from $n_myear_old to $n_myear."
     121        if [ "$(echo "$n_year != $n_year_old" | bc)" -eq 1 ]; then
     122            echo "The number of initial PCM years has been modified from $n_year_old to $n_year."
    123123        fi
    124         sed -i "1s/.*/$i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
     124        sed -i "1s/.*/$i_year $n_year $r_plnt2earth_yr $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
    125125        if [ -f "kill_launchPEM.sh" ]; then
    126126            ./kill_launchPEM.sh
  • trunk/LMDZ.COMMON/libf/evolution/deftank/lib_launchPEM.sh

    r3981 r4065  
    150150# To check if a PCM run is one year
    151151check_runyear() {
    152     if [ -f "run_PCM.def" ]; then
     152    if [ -f "startfi.nc" ]; then
    153153        year_sol=$(ncdump -v controle startfi.nc 2>/dev/null | \
    154154                   sed -n '/controle =/,/;/p' | tr -d '[:space:]' | \
    155155                   sed 's/.*=//; s/;//' | tr ',' '\n' | sed -n '14p')
    156156    else
     157        echo "Warning: no \"startfi.nc\" found! So default year_sol=669 (Mars year) is taken..."
    157158        year_sol=669 # Length of Martian year (sols)
    158159    fi
     
    182183    LC_NUMERIC=en_US.UTF-8
    183184
    184     if [ -v n_mars_years ] && [ ! -z "$n_mars_years" ]; then
    185         if [ $(echo "$n_mars_years <= 0." | bc -l) -eq 1 ]; then
    186             echo "Error: 'n_mars_years' must be > 0!"
     185    if [ -v n_planetary_years ] && [ ! -z "$n_planetary_years" ]; then
     186        if [ $(echo "$n_planetary_years <= 0." | bc -l) -eq 1 ]; then
     187            echo "Error: 'n_planetary_years' must be > 0!"
    187188            errlaunch
    188189        fi
     
    259260    myear=686.9725      # Number of Earth days in Martian year
    260261    eyear=365.256363004 # Number of days in Earth year
    261     convert_years=$(echo "$myear/$eyear" | bc -l)
    262     convert_years=$(printf "%.4f" $convert_years) # Rounding to the 4th decimal to respect the precision of Martian year
    263     if [ -v n_mars_years ]; then
    264         n_myear=$n_mars_years
    265         echo "Number of years to be simulated: $n_myear Martian years."
     262    r_plnt2earth_yr=$(echo "$myear/$eyear" | bc -l)
     263    r_plnt2earth_yr=$(printf "%.4f" $r_plnt2earth_yr) # Rounding to the 4th decimal to respect the precision of Martian year
     264    if [ -v n_planetary_years ]; then
     265        n_year=$n_planetary_years
     266        echo "Number of years to be simulated: $n_year Martian years."
    266267    elif [ -v n_earth_years ]; then
    267         n_myear=$(echo "$n_earth_years/$convert_years" | bc -l)
    268         echo "Number of years to be simulated: $n_earth_years Earth years = $n_myear Martian years."
     268        n_year=$(echo "$n_earth_years/$r_plnt2earth_yr" | bc -l)
     269        echo "Number of years to be simulated: $n_earth_years Earth years = $n_year Martian years."
    269270    fi
    270271}
     
    274275    echo "This is a chained simulation for PEM and PCM runs in $dir on $machine by $user."
    275276    convertyears
    276     i_myear=0.
     277    i_year=0.
    277278    iPEM=1
    278279    iPCM=1
     
    290291
    291292    # Create a file to manage years of the chained simulation and store some info from the PEM runs
    292     echo $i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini > launchPEM.info
     293    echo $i_year $n_year $r_plnt2earth_yr $iPCM $iPEM $nPCM $nPCM_ini > launchPEM.info
    293294}
    294295
     
    303304        ii=$3
    304305    fi
    305     if [ $(echo "$i_myear < $n_myear" | bc -l) -eq 1 ]; then
     306    if [ $(echo "$i_year < $n_year" | bc -l) -eq 1 ]; then
    306307        echo "Run \"PCM $iPCM\" ($ii/$2)"
    307308        if [ $1 -eq 0 ]; then # Mode: processing scripts
     
    331332    fi
    332333    for ((i = $ii; i <= $2; i++)); do
    333         if [ $(echo "$i_myear < $n_myear" | bc -l) -eq 1 ]; then
     334        if [ $(echo "$i_year < $n_year" | bc -l) -eq 1 ]; then
    334335            echo "Run \"PCM $iPCM\" ($i/$2)"
    335336            if [ $1 -eq 0 ]; then # Mode: processing scripts
     
    360361# arg1: launching mode
    361362submitPEM() {
    362     if [ $(echo "$i_myear < $n_myear" | bc -l) -eq 1 ]; then
     363    if [ $(echo "$i_year < $n_year" | bc -l) -eq 1 ]; then
    363364        echo "Run \"PEM $iPEM\""
    364365        if [ $1 -eq 0 ]; then # Mode: processing scripts
     
    393394
    394395    # PEM run
    395     if [ $(echo "$i_myear < $n_myear" | bc -l) -eq 1 ]; then
     396    if [ $(echo "$i_year < $n_year" | bc -l) -eq 1 ]; then
    396397        echo "Run \"PEM $iPEM\""
    397398        if [ $1 -eq 0 ]; then # Mode: processing scripts
     
    460461        # PCM relaunch during the initialization cycle
    461462        iPEM=1
    462         i_myear=0
    463         sed -i "1s/.*/$i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
    464         cleanfiles diags/diagpem .nc $(($iPEM - 1))
    465         cleanfiles diags/diagsoilpem .nc $(($iPEM - 1))
     463        i_year=0
     464        sed -i "1s/.*/$i_year $n_year $r_plnt2earth_yr $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
     465        cleanfiles diags/diagevol .nc $(($iPEM - 1))
     466        cleanfiles diags/diagevol_soil .nc $(($iPEM - 1))
    466467        cleanfiles logs/runPEM .log $(($iPEM - 1))
    467468        cleanfiles starts/restart1D_postPEM .txt $(($iPEM - 1))
     
    490491        iPEM=$(echo "($iPCM - $nPCM_ini)/$nPCM + 1" | bc)
    491492        il=$(echo "($irelaunch - $nPCM_ini + 1)%$nPCM + 1" | bc)
    492         i_myear=$(awk "NR==$iPEM {printf \"%s\n\", \$3}" "launchPEM.info")
    493         sed -i "1s/.*/$i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
    494         cleanfiles diags/diagpem .nc $(($iPEM - 1))
    495         cleanfiles diags/diagsoilpem .nc $(($iPEM - 1))
     493        i_year=$(awk "NR==$iPEM {printf \"%s\n\", \$3}" "launchPEM.info")
     494        sed -i "1s/.*/$i_year $n_year $r_plnt2earth_yr $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
     495        cleanfiles diags/diagevol .nc $(($iPEM - 1))
     496        cleanfiles diags/diagevol_soil .nc $(($iPEM - 1))
    496497        cleanfiles logs/runPEM .log $(($iPEM - 1))
    497498        cleanfiles starts/restart1D_postPEM .txt $(($iPEM - 1))
     
    521522    iPEM=$(echo "$irelaunch + 1" | bc)
    522523    iPCM=$(echo "$nPCM_ini + $nPCM*($irelaunch - 1) + 1" | bc)
    523     i_myear=$(awk "NR==$iPEM {printf \"%s\n\", \$3}" "launchPEM.info")
    524     sed -i "1s/.*/$i_myear $n_myear $convert_years $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
     524    i_year=$(awk "NR==$iPEM {printf \"%s\n\", \$3}" "launchPEM.info")
     525    sed -i "1s/.*/$i_year $n_year $r_plnt2earth_yr $iPCM $iPEM $nPCM $nPCM_ini/" launchPEM.info
    525526    cleanfiles diags/diagfi .nc $(($iPCM - 1))
    526527    cleanfiles diags/diagsoil .nc $(($iPCM - 1))
     
    531532    cleanfiles diags/Xoutdaily4pem .nc $(($iPCM - 1))
    532533    cleanfiles diags/Xoutyearly4pem .nc $(($iPCM - 1))
    533     cleanfiles diags/diagpem .nc $irelaunch
    534     cleanfiles diags/diagsoilpem .nc $irelaunch
     534    cleanfiles diags/diagevol .nc $irelaunch
     535    cleanfiles diags/diagevol_soil .nc $irelaunch
    535536    cleanfiles logs/runPEM .log $irelaunch
    536537    cleanfiles starts/restart1D_postPEM .txt $irelaunch
  • trunk/LMDZ.COMMON/libf/evolution/deftank/run_PEM.def

    r3989 r4065  
    1515
    1616# If evol_orbit=.true., number of Earth years before present to start the PEM run. Default = 0
    17 # year_earth_bp_ini=0
     17# pem_ini_earth_date=0
    1818
    19 # Do you want to vary the obliquity when following "obl_ecc_lsp.asc"? Default = .true.
    20 # var_obl=.true.
     19# Do you want the obliquity to eveolve when following "obl_ecc_lsp.asc"? Default = .true.
     20# evol_obl=.true.
    2121
    22 # Do you want to vary the eccentricity when following "obl_ecc_lsp.asc"? Default = .true.
    23 # var_ecc=.true.
     22# Do you want the eccentricity to evolve when following "obl_ecc_lsp.asc"? Default = .true.
     23# evol_ecc=.true.
    2424
    25 # Do you want to vary the ls perihelie when following "obl_ecc_lsp.asc"? Default = .true.
    26 # var_lsp=.true.
     25# Do you want the ls perihelie to evolve when following "obl_ecc_lsp.asc"? Default = .true.
     26# evol_lsp=.true.
    2727
    2828# Time step length of the PEM in Martian years? Default = 1.
     
    3131#---------- Stopping criteria parameters ----------#
    3232# If evol_orbit=.false., maximal number of iterations if no stopping criterion is reached. Default=100000000.
    33 # nyears_max=100000000
     33# nmax_yr_run=100000000
    3434
    3535# Acceptance rate of sublimating H2O ice surface change. Default = 0.2
     
    6262
    6363# Value of the geothermal flux. Default = 0.
    64 # fluxgeo=0.
     64# flux_geo=0.
    6565
    6666# Depth at which the breccia layer begins. Default = 10 m
     
    8181
    8282# Threshold to consider the amount of H2O ice as an infinite reservoir. Default = 460. kg.m-2 (= 0.5 m)
    83 # h2oice_cap_threshold=460.
     83# threshold_h2oice_cap=460.
    8484
    8585# Do you want the H2O ice to flow along subslope inside a cell? Default = .true.
     
    9191#---------- Layering parameters ----------#
    9292# Do you want to run with the layering algorithm? Default = .false.
    93 # layering=.false.
     93# do_layering=.false.
    9494 
    9595# Value of the dust tendency. Default = 5.78e-2 kg.m-2.y-1
     
    103103
    104104# Some definitions for the physics, in file 'callphys.def'
    105 INCLUDEDEF=callphys.def
     105INCLUDEDEF=run_PCM.def
Note: See TracChangeset for help on using the changeset viewer.