From 0a7b6cd5bee37f8b443fd9e22e1fcbecbfc336d2 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Mon, 21 Jul 2025 17:06:40 +0200 Subject: [PATCH 01/23] save wip towards co2 coupling with openifs48r1 --- src/cpl_driver.F90 | 16 ++++++++++++++++ src/gen_forcing_couple.F90 | 13 +++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/cpl_driver.F90 b/src/cpl_driver.F90 index a26b842f2..edc8bf824 100644 --- a/src/cpl_driver.F90 +++ b/src/cpl_driver.F90 @@ -17,6 +17,8 @@ module cpl_driver use o_param, only : rad USE MOD_PARTIT use mpi + + implicit none save ! @@ -28,8 +30,15 @@ module cpl_driver ! (final number of fields depends now on lwiso switch and is set in subroutine cpl_oasis3mct_define_unstr) #if defined (__oifs) +#if defined(__recom) + integer :: nsend = 8 + integer :: nrecv = 16 +!With oifs, without recom: +#else integer :: nsend = 7 integer :: nrecv = 15 +#endif +!Without oifs #else integer :: nsend = 4 integer :: nrecv = 12 @@ -658,6 +667,9 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) cpl_send( 5)='sia_feom' ! 5. sea ice albedo [%-100] -> cpl_send( 6)='u_feom' ! 6. eastward surface velocity [m/s] -> cpl_send( 7)='v_feom' ! 7. northward surface velocity [m/s] -> +#if defined (__recom) + cpl_send( 8)='FCO2_feom'! 8. CO2 flux [kgCO2 m-2 s-1] -> +#endif #else cpl_send( 1)='sst_feom' ! 1. sea surface temperature [°C] -> cpl_send( 2)='sit_feom' ! 2. sea ice thickness [m] -> @@ -698,6 +710,10 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) cpl_recv(13) = 'calv_oce' cpl_recv(14) = 'u10w_oce' cpl_recv(15) = 'v10w_oce' +#if defined (__recom) + cpl_recv(16) = 'XCO2_oce' +#endif +!Not oifs #else cpl_recv(1) = 'taux_oce' cpl_recv(2) = 'tauy_oce' diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index 67ba51c43..0889b3de5 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -98,6 +98,9 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) #endif use gen_bulk use force_flux_consv_interface +#if defined (__recom) + use REcoM_locVar, only: x_co2atm, co2flux +#endif implicit none integer, intent(in) :: istep @@ -209,6 +212,10 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) do n=1,myDim_nod2D+eDim_nod2D exchange(n) = UVnode(2,1,n) end do +#if defined (__recom) + elseif (i.eq.8) then + exchange(n) = co2flux(:) ! CO2 concentration +#endif else print *, 'not installed yet or error in cpl_oasis3mct_send', mype #else ! oifs @@ -384,6 +391,12 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) if (action) then v_wind(:) = exchange(:) ! meridional wind end if +#if defined (__recom) + elseif (i.eq.16) then + if (action) then + x_co2atm(:) = exchange(:) ! Mass Mixing ratio CO2 + end if +#endif #else ! oifs elseif (i.eq.13) then if (action) then From b2f3de1f8547aabb49ad908ff474e70d82b61b17 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Tue, 22 Jul 2025 10:35:06 +0200 Subject: [PATCH 02/23] minor fixes to co2 coupling --- src/gen_forcing_couple.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index 0889b3de5..f0804b9d4 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -99,7 +99,7 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) use gen_bulk use force_flux_consv_interface #if defined (__recom) - use REcoM_locVar, only: x_co2atm, co2flux + use REcoM_locVar, only: LocAtmCO2, co2flux #endif implicit none @@ -214,7 +214,7 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) end do #if defined (__recom) elseif (i.eq.8) then - exchange(n) = co2flux(:) ! CO2 concentration + exchange(:) = co2flux(:) ! CO2 concentration #endif else print *, 'not installed yet or error in cpl_oasis3mct_send', mype @@ -394,7 +394,7 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) #if defined (__recom) elseif (i.eq.16) then if (action) then - x_co2atm(:) = exchange(:) ! Mass Mixing ratio CO2 + LocAtmCO2(1) = exchange(1) ! Atmospheric CO2 [uatm] end if #endif #else ! oifs From 5e8a5255aedb897cf2bcfb4ab0278036fc3288fc Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Tue, 22 Jul 2025 11:51:28 +0200 Subject: [PATCH 03/23] maybe the right fields now? --- src/gen_forcing_couple.F90 | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index f0804b9d4..84b94ae60 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -99,7 +99,7 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) use gen_bulk use force_flux_consv_interface #if defined (__recom) - use REcoM_locVar, only: LocAtmCO2, co2flux + use recom_modules, only: x_co2atm, GloCO2flux #endif implicit none @@ -214,7 +214,12 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) end do #if defined (__recom) elseif (i.eq.8) then - exchange(:) = co2flux(:) ! CO2 concentration + ! Convert CO2 flux from mmol/(m² day) to kg/(m² s) + ! GloCO2flux is in [mmol/m2/day], need [kg/m2/s] + ! Conversion: mmol/day -> mol/s -> kg/s + ! 1 mmol/day = 1e-3 mol / (24*3600 s) = 1.157e-8 mol/s + ! 1 mol CO2 = 0.04401 kg + exchange(:) = GloCO2flux(:) * 1.157e-8_WP * 0.04401_WP ! [kg m⁻² s⁻¹] #endif else print *, 'not installed yet or error in cpl_oasis3mct_send', mype @@ -394,7 +399,9 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) #if defined (__recom) elseif (i.eq.16) then if (action) then - LocAtmCO2(1) = exchange(1) ! Atmospheric CO2 [uatm] + ! Convert mass mixing ratio (kg/kg) to mole fraction (dimensionless) + ! MW_CO2/MW_air = 44.01/28.97 + x_co2atm(:) = exchange(:) * (28.97_WP/44.01_WP) ! [mole fraction] end if #endif #else ! oifs From ed7431d513561ce6328d5438571923169cb5d72b Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Tue, 22 Jul 2025 11:54:50 +0200 Subject: [PATCH 04/23] higher precision conversion --- src/gen_forcing_couple.F90 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index 84b94ae60..13b6c4e47 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -217,9 +217,9 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) ! Convert CO2 flux from mmol/(m² day) to kg/(m² s) ! GloCO2flux is in [mmol/m2/day], need [kg/m2/s] ! Conversion: mmol/day -> mol/s -> kg/s - ! 1 mmol/day = 1e-3 mol / (24*3600 s) = 1.157e-8 mol/s - ! 1 mol CO2 = 0.04401 kg - exchange(:) = GloCO2flux(:) * 1.157e-8_WP * 0.04401_WP ! [kg m⁻² s⁻¹] + ! 1 mmol/day = 1e-3 mol / (86400 s) = 1.157407407407407e-8 mol/s + ! 1 mol CO2 = 44.0095 g/mol = 0.0440095 kg/mol (NIST 2018) + exchange(:) = GloCO2flux(:) * 1.157407407407407e-8_WP * 0.0440095_WP ! [kg m⁻² s⁻¹] #endif else print *, 'not installed yet or error in cpl_oasis3mct_send', mype @@ -400,8 +400,9 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) elseif (i.eq.16) then if (action) then ! Convert mass mixing ratio (kg/kg) to mole fraction (dimensionless) - ! MW_CO2/MW_air = 44.01/28.97 - x_co2atm(:) = exchange(:) * (28.97_WP/44.01_WP) ! [mole fraction] + ! MW_CO2 = 44.0095 g/mol (NIST 2018) + ! MW_dry_air = 28.9647 g/mol (standard atmosphere composition) + x_co2atm(:) = exchange(:) * (28.9647_WP/44.0095_WP) ! [mole fraction] end if #endif #else ! oifs From 89bb9b2bd1543e167a9fbb0ba6be3d08abd63069 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 23 Jul 2025 10:38:34 +0200 Subject: [PATCH 05/23] fix git merge mistake --- config/bin_2p3z2d/namelist.recom | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config/bin_2p3z2d/namelist.recom b/config/bin_2p3z2d/namelist.recom index 07f2d3f46..5d18e9295 100644 --- a/config/bin_2p3z2d/namelist.recom +++ b/config/bin_2p3z2d/namelist.recom @@ -49,11 +49,7 @@ useErosion = .false. NitrogenSS = .false. ! When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) useAeolianN = .false. ! When set to true, aeolian nitrogen deposition is activated firstyearoffesomcycle = 1958 ! The first year of the actual physical forcing (e.g. JRA-55) used -<<<<<<< HEAD -lastyearoffesomcycle = 2023 ! Last year of the actual physical forcing used -======= lastyearoffesomcycle = 2024 ! Last year of the actual physical forcing used ->>>>>>> origin/fesom2.6_recom_tra_diags numofCO2cycles = 1 ! Number of cycles of the forcing planned currentCO2cycle = 1 ! Which CO2 cycle we are currently running DIC_PI = .true. From d06a657039c34c3a45950b1b5b36bf4e92abcb67 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 23 Jul 2025 14:15:57 +0200 Subject: [PATCH 06/23] get recom to compile on gnu by removing unused and unallocated vars --- src/int_recom/recom_init.F90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/int_recom/recom_init.F90 b/src/int_recom/recom_init.F90 index 3348b512b..361980ef1 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -97,7 +97,6 @@ subroutine recom_init(tracers, partit, mesh) allocate(decayBenthos ( benthos_num )) ! [1/day] Decay rate of detritus in the benthic layer allocate(PAR3D ( nl-1, node_size )) - GloFeDust = 0.d0 AtmFeInput = 0.d0 GloNDust = 0.d0 @@ -131,8 +130,6 @@ subroutine recom_init(tracers, partit, mesh) LocBenthos = 0.d0 decayBenthos = 0.d0 - wFluxPhy = 0.d0 - wFluxDia = 0.d0 PAR3D = 0.d0 ! pco2surf = 0.d0 From 663a67cfb271c495bc01559e9c40cb1f21ae9bce Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 23 Jul 2025 14:16:15 +0200 Subject: [PATCH 07/23] default recom namelists for AWI-ESM3 --- config/namelist.recom.2p3z2d | 355 +++++++++++++++++++++++++++++++ config/namelist.tra.recom.2p3z2d | 90 ++++++++ 2 files changed, 445 insertions(+) create mode 100644 config/namelist.recom.2p3z2d create mode 100644 config/namelist.tra.recom.2p3z2d diff --git a/config/namelist.recom.2p3z2d b/config/namelist.recom.2p3z2d new file mode 100644 index 000000000..5d18e9295 --- /dev/null +++ b/config/namelist.recom.2p3z2d @@ -0,0 +1,355 @@ +! This is the namelist file for recom + +&nam_rsbc +fe_data_source ='Albani' +nm_fe_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/DustClimMonthlyAlbani.nc' +nm_aen_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/AeolianNitrogenDep.nc' +nm_river_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/RiverineInput.nc' +nm_erosion_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/ErosionInput.nc' +nm_co2_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/MonthlyAtmCO2_gcb2023.nc' +/ + +&pavariables +use_REcoM =.true. +REcoM_restart =.true. + +bgc_num = 30 !22 !33 !24 !38 +diags3d_num = 28 ! Number of diagnostic 3d tracers to be saved +bgc_base_num = 22 ! standard tracers +VDet = 20.d0 ! Sinking velocity, constant through the water column and positive downwards +VDet_zoo2 = 200.d0 ! Sinking velocity, constant through the water column +VPhy = 0.d0 !!! If the number of sinking velocities are different from 3, code needs to be changed !!! +VDia = 0.d0 +VCocco = 0.d0 +allow_var_sinking = .true. +biostep = 1 ! Number of times biology should be stepped forward for each time step +REcoM_Geider_limiter = .false. ! Decides what routine should be used to calculate limiters in sms +REcoM_Grazing_Variable_Preference = .true. ! Decides if grazing should have preference for phyN or DiaN +Grazing_detritus = .true. +het_resp_noredfield = .true. ! Decides respiratation of copepod group +diatom_mucus = .true. ! Decides nutrient limitation effect on aggregation +O2dep_remin = .false. ! O2remin Add option for O2 dependency of organic matter remineralization +use_ballasting = .false. ! BALL +use_density_scaling = .false. ! BALL +use_viscosity_scaling = .false. ! BALL +OmegaC_diss = .false. ! DISS Use OmegaC from Mocsy to compute calcite dissolution (after Aumont et al. 2015 and Gehlen et al. 2007) +CO2lim = .false. ! CO2 dependence of growth and calcification +Diags = .true. +constant_CO2 = .true. +UseFeDust = .true. ! Turns dust input of iron off when set to.false. +UseDustClim = .true. +UseDustClimAlbani = .true. ! Use Albani dustclim field (If it is false Mahowald will be used) +use_photodamage = .true. ! use Alvarez et al (2018) for chlorophyll degradation +HetRespFlux_plus = .true. !MB More stable computation of zooplankton respiration fluxes adding a small number to HetN +REcoMDataPath = '/albedo/work/projects/MarESys/ogurses/input/mesh_CORE2_finaltopo_mean/' +restore_alkalinity = .true. +useRivers = .false. +useRivFe = .false. ! When set to true, riverine Fe source is activated +useErosion = .false. +NitrogenSS = .false. ! When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) +useAeolianN = .false. ! When set to true, aeolian nitrogen deposition is activated +firstyearoffesomcycle = 1958 ! The first year of the actual physical forcing (e.g. JRA-55) used +lastyearoffesomcycle = 2024 ! Last year of the actual physical forcing used +numofCO2cycles = 1 ! Number of cycles of the forcing planned +currentCO2cycle = 1 ! Which CO2 cycle we are currently running +DIC_PI = .true. +Nmocsy = 1 ! Length of the vector that is passed to mocsy (always one for recom) +recom_debug =.false. +ciso =.false. ! Main switch to enable/disable carbon isotopes (13|14C) +benthos_num = 4 ! number of benthic BGC tracers -> 8 if (ciso == .true.) otherwise -> 4 +use_MEDUSA = .false. ! Main switch for the sediment model MEDUSA +sedflx_num = 0 ! if 0: no file from MEDUSA is read but default sediment +bottflx_num = 4 ! if ciso&ciso_14: =8; if .not.ciso_14: =6; no ciso: =4 +use_atbox = .false. +add_loopback = .false. ! add loopback fluxes through rivers to the surface +lb_tscale = 1.0 ! /year: fraction of loopback fluxes yearly added to the surface +/ + +&pasinking +Vdet_a = 0.0288 ! [1/day] +Vcalc = 0.0144 ! [1/day] +/ + +&painitialization_N +cPhyN = 0.2d0 +cHetN = 0.2d0 +cZoo2N = 0.2d0 +/ + +&paArrhenius +recom_Tref = 288.15d0 ! [K] +C2K = 273.15d0 ! Conversion from degrees C to K +Ae = 4500.d0 ! [K] Slope of the linear part of the Arrhenius function +reminSi = 0.02d0 +k_o2_remin = 15.d0 ! NEW O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 +/ + +&palimiter_function +NMinSlope = 50.d0 +SiMinSlope = 1000.d0 +NCmin = 0.04d0 !0.05d0 +NCmin_d = 0.04d0 !0.05d0 +NCmin_c = 0.04d0 ! NEW +SiCmin = 0.04d0 +k_Fe = 0.04d0 +k_Fe_d = 0.12d0 +k_Fe_c = 0.09d0 ! NEW +k_si = 4.d0 +P_cm = 3.0d0 ! [1/day] Rate of C-specific photosynthesis +P_cm_d = 3.5d0 +P_cm_c = 2.8d0 ! NEW +/ + +&palight_calculations +k_w = 0.04d0 ! [1/m] Light attenuation coefficient +a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific attenuation coefficients +/ + +&paphotosynthesis +alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] +alfa_d = 0.19d0 ! An initial slope of the P-I curve +alfa_c = 0.10d0 ! NEW +parFrac = 0.43d0 +/ + +&paassimilation +V_cm_fact = 0.7d0 ! scaling factor for temperature dependent maximum of C-specific N-uptake +V_cm_fact_d = 0.7d0 +V_cm_fact_c = 0.7d0 ! NEW +NMaxSlope = 1000.d0 ! Max slope for limiting function +SiMaxSlope = 1000.d0 +NCmax = 0.2d0 ! [mmol N/mmol C] Maximum cell quota of nitrogen (N:C) +NCmax_d = 0.2d0 +NCmax_c = 0.15d0 ! NEW +SiCmax = 0.8d0 +NCuptakeRatio = 0.2d0 ! [mmol N/mmol C] Maximum uptake ratio of N:C +NCUptakeRatio_d = 0.2d0 +NCUptakeRatio_c = 0.2d0 ! NEW +SiCUptakeRatio = 0.2d0 +k_din = 0.55d0 ! [mmol N/m3] Half-saturation constant for nitrate uptake +k_din_d = 1.0d0 +k_din_c = 0.9d0 ! NEW +Chl2N_max = 3.15d0 ! [mg CHL/mmol N] Maximum CHL a : N ratio = 0.3 gCHL gN^-1 +Chl2N_max_d = 4.2d0 +Chl2N_max_c = 3.5d0 ! NEW +res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant +res_phy_d = 0.01d0 +res_phy_c = 0.01d0 ! NEW +biosynth = 2.33d0 ! [mmol C/mmol N] Cost of biosynthesis +biosynthSi = 0.d0 +/ + +&pairon_chem +totalligand = 1.d0 ! [mumol/m3] order 1. Total free ligand +ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron stability constant +/ + +&pazooplankton +graz_max = 0.31d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilonr = 0.09d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss +res_het = 0.028d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +Redfield = 6.625 ! [mmol C/mmol N] Redfield ratio of C:N = 106:16 +loss_het = 0.04d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) +pzDia = 1.0d0 !0.5d0 ! Maximum diatom preference +sDiaNsq = 0.d0 +pzPhy = 0.5d0 !0.25d0 !1.0d0 ! Maximum nano-phytoplankton preference (NEW: 3/12) +sPhyNsq = 0.d0 +pzCocco = 0.666d0 ! NEW (8/12) +sCoccoNsq = 0.d0 ! NEW +pzMicZoo = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference +sMicZooNsq = 0.d0 ! NEW 3Zoo +tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. +/ + +&pasecondzooplankton +graz_max2 = 0.1d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilon2 = 0.0144d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss +res_zoo2 = 0.0107d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +loss_zoo2 = 0.003d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) +fecal_rate_n = 0.104d0 ! [1/day] Temperature dependent N degradation of \ +fecal_rate_c = 0.236d0 +fecal_rate_n_mes = 0.25d0 ! NEW 3Zoo +fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo +pzDia2 = 1.5d0 !1.d0 ! Maximum diatom preference +sDiaNsq2 = 0.d0 +pzPhy2 = 0.5d0 ! Maximum diatom preference +sPhyNsq2 = 0.d0 +pzCocco2 = 0.5d0 ! NEW +sCoccoNsq2 = 0.d0 ! NEW +pzHet = 1.5d0 !0.8d0 ! Maximum diatom preference +sHetNsq = 0.d0 +pzMicZoo2 = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference +sMicZooNsq2 = 0.d0 +t1_zoo2 = 28145.d0 ! Krill temp. function constant1 +t2_zoo2 = 272.5d0 ! Krill temp. function constant2 +t3_zoo2 = 105234.d0 ! Krill temp. function constant3 +t4_zoo2 = 274.15d0 ! Krill temp. function constant3 +/ + +&pathirdzooplankton +graz_max3 = 0.46d0 ! NEW 3Zoo [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilon3 = 0.64d0 ! NEW 3Zoo [(mmol N)2 /m6] Half saturation constant for grazing loss +loss_miczoo = 0.01d0 ! NEW 3Zoo [1/day] Temperature dependent N degradation of extracellular organic N (EON) +res_miczoo = 0.01d0 ! NEW 3Zoo [1/day] Respiration by heterotrophs and mortality (loss to detritus) +pzDia3 = 0.5d0 ! NEW 3Zoo Maximum diatom preference +sDiaNsq3 = 0.d0 ! NEW 3Zoo +pzPhy3 = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference +sPhyNsq3 = 0.d0 ! NEW 3Zoo +pzCocco3 = 0.d0 ! NEW 3Zoo Maximum coccolithophore preference ! ATTENTION: This value needs to be tuned; I start with zero preference! +sCoccoNsq3 = 0.d0 ! NEW 3Zoo +/ + +&pagrazingdetritus +pzDet = 0.5d0 ! Maximum small detritus prefence by first zooplankton +sDetNsq = 0.d0 +pzDetZ2 = 0.5d0 ! Maximum large detritus preference by first zooplankton +sDetZ2Nsq = 0.d0 +pzDet2 = 0.5d0 ! Maximum small detritus prefence by second zooplankton +sDetNsq2 = 0.d0 +pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton +sDetZ2Nsq2 = 0.d0 +/ + +&paaggregation +agg_PD = 0.165d0 ! [m3/(mmol N * day)] Maximum aggregation loss parameter for DetN +agg_PP = 0.015d0 ! [m3/(mmol N * day)] Maximum aggregation loss parameter for PhyN and DiaN (plankton) +/ + +&padin_rho_N +rho_N = 0.11d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) (Remineralization of DON) +/ + +&padic_rho_C1 +rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradation of extracellular organic C (EOC) +/ + +&paphytoplankton_N +lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds +lossN_d = 0.05d0 +lossN_c = 0.05d0 ! NEW +/ + +&paphytoplankton_C +lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon +lossC_d = 0.10d0 +lossC_c = 0.10d0 ! NEW +/ + +&paphytoplankton_ChlA +deg_Chl = 0.25d0 !0.2d0 !0.25d0 ! [1/day] +deg_Chl_d = 0.15d0 !0.2d0 !0.15d0 +deg_Chl_c = 0.2d0 ! NEW (has been 0.5) +/ + +&padetritus_N +gfin = 0.3d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into zooplankton pool) +grazEff2 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into second zooplankton pool) +grazEff3 = 0.8d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) +reminN = 0.165d0 ! [1/day] Temperature dependent remineralisation rate of detritus +/ + +&padetritus_C +reminC = 0.15d0 ! [1/day] Temperature dependent remineralisation rate of detritus +rho_c2 = 0.1d0 ! [1/day] Temperature dependent C degradation of TEP-C +/ + +&paheterotrophs +lossN_z = 0.1d0 +lossC_z = 0.1d0 +/ + +&paseczooloss +lossN_z2 = 0.02d0 +lossC_z2 = 0.02d0 +/ + +&pathirdzooloss +lossN_z3 = 0.05d0 ! NEW 3Zoo +lossC_z3 = 0.05d0 ! NEW 3Zoo +/ + +&paco2lim ! NEW +Cunits = 976.5625 ! Conversion factor between [mol/m3] (model) and [umol/kg] (function): (1000 * 1000) / 1024 +a_co2_phy = 1.162e+00 ! [dimensionless] +a_co2_dia = 1.040e+00 ! [dimensionless] +a_co2_cocco = 1.109e+00 ! [dimensionless] +a_co2_calc = 1.102e+00 ! [dimensionless] +b_co2_phy = 4.888e+01 ! [mol/kg] +b_co2_dia = 2.890e+01 ! [mol/kg] +b_co2_cocco = 3.767e+01 ! [mol/kg] +b_co2_calc = 4.238e+01 ! [mol/kg] +c_co2_phy = 2.255e-01 ! [kg/mol] +c_co2_dia = 8.778e-01 ! [kg/mol] +c_co2_cocco = 3.912e-01 ! [kg/mol] +c_co2_calc = 7.079e-01 ! [kg/mol] +d_co2_phy = 1.023e+07 ! [kg/mol] +d_co2_dia = 2.640e+06 ! [kg/mol] +d_co2_cocco = 9.450e+06 ! [kg/mol] +d_co2_calc = 1.343e+07 ! [kg/mol] +/ + +&pairon +Fe2N = 0.033d0 ! Fe2C * 6.625 +Fe2N_benthos = 0.15d0 ! test, default was 0.14 Fe2C_benthos * 6.625 - will have to be tuned. [umol/m2/day] +kScavFe = 0.07d0 +dust_sol = 0.02d0 ! Dissolution of Dust for bioavaliable +RiverFeConc = 100 +/ + +&pacalc +calc_prod_ratio = 0.02 +calc_diss_guts = 0.0d0 +calc_diss_rate = 0.005714 ! 20.d0/3500.d0 +calc_diss_rate2 = 0.005714d0 +calc_diss_omegac = 0.197d0 ! NEW DISS Value from Aumont et al. 2015, will be used with OmegaC_diss flag +calc_diss_exp = 1.d0 ! NEW DISS Exponent in the dissolution rate of calcite, will be used with OmegaC_diss flag +/ + +&pabenthos_decay_rate +decayRateBenN = 0.005d0 +decayRateBenC = 0.005d0 +decayRateBenSi = 0.005d0 +q_NC_Denit = 0.86d0 ! N:C quota of the denitrification process +/ + +&paco2_flux_param +permil = 0.000000976 ! 1.e-3/1024.5d0 ! Converting DIC from [mmol/m3] to [mol/kg] +permeg = 1.e-6 ! [atm/uatm] Changes units from uatm to atm +!X1 = exp(-5.d0*log(10.d0)) ! Lowest ph-value = 7.7 (phlo) +!X2 = exp(-9.d0*log(10.d0)) ! Highest ph-value = 9.5 (phhi) +Xacc = 1.e-12 ! Accuracy for ph-iteration (phacc) +CO2_for_spinup = 278.d0 ! [uatm] Atmospheric partial pressure of CO2 +/ + +&paalkalinity_restoring +surf_relax_Alk = 3.2e-07 !10.d0/31536000.d0 +/ + +&paballasting +rho_POC = 1033.d0 ! kg m-3; density of POC (see Table 1 in Cram et al., 2018) +rho_PON = 1033.d0 ! kg m-3; density of PON (see Table 1 in Cram et al., 2018) +rho_CaCO3 = 2830.d0 ! kg m-3; density of CaCO3 (see Table 1 in Cram et al., 2018) +rho_opal = 2090.d0 ! kg m-3; density of Opal (see Table 1 in Cram et al., 2018) +rho_ref_part = 1230.d0 ! kg m-3; reference particle density (see Cram et al., 2018) +rho_ref_water = 1027.d0 ! kg m-3; reference seawater density (see Cram et al., 2018) +visc_ref_water = 0.00158d0 ! kg m-1 s-1; reference seawater viscosity, at Temp=4 degC (see Cram et al., 2018) +w_ref1 = 10.d0 ! m s-1; reference sinking velocity of small detritus +w_ref2 = 200.d0 ! m s-1; reference sinking velocity of large detritus +depth_scaling1 = 0.015d0 ! s-1; factor to increase sinking speed of det1 with depth, set to 0 if not wanted +depth_scaling2 = 0.d0 ! s-1; factor to increase sinking speed of det2 with depth, set to 0 if not wanted +max_sinking_velocity = 250.d0 ! d-1; for numerical stability, set a maximum possible sinking velocity here (applies to both detritus classes) +/ + +&paciso +ciso_init = .false. ! initial fractionation of bulk organic matter +ciso_14 = .false. ! include inorganic radiocarbon +ciso_organic_14 = .false. ! include organic radiocarbon +lambda_14 = 3.8561e-12 ! corresponding to 1 year = 365.00 days +delta_CO2_13 = -6.61 ! atmospheric d13C (permil), global-mean value +big_delta_CO2_14(1) = 0. ! atmospheric D14C (permil), northern hemisphere polewards of 30°N +big_delta_CO2_14(2) = 0. ! atmospheric D14C (permil), (sub) tropical zone 30°N - 30°S +big_delta_CO2_14(3) = 0. ! atmospheric D14C (permil), southern hemisphere polewards of 30°S +atbox_spinup = .false. +cosmic_14_init = 2.0 +/ + diff --git a/config/namelist.tra.recom.2p3z2d b/config/namelist.tra.recom.2p3z2d new file mode 100644 index 000000000..d1733bb91 --- /dev/null +++ b/config/namelist.tra.recom.2p3z2d @@ -0,0 +1,90 @@ +&tracer_listsize +num_tracers=100 !number of tracers to allocate. shallbe large or equal to the number of streams in &nml_list +/ + +&tracer_list +nml_tracer_list = +1 , 'MFCT', 'QR4C', 'FCT ', 1., 1., +2 , 'MFCT', 'QR4C', 'FCT ', 1., 1., +1001, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1002, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1003, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1004, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1005, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1006, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1007, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1008, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1009, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1010, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1011, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1012, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1013, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1014, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1015, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1016, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1017, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1018, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1019, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1020, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1021, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1022, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1023, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1024, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1025, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1026, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1027, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1028, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1029, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1030, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1031, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1032, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1033, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!101, 'UPW1', 'UPW1', 'NON ', 0., 0. +/ + +&tracer_init3d ! initial conditions for tracers +n_ic3d = 8 ! number of tracers to initialize +idlist = 1019, 1022, 1018, 1003, 1002, 1001, 2, 1 ! their IDs (0 is temperature, 1 is salinity, etc.). The reading order is defined here! +filelist = 'fe_pisces_opa_eq_init_3D_changed_name.nc', 'woa18_all_o00_01_mmol_fesom2.nc', 'woa13_all_i00_01_fesom2.nc', 'GLODAPv2.2016b.TAlk_fesom2_mmol_fix_z_Fillvalue.nc', 'GLODAPv2.2016b.TCO2_fesom2_mmol_fix_z_Fillvalue.nc', 'woa13_all_n00_01_fesom2.nc', 'phc3.0_winter.nc', 'phc3.0_winter.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist +varlist = 'Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp' ! variables to read from specified files +t_insitu = .true. ! if T is insitu it will be converted to potential after reading it +/ + +&tracer_init2d ! initial conditions for 2D tracers (sea ice) +n_ic2d = 3 ! number of tracers to initialize +idlist = 1, 2, 3 ! their IDs (0 is a_ice, 1 is m_ice, 3 m_snow). The reading order is defined here! +filelist = 'a_ice.nc', 'm_ice.nc', 'm_snow.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist +varlist = 'a_ice', 'm_ice', 'm_snow' ! variables to read from specified files +ini_ice_from_file=.false. +/ + +&tracer_general +! bharmonic diffusion for tracers. We recommend to use this option in very high resolution runs (Redi is generally off there). +smooth_bh_tra =.false. ! use biharmonic diffusion (filter implementation) for tracers +gamma0_tra = 0.0005 ! gammaX_tra are analogous to those in the dynamical part +gamma1_tra = 0.0125 +gamma2_tra = 0. +i_vert_diff =.true. +/ + +&tracer_phys +use_momix = .true. ! switch on/off !Monin-Obukhov -> TB04 mixing +momix_lat = -50.0 ! latitidinal treshhold for TB04, =90 --> global +momix_kv = 0.01 ! PP/KPP, mixing coefficient within MO length +use_instabmix = .true. ! enhance convection in case of instable stratification +instabmix_kv = 0.1 +use_windmix = .false. ! enhance mixing trough wind only for PP mixing (for stability) +windmix_kv = 1.e-3 +windmix_nl = 2 +diff_sh_limit=5.0e-3 ! for KPP, max diff due to shear instability +Kv0_const=.true. +double_diffusion=.false. ! for KPP,dd switch +K_ver=1.0e-5 +K_hor=3000. +surf_relax_T=0.0 +surf_relax_S=1.929e-06 ! 50m/300days 6.43e-07! m/s 10./(180.*86400.) +balance_salt_water =.true. ! balance virtual-salt or freshwater flux or not +clim_relax=0.0 ! 1/s, geometrical information has to be supplied +ref_sss_local=.true. +ref_sss=34. +/ From 2372cc6175c698794c3122ea4b620170f93cb542 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 23 Jul 2025 14:16:44 +0200 Subject: [PATCH 08/23] switch to sea ice masked co2 flux --- src/gen_forcing_couple.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index 13b6c4e47..98a84a79e 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -99,7 +99,7 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) use gen_bulk use force_flux_consv_interface #if defined (__recom) - use recom_modules, only: x_co2atm, GloCO2flux + use REcoM_GloVar, only: x_co2atm, GloCO2flux_seaicemask #endif implicit none @@ -215,11 +215,11 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) #if defined (__recom) elseif (i.eq.8) then ! Convert CO2 flux from mmol/(m² day) to kg/(m² s) - ! GloCO2flux is in [mmol/m2/day], need [kg/m2/s] + ! GloCO2flux_seaicemask is in [mmol/m2/day], need [kg/m2/s] ! Conversion: mmol/day -> mol/s -> kg/s ! 1 mmol/day = 1e-3 mol / (86400 s) = 1.157407407407407e-8 mol/s ! 1 mol CO2 = 44.0095 g/mol = 0.0440095 kg/mol (NIST 2018) - exchange(:) = GloCO2flux(:) * 1.157407407407407e-8_WP * 0.0440095_WP ! [kg m⁻² s⁻¹] + exchange(:) = GloCO2flux_seaicemask(:) * 1.157407407407407e-8_WP * 0.0440095_WP ! [kg m⁻² s⁻¹] #endif else print *, 'not installed yet or error in cpl_oasis3mct_send', mype From 398831e7516d45bbcf736d11a0b6864e4c593f31 Mon Sep 17 00:00:00 2001 From: chrisdane Date: Wed, 23 Jul 2025 14:28:23 +0200 Subject: [PATCH 09/23] add xco2 from oifs --- src/int_recom/recom_init.F90 | 7 ++++++- src/int_recom/recom_main.F90 | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/int_recom/recom_init.F90 b/src/int_recom/recom_init.F90 index 361980ef1..fef4b667e 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -96,7 +96,7 @@ subroutine recom_init(tracers, partit, mesh) allocate(LocBenthos ( benthos_num )) allocate(decayBenthos ( benthos_num )) ! [1/day] Decay rate of detritus in the benthic layer allocate(PAR3D ( nl-1, node_size )) - + GloFeDust = 0.d0 AtmFeInput = 0.d0 GloNDust = 0.d0 @@ -131,6 +131,11 @@ subroutine recom_init(tracers, partit, mesh) LocBenthos = 0.d0 decayBenthos = 0.d0 PAR3D = 0.d0 + + if (use_atbox) then + allocate(x_co2atm ( node_size )) + x_co2atm = 0.d0 + endif ! pco2surf = 0.d0 ! dflux = 0.d0 diff --git a/src/int_recom/recom_main.F90 b/src/int_recom/recom_main.F90 index 452cb1b6d..1a3803e3e 100755 --- a/src/int_recom/recom_main.F90 +++ b/src/int_recom/recom_main.F90 @@ -208,6 +208,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) LocAtmCO2_14 = AtmCO2_14(lat_zone(lat_val), month) end if end if + LocAtmCO2 = x_co2atm(n) ! from oifs end if ! use_atbox if (ciso) then From e885e92b3080937983045309a5c916a7dafcc274 Mon Sep 17 00:00:00 2001 From: chrisdane Date: Wed, 23 Jul 2025 14:36:01 +0200 Subject: [PATCH 10/23] corrected if atmbox case --- src/int_recom/recom_init.F90 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/int_recom/recom_init.F90 b/src/int_recom/recom_init.F90 index fef4b667e..336247eb2 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -133,9 +133,12 @@ subroutine recom_init(tracers, partit, mesh) PAR3D = 0.d0 if (use_atbox) then + allocate(x_co2atm ( 1 )) + else allocate(x_co2atm ( node_size )) - x_co2atm = 0.d0 endif + x_co2atm = 0.d0 + ! pco2surf = 0.d0 ! dflux = 0.d0 From 038e78170aac903fa169d998d26b8c9ae12c35e1 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 6 Aug 2025 09:05:30 +0200 Subject: [PATCH 11/23] change dim of wf to match number of tracers depending on recom setting --- src/int_recom/recom_extra.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/int_recom/recom_extra.F90 b/src/int_recom/recom_extra.F90 index 441fbd724..363438443 100644 --- a/src/int_recom/recom_extra.F90 +++ b/src/int_recom/recom_extra.F90 @@ -23,7 +23,7 @@ subroutine Depth_calculations(n, nn, wf, zf, thick, recipthick, partit, mesh) integer , intent(in) :: n ! Current node ! Output arrays - real(kind=8), dimension(mesh%nl,5), intent(out) :: wf ! [m/day] Flux velocities at the border of the control volumes + real(kind=8), dimension(mesh%nl,6), intent(out) :: wf ! [m/day] Flux velocities at the border of the control volumes real(kind=8), dimension(mesh%nl), intent(out) :: zf ! [m] Depth of vertical fluxes real(kind=8), dimension(mesh%nl-1), intent(out) :: thick ! [m] Distance between two nodes = layer thickness real(kind=8), dimension(mesh%nl-1), intent(out) :: recipthick ! [1/m] Reciprocal thickness From b5c6725fe0842676f20da0b96a91c8d42cf9a1ef Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 6 Aug 2025 14:42:26 +0200 Subject: [PATCH 12/23] add xco2atm output option --- config/namelist.io.recom.2p3z2d | 95 +++++++++++++++++++++++++++++++++ src/io_meandata.F90 | 5 ++ 2 files changed, 100 insertions(+) create mode 100644 config/namelist.io.recom.2p3z2d diff --git a/config/namelist.io.recom.2p3z2d b/config/namelist.io.recom.2p3z2d new file mode 100644 index 000000000..8381d77c2 --- /dev/null +++ b/config/namelist.io.recom.2p3z2d @@ -0,0 +1,95 @@ +&diag_list +ldiag_solver =.false. +lcurt_stress_surf=.false. +ldiag_curl_vel3 =.false. +ldiag_Ri =.false. +ldiag_turbflux =.false. +ldiag_salt3D =.false. +ldiag_dMOC =.false. +ldiag_DVD =.false. +ldiag_forc =.false. +ldiag_extflds =.false. +ldiag_destine =.false. +ldiag_trflx =.false. +ldiag_uvw_sqr =.false. +ldiag_trgrd_xyz =.false. +/ + +&nml_general +io_listsize =150 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list +vec_autorotate =.false. +compression_level = 1 +/ + +! for sea ice related variables use_ice should be true, otherewise there will be no output +! for 'curl_surf' to work lcurt_stress_surf must be .true. otherwise no output +! for 'fer_C', 'bolus_u', 'bolus_v', 'bolus_w', 'fer_K' to work Fer_GM must be .true. otherwise no output +! 'otracers' - all other tracers if applicable +! for 'dMOC' to work ldiag_dMOC must be .true. otherwise no output +&nml_list +io_list = 'sst ',1, 'm', 4, + 'sss ',1, 'm', 4, + 'ssh ',1, 'm', 4, + 'uice ',1, 'm', 4, + 'vice ',1, 'm', 4, + 'a_ice ',1, 'm', 4, + 'm_ice ',1, 'm', 4, + 'm_snow ',1, 'm', 4, + 'MLD1 ',1, 'm', 4, + 'MLD2 ',1, 'm', 4, + 'MLD3 ',1, 'm', 4, + 'tx_sur ',1, 'm', 4, + 'ty_sur ',1, 'm', 4, + 'prec ',1, 'm', 4, + 'snow ',1, 'm', 4, + 'evap ',1, 'm', 4, + 'runoff ',1, 'm', 4, + 'temp ',1, 'm', 4, + 'salt ',1, 'm', 8, + 'otracers ',1, 'm', 4, + 'N2 ',1, 'y', 4, + 'Kv ',1, 'y', 4, + 'u ',1, 'm', 4, + 'v ',1, 'm', 4, + 'unod ',1, 'm', 4, + 'vnod ',1, 'm', 4, + 'w ',1, 'm', 4, + 'Av ',1, 'y', 4, + 'bolus_u ',1, 'y', 4, + 'bolus_v ',1, 'y', 4, + 'bolus_w ',1, 'y', 4, + 'fw ',1, 'm', 4, + 'fh ',1, 'm', 4, + 'dpCO2s ',1, 'm', 4, + 'pCO2s ',1, 'm', 4, + 'CO2f ',1, 'm', 4, + 'xCO2atm ',4, 's', 4, + 'Hp ',1, 'm', 4, + 'aFe ',1, 'm', 4, + 'aN ',1, 'm', 4, + 'denb ',1, 'm', 4, + 'benN ',1, 'm', 4, + 'benC ',1, 'm', 4, + 'benSi ',1, 'm', 4, + 'benCalc ',1, 'm', 4, + 'Chldegd ',1, 'm', 4, + 'Chldegn ',1, 'm', 4, + 'NNAd ',1, 'm', 4, + 'NNAn ',1, 'm', 4, + 'GPPd ',1, 'm', 4, + 'GPPn ',1, 'm', 4, + 'NPPd ',1, 'm', 4, + 'NPPn ',1, 'm', 4, + 'PAR ',1, 'm', 4, + 'respmeso',1, 'm', 4, + 'respmacro',1, 'm', 4, + 'respmicro',1, 'm', 4, + 'calcdiss',1, 'm', 4, + 'calcif',1, 'm', 4, + 'aggn',1, 'm', 4, + 'aggd',1, 'm', 4, + 'docexn',1, 'm', 4, + 'docexd',1, 'm', 4, + 'respn',1, 'm', 4, + 'respd',1, 'm', 4, +/ diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 57492a64c..7efa667d6 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -504,6 +504,11 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) ! output RECOM 2D #if defined(__recom) +CASE ('xCO2atm ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'xCO2atm', 'atmospheric CO2 mass mixing ratio', 'mole fraction', x_co2atm(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + CASE ('dpCO2s ') if (use_REcoM) then call def_stream(nod2D, myDim_nod2D, 'dpCO2s', 'Difference of oceanic pCO2 minus atmospheric pCO2', 'uatm', GlodPCO2surf(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) From 6e19194eafc8a326c6bf2481e56db39123ce0f87 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 6 Aug 2025 14:43:15 +0200 Subject: [PATCH 13/23] multiply xco2 by 1e6 to go from mole fraction to ppm --- src/gen_forcing_couple.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index 98a84a79e..d8fce6af7 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -402,7 +402,7 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) ! Convert mass mixing ratio (kg/kg) to mole fraction (dimensionless) ! MW_CO2 = 44.0095 g/mol (NIST 2018) ! MW_dry_air = 28.9647 g/mol (standard atmosphere composition) - x_co2atm(:) = exchange(:) * (28.9647_WP/44.0095_WP) ! [mole fraction] + x_co2atm(:) = exchange(:) * ((28.9647_WP/44.0095_WP)*1e6_WP) ! [mole fraction] end if #endif #else ! oifs From 20e79e739e3b3c68e4e0b0670d972b62607fa8c4 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 6 Aug 2025 17:25:47 +0200 Subject: [PATCH 14/23] co2 correct flux unit conversion --- src/gen_forcing_couple.F90 | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index d8fce6af7..33c4e1d20 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -214,12 +214,10 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) end do #if defined (__recom) elseif (i.eq.8) then - ! Convert CO2 flux from mmol/(m² day) to kg/(m² s) - ! GloCO2flux_seaicemask is in [mmol/m2/day], need [kg/m2/s] - ! Conversion: mmol/day -> mol/s -> kg/s - ! 1 mmol/day = 1e-3 mol / (86400 s) = 1.157407407407407e-8 mol/s + ! GloCO2flux_seaicemask is in [mmol/m2/s], need [kg/m2/s] + ! Conversion: 1.0e-3_WP -> mol/s -> kg/s ! 1 mol CO2 = 44.0095 g/mol = 0.0440095 kg/mol (NIST 2018) - exchange(:) = GloCO2flux_seaicemask(:) * 1.157407407407407e-8_WP * 0.0440095_WP ! [kg m⁻² s⁻¹] + exchange(:) = GloCO2flux_seaicemask(:) * 1.0e-3_WP * 0.0440095_WP ! [kg m⁻² s⁻¹] #endif else print *, 'not installed yet or error in cpl_oasis3mct_send', mype From f8224a83686fab8ec1d0d4e86c2016010f8c0e22 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Tue, 2 Sep 2025 09:55:02 +0200 Subject: [PATCH 15/23] merge main into branch --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bab416317..c2b7b067a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -250,7 +250,7 @@ if(OPENMP_REPRODUCIBLE) endif() if(${RECOM_COUPLED}) - target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __3Zoo2Det __coccos)# __usetp) + target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __3Zoo2Det)# __usetp) endif() if(${CISO_COUPLED}) From 2fb0cb55b554ed6702b6c786a64a043292477e04 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Tue, 18 Nov 2025 15:49:22 +0100 Subject: [PATCH 16/23] saving wip, recomp + cavity runs, judiths suggestions not included yet --- src/fesom_module.F90 | 1 + src/gen_ic3d.F90 | 28 ++++++++++++++++++--- src/int_recom/recom_forcing.F90 | 44 +++++++++++++++++++++++++++------ src/int_recom/recom_main.F90 | 7 ++++-- src/oce_ale.F90 | 18 ++++++++++++++ 5 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 50e379133..7ecc72a3c 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -38,6 +38,7 @@ module fesom_main_storage_module use iceberg_step use iceberg_ocean_coupling use Toy_Channel_Soufflet, only: compute_zonal_mean + use ieee_arithmetic ! Define icepack module #if defined (__icepack) diff --git a/src/gen_ic3d.F90 b/src/gen_ic3d.F90 index 4af214cd6..732777d0d 100644 --- a/src/gen_ic3d.F90 +++ b/src/gen_ic3d.F90 @@ -412,7 +412,9 @@ SUBROUTINE getcoeffld(tracers, partit, mesh) if (x<0.) x=x+360. if (x>360.) x=x-360. if ( min(i,j)>0 ) then - if (any(ncdata(i:ip1,j:jp1,1) > dummy*0.99_WP)) cycle + ! CAVITY FIX: Check for NaN in climatology data which can occur near cavity regions + if (any(ncdata(i:ip1,j:jp1,1) > dummy*0.99_WP) .or. & + any(.not. ieee_is_finite(ncdata(i:ip1,j:jp1,1)))) cycle x1 = nc_lon(i) x2 = nc_lon(ip1) y1 = nc_lat(j) @@ -423,7 +425,9 @@ SUBROUTINE getcoeffld(tracers, partit, mesh) data1d(:) = ( ncdata(i,j,:) * (x2-x)*(y2-y) + ncdata(ip1,j,:) * (x-x1)*(y2-y) + & ncdata(i,jp1,:) * (x2-x)*(y-y1) + ncdata(ip1, jp1, :) * (x-x1)*(y-y1) ) / denom where (ncdata(i,j,:) > 0.99_WP*dummy .OR. ncdata(ip1,j,:) > 0.99_WP*dummy .OR. & - ncdata(i,jp1,:) > 0.99_WP*dummy .OR. ncdata(ip1,jp1,:) > 0.99_WP*dummy) + ncdata(i,jp1,:) > 0.99_WP*dummy .OR. ncdata(ip1,jp1,:) > 0.99_WP*dummy .OR. & + .not. ieee_is_finite(ncdata(i,j,:)) .OR. .not. ieee_is_finite(ncdata(ip1,j,:)) .OR. & + .not. ieee_is_finite(ncdata(i,jp1,:)) .OR. .not. ieee_is_finite(ncdata(ip1,jp1,:))) data1d(:)=dummy end where @@ -481,6 +485,14 @@ SUBROUTINE getcoeffld(tracers, partit, mesh) end if enddo end if ! --> if (use_cavity) then + else + ! CAVITY FIX: If bilinear interpolation fails (missing data), set fallback values + ! This prevents NaN tracers when climatology has dummy values near cavity regions + do k= ul1, nl1 + if (.not. ieee_is_finite(tracers%data(current_tracer)%values(k,ii))) then + tracers%data(current_tracer)%values(k,ii) = 0.0_WP + endif + enddo end if ! --> if ( min(i,j)>0 ) then end do !ii if (mype==0) then @@ -497,6 +509,7 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) !! ** Purpose : read 3D initial conditions for tracers from netcdf and interpolate on model grid !!---------------------------------------------------------------------- USE insitu2pot_interface + USE ieee_arithmetic IMPLICIT NONE type(t_mesh), intent(in), target :: mesh type(t_partit), intent(inout), target :: partit @@ -521,7 +534,11 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) ! get first coeficients for time inerpolation on model grid for all datas call getcoeffld(tracers, partit, mesh) call nc_end ! deallocate arrqays associated with netcdf file - call extrap_nod(tracers%data(current_tracer)%values(:,:), partit, mesh) + ! CAVITY FIX: Initialize to 0.0 before extrapolation to prevent NaN + where (.not. ieee_is_finite(tracers%data(current_tracer)%values(:,:))) + tracers%data(current_tracer)%values(:,:) = 0.0_WP + end where + call extrap_nod(tracers%data(current_tracer)%values(:,:), partit, mesh) exit elseif (current_tracer==tracers%num_tracers) then if (partit%mype==0) write(*,*) "idlist contains tracer which is not listed in tracer_id!" @@ -534,6 +551,11 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) DEALLOCATE(bilin_indx_i, bilin_indx_j) do current_tracer=1, tracers%num_tracers + !_________________________________________________________________________ + ! CAVITY FIX: Clean up any remaining NaN values before dummy check + where (.not. ieee_is_finite(tracers%data(current_tracer)%values(:,:))) + tracers%data(current_tracer)%values(:,:) = 0.0_WP + end where !_________________________________________________________________________ ! set remaining dummy values from bottom topography to 0.0_WP where (tracers%data(current_tracer)%values > 0.9_WP*dummy) diff --git a/src/int_recom/recom_forcing.F90 b/src/int_recom/recom_forcing.F90 index 59bef0116..52d434e01 100644 --- a/src/int_recom/recom_forcing.F90 +++ b/src/int_recom/recom_forcing.F90 @@ -185,15 +185,38 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali stop endif - call flxco2(co2flux, co2ex, dpco2surf, & - ph, pco2surf, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, K0, & - REcoM_T, REcoM_S, REcoM_Alk, REcoM_DIC, REcoM_Si, REcoM_Phos, kw660, LocAtmCO2, Patm, thick(One), Nmocsy, Lond,Latd, & - optCON='mol/m3',optT='Tpot ',optP='m ',optB='u74',optK1K2='l ',optKf='dg',optGAS='Pinsitu',optS='Sprc') + !!---- Skip CO2 flux calculation in ice shelf cavities (ulevels_nod2d > 1) + !!---- Cavity nodes have uninitialized biogeochemical tracers + !!---- NOTE: ulevels_nod2d is already indexed by local node numbers + if (mesh%ulevels_nod2d(n) > 1) then + !! Set CO2 flux to zero in cavity regions + co2flux(1) = 0.0d0 + co2ex(1) = 0.0d0 + dpco2surf(1) = 0.0d0 + ph(1) = 8.0d0 + pco2surf(1) = 0.0d0 + fco2(1) = 0.0d0 + co2(1) = 0.0d0 + hco3(1) = 0.0d0 + co3(1) = 0.0d0 + OmegaA(1) = 0.0d0 + OmegaC(1) = 0.0d0 + BetaD(1) = 0.0d0 + rhoSW(1) = 1027.0d0 + else + !! Calculate CO2 flux for non-cavity nodes + call flxco2(co2flux, co2ex, dpco2surf, & + ph, pco2surf, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, K0, & + REcoM_T, REcoM_S, REcoM_Alk, REcoM_DIC, REcoM_Si, REcoM_Phos, kw660, LocAtmCO2, Patm, thick(One), Nmocsy, Lond,Latd, & + optCON='mol/m3',optT='Tpot ',optP='m ',optB='u74',optK1K2='l ',optKf='dg',optGAS='Pinsitu',optS='Sprc') + endif ! changed optK1K2='l ' to 'm10' if((co2flux(1)>1.e10) .or. (co2flux(1)<-1.e10)) then ! co2flux(1)=0.0 print*, 'ERROR: co2 flux !' + print*, 'ulevels_nod2d(n): ',mesh%ulevels_nod2d(n) + print*, 'node n (local): ',n print*, 'pco2surf: ',pco2surf print*, 'co2: ',co2 print*, 'rhoSW: ', rhoSW @@ -230,9 +253,16 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali ppo = Loc_slp/Pa2atm !1 !slp divided by 1 atm REcoM_O2 = max(tiny*1e-3,state(one,ioxy)*1e-3) ! convert from mmol/m3 to mol/m3 for mocsy - call o2flux(REcoM_T, REcoM_S, kw660, ppo, REcoM_O2, Nmocsy, o2ex) - oflux = o2ex * 1.e3 *SecondsPerDay !* (1.d0 - Loc_ice_conc) [mmol/m2/d] - o2flux_seaicemask = o2ex * 1.e3 ! back to mmol here [mmol/m2/s] + !!---- Skip O2 flux calculation in ice shelf cavities + if (mesh%ulevels_nod2d(n) > 1) then + o2ex(1) = 0.0d0 + oflux = 0.0d0 + o2flux_seaicemask = 0.0d0 + else + call o2flux(REcoM_T, REcoM_S, kw660, ppo, REcoM_O2, Nmocsy, o2ex) + oflux = o2ex * 1.e3 *SecondsPerDay !* (1.d0 - Loc_ice_conc) [mmol/m2/d] + o2flux_seaicemask = o2ex * 1.e3 ! back to mmol here [mmol/m2/s] + endif ! Source-Minus-Sinks diff --git a/src/int_recom/recom_main.F90 b/src/int_recom/recom_main.F90 index 1a3803e3e..6b72c9c2d 100755 --- a/src/int_recom/recom_main.F90 +++ b/src/int_recom/recom_main.F90 @@ -57,6 +57,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) use o_PARAM use MOD_PARTIT use MOD_PARSUP + use ieee_arithmetic use recom_declarations use bio_fluxes_interface @@ -153,7 +154,8 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) !********************************* LOOP STARTS ***************************************** do n=1, myDim_nod2D ! needs exchange_nod in the end -! if (ulevels_nod2D(n)>1) cycle + !!---- Skip cavity nodes - REcoM not supported in ice shelf cavities + if (ulevels_nod2D(n)>1) cycle ! nzmin = ulevels_nod2D(n) !!---- Number of vertical layers @@ -636,7 +638,8 @@ subroutine bio_fluxes(tracers, partit, mesh) use recom_locvar use recom_glovar use recom_config - + use o_PARAM + use ieee_arithmetic use mod_mesh use MOD_PARTIT use MOD_PARSUP diff --git a/src/oce_ale.F90 b/src/oce_ale.F90 index fe0051854..96517248d 100644 --- a/src/oce_ale.F90 +++ b/src/oce_ale.F90 @@ -3339,6 +3339,7 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) use solve_tracers_ale_interface use write_step_info_interface use check_blowup_interface + use ieee_arithmetic use fer_solve_interface use impl_vert_visc_ale_vtransp_interface #if defined (FESOM_PROFILING) @@ -3356,6 +3357,7 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) real(kind=8) :: t0,t1, t2, t30, t3, t4, t5, t6, t7, t8, t9, t10, loc, glo integer :: node integer :: nz, elem, nzmin, nzmax !for KE diagnostic + integer :: tr_num ! for cavity NaN cleanup !___________________________________________________________________________ ! pointer on necessary derived types real(kind=WP), dimension(:), pointer :: eta_n @@ -3792,6 +3794,22 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) call fesom_profiler_end("oce_tracer_solve") call fesom_profiler_start("oce_thickness_update") #endif +#if defined (__recom) + ! CAVITY FIX: Clean up NaN created by tracer advection/diffusion at cavity nodes + ! Cavity nodes can create NaN during numerical operations with zero/near-zero thickness + if (use_cavity) then + do node=1, partit%myDim_nod2D+partit%eDim_nod2D + if (mesh%ulevels_nod2D(node) > 1) then + ! Clean NaN in ALL levels for cavity nodes (not just cavity layers) + do tr_num=1, tracers%num_tracers + where (.not. ieee_is_finite(tracers%data(tr_num)%values(:, node))) + tracers%data(tr_num)%values(:, node) = 0.0_WP + end where + enddo + endif + enddo + endif +#endif !___________________________________________________________________________ ! Update hnode=hnode_new, helem From b557ca854c193465fbf7468f8db577c359d57f5b Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 3 Jun 2026 16:23:21 +0200 Subject: [PATCH 17/23] mask netcdf output by wet-cell topography instead of value==0 PR #799 set any accumulated output value below 1e-30 to _FillValue. That also masks legitimate ocean zeros: ice-free sea-ice concentration (a_ice and all other 2D ice variables) and vanishing 3D fields such as IDEMIX energy were written as NaN instead of 0, contrary to the CMIP/CMOR convention. The masking was applied uniformly to 2D and 3D fields. Replace the value-based test with a proper wet-cell mask derived from the mesh level arrays (ulevels/nlevels for elements, ulevels_nod2D/ nlevels_nod2D for nodes). Only cells above a cavity or below the bottom topography are written as _FillValue; every wet cell keeps its averaged value, including a genuine zero. 2D fields and non-spatial vertical axes (density / ice classes) are never masked. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/io_meandata.F90 | 76 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index fba00c3d8..d7809e000 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -1977,7 +1977,46 @@ subroutine update_means ! ! !_______________________________________________________________________________ -! main output routine called at the end of each time step --> here is decided if +! Return the vertically valid (wet) index range [ul_loc, kmax_loc] for column j of +! the given output stream. Cells with level index outside this range are below the +! bottom topography or above a cavity and are the only ones written as _FillValue. +! For 2D fields (nlev_loc==1) and non-spatial vertical axes (density / ice classes) +! the whole column is valid, so a legitimate zero (e.g. ice-free a_ice or vanishing +! IDEMIX energy) is kept as zero rather than turned into a missing value. +subroutine get_wet_range(entry, mesh, nlev_loc, j, ul_loc, kmax_loc) + use mod_mesh + implicit none + type(Meandata), intent(in) :: entry + type(t_mesh), intent(in) :: mesh + integer, intent(in) :: nlev_loc, j + integer, intent(out) :: ul_loc, kmax_loc + integer :: nl_bot + + if (nlev_loc == mesh%nl .or. nlev_loc == mesh%nl-1) then + ! genuine 3D field on the vertical grid --> mask by topography / cavity + if (entry%is_elem_based) then + ul_loc = mesh%ulevels(j) + nl_bot = mesh%nlevels(j) + else + ul_loc = mesh%ulevels_nod2D(j) + nl_bot = mesh%nlevels_nod2D(j) + end if + ! full levels (nz, interfaces) keep nl_bot levels, mid layers (nz1) keep nl_bot-1 + if (nlev_loc == mesh%nl) then + kmax_loc = nl_bot + else + kmax_loc = nl_bot - 1 + end if + else + ! 2D fields and non-spatial vertical axes: every entry is valid + ul_loc = 1 + kmax_loc = nlev_loc + end if +end subroutine +! +! +!_______________________________________________________________________________ +! main output routine called at the end of each time step --> here is decided if ! output event is triggered subroutine output(istep, ice, dynamics, tracers, partit, mesh) use g_clock @@ -1999,6 +2038,7 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) logical, save :: lfirst=.true. integer :: n, k integer :: i, j !for OMP loops + integer :: nlev_loc, ul_loc, kmax_loc !for wet-cell masking of output logical :: do_output type(Meandata), pointer :: entry type(t_mesh), intent(in) , target :: mesh @@ -2139,36 +2179,42 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) !___________________________________________________________________ ! write double precision output if (entry%accuracy == i_real8) then -!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(I,J) + nlev_loc = size(entry%local_values_r8,dim=1) +!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(I,J,ul_loc,kmax_loc) DO J=1, size(entry%local_values_r8,dim=2) - DO I=1, size(entry%local_values_r8,dim=1) - ! Check if point has valid data (non-zero accumulated value) - ! Use small epsilon to account for floating point precision - if (abs(entry%local_values_r8(I,J)) < 1.0e-30_real64) then - entry%local_values_r8_copy(I,J) = NC_FILL_DOUBLE ! No data - set to fill value + ! Determine the vertically valid (wet) range for this column. Cells + ! outside [ul_loc,kmax_loc] are below the bottom topography or above + ! the cavity and have never been touched -> they are the only ones set + ! to _FillValue. Wet cells keep their (averaged) value, even when it is + ! a legitimate zero (e.g. ice-free a_ice or vanishing IDEMIX energy). + call get_wet_range(entry, mesh, nlev_loc, J, ul_loc, kmax_loc) + DO I=1, nlev_loc + if (I < ul_loc .or. I > kmax_loc) then + entry%local_values_r8_copy(I,J) = NC_FILL_DOUBLE ! dry cell - set to fill value else entry%local_values_r8_copy(I,J) = entry%local_values_r8(I,J) /real(entry%addcounter,real64) ! compute_means end if entry%local_values_r8(I,J) = 0._real64 ! clean_meanarrays - reset to 0 for next accumulation - END DO ! --> DO I=1, size(entry%local_values_r8,dim=1) + END DO ! --> DO I=1, nlev_loc END DO ! --> DO J=1, size(entry%local_values_r8,dim=2) !$OMP END PARALLEL DO !___________________________________________________________________ ! write single precision output else if (entry%accuracy == i_real4) then -!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(I,J) + nlev_loc = size(entry%local_values_r4,dim=1) +!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(I,J,ul_loc,kmax_loc) DO J=1, size(entry%local_values_r4,dim=2) - DO I=1, size(entry%local_values_r4,dim=1) - ! Check if point has valid data (non-zero accumulated value) - ! Use small epsilon to account for floating point precision - if (abs(entry%local_values_r4(I,J)) < 1.0e-30_real32) then - entry%local_values_r4_copy(I,J) = NC_FILL_FLOAT ! No data - set to fill value + ! see comment in the double precision branch above + call get_wet_range(entry, mesh, nlev_loc, J, ul_loc, kmax_loc) + DO I=1, nlev_loc + if (I < ul_loc .or. I > kmax_loc) then + entry%local_values_r4_copy(I,J) = NC_FILL_FLOAT ! dry cell - set to fill value else entry%local_values_r4_copy(I,J) = entry%local_values_r4(I,J) /real(entry%addcounter,real32) ! compute_means end if entry%local_values_r4(I,J) = 0._real32 ! clean_meanarrays - reset to 0 for next accumulation - END DO ! --> DO I=1, size(entry%local_values_r4,dim=1) + END DO ! --> DO I=1, nlev_loc END DO ! --> DO J=1, size(entry%local_values_r4,dim=2) !$OMP END PARALLEL DO end if ! --> if (entry%accuracy == i_real8) then From 959a1768300d10c9e46281ef8253ee47bcf694ad Mon Sep 17 00:00:00 2001 From: chrisdane Date: Tue, 23 Jun 2026 14:40:45 +0200 Subject: [PATCH 18/23] update using recom subrepo --- config/bin_2p3z2d/namelist.config | 145 +++++++--- config/bin_2p3z2d/namelist.config_old | 76 +++++ config/bin_2p3z2d/namelist.dyn | 91 ++++-- config/bin_2p3z2d/namelist.dyn_old | 24 ++ config/bin_2p3z2d/namelist.io | 390 +++++++++++++++++++++++--- config/bin_2p3z2d/namelist.io_old | 83 ++++++ config/bin_2p3z2d/namelist.oce | 96 +++++-- config/bin_2p3z2d/namelist.oce_old | 26 ++ config/bin_2p3z2d/namelist.recom | 1 - config/bin_2p3z2d/namelist.tra | 225 ++++++++++----- config/bin_2p3z2d/namelist.tra_old | 90 ++++++ src/gen_ic3d.F90 | 86 +++--- src/io_meandata.F90 | 2 - src/oce_setup_step.F90 | 83 ++---- 14 files changed, 1126 insertions(+), 292 deletions(-) create mode 100644 config/bin_2p3z2d/namelist.config_old create mode 100644 config/bin_2p3z2d/namelist.dyn_old create mode 100644 config/bin_2p3z2d/namelist.io_old create mode 100644 config/bin_2p3z2d/namelist.oce_old create mode 100644 config/bin_2p3z2d/namelist.tra_old diff --git a/config/bin_2p3z2d/namelist.config b/config/bin_2p3z2d/namelist.config index ffff081c0..7913968bc 100644 --- a/config/bin_2p3z2d/namelist.config +++ b/config/bin_2p3z2d/namelist.config @@ -1,76 +1,133 @@ -! This is the namelist file for model general configuration +! ============================================================================ +! ============ Namelist file for FESOM2 general configuration ================ +! ============================================================================ +! This file contains the main configuration parameters for FESOM2, including: +! - Model identification and run settings +! - Time stepping and simulation duration +! - Initial time/date settings +! - File paths for mesh, forcing, and output +! - Restart and logging configuration +! - Vertical coordinate system (ALE) +! - Grid geometry and rotation +! - Calendar settings +! - Model components (ice, cavities, etc.) +! - Parallel decomposition +! - Iceberg settings +! ============================================================================ +! ============================================================================ +! RUN IDENTIFICATION +! ============================================================================ &modelname -runid='fesom' +runid = 'fesom' ! run identifier (used in output filenames) / +! ============================================================================ +! TIME STEPPING AND RUN LENGTH +! ============================================================================ ×tep -step_per_day=32 !96 !96 !72 !72 !45 !72 !96 -run_length= 1 !62 !62 !62 !28 -run_length_unit='y' ! y, m, d, s +step_per_day = 36 ! number of time steps per day (determines dt = 86400/step_per_day seconds) + ! common values: 32 (45min), 48 (30min), 72 (20min), 96 (15min), 192 (7min 30sec), + ! 216 (6min 40sec), 240 (6min), 288 (5min), 360 (4min), 720 (2min), 1440 (1min), 2880 (30sec) +run_length = 1 ! total length of simulation run +run_length_unit = 'y' ! unit for run_length: 'y' (years), 'm' (months), 'd' (days), 's' (steps) / -&clockinit ! the model starts at -timenew=0.0 -daynew=1 -yearnew=1958 +! ============================================================================ +! INITIAL TIME/DATE SETTINGS +! ============================================================================ +&clockinit +timenew = 0.0 ! initial time within the day [seconds] (0.0 = midnight) +daynew = 1 ! initial day of the month (1-31) +yearnew = 1958 ! initial year / +! ============================================================================ +! MESH, INITIALIZATION & OUTPUT PATHS +! ============================================================================ &paths -MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' -ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' -ResultPath='/albedo/work/user/...' +MeshPath = '/pool/data/AWICM/FESOM2/MESHES_FESOM2.1/core2/' ! path to mesh files (nod2d.out, elem2d.out, etc.) +ClimateDataPath = '/pool/data/AWICM/FESOM2/INITIAL/phc3.0/' ! path to initial conditions (temperature, salinity) +ResultPath = '/work/ab0246/$USER/runtime/fesom2/' ! path for output files and fesom.clock file / +! ============================================================================ +! RESTART AND LOGGING CONFIGURATION +! ============================================================================ &restart_log -restart_length=1 ! --> do netcdf restart ( only required for d,h,s cases, y, m take 1) -restart_length_unit='y' !output period: y, d, h, s, off -raw_restart_length=1 ! --> do core dump restart -raw_restart_length_unit='off' ! e.g. y, d, h, s, off -bin_restart_length=1 ! --> do derived type binary restart -bin_restart_length_unit='off' ! e.g. y, d, h, s, off -logfile_outfreq=960 !in logfile info. output frequency, # steps +restart_length = 1 ! frequency for netCDF restart files (required for d,h,s; y,m use 1) +restart_length_unit = 'y' ! unit: 'y' (years), 'm' (months), 'd' (days), 'h' (hours), 's' (steps), 'off' (disabled) +raw_restart_length = 1 ! frequency for raw core dump restart files +raw_restart_length_unit = 'y' ! unit: 'y', 'm', 'd', 'h', 's', 'off' +bin_restart_length = 1 ! frequency for binary derived type restart files +bin_restart_length_unit = 'y' ! unit: 'y', 'm', 'd', 'h', 's', 'off' +logfile_outfreq = 960 ! log file output frequency [number of time steps] / +! ============================================================================ +! VERTICAL COORDINATE SYSTEM (ALE - Arbitrary Lagrangian-Eulerian) +! ============================================================================ &ale_def -which_ALE='zstar' ! 'linfs','zlevel', 'zstar' -use_partial_cell=.true. +which_ALE = 'zstar' ! vertical coordinate type: + ! 'linfs' = linear free surface + ! 'zlevel' = z-level (fixed depth levels) + ! 'zstar' = z-star (terrain-following with SSH scaling) +use_partial_cell = .false. ! use partial bottom cells for better topography representation (not recommended) / +! ============================================================================ +! GRID GEOMETRY AND ROTATION +! ============================================================================ &geometry -cartesian=.false. -fplane=.false. -cyclic_length=360 ![degree] -rotated_grid=.true. !option only valid for coupled model case now -force_rotation=.true. -alphaEuler=50. ![degree] Euler angles, convention: -betaEuler=15. ![degree] first around z, then around new x, -gammaEuler=-90. ![degree] then around new z. +cartesian = .false. ! use Cartesian coordinates (false = spherical Earth) +fplane = .false. ! use f-plane approximation (constant Coriolis parameter) +cyclic_length = 360 ! length of cyclic domain [degrees] (360 = global) +rotated_grid = .true. ! use rotated grid (typically for coupled models to avoid pole singularity) +force_rotation = .true. ! force grid rotation even if not coupled +alphaEuler = 50. ! first Euler angle (rotation around z-axis) [degrees] +betaEuler = 15. ! second Euler angle (rotation around new x-axis) [degrees] +gammaEuler = -90. ! third Euler angle (rotation around new z-axis) [degrees] + ! Euler angle convention: rotate first around z, then around new x, then around new z / +! ============================================================================ +! CALENDAR SETTINGS +! ============================================================================ &calendar -include_fleapyear=.false. +include_fleapyear = .true. ! include leap years in calendar (false = 365-day year, true = 365/366-day year) / +! ============================================================================ +! MODEL COMPONENTS AND FEATURES +! ============================================================================ &run_config -use_ice=.true. ! ocean+ice -use_cavity=.false. ! -use_cavity_partial_cell=.false. -use_floatice = .false. -use_sw_pene=.true. -flag_debug=.false. -use_transit=.false. +use_ice = .true. ! enable sea ice model +use_cavity = .false. ! enable ice shelf cavities +use_cavity_partial_cell = .false. ! use partial cells in ice shelf cavities (not recommended) +use_floatice = .false. ! enable floating ice (icebergs) +use_sw_pene = .true. ! enable shortwave radiation penetration into ocean +flag_debug = .false. ! enable debug output (verbose logging) +use_transit = .false. ! enable transient tracer module (CFCs, SF6, etc.) / +! ============================================================================ +! PARALLEL DECOMPOSITION (DOMAIN PARTITIONING) +! ============================================================================ &machine -n_levels=2 -n_part= 12, 36 ! 432 number of partitions on each hierarchy level +n_levels = 2 ! number of hierarchy levels for domain decomposition +n_part = 2, 128 ! number of partitions at each level (total CPUs = product of n_part) + ! example: 2 x 128 = 256 MPI tasks + ! adjust based on mesh size and available compute resources + ! maximum scaling reached at ~300 FESOM2 2D nodes per CPU (see first line in nod2d.out for number of 2D nodes) / +! ============================================================================ +! ICEBERG SETTINGS +! ============================================================================ &icebergs -use_icesheet_coupling=.false. -ib_num=1 -use_icebergs=.false. -steps_per_ib_step=8 -ib_async_mode=0 +use_icesheet_coupling = .false. ! enable ice sheet model +ib_num = 1 ! number of iceberg classes +use_icebergs = .false. ! enable iceberg module +steps_per_ib_step = 8 ! ocean time steps per iceberg time step (iceberg subcycling) +ib_async_mode = 0 ! iceberg asynchronous mode (0=synchronous, 1=asynchronous) / diff --git a/config/bin_2p3z2d/namelist.config_old b/config/bin_2p3z2d/namelist.config_old new file mode 100644 index 000000000..ffff081c0 --- /dev/null +++ b/config/bin_2p3z2d/namelist.config_old @@ -0,0 +1,76 @@ +! This is the namelist file for model general configuration + +&modelname +runid='fesom' +/ + +×tep +step_per_day=32 !96 !96 !72 !72 !45 !72 !96 +run_length= 1 !62 !62 !62 !28 +run_length_unit='y' ! y, m, d, s +/ + +&clockinit ! the model starts at +timenew=0.0 +daynew=1 +yearnew=1958 +/ + +&paths +MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' +ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' +ResultPath='/albedo/work/user/...' +/ + +&restart_log +restart_length=1 ! --> do netcdf restart ( only required for d,h,s cases, y, m take 1) +restart_length_unit='y' !output period: y, d, h, s, off +raw_restart_length=1 ! --> do core dump restart +raw_restart_length_unit='off' ! e.g. y, d, h, s, off +bin_restart_length=1 ! --> do derived type binary restart +bin_restart_length_unit='off' ! e.g. y, d, h, s, off +logfile_outfreq=960 !in logfile info. output frequency, # steps +/ + +&ale_def +which_ALE='zstar' ! 'linfs','zlevel', 'zstar' +use_partial_cell=.true. +/ + +&geometry +cartesian=.false. +fplane=.false. +cyclic_length=360 ![degree] +rotated_grid=.true. !option only valid for coupled model case now +force_rotation=.true. +alphaEuler=50. ![degree] Euler angles, convention: +betaEuler=15. ![degree] first around z, then around new x, +gammaEuler=-90. ![degree] then around new z. +/ + +&calendar +include_fleapyear=.false. +/ + +&run_config +use_ice=.true. ! ocean+ice +use_cavity=.false. ! +use_cavity_partial_cell=.false. +use_floatice = .false. +use_sw_pene=.true. +flag_debug=.false. +use_transit=.false. +/ + +&machine +n_levels=2 +n_part= 12, 36 ! 432 number of partitions on each hierarchy level +/ + +&icebergs +use_icesheet_coupling=.false. +ib_num=1 +use_icebergs=.false. +steps_per_ib_step=8 +ib_async_mode=0 +/ diff --git a/config/bin_2p3z2d/namelist.dyn b/config/bin_2p3z2d/namelist.dyn index fb7919588..8ec74c55b 100644 --- a/config/bin_2p3z2d/namelist.dyn +++ b/config/bin_2p3z2d/namelist.dyn @@ -1,24 +1,79 @@ +! ============================================================================ +! ========== Namelist file for FESOM2 momentum dynamics ====================== +! ============================================================================ +! This file contains configuration for momentum equations and dynamics: +! - Horizontal viscosity schemes and parameters +! - Momentum advection options +! - Free-slip vs no-slip boundary conditions +! - Vertical velocity splitting +! - Split-explicit barotropic subcycling +! - Energy diagnostics +! ============================================================================ + +! ============================================================================ +! HORIZONTAL VISCOSITY +! ============================================================================ &dynamics_visc -visc_gamma0 = 0.003 ! [m/s], backgroung viscosity= gamma0*len, it should be as small a s possible (keep it < 0.01 m/s). -visc_gamma1 = 0.1 ! [nodim], for computation of the flow aware viscosity -visc_gamma2 = 0.285 ! [s/m], is only used in easy backscatter option -visc_easybsreturn= 1.5 - -opt_visc = 5 -! 5=Kinematic (easy) Backscatter -! 6=Biharmonic flow aware (viscosity depends on velocity Laplacian) -! 7=Biharmonic flow aware (viscosity depends on velocity differences) -! 8=Dynamic Backscatter - -use_ivertvisc= .true. +! --- Biharmonic Viscosity Coefficients --- +visc_gamma0 = 0.003 ! background viscosity coefficient [m/s] + ! viscosity = gamma0 × element_length + ! keep < 0.01 m/s for numerical stability +visc_gamma1 = 0.1 ! flow-aware viscosity coefficient [dimensionless] +visc_gamma2 = 0.285 ! additional viscosity coefficient [s/m] + ! only used for easy backscatter (opt_visc=5) and dynamic backscatter (opt_visc=8) +visc_easybsreturn = 1.5 ! energy return parameter for easy backscatter [dimensionless] + +! --- Harmonic (Laplacian) Viscosity Coefficients (for opt_visc=7) --- +! When both are 0, opt_visc=7 is pure biharmonic viscosity. +! When > 0, harmonic viscosity is added to biharmonic (combined mode). +visc_gamma0_h = 0.0 ! < 0.003 background harmonic viscosity coefficient [m/s] +visc_gamma1_h = 0.0 ! < 0.05 flow-aware harmonic viscosity coefficient [dimensionless] + +! --- Viscosity Scheme Selection --- +opt_visc = 5 ! horizontal viscosity scheme: + ! 5 = Kinematic (easy) Backscatter + ! 6 = Biharmonic flow-aware (depends on velocity Laplacian) + ! 7 = Biharmonic flow-aware (depends on velocity differences) + ! + optional Laplacian when visc_gamma0_h or visc_gamma1_h > 0 + ! 8 = Dynamic Backscatter +check_opt_visc = .true. ! check if opt_visc=5 is valid based on resolution/Rossby radius ratio + +! --- Vertical Viscosity --- +use_ivertvisc = .true. ! use implicit vertical viscosity (recommended for stability) / +! ============================================================================ +! GENERAL DYNAMICS SETTINGS +! ============================================================================ &dynamics_general -momadv_opt = 2 ! option for momentum advection in moment only =2 -use_freeslip = .false. ! Switch on free slip -use_wsplit = .false. ! Switch for implicite/explicte splitting of vert. velocity -wsplit_maxcfl= 1.0 ! maximum allowed CFL criteria in vertical (0.5 < w_max_cfl < 1.) - ! in older FESOM it used to be w_exp_max=1.e-3 -ldiag_KE=.false. ! activates energy diagnostics +! --- Momentum Advection --- +momadv_opt = 2 ! momentum advection option (only 2 is currently supported) + +! --- Boundary Conditions --- +use_freeslip = .false. ! enable free-slip lateral boundary conditions (false = no-slip) + +! --- Vertical Velocity Splitting --- +use_wsplit = .false. ! enable implicit/explicit splitting of vertical velocity +wsplit_maxcfl = 1.0 ! maximum allowed vertical CFL criterion (range: 0.5-1.0) + ! in older FESOM versions this was w_exp_max=1.e-3 + +! --- Energy Diagnostics --- +ldiag_KE = .false. ! enable kinetic energy diagnostics (requires additional computation) + +! --- Time Stepping --- +AB_order = 2 ! Adams-Bashforth time stepping order (2 or 3) + +! --- Split-Explicit Barotropic Subcycling --- +use_ssh_se_subcycl = .false. ! enable split-explicit subcycling for barotropic mode + ! (faster time stepping for sea surface height) +se_BTsteps = 50 ! number of barotropic subcycles per baroclinic time step +se_BTtheta = 0.14 ! implicitness parameter for barotropic solver (0-1, default: 0.14) +se_bottdrag = .true. ! include bottom drag in barotropic subcycling +se_bdrag_si = .true. ! use semi-implicit bottom drag (true) or explicit (false) +se_visc = .true. ! include viscosity in barotropic subcycling +se_visc_gamma0 = 10 ! background viscosity for barotropic mode [dimensionless] +se_visc_gamma1 = 19500 ! flow-aware viscosity for barotropic mode [dimensionless] + ! typical values: 19500 (CORE2@32spd), 2750 (CORE2@72spd) +se_visc_gamma2 = 0 ! additional viscosity for barotropic mode [dimensionless] / diff --git a/config/bin_2p3z2d/namelist.dyn_old b/config/bin_2p3z2d/namelist.dyn_old new file mode 100644 index 000000000..fb7919588 --- /dev/null +++ b/config/bin_2p3z2d/namelist.dyn_old @@ -0,0 +1,24 @@ +&dynamics_visc +visc_gamma0 = 0.003 ! [m/s], backgroung viscosity= gamma0*len, it should be as small a s possible (keep it < 0.01 m/s). +visc_gamma1 = 0.1 ! [nodim], for computation of the flow aware viscosity +visc_gamma2 = 0.285 ! [s/m], is only used in easy backscatter option +visc_easybsreturn= 1.5 + +opt_visc = 5 +! 5=Kinematic (easy) Backscatter +! 6=Biharmonic flow aware (viscosity depends on velocity Laplacian) +! 7=Biharmonic flow aware (viscosity depends on velocity differences) +! 8=Dynamic Backscatter + +use_ivertvisc= .true. +/ + +&dynamics_general +momadv_opt = 2 ! option for momentum advection in moment only =2 +use_freeslip = .false. ! Switch on free slip +use_wsplit = .false. ! Switch for implicite/explicte splitting of vert. velocity +wsplit_maxcfl= 1.0 ! maximum allowed CFL criteria in vertical (0.5 < w_max_cfl < 1.) + ! in older FESOM it used to be w_exp_max=1.e-3 +ldiag_KE=.false. ! activates energy diagnostics +/ + diff --git a/config/bin_2p3z2d/namelist.io b/config/bin_2p3z2d/namelist.io index 10bb72c1b..da2f25ed0 100644 --- a/config/bin_2p3z2d/namelist.io +++ b/config/bin_2p3z2d/namelist.io @@ -1,33 +1,64 @@ +! ============================================================================ +! ============ Namelist file for FESOM2 output configuration ================= +! ============================================================================ +! This file contains configuration for model output and diagnostics: +! - Diagnostic flags for optional output fields +! - General output settings (compression, rotation) +! - Output variable list with frequency and precision +! - Complete catalog of all available output fields +! +! See the output catalog at the end of this file for all possible variables. +! Some outputs require specific flags in &diag_list or other namelists. +! ============================================================================ + +! ============================================================================ +! DIAGNOSTIC FLAGS +! ============================================================================ +! Enable/disable optional diagnostic computations and outputs. +! Setting these to .true. enables additional output fields (see catalog below). +! ============================================================================ &diag_list -ldiag_solver =.false. -lcurt_stress_surf=.false. -ldiag_curl_vel3 =.false. -ldiag_Ri =.false. -ldiag_turbflux =.false. -ldiag_salt3D =.false. -ldiag_dMOC =.false. -ldiag_DVD =.false. -ldiag_forc =.false. -ldiag_extflds =.false. +ldiag_solver = .false. ! enables solver diagnostics (convergence, iterations) +lcurt_stress_surf = .false. ! enables 'curl_surf' output (vorticity of surface stress) +ldiag_curl_vel3 = .false. ! enables 'curl_u' output (relative vorticity from 3D velocity) +ldiag_Ri = .false. ! enables Richardson number diagnostics ('shear', 'Ri') +ldiag_turbflux = .false. ! enables turbulent flux diagnostics ('KvdTdz', 'KvdSdz') +ldiag_salt3D = .false. ! enables 3D salinity diagnostics +ldiag_dMOC = .false. ! enables 'dMOC' output (density MOC diagnostics) +ldiag_DVD = .false. ! enables 'DVD' output (Discrete Variance Decay diagnostics) +ldiag_forc = .false. ! enables 'FORC' output (comprehensive forcing diagnostics) +ldiag_extflds = .false. ! enables extended field diagnostics +ldiag_destine = .false. ! enables heat content computation ('hc300m', 'hc700m', 'hc') +ldiag_trflx = .false. ! enables tracer flux diagnostics ('utemp', 'vtemp', 'usalt', 'vsalt') +ldiag_uvw_sqr = .false. ! enables 'UVW_SQR' output (squared velocities: u2, v2, w2) +ldiag_trgrd_xyz = .false. ! enables 'TRGRD_XYZ' output (horizontal & vertical tracer gradients) +ldiag_cmor = .false. ! enables CMOR diagnostics for CMIP6/CMIP7 ('tos', 'sos', 'pbo', 'volo', etc.) / +! ============================================================================ +! GENERAL OUTPUT SETTINGS +! ============================================================================ &nml_general -io_listsize =150 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list -vec_autorotate =.false. +io_listsize = 120 ! total number of streams to allocate. Shall be larger or equal to the number of streams in &nml_list (max. 150) +vec_autorotate = .false. ! unrotate vector fields (velocities, winds) before writing to output files +compression_level = 1 ! compression level for netCDF output (1=fastest, 9=smallest) / -! for sea ice related variables use_ice should be true, otherewise there will be no output -! for 'curl_surf' to work lcurt_stress_surf must be .true. otherwise no output -! for 'fer_C', 'bolus_u', 'bolus_v', 'bolus_w', 'fer_K' to work Fer_GM must be .true. otherwise no output -! 'otracers' - all other tracers if applicable -! for 'dMOC' to work ldiag_dMOC must be .true. otherwise no output +! ============================================================================ +! OUTPUT VARIABLE LIST +! ============================================================================ +! Format: 'variable_id', frequency, unit, precision +! frequency = output frequency (integer) +! unit = 'y' (yearly), 'm' (monthly), 'd' (daily), 'h' (hourly), 's' (steps) +! precision = 4 (single precision) or 8 (double precision) +! ============================================================================ &nml_list -io_list = 'sst ',1, 'm', 4, - 'sss ',1, 'm', 4, - 'ssh ',1, 'm', 4, +io_list = 'sst ',6, 'h', 4, + 'sss ',6, 'h', 4, + 'ssh ',1, 'm', 4, 'uice ',1, 'm', 4, 'vice ',1, 'm', 4, - 'a_ice ',1, 'm', 4, + 'a_ice ',6, 'h', 4, 'm_ice ',1, 'm', 4, 'm_snow ',1, 'm', 4, 'MLD1 ',1, 'm', 4, @@ -37,21 +68,23 @@ io_list = 'sst ',1, 'm', 4, 'ty_sur ',1, 'm', 4, 'temp ',1, 'm', 4, 'salt ',1, 'm', 8, - 'otracers ',1, 'm', 4, - 'N2 ',1, 'y', 4, - 'Kv ',1, 'y', 4, + 'N2 ',1, 'm', 4, + 'Kv ',1, 'm', 4, 'u ',1, 'm', 4, 'v ',1, 'm', 4, 'unod ',1, 'm', 4, 'vnod ',1, 'm', 4, 'w ',1, 'm', 4, - 'Av ',1, 'y', 4, - 'bolus_u ',1, 'y', 4, - 'bolus_v ',1, 'y', 4, - 'bolus_w ',1, 'y', 4, + 'Av ',1, 'm', 4, + 'bolus_u ',1, 'm', 4, + 'bolus_v ',1, 'm', 4, + 'bolus_w ',1, 'm', 4, + 'fw ',1, 'm', 4, + 'fh ',1, 'm', 4, + 'otracers ',1, 'm', 4, 'dpCO2s ',1, 'm', 4, - 'pCO2s ',1, 'm', 4, - 'CO2f ',1, 'm', 4, + 'pCO2s ',6, 'h', 4, + 'CO2f ',6, 'h', 4, 'Hp ',1, 'm', 4, 'aFe ',1, 'm', 4, 'aN ',1, 'm', 4, @@ -69,15 +102,290 @@ io_list = 'sst ',1, 'm', 4, 'NPPd ',1, 'm', 4, 'NPPn ',1, 'm', 4, 'PAR ',1, 'm', 4, - 'respmeso',1, 'm', 4, - 'respmacro',1, 'm', 4, - 'respmicro',1, 'm', 4, - 'calcdiss',1, 'm', 4, - 'calcif',1, 'm', 4, - 'aggn',1, 'm', 4, - 'aggd',1, 'm', 4, - 'docexn',1, 'm', 4, - 'docexd',1, 'm', 4, - 'respn',1, 'm', 4, - 'respd',1, 'm', 4, + 'respmeso ',1, 'm', 4, + 'respmacro ',1, 'm', 4, + 'respmicro ',1, 'm', 4, + 'calcdiss ',1, 'm', 4, + 'calcif ',1, 'm', 4, + 'aggn ',1, 'm', 4, + 'aggd ',1, 'm', 4, + 'docexn ',1, 'm', 4, + 'docexd ',1, 'm', 4, + 'respn ',1, 'm', 4, + 'respd ',1, 'm', 4, + 'xCO2atm ',6, 'h', 4, / + +! ============================================================================ +! COMPLETE CATALOG OF ALL POSSIBLE OUTPUT FIELDS +! ============================================================================ +! Below is a comprehensive list of all valid io_list IDs available in FESOM2. +! To enable any field, copy the line to the &nml_list section above. +! NOTE: Some fields require specific flags to be enabled (see comments). +! ============================================================================ + +! --- 2D OCEAN SURFACE FIELDS --- +! 'sst ',1, 'm', 4, ! sea surface temperature [C] +! 'sss ',1, 'm', 4, ! sea surface salinity [psu] +! 'ssh ',1, 'm', 4, ! sea surface elevation [m] +! 'vve_5 ',1, 'm', 4, ! vertical velocity at 5th level [m/s] +! 't_star ',1, 'm', 4, ! air temperature [C] +! 'qsr ',1, 'm', 4, ! solar radiation [W/s^2] + +! --- 3D OCEAN FIELDS --- +! 'temp ',1, 'm', 4, ! temperature [C] +! 'salt ',1, 'm', 8, ! salinity [psu] +! 'sigma0 ',1, 'm', 4, ! potential density [kg/m3] +! 'u ',1, 'm', 4, ! zonal velocity [m/s] +! 'v ',1, 'm', 4, ! meridional velocity [m/s] +! 'unod ',1, 'm', 4, ! zonal velocity at nodes [m/s] +! 'vnod ',1, 'm', 4, ! meridional velocity at nodes [m/s] +! 'w ',1, 'm', 4, ! vertical velocity [m/s] +! 'otracers ',1, 'm', 4, ! all other tracers if applicable +! 'age ',1, 'm', 4, ! water age tracer [year] (require use_age_tracer=.true.) + +! --- 2D SSH DIAGNOSTIC VARIABLES --- +! 'ssh_rhs ',1, 'm', 4, ! ssh rhs [m/s] +! 'ssh_rhs_old',1, 'm', 4, ! ssh rhs old [m/s] +! 'd_eta ',1, 'm', 4, ! dssh from solver [m] +! 'hbar ',1, 'm', 4, ! ssh n+0.5 tstep [m] +! 'hbar_old ',1, 'm', 4, ! ssh n-0.5 tstep [m] +! 'dhe ',1, 'm', 4, ! dhbar @ elem [m] + +! --- SEA ICE FIELDS (require use_ice=.true.) --- +! 'uice ',1, 'm', 4, ! ice velocity x [m/s] +! 'vice ',1, 'm', 4, ! ice velocity y [m/s] +! 'a_ice ',1, 'm', 4, ! ice concentration [%] +! 'm_ice ',1, 'm', 4, ! ice height per unit area [m] +! 'thdgrice ',1, 'm', 4, ! thermodynamic growth rate ice [m/s] +! 'thdgrarea ',1, 'm', 4, ! thermodynamic growth rate ice concentration [frac/s] +! 'dyngrarea' ,1, 'm', 4, ! dynamic growth rate ice concentration [frac/s] +! 'dyngrice ',1, 'm', 4, ! dynamic growth rate ice [m/s] +! 'thdgrsn ',1, 'm', 4, ! thermodynamic growth rate snow [m/s] +! 'dyngrsnw ',1, 'm', 4, ! dynamic growth rate snow [m/s] +! 'flice ',1, 'm', 4, ! flooding growth rate ice [m/s] +! 'm_snow ',1, 'm', 4, ! snow height per unit area [m] +! 'h_ice ',1, 'm', 4, ! ice thickness over ice-covered fraction [m] +! 'h_snow ',1, 'm', 4, ! snow thickness over ice-covered fraction [m] +! 'fw_ice ',1, 'm', 4, ! fresh water flux from ice ['m/s'] +! 'fw_snw ',1, 'm', 4, ! fresh water flux from snow ['m/s'] + +! --- SEA ICE DEBUG VARIABLES (require use_ice=.true.) --- +! 'strength_ice',1, 'm', 4, ! ice strength [?] +! 'inv_areamass',1, 'm', 4, ! inv_areamass [?] +! 'rhs_a ',1, 'm', 4, ! rhs_a [?] +! 'rhs_m ',1, 'm', 4, ! rhs_m [?] +! 'sgm11 ',1, 'm', 4, ! sgm11 [?] +! 'sgm12 ',1, 'm', 4, ! sgm12 [?] +! 'sgm22 ',1, 'm', 4, ! sgm22 [?] +! 'eps11 ',1, 'm', 4, ! eps11 [?] +! 'eps12 ',1, 'm', 4, ! eps12 [?] +! 'eps22 ',1, 'm', 4, ! eps22 [?] +! 'u_rhs_ice ',1, 'm', 4, ! u_rhs_ice [?] +! 'v_rhs_ice ',1, 'm', 4, ! v_rhs_ice [?] +! 'metric_fac',1, 'm', 4, ! metric_fac [?] +! 'elevat_ice',1, 'm', 4, ! elevat_ice [?] +! 'uwice ',1, 'm', 4, ! uwice [?] +! 'vwice ',1, 'm', 4, ! vwice [?] +! 'twice ',1, 'm', 4, ! twice [?] +! 'swice ',1, 'm', 4, ! swice [?] + +! --- MIXED LAYER DEPTH --- +! 'MLD1 ',1, 'm', 4, ! Mixed Layer Depth [m] Large et al. 1997, bvfreq(nz, node) > db_max +! 'MLD2 ',1, 'm', 4, ! Mixed Layer Depth [m] Levitus treshold, rhopot(nz)-rhopot(1) > 0.125_WP kg/m +! 'MLD3 ',1, 'm', 4, ! Mixed Layer Depth [m] Griffies 2016 , rhopot(nz)-rhopot(1) > 0.03_WP kg/m + +! --- HEAT CONTENT (require ldiag_destine=.true.) --- +! 'hc300m ',1, 'm', 4, ! Vertically integrated heat content upper 300m [J m**-2] +! 'hc700m ',1, 'm', 4, ! Vertically integrated heat content upper 700m [J m**-2] +! 'hc ',1, 'm', 4, ! Vertically integrated heat content total column [J m**-2] + +! --- WATER ISOTOPES IN SEA ICE (require lwiso=.true.) --- +! 'h2o18_ice ',1, 'm', 4, ! h2o18 concentration in sea ice [kmol/m**3] +! 'hDo16_ice ',1, 'm', 4, ! hDo16 concentration in sea ice [kmol/m**3] +! 'h2o16_ice ',1, 'm', 4, ! h2o16 concentration in sea ice [kmol/m**3] + +! --- FRESHWATER FLUX (require use_landice_water=.true.) --- +! 'landice ',1, 'm', 4, ! freshwater flux [m/s] + +! --- SURFACE FORCING --- +! 'tx_sur ',1, 'm', 4, ! zonal wind str. to ocean [N/m2] +! 'ty_sur ',1, 'm', 4, ! meridional wind str. to ocean [N/m2] +! 'curl_surf ',1, 'm', 4, ! vorticity of the surface stress [none] (require lcurt_stress_surf=.true.) +! 'fh ',1, 'm', 4, ! heat flux [W/m2] +! 'fw ',1, 'm', 4, ! fresh water flux [m/s] +! 'atmice_x ',1, 'm', 4, ! stress atmice x [N/m2] +! 'atmice_y ',1, 'm', 4, ! stress atmice y [N/m2] +! 'atmoce_x ',1, 'm', 4, ! stress atmoce x [N/m2] +! 'atmoce_y ',1, 'm', 4, ! stress atmoce y [N/m2] +! 'iceoce_x ',1, 'm', 4, ! stress iceoce x [N/m2] +! 'iceoce_y ',1, 'm', 4, ! stress iceoce y [N/m2] +! 'alpha ',1, 'm', 4, ! thermal expansion [none] +! 'beta ',1, 'm', 4, ! saline contraction [none] +! 'dens_flux ',1, 'm', 4, ! density flux [kg/(m3*s)] +! 'runoff ',1, 'm', 4, ! river runoff [m/s] +! 'evap ',1, 'm', 4, ! evaporation [m/s] +! 'prec ',1, 'm', 4, ! precipitation rain [m/s] +! 'snow ',1, 'm', 4, ! precipitation snow [m/s] +! 'tair ',1, 'm', 4, ! surface air temperature [°C] +! 'shum ',1, 'm', 4, ! specific humidity [] +! 'swr ',1, 'm', 4, ! short wave radiation [W/m^2] +! 'lwr ',1, 'm', 4, ! long wave radiation [W/m^2] +! 'uwind ',1, 'm', 4, ! 10m zonal surface wind velocity [m/s] +! 'vwind ',1, 'm', 4, ! 10m merid. surface wind velocity [m/s] +! 'virtsalt ',1, 'm', 4, ! virtual salt flux [m/s*psu] +! 'relaxsalt ',1, 'm', 4, ! relaxation salt flux [m/s*psu] +! 'realsalt ',1, 'm', 4, ! real salt flux from sea ice [m/s*psu] + +! --- KPP VERTICAL MIXING (require mix_scheme_nmb==1,17,3,37) --- +! 'kpp_obldepth',1, 'm', 4, ! KPP ocean boundary layer depth [m] +! 'kpp_sbuoyflx',1, 'm', 4, ! surface buoyancy flux [m2/s3] + +! --- RECOM 2D BIOGEOCHEMISTRY (require use_REcoM=.true. and __recom) --- +! 'dpCO2s ',1, 'm', 4, ! Difference of oceanic pCO2 minus atmospheric pCO2 [uatm] +! 'pCO2s ',1, 'm', 4, ! Partial pressure of oceanic CO2 [uatm] +! 'CO2f ',1, 'm', 4, ! CO2-flux into the surface water [mmolC/m2/d] +! 'O2f ',1, 'm', 4, ! O2-flux into the surface water [mmolO/m2/d] +! 'Hp ',1, 'm', 4, ! Mean of H-plus ions in the surface water [mol/kg] +! 'aFe ',1, 'm', 4, ! Atmospheric iron input [umolFe/m2/s] +! 'aN ',1, 'm', 4, ! Atmospheric DIN input [mmolN/m2/s] +! 'benN ',1, 'm', 4, ! Benthos Nitrogen [mmol] +! 'benC ',1, 'm', 4, ! Benthos Carbon [mmol] +! 'benSi ',1, 'm', 4, ! Benthos silicon [mmol] +! 'benCalc ',1, 'm', 4, ! Benthos calcite [mmol] +! 'NPPn ',1, 'm', 4, ! Mean NPP nanophytoplankton [mmolC/m2/d] +! 'NPPd ',1, 'm', 4, ! Mean NPP diatoms [mmolC/m2/d] +! 'GPPn ',1, 'm', 4, ! Mean GPP nanophytoplankton [mmolC/m2/d] +! 'GPPd ',1, 'm', 4, ! Mean GPP diatoms [mmolC/m2/d] +! 'NNAn ',1, 'm', 4, ! Net N-assimilation nanophytoplankton [mmolN/m2/d] +! 'NNAd ',1, 'm', 4, ! Net N-assimilation diatoms [mmolN/m2/d] +! 'Chldegn ',1, 'm', 4, ! Chlorophyll degradation nanophytoplankton [1/d] +! 'Chldegd ',1, 'm', 4, ! Chlorophyll degradation diatoms [1/d] +! 'NPPc ',1, 'm', 4, ! Mean NPP coccolithophores [mmolC/(m2*d)] +! 'GPPc ',1, 'm', 4, ! Mean GPP coccolithophores [mmolC/m2/d] +! 'NNAc ',1, 'm', 4, ! Net N-assimilation coccolithophores [mmolN/(m2*d)] +! 'Chldegc ',1, 'm', 4, ! Chlorophyll degradation coccolithophores [1/d] + +! --- RECOM 3D BIOGEOCHEMISTRY (require use_REcoM=.true. and __recom) --- +! 'PAR ',1, 'm', 4, ! PAR [W/m2] +! 'respmeso ',1, 'm', 4, ! Respiration rate of mesozooplankton [mmolC/m2/d] +! 'respmacro ',1, 'm', 4, ! Respiration rate of macrozooplankton [mmolC/m2/d] +! 'respmicro ',1, 'm', 4, ! Respiration rate of microzooplankton [mmolC/m2/d] +! 'calcdiss ',1, 'm', 4, ! Calcite dissolution [mmolC/m2/d] +! 'calcif ',1, 'm', 4, ! Calcification [mmolC/m2/d] +! 'aggn ',1, 'm', 4, ! Aggregation of small phytoplankton [mmolC/m2/d] +! 'aggd ',1, 'm', 4, ! Aggregation of diatoms [mmolC/m2/d] +! 'aggc ',1, 'm', 4, ! Aggregation of coccolithophores [mmolC/m2/d] +! 'docexn ',1, 'm', 4, ! DOC excretion by small phytoplankton [mmolC/m2/d] +! 'docexd ',1, 'm', 4, ! DOC excretion by diatoms [mmolC/m2/d] +! 'docexc ',1, 'm', 4, ! DOC excretion by coccolithophores [mmolC/m2/d] +! 'respn ',1, 'm', 4, ! Respiration by small phytoplankton [mmolC/m2/d] +! 'respd ',1, 'm', 4, ! Respiration by diatoms [mmolC/m2/d] +! 'respc ',1, 'm', 4, ! Respiration by coccolithophores [mmolC/(m2*d)] +! 'NPPn3D ',1, 'm', 4, ! Net primary production of small phytoplankton [mmolC/m2/d] +! 'NPPd3D ',1, 'm', 4, ! Net primary production of diatoms [mmolC/m2/d] +! 'NPPc3D ',1, 'm', 4, ! Net primary production of coccolithophores [mmolC/m2/d] + +! --- WATER ISOTOPES IN OCEAN (require lwiso=.true.) --- +! 'h2o18 ',1, 'm', 4, ! h2o18 concentration [kmol/m**3] +! 'hDo16 ',1, 'm', 4, ! hDo16 concentration [kmol/m**3] +! 'h2o16 ',1, 'm', 4, ! h2o16 concentration [kmol/m**3] + +! --- NEUTRAL SLOPES --- +! 'slopetap_x',1, 'm', 4, ! neutral slope tapered X [none] +! 'slopetap_y',1, 'm', 4, ! neutral slope tapered Y [none] +! 'slopetap_z',1, 'm', 4, ! neutral slope tapered Z [none] +! 'slope_x ',1, 'm', 4, ! neutral slope X [none] +! 'slope_y ',1, 'm', 4, ! neutral slope Y [none] +! 'slope_z ',1, 'm', 4, ! neutral slope Z [none] + +! --- MIXING AND DYNAMICS --- +! 'N2 ',1, 'm', 4, ! brunt väisälä [1/s2] +! 'Kv ',1, 'm', 4, ! vertical diffusivity Kv [m2/s] +! 'Av ',1, 'm', 4, ! vertical viscosity Av [m2/s] + +! --- VISCOSITY TENDENCIES (require dynamics%opt_visc==8) --- +! 'u_dis_tend',1, 'm', 4, ! horizontal velocity viscosity tendency [m/s] +! 'v_dis_tend',1, 'm', 4, ! meridional velocity viscosity tendency [m/s] +! 'u_back_tend',1, 'm', 4, ! horizontal velocity backscatter tendency [m2/s2] +! 'v_back_tend',1, 'm', 4, ! meridional velocity backscatter tendency [m2/s2] +! 'u_total_tend',1, 'm', 4,! horizontal velocity total viscosity tendency [m/s] +! 'v_total_tend',1, 'm', 4,! meridional velocity total viscosity tendency [m/s] + +! --- FERRARI/GM PARAMETERISATION (require Fer_GM=.true.) --- +! 'bolus_u ',1, 'm', 4, ! GM bolus velocity U [m/s] +! 'bolus_v ',1, 'm', 4, ! GM bolus velocity V [m/s] +! 'bolus_w ',1, 'm', 4, ! GM bolus velocity W [m/s] +! 'fer_K ',1, 'm', 4, ! GM, stirring diff. [m2/s] +! 'fer_scal ',1, 'm', 4, ! GM surface scaling [] +! 'fer_C ',1, 'm', 4, ! GM, depth independent speed [m/s] +! 'cfl_z ',1, 'm', 4, ! vertical CFL criteria [?] + +! --- DENSITY MOC DIAGNOSTICS (require ldiag_dMOC=.true.) --- +! 'dMOC ',1, 'm', 4, ! fluxes for density MOC (multiple variables) + +! --- PRESSURE GRADIENT FORCE --- +! 'pgf_x ',1, 'm', 4, ! zonal pressure gradient force [m/s^2] +! 'pgf_y ',1, 'm', 4, ! meridional pressure gradient force [m/s^2] + +! --- ALE LAYER THICKNESS --- +! 'hnode ',1, 'm', 4, ! vertice layer thickness [m] +! 'hnode_new ',1, 'm', 4, ! hnode_new [m] +! 'helem ',1, 'm', 4, ! elemental layer thickness [m] + +! --- OIFS/IFS INTERFACE (require __oifs or __ifsinterface) --- +! 'alb ',1, 'm', 4, ! ice albedo [none] +! 'ist ',1, 'm', 4, ! ice surface temperature [K] +! 'qsi ',1, 'm', 4, ! ice heat flux [W/m^2] +! 'qso ',1, 'm', 4, ! oce heat flux [W/m^2] +! 'enthalpy ',1, 'm', 4, ! enthalpy of fusion [W/m^2] +! 'qcon ',1, 'm', 4, ! conductive heat flux [W/m^2] +! 'qres ',1, 'm', 4, ! residual heat flux [W/m^2] +! 'runoff_liquid',1, 'm', 4, ! liquid water runoff [m/s] +! 'runoff_solid',1, 'm', 4, ! solid water runoff [m/s] + +! --- ICEBERG OUTPUTS (require use_icebergs=.true.) --- +! 'icb ',1, 'm', 4, ! iceberg outputs (multiple variables) + +! --- TKE MIXING DIAGNOSTICS (require mix_scheme_nmb==5 or 56) --- +! 'TKE ',1, 'm', 4, ! TKE diagnostics (multiple variables) + +! --- IDEMIX MIXING DIAGNOSTICS (require mod(mix_scheme_nmb,10)==6) --- +! 'IDEMIX ',1, 'm', 4, ! IDEMIX diagnostics (multiple variables) + +! --- TIDAL MIXING DIAGNOSTICS (require mod(mix_scheme_nmb,10)==7) --- +! 'TIDAL ',1, 'm', 4, ! TIDAL diagnostics (multiple variables) + +! --- FORCING DIAGNOSTICS (require ldiag_forc=.true.) --- +! 'FORC ',1, 'm', 4, ! forcing diagnostics (multiple variables) + +! --- DISCRETE VARIANCE DECAY (require ldiag_DVD=.true.) --- +! 'DVD ',1, 'm', 4, ! DVD diagnostics (multiple variables) + +! --- SPLIT-EXPLICIT SUBCYCLING (require dynamics%use_ssh_se_subcycl=.true.) --- +! 'SPLIT-EXPL',1, 'm', 4, ! split-explicit diagnostics (multiple variables) + +! --- SQUARED VELOCITIES (require ldiag_uvw_sqr=.true.) --- +! 'UVW_SQR ',1, 'm', 4, ! squared velocities (u2, v2, w2) + +! --- TRACER GRADIENTS (require ldiag_trgrd_xyz=.true.) --- +! 'TRGRD_XYZ ',1, 'm', 4, ! horizontal and vertical tracer gradients + +! --- CMOR DIAGNOSTICS FOR CMIP6/CMIP7 (require ldiag_cmor=.true.) --- +! 'tos ',1, 'm', 8, ! sea surface temperature [degC] (CMOR standard) +! 'sos ',1, 'm', 8, ! sea surface salinity [psu] (CMOR standard) +! 'pbo ',1, 'm', 8, ! sea water pressure at sea floor [Pa] +! 'opottemptend',1, 'm', 8,! ocean potential temperature tendency [W/m^2] +! 'volo ',1, 'm', 8, ! ocean volume [m^3] (global scalar) +! 'soga ',1, 'm', 8, ! global mean sea water salinity [psu] (global scalar) +! 'thetaoga ',1, 'm', 8, ! global mean sea water potential temperature [degC] (global scalar) +! 'siarean ',1, 'm', 8, ! sea ice area Northern hemisphere [10^12 m^2] (global scalar) +! 'siareas ',1, 'm', 8, ! sea ice area Southern hemisphere [10^12 m^2] (global scalar) +! 'siextentn ',1, 'm', 8, ! sea ice extent Northern hemisphere [10^12 m^2] (global scalar) +! 'siextents ',1, 'm', 8, ! sea ice extent Southern hemisphere [10^12 m^2] (global scalar) +! 'sivoln ',1, 'm', 8, ! sea ice volume Northern hemisphere [10^9 m^3] (global scalar) +! 'sivols ',1, 'm', 8, ! sea ice volume Southern hemisphere [10^9 m^3] (global scalar) + +! ============================================================================ +! END OF CATALOG +! ============================================================================ diff --git a/config/bin_2p3z2d/namelist.io_old b/config/bin_2p3z2d/namelist.io_old new file mode 100644 index 000000000..10bb72c1b --- /dev/null +++ b/config/bin_2p3z2d/namelist.io_old @@ -0,0 +1,83 @@ +&diag_list +ldiag_solver =.false. +lcurt_stress_surf=.false. +ldiag_curl_vel3 =.false. +ldiag_Ri =.false. +ldiag_turbflux =.false. +ldiag_salt3D =.false. +ldiag_dMOC =.false. +ldiag_DVD =.false. +ldiag_forc =.false. +ldiag_extflds =.false. +/ + +&nml_general +io_listsize =150 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list +vec_autorotate =.false. +/ + +! for sea ice related variables use_ice should be true, otherewise there will be no output +! for 'curl_surf' to work lcurt_stress_surf must be .true. otherwise no output +! for 'fer_C', 'bolus_u', 'bolus_v', 'bolus_w', 'fer_K' to work Fer_GM must be .true. otherwise no output +! 'otracers' - all other tracers if applicable +! for 'dMOC' to work ldiag_dMOC must be .true. otherwise no output +&nml_list +io_list = 'sst ',1, 'm', 4, + 'sss ',1, 'm', 4, + 'ssh ',1, 'm', 4, + 'uice ',1, 'm', 4, + 'vice ',1, 'm', 4, + 'a_ice ',1, 'm', 4, + 'm_ice ',1, 'm', 4, + 'm_snow ',1, 'm', 4, + 'MLD1 ',1, 'm', 4, + 'MLD2 ',1, 'm', 4, + 'MLD3 ',1, 'm', 4, + 'tx_sur ',1, 'm', 4, + 'ty_sur ',1, 'm', 4, + 'temp ',1, 'm', 4, + 'salt ',1, 'm', 8, + 'otracers ',1, 'm', 4, + 'N2 ',1, 'y', 4, + 'Kv ',1, 'y', 4, + 'u ',1, 'm', 4, + 'v ',1, 'm', 4, + 'unod ',1, 'm', 4, + 'vnod ',1, 'm', 4, + 'w ',1, 'm', 4, + 'Av ',1, 'y', 4, + 'bolus_u ',1, 'y', 4, + 'bolus_v ',1, 'y', 4, + 'bolus_w ',1, 'y', 4, + 'dpCO2s ',1, 'm', 4, + 'pCO2s ',1, 'm', 4, + 'CO2f ',1, 'm', 4, + 'Hp ',1, 'm', 4, + 'aFe ',1, 'm', 4, + 'aN ',1, 'm', 4, + 'denb ',1, 'm', 4, + 'benN ',1, 'm', 4, + 'benC ',1, 'm', 4, + 'benSi ',1, 'm', 4, + 'benCalc ',1, 'm', 4, + 'Chldegd ',1, 'm', 4, + 'Chldegn ',1, 'm', 4, + 'NNAd ',1, 'm', 4, + 'NNAn ',1, 'm', 4, + 'GPPd ',1, 'm', 4, + 'GPPn ',1, 'm', 4, + 'NPPd ',1, 'm', 4, + 'NPPn ',1, 'm', 4, + 'PAR ',1, 'm', 4, + 'respmeso',1, 'm', 4, + 'respmacro',1, 'm', 4, + 'respmicro',1, 'm', 4, + 'calcdiss',1, 'm', 4, + 'calcif',1, 'm', 4, + 'aggn',1, 'm', 4, + 'aggd',1, 'm', 4, + 'docexn',1, 'm', 4, + 'docexd',1, 'm', 4, + 'respn',1, 'm', 4, + 'respd',1, 'm', 4, +/ diff --git a/config/bin_2p3z2d/namelist.oce b/config/bin_2p3z2d/namelist.oce index 7af6867f7..955f06cbb 100644 --- a/config/bin_2p3z2d/namelist.oce +++ b/config/bin_2p3z2d/namelist.oce @@ -1,26 +1,76 @@ -! The namelist file for the finite-volume ocean model +! ============================================================================ +! ============ Namelist file for FESOM2 ocean dynamics ====================== +! ============================================================================ +! This file contains configuration for ocean dynamics and parameterizations: +! - Bottom drag and vertical viscosity +! - Gent-McWilliams (GM) eddy parameterization +! - Redi isopycnal diffusion +! - Vertical mixing schemes (KPP, PP) +! - Convection parameters +! - Tidal forcing +! ============================================================================ +! ============================================================================ +! OCEAN DYNAMICS AND PARAMETERIZATIONS +! ============================================================================ &oce_dyn -C_d=0.0025 ! Bottom drag, nondimensional -A_ver= 1.e-4 ! Vertical viscosity, m^2/s -scale_area=5.8e9 ! Visc. and diffus. are for an element with scale_area -SPP=.false. ! Salt Plume Parameterization -Fer_GM=.true. ! to swith on/off GM after Ferrari et al. 2010 -K_GM_max = 2000.0 ! max. GM thickness diffusivity (m2/s) -K_GM_min = 2.0 ! max. GM thickness diffusivity (m2/s) -K_GM_bvref = 2 ! def of bvref in ferreira scaling 0=srf,1=bot mld,2=mean over mld,3=weighted mean over mld -K_GM_rampmax = -1.0 ! Resol >K_GM_rampmax[km] GM on -K_GM_rampmin = -1.0 ! Resol K_GM_rampmax[km] GM on +K_GM_rampmin = -1.0 ! Resol K_GM_rampmax[km] GM on +K_GM_rampmin = -1.0 ! Resol 4th order, =0.0 --> 3rd order, =0.5 --> mixed 3rd&4th order +! ============================================================================ +! nml_tracer_list = +! idx, hor. Adv, vert. Adv., use FCT, hor.Ord., vert. Ord. +! 1 , 'MFCT' , 'QR4C' , 'FCT ' , 1. , 1. , ! temperature +! 2 , 'MFCT' , 'QR4C' , 'FCT ' , 1. , 1. , ! salinity +!101 , 'UPW1' , 'UPW1' , 'NON ' , 0. , 0. ! example passive tracer &tracer_list -nml_tracer_list = -1 , 'MFCT', 'QR4C', 'FCT ', 1., 1., -2 , 'MFCT', 'QR4C', 'FCT ', 1., 1., -1001, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1002, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1003, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1004, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1005, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1006, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1007, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1008, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1009, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1010, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1011, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1012, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1013, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1014, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1015, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1016, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1017, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1018, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1019, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1020, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1021, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1022, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1023, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1024, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1025, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1026, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1027, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1028, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1029, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1030, 'MFCT', 'QR4C', 'FCT ', 1., 1., -!1031, 'MFCT', 'QR4C', 'FCT ', 1., 1., -!1032, 'MFCT', 'QR4C', 'FCT ', 1., 1., -!1033, 'MFCT', 'QR4C', 'FCT ', 1., 1., -!101, 'UPW1', 'UPW1', 'NON ', 0., 0. +nml_tracer_list = +1 , 'MFCT', 'QR4C', 'FCT ', 0., 1., +2 , 'MFCT', 'QR4C', 'FCT ', 0., 1., +1001, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1002, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1003, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1004, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1005, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1006, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1007, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1008, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1009, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1010, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1011, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1012, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1013, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1014, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1015, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1016, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1017, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1018, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1019, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1020, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1021, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1022, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1023, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1024, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1025, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1026, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1027, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1028, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1029, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1030, 'MFCT', 'QR4C', 'FCT ', 0., 1., / -&tracer_init3d ! initial conditions for tracers -n_ic3d = 8 ! number of tracers to initialize -idlist = 1019, 1022, 1018, 1003, 1002, 1001, 2, 1 ! their IDs (0 is temperature, 1 is salinity, etc.). The reading order is defined here! -filelist = 'fe_pisces_opa_eq_init_3D_changed_name.nc', 'woa18_all_o00_01_mmol_fesom2.nc', 'woa13_all_i00_01_fesom2.nc', 'GLODAPv2.2016b.TAlk_fesom2_mmol_fix_z_Fillvalue.nc', 'GLODAPv2.2016b.TCO2_fesom2_mmol_fix_z_Fillvalue.nc', 'woa13_all_n00_01_fesom2.nc', 'phc3.0_winter.nc', 'phc3.0_winter.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist -varlist = 'Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp' ! variables to read from specified files -t_insitu = .true. ! if T is insitu it will be converted to potential after reading it +! ============================================================================ +! 3D TRACER INITIAL CONDITIONS (OCEAN) +! ============================================================================ +&tracer_init3d +n_ic3d = 8 ! number of 3D tracers to initialize from files +idlist = 1, 2, ! tracer IDs to initialize (1=temperature, 2=salinity) + 1001, ! nitrate in seawater + 1002, ! dissolved inorganic carbon in seawater + 1003, ! seawater alkalinity + 1018, ! silicate in seawater + 1019, ! iron in seawater + 1022, ! dissolved molecular oxygen in seawater +filelist = 'phc3.0_winter.nc', 'phc3.0_winter.nc', ! netCDF files in ClimateDataPath (one per tracer) + 'woa13_all_n00_01_fesom2.nc' ! 1001 + 'GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc', ! 1002; for today: GLODAPv2.2016b.TCO2_fesom2_mmol_fix_z_Fillvalue.nc; for PI: GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc + 'GLODAPv2.2016b.TAlk_fesom2_mmol_fix_z_Fillvalue.nc', ! 1003 + 'woa13_all_i00_01_fesom2.nc', ! 1018 + 'fe_pisces_opa_eq_init_3D_changed_name.nc', ! 1019 + 'woa18_all_o00_01_mmol_fesom2.nc', ! 1022 +varlist = 'temp', 'salt', ! variable names in the netCDF files + 'n_an' ! 1001 + 'PI_TCO2_mmol', ! 1002; for today: TCO2_mmol; for PI: PI_TCO2_mmol + 'TAlk_mmol', ! 1003 + 'i_an', ! 1018 + 'Fe', ! 1019 + 'oxygen_mmol', ! 1022 +t_insitu = .true. ! if true, convert in-situ temperature to potential temperature / -&tracer_init2d ! initial conditions for 2D tracers (sea ice) -n_ic2d = 3 ! number of tracers to initialize -idlist = 1, 2, 3 ! their IDs (0 is a_ice, 1 is m_ice, 3 m_snow). The reading order is defined here! -filelist = 'a_ice.nc', 'm_ice.nc', 'm_snow.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist -varlist = 'a_ice', 'm_ice', 'm_snow' ! variables to read from specified files -ini_ice_from_file=.false. +! ============================================================================ +! 2D TRACER INITIAL CONDITIONS (SEA ICE) +! ============================================================================ +&tracer_init2d +n_ic2d = 3 ! number of 2D tracers to initialize from files +idlist = 1, 2, 3 ! tracer IDs (1=ice concentration, 2=ice thickness, 3=snow thickness) +filelist = 'a_ice.nc', 'm_ice.nc', 'm_snow.nc' ! netCDF files in ClimateDataPath +varlist = 'a_ice', 'm_ice', 'm_snow' ! variable names in the netCDF files +ini_ice_from_file = .false. ! enable initialization from files (false = use default values) / +! ============================================================================ +! TRACER GENERAL SETTINGS +! ============================================================================ &tracer_general -! bharmonic diffusion for tracers. We recommend to use this option in very high resolution runs (Redi is generally off there). -smooth_bh_tra =.false. ! use biharmonic diffusion (filter implementation) for tracers -gamma0_tra = 0.0005 ! gammaX_tra are analogous to those in the dynamical part -gamma1_tra = 0.0125 -gamma2_tra = 0. -i_vert_diff =.true. +! --- Biharmonic Diffusion --- +! Recommended for very high resolution runs (where Redi is typically disabled) +smooth_bh_tra = .false. ! enable biharmonic diffusion (filter implementation) for tracers +gamma0_tra = 0.0005 ! background biharmonic diffusion coefficient [dimensionless] +gamma1_tra = 0.0125 ! flow-aware biharmonic diffusion coefficient [dimensionless] +gamma2_tra = 0. ! additional biharmonic diffusion coefficient [dimensionless] + +! --- Vertical Diffusion and Time Stepping --- +i_vert_diff = .true. ! use implicit vertical diffusion (recommended for stability) +AB_order = 2 ! Adams-Bashforth time stepping order (2 or 3) / +! ============================================================================ +! TRACER PHYSICS AND PARAMETERIZATIONS +! ============================================================================ &tracer_phys -use_momix = .true. ! switch on/off !Monin-Obukhov -> TB04 mixing -momix_lat = -50.0 ! latitidinal treshhold for TB04, =90 --> global -momix_kv = 0.01 ! PP/KPP, mixing coefficient within MO length -use_instabmix = .true. ! enhance convection in case of instable stratification -instabmix_kv = 0.1 -use_windmix = .false. ! enhance mixing trough wind only for PP mixing (for stability) -windmix_kv = 1.e-3 -windmix_nl = 2 -diff_sh_limit=5.0e-3 ! for KPP, max diff due to shear instability -Kv0_const=.true. -double_diffusion=.false. ! for KPP,dd switch -K_ver=1.0e-5 -K_hor=3000. -surf_relax_T=0.0 -surf_relax_S=1.929e-06 ! 50m/300days 6.43e-07! m/s 10./(180.*86400.) -balance_salt_water =.true. ! balance virtual-salt or freshwater flux or not -clim_relax=0.0 ! 1/s, geometrical information has to be supplied -ref_sss_local=.true. -ref_sss=34. +! --- Monin-Obukhov Mixing (TB04) --- +use_momix = .false. ! enable Monin-Obukhov mixing (Timmermann & Beckmann 2004) +momix_lat = -50.0 ! latitude threshold for TB04 [degrees] (90 = global, -50 = south of 50°S) +momix_kv = 0.01 ! mixing coefficient within MO length [m²/s] + +! --- Convective Instability Mixing --- +use_instabmix = .true. ! enhance mixing for unstable stratification (convection) +instabmix_kv = 0.1 ! mixing coefficient for unstable stratification [m²/s] + +! --- Wind Mixing (PP scheme only) --- +use_windmix = .false. ! enhance near-surface mixing by wind (for PP mixing stability) +windmix_kv = 1.e-3 ! wind mixing coefficient [m²/s] +windmix_nl = 2 ! number of surface layers for wind mixing + +! --- Shear Instability (KPP) --- +diff_sh_limit = 5.0e-3 ! maximum diffusivity due to shear instability [m²/s] (for KPP) + +! --- Background Diffusivity --- +Kv0_const = .true. ! use constant background vertical diffusivity +K_ver = 1.0e-5 ! background vertical diffusivity [m²/s] +K_hor = 0. ! background horizontal diffusivity [m²/s] + +! --- Double Diffusion (KPP) --- +double_diffusion = .false. ! enable double diffusion parameterization (for KPP) + +! --- Surface Restoring --- +surf_relax_T = 0.0 ! surface temperature restoring coefficient [m/s] (0 = disabled) +surf_relax_S = 1.929e-06 ! surface salinity restoring coefficient [m/s] +balance_salt_water = .true. ! balance virtual salt flux with freshwater flux + +! --- Climatology Restoring --- +clim_relax = 0.0 ! 3D climatology restoring coefficient [1/s] (0 = disabled) + +! --- Reference Salinity --- +ref_sss_local = .true. ! use local reference SSS (true) or global constant (false) +ref_sss = 34. ! global reference salinity [psu] (if ref_sss_local=false) / diff --git a/config/bin_2p3z2d/namelist.tra_old b/config/bin_2p3z2d/namelist.tra_old new file mode 100644 index 000000000..d1733bb91 --- /dev/null +++ b/config/bin_2p3z2d/namelist.tra_old @@ -0,0 +1,90 @@ +&tracer_listsize +num_tracers=100 !number of tracers to allocate. shallbe large or equal to the number of streams in &nml_list +/ + +&tracer_list +nml_tracer_list = +1 , 'MFCT', 'QR4C', 'FCT ', 1., 1., +2 , 'MFCT', 'QR4C', 'FCT ', 1., 1., +1001, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1002, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1003, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1004, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1005, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1006, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1007, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1008, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1009, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1010, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1011, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1012, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1013, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1014, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1015, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1016, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1017, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1018, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1019, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1020, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1021, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1022, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1023, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1024, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1025, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1026, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1027, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1028, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1029, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1030, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1031, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1032, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1033, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!101, 'UPW1', 'UPW1', 'NON ', 0., 0. +/ + +&tracer_init3d ! initial conditions for tracers +n_ic3d = 8 ! number of tracers to initialize +idlist = 1019, 1022, 1018, 1003, 1002, 1001, 2, 1 ! their IDs (0 is temperature, 1 is salinity, etc.). The reading order is defined here! +filelist = 'fe_pisces_opa_eq_init_3D_changed_name.nc', 'woa18_all_o00_01_mmol_fesom2.nc', 'woa13_all_i00_01_fesom2.nc', 'GLODAPv2.2016b.TAlk_fesom2_mmol_fix_z_Fillvalue.nc', 'GLODAPv2.2016b.TCO2_fesom2_mmol_fix_z_Fillvalue.nc', 'woa13_all_n00_01_fesom2.nc', 'phc3.0_winter.nc', 'phc3.0_winter.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist +varlist = 'Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp' ! variables to read from specified files +t_insitu = .true. ! if T is insitu it will be converted to potential after reading it +/ + +&tracer_init2d ! initial conditions for 2D tracers (sea ice) +n_ic2d = 3 ! number of tracers to initialize +idlist = 1, 2, 3 ! their IDs (0 is a_ice, 1 is m_ice, 3 m_snow). The reading order is defined here! +filelist = 'a_ice.nc', 'm_ice.nc', 'm_snow.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist +varlist = 'a_ice', 'm_ice', 'm_snow' ! variables to read from specified files +ini_ice_from_file=.false. +/ + +&tracer_general +! bharmonic diffusion for tracers. We recommend to use this option in very high resolution runs (Redi is generally off there). +smooth_bh_tra =.false. ! use biharmonic diffusion (filter implementation) for tracers +gamma0_tra = 0.0005 ! gammaX_tra are analogous to those in the dynamical part +gamma1_tra = 0.0125 +gamma2_tra = 0. +i_vert_diff =.true. +/ + +&tracer_phys +use_momix = .true. ! switch on/off !Monin-Obukhov -> TB04 mixing +momix_lat = -50.0 ! latitidinal treshhold for TB04, =90 --> global +momix_kv = 0.01 ! PP/KPP, mixing coefficient within MO length +use_instabmix = .true. ! enhance convection in case of instable stratification +instabmix_kv = 0.1 +use_windmix = .false. ! enhance mixing trough wind only for PP mixing (for stability) +windmix_kv = 1.e-3 +windmix_nl = 2 +diff_sh_limit=5.0e-3 ! for KPP, max diff due to shear instability +Kv0_const=.true. +double_diffusion=.false. ! for KPP,dd switch +K_ver=1.0e-5 +K_hor=3000. +surf_relax_T=0.0 +surf_relax_S=1.929e-06 ! 50m/300days 6.43e-07! m/s 10./(180.*86400.) +balance_salt_water =.true. ! balance virtual-salt or freshwater flux or not +clim_relax=0.0 ! 1/s, geometrical information has to be supplied +ref_sss_local=.true. +ref_sss=34. +/ diff --git a/src/gen_ic3d.F90 b/src/gen_ic3d.F90 index 67a3f7d1e..bd285494e 100644 --- a/src/gen_ic3d.F90 +++ b/src/gen_ic3d.F90 @@ -251,8 +251,8 @@ SUBROUTINE nc_ic3d_ini(partit, mesh) warn = 0 if (mype==0) then - write(*,*) 'reading ', trim(filename) - write(*,*) 'variable : ', trim(varname) + write(*,*) 'variable ', trim(varname) + write(*,*) 'from ', trim(filename) end if call nc_readGrid(partit) @@ -538,7 +538,7 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) type(t_mesh), intent(in), target :: mesh type(t_partit), intent(inout), target :: partit type(t_tracer), intent(inout), target :: tracers - integer :: n, i + integer :: n, i, id real(kind=WP) :: locTmax, locTmin, locSmax, locSmin, glo real(kind=WP) :: locDINmax, locDINmin, locDICmax, locDICmin, locAlkmax !OG real(kind=WP) :: locAlkmin, locDSimax, locDSimin, locDFemax, locDFemin @@ -621,41 +621,11 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) locTmin = 6666 locSmax = locTmax locSmin = locTmin - -#if defined(__recom) - locDINmax = -66666 - locDINmin = 66666 - locDICmax = locDINmax - locDICmin = locDINmin - locAlkmax = locDINmax - locAlkmin = locDINmin - locDSimax = locDINmax - locDSimin = locDINmin - locDFemax = locDINmax - locDFemin = locDINmin - locO2max = locDINmax - locO2min = locDINmin -#endif do n=1, partit%myDim_nod2d locTmax = max(locTmax,maxval(tracers%data(1)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) locTmin = min(locTmin,minval(tracers%data(1)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) locSmax = max(locSmax,maxval(tracers%data(2)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) locSmin = min(locSmin,minval(tracers%data(2)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - -#if defined(__recom) - locDINmax = max(locDINmax,maxval(tracers%data(3)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locDINmin = min(locDINmin,minval(tracers%data(3)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locDICmax = max(locDICmax,maxval(tracers%data(4)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locDICmin = min(locDICmin,minval(tracers%data(4)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locAlkmax = max(locAlkmax,maxval(tracers%data(5)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locAlkmin = min(locAlkmin,minval(tracers%data(5)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locDSimax = max(locDSimax,maxval(tracers%data(20)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locDSimin = min(locDSimin,minval(tracers%data(20)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locDFemax = max(locDFemax,maxval(tracers%data(21)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locDFemin = min(locDFemin,minval(tracers%data(21)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locO2max = max(locO2max,maxval(tracers%data(24)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) - locO2min = min(locO2min,minval(tracers%data(24)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) -#endif end do call MPI_AllREDUCE(locTmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, partit%MPI_COMM_FESOM, partit%MPIerr) if (partit%mype==0) write(*,*) ' |-> gobal max init. temp. =', glo @@ -665,14 +635,60 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) if (partit%mype==0) write(*,*) ' |-> gobal max init. salt. =', glo call MPI_AllREDUCE(locSmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, partit%MPI_COMM_FESOM, partit%MPIerr) if (partit%mype==0) write(*,*) ' `-> gobal min init. salt. =', glo -#if defined(__recom) +#if defined(__recom) + locDINmax = -66666 + locDINmin = 66666 + locDICmax = locDINmax + locDICmin = locDINmin + locAlkmax = locDINmax + locAlkmin = locDINmin + locDSimax = locDINmax + locDSimin = locDINmin + locDFemax = locDINmax + locDFemin = locDINmin + locO2max = locDINmax + locO2min = locDINmin + do i=3, tracers%num_tracers + id=tracers%data(i)%ID + SELECT CASE (id) + CASE (1001) ! din + do n=1, partit%myDim_nod2d + locDINmax = max(locDINmax,maxval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDINmin = min(locDINmin,minval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + end do + CASE (1002) ! dic + do n=1, partit%myDim_nod2d + locDICmax = max(locDICmax,maxval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDICmin = min(locDICmin,minval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + end do + CASE (1003) ! alk + do n=1, partit%myDim_nod2d + locAlkmax = max(locAlkmax,maxval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locAlkmin = min(locAlkmin,minval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + end do + CASE (1018) ! si + do n=1, partit%myDim_nod2d + locDSimax = max(locDSimax,maxval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDSimin = min(locDSimin,minval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + end do + CASE (1019) ! fe + do n=1, partit%myDim_nod2d + locDFemax = max(locDFemax,maxval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDFemin = min(locDFemin,minval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + end do + CASE (1022) ! o2 + do n=1, partit%myDim_nod2d + locO2max = max(locO2max,maxval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locO2min = min(locO2min,minval(tracers%data(i)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + end do + END SELECT + end do ! i num_tracers if (partit%mype==0) write(*,*) "Sanity check for REcoM variables" call MPI_AllREDUCE(locDINmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, partit%MPI_COMM_FESOM, partit%MPIerr) if (partit%mype==0) write(*,*) ' |-> gobal max init. DIN. =', glo call MPI_AllREDUCE(locDINmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, partit%MPI_COMM_FESOM, partit%MPIerr) if (partit%mype==0) write(*,*) ' |-> gobal min init. DIN. =', glo - call MPI_AllREDUCE(locDICmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, partit%MPI_COMM_FESOM, partit%MPIerr) if (partit%mype==0) write(*,*) ' |-> gobal max init. DIC. =', glo call MPI_AllREDUCE(locDICmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, partit%MPI_COMM_FESOM, partit%MPIerr) diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 166607550..1f9617f3e 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -3002,7 +3002,6 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) else entry%local_values_r8_copy(I,J) = entry%local_values_r8(I,J) /real(entry%addcounter,real64) ! compute_means end if -#endif entry%local_values_r8(I,J) = 0._real64 ! clean_meanarrays - reset to 0 for next accumulation END DO ! --> DO I=1, nlev_loc END DO ! --> DO J=1, size(entry%local_values_r8,dim=2) @@ -3022,7 +3021,6 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) else entry%local_values_r4_copy(I,J) = entry%local_values_r4(I,J) /real(entry%addcounter,real32) ! compute_means end if -#endif entry%local_values_r4(I,J) = 0._real32 ! clean_meanarrays - reset to 0 for next accumulation END DO ! --> DO I=1, nlev_loc END DO ! --> DO J=1, size(entry%local_values_r4,dim=2) diff --git a/src/oce_setup_step.F90 b/src/oce_setup_step.F90 index 48a5c84a1..b5aaf00d6 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -1080,7 +1080,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) type(t_partit), intent(inout), target :: partit type(t_mesh), intent(in) , target :: mesh !___________________________________________________________________________ - integer :: i, k, counter, rcounter3, id + integer :: i, k, counter, rcounter3, id, alk_check character(len=10) :: i_string, id_string real(kind=WP) :: loc, max_temp, min_temp, max_salt, min_salt !___________________________________________________________________________ @@ -1095,54 +1095,17 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) if (mype==0) write(*,*) 'tracer IDs are: ', tracers%data(1:tracers%num_tracers)%ID ! #if defined(__recom) - ! read preindustrial DIC - if(DIC_PI) then - filelist(5) = 'GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc' - varlist(5) = 'PI_TCO2_mmol' - end if - if (mype==0) then - write(*,*) - print *, achar(27)//'[36m'//'*************************'//achar(27)//'[0m' - print *, achar(27)//'[36m'//' --> RECOM ON'//achar(27)//'[0m' - if (ciso) then - print *, achar(27)//'[36m'//' --> CISO ON'//achar(27)//'[0m' - else - print *, achar(27)//'[36m'//' --> CISO OFF'//achar(27)//'[0m' - endif - if(DIC_PI) then - print *, achar(27)//'[36m'// ' --> Preindustrial DIC will be used'//achar(27)//'[0m' - end if - if (restore_alkalinity) then - print *, achar(27)//'[36m'//' --> Alkalinity restoring = .true.'//achar(27)//'[0m' - endif - print *, achar(27)//'[36m'//'*************************'//achar(27)//'[0m' - write(*,*) - write(*,*) 'read Iron climatology from:', trim(filelist(1)) - write(*,*) 'read Oxygen climatology from:', trim(filelist(2)) - write(*,*) 'read Silicate climatology from:', trim(filelist(3)) - write(*,*) 'read Alkalinity climatology from:', trim(filelist(4)) - write(*,*) 'read DIC climatology from:', trim(filelist(5)) - write(*,*) 'read Nitrate climatology from:', trim(filelist(6)) - write(*,*) 'read Salt climatology from:', trim(filelist(7)) - write(*,*) 'read Temperature climatology from:', trim(filelist(8)) + write(*,*) + print *, achar(27)//'[36m'//'*************************'//achar(27)//'[0m' + print *, achar(27)//'[36m'//' --> RECOM ON'//achar(27)//'[0m' + if (ciso) then + print *, achar(27)//'[36m'//' --> CISO ON'//achar(27)//'[0m' + else + print *, achar(27)//'[36m'//' --> CISO OFF'//achar(27)//'[0m' + endif + print *, achar(27)//'[36m'//'*************************'//achar(27)//'[0m' end if - ! read ocean state - ! this must be always done! First two tracers with IDs 0 and 1 are the temperature and salinity. -! if(mype==0) write(*,*) 'read Iron climatology from:', trim(filelist(1)) -! if(mype==0) write(*,*) 'read Oxygen climatology from:', trim(filelist(2)) -! if(mype==0) write(*,*) 'read Silicate climatology from:', trim(filelist(3)) -! if(mype==0) write(*,*) 'read Alkalinity climatology from:', trim(filelist(4)) -! if(mype==0) write(*,*) 'read DIC climatology from:', trim(filelist(5)) -! if(mype==0) write(*,*) 'read Nitrate climatology from:', trim(filelist(6)) -! if(mype==0) write(*,*) 'read Salt climatology from:', trim(filelist(7)) -! if(mype==0) write(*,*) 'read Temperature climatology from:', trim(filelist(8)) -#else - ! read ocean state - ! this must be always done! First two tracers with IDs 0 and 1 are the temperature and salinity. - if(mype==0) write(*,*) 'read Temperature climatology from:', trim(filelist(1)) - if(mype==0) write(*,*) 'read Salinity climatology from:', trim(filelist(2)) - #endif if(any(idlist == 14) .and. mype==0) write(*,*) 'read radiocarbon climatology from:', trim(filelist(3)) call do_ic3d(tracers, partit, mesh) @@ -1162,12 +1125,26 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) #if defined(__recom) if (restore_alkalinity) then - if (mype==0) write(*,*) - if (mype==0) print *, achar(27)//'[46;1m'//' --> Set surface field for alkalinity restoring'//achar(27)//'[0m' - if (mype==0) write(*,*) - Alk_surf = tracers%data(5)%values(1,:) ! alkalinity is the 5th tracer - endif - + if (mype==0) then + write(*,*) + print *, achar(27)//'[46;1m'//' restore_alkalinity is true --> Set surface field for alkalinity restoring'//achar(27)//'[0m' + write(*,*) + end if + alk_check=1 + do i=3, tracers%num_tracers + id=tracers%data(i)%ID + SELECT CASE (id) + CASE (1003) ! alk + Alk_surf = tracers%data(i)%values(1,:) ! surface alkalinity + alk_check = 0 + END SELECT + end do + if (alk_check /= 0) then + if (mype==0) write(*,*) 'not a single tracer ID = 1003 = alkalinity. this should not happen' + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + end if + endif ! restore_alkalinity #endif ! count the passive tracers which require 3D source (ptracers_restore_total) From 7bbb455b3b2f34c1196270a99441b1e8db131af5 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Tue, 30 Jun 2026 00:18:34 +0200 Subject: [PATCH 19/23] io_meandata: route REcoM/BGC fields through XIOS + fix otracers labels - Register the two name-dispatched diagnostics xCO2atm and NPPn3D in the XIOS xios_ids list (they were the only ones missing). - Add 3D carbonate-system output (CO2_aq, pH, pCO2, HCO3, CO3, OmegaC) computed by MOCSY: def_stream + CASE + xios_ids, native units. - WI-5: dispatch the otracers prognostic tracers by symbolic tracer_ids%* instead of hardcoded absolute ids. The literals assumed the full config, so for coccos-off setups (e.g. 2p3z2d) microzoo (1029/1030) was mislabelled CoccoN/CoccoC. Now correct for every &parecomsetup (also fixes the legacy serial output). Requires the recom submodule's -1 sentinel defaults (bumped here). - Register the phaeocystis and T* physiology diagnostics in xios_ids so they are sendable; their output stays gated in file_def. Also carries the in-progress __MULTIO mean-computation guard in the wet/dry masking loops. --- src/io_meandata.F90 | 92 +++++++++++++++++++++++++++++++++++---------- src/recom | 2 +- 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 166607550..0297dd2e5 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -216,6 +216,7 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) use recom_glovar use recom_config use recom_ciso + use recom_declarations, only: tracer_ids ! symbolic tracer ids (config-aware), see WI-5 #endif use g_forcing_param, only: use_virt_salt, use_landice_water, use_age_tracer !---fwf-code, age-code use g_config, only : use_cavity, lwiso !---wiso-code @@ -274,7 +275,7 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) "benSi ", "beta ", "bolus_u ", & "bolus_v ", "bolus_w ", "calcdiss ", & "calcif ", "cfl_z ", "Chldegc ", & - "Chldegd ", "Chldegn ", "CO2f ", & + "Chldegd ", "Chldegn ", "CO2_aq ", "CO2f ", "CO3 ", & "curl_surf ", "dens_flux ", "d_eta ", & "dhe ", "dMOC ", "docexc ", & "docexd ", "docexn ", "dpCO2s ", & @@ -291,7 +292,7 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) "GPPn ", "h2o16 ", "h2o16_ice ", & "h2o18 ", "h2o18_ice ", "hbar ", & "hbar_old ", "hc ", "hc300m ", & - "hc700m ", "hDo16 ", "hDo16_ice ", & + "hc700m ", "HCO3 ", "hDo16 ", "hDo16_ice ", & "helem ", "h_ice ", "hnode ", & "hnode_new ", "Hp ", "hpnd ", & "h_snow ", "icb ", "iceoce_x ", & @@ -303,11 +304,11 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) "MLD3 ", "m_snow ", "N2 ", & "NNAc ", "NNAd ", "NNAn ", & "NPPc ", "NPPc3D ", "NPPd ", & - "NPPd3D ", "NPPn ", "O2f ", & + "NPPd3D ", "NPPn ", "NPPn3D ", "O2f ", "OmegaC ", & "opottempdiff ", "opottemprmadvect ", "opottemptend ", & "osaltdiff ", "osaltrmadvect ", "osalttend ", & - "otracers ", "PAR ", "pbo ", & - "pCO2s ", "pgf_x ", "pgf_y ", & + "otracers ", "PAR ", "pbo ", "pCO2 ", & + "pCO2s ", "pgf_x ", "pgf_y ", "pH ", & "prec ", "qcon ", "qres ", & "qsi ", "qso ", "qsr ", & "realsalt ", "redi_K ", "relaxsalt ", & @@ -339,7 +340,18 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) "virtsalt ", "vnod ", "vnod_sfc ", & "volo ", & "v_rhs_ice ", "v_total_tend ", "vve_5 ", & - "vwice ", "vwind ", "w " /) + "vwice ", "vwind ", "w ", & + "xCO2atm ", & + ! WI-2: phaeocystis + T* physiology diagnostics. Registered here so XIOS + ! can send them; their actual output is gated in file_def_fesom.xml.j2 + ! (coccos for phaeo*, ltra_diag for the T* family). + "NPPp", "NPPp3D", "GPPp", "NNAp", "Chldegp", & + "TPhyCO2", "TDiaCO2", "TCoccoCO2", "TPhaeoCO2", & + "TCphot_phyto", "TCphot_diatoms", "TCphot_cocco", "TCphot_phaeo", & + "TCphotLL_phyto", "TCphotLL_dia", "TCphotLL_cocco", "TCphotLL_phaeo", & + "TqLF_phyto", "TqLF_diatoms", "TqLF_cocco", "TqLF_phaeo", & + "TTemp_phyto", "TTemp_diatoms", "TTemp_cocco", "TTemp_phaeo", & + "TSi_assimDia" /) integer :: k if (mype==0) WRITE(*,*) 'XIOS mode: skipping namelist.io; registering all ', & size(xios_ids), ' known streams. XML decides output.' @@ -1130,6 +1142,40 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'NPPp3D','Net primary production of phaeocystis', 'mmolC/(m2*d)', NPPp3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! Phaeocystis endif +!_______________________________________________________________________________ +! WI-4: 3D carbonate-system fields (MOCSY). Computed every step in recom_main but +! previously not output. Units verbatim from the REcoM_GloVar declarations so XIOS +! output is directly comparable to the legacy serial output. +CASE ('CO2_aq ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CO2_aq', 'Aqueous CO2 concentration (MOCSY)', '[mol/m3]', CO23D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('pH ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'pH', 'pH on total scale (MOCSY)', 'total_scale', pH3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('pCO2 ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'pCO2', 'CO2 partial pressure (MOCSY)', 'uatm', pCO23D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('HCO3 ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'HCO3', 'Bicarbonate ion concentration (MOCSY)', '[mol/m3]', HCO33D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('CO3 ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CO3', 'Carbonate ion concentration', '[mol/m3]', CO33D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('OmegaC ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'OmegaC', 'Calcite saturation state', 'none', OmegaC3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + CASE ('TTemp_diatoms ') if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'TTemp_diatoms','Temperature dependence of diatoms PS', 'per day',TTemp_diatoms(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -1383,72 +1429,72 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'O2', 'O2', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1023) then + else if (tracers%data(j)%ID==tracer_ids%macrozooplankton_nitrogen) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo2N', 'Intracellular conc of Nitrogen in second zooplankton', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1024) then + else if (tracers%data(j)%ID==tracer_ids%macrozooplankton_carbon) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo2C', 'Intracellular conc of Carbon in second zooplankton', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1025) then + else if (tracers%data(j)%ID==tracer_ids%macrozooplankton_detrital_nitrogen) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'idetz2n', 'idetz2n', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1026) then + else if (tracers%data(j)%ID==tracer_ids%macrozooplankton_detrital_carbon) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'idetz2c', 'idetz2c', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1027) then + else if (tracers%data(j)%ID==tracer_ids%macrozooplankton_detrital_silica) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'idetz2si', 'idetz2si', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1028) then + else if (tracers%data(j)%ID==tracer_ids%macrozooplankton_detrital_calcite) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'idetz2calc', 'idetz2calc', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1029) then + else if (tracers%data(j)%ID==tracer_ids%coccolithophore_nitrogen) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CoccoN', 'CoccoN', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1030) then + else if (tracers%data(j)%ID==tracer_ids%coccolithophore_carbon) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CoccoC', 'CoccoC', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1031) then + else if (tracers%data(j)%ID==tracer_ids%coccolithophore_chlorophyll) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CoccoChl', 'CoccoChl', '[mg/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1032) then + else if (tracers%data(j)%ID==tracer_ids%phaeocystis_nitrogen) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoN', 'PhaeoN', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW endif - else if (tracers%data(j)%ID==1033) then + else if (tracers%data(j)%ID==tracer_ids%phaeocystis_carbon) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoC', 'PhaeoC', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW endif - else if (tracers%data(j)%ID==1034) then + else if (tracers%data(j)%ID==tracer_ids%phaeocystis_chlorophyll) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoChl', 'PhaeoChl', '[mg/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW endif - else if (tracers%data(j)%ID==1035) then + else if (tracers%data(j)%ID==tracer_ids%microzooplankton_nitrogen) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo3N', 'Zoo3N', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif - else if (tracers%data(j)%ID==1036) then + else if (tracers%data(j)%ID==tracer_ids%microzooplankton_carbon) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo3C', 'Zoo3C', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif @@ -2997,6 +3043,9 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) ! a legitimate zero (e.g. ice-free a_ice or vanishing IDEMIX energy). call get_wet_range(entry, mesh, nlev_loc, J, ul_loc, kmax_loc) DO I=1, nlev_loc +#if defined(__MULTIO) + entry%local_values_r8_copy(I,J) = entry%local_values_r8(I,J) /real(entry%addcounter,real64) ! compute_means +#else if (I < ul_loc .or. I > kmax_loc) then entry%local_values_r8_copy(I,J) = NC_FILL_DOUBLE ! dry cell - set to fill value else @@ -3017,6 +3066,9 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) ! see comment in the double precision branch above call get_wet_range(entry, mesh, nlev_loc, J, ul_loc, kmax_loc) DO I=1, nlev_loc +#if defined(__MULTIO) + entry%local_values_r4_copy(I,J) = entry%local_values_r4(I,J) /real(entry%addcounter,real32) ! compute_means +#else if (I < ul_loc .or. I > kmax_loc) then entry%local_values_r4_copy(I,J) = NC_FILL_FLOAT ! dry cell - set to fill value else diff --git a/src/recom b/src/recom index 12f739a35..c67e50bac 160000 --- a/src/recom +++ b/src/recom @@ -1 +1 @@ -Subproject commit 12f739a35372fbd61835d40962fde380c0a2aa74 +Subproject commit c67e50bac66bd7a817a0a98fa4dcf2da8362641c From 20d3b2179c38e5c94e6cac708a81a3c80162b466 Mon Sep 17 00:00:00 2001 From: chrisdane Date: Wed, 15 Jul 2026 11:24:25 +0200 Subject: [PATCH 20/23] corrected xco2atm output; recom subrepo co2 branch --- src/gen_forcing_couple.F90 | 9 +++++---- src/io_meandata.F90 | 2 +- src/recom | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index fdfb14365..b7729b946 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -391,10 +391,11 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) end do #if defined (__recom) elseif (i.eq.8) then - ! GloCO2flux_seaicemask is in [mmol/m2/s], need [kg/m2/s] + ! GloCO2flux_seaicemask is in [mmolCO2 m-2 s-1], need [kgCO2 m-2 s-1] ! Conversion: 1.0e-3_WP -> mol/s -> kg/s ! 1 mol CO2 = 44.0095 g/mol = 0.0440095 kg/mol (NIST 2018) - exchange(:) = GloCO2flux_seaicemask(:) * 1.0e-3_WP * 0.0440095_WP ! [kg m⁻² s⁻¹] + ! *-1 for correct flux direction convention: oifs expects >0: downward; fesom: >0: upward + exchange(:) = GloCO2flux_seaicemask(:) * 1.0e-3_WP * 0.0440095_WP * -1 ! [kgCO2 m-2 s-1] #endif else print *, 'not installed yet or error in cpl_oasis3mct_send', mype @@ -578,10 +579,10 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) #if defined (__recom) elseif (i.eq.16) then if (action) then - ! Convert mass mixing ratio (kg/kg) to mole fraction (dimensionless) + ! Convert mass mixing ratio (kg/kg) to ppm ! MW_CO2 = 44.0095 g/mol (NIST 2018) ! MW_dry_air = 28.9647 g/mol (standard atmosphere composition) - x_co2atm(:) = exchange(:) * ((28.9647_WP/44.0095_WP)*1e6_WP) ! [mole fraction] + x_co2atm(:) = exchange(:) * ((28.9647_WP/44.0095_WP)*1e6_WP) ! [ppm] end if #endif #else diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 1f9617f3e..329616ffd 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -834,7 +834,7 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) CASE ('xCO2atm ') if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'xCO2atm', 'atmospheric CO2 mass mixing ratio', 'mole fraction', x_co2atm(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, 'xCO2atm', 'atmospheric CO2', 'ppm', x_co2atm(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('dpCO2s ') diff --git a/src/recom b/src/recom index 12f739a35..f77826c56 160000 --- a/src/recom +++ b/src/recom @@ -1 +1 @@ -Subproject commit 12f739a35372fbd61835d40962fde380c0a2aa74 +Subproject commit f77826c56a2b3d81258612934b66f8bf47b24fb8 From b6d958fa1e6f3fad679bf20b7500554c033d5e3f Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 15 Jul 2026 20:19:14 +0200 Subject: [PATCH 21/23] Fix missing #endif in io_meandata compute_means MULTIO blocks The two `#if defined(__MULTIO) ... #else ...` blocks in the r8 and r4 compute_means loops were missing their closing `#endif`, causing "#if without #endif" and failing the non-MULTIO build. Add the #endif after the wet/dry fill-value branch (before the accumulation reset), matching the intended structure so the reset runs in both branches. --- src/io_meandata.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 4fee99680..e287acf6d 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -3051,6 +3051,7 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) else entry%local_values_r8_copy(I,J) = entry%local_values_r8(I,J) /real(entry%addcounter,real64) ! compute_means end if +#endif entry%local_values_r8(I,J) = 0._real64 ! clean_meanarrays - reset to 0 for next accumulation END DO ! --> DO I=1, nlev_loc END DO ! --> DO J=1, size(entry%local_values_r8,dim=2) @@ -3073,6 +3074,7 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) else entry%local_values_r4_copy(I,J) = entry%local_values_r4(I,J) /real(entry%addcounter,real32) ! compute_means end if +#endif entry%local_values_r4(I,J) = 0._real32 ! clean_meanarrays - reset to 0 for next accumulation END DO ! --> DO I=1, nlev_loc END DO ! --> DO J=1, size(entry%local_values_r4,dim=2) From df0fc2ce91b31bcdf5b7272faaf1ab6dea09641a Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 15 Jul 2026 23:14:44 +0200 Subject: [PATCH 22/23] Remove stale bin_2p3z2d *_old namelist files --- config/bin_2p3z2d/namelist.config_old | 76 ---------------------- config/bin_2p3z2d/namelist.dyn_old | 24 ------- config/bin_2p3z2d/namelist.io_old | 83 ------------------------ config/bin_2p3z2d/namelist.oce_old | 26 -------- config/bin_2p3z2d/namelist.tra_old | 90 --------------------------- 5 files changed, 299 deletions(-) delete mode 100644 config/bin_2p3z2d/namelist.config_old delete mode 100644 config/bin_2p3z2d/namelist.dyn_old delete mode 100644 config/bin_2p3z2d/namelist.io_old delete mode 100644 config/bin_2p3z2d/namelist.oce_old delete mode 100644 config/bin_2p3z2d/namelist.tra_old diff --git a/config/bin_2p3z2d/namelist.config_old b/config/bin_2p3z2d/namelist.config_old deleted file mode 100644 index ffff081c0..000000000 --- a/config/bin_2p3z2d/namelist.config_old +++ /dev/null @@ -1,76 +0,0 @@ -! This is the namelist file for model general configuration - -&modelname -runid='fesom' -/ - -×tep -step_per_day=32 !96 !96 !72 !72 !45 !72 !96 -run_length= 1 !62 !62 !62 !28 -run_length_unit='y' ! y, m, d, s -/ - -&clockinit ! the model starts at -timenew=0.0 -daynew=1 -yearnew=1958 -/ - -&paths -MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' -ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' -ResultPath='/albedo/work/user/...' -/ - -&restart_log -restart_length=1 ! --> do netcdf restart ( only required for d,h,s cases, y, m take 1) -restart_length_unit='y' !output period: y, d, h, s, off -raw_restart_length=1 ! --> do core dump restart -raw_restart_length_unit='off' ! e.g. y, d, h, s, off -bin_restart_length=1 ! --> do derived type binary restart -bin_restart_length_unit='off' ! e.g. y, d, h, s, off -logfile_outfreq=960 !in logfile info. output frequency, # steps -/ - -&ale_def -which_ALE='zstar' ! 'linfs','zlevel', 'zstar' -use_partial_cell=.true. -/ - -&geometry -cartesian=.false. -fplane=.false. -cyclic_length=360 ![degree] -rotated_grid=.true. !option only valid for coupled model case now -force_rotation=.true. -alphaEuler=50. ![degree] Euler angles, convention: -betaEuler=15. ![degree] first around z, then around new x, -gammaEuler=-90. ![degree] then around new z. -/ - -&calendar -include_fleapyear=.false. -/ - -&run_config -use_ice=.true. ! ocean+ice -use_cavity=.false. ! -use_cavity_partial_cell=.false. -use_floatice = .false. -use_sw_pene=.true. -flag_debug=.false. -use_transit=.false. -/ - -&machine -n_levels=2 -n_part= 12, 36 ! 432 number of partitions on each hierarchy level -/ - -&icebergs -use_icesheet_coupling=.false. -ib_num=1 -use_icebergs=.false. -steps_per_ib_step=8 -ib_async_mode=0 -/ diff --git a/config/bin_2p3z2d/namelist.dyn_old b/config/bin_2p3z2d/namelist.dyn_old deleted file mode 100644 index fb7919588..000000000 --- a/config/bin_2p3z2d/namelist.dyn_old +++ /dev/null @@ -1,24 +0,0 @@ -&dynamics_visc -visc_gamma0 = 0.003 ! [m/s], backgroung viscosity= gamma0*len, it should be as small a s possible (keep it < 0.01 m/s). -visc_gamma1 = 0.1 ! [nodim], for computation of the flow aware viscosity -visc_gamma2 = 0.285 ! [s/m], is only used in easy backscatter option -visc_easybsreturn= 1.5 - -opt_visc = 5 -! 5=Kinematic (easy) Backscatter -! 6=Biharmonic flow aware (viscosity depends on velocity Laplacian) -! 7=Biharmonic flow aware (viscosity depends on velocity differences) -! 8=Dynamic Backscatter - -use_ivertvisc= .true. -/ - -&dynamics_general -momadv_opt = 2 ! option for momentum advection in moment only =2 -use_freeslip = .false. ! Switch on free slip -use_wsplit = .false. ! Switch for implicite/explicte splitting of vert. velocity -wsplit_maxcfl= 1.0 ! maximum allowed CFL criteria in vertical (0.5 < w_max_cfl < 1.) - ! in older FESOM it used to be w_exp_max=1.e-3 -ldiag_KE=.false. ! activates energy diagnostics -/ - diff --git a/config/bin_2p3z2d/namelist.io_old b/config/bin_2p3z2d/namelist.io_old deleted file mode 100644 index 10bb72c1b..000000000 --- a/config/bin_2p3z2d/namelist.io_old +++ /dev/null @@ -1,83 +0,0 @@ -&diag_list -ldiag_solver =.false. -lcurt_stress_surf=.false. -ldiag_curl_vel3 =.false. -ldiag_Ri =.false. -ldiag_turbflux =.false. -ldiag_salt3D =.false. -ldiag_dMOC =.false. -ldiag_DVD =.false. -ldiag_forc =.false. -ldiag_extflds =.false. -/ - -&nml_general -io_listsize =150 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list -vec_autorotate =.false. -/ - -! for sea ice related variables use_ice should be true, otherewise there will be no output -! for 'curl_surf' to work lcurt_stress_surf must be .true. otherwise no output -! for 'fer_C', 'bolus_u', 'bolus_v', 'bolus_w', 'fer_K' to work Fer_GM must be .true. otherwise no output -! 'otracers' - all other tracers if applicable -! for 'dMOC' to work ldiag_dMOC must be .true. otherwise no output -&nml_list -io_list = 'sst ',1, 'm', 4, - 'sss ',1, 'm', 4, - 'ssh ',1, 'm', 4, - 'uice ',1, 'm', 4, - 'vice ',1, 'm', 4, - 'a_ice ',1, 'm', 4, - 'm_ice ',1, 'm', 4, - 'm_snow ',1, 'm', 4, - 'MLD1 ',1, 'm', 4, - 'MLD2 ',1, 'm', 4, - 'MLD3 ',1, 'm', 4, - 'tx_sur ',1, 'm', 4, - 'ty_sur ',1, 'm', 4, - 'temp ',1, 'm', 4, - 'salt ',1, 'm', 8, - 'otracers ',1, 'm', 4, - 'N2 ',1, 'y', 4, - 'Kv ',1, 'y', 4, - 'u ',1, 'm', 4, - 'v ',1, 'm', 4, - 'unod ',1, 'm', 4, - 'vnod ',1, 'm', 4, - 'w ',1, 'm', 4, - 'Av ',1, 'y', 4, - 'bolus_u ',1, 'y', 4, - 'bolus_v ',1, 'y', 4, - 'bolus_w ',1, 'y', 4, - 'dpCO2s ',1, 'm', 4, - 'pCO2s ',1, 'm', 4, - 'CO2f ',1, 'm', 4, - 'Hp ',1, 'm', 4, - 'aFe ',1, 'm', 4, - 'aN ',1, 'm', 4, - 'denb ',1, 'm', 4, - 'benN ',1, 'm', 4, - 'benC ',1, 'm', 4, - 'benSi ',1, 'm', 4, - 'benCalc ',1, 'm', 4, - 'Chldegd ',1, 'm', 4, - 'Chldegn ',1, 'm', 4, - 'NNAd ',1, 'm', 4, - 'NNAn ',1, 'm', 4, - 'GPPd ',1, 'm', 4, - 'GPPn ',1, 'm', 4, - 'NPPd ',1, 'm', 4, - 'NPPn ',1, 'm', 4, - 'PAR ',1, 'm', 4, - 'respmeso',1, 'm', 4, - 'respmacro',1, 'm', 4, - 'respmicro',1, 'm', 4, - 'calcdiss',1, 'm', 4, - 'calcif',1, 'm', 4, - 'aggn',1, 'm', 4, - 'aggd',1, 'm', 4, - 'docexn',1, 'm', 4, - 'docexd',1, 'm', 4, - 'respn',1, 'm', 4, - 'respd',1, 'm', 4, -/ diff --git a/config/bin_2p3z2d/namelist.oce_old b/config/bin_2p3z2d/namelist.oce_old deleted file mode 100644 index 7af6867f7..000000000 --- a/config/bin_2p3z2d/namelist.oce_old +++ /dev/null @@ -1,26 +0,0 @@ -! The namelist file for the finite-volume ocean model - -&oce_dyn -C_d=0.0025 ! Bottom drag, nondimensional -A_ver= 1.e-4 ! Vertical viscosity, m^2/s -scale_area=5.8e9 ! Visc. and diffus. are for an element with scale_area -SPP=.false. ! Salt Plume Parameterization -Fer_GM=.true. ! to swith on/off GM after Ferrari et al. 2010 -K_GM_max = 2000.0 ! max. GM thickness diffusivity (m2/s) -K_GM_min = 2.0 ! max. GM thickness diffusivity (m2/s) -K_GM_bvref = 2 ! def of bvref in ferreira scaling 0=srf,1=bot mld,2=mean over mld,3=weighted mean over mld -K_GM_rampmax = -1.0 ! Resol >K_GM_rampmax[km] GM on -K_GM_rampmin = -1.0 ! Resol TB04 mixing -momix_lat = -50.0 ! latitidinal treshhold for TB04, =90 --> global -momix_kv = 0.01 ! PP/KPP, mixing coefficient within MO length -use_instabmix = .true. ! enhance convection in case of instable stratification -instabmix_kv = 0.1 -use_windmix = .false. ! enhance mixing trough wind only for PP mixing (for stability) -windmix_kv = 1.e-3 -windmix_nl = 2 -diff_sh_limit=5.0e-3 ! for KPP, max diff due to shear instability -Kv0_const=.true. -double_diffusion=.false. ! for KPP,dd switch -K_ver=1.0e-5 -K_hor=3000. -surf_relax_T=0.0 -surf_relax_S=1.929e-06 ! 50m/300days 6.43e-07! m/s 10./(180.*86400.) -balance_salt_water =.true. ! balance virtual-salt or freshwater flux or not -clim_relax=0.0 ! 1/s, geometrical information has to be supplied -ref_sss_local=.true. -ref_sss=34. -/ From fe02a881d4db9bf6566d636d5eb63203a10cb621 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Thu, 23 Jul 2026 13:39:19 +0200 Subject: [PATCH 23/23] cpl(__oifs): coupled-slab ice surface temperature + sea-ice-thickness exchange Cherry-pick of the coupled-slab ice-surftemp feature onto the recom/CO2 coupling branch. sit_feom keeps the canonical __oifs slot 8 (matching the non-recom coupled-slab); recom's FCO2_feom moves to slot 9, active only under __recom, so the sea-ice-thickness slot does not depend on the CO2 coupling. nsend: __oifs+__recom = 9, __oifs = 8. --- src/MOD_ICE.F90 | 11 ++++++- src/cpl_driver.F90 | 7 +++-- src/gen_forcing_couple.F90 | 26 +++++++++++++++-- src/ice_thermo_cpl.F90 | 59 +++++++++++++++++++++++++++++++------- 4 files changed, 85 insertions(+), 18 deletions(-) diff --git a/src/MOD_ICE.F90 b/src/MOD_ICE.F90 index 87499663d..66161c238 100644 --- a/src/MOD_ICE.F90 +++ b/src/MOD_ICE.F90 @@ -120,6 +120,11 @@ MODULE MOD_ICE #if defined (__oifs) || defined (__ifsinterface) || defined(__yac) !___________________________________________________________________________ real(kind=WP), allocatable, dimension(:) :: ice_alb, enthalpyoffuse, runoff_liquid, runoff_solid, flx_qres, flx_qcon + ! ist anchor: ice surface temperature as ACTUALLY TRANSMITTED at the last + ! OASIS send -- the temperature OIFS evaluates its ice-tile fluxes at for + ! the coming coupling interval. Consumed by the implicit (dQ/dT-linearized) + ! surface-temperature solve in ice_thermo_cpl.F90 (ice_surftemp). + real(kind=WP), allocatable, dimension(:) :: ist_ref ! !!! DONT FORGET ice_temp rhs_tempdiv rhs_temp is advected for oifs !!! --> becomes additional ice ! tracer in ice%data(4)%values #endif /* (__oifs) */ @@ -886,8 +891,12 @@ subroutine ice_init(ice, partit, mesh) ice%atmcoupl%runoff_solid= 0.0_WP allocate(ice%atmcoupl%flx_qres(node_size)) allocate(ice%atmcoupl%flx_qcon(node_size)) - ice%atmcoupl%flx_qres = 0.0_WP + ice%atmcoupl%flx_qres = 0.0_WP ice%atmcoupl%flx_qcon = 0.0_WP + ! 0 = "no send yet": ice_surftemp falls back to the local t as anchor + ! until the first actual OASIS transmission populates it. + allocate(ice%atmcoupl%ist_ref(node_size)) + ice%atmcoupl%ist_ref = 0.0_WP #endif /* (__oifs) */ #endif /* (__coupled: oasis or ifsinterface or yac) */ diff --git a/src/cpl_driver.F90 b/src/cpl_driver.F90 index 24a2538c9..2a34ab14c 100644 --- a/src/cpl_driver.F90 +++ b/src/cpl_driver.F90 @@ -31,11 +31,11 @@ module cpl_driver #if defined (__oifs) #if defined(__recom) - integer :: nsend = 8 + integer :: nsend = 9 integer :: nrecv = 16 !With oifs, without recom: #else - integer :: nsend = 7 + integer :: nsend = 8 integer :: nrecv = 15 #endif !Without oifs @@ -670,8 +670,9 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) cpl_send( 5)='sia_feom' ! 5. sea ice albedo [%-100] -> cpl_send( 6)='u_feom' ! 6. eastward surface velocity [m/s] -> cpl_send( 7)='v_feom' ! 7. northward surface velocity [m/s] -> + cpl_send( 8)='sit_feom' ! 8. effective sea ice thickness [m] -> #if defined (__recom) - cpl_send( 8)='FCO2_feom'! 8. CO2 flux [kgCO2 m-2 s-1] -> + cpl_send( 9)='FCO2_feom'! 9. CO2 flux [kgCO2 m-2 s-1] -> #endif #else cpl_send( 1)='sst_feom' ! 1. sea surface temperature [°C] -> diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index b7729b946..ba40c34e1 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -378,7 +378,13 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) elseif (i.eq.3) then exchange(:) = m_snow(:) ! snow thickness elseif (i.eq.4) then - exchange(:) = ice_temp(:) ! ice surface temperature + ! Concentration-weighted ice surface temperature (ist*a_ice). + ! The o2a remap blend must be concentration-weighted so the + ! atmosphere's prescribed ice-tile skin is representative of the + ! ice actually present in the cell; PAIRED with + ! ECE_CPL_NEMO_WEIGHTED_ICE=.true. (OIFS divides by the received + ! ice fraction on ingest) and a weighted-convention rstos.nc. + exchange(:) = ice_temp(:)*a_ice(:) ! ice surface temperature * concentration elseif (i.eq.5) then exchange(:) = ice_alb(:) ! ice albedo elseif (i.eq.6) then @@ -389,15 +395,21 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) do n=1,myDim_nod2D+eDim_nod2D exchange(n) = UVnode(2,1,n) end do -#if defined (__recom) elseif (i.eq.8) then + ! Effective (grid-mean = per-ice * concentration) sea-ice + ! thickness for the atmosphere's ice-tile slab conduction + ! (OIFS ECE_FESIM_GET_ICE_STATE divides by the received ice + ! fraction under LNEMOLIMTHK). Weighted convention as ist/alb. + exchange(:) = m_ice(:) ! effective sea ice thickness +#if defined (__recom) + elseif (i.eq.9) then ! GloCO2flux_seaicemask is in [mmolCO2 m-2 s-1], need [kgCO2 m-2 s-1] ! Conversion: 1.0e-3_WP -> mol/s -> kg/s ! 1 mol CO2 = 44.0095 g/mol = 0.0440095 kg/mol (NIST 2018) ! *-1 for correct flux direction convention: oifs expects >0: downward; fesom: >0: upward exchange(:) = GloCO2flux_seaicemask(:) * 1.0e-3_WP * 0.0440095_WP * -1 ! [kgCO2 m-2 s-1] #endif - else + else print *, 'not installed yet or error in cpl_oasis3mct_send', mype #else ! AWI-CM2 outgoing state vectors @@ -458,6 +470,14 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) #endif endif call cpl_oasis3mct_send(i, exchange, action, partit) +#if defined (__oifs) + ! Anchor for the implicit ice surface-temperature solve + ! (ice_thermo_cpl.F90/ice_surftemp): remember the ist as ACTUALLY + ! transmitted -- the temperature OIFS evaluates its ice-tile fluxes + ! at for the coming coupling interval. `action` is only true on real + ! OASIS transmissions, so this stays frozen between coupling events. + if (i==4 .and. action) ice%atmcoupl%ist_ref(:) = exchange(:) +#endif end do #ifdef VERBOSE do i=1, nsend diff --git a/src/ice_thermo_cpl.F90 b/src/ice_thermo_cpl.F90 index 462f18ede..2ffe15230 100644 --- a/src/ice_thermo_cpl.F90 +++ b/src/ice_thermo_cpl.F90 @@ -37,6 +37,9 @@ subroutine thermodynamics(ice, partit, mesh) real(kind=WP) :: A, h, hsn, alb, t !---- atmospheric heat fluxes (provided by ECHAM) real(kind=WP) :: a2ohf, a2ihf, qres, qcon + !---- tref: ist anchor the atmosphere evaluated a2ihf at, the linearization + !---- anchor for the internal surface-temperature solve (see ice_surftemp). + real(kind=WP) :: tref !---- evaporation and sublimation (provided by ECHAM) real(kind=WP) :: evap, subli !---- add residual freshwater flux over ice to freshwater (setted in ice_growth) @@ -74,6 +77,7 @@ subroutine thermodynamics(ice, partit, mesh) real(kind=WP), dimension(:) , pointer :: fresh_wa_flux, net_heat_flux #if defined (__oifs) || defined (__ifsinterface) real(kind=WP), dimension(:) , pointer :: ice_temp, ice_alb, enthalpyoffuse, ice_heat_qres, ice_heat_qcon, runoff_liquid, runoff_solid + real(kind=WP), dimension(:) , pointer :: ist_ref #endif #if defined (__oasis) || defined (__ifsinterface) || defined (__yac) real(kind=WP), dimension(:) , pointer :: oce_heat_flux, ice_heat_flux @@ -109,7 +113,8 @@ subroutine thermodynamics(ice, partit, mesh) runoff_solid => ice%atmcoupl%runoff_solid(:) ice_heat_qres => ice%atmcoupl%flx_qres(:) ice_heat_qcon => ice%atmcoupl%flx_qcon(:) -#endif + ist_ref => ice%atmcoupl%ist_ref(:) +#endif #if defined (__oasis) || defined (__ifsinterface) || defined (__yac) oce_heat_flux => ice%atmcoupl%oce_flx_h(:) ice_heat_flux => ice%atmcoupl%ice_flx_h(:) @@ -173,7 +178,12 @@ subroutine thermodynamics(ice, partit, mesh) qres = 0.0_WP qcon = 0.0_WP if(A>Aimin) then - call ice_surftemp(ice%thermo, max(h/(max(A,Aimin)),0.05), hsn/(max(A,Aimin)), a2ihf, t) + ! Anchor temperature for the implicit flux linearization: the ist OIFS + ! actually evaluated a2ihf at (captured at the OASIS send). Fall back + ! to the local t before the first transmission (cold start / restart). + tref = ist_ref(inod) + if (tref < 100.0_WP) tref = t + call ice_surftemp(ice%thermo, max(h/(max(A,Aimin)),0.05), hsn/(max(A,Aimin)), a2ihf, tref, t) ice_temp(inod) = t else ! Freezing temp of saltwater in K @@ -281,11 +291,13 @@ subroutine ice_growth !---- atmospheric heat fluxes (provided by the atmosphere model) -#if defined (__oifs) || defined (__ifsinterface) - Qatmice = -qres-qcon -#else + ! Coupled-slab convention: the atmosphere solves the ice surface + ! temperature implicitly in its own surface scheme, with slab conduction + ! through the coupled ice/snow thickness, and its surface energy balance + ! flux drives ice growth directly. The ice model's own surface-temperature + ! solve is internal-only (albedo/melt-pond state) and does not enter the + ! growth budget. Qatmice = -a2ihf -#endif Qatmocn = -a2ohf !---- oceanic heat fluxes @@ -539,13 +551,15 @@ subroutine ice_growth return end subroutine ice_growth - subroutine ice_surftemp(ithermp, h,hsn,a2ihf,t) + subroutine ice_surftemp(ithermp, h,hsn,a2ihf,tref,t) ! INPUT: ! a2ihf - Total atmo heat flux to ice ! A - Ice fraction ! h - Ice thickness ! hsn - Snow thickness - ! + ! tref - ist the atmosphere evaluated a2ihf at (last transmitted ist); + ! linearization anchor for the implicit flux term + ! ! INPUT/OUTPUT: ! t - Ice surface temperature @@ -556,7 +570,15 @@ subroutine ice_surftemp(ithermp, h,hsn,a2ihf,t) !---- ocean variables (provided by FESOM) real(kind=WP) h real(kind=WP) hsn + real(kind=WP) tref real(kind=WP) t + !---- flux-linearization coefficient dQ/dT [W/m2/K] + real(kind=WP) zlam + !---- bulk near-neutral turbulent flux sensitivity rho*cp*C_H*|U| [W/m2/K] + !---- (C_H ~ 1.5e-3, |U| ~ 8 m/s). Radiative + turbulent together give + !---- ~20 W/m2/K, the standard fallback flux derivative used in + !---- NEMO/SI3-family couplings when the atmosphere does not export dQ/dT. + real(kind=WP), parameter :: zlam_turb = 16.0_WP !---- local variables real(kind=WP) snicecond real(kind=WP) zsniced @@ -570,12 +592,14 @@ subroutine ice_surftemp(ithermp, h,hsn,a2ihf,t) !---- freezing temperature of sea-water [K] real(kind=WP) :: TFrezs - real(kind=WP), pointer :: con, consn, cpsno, rhoice, rhosno + real(kind=WP), pointer :: con, consn, cpsno, rhoice, rhosno, emiss_ice, boltzmann con => ice%thermo%con consn => ice%thermo%consn cpsno => ice%thermo%cpsno rhoice => ice%thermo%rhoice rhosno => ice%thermo%rhosno + emiss_ice => ice%thermo%emiss_ice + boltzmann => ice%thermo%boltzmann !---- compute freezing temperature of sea-water from salinity TFrezs = -0.0575_WP*S_oc + 1.7105e-3_WP*sqrt(S_oc**3) - 2.155e-4_WP*(S_oc**2)+273.15 @@ -587,9 +611,22 @@ subroutine ice_surftemp(ithermp, h,hsn,a2ihf,t) zcpdt=hcapice/dt ! Energy required to change temperature of top ice "layer" [J/(sm²K)] zcprosn=rhosno*cpsno/dt ! Specific Energy required to change temperature of 1m snow on ice [J/(sm³K)] zcpdte=zcpdt !+zcprosn*hsn ! Combined Energy required to change temperature of snow + 0.05m of upper ice - t=(zcpdte*t+a2ihf+zicefl)/(zcpdte+con/zsniced) ! New sea ice surf temp [K] + + !---- Implicit (dQ/dT-linearized) atmospheric flux. + ! a2ihf was computed by the atmosphere at tref (the last transmitted ist) + ! and is held constant over the coupling interval. As the surface departs + ! from tref, the flux's dominant temperature response is the surface's own + ! longwave emission, linearized here: + ! Q(t) = a2ihf + zlam*(tref - t), zlam = 4*eps*sigma*tref**3 + ! This keeps the internal surface-temperature solve stable regardless of + ! the snow/ice insulation (con/zsniced) and leaves the fixed point unchanged + ! wherever the surface tracks the coupling temperature. In coupled-slab mode + ! the growth budget is driven by the atmosphere flux (-a2ihf), so this solve + ! only sets the internal skin temperature (albedo/melt-pond state). + zlam=4.0_WP*emiss_ice*boltzmann*tref**3 + zlam_turb + t=(zcpdte*t+a2ihf+zlam*tref+zicefl)/(zcpdte+con/zsniced+zlam) ! New sea ice surf temp [K] if (t>273.15_WP) then - qres=(con/zsniced+zcpdte)*(t-273.15_WP) + qres=(con/zsniced+zcpdte+zlam)*(t-273.15_WP) t=273.15_WP endif qcon=con*(t-TFrezs)/max(zsniced, himin)