diff --git a/.gitignore b/.gitignore index f869d2cbc..820a4f247 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ Makefile.in mesh_part/build test/output_pi src/cvmix_driver/CVMix-* +finished_config.yaml diff --git a/config/bin_2p1z1d/job_albedo b/config/bin_2p1z1d/job_albedo index bac3e2b3a..23caf2e11 100755 --- a/config/bin_2p1z1d/job_albedo +++ b/config/bin_2p1z1d/job_albedo @@ -1,16 +1,15 @@ #!/bin/bash -#SBATCH --account=nwg_hauck.maresys # edit your account +#SBATCH --account=biogeo_model.biogeo_model # edit your account #SBATCH --job-name=recom #SBATCH --partition=mpp #SBATCH --time=01:30:00 -####SBATCH --constraint="[rack1|rack3]" #SBATCH --qos=12h #SBATCH --nodes=9 # Number of tasks (MPI) tasks to be launched #SBATCH --tasks-per-node 96 #8 #4 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O #SBATCH --cpus-per-task 1 -#SBATCH -o fesom2o.out -#SBATCH -e fesom2e.out +#SBATCH -o slurm-out.out +#SBATCH -e slurm-err.out # disable hyperthreading #SBATCH --hint=nomultithread @@ -35,23 +34,22 @@ cp -n ../config/namelist.icepack . #___DETERMINE SLURM JOBID+OUTPUTFILE____________________________________________ jobid=$(echo $SLURM_JOB_ID | cut -d"." -f1) -fname="fesom2_${SLURM_JOB_NAME}_${jobid}.out" +fname="fesom2.0.out" #___PUT JOB IN QUEUE____________________________________________________________ date -####srun --mpi=pmi2 ./fesom.x >> ${fname} srun --mpi=pmi2 ./fesom.x > fesom2.0.out date #qstat -f $PBS_JOBID #export EXITSTATUS=$? #if [ ${EXITSTATUS} -eq 0 ] || [ ${EXITSTATUS} -eq 127 ] ; then -#sbatch job_ollie +#sbatch job_albedo #fi -#Resultpath='/albedo/scratch/user/ogurses/ocean_only/' -Resultpath='/albedo/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags/' -test -d $Resultpath/fesom.2019.oce.restart && exit + +Resultpath='/albedo/scratch/user/XXXX/' +test -e $Resultpath/fesom.XXXX.oce.restart && exit IsInFile=$( tail -3 fesom2.0.out | grep -c timesteps) if (( IsInFile > 0 )); then diff --git a/config/bin_2p1z1d/namelist.config b/config/bin_2p1z1d/namelist.config index eb9a4375d..27c3d140a 100644 --- a/config/bin_2p1z1d/namelist.config +++ b/config/bin_2p1z1d/namelist.config @@ -1,67 +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/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags/' +MeshPath = '/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' ! path to mesh files (nod2d.out, elem2d.out, etc.) +ClimateDataPath = '/albedo/work/projects/MarESys/ogurses/input/corrected_input/' ! path to initial conditions (temperature, salinity) +ResultPath = '/albedo/scratch/user/XXXX' / +! ============================================================================ +! 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 = 'off' ! unit: 'y', 'm', 'd', 'h', 's', 'off' +bin_restart_length = 1 ! frequency for binary derived type restart files +bin_restart_length_unit = 'off' ! 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 = .false. ! 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_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. ! 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_2p1z1d/namelist.forcing b/config/bin_2p1z1d/namelist.forcing index a17799393..d890c69ec 100644 --- a/config/bin_2p1z1d/namelist.forcing +++ b/config/bin_2p1z1d/namelist.forcing @@ -23,11 +23,23 @@ ncar_bulk_z_shum=10.0 ! height at which humi forcing is located (CORE, JRA-do: 1 use_landice_water=.false. landice_start_mon=5 landice_end_mon=10 +fwf_path='./mesh/' + +/ + +&age_tracer +use_age_tracer=.false. +use_age_mask=.false. +age_tracer_path='./mesh/' +age_start_year=2000 + / &nam_sbc nm_xwind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 nm_ywind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 + nm_xstre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 + nm_ystre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 nm_humi_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/huss.clim61' ! name of file with humidity nm_qsr_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rsds.clim61' ! name of file with solar heat nm_qlw_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rlds.clim61' ! name of file with Long wave @@ -37,24 +49,32 @@ landice_end_mon=10 nm_mslp_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/psl.clim61' ! air_pressure_at_sea_level nm_xwind_var = 'uas' ! name of variable in file with wind nm_ywind_var = 'vas' ! name of variable in file with wind - nm_humi_var = 'huss' ! name of variable in file with humidity - nm_qsr_var = 'rsds' ! name of variable in file with solar heat - nm_qlw_var = 'rlds' ! name of variable in file with Long wave + nm_xstre_var = 'uas' ! name of variable in file with wind + nm_ystre_var = 'vas' ! name of variable in file with wind + nm_humi_var = 'huss' ! name of variable in file with humidity + nm_qsr_var = 'rsds' ! name of variable in file with solar heat + nm_qlw_var = 'rlds' ! name of variable in file with Long wave nm_tair_var = 'tas' ! name of variable in file with 2m air temperature - nm_prec_var = 'prra' ! name of variable in file with total precipitation - nm_snow_var = 'prsn' ! name of variable in file with total precipitation - nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level + nm_prec_var = 'prra' ! name of variable in file with total precipitation + nm_snow_var = 'prsn' ! name of variable in file with total precipitation + nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level nm_nc_iyear = 1900 nm_nc_imm = 1 ! initial month of time axis in netCDF nm_nc_idd = 1 ! initial day of time axis in netCDF nm_nc_freq = 1 ! data points per day (i.e. 86400 if the time axis is in seconds) nm_nc_tmid = 0 ! 1 if the time stamps are given at the mid points of the netcdf file, 0 otherwise (i.e. 1 in CORE1, CORE2; 0 in JRA55) y_perpetual=.true. - l_xwind=.true. l_ywind=.true. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. + l_xwind=.true. l_ywind=.true. l_xstre=.false. l_ystre=.false. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. nm_runoff_file ='/albedo/pool/FESOM/forcing/CORE2/runoff.nc' runoff_data_source ='CORE2' !Dai09, CORE2 !runoff_data_source ='Dai09' !Dai09, CORE2, JRA55 !runoff_climatology =.true. - nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' sss_data_source ='CORE2' + nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' + chl_data_source ='None' !'Sweeney' monthly chlorophyll climatology or 'NONE' for constant chl_const (below). Make use_sw_pene=.TRUE. in namelist.config! + nm_chl_data_file ='/pool/data/AWICM/FESOM2/FORCING/JRA55-do-v1.4.0/Sweeney/Sweeney_2005.nc' + chl_const = 0.1 + use_runoff_mapper = .FALSE. + runoff_basins_file = 'runoff_maps_regular.nc' + runoff_radius = 500000. / diff --git a/config/bin_2p1z1d/namelist.io b/config/bin_2p1z1d/namelist.io index 7a6fe3cff..1cff5280d 100644 --- a/config/bin_2p1z1d/namelist.io +++ b/config/bin_2p1z1d/namelist.io @@ -55,7 +55,6 @@ io_list = 'sst ',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, diff --git a/config/bin_2p1z1d/namelist.recom b/config/bin_2p1z1d/namelist.recom index dd53c8538..afde32d97 100644 --- a/config/bin_2p1z1d/namelist.recom +++ b/config/bin_2p1z1d/namelist.recom @@ -1,353 +1,514 @@ -! This is the namelist file for recom - +! ============================================================================ +! ============ Namelist file for REcoM Biogeochemical Model ================= +! ============================================================================ +! Regional Ecosystem Model (REcoM) configuration +! This file controls biogeochemical processes including: +! - Carbon, nitrogen, silicon, iron cycling +! - Phytoplankton (small phyto, diatoms, coccolithophores) +! - Zooplankton (micro, meso, krill) +! - Organic matter remineralization and sinking +! - Carbonate chemistry and air-sea CO2 fluxes +! - External nutrient inputs (dust, rivers, erosion) +! ============================================================================ + +! ============================================================================ +! DATA SOURCES AND INPUT FILES +! ============================================================================ &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' +nm_co2_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/MonthlyAtmCO2_gcb2024.nc' / -&pavariables -use_REcoM =.true. -REcoM_restart =.true. - -bgc_num = 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 = 2022 ! 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 +! ============================================================================ +! GENERAL MODEL CONFIGURATION +! ============================================================================ +&parecomsetup +enable_3zoo2det = .false. ! Enable 3 zooplankton + 2 detritus configuration (currently disabled) +enable_coccos = .false. ! Enable coccolithophores (currently disabled) / +! ============================================================================ +! MAIN MODEL SWITCHES AND SETTINGS +! ============================================================================ +! --- Core Model Settings --- +&pavariables +use_REcoM = .true. +REcoM_restart = .true. +recom_debug = .false. + +! --- Tracer Configuration --- +bgc_num = 22 ! Total number of BGC tracers +diags3d_num = 28 ! Number of diagnostic 3D tracers +bgc_base_num = 22 ! Number of standard tracers +benthos_num = 4 ! Number of benthic BGC tracers (8 if ciso=.true., else 4) +sedflx_num = 0 ! Sediment fluxes from MEDUSA (0 = use defaults) +bottflx_num = 4 ! Bottom fluxes (8 if ciso & ciso_14, 6 if not ciso_14, 4 otherwise) + +! --- Sinking Velocities [m/day] --- +VDet = 20.0 ! Small detritus sinking velocity (constant, positive down) +VDet_zoo2 = 200.0 ! Large detritus sinking velocity +VPhy = 0.0 ! Small phytoplankton (non-sinking) +VDia = 0.0 ! Diatoms (variable sinking if allow_var_sinking=.true.) +VCocco = 0.0 ! Coccolithophores +allow_var_sinking = .true. ! Enable variable sinking velocity + +! --- Time Stepping --- +biostep = 1 ! Number of biology sub-steps per physical time step + +! --- Process Switches --- +REcoM_Geider_limiter = .false. ! Use Geider limiter for nutrient limitation +REcoM_Grazing_Variable_Preference = .true. ! Variable grazing preference (PhyN vs DiaN) +Grazing_detritus = .true. ! Enable zooplankton grazing on detritus +het_resp_noredfield = .true. ! Non-Redfield respiration for copepods +diatom_mucus = .true. ! Nutrient-limited diatom aggregation +O2dep_remin = .false. ! O2-dependent organic matter remineralization +use_ballasting = .false. ! Ballast effect on sinking +use_density_scaling = .false. ! Density-dependent sinking +use_viscosity_scaling = .false. ! Viscosity-dependent sinking +OmegaC_diss = .false. ! OmegaC-dependent calcite dissolution (set calc_diss_guts=0 if false) +CO2lim = .false. ! CO2 effects on growth and calcification +use_photodamage = .true. ! Chlorophyll photodamage (Alvarez et al. 2018) +HetRespFlux_plus = .true. ! Stabilized zooplankton respiration computation +Diags = .true. ! Enable diagnostics output + +! --- External Inputs --- +constant_CO2 = .true. +UseFeDust = .true. ! Enable iron input from dust +UseDustClim = .true. ! Use dust climatology +UseDustClimAlbani = .true. ! Use Albani dust fields (false = Mahowald) +useRivers = .false. ! Enable riverine inputs +useRivFe = .false. ! Enable riverine iron source +useErosion = .false. ! Enable erosion inputs +NitrogenSS = .false. ! Enable nitrogen sources/sinks (rivers, aeolian, denitrification) +useAeolianN = .false. ! Enable aeolian nitrogen deposition + +! --- Time Period Configuration --- +firstyearoffesomcycle = 1958 ! First year of physical forcing (e.g., JRA-55) +lastyearoffesomcycle = 2024 ! Last year of physical forcing +numofCO2cycles = 1 ! Number of forcing cycles +currentCO2cycle = 1 ! Current forcing cycle number + +! --- Alkalinity and Carbon --- +DIC_PI = .true. ! Use pre-industrial DIC +restore_alkalinity = .true. ! Restore surface alkalinity +Nmocsy = 1 ! Vector length for mocsy (always 1 for REcoM) + +! --- Data Path --- +REcoMDataPath = '/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/' + +! --- Carbon Isotopes --- +ciso = .false. ! Enable carbon isotopes (13C, 14C) + +! --- Sediment Model --- +use_MEDUSA = .false. ! Enable MEDUSA sediment model +add_loopback = .false. ! Add loopback fluxes through rivers +lb_tscale = 1.0 ! Loopback timescale [1/year] + +! --- Miscellaneous --- +use_atbox = .false. ! Use atmospheric box model +/ + +! ============================================================================ +! SINKING VELOCITY PARAMETERS +! ============================================================================ &pasinking -Vdet_a = 0.0288 ! [1/day] -Vcalc = 0.0144 ! [1/day] +Vdet_a = 0.0288 ! Slope of the linearly increasing sinking velocity [1/day] +Vcalc = 0.0144 ! Depth dependence of calcite dissolution (when use_coccos disabled) [1/day] / +! ============================================================================ +! INITIAL CONDITIONS +! ============================================================================ &painitialization_N -cPhyN = 0.2d0 -cHetN = 0.2d0 -cZoo2N = 0.2d0 +cPhyN = 0.2 ! Initial small phytoplankton nitrogen [mmol N/m³] +cHetN = 0.2 ! Initial microzooplankton nitrogen [mmol N/m³] +cZoo2N = 0.2 ! Initial mesozooplankton nitrogen [mmol N/m³] / +! ============================================================================ +! TEMPERATURE DEPENDENCE (ARRHENIUS) +! ============================================================================ &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 +recom_Tref = 288.15 ! Reference temperature [K] +C2K = 273.15 ! Celsius to Kelvin conversion +Ae = 4500.0 ! Arrhenius slope [K] +reminSi = 0.02 ! Silicate remineralization base rate [1/day] +k_o2_remin = 15.0 ! Half-saturation for O2 remineralization [mmol O2/m³] / &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 -/ - +! --- Limitation Function Slopes --- +NMinSlope = 50.0 ! Nitrogen minimum slope +SiMinSlope = 1000.0 ! Silicon minimum slope + +! --- Minimum Quotas [mmol/mmol C] --- +NCmin = 0.04 ! Small phytoplankton N:C minimum +NCmin_d = 0.04 ! Diatom N:C minimum +NCmin_c = 0.04 ! Coccolithophore N:C minimum +SiCmin = 0.04 ! Diatom Si:C minimum + +! --- Half-Saturation Constants --- +k_Fe = 0.04 ! Small phyto iron half-sat [µmol Fe/m³] +k_Fe_d = 0.12 ! Diatom iron half-sat [µmol Fe/m³] +k_Fe_c = 0.09 ! Coccolith iron half-sat [µmol Fe/m³] +k_si = 4.0 ! Silicon half-sat [mmol Si/m³] + +! --- Maximum Photosynthesis Rates [1/day] --- +P_cm = 3.0 ! Small phytoplankton max C-specific photosynthesis +P_cm_d = 3.5 ! Diatom max C-specific photosynthesis +P_cm_c = 2.8 ! Coccolithophore max C-specific photosynthesis +/ + +! ============================================================================ +! LIGHT ATTENUATION +! ============================================================================ &palight_calculations -k_w = 0.04d0 ! [1/m] Light attenuation coefficient -a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific attenuation coefficients +k_w = 0.04 ! Water attenuation coefficient [1/m] +a_chl = 0.03 ! Chlorophyll-specific attenuation [1/m per mg Chl/m³] / +! ============================================================================ +! PHOTOSYNTHESIS (P-I CURVE) +! ============================================================================ &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 +alfa = 0.14 ! Small phyto initial P-I slope [(mmol C·m²)/(mg Chl·W·day)] +alfa_d = 0.19 ! Diatom initial P-I slope +alfa_c = 0.10 ! Coccolithophore initial P-I slope +parFrac = 0.43 ! Fraction of shortwave that is PAR / +! ============================================================================ +! NUTRIENT ASSIMILATION +! ============================================================================ &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 -/ - +! --- Maximum Uptake Scaling --- +V_cm_fact = 0.7 ! Small phyto N-uptake scaling factor +V_cm_fact_d = 0.7 ! Diatom N-uptake scaling factor +V_cm_fact_c = 0.7 ! Coccolithophore N-uptake scaling factor + +! --- Limitation Function Slopes --- +NMaxSlope = 1000.0 ! Nitrogen maximum slope +SiMaxSlope = 1000.0 ! Silicon maximum slope + +! --- Maximum Cell Quotas [mmol/mmol C] --- +NCmax = 0.2 ! Small phyto maximum N:C +NCmax_d = 0.2 ! Diatom maximum N:C +NCmax_c = 0.15 ! Coccolithophore maximum N:C +SiCmax = 0.8 ! Diatom maximum Si:C + +! --- Maximum Uptake Ratios [mmol/mmol C] --- +NCuptakeRatio = 0.2 ! Small phyto N:C uptake ratio +NCUptakeRatio_d = 0.2 ! Diatom N:C uptake ratio +NCUptakeRatio_c = 0.2 ! Coccolithophore N:C uptake ratio +SiCUptakeRatio = 0.2 ! Diatom Si:C uptake ratio + +! --- Chlorophyll Parameters --- +Chl2N_max = 3.15 ! Small phyto max Chl:N [mg Chl/mmol N] +Chl2N_max_d = 4.2 ! Diatom max Chl:N [mg Chl/mmol N] +Chl2N_max_c = 3.5 ! Coccolithophore max Chl:N [mg Chl/mmol N] + +! --- Half-Saturation Constants --- +k_din = 0.55 ! Small phyto nitrate half-sat [mmol N/m³] +k_din_d = 1.0 ! Diatom nitrate half-sat [mmol N/m³] +k_din_c = 0.9 ! Coccolith nitrate half-sat [mmol N/m³] + +! --- Respiration and Biosynthesis --- +res_phy = 0.01 ! Small phyto maintenance respiration [1/day] +res_phy_d = 0.01 ! Diatom maintenance respiration [1/day] +res_phy_c = 0.01 ! Coccolithophore maintenance respiration [1/day] +biosynth = 2.33 ! Cost of biosynthesis [mmol C/mmol N] +biosynthSi = 0.0 ! Silicon biosynthesis cost [mmol C/mmol Si] +/ + +! ============================================================================ +! IRON CHEMISTRY +! ============================================================================ &pairon_chem -totalligand = 1.d0 ! [mumol/m3] order 1. Total free ligand -ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron stability constant +totalligand = 1.0 ! Total free ligand concentration [µmol/m³] +ligandStabConst = 100.0 ! Ligand-Fe stability constant [m³/µmol] / +! ============================================================================ +! MICROZOOPLANKTON (FIRST ZOOPLANKTON) +! ============================================================================ &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. -/ - +graz_max = 0.31 ! Maximum grazing rate [1/day] +epsilonr = 0.09 ! Half-saturation constant [(mmol N)²/m⁶] +res_het = 0.028 ! Respiration + mortality [1/day] +Redfield = 6.625 ! C:N Redfield ratio [mmol C/mmol N] +loss_het = 0.04 ! Extracellular N degradation [1/day] +tiny_het = 1.d-5 ! Small number for stable computation + +! --- Grazing Preferences --- +pzDia = 1.0 ! Diatom preference (maximum) +sDiaNsq = 0.0 ! Diatom preference slope +pzPhy = 0.5 ! Small phyto preference +sPhyNsq = 0.0 ! Small phyto preference slope +pzCocco = 0.666 ! Coccolithophore preference +sCoccoNsq = 0.0 ! Coccolithophore preference slope +pzMicZoo = 1.0 ! Microzooplankton preference (self-grazing) +sMicZooNsq = 0.0 ! Microzooplankton preference slope +/ + +! ============================================================================ +! MESOZOOPLANKTON (SECOND ZOOPLANKTON) +! ============================================================================ &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 -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 -/ - +graz_max2 = 0.1 ! Maximum grazing rate [1/day] +epsilon2 = 0.0144 ! Half-saturation constant [(mmol N)²/m⁶] +res_zoo2 = 0.0107 ! Respiration + mortality [1/day] +loss_zoo2 = 0.003 ! Extracellular N degradation [1/day] + +! --- Fecal Pellet Production --- +fecal_rate_n = 0.104 ! Nitrogen fecal rate [1/day] +fecal_rate_c = 0.236 ! Carbon fecal rate [1/day] +fecal_rate_n_mes = 0.25 ! Mesozooplankton N fecal rate [1/day] +fecal_rate_c_mes = 0.32 ! Mesozooplankton C fecal rate [1/day] + +! --- Grazing Preferences --- +pzDia2 = 1.5 ! Diatom preference +sDiaNsq2 = 0.0 ! Diatom preference slope +pzPhy2 = 0.5 ! Small phyto preference +sPhyNsq2 = 0.0 ! Small phyto preference slope +pzCocco2 = 0.5 ! Coccolithophore preference (unused) +sCoccoNsq2 = 0.0 ! Coccolithophore preference slope +pzHet = 1.5 ! Microzooplankton preference +sHetNsq = 0.0 ! Microzooplankton preference slope + +! --- Temperature Function (Krill-specific) --- +t1_zoo2 = 28145.0 ! Temperature function constant 1 +t2_zoo2 = 272.5 ! Temperature function constant 2 [K] +t3_zoo2 = 105234.0 ! Temperature function constant 3 +t4_zoo2 = 274.15 ! Temperature function constant 4 [K] +/ + +! ============================================================================ +! MICROZOOPLANKTON (THIRD ZOOPLANKTON) +! ============================================================================ &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 -/ - +graz_max3 = 0.46 ! Maximum grazing rate [1/day] +epsilon3 = 0.64 ! Half-saturation constant [(mmol N)²/m⁶] +loss_miczoo = 0.01 ! Extracellular N degradation [1/day] +res_miczoo = 0.01 ! Respiration + mortality [1/day] + +! --- Grazing Preferences --- +pzDia3 = 0.5 ! Diatom preference +sDiaNsq3 = 0.0 ! Diatom preference slope +pzPhy3 = 1.0 ! Small phyto preference +sPhyNsq3 = 0.0 ! Small phyto preference slope +pzCocco3 = 0.0 ! Coccolithophore preference (unused) +sCoccoNsq3 = 0.0 ! Coccolithophore preference slope +/ + +! ============================================================================ +! GRAZING ON DETRITUS +! ============================================================================ &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 -/ - +! --- First Zooplankton (Microzooplankton) --- +pzDet = 0.5 ! Small detritus preference +sDetNsq = 0.0 ! Small detritus preference slope +pzDetZ2 = 0.5 ! Large detritus preference +sDetZ2Nsq = 0.0 ! Large detritus preference slope + +! --- Second Zooplankton (Mesozooplankton) --- +pzDet2 = 0.5 ! Small detritus preference +sDetNsq2 = 0.0 ! Small detritus preference slope +pzDetZ22 = 0.5 ! Large detritus preference +sDetZ2Nsq2 = 0.0 ! Large detritus preference slope +/ + +! ============================================================================ +! AGGREGATION +! ============================================================================ &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) +agg_PD = 0.165 ! Detritus aggregation rate [m³/(mmol N·day)] +agg_PP = 0.015 ! Plankton aggregation rate [m³/(mmol N·day)] / +! ============================================================================ +! DISSOLVED ORGANIC MATTER REMINERALIZATION +! ============================================================================ &padin_rho_N -rho_N = 0.11d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) (Remineralization of DON) +rho_N = 0.11 ! DON remineralization rate [1/day] +rho_Nt = 0.67d0 ! [1/day] terrestrial N degradation of extracellular organic N (DONt) (Remineralization of terrestrial DON) ~ scale of 1.5 years ! R2OMIP / &padic_rho_C1 -rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradation of extracellular organic C (EOC) +rho_C1 = 0.1 ! DOC remineralization rate [1/day] / +! ============================================================================ +! PHYTOPLANKTON LOSSES +! ============================================================================ &paphytoplankton_N -lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds -lossN_d = 0.05d0 -lossN_c = 0.05d0 ! NEW +lossN = 0.05 ! Small phyto N loss rate [1/day] +lossN_d = 0.05 ! Diatom N loss rate [1/day] +lossN_c = 0.05 ! Coccolithophore N loss rate [1/day] / &paphytoplankton_C -lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon -lossC_d = 0.10d0 -lossC_c = 0.10d0 ! NEW +lossC = 0.10 ! Small phyto C loss rate [1/day] +lossC_d = 0.10 ! Diatom C loss rate [1/day] +lossC_c = 0.10 ! Coccolithophore C loss rate [1/day] / &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) +deg_Chl = 0.25 !0.2 !0.25 ! Small phyto Chl degradation [1/day] +deg_Chl_d = 0.15 !0.2 !0.15 ! Diatom Chl degradation [1/day] +deg_Chl_c = 0.2 ! Coccolithophore Chl degradation [1/day] / +! ============================================================================ +! DETRITUS REMINERALIZATION +! ============================================================================ &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 +gfin = 0.3 ! First zooplankton grazing efficiency +grazEff2 = 0.8 ! Second zooplankton grazing efficiency +grazEff3 = 0.8 ! Third zooplankton grazing efficiency +reminN = 0.165 ! Detritus N remineralization rate [1/day] / &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 +reminC = 0.15 ! Detritus C remineralization rate [1/day] +rho_c2 = 0.1 ! TEP-C degradation rate [1/day] / +! ============================================================================ +! ZOOPLANKTON LOSSES +! ============================================================================ &paheterotrophs -lossN_z = 0.1d0 -lossC_z = 0.1d0 +lossN_z = 0.1 ! First zooplankton N loss [1/day] +lossC_z = 0.1 ! First zooplankton C loss [1/day] / &paseczooloss -lossN_z2 = 0.02d0 -lossC_z2 = 0.02d0 +lossN_z2 = 0.02 ! Second zooplankton N loss [1/day] +lossC_z2 = 0.02 ! Second zooplankton C loss [1/day] / &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] +lossN_z3 = 0.05 ! Third zooplankton N loss [1/day] +lossC_z3 = 0.05 ! Third zooplankton C loss [1/day] +/ + +! ============================================================================ +! CO2 LIMITATION PARAMETERS +! ============================================================================ +&paco2lim +Cunits = 976.5625 ! Unit conversion factor: mol/m³ → µmol/kg + +! --- Small Phytoplankton --- +a_co2_phy = 1.162e+00 ! Dimensionless +b_co2_phy = 4.888e+01 ! [mol/kg] +c_co2_phy = 2.255e-01 ! [kg/mol] +d_co2_phy = 1.023e+07 ! [kg/mol] + +! --- Diatoms --- +a_co2_dia = 1.040e+00 ! Dimensionless +b_co2_dia = 2.890e+01 ! [mol/kg] +c_co2_dia = 8.778e-01 ! [kg/mol] +d_co2_dia = 2.640e+06 ! [kg/mol] + +! --- Coccolithophores --- +a_co2_cocco = 1.109e+00 ! Dimensionless (growth) +b_co2_cocco = 3.767e+01 ! [mol/kg] (growth) +c_co2_cocco = 3.912e-01 ! [kg/mol] (growth) +d_co2_cocco = 9.450e+06 ! [kg/mol] (growth) + +a_co2_calc = 1.102e+00 ! Dimensionless (calcification) +b_co2_calc = 4.238e+01 ! [mol/kg] (calcification) +c_co2_calc = 7.079e-01 ! [kg/mol] (calcification) +d_co2_calc = 1.343e+07 ! [kg/mol] (calcification) / &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 +Fe2N = 0.033 ! Iron to nitrogen ratio (= Fe2C × 6.625) +Fe2N_benthos = 0.15 ! Benthic flux ratio [micromol Fe : mmol N,] +kScavFe = 0.07 ! Iron scavenging rate [1/day] +dust_sol = 0.02 ! Dust iron solubility fraction +RiverFeConc = 100 ! Riverine iron concentration [µmol/m³] / +! ============================================================================ +! CALCITE PRODUCTION AND DISSOLUTION +! ============================================================================ &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 +calc_prod_ratio = 0.02 ! Calcite production ratio (CaCO₃:POC) +calc_diss_guts = 0.0 ! Gut dissolution fraction (set to 0 if OmegaC_diss=.false.) +calc_diss_rate = 0.005714 ! Standard dissolution rate [1/day] = 20/3500 +calc_diss_rate2 = 0.005714 ! Standard dissolution rate [1/day] +calc_diss_omegac = 0.197 ! Critical Ω_calcite (Aumont et al. 2015) +calc_diss_exp = 1.0 ! Dissolution rate exponent / +! ============================================================================ +! BENTHIC PROCESSES +! ============================================================================ &pabenthos_decay_rate -decayRateBenN = 0.005d0 -decayRateBenC = 0.005d0 -decayRateBenSi = 0.005d0 -q_NC_Denit = 0.86d0 ! N:C quota of the denitrification process +decayRateBenN = 0.005 ! Benthic N decay rate [1/day] +decayRateBenC = 0.005 ! Benthic C decay rate [1/day] +decayRateBenSi = 0.005 ! Benthic Si decay rate [1/day] +q_NC_Denit = 0.86 ! N:C quota for denitrification / +! ============================================================================ +! AIR-SEA CO2 FLUX +! ============================================================================ &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 +permil = 0.000000976 ! DIC conversion: mmol/m³ → mol/kg (1e-3/1024.5) +permeg = 1.e-6 ! Pressure conversion: µatm → atm +!X1 = exp(-5.0*log(10.0)) ! Lowest ph-value = 7.7 (phlo) +!X2 = exp(-9.0*log(10.0)) ! Highest ph-value = 9.5 (phhi) +Xacc = 1.e-12 ! pH iteration accuracy +CO2_for_spinup = 278.0 ! Pre-industrial atmospheric pCO₂ [µatm] / +! ============================================================================ +! ALKALINITY RESTORING +! ============================================================================ &paalkalinity_restoring -surf_relax_Alk = 3.2e-07 !10.d0/31536000.d0 +surf_relax_Alk = 3.2e-07 ! Surface alkalinity relaxation [1/s] = 10 days⁻¹ / +! ============================================================================ +! BALLASTING AND DENSITY-DEPENDENT SINKING +! ============================================================================ &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) -/ - +! --- Particle Densities [kg/m³] --- +rho_POC = 1033.0 ! POC density +rho_PON = 1033.0 ! PON density +rho_CaCO3 = 2830.0 ! Calcite density +rho_opal = 2090.0 ! Biogenic opal density +rho_ref_part = 1230.0 ! Reference particle density +rho_ref_water = 1027.0 ! Reference seawater density + +! --- Viscosity and Sinking --- +visc_ref_water = 0.00158 ! Reference seawater viscosity [kg·m⁻¹·s⁻¹] at 4°C +w_ref1 = 10.0 ! Reference sinking velocity, small detritus [m/day] +w_ref2 = 200.0 ! Reference sinking velocity, large detritus [m/day] +depth_scaling1 = 0.015 ! Depth-dependent increase sinking speed of det1 [1/day] +depth_scaling2 = 0.0 ! Depth-dependent increase sinking speed of det2 [1/day] +max_sinking_velocity = 250.0 ! Maximum sinking velocity [m/day] (numerical stability) +/ + +! ============================================================================ +! CARBON ISOTOPES (¹³C AND ¹⁴C) +! ============================================================================ &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 +ciso_init = .false. ! Initialize with fractionated organic matter +ciso_14 = .false. ! Include inorganic radiocarbon (¹⁴C-DIC) +ciso_organic_14 = .false. ! Include organic radiocarbon (¹⁴C-POC/DOC) +lambda_14 = 3.8561e-12 ! ¹⁴C decay constant [s⁻¹] (5730 yr half-life) +delta_CO2_13 = -6.61 ! Atmospheric δ¹³C [‰] (global mean) + +! --- Atmospheric Δ¹⁴C 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 +atbox_spinup = .false. +cosmic_14_init = 2.0 / - diff --git a/config/bin_2p3z2d/job_albedo b/config/bin_2p3z2d/job_albedo index 5f3c516e7..23caf2e11 100755 --- a/config/bin_2p3z2d/job_albedo +++ b/config/bin_2p3z2d/job_albedo @@ -1,16 +1,15 @@ #!/bin/bash -#SBATCH --account=nwg_hauck.maresys # edit your account +#SBATCH --account=biogeo_model.biogeo_model # edit your account #SBATCH --job-name=recom #SBATCH --partition=mpp #SBATCH --time=01:30:00 -####SBATCH --constraint="[rack1|rack3]" #SBATCH --qos=12h #SBATCH --nodes=9 # Number of tasks (MPI) tasks to be launched #SBATCH --tasks-per-node 96 #8 #4 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O #SBATCH --cpus-per-task 1 -#SBATCH -o fesom2o.out -#SBATCH -e fesom2e.out +#SBATCH -o slurm-out.out +#SBATCH -e slurm-err.out # disable hyperthreading #SBATCH --hint=nomultithread @@ -35,23 +34,22 @@ cp -n ../config/namelist.icepack . #___DETERMINE SLURM JOBID+OUTPUTFILE____________________________________________ jobid=$(echo $SLURM_JOB_ID | cut -d"." -f1) -fname="fesom2_${SLURM_JOB_NAME}_${jobid}.out" +fname="fesom2.0.out" #___PUT JOB IN QUEUE____________________________________________________________ date -####srun --mpi=pmi2 ./fesom.x >> ${fname} srun --mpi=pmi2 ./fesom.x > fesom2.0.out date #qstat -f $PBS_JOBID #export EXITSTATUS=$? #if [ ${EXITSTATUS} -eq 0 ] || [ ${EXITSTATUS} -eq 127 ] ; then -#sbatch job_ollie +#sbatch job_albedo #fi -#Resultpath='/albedo/scratch/user/ogurses/ocean_only/' -Resultpath='/albedo/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags_3Zoo2Det_v3/' -test -d $Resultpath/fesom.2019.oce.restart && exit + +Resultpath='/albedo/scratch/user/XXXX/' +test -e $Resultpath/fesom.XXXX.oce.restart && exit IsInFile=$( tail -3 fesom2.0.out | grep -c timesteps) if (( IsInFile > 0 )); then diff --git a/config/bin_2p3z2d/namelist.config b/config/bin_2p3z2d/namelist.config index 25c5e4a31..27c3d140a 100644 --- a/config/bin_2p3z2d/namelist.config +++ b/config/bin_2p3z2d/namelist.config @@ -1,67 +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/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags_3Zoo2Det_v3/' +MeshPath = '/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' ! path to mesh files (nod2d.out, elem2d.out, etc.) +ClimateDataPath = '/albedo/work/projects/MarESys/ogurses/input/corrected_input/' ! path to initial conditions (temperature, salinity) +ResultPath = '/albedo/scratch/user/XXXX' / +! ============================================================================ +! 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 = 'off' ! unit: 'y', 'm', 'd', 'h', 's', 'off' +bin_restart_length = 1 ! frequency for binary derived type restart files +bin_restart_length_unit = 'off' ! 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 = .false. ! 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_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. ! 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.forcing b/config/bin_2p3z2d/namelist.forcing index a17799393..d890c69ec 100644 --- a/config/bin_2p3z2d/namelist.forcing +++ b/config/bin_2p3z2d/namelist.forcing @@ -23,11 +23,23 @@ ncar_bulk_z_shum=10.0 ! height at which humi forcing is located (CORE, JRA-do: 1 use_landice_water=.false. landice_start_mon=5 landice_end_mon=10 +fwf_path='./mesh/' + +/ + +&age_tracer +use_age_tracer=.false. +use_age_mask=.false. +age_tracer_path='./mesh/' +age_start_year=2000 + / &nam_sbc nm_xwind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 nm_ywind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 + nm_xstre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 + nm_ystre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 nm_humi_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/huss.clim61' ! name of file with humidity nm_qsr_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rsds.clim61' ! name of file with solar heat nm_qlw_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rlds.clim61' ! name of file with Long wave @@ -37,24 +49,32 @@ landice_end_mon=10 nm_mslp_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/psl.clim61' ! air_pressure_at_sea_level nm_xwind_var = 'uas' ! name of variable in file with wind nm_ywind_var = 'vas' ! name of variable in file with wind - nm_humi_var = 'huss' ! name of variable in file with humidity - nm_qsr_var = 'rsds' ! name of variable in file with solar heat - nm_qlw_var = 'rlds' ! name of variable in file with Long wave + nm_xstre_var = 'uas' ! name of variable in file with wind + nm_ystre_var = 'vas' ! name of variable in file with wind + nm_humi_var = 'huss' ! name of variable in file with humidity + nm_qsr_var = 'rsds' ! name of variable in file with solar heat + nm_qlw_var = 'rlds' ! name of variable in file with Long wave nm_tair_var = 'tas' ! name of variable in file with 2m air temperature - nm_prec_var = 'prra' ! name of variable in file with total precipitation - nm_snow_var = 'prsn' ! name of variable in file with total precipitation - nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level + nm_prec_var = 'prra' ! name of variable in file with total precipitation + nm_snow_var = 'prsn' ! name of variable in file with total precipitation + nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level nm_nc_iyear = 1900 nm_nc_imm = 1 ! initial month of time axis in netCDF nm_nc_idd = 1 ! initial day of time axis in netCDF nm_nc_freq = 1 ! data points per day (i.e. 86400 if the time axis is in seconds) nm_nc_tmid = 0 ! 1 if the time stamps are given at the mid points of the netcdf file, 0 otherwise (i.e. 1 in CORE1, CORE2; 0 in JRA55) y_perpetual=.true. - l_xwind=.true. l_ywind=.true. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. + l_xwind=.true. l_ywind=.true. l_xstre=.false. l_ystre=.false. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. nm_runoff_file ='/albedo/pool/FESOM/forcing/CORE2/runoff.nc' runoff_data_source ='CORE2' !Dai09, CORE2 !runoff_data_source ='Dai09' !Dai09, CORE2, JRA55 !runoff_climatology =.true. - nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' sss_data_source ='CORE2' + nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' + chl_data_source ='None' !'Sweeney' monthly chlorophyll climatology or 'NONE' for constant chl_const (below). Make use_sw_pene=.TRUE. in namelist.config! + nm_chl_data_file ='/pool/data/AWICM/FESOM2/FORCING/JRA55-do-v1.4.0/Sweeney/Sweeney_2005.nc' + chl_const = 0.1 + use_runoff_mapper = .FALSE. + runoff_basins_file = 'runoff_maps_regular.nc' + runoff_radius = 500000. / diff --git a/config/bin_2p3z2d/namelist.recom b/config/bin_2p3z2d/namelist.recom index 24145b956..f04a4a97e 100644 --- a/config/bin_2p3z2d/namelist.recom +++ b/config/bin_2p3z2d/namelist.recom @@ -1,355 +1,516 @@ -! This is the namelist file for recom - +! ============================================================================ +! ============ Namelist file for REcoM Biogeochemical Model ================= +! ============================================================================ +! Regional Ecosystem Model (REcoM) configuration +! This file controls biogeochemical processes including: +! - Carbon, nitrogen, silicon, iron cycling +! - Phytoplankton (small phyto, diatoms, coccolithophores) +! - Zooplankton (micro, meso, krill) +! - Organic matter remineralization and sinking +! - Carbonate chemistry and air-sea CO2 fluxes +! - External nutrient inputs (dust, rivers, erosion) +! ============================================================================ + +! ============================================================================ +! DATA SOURCES AND INPUT FILES +! ============================================================================ &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' +nm_co2_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/MonthlyAtmCO2_gcb2024.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 = 2022 ! 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 +! ============================================================================ +! GENERAL MODEL CONFIGURATION +! ============================================================================ +&parecomsetup +enable_3zoo2det = .true. ! Enable 3 zooplankton + 2 detritus configuration +enable_coccos = .false. ! Enable coccolithophores (currently disabled) / +! ============================================================================ +! MAIN MODEL SWITCHES AND SETTINGS +! ============================================================================ +! --- Core Model Settings --- +&pavariables +use_REcoM = .true. +REcoM_restart = .true. +recom_debug = .false. + +! --- Tracer Configuration --- +bgc_num = 30 ! Total number of BGC tracers +diags3d_num = 28 ! Number of diagnostic 3D tracers +bgc_base_num = 22 ! Number of standard tracers +benthos_num = 4 ! Number of benthic BGC tracers (8 if ciso=.true., else 4) +sedflx_num = 0 ! Sediment fluxes from MEDUSA (0 = use defaults) +bottflx_num = 4 ! Bottom fluxes (8 if ciso & ciso_14, 6 if not ciso_14, 4 otherwise) + +! --- Sinking Velocities [m/day] --- +VDet = 20.0 ! Small detritus sinking velocity (constant, positive down) +VDet_zoo2 = 200.0 ! Large detritus sinking velocity +VPhy = 0.0 ! Small phytoplankton (non-sinking) +VDia = 0.0 ! Diatoms (variable sinking if allow_var_sinking=.true.) +VCocco = 0.0 ! Coccolithophores +allow_var_sinking = .true. ! Enable variable sinking velocity + +! --- Time Stepping --- +biostep = 1 ! Number of biology sub-steps per physical time step + +! --- Process Switches --- +REcoM_Geider_limiter = .false. ! Use Geider limiter for nutrient limitation +REcoM_Grazing_Variable_Preference = .true. ! Variable grazing preference (PhyN vs DiaN) +Grazing_detritus = .true. ! Enable zooplankton grazing on detritus +het_resp_noredfield = .true. ! Non-Redfield respiration for copepods +diatom_mucus = .true. ! Nutrient-limited diatom aggregation +O2dep_remin = .true. ! O2-dependent organic matter remineralization +use_ballasting = .true. ! Ballast effect on sinking +use_density_scaling = .true. ! Density-dependent sinking +use_viscosity_scaling = .true. ! Viscosity-dependent sinking +OmegaC_diss = .false. ! OmegaC-dependent calcite dissolution (set calc_diss_guts=0 if false) +CO2lim = .true. ! CO2 effects on growth and calcification +use_photodamage = .true. ! Chlorophyll photodamage (Alvarez et al. 2018) +HetRespFlux_plus = .true. ! Stabilized zooplankton respiration computation +Diags = .true. ! Enable diagnostics output + +! --- External Inputs --- +constant_CO2 = .true. +UseFeDust = .true. ! Enable iron input from dust +UseDustClim = .true. ! Use dust climatology +UseDustClimAlbani = .true. ! Use Albani dust fields (false = Mahowald) +useRivers = .false. ! Enable riverine inputs +useRivFe = .false. ! Enable riverine iron source +useErosion = .false. ! Enable erosion inputs +NitrogenSS = .false. ! Enable nitrogen sources/sinks (rivers, aeolian, denitrification) +useAeolianN = .false. ! Enable aeolian nitrogen deposition + +! --- Time Period Configuration --- +firstyearoffesomcycle = 1958 ! First year of physical forcing (e.g., JRA-55) +lastyearoffesomcycle = 2024 ! Last year of physical forcing +numofCO2cycles = 1 ! Number of forcing cycles +currentCO2cycle = 1 ! Current forcing cycle number + +! --- Alkalinity and Carbon --- +DIC_PI = .true. ! Use pre-industrial DIC +restore_alkalinity = .true. ! Restore surface alkalinity +Nmocsy = 1 ! Vector length for mocsy (always 1 for REcoM) + +! --- Data Path --- +REcoMDataPath = '/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/' + +! --- Carbon Isotopes --- +ciso = .false. ! Enable carbon isotopes (13C, 14C) + +! --- Sediment Model --- +use_MEDUSA = .false. ! Enable MEDUSA sediment model +add_loopback = .false. ! Add loopback fluxes through rivers +lb_tscale = 1.0 ! Loopback timescale [1/year] + +! --- Miscellaneous --- +use_atbox = .false. ! Use atmospheric box model +/ + +! ============================================================================ +! SINKING VELOCITY PARAMETERS +! ============================================================================ &pasinking -Vdet_a = 0.0288 ! [1/day] -Vcalc = 0.0144 ! [1/day] +Vdet_a = 0.0288 ! Slope of the linearly increasing sinking velocity [1/day] +Vcalc = 0.0144 ! Depth dependence of calcite dissolution (when use_coccos disabled) [1/day] / +! ============================================================================ +! INITIAL CONDITIONS +! ============================================================================ &painitialization_N -cPhyN = 0.2d0 -cHetN = 0.2d0 -cZoo2N = 0.2d0 +cPhyN = 0.2 ! Initial small phytoplankton nitrogen [mmol N/m³] +cHetN = 0.2 ! Initial microzooplankton nitrogen [mmol N/m³] +cZoo2N = 0.2 ! Initial mesozooplankton nitrogen [mmol N/m³] / +! ============================================================================ +! TEMPERATURE DEPENDENCE (ARRHENIUS) +! ============================================================================ &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 +recom_Tref = 288.15 ! Reference temperature [K] +C2K = 273.15 ! Celsius to Kelvin conversion +Ae = 4500.0 ! Arrhenius slope [K] +reminSi = 0.02 ! Silicate remineralization base rate [1/day] +k_o2_remin = 15.0 ! Half-saturation for O2 remineralization [mmol O2/m³] / &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 -/ - +! --- Limitation Function Slopes --- +NMinSlope = 50.0 ! Nitrogen minimum slope +SiMinSlope = 1000.0 ! Silicon minimum slope + +! --- Minimum Quotas [mmol/mmol C] --- +NCmin = 0.04 ! Small phytoplankton N:C minimum +NCmin_d = 0.04 ! Diatom N:C minimum +NCmin_c = 0.04 ! Coccolithophore N:C minimum +SiCmin = 0.04 ! Diatom Si:C minimum + +! --- Half-Saturation Constants --- +k_Fe = 0.04 ! Small phyto iron half-sat [µmol Fe/m³] +k_Fe_d = 0.12 ! Diatom iron half-sat [µmol Fe/m³] +k_Fe_c = 0.09 ! Coccolith iron half-sat [µmol Fe/m³] +k_si = 4.0 ! Silicon half-sat [mmol Si/m³] + +! --- Maximum Photosynthesis Rates [1/day] --- +P_cm = 3.0 ! Small phytoplankton max C-specific photosynthesis +P_cm_d = 3.5 ! Diatom max C-specific photosynthesis +P_cm_c = 2.8 ! Coccolithophore max C-specific photosynthesis +/ + +! ============================================================================ +! LIGHT ATTENUATION +! ============================================================================ &palight_calculations -k_w = 0.04d0 ! [1/m] Light attenuation coefficient -a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific attenuation coefficients +k_w = 0.04 ! Water attenuation coefficient [1/m] +a_chl = 0.03 ! Chlorophyll-specific attenuation [1/m per mg Chl/m³] / +! ============================================================================ +! PHOTOSYNTHESIS (P-I CURVE) +! ============================================================================ &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 +alfa = 0.14 ! Small phyto initial P-I slope [(mmol C·m²)/(mg Chl·W·day)] +alfa_d = 0.19 ! Diatom initial P-I slope +alfa_c = 0.10 ! Coccolithophore initial P-I slope +parFrac = 0.43 ! Fraction of shortwave that is PAR / +! ============================================================================ +! NUTRIENT ASSIMILATION +! ============================================================================ &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 -/ - +! --- Maximum Uptake Scaling --- +V_cm_fact = 0.7 ! Small phyto N-uptake scaling factor +V_cm_fact_d = 0.7 ! Diatom N-uptake scaling factor +V_cm_fact_c = 0.7 ! Coccolithophore N-uptake scaling factor + +! --- Limitation Function Slopes --- +NMaxSlope = 1000.0 ! Nitrogen maximum slope +SiMaxSlope = 1000.0 ! Silicon maximum slope + +! --- Maximum Cell Quotas [mmol/mmol C] --- +NCmax = 0.2 ! Small phyto maximum N:C +NCmax_d = 0.2 ! Diatom maximum N:C +NCmax_c = 0.15 ! Coccolithophore maximum N:C +SiCmax = 0.8 ! Diatom maximum Si:C + +! --- Maximum Uptake Ratios [mmol/mmol C] --- +NCuptakeRatio = 0.2 ! Small phyto N:C uptake ratio +NCUptakeRatio_d = 0.2 ! Diatom N:C uptake ratio +NCUptakeRatio_c = 0.2 ! Coccolithophore N:C uptake ratio +SiCUptakeRatio = 0.2 ! Diatom Si:C uptake ratio + +! --- Chlorophyll Parameters --- +Chl2N_max = 3.15 ! Small phyto max Chl:N [mg Chl/mmol N] +Chl2N_max_d = 4.2 ! Diatom max Chl:N [mg Chl/mmol N] +Chl2N_max_c = 3.5 ! Coccolithophore max Chl:N [mg Chl/mmol N] + +! --- Half-Saturation Constants --- +k_din = 0.55 ! Small phyto nitrate half-sat [mmol N/m³] +k_din_d = 1.0 ! Diatom nitrate half-sat [mmol N/m³] +k_din_c = 0.9 ! Coccolith nitrate half-sat [mmol N/m³] + +! --- Respiration and Biosynthesis --- +res_phy = 0.01 ! Small phyto maintenance respiration [1/day] +res_phy_d = 0.01 ! Diatom maintenance respiration [1/day] +res_phy_c = 0.01 ! Coccolithophore maintenance respiration [1/day] +biosynth = 2.33 ! Cost of biosynthesis [mmol C/mmol N] +biosynthSi = 0.0 ! Silicon biosynthesis cost [mmol C/mmol Si] +/ + +! ============================================================================ +! IRON CHEMISTRY +! ============================================================================ &pairon_chem -totalligand = 1.d0 ! [mumol/m3] order 1. Total free ligand -ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron stability constant +totalligand = 1.0 ! Total free ligand concentration [µmol/m³] +ligandStabConst = 100.0 ! Ligand-Fe stability constant [m³/µmol] / +! ============================================================================ +! MICROZOOPLANKTON (FIRST ZOOPLANKTON) +! ============================================================================ &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. -/ - +graz_max = 0.31 ! Maximum grazing rate [1/day] +epsilonr = 0.09 ! Half-saturation constant [(mmol N)²/m⁶] +res_het = 0.028 ! Respiration + mortality [1/day] +Redfield = 6.625 ! C:N Redfield ratio [mmol C/mmol N] +loss_het = 0.04 ! Extracellular N degradation [1/day] +tiny_het = 1.d-5 ! Small number for stable computation + +! --- Grazing Preferences --- +pzDia = 0.5 ! Diatom preference (maximum) +sDiaNsq = 0.0 ! Diatom preference slope +pzPhy = 0.04 ! Small phyto preference +sPhyNsq = 0.0 ! Small phyto preference slope +pzCocco = 0.4 ! Coccolithophore preference (unused in 2p3z3d) +sCoccoNsq = 0.0 ! Coccolithophore preference slope +pzMicZoo = 1.0 ! Microzooplankton preference (self-grazing) +sMicZooNsq = 0.0 ! Microzooplankton preference slope +/ + +! ============================================================================ +! MESOZOOPLANKTON (SECOND ZOOPLANKTON) +! ============================================================================ &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 -/ - +graz_max2 = 0.1 ! Maximum grazing rate [1/day] +epsilon2 = 0.0144 ! Half-saturation constant [(mmol N)²/m⁶] +res_zoo2 = 0.0107 ! Respiration + mortality [1/day] +loss_zoo2 = 0.003 ! Extracellular N degradation [1/day] + +! --- Fecal Pellet Production --- +fecal_rate_n = 0.104 ! Nitrogen fecal rate [1/day] +fecal_rate_c = 0.236 ! Carbon fecal rate [1/day] +fecal_rate_n_mes = 0.25 ! Mesozooplankton N fecal rate [1/day] +fecal_rate_c_mes = 0.32 ! Mesozooplankton C fecal rate [1/day] + +! --- Grazing Preferences --- +pzDia2 = 1.0 ! Diatom preference +sDiaNsq2 = 0.0 ! Diatom preference slope +pzPhy2 = 0.07 ! Small phyto preference +sPhyNsq2 = 0.0 ! Small phyto preference slope +pzCocco2 = 0.7 ! Coccolithophore preference (unused) +sCoccoNsq2 = 0.0 ! Coccolithophore preference slope +pzHet = 1.5 ! Microzooplankton preference +sHetNsq = 0.0 ! Microzooplankton preference slope +pzMicZoo2 = 1.0 ! Mesozooplankton preference +sMicZooNsq2 = 0.0 ! Mesozooplankton preference slope + +! --- Temperature Function (Krill-specific) --- +t1_zoo2 = 28145.0 ! Temperature function constant 1 +t2_zoo2 = 272.5 ! Temperature function constant 2 [K] +t3_zoo2 = 105234.0 ! Temperature function constant 3 +t4_zoo2 = 274.15 ! Temperature function constant 4 [K] +/ + +! ============================================================================ +! MICROZOOPLANKTON (THIRD ZOOPLANKTON) +! ============================================================================ &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 -/ - +graz_max3 = 0.46 ! Maximum grazing rate [1/day] +epsilon3 = 0.64 ! Half-saturation constant [(mmol N)²/m⁶] +loss_miczoo = 0.01 ! Extracellular N degradation [1/day] +res_miczoo = 0.02 ! Respiration + mortality [1/day] + +! --- Grazing Preferences --- +pzDia3 = 0.04 ! Diatom preference +sDiaNsq3 = 0.0 ! Diatom preference slope +pzPhy3 = 0.07 ! Small phyto preference +sPhyNsq3 = 0.0 ! Small phyto preference slope +pzCocco3 = 0.7 ! Coccolithophore preference (unused) +sCoccoNsq3 = 0.0 ! Coccolithophore preference slope +/ + +! ============================================================================ +! GRAZING ON DETRITUS +! ============================================================================ &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 -/ - +! --- First Zooplankton (Microzooplankton) --- +pzDet = 0.5 ! Small detritus preference +sDetNsq = 0.0 ! Small detritus preference slope +pzDetZ2 = 0.5 ! Large detritus preference +sDetZ2Nsq = 0.0 ! Large detritus preference slope + +! --- Second Zooplankton (Mesozooplankton) --- +pzDet2 = 0.5 ! Small detritus preference +sDetNsq2 = 0.0 ! Small detritus preference slope +pzDetZ22 = 0.5 ! Large detritus preference +sDetZ2Nsq2 = 0.0 ! Large detritus preference slope +/ + +! ============================================================================ +! AGGREGATION +! ============================================================================ &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) +agg_PD = 0.165 ! Detritus aggregation rate [m³/(mmol N·day)] +agg_PP = 0.015 ! Plankton aggregation rate [m³/(mmol N·day)] / +! ============================================================================ +! DISSOLVED ORGANIC MATTER REMINERALIZATION +! ============================================================================ &padin_rho_N -rho_N = 0.11d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) (Remineralization of DON) +rho_N = 0.11 ! DON remineralization rate [1/day] +rho_Nt = 0.67d0 ! [1/day] terrestrial N degradation of extracellular organic N (DONt) (Remineralization of terrestrial DON) ~ scale of 1.5 years ! R2OMIP / &padic_rho_C1 -rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradation of extracellular organic C (EOC) +rho_C1 = 0.1 ! DOC remineralization rate [1/day] / +! ============================================================================ +! PHYTOPLANKTON LOSSES +! ============================================================================ &paphytoplankton_N -lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds -lossN_d = 0.05d0 -lossN_c = 0.05d0 ! NEW +lossN = 0.05 ! Small phyto N loss rate [1/day] +lossN_d = 0.05 ! Diatom N loss rate [1/day] +lossN_c = 0.05 ! Coccolithophore N loss rate [1/day] / &paphytoplankton_C -lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon -lossC_d = 0.10d0 -lossC_c = 0.10d0 ! NEW +lossC = 0.10 ! Small phyto C loss rate [1/day] +lossC_d = 0.10 ! Diatom C loss rate [1/day] +lossC_c = 0.10 ! Coccolithophore C loss rate [1/day] / &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) +deg_Chl = 0.25 !0.2 !0.25 ! Small phyto Chl degradation [1/day] +deg_Chl_d = 0.15 !0.2 !0.15 ! Diatom Chl degradation [1/day] +deg_Chl_c = 0.2 ! Coccolithophore Chl degradation [1/day] / +! ============================================================================ +! DETRITUS REMINERALIZATION +! ============================================================================ &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 +gfin = 0.3 ! First zooplankton grazing efficiency +grazEff2 = 0.8 ! Second zooplankton grazing efficiency +grazEff3 = 0.8 ! Third zooplankton grazing efficiency +reminN = 0.165 ! Detritus N remineralization rate [1/day] / &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 +reminC = 0.15 ! Detritus C remineralization rate [1/day] +rho_c2 = 0.1 ! TEP-C degradation rate [1/day] / +! ============================================================================ +! ZOOPLANKTON LOSSES +! ============================================================================ &paheterotrophs -lossN_z = 0.1d0 -lossC_z = 0.1d0 +lossN_z = 0.1 ! First zooplankton N loss [1/day] +lossC_z = 0.1 ! First zooplankton C loss [1/day] / &paseczooloss -lossN_z2 = 0.02d0 -lossC_z2 = 0.02d0 +lossN_z2 = 0.02 ! Second zooplankton N loss [1/day] +lossC_z2 = 0.02 ! Second zooplankton C loss [1/day] / &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] +lossN_z3 = 0.05 ! Third zooplankton N loss [1/day] +lossC_z3 = 0.05 ! Third zooplankton C loss [1/day] +/ + +! ============================================================================ +! CO2 LIMITATION PARAMETERS +! ============================================================================ +&paco2lim +Cunits = 976.5625 ! Unit conversion factor: mol/m³ → µmol/kg + +! --- Small Phytoplankton --- +a_co2_phy = 1.162e+00 ! Dimensionless +b_co2_phy = 4.888e+01 ! [mol/kg] +c_co2_phy = 2.255e-01 ! [kg/mol] +d_co2_phy = 1.023e+07 ! [kg/mol] + +! --- Diatoms --- +a_co2_dia = 1.040e+00 ! Dimensionless +b_co2_dia = 2.890e+01 ! [mol/kg] +c_co2_dia = 8.778e-01 ! [kg/mol] +d_co2_dia = 2.640e+06 ! [kg/mol] + +! --- Coccolithophores --- +a_co2_cocco = 1.109e+00 ! Dimensionless (growth) +b_co2_cocco = 3.767e+01 ! [mol/kg] (growth) +c_co2_cocco = 3.912e-01 ! [kg/mol] (growth) +d_co2_cocco = 9.450e+06 ! [kg/mol] (growth) + +a_co2_calc = 1.102e+00 ! Dimensionless (calcification) +b_co2_calc = 4.238e+01 ! [mol/kg] (calcification) +c_co2_calc = 7.079e-01 ! [kg/mol] (calcification) +d_co2_calc = 1.343e+07 ! [kg/mol] (calcification) / &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 +Fe2N = 0.033 ! Iron to nitrogen ratio (= Fe2C × 6.625) +Fe2N_benthos = 0.15 ! Benthic flux ratio [micromol Fe : mmol N,] +kScavFe = 0.07 ! Iron scavenging rate [1/day] +dust_sol = 0.02 ! Dust iron solubility fraction +RiverFeConc = 100 ! Riverine iron concentration [µmol/m³] / +! ============================================================================ +! CALCITE PRODUCTION AND DISSOLUTION +! ============================================================================ &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 +calc_prod_ratio = 0.02 ! Calcite production ratio (CaCO₃:POC) +calc_diss_guts = 0.0 ! Gut dissolution fraction (set to 0 if OmegaC_diss=.false.) +calc_diss_rate = 0.005714 ! Standard dissolution rate [1/day] = 20/3500 +calc_diss_rate2 = 0.005714 ! Standard dissolution rate [1/day] +calc_diss_omegac = 0.197 ! Critical Ω_calcite (Aumont et al. 2015) +calc_diss_exp = 1.0 ! Dissolution rate exponent / +! ============================================================================ +! BENTHIC PROCESSES +! ============================================================================ &pabenthos_decay_rate -decayRateBenN = 0.005d0 -decayRateBenC = 0.005d0 -decayRateBenSi = 0.005d0 -q_NC_Denit = 0.86d0 ! N:C quota of the denitrification process +decayRateBenN = 0.005 ! Benthic N decay rate [1/day] +decayRateBenC = 0.005 ! Benthic C decay rate [1/day] +decayRateBenSi = 0.005 ! Benthic Si decay rate [1/day] +q_NC_Denit = 0.86 ! N:C quota for denitrification / +! ============================================================================ +! AIR-SEA CO2 FLUX +! ============================================================================ &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 +permil = 0.000000976 ! DIC conversion: mmol/m³ → mol/kg (1e-3/1024.5) +permeg = 1.e-6 ! Pressure conversion: µatm → atm +!X1 = exp(-5.0*log(10.0)) ! Lowest ph-value = 7.7 (phlo) +!X2 = exp(-9.0*log(10.0)) ! Highest ph-value = 9.5 (phhi) +Xacc = 1.e-12 ! pH iteration accuracy +CO2_for_spinup = 278.0 ! Pre-industrial atmospheric pCO₂ [µatm] / +! ============================================================================ +! ALKALINITY RESTORING +! ============================================================================ &paalkalinity_restoring -surf_relax_Alk = 3.2e-07 !10.d0/31536000.d0 +surf_relax_Alk = 3.2e-07 ! Surface alkalinity relaxation [1/s] = 10 days⁻¹ / +! ============================================================================ +! BALLASTING AND DENSITY-DEPENDENT SINKING +! ============================================================================ &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) -/ - +! --- Particle Densities [kg/m³] --- +rho_POC = 1033.0 ! POC density +rho_PON = 1033.0 ! PON density +rho_CaCO3 = 2830.0 ! Calcite density +rho_opal = 2090.0 ! Biogenic opal density +rho_ref_part = 1230.0 ! Reference particle density +rho_ref_water = 1027.0 ! Reference seawater density + +! --- Viscosity and Sinking --- +visc_ref_water = 0.00158 ! Reference seawater viscosity [kg·m⁻¹·s⁻¹] at 4°C +w_ref1 = 10.0 ! Reference sinking velocity, small detritus [m/day] +w_ref2 = 200.0 ! Reference sinking velocity, large detritus [m/day] +depth_scaling1 = 0.01 ! Depth-dependent increase sinking speed of det1 [1/day] +depth_scaling2 = 0.0 ! Depth-dependent increase sinking speed of det2 [1/day] +max_sinking_velocity = 250.0 ! Maximum sinking velocity [m/day] (numerical stability) +/ + +! ============================================================================ +! CARBON ISOTOPES (¹³C AND ¹⁴C) +! ============================================================================ &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 +ciso_init = .false. ! Initialize with fractionated organic matter +ciso_14 = .false. ! Include inorganic radiocarbon (¹⁴C-DIC) +ciso_organic_14 = .false. ! Include organic radiocarbon (¹⁴C-POC/DOC) +lambda_14 = 3.8561e-12 ! ¹⁴C decay constant [s⁻¹] (5730 yr half-life) +delta_CO2_13 = -6.61 ! Atmospheric δ¹³C [‰] (global mean) + +! --- Atmospheric Δ¹⁴C 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 +atbox_spinup = .false. +cosmic_14_init = 2.0 / - diff --git a/config/bin_3p3z2d/namelist.config b/config/bin_3p3z2d/namelist.config deleted file mode 100644 index 9a048d633..000000000 --- a/config/bin_3p3z2d/namelist.config +++ /dev/null @@ -1,67 +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/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags_3Zoo2Det_coccos/' -/ - -&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. -/ - -&machine -n_levels=2 -n_part= 12, 36 ! 432 number of partitions on each hierarchy level -/ diff --git a/config/bin_3p3z2d/job_albedo b/config/bin_4p3z2d/job_albedo similarity index 78% rename from config/bin_3p3z2d/job_albedo rename to config/bin_4p3z2d/job_albedo index 9eff795cb..23caf2e11 100755 --- a/config/bin_3p3z2d/job_albedo +++ b/config/bin_4p3z2d/job_albedo @@ -1,16 +1,15 @@ #!/bin/bash -#SBATCH --account=nwg_hauck.maresys # edit your account +#SBATCH --account=biogeo_model.biogeo_model # edit your account #SBATCH --job-name=recom #SBATCH --partition=mpp #SBATCH --time=01:30:00 -####SBATCH --constraint="[rack1|rack3]" #SBATCH --qos=12h #SBATCH --nodes=9 # Number of tasks (MPI) tasks to be launched #SBATCH --tasks-per-node 96 #8 #4 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O #SBATCH --cpus-per-task 1 -#SBATCH -o fesom2o.out -#SBATCH -e fesom2e.out +#SBATCH -o slurm-out.out +#SBATCH -e slurm-err.out # disable hyperthreading #SBATCH --hint=nomultithread @@ -35,23 +34,22 @@ cp -n ../config/namelist.icepack . #___DETERMINE SLURM JOBID+OUTPUTFILE____________________________________________ jobid=$(echo $SLURM_JOB_ID | cut -d"." -f1) -fname="fesom2_${SLURM_JOB_NAME}_${jobid}.out" +fname="fesom2.0.out" #___PUT JOB IN QUEUE____________________________________________________________ date -####srun --mpi=pmi2 ./fesom.x >> ${fname} srun --mpi=pmi2 ./fesom.x > fesom2.0.out date #qstat -f $PBS_JOBID #export EXITSTATUS=$? #if [ ${EXITSTATUS} -eq 0 ] || [ ${EXITSTATUS} -eq 127 ] ; then -#sbatch job_ollie +#sbatch job_albedo #fi -#Resultpath='/albedo/scratch/user/ogurses/ocean_only/' -Resultpath='/albedo/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags_3Zoo2Det_coccos/' -test -d $Resultpath/fesom.2019.oce.restart && exit + +Resultpath='/albedo/scratch/user/XXXX/' +test -e $Resultpath/fesom.XXXX.oce.restart && exit IsInFile=$( tail -3 fesom2.0.out | grep -c timesteps) if (( IsInFile > 0 )); then diff --git a/config/bin_4p3z2d/namelist.config b/config/bin_4p3z2d/namelist.config new file mode 100644 index 000000000..27c3d140a --- /dev/null +++ b/config/bin_4p3z2d/namelist.config @@ -0,0 +1,133 @@ +! ============================================================================ +! ============ 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' ! run identifier (used in output filenames) +/ + +! ============================================================================ +! TIME STEPPING AND RUN LENGTH +! ============================================================================ +×tep +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) +/ + +! ============================================================================ +! 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/' ! path to mesh files (nod2d.out, elem2d.out, etc.) +ClimateDataPath = '/albedo/work/projects/MarESys/ogurses/input/corrected_input/' ! path to initial conditions (temperature, salinity) +ResultPath = '/albedo/scratch/user/XXXX' +/ + +! ============================================================================ +! RESTART AND LOGGING CONFIGURATION +! ============================================================================ +&restart_log +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 = 'off' ! unit: 'y', 'm', 'd', 'h', 's', 'off' +bin_restart_length = 1 ! frequency for binary derived type restart files +bin_restart_length_unit = 'off' ! 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' ! 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. ! 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 leap years in calendar (false = 365-day year, true = 365/366-day year) +/ + +! ============================================================================ +! MODEL COMPONENTS AND FEATURES +! ============================================================================ +&run_config +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 ! 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. ! 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_3p3z2d/namelist.dyn b/config/bin_4p3z2d/namelist.dyn similarity index 100% rename from config/bin_3p3z2d/namelist.dyn rename to config/bin_4p3z2d/namelist.dyn diff --git a/config/bin_3p3z2d/namelist.forcing b/config/bin_4p3z2d/namelist.forcing similarity index 65% rename from config/bin_3p3z2d/namelist.forcing rename to config/bin_4p3z2d/namelist.forcing index a17799393..d890c69ec 100644 --- a/config/bin_3p3z2d/namelist.forcing +++ b/config/bin_4p3z2d/namelist.forcing @@ -23,11 +23,23 @@ ncar_bulk_z_shum=10.0 ! height at which humi forcing is located (CORE, JRA-do: 1 use_landice_water=.false. landice_start_mon=5 landice_end_mon=10 +fwf_path='./mesh/' + +/ + +&age_tracer +use_age_tracer=.false. +use_age_mask=.false. +age_tracer_path='./mesh/' +age_start_year=2000 + / &nam_sbc nm_xwind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 nm_ywind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 + nm_xstre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 + nm_ystre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 nm_humi_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/huss.clim61' ! name of file with humidity nm_qsr_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rsds.clim61' ! name of file with solar heat nm_qlw_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rlds.clim61' ! name of file with Long wave @@ -37,24 +49,32 @@ landice_end_mon=10 nm_mslp_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/psl.clim61' ! air_pressure_at_sea_level nm_xwind_var = 'uas' ! name of variable in file with wind nm_ywind_var = 'vas' ! name of variable in file with wind - nm_humi_var = 'huss' ! name of variable in file with humidity - nm_qsr_var = 'rsds' ! name of variable in file with solar heat - nm_qlw_var = 'rlds' ! name of variable in file with Long wave + nm_xstre_var = 'uas' ! name of variable in file with wind + nm_ystre_var = 'vas' ! name of variable in file with wind + nm_humi_var = 'huss' ! name of variable in file with humidity + nm_qsr_var = 'rsds' ! name of variable in file with solar heat + nm_qlw_var = 'rlds' ! name of variable in file with Long wave nm_tair_var = 'tas' ! name of variable in file with 2m air temperature - nm_prec_var = 'prra' ! name of variable in file with total precipitation - nm_snow_var = 'prsn' ! name of variable in file with total precipitation - nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level + nm_prec_var = 'prra' ! name of variable in file with total precipitation + nm_snow_var = 'prsn' ! name of variable in file with total precipitation + nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level nm_nc_iyear = 1900 nm_nc_imm = 1 ! initial month of time axis in netCDF nm_nc_idd = 1 ! initial day of time axis in netCDF nm_nc_freq = 1 ! data points per day (i.e. 86400 if the time axis is in seconds) nm_nc_tmid = 0 ! 1 if the time stamps are given at the mid points of the netcdf file, 0 otherwise (i.e. 1 in CORE1, CORE2; 0 in JRA55) y_perpetual=.true. - l_xwind=.true. l_ywind=.true. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. + l_xwind=.true. l_ywind=.true. l_xstre=.false. l_ystre=.false. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. nm_runoff_file ='/albedo/pool/FESOM/forcing/CORE2/runoff.nc' runoff_data_source ='CORE2' !Dai09, CORE2 !runoff_data_source ='Dai09' !Dai09, CORE2, JRA55 !runoff_climatology =.true. - nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' sss_data_source ='CORE2' + nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' + chl_data_source ='None' !'Sweeney' monthly chlorophyll climatology or 'NONE' for constant chl_const (below). Make use_sw_pene=.TRUE. in namelist.config! + nm_chl_data_file ='/pool/data/AWICM/FESOM2/FORCING/JRA55-do-v1.4.0/Sweeney/Sweeney_2005.nc' + chl_const = 0.1 + use_runoff_mapper = .FALSE. + runoff_basins_file = 'runoff_maps_regular.nc' + runoff_radius = 500000. / diff --git a/config/bin_3p3z2d/namelist.ice b/config/bin_4p3z2d/namelist.ice similarity index 100% rename from config/bin_3p3z2d/namelist.ice rename to config/bin_4p3z2d/namelist.ice diff --git a/config/bin_3p3z2d/namelist.icepack b/config/bin_4p3z2d/namelist.icepack similarity index 100% rename from config/bin_3p3z2d/namelist.icepack rename to config/bin_4p3z2d/namelist.icepack diff --git a/config/bin_3p3z2d/namelist.io b/config/bin_4p3z2d/namelist.io similarity index 57% rename from config/bin_3p3z2d/namelist.io rename to config/bin_4p3z2d/namelist.io index b1d4c18e6..b66adf757 100644 --- a/config/bin_3p3z2d/namelist.io +++ b/config/bin_4p3z2d/namelist.io @@ -12,7 +12,7 @@ ldiag_extflds =.false. / &nml_general -io_listsize =100 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list +io_listsize =150 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list vec_autorotate =.false. / @@ -72,6 +72,25 @@ io_list = 'sst ',1, 'm', 4, 'NPPn ',1, 'm', 4, 'NPPc ',1, 'm', 4, 'PAR ',1, 'm', 4, + 'CO2 ',1, 'm', 4, + 'pH ',1, 'm', 4, + 'pCO2 ',1, 'm', 4, + 'HCO3 ',1, 'm', 4, + 'CO3 ',1, 'm', 4, + 'OmegaC ',1, 'm', 4, + 'kspc ',1, 'm', 4, + 'rhoSW ',1, 'm', 4, + 'wsink_det1',1, 'm', 8, + 'wsink_det2',1, 'm', 8, + 'rho_det1',1, 'm', 8, + 'rho_det2',1, 'm', 8, + 'scaling_rho_1',1, 'm', 8, + 'scaling_rho_2',1, 'm', 8, + 'scaling_visc',1, 'm', 8, + 'grazmeso_tot',1, 'm', 4, + 'grazmeso_n',1, 'm', 4, + 'grazmeso_d',1, 'm', 4, + 'grazmeso_c',1, 'm', 4, 'respmeso',1, 'm', 4, 'respmacro',1, 'm', 4, 'respmicro',1, 'm', 4, @@ -86,4 +105,33 @@ io_list = 'sst ',1, 'm', 4, 'respn',1, 'm', 4, 'respd',1, 'm', 4, 'respc',1, 'm', 4, + 'NPPp ',1, 'm', 4, + 'GPPp ',1, 'm', 4, + 'NNAp ',1, 'm', 4, + 'Chldegp ',1, 'm', 4, + 'grazmeso_p',1, 'm', 4, + 'aggp ',1, 'm', 4, + 'respp ',1, 'm', 4, + 'docexp ',1, 'm', 4, + 'TTemp_diatoms',1, 'm', 4, + 'TTemp_phyto',1, 'm', 4, + 'TTemp_cocco',1, 'm', 4, + 'TTemp_phaeo',1, 'm', 4, + 'TPhyCO2 ',1, 'm', 4, + 'TDiaCO2 ',1, 'm', 4, + 'TCoccoCO2 ',1, 'm', 4, + 'TPhaeoCO2 ',1, 'm', 4, + 'TqLF_phyto ',1, 'm', 4, + 'TqLF_diatoms',1, 'm', 4, + 'TqLF_cocco ',1, 'm', 4, + 'TqLF_phaeo ',1, 'm', 4, + 'TCphotLL_phyto ',1, 'm', 4, + 'TCphotLL_dia ',1, 'm', 4, + 'TCphotLL_cocco ',1, 'm', 4, + 'TCphotLL_phaeo ',1, 'm', 4, + 'TCphot_phyto',1, 'm', 4, + 'TCphot_diatoms',1, 'm', 4, + 'TCphot_cocco',1, 'm', 4, + 'TCphot_phaeo',1, 'm', 4, + 'TSi_assimDia',1, 'm', 4, / diff --git a/config/bin_3p3z2d/namelist.oce b/config/bin_4p3z2d/namelist.oce similarity index 100% rename from config/bin_3p3z2d/namelist.oce rename to config/bin_4p3z2d/namelist.oce diff --git a/config/bin_4p3z2d/namelist.recom b/config/bin_4p3z2d/namelist.recom new file mode 100644 index 000000000..ee098cc1e --- /dev/null +++ b/config/bin_4p3z2d/namelist.recom @@ -0,0 +1,554 @@ +! ============================================================================ +! ============ Namelist file for REcoM Biogeochemical Model ================= +! ============================================================================ +! Regional Ecosystem Model (REcoM) configuration +! This file controls biogeochemical processes including: +! - Carbon, nitrogen, silicon, iron cycling +! - Phytoplankton (small phyto, diatoms, coccolithophores) +! - Zooplankton (micro, meso, krill) +! - Organic matter remineralization and sinking +! - Carbonate chemistry and air-sea CO2 fluxes +! - External nutrient inputs (dust, rivers, erosion) +! ============================================================================ + +! ============================================================================ +! DATA SOURCES AND INPUT FILES +! ============================================================================ +&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_gcb2024.nc' +/ + +! ============================================================================ +! GENERAL MODEL CONFIGURATION +! ============================================================================ +&parecomsetup +enable_3zoo2det = .true. ! Enable 3 zooplankton + 2 detritus configuration +enable_coccos = .true. ! Enable coccolithophores +/ + +! ============================================================================ +! MAIN MODEL SWITCHES AND SETTINGS +! ============================================================================ +! --- Core Model Settings --- +&pavariables +use_REcoM = .true. +REcoM_restart = .true. +recom_debug = .false. + +! --- Tracer Configuration --- +bgc_num = 36 ! Total number of BGC tracers +diags3d_num = 31 ! Number of diagnostic 3D tracers +bgc_base_num = 22 ! Number of standard tracers +benthos_num = 4 ! Number of benthic BGC tracers (8 if ciso=.true., else 4) +sedflx_num = 0 ! Sediment fluxes from MEDUSA (0 = use defaults) +bottflx_num = 4 ! Bottom fluxes (8 if ciso & ciso_14, 6 if not ciso_14, 4 otherwise) + +! --- Sinking Velocities [m/day] --- +VDet = 20.0 ! Small detritus sinking velocity (constant, positive down) +VDet_zoo2 = 200.0 ! Large detritus sinking velocity +VPhy = 0.0 ! Small phytoplankton (non-sinking) +VDia = 0.0 ! Diatoms (variable sinking if allow_var_sinking=.true.) +VCocco = 0.0 ! Coccolithophores +VPhaeo = 0.0 +allow_var_sinking = .true. ! Enable variable sinking velocity + +! --- Time Stepping --- +biostep = 1 ! Number of biology sub-steps per physical time step + +! --- Process Switches --- +REcoM_Geider_limiter = .false. ! Use Geider limiter for nutrient limitation +REcoM_Grazing_Variable_Preference = .true. ! Variable grazing preference (PhyN vs DiaN) +Grazing_detritus = .true. ! Enable zooplankton grazing on detritus +het_resp_noredfield = .true. ! Non-Redfield respiration for copepods +diatom_mucus = .true. ! Nutrient-limited diatom aggregation +O2dep_remin = .true. ! O2-dependent organic matter remineralization +use_ballasting = .true. ! Ballast effect on sinking +use_density_scaling = .true. ! Density-dependent sinking +use_viscosity_scaling = .true. ! Viscosity-dependent sinking +OmegaC_diss = .true. ! OmegaC-dependent calcite dissolution (set calc_diss_guts=0 if false) +CO2lim = .true. ! CO2 effects on growth and calcification +use_photodamage = .true. ! Chlorophyll photodamage (Alvarez et al. 2018) +HetRespFlux_plus = .true. ! Stabilized zooplankton respiration computation +Diags = .true. ! Enable diagnostics output + +! --- External Inputs --- +constant_CO2 = .true. +UseFeDust = .true. ! Enable iron input from dust +UseDustClim = .true. ! Use dust climatology +UseDustClimAlbani = .true. ! Use Albani dust fields (false = Mahowald) +useRivers = .false. ! Enable riverine inputs +useRivFe = .false. ! Enable riverine iron source +useErosion = .false. ! Enable erosion inputs +NitrogenSS = .false. ! Enable nitrogen sources/sinks (rivers, aeolian, denitrification) +useAeolianN = .false. ! Enable aeolian nitrogen deposition + +! --- Time Period Configuration --- +firstyearoffesomcycle = 1958 ! First year of physical forcing (e.g., JRA-55) +lastyearoffesomcycle = 2024 ! Last year of physical forcing +numofCO2cycles = 1 ! Number of forcing cycles +currentCO2cycle = 1 ! Current forcing cycle number + +! --- Alkalinity and Carbon --- +DIC_PI = .true. ! Use pre-industrial DIC +restore_alkalinity = .true. ! Restore surface alkalinity +Nmocsy = 1 ! Vector length for mocsy (always 1 for REcoM) + +! --- Data Path --- +REcoMDataPath = '/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/' + +! --- Carbon Isotopes --- +ciso = .false. ! Enable carbon isotopes (13C, 14C) + +! --- Sediment Model --- +use_MEDUSA = .false. ! Enable MEDUSA sediment model +add_loopback = .false. ! Add loopback fluxes through rivers +lb_tscale = 1.0 ! Loopback timescale [1/year] + +! --- Miscellaneous --- +use_atbox = .false. ! Use atmospheric box model +/ + +! ============================================================================ +! SINKING VELOCITY PARAMETERS +! ============================================================================ +&pasinking +Vdet_a = 0.0288 ! Slope of the linearly increasing sinking velocity [1/day] +Vcalc = 0.0144 ! Depth dependence of calcite dissolution (when use_coccos disabled) [1/day] +/ + +! ============================================================================ +! INITIAL CONDITIONS +! ============================================================================ +&painitialization_N +cPhyN = 0.2 ! Initial small phytoplankton nitrogen [mmol N/m³] +cHetN = 0.2 ! Initial microzooplankton nitrogen [mmol N/m³] +cZoo2N = 0.2 ! Initial mesozooplankton nitrogen [mmol N/m³] +/ + +! ============================================================================ +! TEMPERATURE DEPENDENCE (ARRHENIUS) +! ============================================================================ +&paArrhenius +recom_Tref = 288.15 ! Reference temperature [K] +C2K = 273.15 ! Celsius to Kelvin conversion +Ae = 4500.0 ! Arrhenius slope [K] +Tmax_phaeo = 16.0 ! [°C] For Blanchard temp fxn: maximum temperature +Topt_phaeo = 6.7982 ! [°C] For Blanchard temp fxn: optimum temperature +uopt_phaeo = 0.6903 ! [1/day] For Blanchard temp fxn: optimum growth rate +beta_phaeo = 0.7114 ! [unitless] For Blanchard temp fxn +ord_d = -0.2216 ! diatom ordonnée +expon_d = 0.0406 ! diatom exponent +ord_phy = -0.7338 ! small phyto ordonnée +expon_phy = 0.06422 ! small phyto exponent +ord_cocco = -0.2310 ! coccolitho ordonnée +expon_cocco = 0.0327 ! coccolitho exponent +ord_phaeo = -0.2310 ! phaeocystis ordonnée +expon_phaeo = 0.0327 ! phaeocystis exponent +reminSi = 0.02 ! Silicate remineralization base rate [1/day] +k_o2_remin = 15.0 ! Half-saturation for O2 remineralization [mmol O2/m³] +/ + +&palimiter_function +! --- Limitation Function Slopes --- +NMinSlope = 50.0 ! Nitrogen minimum slope +SiMinSlope = 1000.0 ! Silicon minimum slope + +! --- Minimum Quotas [mmol/mmol C] --- +NCmin = 0.04 ! Small phytoplankton N:C minimum +NCmin_d = 0.04 ! Diatom N:C minimum +NCmin_c = 0.04 ! Coccolithophore N:C minimum +NCmin_p = 0.04 ! Phaeocystis N:C minimum +SiCmin = 0.04 ! Diatom Si:C minimum + +! --- Half-Saturation Constants --- +k_Fe = 0.04 ! Small phyto iron half-sat [µmol Fe/m³] +k_Fe_d = 0.12 ! Diatom iron half-sat [µmol Fe/m³] +k_Fe_c = 0.09 ! Coccolith iron half-sat [µmol Fe/m³] +k_Fe_p = 0.09 ! NEW for Phaeocystis (to be tuned) +k_si = 4.0 ! Silicon half-sat [mmol Si/m³] + +! --- Maximum Photosynthesis Rates [1/day] --- +P_cm = 3.0 ! Small phytoplankton max C-specific photosynthesis +P_cm_d = 3.5 ! Diatom max C-specific photosynthesis +P_cm_c = 2.8 ! Coccolithophore max C-specific photosynthesis +P_cm_p = 0.75 ! NEW for Phaeocystis (to be tuned) +/ + +! ============================================================================ +! LIGHT ATTENUATION +! ============================================================================ +&palight_calculations +k_w = 0.04 ! Water attenuation coefficient [1/m] +a_chl = 0.03 ! Chlorophyll-specific attenuation [1/m per mg Chl/m³] +/ + +! ============================================================================ +! PHOTOSYNTHESIS (P-I CURVE) +! ============================================================================ +&paphotosynthesis +alfa = 0.14 ! Small phyto initial P-I slope [(mmol C·m²)/(mg Chl·W·day)] +alfa_d = 0.19 ! Diatom initial P-I slope +alfa_c = 0.10 ! Coccolithophore initial P-I slope +alfa_p = 0.17 ! Phaeocystis initial P-I slope (to be tuned) +parFrac = 0.43 ! Fraction of shortwave that is PAR +/ + +! ============================================================================ +! NUTRIENT ASSIMILATION +! ============================================================================ +&paassimilation +! --- Maximum Uptake Scaling --- +V_cm_fact = 0.7 ! Small phyto N-uptake scaling factor +V_cm_fact_d = 0.7 ! Diatom N-uptake scaling factor +V_cm_fact_c = 0.7 ! Coccolithophore N-uptake scaling factor +V_cm_fact_p = 0.7 ! NEW for Phaeocystis + +! --- Limitation Function Slopes --- +NMaxSlope = 1000.0 ! Nitrogen maximum slope +SiMaxSlope = 1000.0 ! Silicon maximum slope + +! --- Maximum Cell Quotas [mmol/mmol C] --- +NCmax = 0.2 ! Small phyto maximum N:C +NCmax_d = 0.2 ! Diatom maximum N:C +NCmax_c = 0.15 ! Coccolithophore maximum N:C +NCmax_p = 0.15 ! Phaeocystis maximum N:C (to be tuned) +SiCmax = 0.8 ! Diatom maximum Si:C + +! --- Maximum Uptake Ratios [mmol/mmol C] --- +NCuptakeRatio = 0.2 ! Small phyto N:C uptake ratio +NCUptakeRatio_d = 0.2 ! Diatom N:C uptake ratio +NCUptakeRatio_c = 0.2 ! Coccolithophore N:C uptake ratio +NCUptakeRatio_p = 0.2 ! NEW for Phaeocystis +SiCUptakeRatio = 0.2 ! Diatom Si:C uptake ratio + +! --- Chlorophyll Parameters --- +Chl2N_max = 3.15 ! Small phyto max Chl:N [mg Chl/mmol N] +Chl2N_max_d = 4.2 ! Diatom max Chl:N [mg Chl/mmol N] +Chl2N_max_c = 3.5 ! Coccolithophore max Chl:N [mg Chl/mmol N] +Chl2N_max_p = 2.6 ! NEW for Phaeocystis + +! --- Half-Saturation Constants --- +k_din = 0.55 ! Small phyto nitrate half-sat [mmol N/m³] +k_din_d = 1.0 ! Diatom nitrate half-sat [mmol N/m³] +k_din_c = 0.9 ! Coccolith nitrate half-sat [mmol N/m³] +k_din_p = 0.7 ! NEW for Phaeocystis (to be tuned) + +! --- Respiration and Biosynthesis --- +res_phy = 0.01 ! Small phyto maintenance respiration [1/day] +res_phy_d = 0.01 ! Diatom maintenance respiration [1/day] +res_phy_c = 0.01 ! Coccolithophore maintenance respiration [1/day] +res_phy_p = 0.01 ! NEW for phaeocystis +biosynth = 2.33 ! Cost of biosynthesis [mmol C/mmol N] +biosynthSi = 0.0 ! Silicon biosynthesis cost [mmol C/mmol Si] +/ + +! ============================================================================ +! IRON CHEMISTRY +! ============================================================================ +&pairon_chem +totalligand = 1.0 ! Total free ligand concentration [µmol/m³] +ligandStabConst = 100.0 ! Ligand-Fe stability constant [m³/µmol] +/ + +! ============================================================================ +! MICROZOOPLANKTON (FIRST ZOOPLANKTON) +! ============================================================================ +&pazooplankton +graz_max = 0.31 ! Maximum grazing rate [1/day] +epsilonr = 0.09 ! Half-saturation constant [(mmol N)²/m⁶] +res_het = 0.028 ! Respiration + mortality [1/day] +Redfield = 6.625 ! C:N Redfield ratio [mmol C/mmol N] +loss_het = 0.04 ! Extracellular N degradation [1/day] +tiny_het = 1.d-5 ! Small number for stable computation + +! --- Grazing Preferences --- +pzDia = 1.0 ! Diatom preference (maximum) NEW value for Phaeocystis +sDiaNsq = 0.0 ! Diatom preference slope +pzPhy = 0.5 ! Small phyto preference NEW value for Phaeocystis +sPhyNsq = 0.0 ! Small phyto preference slope +pzCocco = 0.666 ! Coccolithophore preference NEW value for Phaeocystis +sCoccoNsq = 0.0 ! Coccolithophore preference slope +pzPhaeo = 0.5 ! Phaeocystis preference +sPhaeoNsq = 0.0 ! Phaeocystis preference slope +pzMicZoo = 1.0 ! Microzooplankton preference (self-grazing) +sMicZooNsq = 0.0 ! Microzooplankton preference slope +/ + +! ============================================================================ +! MESOZOOPLANKTON (SECOND ZOOPLANKTON) +! ============================================================================ +&pasecondzooplankton +graz_max2 = 0.25 ! Maximum grazing rate [1/day] NEW value for Phaeocystis +epsilon2 = 0.0144 ! Half-saturation constant [(mmol N)²/m⁶] +res_zoo2 = 0.0107 ! Respiration + mortality [1/day] +loss_zoo2 = 0.003 ! Extracellular N degradation [1/day] + +! --- Fecal Pellet Production --- +fecal_rate_n = 0.104 ! Nitrogen fecal rate [1/day] +fecal_rate_c = 0.236 ! Carbon fecal rate [1/day] +fecal_rate_n_mes = 0.25 ! Mesozooplankton N fecal rate [1/day] +fecal_rate_c_mes = 0.32 ! Mesozooplankton C fecal rate [1/day] + +! --- Grazing Preferences --- +pzDia2 = 1.5 !1.0 ! Diatom preference NEW value for Phaeocystis +sDiaNsq2 = 0.0 ! Diatom preference slope +pzPhy2 = 0.5 !0.07 ! Small phyto preference NEW value for Phaeocystis +sPhyNsq2 = 0.0 ! Small phyto preference slope +pzCocco2 = 0.5 !0.7 ! Coccolithophore preference NEW value for Phaeocystis +sCoccoNsq2 = 0.0 ! Coccolithophore preference slope +pzPhaeo2 = 0.5 ! Phaeocystis preference +sPhaeoNsq2 = 0.0 ! Phaeocystis preference slope +pzHet = 1.5 ! Microzooplankton preference +sHetNsq = 0.0 ! Microzooplankton preference slope +pzMicZoo2 = 1.0 ! Mesozooplankton preference +sMicZooNsq2 = 0.0 ! Mesozooplankton preference slope + +! --- Temperature Function (Krill-specific) --- +t1_zoo2 = 28145.0 ! Temperature function constant 1 +t2_zoo2 = 272.5 ! Temperature function constant 2 [K] +t3_zoo2 = 105234.0 ! Temperature function constant 3 +t4_zoo2 = 274.15 ! Temperature function constant 4 [K] +/ + +! ============================================================================ +! MICROZOOPLANKTON (THIRD ZOOPLANKTON) +! ============================================================================ +&pathirdzooplankton +graz_max3 = 0.36 ! Maximum grazing rate [1/day] NEW value for Phaeocystis +epsilon3 = 0.64 ! Half-saturation constant [(mmol N)²/m⁶] +loss_miczoo = 0.01 ! Extracellular N degradation [1/day] +res_miczoo = 0.01 ! Respiration + mortality [1/day] NEW value for Phaeocystis + +! --- Grazing Preferences --- +pzDia3 = 0.5 !0.04 ! Maximum diatom preference NEW value for Phaeocystis +sDiaNsq3 = 0.0 ! Diatom preference slope +pzPhy3 = 1.0 !0.07 ! Small phyto preference NEW value for Phaeocystis +sPhyNsq3 = 0.0 ! Small phyto preference slope +pzCocco3 = 0.5 !0.7 ! Coccolithophore preference ATTENTION: This value needs to be tuned; I start with zero preference! ! NEW value for Phaeocystis +sCoccoNsq3 = 0.0 ! Coccolithophore preference slope +pzPhaeo3 = 0.25 ! Phaeocystis preference +sPhaeoNsq3 = 0.0 ! Phaeocystis preference slope +/ + +! ============================================================================ +! GRAZING ON DETRITUS +! ============================================================================ +&pagrazingdetritus +! --- First Zooplankton (Microzooplankton) --- +pzDet = 0.5 ! Small detritus preference +sDetNsq = 0.0 ! Small detritus preference slope +pzDetZ2 = 0.5 ! Large detritus preference +sDetZ2Nsq = 0.0 ! Large detritus preference slope + +! --- Second Zooplankton (Mesozooplankton) --- +pzDet2 = 0.5 ! Small detritus preference +sDetNsq2 = 0.0 ! Small detritus preference slope +pzDetZ22 = 0.5 ! Large detritus preference +sDetZ2Nsq2 = 0.0 ! Large detritus preference slope +/ + +! ============================================================================ +! AGGREGATION +! ============================================================================ +&paaggregation +agg_PD = 0.165 ! Detritus aggregation rate [m³/(mmol N·day)] +agg_PP = 0.015 ! Plankton aggregation rate [m³/(mmol N·day)] +/ + +! ============================================================================ +! DISSOLVED ORGANIC MATTER REMINERALIZATION +! ============================================================================ +&padin_rho_N +rho_N = 0.11 ! DON remineralization rate [1/day] +rho_Nt = 0.67d0 ! [1/day] terrestrial N degradation of extracellular organic N (DONt) (Remineralization of terrestrial DON) ~ scale of 1.5 years ! R2OMIP +/ + +&padic_rho_C1 +rho_C1 = 0.1 ! DOC remineralization rate [1/day] +/ + +! ============================================================================ +! PHYTOPLANKTON LOSSES +! ============================================================================ +&paphytoplankton_N +lossN = 0.05 ! Small phyto N loss rate [1/day] +lossN_d = 0.05 ! Diatom N loss rate [1/day] +lossN_c = 0.05 ! Coccolithophore N loss rate [1/day] +lossN_p = 0.05 ! NEW for Phaeocystis +/ + +&paphytoplankton_C +lossC = 0.10 ! Small phyto C loss rate [1/day] +lossC_d = 0.10 ! Diatom C loss rate [1/day] +lossC_c = 0.10 ! Coccolithophore C loss rate [1/day] +lossC_p = 0.10 ! NEW for Phaeocystis +/ + +&paphytoplankton_ChlA +deg_Chl = 0.15 !0.25 !0.2 ! Small phyto Chl degradation [1/day] +deg_Chl_d = 0.2 !0.15 ! Diatom Chl degradation [1/day] +deg_Chl_c = 0.2 ! Coccolithophore Chl degradation [1/day] +deg_Chl_p = 0.15 ! NEW for Phaeocystis +/ + +! ============================================================================ +! DETRITUS REMINERALIZATION +! ============================================================================ +&padetritus_N +gfin = 0.3 ! First zooplankton grazing efficiency +grazEff2 = 0.8 ! Second zooplankton grazing efficiency +grazEff3 = 0.8 ! Third zooplankton grazing efficiency +reminN = 0.165 ! Detritus N remineralization rate [1/day] +/ + +&padetritus_C +reminC = 0.15 ! Detritus C remineralization rate [1/day] +rho_c2 = 0.1 ! TEP-C degradation rate [1/day] +/ + +! ============================================================================ +! ZOOPLANKTON LOSSES +! ============================================================================ +&paheterotrophs +lossN_z = 0.1 ! First zooplankton N loss [1/day] +lossC_z = 0.1 ! First zooplankton C loss [1/day] +/ + +&paseczooloss +lossN_z2 = 0.02 ! Second zooplankton N loss [1/day] +lossC_z2 = 0.02 ! Second zooplankton C loss [1/day] +/ + +&pathirdzooloss +lossN_z3 = 0.05 ! Third zooplankton N loss [1/day] +lossC_z3 = 0.05 ! Third zooplankton C loss [1/day] +/ + +! ============================================================================ +! CO2 LIMITATION PARAMETERS +! ============================================================================ +&paco2lim +Cunits = 976.5625 ! Unit conversion factor: mol/m³ → µmol/kg + +! --- Small Phytoplankton --- +a_co2_phy = 1.162e+00 ! Dimensionless +b_co2_phy = 4.888e+01 ! [mol/kg] +c_co2_phy = 2.255e-01 ! [kg/mol] +d_co2_phy = 1.023e+07 ! [kg/mol] + +! --- Diatoms --- +a_co2_dia = 1.040e+00 ! Dimensionless +b_co2_dia = 2.890e+01 ! [mol/kg] +c_co2_dia = 8.778e-01 ! [kg/mol] +d_co2_dia = 2.640e+06 ! [kg/mol] + +! --- Coccolithophores --- +a_co2_cocco = 1.109e+00 ! Dimensionless (growth) +b_co2_cocco = 3.767e+01 ! [mol/kg] (growth) +c_co2_cocco = 3.912e-01 ! [kg/mol] (growth) +d_co2_cocco = 9.450e+06 ! [kg/mol] (growth) + +! --- Phaeocystis --- +a_co2_phaeo = 1.162e+00 ! Dimensionless +b_co2_phaeo = 4.888e+01 ! [mol/kg] +c_co2_phaeo = 2.255e-01 ! [kg/mol] +d_co2_phaeo = 1.023e+07 ! [kg/mol] + +a_co2_calc = 1.102e+00 ! Dimensionless (calcification) +b_co2_calc = 4.238e+01 ! [mol/kg] (calcification) +c_co2_calc = 7.079e-01 ! [kg/mol] (calcification) +d_co2_calc = 1.343e+07 ! [kg/mol] (calcification) +/ + +&pairon +Fe2N = 0.033 ! Iron to nitrogen ratio (= Fe2C × 6.625) +Fe2N_benthos = 0.15 ! Benthic flux ratio [micromol Fe : mmol N,] +kScavFe = 0.07 ! Iron scavenging rate [1/day] +dust_sol = 0.02 ! Dust iron solubility fraction +RiverFeConc = 100 ! Riverine iron concentration [µmol/m³] +/ + +! ============================================================================ +! CALCITE PRODUCTION AND DISSOLUTION +! ============================================================================ +&pacalc +calc_prod_ratio = 0.02 ! Calcite production ratio (CaCO₃:POC) +calc_diss_guts = 0.5 ! Gut dissolution fraction (set to 0 if OmegaC_diss=.false.) +calc_diss_rate = 0.005714 ! Standard dissolution rate [1/day] = 20/3500 +calc_diss_rate2 = 0.005714 ! Standard dissolution rate [1/day] +calc_diss_omegac = 0.197 ! Critical Ω_calcite (Aumont et al. 2015) +calc_diss_exp = 1.0 ! Dissolution rate exponent +/ + +! ============================================================================ +! BENTHIC PROCESSES +! ============================================================================ +&pabenthos_decay_rate +decayRateBenN = 0.005 ! Benthic N decay rate [1/day] +decayRateBenC = 0.005 ! Benthic C decay rate [1/day] +decayRateBenSi = 0.005 ! Benthic Si decay rate [1/day] +q_NC_Denit = 0.86 ! N:C quota for denitrification +/ + +! ============================================================================ +! AIR-SEA CO2 FLUX +! ============================================================================ +&paco2_flux_param +permil = 0.000000976 ! DIC conversion: mmol/m³ → mol/kg (1e-3/1024.5) +permeg = 1.e-6 ! Pressure conversion: µatm → atm +!X1 = exp(-5.0*log(10.0)) ! Lowest ph-value = 7.7 (phlo) +!X2 = exp(-9.0*log(10.0)) ! Highest ph-value = 9.5 (phhi) +Xacc = 1.e-12 ! pH iteration accuracy +CO2_for_spinup = 278.0 ! Pre-industrial atmospheric pCO₂ [µatm] +/ + +! ============================================================================ +! ALKALINITY RESTORING +! ============================================================================ +&paalkalinity_restoring +surf_relax_Alk = 3.2e-07 ! Surface alkalinity relaxation [1/s] = 10 days⁻¹ +/ + +! ============================================================================ +! BALLASTING AND DENSITY-DEPENDENT SINKING +! ============================================================================ +&paballasting +! --- Particle Densities [kg/m³] --- +rho_POC = 1033.0 ! POC density +rho_PON = 1033.0 ! PON density +rho_CaCO3 = 2830.0 ! Calcite density +rho_opal = 2090.0 ! Biogenic opal density +rho_ref_part = 1230.0 ! Reference particle density +rho_ref_water = 1027.0 ! Reference seawater density + +! --- Viscosity and Sinking --- +visc_ref_water = 0.00158 ! Reference seawater viscosity [kg·m⁻¹·s⁻¹] at 4°C +w_ref1 = 10.0 ! Reference sinking velocity, small detritus [m/day] +w_ref2 = 200.0 ! Reference sinking velocity, large detritus [m/day] +depth_scaling1 = 0.01 ! Depth-dependent increase sinking speed of det1 [1/day] +depth_scaling2 = 0.0 ! Depth-dependent increase sinking speed of det2 [1/day] +max_sinking_velocity = 250.0 ! Maximum sinking velocity [m/day] (numerical stability) +/ + +! ============================================================================ +! CARBON ISOTOPES (¹³C AND ¹⁴C) +! ============================================================================ +&paciso +ciso_init = .false. ! Initialize with fractionated organic matter +ciso_14 = .false. ! Include inorganic radiocarbon (¹⁴C-DIC) +ciso_organic_14 = .false. ! Include organic radiocarbon (¹⁴C-POC/DOC) +lambda_14 = 3.8561e-12 ! ¹⁴C decay constant [s⁻¹] (5730 yr half-life) +delta_CO2_13 = -6.61 ! Atmospheric δ¹³C [‰] (global mean) + +! --- Atmospheric Δ¹⁴C +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/bin_3p3z2d/namelist.tra b/config/bin_4p3z2d/namelist.tra similarity index 96% rename from config/bin_3p3z2d/namelist.tra rename to config/bin_4p3z2d/namelist.tra index 33be191e7..7fd6837a2 100644 --- a/config/bin_3p3z2d/namelist.tra +++ b/config/bin_4p3z2d/namelist.tra @@ -39,6 +39,9 @@ nml_tracer_list = 1031, 'MFCT', 'QR4C', 'FCT ', 1., 1., 1032, 'MFCT', 'QR4C', 'FCT ', 1., 1., 1033, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1034, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1035, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1036, 'MFCT', 'QR4C', 'FCT ', 1., 1., !101, 'UPW1', 'UPW1', 'NON ', 0., 0. / diff --git a/config/namelist.cvmix b/config/namelist.cvmix index 5c73d9403..58969e414 100644 --- a/config/namelist.cvmix +++ b/config/namelist.cvmix @@ -146,11 +146,11 @@ kpp_reduce_tauuice = .false. ! reduce wind stress (u*) under sea ice ! (MOST). The code logic probably augments or replaces parts of the standard boundary ! (layer similarity (or nonlocal mixing) using a Stokes‐drift‐aware correction. kpp_use_StokesMOST= .false. !.true. - + ! approximate proportionality between surface wind velocity and stokes velocity ! U_stokes ~ kpp_A_stokes * U_wind kpp_A_stokes = 0.005 ! a - + ! Langmuir option ! Option of Langmuir enhanced mixing apply an enhancement factor to the ! turbulent velocity scale @@ -159,7 +159,7 @@ kpp_A_stokes = 0.005 ! a ! (Langmuir_EFactor - cvmix_one) ! NONE - Langmuir switched off, MixingCoefEnhancement=1 kpp_langmuir_mixing= "NONE" !"LWF16" - + ! Option of Langmuir turbulence enhanced entrainment - modify the unresolved shear ! LWF16 - Li Q., Webb A., Fox-Kemper B., Craig A., Danabasoglu G., ! Large W., Vertenstein M., 2016, Langmuir mixing effects on diff --git a/setups/forcings.yml b/setups/forcings.yml index 5e71d53dd..3ad3dd46c 100644 --- a/setups/forcings.yml +++ b/setups/forcings.yml @@ -254,4 +254,66 @@ test_global: calendar: include_fleapyear: False +test_recom: + forcing_exchange_coeff: + Ce_atm_oce: 1.75e-3 + Ch_atm_oce: 1.75e-3 + Cd_atm_oce: 1.0e-3 + Ce_atm_ice: 1.75e-3 + Ch_atm_ice: 1.75e-3 + Cd_atm_ice: 1.2e-3 + forcing_bulk: + AOMIP_drag_coeff: False + ncar_bulk_formulae: True + ncar_bulk_z_wind: 10.0 + ncar_bulk_z_tair: 10.0 + ncar_bulk_z_shum: 10.0 + land_ice: + use_landice_water: False + landice_start_mon: 5 + landice_end_mon: 10 + nam_sbc: + nm_xwind_file: u_10. + nm_ywind_file: v_10. + nm_humi_file: q_10. + nm_qsr_file: ncar_rad. + nm_qlw_file: ncar_rad. + nm_tair_file: t_10. + nm_prec_file: ncar_precip. + nm_snow_file: ncar_precip. + nm_mslp_file: slp. + nm_xwind_var: U_10_MOD + nm_ywind_var: V_10_MOD + nm_humi_var: Q_10_MOD + nm_qsr_var: SWDN_MOD + nm_qlw_var: LWDN_MOD + nm_tair_var: T_10_MOD + nm_prec_var: RAIN + nm_snow_var: SNOW + nm_mslp_var: SLP + nm_nc_iyear: 1948 + nm_nc_imm: 1 + nm_nc_idd: 1 + nm_nc_freq: 1 + nm_nc_tmid: 1 + l_xwind: True + l_ywind: True + l_humi: True + l_qsr: True + l_qlw: True + l_tair: True + l_prec: True + l_mslp: False + l_cloud: False + l_snow: True + nm_runoff_file: runoff.nc + runoff_data_source: CORE2 + nm_sss_data_file: PHC2_salx.nc + sss_data_source: CORE2 + namelist.config: + clockinit: + yearnew: 1958 + calendar: + include_fleapyear: True + diff --git a/setups/paths.yml b/setups/paths.yml index 435cd6a86..09d5db735 100644 --- a/setups/paths.yml +++ b/setups/paths.yml @@ -62,9 +62,11 @@ docker: forcing: test_global: ./test/input/global/ test_icebergs: ./test/input/icebergs/ + test_recom: ./test/input/global/ clim: test_global: ./test/input/global/ test_icebergs: ./test/input/icebergs/ + test_recom: ./test/input/recom/ opath: opath: ./test/ diff --git a/setups/test_pi_recom/README.md b/setups/test_pi_recom/README.md new file mode 100644 index 000000000..64b45572f --- /dev/null +++ b/setups/test_pi_recom/README.md @@ -0,0 +1,74 @@ + REcoM Biogeochemistry CI Test + +This test validates FESOM2 with REcoM (Regulated Ecosystem Model) biogeochemistry module. + +## Test Configuration + +- **Mesh**: PI mesh (test_global) - ~3k nodes +- **Duration**: 1 day +- **Time steps**: 32 per day +- **Processes**: 2 MPI tasks +- **Features**: + - REcoM biogeochemistry (30 tracers) + - 3 zooplankton, 2 detritus groups + - Iron chemistry with dust input + - CO2 system (without calcification for this test) + +## Required Input Files + +All files are located in `test/input/recom/`: + +### REcoM-specific files: +- `DustClimMonthlyAlbani_pimesh.nc` - Dust deposition climatology +- `MonthlyAtmCO2_gcb2024.nc` - Atmospheric CO2 concentration +- `GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc` - Pre-industrial DIC (optional) + +### Initial conditions for biogeochemical tracers: +- `fe5deg.nc` - Iron (Fe) +- `oxy5deg.nc` - Oxygen +- `si5deg.nc` - Silicate +- `talk5deg.nc` - Total alkalinity +- `tco2_5deg.nc` - Total dissolved inorganic carbon +- `din5deg.nc` - Dissolved inorganic nitrogen +- `woa18_netcdf_5deg.nc` - Temperature and salinity + +## Build Instructions + +Compile FESOM2 with REcoM support: + +```bash +./configure.sh ubuntu -DRECOM_COUPLED=ON +``` + +## Running the Test + +### Local Docker Test: +```bash +mkrun recom test_pi_recom -m docker +cd work_recom +./job_docker_new +``` + +### CI Test (GitHub Actions): +The test runs automatically via `.github/workflows/fesom2_recom.yml` on pull requests to main branch. + +## Expected Outputs + +The test outputs daily averages for: +- Physical variables: SST, temperature, salinity, velocities, sea ice +- Biogeochemical variables: DIN (nitrogen), DIC (carbon) + +## Validation + +The `fcheck` values in `setup.yml` validate that: +1. Physical fields match baseline test_pi values +2. Biogeochemical tracers are within expected ranges: + - DIN: ~15 mmol/m³ (global mean) + - DIC: ~2100 mmol/m³ (global mean) + +## Notes + +- This test uses `REcoM_restart=False` for initialization from climatology +- Cavity is disabled (`use_cavity=False`) +- Uses standard PI mesh without cavity features +- Test follows the same pattern as icebergs and cavity tests diff --git a/config/bin_3p3z2d/namelist.recom b/setups/test_pi_recom/namelist.recom similarity index 72% rename from config/bin_3p3z2d/namelist.recom rename to setups/test_pi_recom/namelist.recom index 3679e244f..7d3677575 100644 --- a/config/bin_3p3z2d/namelist.recom +++ b/setups/test_pi_recom/namelist.recom @@ -2,25 +2,30 @@ &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' +nm_fe_data_file ='DustClimMonthlyAlbani_pimesh.nc' +nm_aen_data_file ='' +nm_river_data_file ='' +nm_erosion_data_file ='' +nm_co2_data_file ='MonthlyAtmCO2_gcb2024.nc' +/ + +&parecomsetup +enable_3zoo2det = .true. +enable_coccos = .false. / &pavariables use_REcoM =.true. -REcoM_restart =.true. +REcoM_restart =.false. -bgc_num = 33 !30 !22 !33 !24 !38 +bgc_num = 30 !24 !38 !22 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 +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 @@ -29,10 +34,10 @@ Grazing_detritus = .true. het_resp_noredfield = .true. ! Decides respiratation of copepod group diatom_mucus = .true. ! Decides nutrient limitation effect on aggregation O2dep_remin = .true. ! O2remin Add option for O2 dependency of organic matter remineralization -use_ballasting = .true. ! BALL -use_density_scaling = .true. ! BALL -use_viscosity_scaling = .true. ! BALL -OmegaC_diss = .true. ! DISS Use OmegaC from Mocsy to compute calcite dissolution (after Aumont et al. 2015 and Gehlen et al. 2007) +use_ballasting = .true. +use_density_scaling = .true. +use_viscosity_scaling = .true. +OmegaC_diss = .false. ! Use OmegaC from Mocsy to compute calcite dissolution (after Aumont et al. 2015 and Gehlen et al. 2007) -> set calc_diss_guts to zero if this is false!!!! CO2lim = .true. ! CO2 dependence of growth and calcification Diags = .true. constant_CO2 = .true. @@ -41,7 +46,7 @@ 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/' +REcoMDataPath = './' restore_alkalinity = .true. useRivers = .false. useRivFe = .false. ! When set to true, riverine Fe source is activated @@ -49,7 +54,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 -lastyearoffesomcycle = 2023 ! Last year of the actual physical forcing 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. @@ -81,23 +86,23 @@ 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 +k_o2_remin = 15.d0 ! 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 +NCmin = 0.04d0 +NCmin_d = 0.04d0 +NCmin_c = 0.04d0 SiCmin = 0.04d0 k_Fe = 0.04d0 k_Fe_d = 0.12d0 -k_Fe_c = 0.09d0 ! NEW +k_Fe_c = 0.09d0 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 +P_cm_c = 2.8d0 / &palight_calculations @@ -108,33 +113,33 @@ a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific at &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 +alfa_c = 0.10d0 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 +V_cm_fact_c = 0.7d0 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 +NCmax_c = 0.15d0 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 +NCUptakeRatio_c = 0.2d0 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 +k_din_c = 0.9d0 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 +Chl2N_max_c = 3.5d0 res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant res_phy_d = 0.01d0 -res_phy_c = 0.01d0 ! NEW +res_phy_c = 0.01d0 biosynth = 2.33d0 ! [mmol C/mmol N] Cost of biosynthesis biosynthSi = 0.d0 / @@ -145,19 +150,19 @@ ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron sta / &pazooplankton -graz_max = 0.31d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +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) +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 = 0.5d0 !1.0d0 !0.5d0 ! Maximum diatom preference +pzDia = 0.5d0 ! Maximum diatom preference sDiaNsq = 0.d0 -pzPhy = 0.04d0 !0.5d0 !0.25d0 !1.0d0 ! Maximum nano-phytoplankton preference (NEW: 3/12) +pzPhy = 0.04d0 ! Maximum small phytoplankton preference sPhyNsq = 0.d0 -pzCocco = 0.4d0 !0.666d0 ! NEW (8/12) -sCoccoNsq = 0.d0 ! NEW -pzMicZoo = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference -sMicZooNsq = 0.d0 ! NEW 3Zoo +pzCocco = 0.4d0 ! Maximum coccolithophore preference ! will not be used in the 2p3z3d version +sCoccoNsq = 0.d0 +pzMicZoo = 1.0d0 ! Maximum microzooplankton preference +sMicZooNsq = 0.d0 tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. / @@ -168,17 +173,17 @@ res_zoo2 = 0.0107d0 ! [1/day] Respiration by heterotrophs and mo 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.0d0 !1.5d0 !1.d0 ! Maximum diatom preference +fecal_rate_n_mes = 0.25d0 +fecal_rate_c_mes = 0.32d0 +pzDia2 = 1.0d0 ! Maximum diatom preference sDiaNsq2 = 0.d0 -pzPhy2 = 0.07d0 !0.5d0 ! Maximum diatom preference +pzPhy2 = 0.07d0 ! Maximum small phytoplankton preference sPhyNsq2 = 0.d0 -pzCocco2 = 0.7 !0.5d0 ! NEW -sCoccoNsq2 = 0.d0 ! NEW -pzHet = 1.5d0 !0.8d0 ! Maximum diatom preference +pzCocco2 = 0.7d0 ! Maximum coccolithophore preference ! will not be used in the 2p3z3d version +sCoccoNsq2 = 0.d0 +pzHet = 1.5d0 ! Maximum mesozooplankton preference sHetNsq = 0.d0 -pzMicZoo2 = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference +pzMicZoo2 = 1.0d0 ! Maximum microzooplankton preference sMicZooNsq2 = 0.d0 t1_zoo2 = 28145.d0 ! Krill temp. function constant1 t2_zoo2 = 272.5d0 ! Krill temp. function constant2 @@ -187,16 +192,16 @@ 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.02d0 !0.01d0 ! NEW 3Zoo [1/day] Respiration by heterotrophs and mortality (loss to detritus) -pzDia3 = 0.04d0 !0.5d0 ! NEW 3Zoo Maximum diatom preference -sDiaNsq3 = 0.d0 ! NEW 3Zoo -pzPhy3 = 0.07 !1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference -sPhyNsq3 = 0.d0 ! NEW 3Zoo -pzCocco3 = 0.7d0 !0.d0 ! NEW 3Zoo Maximum coccolithophore preference ! ATTENTION: This value needs to be tuned; I start with zero preference! -sCoccoNsq3 = 0.d0 ! NEW 3Zoo +graz_max3 = 0.46d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilon3 = 0.64d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss +loss_miczoo = 0.01d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) +res_miczoo = 0.02d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +pzDia3 = 0.04d0 ! Maximum diatom preference +sDiaNsq3 = 0.d0 +pzPhy3 = 0.07d0 ! Maximum small phytoplankton preference +sPhyNsq3 = 0.d0 +pzCocco3 = 0.7d0 ! Maximum coccolithophore preference ! will not be used in the 2p3z3d version +sCoccoNsq3 = 0.d0 / &pagrazingdetritus @@ -204,10 +209,10 @@ pzDet = 0.5d0 ! Maximum small detritus prefence by first zoopl 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 +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 @@ -226,25 +231,25 @@ rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradatio &paphytoplankton_N lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds lossN_d = 0.05d0 -lossN_c = 0.05d0 ! NEW +lossN_c = 0.05d0 / &paphytoplankton_C lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon lossC_d = 0.10d0 -lossC_c = 0.10d0 ! NEW +lossC_c = 0.10d0 / &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) +deg_Chl = 0.25d0 !0.075 !0.2d0 !0.25d0 ! [1/day] +deg_Chl_d = 0.15d0 !0.075 !0.2d0 !0.15d0 +deg_Chl_c = 0.2d0 !0.075 !0.2d0 / &padetritus_N -gfin = 0.3d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into zooplankton pool) +gfin = 0.3d0 ! [] 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) +grazEff3 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) reminN = 0.165d0 ! [1/day] Temperature dependent remineralisation rate of detritus / @@ -264,11 +269,11 @@ lossC_z2 = 0.02d0 / &pathirdzooloss -lossN_z3 = 0.05d0 ! NEW 3Zoo -lossC_z3 = 0.05d0 ! NEW 3Zoo +lossN_z3 = 0.05d0 +lossC_z3 = 0.05d0 / -&paco2lim ! NEW +&paco2lim 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] @@ -298,11 +303,11 @@ RiverFeConc = 100 &pacalc calc_prod_ratio = 0.02 -calc_diss_guts = 0.5d0 !0.0d0 -calc_diss_rate = 0.005714d0 ! 20.d0/3500.d0 +calc_diss_guts = 0.0d0 ! set to zero if OmegaC_diss is set to false +calc_diss_rate = 0.005714d0 ! 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 +calc_diss_omegac = 0.197d0 ! Value from Aumont et al. 2015, is used with OmegaC_diss flag +calc_diss_exp = 1.d0 ! Exponent in the dissolution rate of calcite, is used with OmegaC_diss flag / &pabenthos_decay_rate @@ -333,9 +338,9 @@ rho_opal = 2090.d0 ! kg m-3; density of Opal (see Table 1 in Cram 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_ref1 = 5.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.01d0 !5d0 ! s-1; factor to increase sinking speed of det1 with depth, set to 0 if not wanted +depth_scaling1 = 0.01d0 ! 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) / diff --git a/setups/test_pi_recom/namelist.tra b/setups/test_pi_recom/namelist.tra new file mode 100644 index 000000000..c6f24dca8 --- /dev/null +++ b/setups/test_pi_recom/namelist.tra @@ -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 = 'fe5deg.nc', 'oxy5deg.nc', 'si5deg.nc', 'talk5deg.nc', 'tco2_5deg.nc', 'din5deg.nc', 'woa18_netcdf_5deg.nc', 'woa18_netcdf_5deg.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/setups/test_pi_recom/setup.yml b/setups/test_pi_recom/setup.yml new file mode 100644 index 000000000..54c95dcd1 --- /dev/null +++ b/setups/test_pi_recom/setup.yml @@ -0,0 +1,151 @@ +mesh: test_global +forcing: test_recom +clim: + type: test_recom + filelist: + - 'fe5deg.nc' + - 'oxy5deg.nc' + - 'si5deg.nc' + - 'talk5deg.nc' + - 'tco2_5deg.nc' + - 'din5deg.nc' + - 'woa18_netcdf_5deg.nc' + - 'woa18_netcdf_5deg.nc' + varlist: ['Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp'] +ntasks: 2 +time: "00:15:00" + +namelist.config: + run_config: + use_cavity: False + use_cavity_partial_cell: False + timestep: + step_per_day: 32 + run_length: 1 + run_length_unit: "d" + geometry: + force_rotation: True + restart_log: + restart_length: 1 + restart_length_unit: "d" + logfile_outfreq: 10 + +namelist.dyn: + dynamics_general: + use_wsplit: True + +namelist.ice: + ice_dyn: + whichEVP: 1 + evp_rheol_steps: 120 + +namelist.tra: + tracer_listsize: + num_tracers: 100 + tracer_init3d: + n_ic3d: 8 + idlist: [1019, 1022, 1018, 1003, 1002, 1001, 2, 1] + filelist: ['fe5deg.nc', 'oxy5deg.nc', 'si5deg.nc', 'talk5deg.nc', 'tco2_5deg.nc', 'din5deg.nc', 'woa18_netcdf_5deg.nc', 'woa18_netcdf_5deg.nc'] + varlist: ['Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp'] + t_insitu: True + +namelist.recom: + nam_rsbc: + fe_data_source: 'Albani' + nm_fe_data_file: 'DustClimMonthlyAlbani_pimesh.nc' + nm_co2_data_file: 'MonthlyAtmCO2_gcb2024.nc' + parecomsetup: + enable_3zoo2det: True + enable_coccos: False + pavariables: + use_REcoM: True + REcoM_restart: False + bgc_num: 30 + diags3d_num: 28 + bgc_base_num: 22 + biostep: 1 + REcoM_Geider_limiter: False + REcoM_Grazing_Variable_Preference: True + Grazing_detritus: True + het_resp_noredfield: True + diatom_mucus: True + O2dep_remin: True + use_ballasting: True + use_density_scaling: True + use_viscosity_scaling: True + OmegaC_diss: False + CO2lim: True + Diags: True + constant_CO2: True + UseFeDust: True + UseDustClim: True + UseDustClimAlbani: True + use_photodamage: True + HetRespFlux_plus: True + restore_alkalinity: True + useRivers: False + useRivFe: False + useErosion: False + NitrogenSS: False + useAeolianN: False + firstyearoffesomcycle: 1958 + lastyearoffesomcycle: 2024 + numofCO2cycles: 1 + currentCO2cycle: 1 + DIC_PI: True + Nmocsy: 1 + recom_debug: False + ciso: False + benthos_num: 4 + use_MEDUSA: False + sedflx_num: 0 + bottflx_num: 4 + use_atbox: False + add_loopback: False + lb_tscale: 1.0 + +namelist.io: + nml_list: + io_list: + "sst ": + freq: 1 + unit: d + prec: 8 + "a_ice ": + freq: 1 + unit: d + prec: 8 + "temp ": + freq: 1 + unit: d + prec: 8 + "salt ": + freq: 1 + unit: d + prec: 8 + "u ": + freq: 1 + unit: d + prec: 8 + "v ": + freq: 1 + unit: d + prec: 8 + "DIN ": + freq: 1 + unit: d + prec: 8 + "DIC ": + freq: 1 + unit: d + prec: 8 + +fcheck: + a_ice: 0.8751385167232245 + salt: 34.730446281564674 + sst: 8.553913157676204 + temp: 2.4698052420959806 + u: -0.0021267214031837154 + v: 0.0002005313874256175 + DIN: 15.0 + DIC: 2100.0 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 65817d890..3b3c3bb5f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -310,7 +310,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) # __usetp) endif() if(${CISO_COUPLED}) diff --git a/src/MOD_TRACER.F90 b/src/MOD_TRACER.F90 index efeeed623..0d0d6a913 100644 --- a/src/MOD_TRACER.F90 +++ b/src/MOD_TRACER.F90 @@ -20,6 +20,9 @@ MODULE MOD_TRACER real(kind=WP) :: tra_adv_pv = 1. ! a parameter to be used in horizontal advection (for QR4C it is the fraction of fourth-order contribution in the solution) integer :: AB_order=2 integer :: ID +!___________________________________________________________________________ +! TODO: Make it as a part of namelist.tra +logical :: ltra_diag = .true. ! OG - tra_diag contains procedure WRITE_T_TRACER_DATA @@ -41,7 +44,15 @@ MODULE MOD_TRACER ! compute Tstar = 0.5*( T^(n+1) + T^n) real(kind=WP), allocatable, dimension(:,:,:) :: dvd_trflx_hor, dvd_trflx_ver -!_______________________________________________________________________________ +! in case ltra_diag=.true. --> calculate tracer diags ! OG - tra_diag +real(kind=WP), allocatable :: tra_advhoriz(:,:,:), tra_advvert(:,:,:) +real(kind=WP), allocatable :: tra_diff_part_hor_redi(:,:,:) +real(kind=WP), allocatable :: tra_diff_part_ver_expl(:,:,:) +real(kind=WP), allocatable :: tra_diff_part_ver_redi_expl(:,:,:) +real(kind=WP), allocatable :: tra_diff_part_ver_impl(:,:,:) +real(kind=WP), allocatable :: tra_recom_sms(:,:,:) +real(kind=WP), allocatable :: tra_advvert_LO(:,:,:), tra_advhoriz_LO(:,:,:) + ! The fct part real(kind=WP),allocatable,dimension(:,:) :: fct_LO ! Low-order solution real(kind=WP),allocatable,dimension(:,:) :: adv_flux_hor ! Antidif. horiz. contrib. from edges / backup for iterafive fct scheme diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 50e379133..686882e71 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -183,7 +183,7 @@ subroutine fesom_init(fesom_total_nsteps) f%npes =>f%partit%npes - + if(f%mype==0) then call plot_fesomlogo() write(*,*) @@ -206,10 +206,10 @@ subroutine fesom_init(fesom_total_nsteps) #if defined (FESOM_PROFILING) call fesom_profiler_end("setup_model") #endif - + if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call clock_init'//achar(27)//'[0m' call clock_init(f%partit) ! read the clock file - + if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call get_run_steps'//achar(27)//'[0m' call get_run_steps(fesom_total_nsteps, f%partit) f%total_nsteps=fesom_total_nsteps diff --git a/src/gen_forcing_init.F90 b/src/gen_forcing_init.F90 index aa7afca18..2106db03f 100644 --- a/src/gen_forcing_init.F90 +++ b/src/gen_forcing_init.F90 @@ -142,7 +142,6 @@ subroutine forcing_array_setup(partit, mesh) evaporation = 0.0_WP ice_sublimation = 0.0_WP - #if defined (__oasis) || defined (__ifsinterface) allocate(sublimation(n2), evap_no_ifrac(n2)) sublimation=0.0_WP diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index 869b00a52..11d861893 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -175,6 +175,10 @@ subroutine setup_model(partit) endif call par_ex(partit%MPI_COMM_FESOM, partit%mype, 1) endif + + read (fileunit, NML=parecomsetup, iostat=istat) + if (istat /= 0) call check_namelist_read(fileunit, 'parecomsetup', nmlfile, partit) + read (fileunit, NML=pavariables, iostat=istat) if (istat /= 0) call check_namelist_read(fileunit, 'pavariables', nmlfile, partit) diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index b95a99af7..1240b5ac2 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -1457,6 +1457,7 @@ SUBROUTINE sbc_do(partit, mesh) #if defined (__recom) use recom_config use recom_glovar + use REcoM_ciso #endif IMPLICIT NONE @@ -1473,8 +1474,9 @@ SUBROUTINE sbc_do(partit, mesh) integer :: firstyearofcurrentCO2cycle, totnumyear, currentCO2year character(4) :: currentCO2year_char real(kind=8), allocatable :: ncdata(:) - integer :: CO2start, CO2count - integer :: status, ncid, varid + integer :: CO2start, CO2count, RIstart, RIcount + real(kind=8) :: locmax, locmin, glo + integer :: status, ncid, varid, ierror, n #endif type(t_partit), intent(inout), target :: partit type(t_mesh), intent(in), target :: mesh @@ -1659,10 +1661,40 @@ SUBROUTINE sbc_do(partit, mesh) ! ******** Atmospheric CO2 ********* if (mstep == 1) then ! The year has changed + if (use_atbox) then +! Atmospheric box model CO2 values + AtmCO2(:) = x_co2atm(1) + if (ciso) then + AtmCO2_13(:) = x_co2atm_13(1) + if (ciso_14) AtmCO2_14(:,1) = x_co2atm_14(1) + end if + else +! Prescribed atmospheric CO2 values + if (constant_CO2) then AtmCO2(:) = CO2_for_spinup if (mype==0) write(*,*) 'Constant_CO2 = ', CO2_for_spinup - if (mype==0) write(*,*),'Atm CO2=', AtmCO2 + if (mype==0) write(*,*),'Atm CO2=', AtmCO2 + if (ciso) then + AtmCO2_13 = CO2_for_spinup * (1. + 0.001 * delta_co2_13) + if (ciso_14) then +! Atmospheric 14C varies with latitude + do i=1, myDim_nod2D +! Latitude of atmospheric input data + lat_val = geo_coord_nod2D(2,i) / rad +! Binning to latitude zones + if (ciso_organic_14) then +! Convert Delta_14C to delta_14C + delta_co2_14 = (big_delta_co2_14(lat_zone(lat_val)) + 2. * delta_co2_13 + 50.) / & + (0.95 - 0.002 * delta_co2_13) + else +! "Inorganic" 14C approximation: delta_14C := Delta_14C + delta_co2_14 = big_delta_co2_14(lat_zone(lat_val)) + end if + AtmCO2_14(lat_zone(lat_val),:) = CO2_for_spinup * (1. + 0.001 * delta_co2_14) + end do + end if + end if else filename=trim(make_full_path(nm_co2_data_file)) if (mype==0) write(*,*) 'Updating CO2 climatology for month ', i,' from ', trim(filename) @@ -1696,8 +1728,18 @@ SUBROUTINE sbc_do(partit, mesh) if (mype==0) write(*,*),'Atm CO2=', AtmCO2 status=nf90_close(ncid) end if + end if ! atmospheric box model or prescribed CO2 values + +! Control output of atmospheric CO2 values + if (mype==0) then !OG + print *, "In atm_input: AtmCO2 = ", AtmCO2(1) + if (ciso) then + print *, " AtmCO2_13 = ", AtmCO2_13(1) + if (ciso_14) print *, " AtmCO2_14 = ", AtmCO2_14(:,1) + end if + if (use_atbox) print *, " use_atbox = .true." + end if end if - ! ******** Fe deposition ********* if (fe_data_source=='Albani') then if (update_monthly_flag) then @@ -1737,44 +1779,228 @@ SUBROUTINE sbc_do(partit, mesh) if (mstep==1 .and. mype==0) write(*,*) 'useAeolianN is switched off' end if -! ******** Riverine input (Nutrients) ********* + !----------------------------------------------------------------------------- + ! Configure river nutrient inputs + !----------------------------------------------------------------------------- + if (useRivers) then -!< read riverine input + ! *** River inputs are in mmol/m2/s *** - ! add river nutrients as surface boundary condition (surface_bc function in oce_ale_tracers) + if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> River_input'//achar(27)//'[0m' + ! add river nutrients as surface boundary condition (surface_bc function in oce_ale_tracers) + ! Enable river input flag is_riverinput = 1.0d0 - if (update_monthly_flag) then - i=month - if (mstep > 1) i=i+1 - if (i > 12) i=1 - filename=trim(nm_river_data_file) - if (mype==0) write(*,*) 'Updating riverine restoring data for month', i,' from ', trim(filename) - call read_2ddata_on_grid_NetCDF(filename,'Alkalinity', i, RiverAlk2D, partit, mesh) - ! write(*,*) mype, 'RiverAlk2D', maxval(RiverAlk2D(:)), minval(RiverAlk2D(:)) - ! molar convertion of [CaCo3] * 2 -> [total Alkalinity] - RiverAlk2D = RiverAlk2D * 2 - - call read_2ddata_on_grid_NetCDF(filename, 'DIC', i, RiverDIC2D, partit, mesh) - ! write(*,*) mype, 'RiverDIC2D', maxval(RiverDIC2D(:)), minval(RiverDIC2D(:)) - - call read_2ddata_on_grid_NetCDF(filename, 'DIN', i, RiverDIN2D, partit, mesh) - ! write(*,*) mype, 'RiverDIN2D', maxval(RiverDIN2D(:)), minval(RiverDIN2D(:)) - - call read_2ddata_on_grid_NetCDF(filename, 'DOC', i, RiverDOC2D, partit, mesh) - ! write(*,*) mype, 'RiverDOC2D', maxval(RiverDOC2D(:)), minval(RiverDOC2D(:)) - - call read_2ddata_on_grid_NetCDF(filename, 'DON', i, RiverDON2D, partit, mesh) - ! write(*,*) mype, 'RiverDON2D', maxval(RiverDON2D(:)), minval(RiverDON2D(:)) - - RiverDSi2D = RiverDIN2D * (16/15) - end if - else - is_riverinput = 0.0d0 - if (mype==0 .and. mstep==1) write(*,*) 'No riverine input' - end if + if (mstep == 1) then + + ! Determine input type: constant pre-industrial or transient + if (mype==0) then + ! Use constant pre-industrial river inputs + if (constant_PI_Rivers) then + write(*,'(A)') 'INFO: Using constant pre-industrial riverine inputs' + filename = trim(REcoMDataPath) // 'Rivers_R2OMIP_PI.nc' + else + ! Use transient (year-specific) river inputs + write(*,'(A,A,A,A)') 'INFO: Using transient riverine inputs - model year = ', & + trim(cyearnew), ' from ', trim(filename) + ! Construct filename for current year + filename = trim(REcoMDataPath) // 'Rivers_R2OMIP_' // trim(cyearnew) // '.nc' + endif + ! open file + write(*,*), trim(filename) + status=nf90_open(filename, nf90_nowrite, ncid) + endif + + call MPI_BCast(status, 1, MPI_INTEGER, 0, MPI_COMM_FESOM, ierror) + + if (status.ne.nf90_noerr)then + print*,'ERROR: CANNOT READ runoff FILE CORRECTLY !!!!!' + print*,'Error in opening netcdf file '//filename + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + endif + + call load_river_variable(ncid, 'DIC', RiverDIC2D, partit, mesh) + locmax = -66666 + locmin = 66666 + locmax = max(locmax,maxval(RiverDIC2D)) + locmin = min(locmin,minval(RiverDIC2D)) + + if (mype==0) write(*,*) "Sanity check for Riverine input after reading Rivers_R2OMIP file" + call MPI_AllREDUCE(locmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global max init. riverine DIC. =', glo + call MPI_AllREDUCE(locmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global min init. riverine DIC. =', glo + + call load_river_variable(ncid, 'DIN', RiverDIN2D, partit, mesh) + locmax = -66666 + locmin = 66666 + locmax = max(locmax,maxval(RiverDIN2D)) + locmin = min(locmin,minval(RiverDIN2D)) + + if (mype==0) write(*,*) "Sanity check for Riverine input after reading Rivers_R2OMIP file" + call MPI_AllREDUCE(locmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global max init. riverine DIN. =', glo + call MPI_AllREDUCE(locmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global min init. riverine DIN. =', glo + + call load_river_variable(ncid, 'DOC_l', RiverDOCl2D, partit, mesh) + locmax = -66666 + locmin = 66666 + locmax = max(locmax,maxval(RiverDOCl2D)) + locmin = min(locmin,minval(RiverDOCl2D)) + + call MPI_AllREDUCE(locmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global max riverine DOCl. =', glo + call MPI_AllREDUCE(locmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global min riverine DOCl. =', glo + + call load_river_variable(ncid, 'DOC_sl', RiverDOCsl2D, partit, mesh) + locmax = -66666 + locmin = 66666 + locmax = max(locmax,maxval(RiverDOCsl2D)) + locmin = min(locmin,minval(RiverDOCsl2D)) + + call MPI_AllREDUCE(locmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global max riverine DOCsl. =', glo + call MPI_AllREDUCE(locmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global min riverine DOCsl. =', glo + + call load_river_variable(ncid, 'POC', RiverPOC2D, partit, mesh) + locmax = -66666 + locmin = 66666 + locmax = max(locmax,maxval(RiverPOC2D)) + locmin = min(locmin,minval(RiverPOC2D)) + + call MPI_AllREDUCE(locmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global max riverine POC. =', glo + call MPI_AllREDUCE(locmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> global min riverine POC. =', glo + + if (mype == 0) then + status = nf90_close(ncid) ! Close file once + endif + + !allocate(ncdata(mesh%nod2D)) + !if (mype==0) then + ! status=nf90_inq_varid(ncid, 'DIC', varid) + ! RIstart = 1 + ! RIcount = mesh%nod2D + ! status=nf90_get_var(ncid, varid, ncdata, start=(/RIstart/), count=(/RIcount/)) + ! status=nf90_close(ncid) + !endif + !call MPI_BCast(ncdata, nod2D, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM, ierror) + !RiverDIC2D=ncdata(myList_nod2D) + !deallocate(ncdata) + !write(*,*), 'here' + + ! Read all nutrient fields from PI file + !i=1 + !call read_2ddata_on_grid_NetCDF(filename, 'DIC', i, RiverDIC2D, partit, mesh) + !call read_2ddata_on_grid_NetCDF(filename, 'DIN', i, RiverDIN2D, partit, mesh) + !call read_2ddata_on_grid_NetCDF(filename, 'DOC_l', i, RiverDOCl2D, partit, mesh) + !call read_2ddata_on_grid_NetCDF(filename, 'DOC_sl', i, RiverDOCsl2D, partit, mesh) + !call read_2ddata_on_grid_NetCDF(filename, 'POC', i, RiverPOC2D, partit, mesh) + + + + !if (mype==0) write(*,'(A)') 'INFO: Using constant pre-industrial riverine inputs' + ! Check for read errors + !if (i /= 0) then + ! if (mype==0) write(*,'(A,A)') 'ERROR: Failed to read PI river inputs from ', trim(filename) + ! stop + !endif + !endif + + else + + ! Use transient (year-specific) river inputs + !if (mstep == 1) then + !if (mype==0) write(*,'(A,A,A,A)') 'INFO: Using transient riverine inputs - model year = ', & + ! trim(cyearnew), ' from ', trim(filename) + + ! Construct filename for current year + !filename = trim(REcoMDataPath) // 'Rivers_R2OMIP_' // trim(cyearnew) // '.nc' + + ! Read all nutrient fields for current year + !call read_2ddata_on_grid_NetCDF(filename, 'DIC', i, RiverDIC2D, partit, mesh) + !if (i /= 0) then + !if (mype==0) write(*,'(A,A,A)') 'ERROR: Failed to read DIC from ', trim(filename) + !stop + ! endif + + !call read_2ddata_on_grid_NetCDF(filename, 'DIN', i, RiverDIN2D, partit, mesh) + !if (i /= 0) then + !if (mype==0) write(*,'(A,A,A)') 'ERROR: Failed to read DIN from ', trim(filename) + !stop + !endif + + !call read_2ddata_on_grid_NetCDF(filename, 'DOC_l', i, RiverDOCl2D, partit, mesh) + !if (i /= 0) then + !if (mype==0) write(*,'(A,A,A)') 'ERROR: Failed to read DOC_l from ', trim(filename) + !stop + !endif + + !call read_2ddata_on_grid_NetCDF(filename, 'DOC_sl', i, RiverDOCsl2D, partit, mesh) + !if (i /= 0) then + !if (mype==0) write(*,'(A,A,A)') 'ERROR: Failed to read DOC_sl from ', trim(filename) + !stop + !endif + + !call read_2ddata_on_grid_NetCDF(filename, 'POC', i, RiverPOC2D, partit, mesh) + !if (i /= 0) then + !if (mype==0) write(*,'(A,A,A)') 'ERROR: Failed to read POC from ', trim(filename) + !stop + !endif + !endif + + endif + + else + + ! Rivers disabled: set all inputs to zero + is_riverinput = 0.0d0 + RiverDIC2D = 0.0d0 + RiverDIN2D = 0.0d0 + RiverDOCl2D = 0.0d0 + RiverDOCsl2D = 0.0d0 + RiverPOC2D = 0.0d0 + + endif + +!IF (.FALSE.) THEN ! CHECK OG +! if (update_monthly_flag) then +! i=month +! if (mstep > 1) i=i+1 +! if (i > 12) i=1 +! filename=trim(nm_river_data_file) +! if (mype==0) write(*,*) 'Updating riverine restoring data for month', i,' from ', trim(filename) +! call read_2ddata_on_grid_NetCDF(filename,'Alkalinity', i, RiverAlk2D, partit, mesh) +! ! write(*,*) mype, 'RiverAlk2D', maxval(RiverAlk2D(:)), minval(RiverAlk2D(:)) +! ! molar convertion of [CaCo3] * 2 -> [total Alkalinity] +! RiverAlk2D = RiverAlk2D * 2 +! +! call read_2ddata_on_grid_NetCDF(filename, 'DIC', i, RiverDIC2D, partit, mesh) +! ! write(*,*) mype, 'RiverDIC2D', maxval(RiverDIC2D(:)), minval(RiverDIC2D(:)) +! +! call read_2ddata_on_grid_NetCDF(filename, 'DIN', i, RiverDIN2D, partit, mesh) +! ! write(*,*) mype, 'RiverDIN2D', maxval(RiverDIN2D(:)), minval(RiverDIN2D(:)) +! +! call read_2ddata_on_grid_NetCDF(filename, 'DOC', i, RiverDOC2D, partit, mesh) +! ! write(*,*) mype, 'RiverDOC2D', maxval(RiverDOC2D(:)), minval(RiverDOC2D(:)) +! +! call read_2ddata_on_grid_NetCDF(filename, 'DON', i, RiverDON2D, partit, mesh) +! ! write(*,*) mype, 'RiverDON2D', maxval(RiverDON2D(:)), minval(RiverDON2D(:)) +! +! RiverDSi2D = RiverDIN2D * (16/15) +! end if +! else +! is_riverinput = 0.0d0 +! if (mype==0 .and. mstep==1) write(*,*) 'No riverine input' +! end if +!ENDIF ! ******** Riverine input of iron ********* if (useRivFe) then diff --git a/src/int_recom/recom/gasx.F90 b/src/int_recom/recom/gasx.F90 index bd5473527..c4d2d8b01 100755 --- a/src/int_recom/recom/gasx.F90 +++ b/src/int_recom/recom/gasx.F90 @@ -6,7 +6,7 @@ MODULE gasx !> Computes air-sea CO2 flux & surface-ocean carbonate system vars (pH, CO2*, HCO3- and CO32-, OmegaA, OmegaC, R) !! from T, S, P, ALK, DIC, total inorganic silicon, total inorganic phosphorus, all as 1-D arrays SUBROUTINE flxco2(co2flux, co2ex, dpco2, & - ph, pco2, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, & + ph, pco2, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, K0, & temp, sal, alk, dic, sil, phos, kw660, xco2, Patm, dz1, N, lon, lat, & optCON, optT, optP, optB, optK1K2, optKf, optGAS, optS ) ! Purpose: @@ -127,6 +127,8 @@ SUBROUTINE flxco2(co2flux, co2ex, dpco2, ! rhoSW = in-situ density of seawater; rhoSW = f(s, t, p) ! p = pressure [decibars]; p = f(depth, latitude) if computed from depth [m] OR p = depth if [db] ! tempis = in-situ temperature [degrees C] + ! K0 = CO2 solubility [(mol/kg) / atm] + #if USE_PRECISION == 2 # define SGLE(x) (x) @@ -237,10 +239,12 @@ SUBROUTINE flxco2(co2flux, co2ex, dpco2, REAL(kind=rx), INTENT(out), DIMENSION(N) :: p !> in-situ temperature \b [degrees C] REAL(kind=rx), INTENT(out), DIMENSION(N) :: tempis + !> K0, solubility of CO2 \b [(mol/kg) / atm] + REAL(kind=rx), INTENT(out), DIMENSION(N) :: K0 ! Local variables REAL(kind=r8) :: tk, invtk, dtemp - REAL(kind=r8) :: tmp, K0, co2star, co2starair, kwco2 + REAL(kind=r8) :: tmp, co2star, co2starair, kwco2 ! K0 REAL(kind=rx), DIMENSION(N) :: pCO2atm, fCO2atm REAL(kind=rx), DIMENSION(N) :: depth0, lat0 @@ -361,7 +365,7 @@ SUBROUTINE flxco2(co2flux, co2ex, dpco2, K0 = EXP( tmp + DBLE(salprac(i))*(0.023517d0 - 0.00023656d0*tk + 0.0047036e-4_r8*tk*tk) ) ! "Atmospheric" [CO2*], air-sea CO2 flux, sfc DIC rate of change, & Delta pCO2 - co2starair = K0 * DBLE(fco2atm(i)) * 1.0e-6_r8 * DBLE(rhoSW(i)) !Equil. [CO2*] for atm CO2 at Patm & sfc-water T,S [mol/m3] + co2starair = K0(i) * DBLE(fco2atm(i)) * 1.0e-6_r8 * DBLE(rhoSW(i)) !Equil. [CO2*] for atm CO2 at Patm & sfc-water T,S [mol/m3] co2star = DBLE(co2(i)) !Oceanic [CO2*] in [mol/m3] from vars.f90 co2flux(i) = SGLE(kwco2 * (co2starair - co2star)) !Air-sea CO2 flux [mol/(m2 * s)] ! the conversion from co2flux to impact on dic is done in recom_forcing/recom_sms diff --git a/src/int_recom/recom/vars.F90 b/src/int_recom/recom/vars.F90 index 2ef70defa..d20069a10 100755 --- a/src/int_recom/recom/vars.F90 +++ b/src/int_recom/recom/vars.F90 @@ -570,7 +570,7 @@ SUBROUTINE vars_sprac (ph, pco2, fco2, co2, hco3, co3, OmegaA, OmegaC, kspc_out, ! If Absolute salinity is given IF (trim(opS) == 'Sabs') THEN ! If in-situ or potential temperature is given - IF (trim(optT) /= 'Scsv') THEN + IF (trim(optT) /= 'Scsv') THEN !!!!!!!!! Is it a bug? OG 20.03.2025 Scsv -> Tcsv .OR. tcsv ! First compute conservative temperature tempcsv = gsw_ct_from_t (DBLE(ssal), tempis90, DBLE(p(i))) ELSE diff --git a/src/int_recom/recom_atbox.F90 b/src/int_recom/recom_atbox.F90 new file mode 100644 index 000000000..4474d44ee --- /dev/null +++ b/src/int_recom/recom_atbox.F90 @@ -0,0 +1,91 @@ + subroutine recom_atbox(partit, mesh) +! Simple 0-d box model to calculate the temporal evolution of atmospheric CO2. +! Initially the box model was part of module recom_ciso. Now it can be run also +! without carbon isotopes (ciso==.false.) +! mbutzin, 2021-07-08 + +! Settings are copied from subroutine bio_fluxes, +! some of the following modules may be unnecessary here +! use REcoM_declarations +! use REcoM_LocVar + use REcoM_GloVar + use recom_config + use recom_ciso + + use mod_mesh + USE MOD_PARTIT + USE MOD_PARSUP + + use g_config + use o_arrays + use g_comm_auto + use g_forcing_arrays + use g_support + + + implicit none + integer :: n, elem, elnodes(3),n1 + real(kind=WP) :: total_co2flux, & ! (mol / s) + total_co2flux_13, & ! (mol / s) carbon-13 + total_co2flux_14 ! (mol / s) radiocarbon + real(kind=WP), parameter :: mol_allatm = 1.7726e20 ! atmospheric inventory of all compounds (mol) + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + +#include "../associate_part_def.h" +#include "../associate_mesh_def.h" +#include "../associate_part_ass.h" +#include "../associate_mesh_ass.h" + +! Globally integrated air-sea CO2 flux (mol / s) + total_co2flux = 0. + call integrate_nod(0.001 * GloCO2flux_seaicemask , total_CO2flux, partit, mesh) + +! Atmospheric carbon budget (mol) +! mass of the dry atmosphere = 5.1352e18 kg (Trenberth & Smith 2005, doi:10.1175/JCLI-3299.1) +! mean density of air = 0.02897 kg / mol (https://nssdc.gsfc.nasa.gov/planetary/factsheet/earthfact.html) +! => total molecular inventory of the dry atmosphere: moles_atm = 1.7726e20 mol == constant. +! mol_co2atm = mol_co2atm - total_co2flux * dt +! Atmospheric mixing ratios in ppm +! x_co2atm(1) = mol_co2atm / mol_allatm * 1.e6 ! ppm + x_co2atm(1) = x_co2atm(1) - total_co2flux / mol_allatm * dt * 1.e6 + x_co2atm = x_co2atm(1) + + if (ciso) then +! Consider 13CO2 (and maybe also 14CO2) + +! Globally integrated air-sea 13CO2 flux (mol / s) + total_co2flux_13 = 0. + call integrate_nod(0.001 * GloCO2flux_seaicemask_13, total_co2flux_13, partit, mesh) + +! Atmospheric carbon-13 budget (mol) +! mol_co2atm_13 = mol_co2atm_13 - total_co2flux_13 * dt +! Budget in terms of the 13C / 12C volume mixing ratio +! x_co2atm_13(1) = mol_co2atm_13 / mol_allatm * 1.e6 + x_co2atm_13(1) = x_co2atm_13(1) - total_co2flux_13 / mol_allatm * dt * 1.e6 + x_co2atm_13 = x_co2atm_13(1) + + if (ciso_14) then + total_co2flux_14 = 0. ! globally integrated air-sea 14CO2 flux (mol / s) + call integrate_nod(0.001 * GloCO2flux_seaicemask_14, total_co2flux_14, partit, mesh) +! Atmospheric radiocarbon budget in mol: +! mol_co2atm_14 = mol_co2atm_14 + dt * (cosmic_14(1) - mol_co2atm_14 * lambda_14 - total_co2flux_14) +! = (mol_co2atm_14 + dt * (cosmic_14(1) - total_co2flux_14)) / (1 + lambda_14 * dt) +! Budget in terms of the 14C / 12C volume mixing ratio + x_co2atm_14(1) = (x_co2atm_14(1) + dt * (cosmic_14(1) - total_co2flux_14) / mol_allatm * 1.e6) / & + (1 + lambda_14 * dt) + x_co2atm_14 = x_co2atm_14(1) + +! Adjust cosmogenic 14C production (mol / s) in spinup runs, + r_atm_14 = x_co2atm_14(1) / x_co2atm(1) +! r_atm_spinup_14 is calculated once-only in subroutine recom_init + if (atbox_spinup .and. abs(r_atm_14 - r_atm_spinup_14) > 0.001) then + cosmic_14(1) = cosmic_14(1) * (r_atm_spinup_14 / r_atm_14) +! cosmic_14(1) = cosmic_14(1) * (1 + 0.01 * (r_atm_14_spinup / r_atm_14)) + end if + cosmic_14 = cosmic_14(1) + endif + end if + + return + end subroutine recom_atbox diff --git a/src/int_recom/recom_extra.F90 b/src/int_recom/recom_extra.F90 index 5495e0c8f..bdc752315 100644 --- a/src/int_recom/recom_extra.F90 +++ b/src/int_recom/recom_extra.F90 @@ -1,34 +1,35 @@ !=============================================================================== ! Subroutine for calculating flux-depth and thickness of control volumes !=============================================================================== -subroutine Depth_calculations(n,Nn,wF,zF,thick,recipthick, partit, mesh) - use recom_config +subroutine Depth_calculations(n, nn, wf, zf, thick, recipthick, partit, mesh) + use recom_config use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP - USE o_PARAM - USE o_ARRAYS - USE g_CONFIG - use g_forcing_arrays - use g_comm_auto - - use g_clock - use g_rotate_grid + use MOD_PARTIT + use MOD_PARSUP + use o_PARAM + use o_ARRAYS + use g_CONFIG + use g_forcing_arrays + use g_comm_auto + use g_clock + use g_rotate_grid - implicit none -! Input - type(t_partit), intent(inout), target :: partit - type(t_mesh) , intent(inout), target :: mesh - - Integer, intent(in) :: Nn ! Total number of nodes -! Output - real(kind=8),dimension(mesh%nl), intent(out) :: zF ! [m] Depth of vertical fluxes + implicit none - real(kind=8),dimension(mesh%nl-1), intent(out) :: thick ! [m] Distance between two nodes = thickness - real(kind=8),dimension(mesh%nl-1), intent(out) :: recipthick ! [1/m] reciprocal of thickness + ! Input parameters + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + integer , intent(in) :: n ! Current node + integer , intent(in) :: nn ! Total number of vertical nodes - real(kind=8),dimension(mesh%nl,5), intent(out) :: wF ! [m/day] Velocities of fluxes at the border of the control volumes - Integer :: k, n ! Index for depth + ! Output arrays + 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 + + ! Local variables + integer :: k ! Layer index #include "../associate_part_def.h" #include "../associate_mesh_def.h" @@ -48,16 +49,17 @@ subroutine Depth_calculations(n,Nn,wF,zF,thick,recipthick, partit, mesh) ! allocate(Z_3d_n(nl-1,myDim_nod2D+eDim_nod2D)) ! ============================================================================== modular -!! Background sinking speed - - wF(2:Nn,ivphy) = VPhy - wF(2:Nn,ivdia) = VDia - wF(2:Nn,ivdet) = VDet - wF(2:Nn,ivdetsc) = VDet_zoo2 - wF(2:Nn,ivcoc) = VCocco + !! Background sinking speed + wF(2:Nn, ivphy) = VPhy ! Phytoplankton sinking velocity + wF(2:Nn, ivdia) = VDia ! Diatoms sinking velocity + wF(2:Nn, ivdet) = VDet ! Detritus sinking velocity + wF(2:Nn, ivdetsc) = VDet_zoo2 ! Second detritus sinking velocity + wF(2:Nn, ivcoc) = VCocco ! Coccolithophores sinking velocity + wF(2:Nn, ivpha) = VPhaeo ! Phaeocystis sinking velocity - wF(1,:) = 0.d0 - wF(Nn+1,:) = 0.d0 + !! Boundary conditions (surface and bottom) + wF(1,:) = 0.d0 + wF(Nn+1,:) = 0.d0 !if (allow_var_sinking) then !! wF(2:Nn+1,ivdet) = Vdet_a * abs(zbar_n(2:Nn+1)) + VDet @@ -65,31 +67,25 @@ subroutine Depth_calculations(n,Nn,wF,zF,thick,recipthick, partit, mesh) ! wF(2:Nn+1,ivdet) = Vcalc * abs(zbar_3d_n(2:Nn+1, n)) + VDet !end if -!---------------------------------------------------- -! Vertical layers thickness - - thick =0.0_WP - recipthick=0.0_WP - zF=0.0_WP + !! Calculate layer thickness and reciprocal of it + thick = 0.0_WP + recipthick = 0.0_WP + zf = 0.0_WP -!do n=1,myDim_nod2D+eDim_nod2D - do k=1, Nn !nlevels_nod2D(n)-1 - thick(k)=hnode(k,n) - if (hnode(k,n) > 0._WP) then - recipthick(k)=1./hnode(k,n) - else - recipthick(k)=0._WP - end if - end do -!end do - -! layer depth (negative) + do k=1, nn + thick(k) = hnode(k,n) + if (hnode(k,n) > 0.0_WP) then +! if thick(k) > 0.0_WP) then ! alternative + recipthick(k) = 1.0/hnode(k,n) + else + recipthick(k) = 0.0_WP + end if + end do -!do n=1,myDim_nod2D+eDim_nod2D - do k=1, Nn+1 !nlevels_nod2D(n) - zF(k)=zbar_3d_n(k,n) - end do -!end do + !! set layer depth (negative) + do k=1, nn+1 + zf(k)=zbar_3d_n(k,n) + end do end subroutine Depth_calculations @@ -100,24 +96,26 @@ subroutine Cobeta(partit, mesh) use REcoM_GloVar use g_clock use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use o_PARAM use g_comm_auto - Implicit none + + implicit none -! Declarations - real(kind=8) :: yearfrac ! The fraction of the year that has passed [0 1] - real(kind=8) :: yDay ! yearfrac in radians [0 2*pi] - real(kind=8) :: declination = 0.d0 ! Declination of the sun at present lat and time - real(kind=8) :: CosAngleNoon = 0.d0 ! Cos(Angle of Incidence) at Noon ? - integer :: n + ! Input parameters + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh -! Constants - real(kind=8) :: nWater = 1.33 + ! Local variables + real(kind=8) :: yearfrac ! Fraction of year [0 1] + real(kind=8) :: yDay ! Year fraction in radians [0 2*pi] + real(kind=8) :: declination = 0.d0 ! Declination of the sun at present lat and time + real(kind=8) :: CosAngleNoon = 0.d0 ! Cosine of Angle of Incidence at noon + integer :: n - type(t_partit), intent(inout), target :: partit - type(t_mesh) , intent(inout), target :: mesh + ! Constants + real(kind=8), parameter :: nWater = 1.33 ! Refractive indices of water #include "../associate_part_def.h" #include "../associate_mesh_def.h" @@ -131,9 +129,11 @@ subroutine Cobeta(partit, mesh) !! Publishing Company, Amsterdam, Oxford, !! New York, 1976, ISBN 0-444-41444-4. - yearfrac = mod(real(daynew),real(ndpyr))/real(ndpyr) - yDay = 2 * pi * yearfrac - declination = 0.006918 & + !! Calculate solar declination using Paltridge & Platt (1976) formula + yearfrac = mod(real(daynew), real(ndpyr)) / real(ndpyr) + yDay = 2.0d0 * pi * yearfrac + + declination = 0.006918 & - 0.399912 * cos( yDay) & + 0.070257 * sin( yDay) & - 0.006758 * cos(2 * yDay) & @@ -141,33 +141,35 @@ subroutine Cobeta(partit, mesh) - 0.002697 * cos(3 * yDay) & + 0.001480 * sin(3 * yDay) - do n=1, myDim_nod2D!+eDim_nod2D - - cosAngleNoon = sin(geo_coord_nod2D(2,n)) * sin(declination) & - + cos(geo_coord_nod2D(2,n)) * cos(declination) - cosAI(n) = sqrt(1-(1-cosAngleNoon**2)/nWater**2) + !! Calculate cosine of angle of incidence for each node + do n = 1, myDim_nod2D + cosAngleNoon = sin(geo_coord_nod2D(2, n)) * sin(declination) & + + cos(geo_coord_nod2D(2, n)) * cos(declination) - end do + cosAI(n) = sqrt(1.0d0 - (1.0d0 - cosAngleNoon**2) / nWater**2) + end do end subroutine Cobeta !================================================================================ ! Calculating second zooplankton respiration rates !================================================================================ subroutine krill_resp(n, partit, mesh) - use REcoM_declarations - use REcoM_LocVar - use REcoM_GloVar - use g_clock - use o_PARAM -! use g_PARSUP + use REcoM_declarations + use REcoM_LocVar + use REcoM_GloVar + use g_clock + use o_PARAM use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP - use g_comm_auto - implicit none - integer :: n - - type(t_partit), intent(inout), target :: partit - type(t_mesh) , intent(inout), target :: mesh + use MOD_PARTIT + use MOD_PARSUP + use g_comm_auto + + implicit none + + ! Input parameters + integer :: n + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + #include "../associate_part_def.h" #include "../associate_mesh_def.h" #include "../associate_part_ass.h" @@ -202,3 +204,62 @@ subroutine krill_resp(n, partit, mesh) endif end subroutine krill_resp + +! Load river biogeochemical variables from NetCDF file R2OMIP +! Variables: DIN, DOCl, DOCs, POC + +! Subroutine to read and broadcast a single variable + +subroutine load_river_variable(ncid, vari, model_2Darray, partit, mesh) + + use, intrinsic :: ISO_FORTRAN_ENV, only: real64 + + use g_config + use o_param + USE MOD_MESH + USE MOD_PARTIT + USE MOD_PARSUP + use g_rotate_grid + use netcdf + implicit none + + type(t_mesh), intent(in) , target :: mesh + type(t_partit), intent(inout), target :: partit + integer :: n + integer :: status, ncid, varid + integer :: RIstart, RIcount + + real(real64), allocatable :: ncdata(:) + + real(real64), intent(out) :: model_2Darray(partit%myDim_nod2D+partit%eDim_nod2D) + + character(*), intent(in) :: vari + integer :: ierror + +#include "../associate_part_def.h" +#include "../associate_mesh_def.h" +#include "../associate_part_ass.h" +#include "../associate_mesh_ass.h" + + ! Allocate temporary array for full domain + allocate(ncdata(mesh%nod2D)) + + if (mype == 0) then + status = nf90_inq_varid(ncid, trim(vari), varid) + RIstart = 1 + RIcount = nod2D + status = nf90_get_var(ncid, varid, ncdata, start=(/RIstart/), count=(/RIcount/)) + endif + + ! Broadcast to all processes + call MPI_BCast(ncdata, nod2D, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM, ierror) + + ! Extract local partition + model_2Darray=ncdata(myList_nod2D) + + ! Clean up + deallocate(ncdata) + +end subroutine load_river_variable + + diff --git a/src/int_recom/recom_forcing.F90 b/src/int_recom/recom_forcing.F90 index 81650779d..ae314f16b 100644 --- a/src/int_recom/recom_forcing.F90 +++ b/src/int_recom/recom_forcing.F90 @@ -1,7 +1,7 @@ !=============================================================================== ! REcoM_Forcing !=============================================================================== -subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sali_depth & +subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali_depth & , CO2_watercolumn & , pH_watercolumn & , pCO2_watercolumn & @@ -66,7 +66,7 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal !!---- Subroutine Depth real(kind=8),dimension(mesh%nl) :: zF ! [m] Depth of fluxes - real(kind=8),dimension(mesh%nl,5) :: SinkVel ! [m/day] + real(kind=8),dimension(mesh%nl,6) :: SinkVel ! [m/day] real(kind=8),dimension(mesh%nl-1) :: thick ! [m] Vertical distance between two nodes = Thickness real(kind=8),dimension(mesh%nl-1) :: recipthick ! [1/m] reciprocal of thick @@ -110,10 +110,13 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal tiny_Si = tiny_C_d/SiCmax ! SiCmax = 0.8d0 -#if defined (__coccos) - tiny_N_c = tiny_chl/chl2N_max_c ! 0.00001/ 3.5d0 +if (enable_coccos) then + tiny_N_c = tiny_chl/chl2N_max_c ! 0.00001/ 3.5d0 tiny_C_c = tiny_N_c/NCmax_c ! NCmax_c = 0.15d0 -#endif + + tiny_N_p = tiny_chl/chl2N_max_p ! 0.00001/ 3.5d0 + tiny_C_p = tiny_N_p/NCmax_p ! NCmax_c = 0.15d0 +endif call Cobeta(partit, mesh) call Depth_calculations(n, Nn,SinkVel,zF,thick,recipthick, partit, mesh) @@ -134,7 +137,7 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal REcoM_T = min(REcoM_T, 40.d0) !!---- minimum set to 21: K1/K2 Lueker valid between 2degC-35degC and 19-43psu, else causes trouble in regions with S between 19 and 21 and ice conc above 97% - REcoM_S = max(21.d0, Sali(1)) + REcoM_S = max(21.d0, Sali(1)) !!---- maximum set to 43: K1/K2 Lueker valid between 2degC-35degC and 19-43psu, else causes trouble REcoM_S = min(REcoM_S, 43.d0) !!!!!!!! !!---- convert from Pa to atm. @@ -183,7 +186,7 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal endif call flxco2(co2flux, co2ex, dpco2surf, & - ph, pco2surf, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, & + 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') @@ -259,19 +262,71 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal state(1:nn,idiac) = max(tiny_C_d,state(1:nn,idiac)) state(1:nn,idiasi) = max(tiny_Si, state(1:nn,idiasi)) -#if defined (__coccos) +if (enable_coccos) then state(1:nn,icchl) = max(tiny_chl,state(1:nn,icchl)) state(1:nn,icocn) = max(tiny_N_c,state(1:nn,icocn)) state(1:nn,icocc) = max(tiny_C_c,state(1:nn,icocc)) -#endif -#if defined (__3Zoo2Det) + state(1:nn,iphachl) = max(tiny_chl,state(1:nn,iphachl)) + state(1:nn,iphan) = max(tiny_N_p,state(1:nn,iphan)) + state(1:nn,iphac) = max(tiny_C_p,state(1:nn,iphac)) +endif + +if (enable_3zoo2det) then state(1:nn,imiczoon) = max(tiny,state(1:nn,imiczoon)) state(1:nn,imiczooc) = max(tiny,state(1:nn,imiczooc)) -#endif +endif if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> ciso after REcoM_Forcing'//achar(27)//'[0m' + if (ciso) then +! Calculate carbon-isotopic fractionation, radioactive decay is calculated in oce_ale_tracer.F90 + +! Fractionation due to air-sea exchange and chemical speciation of CO2 + call recom_ciso_airsea(recom_t(1), co3(1), recom_dic(1)) ! -> alpha_aq, alpha_dic. CO3 is taken from mocsy + +! Isotopic ratios of dissolved CO2, also needed to calculate biogenic fractionation + r_dic_13 = max(tiny*1e-3,state(1,idic_13)*1e-3) / recom_dic(1) + r_co2s_13 = alpha_aq_13 / alpha_dic_13 * r_dic_13 +! Calculate air-sea fluxes of 13|14CO2 in mmol / m**2 / s + kwco2 = kw660(1) * (660/scco2(REcoM_T(1)))**0.5 ! Piston velocity (via mocsy) + co2sat = co2flux(1) / (kwco2 + tiny) + co2(1) ! Saturation concentration of CO2 (via mocsy) +! co2flux_13 = kwco2 * alpha_k_13 * (alpha_aq_13 * r_atm_13 * co2sat - r_co2s_13 * co2(1)) +! co2flux_13 = alpha_k_13 * alpha_aq_13 * kwco2 * (r_atm_13 * co2sat - r_dic_13 * co2(1) / alpha_dic_13) +! Fractionation factors were determined for freshwater, include a correction for enhanced fractionation in seawater + co2flux_13 = (alpha_k_13 * alpha_aq_13 - 0.0002) * kwco2 * (r_atm_13 * co2sat - r_dic_13 * co2(1) / alpha_dic_13) + co2flux_seaicemask_13 = co2flux_13 * 1.e3 + +! Biogenic fractionation due to photosynthesis of plankton +! phyc_13|14 and diac_13|14 are only used in REcoM_sms to calculate DIC_13|14, DOC_13|14 and DetC_13|14 + + call recom_ciso_photo(co2(1)) ! -> alpha_p + r_phyc_13 = r_co2s_13 / alpha_p_13 + r_diac_13 = r_co2s_13 / alpha_p_dia_13 + state(1:nn,iphyc_13) = max((tiny_C * r_phyc_13), (state(1:nn,iphyc) * r_phyc_13)) + state(1:nn,idiac_13) = max((tiny_C_d * r_diac_13), (state(1:nn,idiac) * r_diac_13)) + +! The same for radiocarbon, fractionation factors have been already derived above + if (ciso_14) then +! Air-sea exchange + r_dic_14 = max(tiny*1e-3,state(1,idic_14)*1e-3) / recom_dic(1) + r_co2s_14 = alpha_aq_14 / alpha_dic_14 * r_dic_14 +! co2flux_14 = kwco2 * alpha_k_14 * (alpha_aq_14 * r_atm_14 * co2sat - r_co2s_14 * co2(1)) +! Fractionation factors were determined for freshwater, include a correction for enhanced fractionation seawater + co2flux_14 = (alpha_k_14 * alpha_aq_14 - 0.0004) * kwco2 * (r_atm_14 * co2sat - r_dic_14 * co2(1) / alpha_dic_14) + co2flux_seaicemask_14 = co2flux_14 * 1.e3 +! Biogenic fractionation + if (ciso_organic_14) then + r_phyc_14 = r_co2s_14 / alpha_p_14 + r_diac_14 = r_co2s_14 / alpha_p_dia_14 + state(1:nn,iphyc_14) = max((tiny_C * r_phyc_14), (state(1:nn,iphyc) * r_phyc_14)) + state(1:nn,idiac_14) = max((tiny_C_d * r_diac_14), (state(1:nn,idiac) * r_diac_14)) + end if + end if +! Radiocarbon + end if +! ciso + !------------------------------------------------------------------------------- ! Diagnostics if (Diags) then @@ -291,10 +346,66 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal locNNAd = sum(vertNNAd(1:nn) * thick(1:nn)) locChldegd = sum(vertChldegd(1:nn) * thick(1:nn)) +if (enable_coccos) then locNPPc = sum(vertNPPc(1:nn) * thick(1:nn)) locGPPc = sum(vertGPPc(1:nn) * thick(1:nn)) locNNAc = sum(vertNNAc(1:nn) * thick(1:nn)) locChldegc = sum(vertChldegc(1:nn) * thick(1:nn)) + locNPPp = sum(vertNPPp(1:nn) * thick(1:nn)) + locGPPp = sum(vertGPPp(1:nn) * thick(1:nn)) + locNNAp = sum(vertNNAp(1:nn) * thick(1:nn)) + locChldegp = sum(vertChldegp(1:nn) * thick(1:nn)) +endif + + if (Grazing_detritus) then ! only for the case if grazing detritus is used, as probably only needed for tuning which uses detritus grazing + ! Mesozooplankton + locgrazmeso_tot = sum(vertgrazmeso_tot(1:nn) * thick(1:nn)) + locgrazmeso_n = sum(vertgrazmeso_n(1:nn) * thick(1:nn)) + locgrazmeso_d = sum(vertgrazmeso_d(1:nn) * thick(1:nn)) + if (enable_coccos) then + locgrazmeso_c = sum(vertgrazmeso_c(1:nn) * thick(1:nn)) + locgrazmeso_p = sum(vertgrazmeso_p(1:nn) * thick(1:nn)) + endif + locgrazmeso_det = sum(vertgrazmeso_det(1:nn) * thick(1:nn)) + if (enable_3zoo2det) then + locgrazmeso_mic = sum(vertgrazmeso_mic(1:nn) * thick(1:nn)) + locgrazmeso_det2= sum(vertgrazmeso_det2(1:nn) * thick(1:nn)) + endif + + if (enable_3zoo2det) then + ! Macrozooplankton + locgrazmacro_tot = sum(vertgrazmacro_tot(1:nn) * thick(1:nn)) + locgrazmacro_n = sum(vertgrazmacro_n(1:nn) * thick(1:nn)) + locgrazmacro_d = sum(vertgrazmacro_d(1:nn) * thick(1:nn)) + if (enable_coccos) then + locgrazmacro_c = sum(vertgrazmacro_c(1:nn) * thick(1:nn)) + locgrazmacro_p = sum(vertgrazmacro_p(1:nn) * thick(1:nn)) + endif + locgrazmacro_mes = sum(vertgrazmacro_mes(1:nn) * thick(1:nn)) + locgrazmacro_det = sum(vertgrazmacro_det(1:nn) * thick(1:nn)) + locgrazmacro_mic = sum(vertgrazmacro_mic(1:nn) * thick(1:nn)) + locgrazmacro_det2 = sum(vertgrazmacro_det2(1:nn) * thick(1:nn)) + + ! Microzooplankton + locgrazmicro_tot = sum(vertgrazmicro_tot(1:nn) * thick(1:nn)) + locgrazmicro_n = sum(vertgrazmicro_n(1:nn) * thick(1:nn)) + locgrazmicro_d = sum(vertgrazmicro_d(1:nn) * thick(1:nn)) + if (enable_coccos) then + locgrazmicro_c = sum(vertgrazmicro_c(1:nn) * thick(1:nn)) + locgrazmicro_p = sum(vertgrazmicro_p(1:nn) * thick(1:nn)) + endif + + endif + endif + + ! Dissolution and remineralization ! R2OMIP + locDISSOC = sum(vertDISSOC(1:nn) * thick(1:nn)) + locDISSON = sum(vertDISSON(1:nn) * thick(1:nn)) + locDISSOSi = sum(vertDISSOSi(1:nn) * thick(1:nn)) + locREMOC = sum(vertREMOC(1:nn) * thick(1:nn)) + locREMOCt = sum(vertREMOCt(1:nn) * thick(1:nn)) + locREMON = sum(vertREMON(1:nn) * thick(1:nn)) + end if end subroutine REcoM_Forcing diff --git a/src/int_recom/recom_init.F90 b/src/int_recom/recom_init.F90 index e9b5aebbf..d622b83c2 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -45,6 +45,9 @@ subroutine recom_init(tracers, partit, mesh) type(t_partit), intent(inout), target :: partit type(t_mesh), intent(in) , target :: mesh + ! After reading tracer namelist - validate actual IDs + integer, dimension(tracers%num_tracers) :: tracer_id_array + #include "../associate_part_def.h" #include "../associate_mesh_def.h" #include "../associate_part_ass.h" @@ -63,14 +66,24 @@ subroutine recom_init(tracers, partit, mesh) allocate(GloNDust ( node_size )) allocate(AtmNInput ( node_size )) + ! calcite dissolution at the ocean bottom + allocate(OmegaC_bottom(node_size)) !R2OMIP + !! * River nutrients as surface boundary condition * - allocate(RiverDIN2D ( node_size )) +! allocate(RiverDIN2D ( node_size )) allocate(RiverDON2D ( node_size )) - allocate(RiverDOC2D ( node_size )) +! allocate(RiverDOC2D ( node_size )) allocate(RiverDSi2D ( node_size )) - allocate(RiverDIC2D ( node_size )) +! allocate(RiverDIC2D ( node_size )) allocate(RiverAlk2D ( node_size )) + allocate(RiverDIC2D ( node_size )) ! R2OMIP + allocate(RiverDIN2D ( node_size )) ! R2OMIP + allocate(RiverDOCl2D ( node_size )) ! R2OMIP + allocate(RiverDOCsl2D ( node_size )) ! R2OMIP + allocate(RiverPOC2D ( node_size )) ! R2OMIP + allocate(RiverFe ( node_size )) + !! * Erosion nutrients as surface boundary condition * allocate(ErosionTON2D ( node_size )) allocate(ErosionTOC2D ( node_size )) @@ -90,26 +103,49 @@ subroutine recom_init(tracers, partit, mesh) allocate(GlodecayBenthos ( node_size, benthos_num )) allocate(Benthos ( node_size, benthos_num )) allocate(Benthos_tr ( node_size, benthos_num, num_tracers )) ! kh 25.03.22 buffer per tracer index + + allocate(LocDenit ( node_size )) + allocate(LocBurial ( benthos_num, node_size )) ! R2OMIP + allocate(Burial ( benthos_num, node_size )) ! R2OMIP + allocate(BurialBen ( benthos_num )) ! R2OMIP + allocate(Sed_2_Ocean_Flux ( node_size, 6 )) ! DIN, DIC, Alk, DSi, DFe, O2 ! R2OMIP + allocate(Ocean_2_Sed_Flux ( node_size, benthos_num )) ! C, Si, N, Calc ! R2OMIP + allocate(GloHplus ( node_size )) allocate(DenitBen ( node_size )) + allocate(PistonVelocity ( node_size )) + allocate(alphaCO2 ( node_size )) + 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 AtmNInput = 0.d0 - RiverDIN2D = 0.d0 + ! calcite dissolution at the ocean bottom !R2OMIP + OmegaC_bottom = 0.d0 + +! RiverDIN2D = 0.d0 RiverDON2D = 0.d0 - RiverDOC2D = 0.d0 +! RiverDOC2D = 0.d0 RiverDSi2D = 0.d0 - RiverDIC2D = 0.d0 +! RiverDIC2D = 0.d0 RiverAlk2D = 0.d0 - ErosionTON2D = 0.d0 + RiverDIC2D = 0.d0 + RiverDIN2D = 0.d0 + RiverDOCl2D = 0.d0 + RiverDOCsl2D = 0.d0 + RiverPOC2D = 0.d0 + + RiverFe = 0.d0 + + ErosionTOC2D = 0.d0 ErosionTON2D = 0.d0 ErosionTSi2D = 0.d0 @@ -127,11 +163,15 @@ subroutine recom_init(tracers, partit, mesh) Benthos_tr(:,:,:) = 0.0d0 ! kh 25.03.22 GloHplus = exp(-8.d0 * log(10.d0)) ! = 10**(-8) DenitBen = 0.d0 + PistonVelocity = 0.d0 + alphaCO2 = 0.d0 + + Burial = 0.d0 ! R2OMIP + Sed_2_Ocean_Flux = 0.0d0 ! R2OMIP + Ocean_2_Sed_Flux = 0.0d0 ! R2OMIP LocBenthos = 0.d0 decayBenthos = 0.d0 - wFluxPhy = 0.d0 - wFluxDia = 0.d0 PAR3D = 0.d0 ! pco2surf = 0.d0 @@ -148,28 +188,100 @@ subroutine recom_init(tracers, partit, mesh) allocate(NPPn ( node_size )) allocate(NPPd ( node_size )) allocate(NPPc ( node_size )) + allocate(NPPp ( node_size )) allocate(GPPn ( node_size )) allocate(GPPd ( node_size )) allocate(GPPc ( node_size )) + allocate(GPPp ( node_size )) allocate(NNAn ( node_size )) allocate(NNAd ( node_size )) allocate(NNAc ( node_size )) + allocate(NNAp ( node_size )) allocate(Chldegn ( node_size )) allocate(Chldegd ( node_size )) allocate(Chldegc ( node_size )) + allocate(Chldegp ( node_size )) NPPn = 0.d0 NPPd = 0.d0 NPPc = 0.d0 + NPPp = 0.d0 GPPn = 0.d0 GPPd = 0.d0 GPPc = 0.d0 + GPPp = 0.d0 NNAn = 0.d0 NNAd = 0.d0 NNAc = 0.d0 + NNAp = 0.d0 Chldegn = 0.d0 Chldegd = 0.d0 Chldegc = 0.d0 + Chldegp = 0.d0 + + allocate(grazmeso_tot(node_size)) + allocate(grazmeso_n(node_size)) + allocate(grazmeso_d(node_size)) + allocate(grazmeso_c(node_size)) + allocate(grazmeso_p(node_size)) + allocate(grazmeso_det(node_size)) + allocate(grazmeso_mic(node_size)) + allocate(grazmeso_det2(node_size)) + + grazmeso_tot = 0.d0 + grazmeso_n = 0.d0 + grazmeso_d = 0.d0 + grazmeso_c = 0.d0 + grazmeso_p = 0.d0 + grazmeso_det = 0.d0 + grazmeso_mic = 0.d0 + grazmeso_det2= 0.d0 + + allocate(grazmacro_tot(node_size)) + allocate(grazmacro_n(node_size)) + allocate(grazmacro_d(node_size)) + allocate(grazmacro_c(node_size)) + allocate(grazmacro_p(node_size)) + allocate(grazmacro_mes(node_size)) + allocate(grazmacro_det(node_size)) + allocate(grazmacro_mic(node_size)) + allocate(grazmacro_det2(node_size)) + + grazmacro_tot = 0.d0 + grazmacro_n = 0.d0 + grazmacro_d = 0.d0 + grazmacro_c = 0.d0 + grazmacro_p = 0.d0 + grazmacro_mes = 0.d0 + grazmacro_det = 0.d0 + grazmacro_mic = 0.d0 + grazmacro_det2= 0.d0 + + allocate(grazmicro_tot(node_size)) + allocate(grazmicro_n(node_size)) + allocate(grazmicro_d(node_size)) + allocate(grazmicro_c(node_size)) + allocate(grazmicro_p(node_size)) + + grazmicro_tot = 0.d0 + grazmicro_n = 0.d0 + grazmicro_d = 0.d0 + grazmicro_c = 0.d0 + grazmicro_p = 0.d0 + + ! Dissolution and remineralization ! R2OMIP + allocate(DISSOC(node_size)) + allocate(DISSON(node_size)) + allocate(DISSOSi(node_size)) + allocate(REMOC(node_size)) + allocate(REMOCt(node_size)) + allocate(REMON(node_size)) + DISSOC = 0.d0 + DISSON = 0.d0 + DISSOSi = 0.d0 + REMOC = 0.d0 + REMOCt = 0.d0 + REMON = 0.d0 !! *** Allocate 3D diagnostics *** allocate(respmeso ( nl-1, node_size )) @@ -180,15 +292,34 @@ subroutine recom_init(tracers, partit, mesh) allocate(aggn ( nl-1, node_size )) allocate(aggd ( nl-1, node_size )) allocate(aggc ( nl-1, node_size )) + allocate(aggp ( nl-1, node_size )) allocate(docexn ( nl-1, node_size )) allocate(docexd ( nl-1, node_size )) allocate(docexc ( nl-1, node_size )) + allocate(docexp ( nl-1, node_size )) allocate(respn ( nl-1, node_size )) allocate(respd ( nl-1, node_size )) allocate(respc ( nl-1, node_size )) + allocate(respp ( nl-1, node_size )) allocate(NPPn3D ( nl-1, node_size )) allocate(NPPd3D ( nl-1, node_size )) allocate(NPPc3D ( nl-1, node_size )) + allocate(NPPp3D ( nl-1, node_size )) + + allocate(photn ( nl-1, node_size )) + allocate(photd ( nl-1, node_size )) + allocate(photc ( nl-1, node_size )) + allocate(photp ( nl-1, node_size )) + allocate(DOCremin ( nl-1, node_size )) + allocate(Nassimn ( nl-1, node_size )) + allocate(Nassimd ( nl-1, node_size )) + allocate(Nassimc ( nl-1, node_size )) + allocate(Nassimp ( nl-1, node_size )) + allocate(DONremin ( nl-1, node_size )) + allocate(fastcdis ( nl-1, node_size )) + allocate(mesocdis ( nl-1, node_size )) + allocate(microcdis ( nl-1, node_size )) + allocate(macrocdis ( nl-1, node_size )) respmeso = 0.d0 respmacro = 0.d0 @@ -198,15 +329,93 @@ subroutine recom_init(tracers, partit, mesh) aggn = 0.d0 aggd = 0.d0 aggc = 0.d0 + aggp = 0.d0 docexn = 0.d0 docexd = 0.d0 docexc = 0.d0 + docexp = 0.d0 respn = 0.d0 respd = 0.d0 respc = 0.d0 + respp = 0.d0 NPPn3D = 0.d0 NPPd3D = 0.d0 NPPc3D = 0.d0 + NPPp3D = 0.d0 + + photn = 0.d0 + photd = 0.d0 + photc = 0.d0 + photp = 0.d0 + DOCremin = 0.d0 + Nassimn = 0.d0 + Nassimd = 0.d0 + Nassimc = 0.d0 + Nassimp = 0.d0 + DONremin = 0.d0 + fastcdis = 0.d0 + mesocdis = 0.d0 + microcdis = 0.d0 + macrocdis = 0.d0 + +!! From Hannahs new temperature function (not sure if needed as diagnostic): + + allocate(TTemp_diatoms (nl-1,node_size)) + allocate(TTemp_phyto (nl-1,node_size)) + allocate(TTemp_cocco (nl-1,node_size)) + allocate(TTemp_phaeo (nl-1,node_size)) + + TTemp_diatoms (:,:) = 0.d0 + TTemp_phyto (:,:) = 0.d0 + TTemp_cocco (:,:) = 0.d0 + TTemp_phaeo (:,:) = 0.d0 + + allocate(TPhyCO2 (nl-1,node_size)) + allocate(TDiaCO2 (nl-1,node_size)) + allocate(TCoccoCO2 (nl-1,node_size)) + allocate(TPhaeoCO2 (nl-1,node_size)) + + TPhyCO2 (:,:) = 0.d0 + TDiaCO2 (:,:) = 0.d0 + TCoccoCO2 (:,:) = 0.d0 + TPhaeoCO2 (:,:) = 0.d0 + + allocate(TqlimitFac_phyto (nl-1,node_size)) + allocate(TqlimitFac_diatoms (nl-1,node_size)) + allocate(TqlimitFac_cocco (nl-1,node_size)) + allocate(TqlimitFac_phaeo (nl-1,node_size)) + + TqlimitFac_phyto (:,:) = 0.d0 + TqlimitFac_diatoms (:,:) = 0.d0 + TqlimitFac_cocco (:,:) = 0.d0 + TqlimitFac_phaeo (:,:) = 0.d0 + + + allocate(TCphotLigLim_diatoms (nl-1,node_size)) + allocate(TCphotLigLim_phyto (nl-1,node_size)) + allocate(TCphotLigLim_cocco (nl-1,node_size)) + allocate(TCphotLigLim_phaeo (nl-1,node_size)) + + + TCphotLigLim_diatoms (:,:) = 0.d0 + TCphotLigLim_phyto (:,:) = 0.d0 + TCphotLigLim_cocco (:,:) = 0.d0 + TCphotLigLim_phaeo (:,:) = 0.d0 + + allocate(TCphot_diatoms (nl-1,node_size)) + allocate(TCphot_phyto (nl-1,node_size)) + allocate(TCphot_cocco (nl-1,node_size)) + allocate(TCphot_phaeo (nl-1,node_size)) + + TCphot_diatoms (:,:) = 0.d0 + TCphot_phyto (:,:) = 0.d0 + TCphot_cocco (:,:) = 0.d0 + TCphot_phaeo (:,:) = 0.d0 + + allocate(TSi_assimDia (nl-1,node_size)) + + TSi_assimDia (:,:) = 0.d0 + end if !! *** Allocate 3D mocsy *** @@ -246,125 +455,258 @@ subroutine recom_init(tracers, partit, mesh) Sinkingvel1(:,:) = 0.d0 Sinkingvel2(:,:) = 0.d0 + allocate(Sinkvel1_tr(nl,node_size,num_tracers), Sinkvel2_tr(nl,node_size,num_tracers)) ! OG 16.03.23 + Sinkvel1_tr(:,:,:) = 0.0d0 + Sinkvel2_tr(:,:,:) = 0.0d0 + + allocate(dtr_bf_dic(nl,node_size,num_tracers),dtr_bflux_dic(nl,node_size)) ! RP on 26.09.2025 + dtr_bflux_dic(:,:) = 0.0d0 !RP on 26.09.2025 + dtr_bf_dic(:,:,:) = 0.0d0 !RP on 26.09.2025 + + allocate(dtr_bf_din(nl,node_size,num_tracers),dtr_bflux_din(nl,node_size)) + dtr_bflux_din(:,:) = 0.0d0 + dtr_bf_din(:,:,:) = 0.0d0 + + allocate(dtr_bf_alk(nl,node_size,num_tracers),dtr_bflux_alk(nl,node_size)) + dtr_bflux_alk(:,:) = 0.0d0 + dtr_bf_alk(:,:,:) = 0.0d0 + + allocate(dtr_bf_dsi(nl,node_size,num_tracers),dtr_bflux_dsi(nl,node_size)) + dtr_bflux_dsi(:,:) = 0.0d0 + dtr_bf_dsi(:,:,:) = 0.0d0 + + if (use_MEDUSA) then + allocate(GloSed(node_size,sedflx_num)) + allocate(SinkFlx(node_size,bottflx_num)) + allocate(SinkFlx_tr(node_size,bottflx_num,num_tracers)) ! kh 25.03.22 buffer sums per tracer index + + SinkFlx(:,:) = 0.d0 + SinkFlx_tr(:,:,:) = 0.0d0 ! kh 25.03.22 + GloSed(:,:) = 0.d0 + allocate(lb_flux(node_size,9)) + lb_flux(:,:) = 0.d0 + end if + + ! After reading parecomsetup namelist + call initialize_tracer_indices + + ! Validation check here + call validate_recom_tracers(num_tracers, mype) + + ! ... populate tracer_id_array from namelist ... + tracer_id_array = tracers%data(1:tracers%num_tracers)%ID + call validate_tracer_id_sequence(tracer_id_array, num_tracers, mype) + + !=============================================================================== + ! Model Configuration Summary + !=============================================================================== + ! Configuration 1: Base model (enable_3zoo2det=F, enable_coccos=F) + ! - 2 Phytoplankton: General Phy, Diatoms + ! - 1 Zooplankton: Heterotrophs + ! - 1 Detritus pool + ! + ! Configuration 2: 3Zoo2Det (enable_3zoo2det=T, enable_coccos=F) + ! - 2 Phytoplankton: General Phy, Diatoms + ! - 3 Zooplankton: Het, Zoo2, Zoo3 + ! - 2 Detritus pools + ! + ! Configuration 3: Coccos (enable_3zoo2det=F, enable_coccos=T) + ! - 4 Phytoplankton: General Phy, Diatoms, Coccos, Phaeo + ! - 1 Zooplankton: Heterotrophs + ! - 1 Detritus pool + ! + ! Configuration 4: Full model (enable_3zoo2det=T, enable_coccos=T) + ! - 4 Phytoplankton: General Phy, Diatoms, Coccos, Phaeo + ! - 3 Zooplankton: Het, Zoo2, Zoo3 + ! - 2 Detritus pools + !=============================================================================== + DO i=num_tracers-bgc_num+1, num_tracers id=tracers%data(i)%ID SELECT CASE (id) -! ******************* -! CASE 2phy 1zoo 1det -! ******************* -! Skip: DIN, DIC, Alk, DSi and O2 are read from files -! Fe [mol/L] => [umol/m3] Check the units again! + !--------------------------------------------------------------------------- + ! Base Model: 2 Phytoplankton + 1 Zooplankton + 1 Detritus + !--------------------------------------------------------------------------- + ! Skip: DIN, DIC, Alk, DSi and O2 are read from files + ! Fe [mol/L] => [umol/m3] Check the units again! + + ! --- Small Phytoplankton + CASE (1004) ! PhyN - Phytoplankton Nitrogen + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max - CASE (1004) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max ! PhyN + CASE (1005) ! PhyC - Phytoplankton Carbon + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax - CASE (1005) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax ! PhyC + CASE (1006) ! PhyChl - Phytoplankton Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl - CASE (1006) - tracers%data(i)%values(:,:) = tiny_chl ! PhyChl + ! --- Detritus (Non-living organic matter) --- + CASE (1007) ! DetN - Detrital Nitrogen + tracers%data(i)%values(:,:) = tiny - CASE (1007) - tracers%data(i)%values(:,:) = tiny ! DetN + CASE (1008) ! DetC - Detrital Carbon + tracers%data(i)%values(:,:) = tiny - CASE (1008) - tracers%data(i)%values(:,:) = tiny ! DetC + ! --- Mesozooplankton (Heterotrophs) --- + CASE (1009) ! HetN - Heterotroph Nitrogen + tracers%data(i)%values(:,:) = tiny - CASE (1009) - tracers%data(i)%values(:,:) = tiny ! HetN + CASE (1010) ! HetC - Heterotroph Carbon (using Redfield ratio) + tracers%data(i)%values(:,:) = tiny * Redfield - CASE (1010) - tracers%data(i)%values(:,:) = tiny * Redfield ! HetC + ! --- Dissolved Organic Matter --- + CASE (1011) ! DON - Dissolved Organic Nitrogen + tracers%data(i)%values(:,:) = tiny - CASE (1011) - tracers%data(i)%values(:,:) = tiny ! DON + CASE (1012) ! DOC - Dissolved Organic Carbon + tracers%data(i)%values(:,:) = tiny - CASE (1012) - tracers%data(i)%values(:,:) = tiny ! DOC + ! --- Diatoms --- + CASE (1013) ! DiaN - Diatom Nitrogen + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max - CASE (1013) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max ! DiaN + CASE (1014) ! DiaC - Diatom Carbon + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax - CASE (1014) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax ! DiaC + CASE (1015) ! DiaChl - Diatom Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl - CASE (1015) - tracers%data(i)%values(:,:) = tiny_chl ! DiaChl + CASE (1016) ! DiaSi - Diatom Silica + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max_d/NCmax_d/SiCmax - CASE (1016) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max_d/NCmax_d/SiCmax ! DiaSi + CASE (1017) ! DetSi - Detrital Silica + tracers%data(i)%values(:,:) = tiny - CASE (1017) - tracers%data(i)%values(:,:) = tiny ! DetSi + ! --- Iron (micronutrient) --- + CASE (1019) ! Fe - Iron (unit conversion: mol/L => umol/m3) + tracers%data(i)%values(:,:) = tracers%data(i)%values(:,:)* 1.e9 - CASE (1019) - tracers%data(i)%values(:,:) = tracers%data(i)%values(:,:)* 1.e9 ! Fe [mol/L] => [umol/m3] Check the units again! + ! --- Calcium Carbonate (Calcite) --- + CASE (1020) ! PhyCalc - Phytoplankton Calcite + tracers%data(i)%values(:,:) = tiny * Redfield - CASE (1020) - tracers%data(i)%values(:,:) = tiny * Redfield ! PhyCalc + CASE (1021) ! DetCalc - Detrital Calcite + tracers%data(i)%values(:,:) = tiny - CASE (1021) - tracers%data(i)%values(:,:) = tiny ! DetCalc + !--------------------------------------------------------------------------- + ! Extended Model: Additional Zooplankton and Detritus (enable_3zoo2det) + !--------------------------------------------------------------------------- -! ******************* -! CASE 2phy 2zoo 2det -! ******************* -#if defined (__3Zoo2Det) CASE (1023) - tracers%data(i)%values(:,:) = tiny ! Zoo2N + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! Zoo2N - Macrozooplankton Nitrogen + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! CoccoN - Coccolithophore Nitrogen + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max + END IF + CASE (1024) - tracers%data(i)%values(:,:) = tiny * Redfield ! Zoo2C + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! Zoo2C - Macrozooplankton Carbon + tracers%data(i)%values(:,:) = tiny * Redfield + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! CoccoC - Coccolithophore Carbon + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max / NCmax + END IF + CASE (1025) - tracers%data(i)%values(:,:) = tiny ! DetZ2N + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! DetZ2N - Macrozooplankton Detrital Nitrogen + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! CoccoChl - Coccolithophore Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl + END IF + CASE (1026) - tracers%data(i)%values(:,:) = tiny ! DetZ2C + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! DetZ2C - Macrozooplankton Detrital Carbon + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! PhaeoN - Phaeocystis Nitrogen + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max + END IF + CASE (1027) - tracers%data(i)%values(:,:) = tiny ! DetZ2Si + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! DetZ2Si - Zooplankton 2 Detrital Silica + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! PhaeoC - Phaeocystis Carbon + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max / NCmax + END IF + CASE (1028) - tracers%data(i)%values(:,:) = tiny ! DetZ2Calc -#endif + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! DetZ2Calc - Macrozooplankton Detrital Calcite + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! PhaeoChl - Phaeocystis Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl + END IF + + !--------------------------------------------------------------------------- + ! Extended Model: Coccolithophores with 3Zoo2Det + !--------------------------------------------------------------------------- -! ******************* -! CASE 3phy 2zoo 2det -! ******************* -#if defined (__coccos) & defined (__3Zoo2Det) CASE (1029) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max ! CoccoN + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! CoccoN - Coccolithophore Nitrogen + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max + ELSE IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! Zoo3N - Microzooplankton Nitrogen + tracers%data(i)%values(:,:) = tiny + END IF + CASE (1030) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax ! CoccoC + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! CoccoC - Coccolithophore Carbon + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max / NCmax + ELSE IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! Zoo3C - Microzooplankton Carbon + tracers%data(i)%values(:,:) = tiny * Redfield + END IF + CASE (1031) - tracers%data(i)%values(:,:) = tiny_chl ! CoccoChl -! ******************* -! CASE 3phy 1zoo 1det -! ******************* -#elif defined (__coccos) & !defined (__3Zoo2Det) - CASE (1023) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max ! CoccoN - CASE (1024) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax ! CoccoC - CASE (1025) - tracers%data(i)%values(:,:) = tiny_chl ! CoccoChl -#endif + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! CoccoChl - Coccolithophore Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl + ELSE IF (useRivers) THEN + tracers%data(i)%values(:,:) = 0.0_WP !tiny !R2OMIP + END IF -! ******************* -! CASE 3phy 3zoo 2det -! ******************* -#if defined (__coccos) & defined (__3Zoo2Det) CASE (1032) - tracers%data(i)%values(:,:) = tiny ! Zoo3N + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! PhaeoN - Phaeocystis Nitrogen + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max + END IF + CASE (1033) - tracers%data(i)%values(:,:) = tiny * Redfield ! Zoo3C -#elif !defined (__coccos) & defined (__3Zoo2Det) -! ******************* -! CASE 2phy 3zoo 2det -! ******************* - CASE (1029) - tracers%data(i)%values(:,:) = tiny ! Zoo3N - CASE (1030) - tracers%data(i)%values(:,:) = tiny * Redfield ! Zoo3C -#endif + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! PhaeoC - Phaeocystis Carbon + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max / NCmax + END IF + + CASE (1034) + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! PhaeoChl - Phaeocystis Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl + END IF + + CASE (1035) + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! Zoo3N - Zooplankton 3 Nitrogen + tracers%data(i)%values(:,:) = tiny + END IF + + CASE (1036) + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! Zoo3C - Zooplankton 3 Carbon + tracers%data(i)%values(:,:) = tiny * Redfield + END IF END SELECT END DO @@ -445,5 +787,16 @@ subroutine recom_init(tracers, partit, mesh) call MPI_AllREDUCE(locO2min , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) if (mype==0) write(*,*) ' `-> gobal min init. O2. =', glo + if (enable_3zoo2det) then + is_3zoo2det=1.0_WP + else + is_3zoo2det=0.0_WP + endif + + if (enable_coccos) then + is_coccos=1.0_WP + else + is_coccos=0.0_WP + endif end subroutine recom_init diff --git a/src/int_recom/recom_main.F90 b/src/int_recom/recom_main.F90 index c9c5575e5..8158049ef 100755 --- a/src/int_recom/recom_main.F90 +++ b/src/int_recom/recom_main.F90 @@ -6,8 +6,8 @@ module recom_interface interface subroutine recom(ice, dynamics, tracers, partit, mesh) use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use mod_tracer use MOD_DYN use MOD_ICE @@ -29,8 +29,8 @@ subroutine bio_fluxes(tracers, partit, mesh) use recom_config use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use mod_tracer use g_config @@ -52,11 +52,11 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) use MOD_MESH use MOD_TRACER use MOD_DYN - USE MOD_ICE + use MOD_ICE use o_ARRAYS use o_PARAM - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use recom_declarations use bio_fluxes_interface @@ -64,10 +64,12 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) use recom_glovar use recom_config use recom_ciso + use recom_diags_management use g_clock use g_forcing_arrays, only: press_air, u_wind, v_wind, shortwave use g_comm_auto - IMPLICIT NONE + + implicit none type(t_dyn) , intent(inout), target :: dynamics type(t_tracer), intent(inout), target :: tracers @@ -98,6 +100,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) integer :: idiags real(kind=8) :: Sali + logical :: do_update = .false. real(kind=8), allocatable :: Temp(:), Sali_depth(:), zr(:), PAR(:) real(kind=8), allocatable :: C(:,:) @@ -113,6 +116,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) real(kind=8), allocatable :: OmegaC_watercolumn(:) real(kind=8), allocatable :: kspc_watercolumn(:) real(kind=8), allocatable :: rhoSW_watercolumn(:) + real(kind=WP) :: ttf_rhs_bak (mesh%nl-1, tracers%num_tracers) ! local variable #include "../associate_part_def.h" #include "../associate_mesh_def.h" @@ -135,6 +139,17 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) if (restore_alkalinity) call bio_fluxes(tracers, partit, mesh) if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> bio_fluxes'//achar(27)//'[0m' + if (use_atbox) then ! MERGE +! Prognostic atmospheric isoCO2 + call recom_atbox(partit,mesh) +! optional I/O of isoCO2 and inferred cosmogenic 14C production; this may cost some CPU time + if (ciso .and. ciso_14) then + call annual_event(do_update) + if (do_update .and. mype==0) write (*, fmt = '(a50,2x,i6,4(2x,f6.2))') & + 'Year, xCO2 (ppm), cosmic 14C flux (at / cm² / s):', & + yearold, x_co2atm(1), x_co2atm_13(1), x_co2atm_14(1), cosmic_14(1) * production_rate_to_flux_14 + end if + end if ! ====================================================================================== !********************************* LOOP STARTS ***************************************** @@ -160,6 +175,9 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) !!---- Benthic layers LocBenthos(1:benthos_num) = Benthos(n,1:benthos_num) + !!---- Burial in Benthic layers + BurialBen(1:benthos_num) = Burial(1:benthos_num,n) ! R2OMIP + !!---- Local conc of [H+]-ions from last time step. Decleared and saved in LocVar. !!---- used as first guess for H+ conc. in subroutine CO2flux (provided by recom_init) Hplus = GloHplus(n) @@ -176,6 +194,31 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) !!---- Atmospheric CO2 in LocVar LocAtmCO2 = AtmCO2(month) +! Update of prognostic atmospheric CO2 values + if (use_atbox) then + LocAtmCO2 = x_co2atm(1) + if (ciso) then + LocAtmCO2_13 = x_co2atm_13(1) + if (ciso_14) LocAtmCO2_14 = x_co2atm_14(1) + end if + else +! Consider prescribed atmospheric CO2 values + if (ciso) then + LocAtmCO2_13 = AtmCO2_13(month) + if (ciso_14) then +! Latitude of nodal point n + lat_val = geo_coord_nod2D(2,n) / rad +! Zonally binned NH / SH / TZ 14CO2 input values + LocAtmCO2_14 = AtmCO2_14(lat_zone(lat_val), month) + end if + end if + end if ! use_atbox + + if (ciso) then + r_atm_13 = LocAtmCO2_13(1) / LocAtmCO2(1) + if (ciso_14) r_atm_14 = LocAtmCO2_14(1) / LocAtmCO2(1) + end if + !!---- Shortwave penetration SW = parFrac * shortwave(n) SW = SW * (1.d0 - a_ice(n)) @@ -206,6 +249,15 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) C(1:nzmax, tr_num-2) = tracers%data(tr_num)%values(1:nzmax, n) end do + ttf_rhs_bak = 0.0 + + + do tr_num=1, num_tracers + if (tracers%data(tr_num)%ltra_diag) then + ttf_rhs_bak(1:nzmax,tr_num) = tracers%data(tr_num)%values(1:nzmax, n) + end if + end do + !!---- Depth of the nodes in the water column zr(1:nzmax) = Z_3d_n(1:nzmax, n) @@ -217,57 +269,151 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) NDust = GloNDust(n) * (1.d0 - a_ice(n)) if (Diags) then - - !! * Allocate 3D diagnostics * - allocate(vertrespmeso(nl-1), vertrespmacro(nl-1), vertrespmicro(nl-1)) - vertrespmeso = 0.d0 - vertrespmacro = 0.d0 - vertrespmicro = 0.d0 - - allocate(vertcalcdiss(nl-1), vertcalcif(nl-1)) - vertcalcdiss = 0.d0 - vertcalcif = 0.d0 - - allocate(vertaggn(nl-1), vertaggd(nl-1), vertaggc(nl-1)) - vertaggn = 0.d0 - vertaggd = 0.d0 - vertaggc = 0.d0 - - allocate(vertdocexn(nl-1), vertdocexd(nl-1), vertdocexc(nl-1)) - vertdocexn = 0.d0 - vertdocexd = 0.d0 - vertdocexc = 0.d0 - - allocate(vertrespn(nl-1), vertrespd(nl-1), vertrespc(nl-1)) - vertrespn = 0.d0 - vertrespd = 0.d0 - vertrespc = 0.d0 - - !! * Allocate 2D diagnostics * - allocate(vertNPPn(nl-1), vertGPPn(nl-1), vertNNAn(nl-1), vertChldegn(nl-1)) - vertNPPn = 0.d0 - vertGPPn = 0.d0 - vertNNAn = 0.d0 - vertChldegn = 0.d0 - - allocate(vertNPPd(nl-1), vertGPPd(nl-1), vertNNAd(nl-1), vertChldegd(nl-1)) - vertNPPd = 0.d0 - vertGPPd = 0.d0 - vertNNAd = 0.d0 - vertChldegd = 0.d0 - - allocate(vertNPPc(nl-1), vertGPPc(nl-1), vertNNAc(nl-1), vertChldegc(nl-1)) - vertNPPc = 0.d0 - vertGPPc = 0.d0 - vertNNAc = 0.d0 - vertChldegc = 0.d0 + ! Allocate and initialize all diagnostic arrays for a water column + call allocate_and_init_diags(nl) + allocate(vertmesocdis(nl-1)) + vertmesocdis = 0.d0 + +if (enable_3zoo2det) then + allocate(vertfastcdis(nl-1)) + vertfastcdis = 0.d0 !RP 14.07.2025 + allocate( vertmicrocdis(nl-1), vertmacrocdis(nl-1)) !RP 14.07.2025 + vertmicrocdis = 0.d0 + vertmacrocdis = 0.d0 +endif + allocate(vertphotn(nl-1), vertphotd(nl-1)) !RP 14.07.2025 + vertphotn = 0.d0 + vertphotd = 0.d0 + allocate(vertNassimn(nl-1), vertNassimd(nl-1)) !RP 14.07.2025 + vertNassimn = 0.d0 + vertNassimd = 0.d0 + allocate(vertDONremin(nl-1), vertDOCremin(nl-1)) !RP 15.07.2025 + vertDONremin = 0.d0 + vertDOCremin = 0.d0 +if (enable_coccos) then + allocate(vertphotc(nl-1), vertphotp(nl-1)) !RP 14.07.2025 + vertphotc = 0.d0 + vertphotp = 0.d0 + allocate(vertNassimc(nl-1), vertNassimp(nl-1)) !RP 14.07.2025 + vertNassimc = 0.d0 + vertNassimp = 0.d0 +endif end if +! +! !! * Allocate 3D diagnostics * +! allocate(vertrespmeso(nl-1)) +! vertrespmeso = 0.d0 +! +!if (enable_3zoo2det) then +! allocate(vertrespmacro(nl-1), vertrespmicro(nl-1)) +! vertrespmacro = 0.d0 +! vertrespmicro = 0.d0 +!endif +! allocate(vertcalcdiss(nl-1), vertcalcif(nl-1)) +! vertcalcdiss = 0.d0 +! vertcalcif = 0.d0 +! +! allocate(vertaggn(nl-1), vertaggd(nl-1)) +! vertaggn = 0.d0 +! vertaggd = 0.d0 +! +! allocate(vertdocexn(nl-1), vertdocexd(nl-1)) +! vertdocexn = 0.d0 +! vertdocexd = 0.d0 +! +! allocate(vertrespn(nl-1), vertrespd(nl-1)) +! vertrespn = 0.d0 +! vertrespd = 0.d0 +! +! allocate(VTPhyCO2(nl-1), VTDiaCO2(nl-1)) +! VTPhyCO2 = 0.d0 +! VTDiaCO2 = 0.d0 +! +! allocate(VTCphotLigLim_phyto(nl-1), VTCphotLigLim_diatoms(nl-1)) +! VTCphotLigLim_phyto = 0.d0 +! VTCphotLigLim_diatoms = 0.d0 +! +! allocate(VTCphot_phyto(nl-1), VTCphot_diatoms(nl-1)) +! VTCphot_phyto = 0.d0 +! VTCphot_diatoms = 0.d0 +! +!if (enable_coccos) then +! allocate(VTTemp_diatoms(nl-1), VTTemp_phyto(nl-1)) +! VTTemp_diatoms = 0.d0 +! VTTemp_phyto = 0.d0 +! +! allocate(VTqlimitFac_phyto(nl-1), VTqlimitFac_diatoms(nl-1)) +! VTqlimitFac_phyto = 0.d0 +! VTqlimitFac_diatoms = 0.d0 +! +! allocate(VTSi_assimDia(nl-1)) +! VTSi_assimDia = 0.d0 +! +! allocate(vertaggc(nl-1), vertdocexc(nl-1), vertrespc(nl-1)) +! vertaggc = 0.d0 +! vertdocexc = 0.d0 +! vertrespc = 0.d0 +! +! allocate(vertaggp(nl-1), vertdocexp(nl-1), vertrespp(nl-1)) ! Phaeocystis +! vertaggp = 0.d0 +! vertdocexp = 0.d0 +! vertrespp = 0.d0 +! +! allocate(VTTemp_cocco(nl-1), VTTemp_phaeo(nl-1)) +! VTTemp_cocco = 0.d0 +! VTTemp_phaeo = 0.d0 +! +! allocate(VTCoccoCO2(nl-1), VTPhaeoCO2(nl-1)) +! VTCoccoCO2 = 0.d0 +! VTPhaeoCO2 = 0.d0 +! +! allocate(VTqlimitFac_cocco(nl-1), VTqlimitFac_phaeo(nl-1)) +! VTqlimitFac_cocco = 0.d0 +! VTqlimitFac_phaeo = 0.d0 +! +! allocate(VTCphotLigLim_cocco(nl-1), VTCphotLigLim_phaeo(nl-1)) +! VTCphotLigLim_cocco = 0.d0 +! VTCphotLigLim_phaeo = 0.d0 +! +! allocate(VTCphot_cocco(nl-1), VTCphot_phaeo(nl-1)) +! VTCphot_cocco = 0.d0 +! VTCphot_phaeo = 0.d0 +! +! +!endif +! +! !! * Allocate 2D diagnostics * +! allocate(vertNPPn(nl-1), vertGPPn(nl-1), vertNNAn(nl-1), vertChldegn(nl-1)) +! vertNPPn = 0.d0 +! vertGPPn = 0.d0 +! vertNNAn = 0.d0 +! vertChldegn = 0.d0 +! +! allocate(vertNPPd(nl-1), vertGPPd(nl-1), vertNNAd(nl-1), vertChldegd(nl-1)) +! vertNPPd = 0.d0 +! vertGPPd = 0.d0 +! vertNNAd = 0.d0 +! vertChldegd = 0.d0 +! +!if (enable_coccos) then +! allocate(vertNPPc(nl-1), vertGPPc(nl-1), vertNNAc(nl-1), vertChldegc(nl-1)) +! vertNPPc = 0.d0 +! vertGPPc = 0.d0 +! vertNNAc = 0.d0 +! vertChldegc = 0.d0 +! +! allocate(vertNPPp(nl-1), vertGPPp(nl-1), vertNNAp(nl-1), vertChldegp(nl-1)) +! vertNPPp = 0.d0 +! vertGPPp = 0.d0 +! vertNNAp = 0.d0 +! vertChldegp = 0.d0 +!endif if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> REcoM_Forcing'//achar(27)//'[0m' ! ====================================================================================== !******************************** RECOM FORCING **************************************** - call REcoM_Forcing(zr, n, nzmax, C, SW, Loc_slp , Temp, Sali, Sali_depth & + call REcoM_Forcing(zr, n, nzmax, C, SW, Loc_slp, Temp, Sali, Sali_depth & , CO2_watercolumn & ! NEW MOCSY CO2 for the whole watercolumn , pH_watercolumn & ! NEW MOCSY pH for the whole watercolumn , pCO2_watercolumn & ! NEW MOCSY pCO2 for the whole watercolumn @@ -282,69 +428,192 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) tracers%data(tr_num)%values(1:nzmax, n) = C(1:nzmax, tr_num-2) end do + ! recom_sms + + do tr_num=1, num_tracers + if (tracers%data(tr_num)%ltra_diag) then + tracers%work%tra_recom_sms(1:nzmax,n,tr_num) = tracers%data(tr_num)%values(1:nzmax, n) - ttf_rhs_bak(1:nzmax,tr_num) + !if (mype==0) print *, tra_recom_sms(:,:,tr_num) + end if + + end do + !!---- Local variables that have been changed during the time-step are stored so they can be saved Benthos(n,1:benthos_num) = LocBenthos(1:benthos_num) GlodecayBenthos(n, 1:benthos_num) = decayBenthos(1:benthos_num)/SecondsPerDay ! convert from [mmol/m2/d] to [mmol/m2/s] - if (Diags) then - - !! * Update 2D diagnostics * - NPPn(n) = locNPPn - NPPd(n) = locNPPd - NPPc(n) = locNPPc - GPPn(n) = locGPPn - GPPd(n) = locGPPd - GPPc(n) = locGPPc - NNAn(n) = locNNAn - NNAd(n) = locNNAd - NNAc(n) = locNNAc - Chldegn(n) = locChldegn - Chldegd(n) = locChldegd - Chldegc(n) = locChldegc - - !! * Update 3D diagnostics * - respmeso (1:nzmax,n) = vertrespmeso (1:nzmax) - respmacro (1:nzmax,n) = vertrespmacro (1:nzmax) - respmicro (1:nzmax,n) = vertrespmicro (1:nzmax) - calcdiss (1:nzmax,n) = vertcalcdiss (1:nzmax) - calcif (1:nzmax,n) = vertcalcif (1:nzmax) - aggn (1:nzmax,n) = vertaggn (1:nzmax) - aggd (1:nzmax,n) = vertaggd (1:nzmax) - aggc (1:nzmax,n) = vertaggc (1:nzmax) - docexn (1:nzmax,n) = vertdocexn (1:nzmax) - docexd (1:nzmax,n) = vertdocexd (1:nzmax) - docexc (1:nzmax,n) = vertdocexc (1:nzmax) - respn (1:nzmax,n) = vertrespn (1:nzmax) - respd (1:nzmax,n) = vertrespd (1:nzmax) - respc (1:nzmax,n) = vertrespc (1:nzmax) - NPPn3D (1:nzmax,n) = vertNPPn (1:nzmax) - NPPd3D (1:nzmax,n) = vertNPPd (1:nzmax) - NPPc3D (1:nzmax,n) = vertNPPc (1:nzmax) -if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> ciso after REcoM_Forcing'//achar(27)//'[0m' - - !! * Deallocating 2D diagnostics * - deallocate(vertNPPn, vertGPPn, vertNNAn, vertChldegn) - deallocate(vertNPPd, vertGPPd, vertNNAd, vertChldegd) - deallocate(vertNPPc, vertGPPc, vertNNAc, vertChldegc) - - !! * Deallocating 3D Diagnostics * - deallocate(vertrespmeso, vertrespmacro, vertrespmicro ) - deallocate(vertcalcdiss, vertcalcif ) - deallocate(vertaggn, vertaggd, vertaggc ) - deallocate(vertdocexn, vertdocexd, vertdocexc ) - deallocate(vertrespn, vertrespd, vertrespc ) + if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> ciso after REcoM_Forcing'//achar(27)//'[0m' - end if + if (Diags) then + call update_2d_diags(n) + mesocdis (1:nzmax,n) = vertmesocdis (1:nzmax) +if (enable_3zoo2det) then + microcdis (1:nzmax,n) = vertmicrocdis (1:nzmax) !RP 14.07.2025 + macrocdis (1:nzmax,n) = vertmacrocdis (1:nzmax) !RP 14.07.2025 + fastcdis (1:nzmax,n) = vertfastcdis (1:nzmax) !RP 14.07.2025 +endif + photn (1:nzmax,n) = vertphotn (1:nzmax) !RP 14.07.2025 + photd (1:nzmax,n) = vertphotd (1:nzmax) !RP 14.07.2025 + Nassimn (1:nzmax,n) = vertNassimn (1:nzmax) !RP 14.07.2025 + Nassimd (1:nzmax,n) = vertNassimd (1:nzmax) !RP 14.07.2025 +if (enable_coccos) then + photc (1:nzmax,n) = vertphotc (1:nzmax) !RP 14.07.2025 + photp (1:nzmax,n) = vertphotp (1:nzmax) !RP 14.07.2025 + Nassimc (1:nzmax,n) = vertNassimc (1:nzmax) !RP 14.07.2025 + Nassimp (1:nzmax,n) = vertNassimp (1:nzmax) !RP 14.07.2025 +endif + DONremin (1:nzmax,n) = vertDONremin (1:nzmax) !RP 14.07.2025 + DOCremin (1:nzmax,n) = vertDOCremin (1:nzmax) !RP 15.07.2025 + + call update_3d_diags(n, nzmax) + ! Deallocate vertical tracer array + call deallocate_diags() + + deallocate(vertmesocdis) + +if (enable_3zoo2det) then + deallocate(vertfastcdis) + deallocate(vertmicrocdis,vertmacrocdis) ! RP 14.07.2025 +endif + deallocate(vertDONremin, vertDOCremin) !RP 15.07.2025 + deallocate(vertphotn, vertNassimn) !RP 14.07.2025 + deallocate(vertphotd, vertNassimd) !RP 14.07.2025 +if (enable_coccos) then + deallocate(vertphotc, vertNassimc) !RP 14.07.2025 + deallocate(vertphotp, vertNassimp) !RP 08.01.2026 +endif + endif +! !! * Update 2D diagnostics * +! NPPn(n) = locNPPn +! NPPd(n) = locNPPd +! GPPn(n) = locGPPn +! GPPd(n) = locGPPd +! NNAn(n) = locNNAn +! NNAd(n) = locNNAd +! Chldegn(n) = locChldegn +! Chldegd(n) = locChldegd +! +!if (enable_coccos) then +! NPPc(n) = locNPPc +! GPPc(n) = locGPPc +! NNAc(n) = locNNAc +! Chldegc(n) = locChldegc +! NPPp(n) = locNPPp +! GPPp(n) = locGPPp +! NNAp(n) = locNNAp +! Chldegp(n) = locChldegp +!endif +! +! !! * Update 3D diagnostics * +! respmeso (1:nzmax,n) = vertrespmeso (1:nzmax) +!if (enable_3zoo2det) then +! respmacro (1:nzmax,n) = vertrespmacro (1:nzmax) +! respmicro (1:nzmax,n) = vertrespmicro (1:nzmax) +!endif +! calcdiss (1:nzmax,n) = vertcalcdiss (1:nzmax) +! calcif (1:nzmax,n) = vertcalcif (1:nzmax) +! +! aggn (1:nzmax,n) = vertaggn (1:nzmax) +! docexn (1:nzmax,n) = vertdocexn (1:nzmax) +! respn (1:nzmax,n) = vertrespn (1:nzmax) +! NPPn3D (1:nzmax,n) = vertNPPn (1:nzmax) +! +! aggd (1:nzmax,n) = vertaggd (1:nzmax) +! docexd (1:nzmax,n) = vertdocexd (1:nzmax) +! respd (1:nzmax,n) = vertrespd (1:nzmax) +! NPPd3D (1:nzmax,n) = vertNPPd (1:nzmax) +! +! TPhyCO2 (1:nzmax,n) = VTPhyCO2 (1:nzmax) +! TDiaCO2 (1:nzmax,n) = VTDiaCO2 (1:nzmax) +! TCphotLigLim_phyto (1:nzmax,n) = VTCphotLigLim_phyto (1:nzmax) +! TCphotLigLim_diatoms(1:nzmax,n) = VTCphotLigLim_diatoms (1:nzmax) +! TCphot_phyto (1:nzmax,n) = VTCphot_phyto (1:nzmax) +! TCphot_diatoms (1:nzmax,n) = VTCphot_diatoms (1:nzmax) +! +!if (enable_coccos) then +! +! TTemp_phyto (1:nzmax,n) = VTTemp_phyto (1:nzmax) +! TqlimitFac_phyto (1:nzmax,n) = VTqlimitFac_phyto (1:nzmax) +! TTemp_diatoms (1:nzmax,n) = VTTemp_diatoms (1:nzmax) !! NEW from here tracking vars +! TqlimitFac_diatoms (1:nzmax,n) = VTqlimitFac_diatoms (1:nzmax) +! TSi_assimDia (1:nzmax,n) = VTSi_assimDia (1:nzmax) +! +! aggc (1:nzmax,n) = vertaggc (1:nzmax) +! docexc (1:nzmax,n) = vertdocexc (1:nzmax) +! respc (1:nzmax,n) = vertrespc (1:nzmax) +! NPPc3D (1:nzmax,n) = vertNPPc (1:nzmax) +! +! aggp (1:nzmax,n) = vertaggp (1:nzmax) +! docexp (1:nzmax,n) = vertdocexp (1:nzmax) +! respp (1:nzmax,n) = vertrespp (1:nzmax) +! NPPp3D (1:nzmax,n) = vertNPPp (1:nzmax) +! +! TTemp_cocco (1:nzmax,n) = VTTemp_cocco (1:nzmax) +! TCoccoCO2 (1:nzmax,n) = VTCoccoCO2 (1:nzmax) +! TqlimitFac_cocco (1:nzmax,n) = VTqlimitFac_cocco (1:nzmax) +! TCphotLigLim_cocco (1:nzmax,n) = VTCphotLigLim_cocco (1:nzmax) +! TCphot_cocco (1:nzmax,n) = VTCphot_cocco (1:nzmax) +! +! TTemp_phaeo (1:nzmax,n) = VTTemp_phaeo (1:nzmax) +! TPhaeoCO2 (1:nzmax,n) = VTPhaeoCO2 (1:nzmax) +! TqlimitFac_phaeo (1:nzmax,n) = VTqlimitFac_phaeo (1:nzmax) +! TCphotLigLim_phaeo (1:nzmax,n) = VTCphotLigLim_phaeo (1:nzmax) +! TCphot_phaeo (1:nzmax,n) = VTCphot_phaeo (1:nzmax) +! +! endif +! +!if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> ciso after REcoM_Forcing'//achar(27)//'[0m' +! +! !! * Deallocating 2D diagnostics * +! deallocate(vertNPPn, vertGPPn, vertNNAn, vertChldegn) +! deallocate(vertNPPd, vertGPPd, vertNNAd, vertChldegd) +!if (enable_coccos) then +! deallocate(vertNPPc, vertGPPc, vertNNAc, vertChldegc) +! deallocate(vertNPPp, vertGPPp, vertNNAp, vertChldegp) +!endif +! +! !! * Deallocating 3D Diagnostics * +! deallocate(vertrespmeso) +!if (enable_3zoo2det) then +! deallocate(vertrespmacro, vertrespmicro) +!endif +! deallocate(vertcalcdiss, vertcalcif) +! deallocate(vertaggn, vertdocexn, vertrespn) +! deallocate(vertaggd, vertdocexd, vertrespd) +! deallocate(VTPhyCO2, VTCphotLigLim_phyto, VTCphot_phyto) +! deallocate(VTDiaCO2, VTCphotLigLim_diatoms, VTCphot_diatoms) +! +!if (enable_coccos) then +! deallocate(vertgrazmeso_c) +! deallocate(VTTemp_phyto, VTqlimitFac_phyto) +! deallocate(VTTemp_diatoms, VTqlimitFac_diatoms) +! +! deallocate(VTSi_assimDia) +! deallocate(vertaggc, vertdocexc, vertrespc) +! deallocate(vertaggp, vertdocexp, vertrespp) +! +! deallocate(VTTemp_cocco, VTCoccoCO2, VTqlimitFac_cocco, VTCphotLigLim_cocco, VTCphot_cocco) +! deallocate(VTTemp_phaeo, VTPhaeoCO2, VTqlimitFac_phaeo, VTCphotLigLim_phaeo, VTCphot_phaeo) +! +!endif AtmFeInput(n) = FeDust AtmNInput(n) = NDust GloHplus(n) = ph(1) + PistonVelocity(n) = kw660(1) + alphaCO2(n) = K0(1) GloPCO2surf(n) = pco2surf(1) GlodPCO2surf(n) = dpco2surf(1) GloCO2flux(n) = dflux(1) ! [mmol/m2/d] GloCO2flux_seaicemask(n) = co2flux_seaicemask(1) ! [mmol/m2/s] GloO2flux_seaicemask(n) = o2flux_seaicemask(1) ! [mmol/m2/s] + if (ciso) then + GloCO2flux_seaicemask_13(n) = co2flux_seaicemask_13(1) ! [mmol/m2/s] + if (ciso_14) then + GloCO2flux_seaicemask_14(n) = co2flux_seaicemask_14(1) ! [mmol/m2/s] + end if + end if GloO2flux(n) = oflux(1) ! [mmol/m2/d] PAR3D(1:nzmax,n) = PAR(1:nzmax) @@ -375,6 +644,16 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) call exchange_nod(GloCO2flux_seaicemask, partit) call exchange_nod(GloO2flux_seaicemask, partit) + if (ciso) then + call exchange_nod(GloPCO2surf_13, partit) + call exchange_nod(GloCO2flux_13, partit) + call exchange_nod(GloCO2flux_seaicemask_13, partit) + if (ciso_14) then + call exchange_nod(GloPCO2surf_14, partit) + call exchange_nod(GloCO2flux_14, partit) + call exchange_nod(GloCO2flux_seaicemask_14, partit) + end if + end if do n=1, benthos_num call exchange_nod(Benthos(:,n), partit) end do @@ -388,16 +667,56 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) call exchange_nod(NNAd, partit) call exchange_nod(Chldegn, partit) call exchange_nod(Chldegd, partit) - call exchange_nod(NPPc, partit) - call exchange_nod(GPPc, partit) - call exchange_nod(NNAc, partit) - call exchange_nod(Chldegc, partit) + if (enable_coccos) then + call exchange_nod(NPPc, partit) + call exchange_nod(GPPc, partit) + call exchange_nod(NNAc, partit) + call exchange_nod(Chldegc, partit) + call exchange_nod(NPPp, partit) + call exchange_nod(GPPp, partit) + call exchange_nod(NNAp, partit) + call exchange_nod(Chldegp, partit) + endif + call exchange_nod(grazmeso_tot, partit) + call exchange_nod(grazmeso_n, partit) + call exchange_nod(grazmeso_d, partit) + if (enable_coccos) then + call exchange_nod(grazmeso_c, partit) + call exchange_nod(grazmeso_p, partit) + endif + call exchange_nod(grazmeso_det, partit) + if (enable_3zoo2det) then + call exchange_nod(grazmeso_mic, partit) + call exchange_nod(grazmeso_det2, partit) + call exchange_nod(grazmacro_tot, partit) + call exchange_nod(grazmacro_n, partit) + call exchange_nod(grazmacro_d, partit) + if (enable_coccos) then + call exchange_nod(grazmacro_c, partit) + call exchange_nod(grazmacro_p, partit) + endif + call exchange_nod(grazmacro_mes, partit) + call exchange_nod(grazmacro_det, partit) + call exchange_nod(grazmacro_mic, partit) + call exchange_nod(grazmacro_det2, partit) + call exchange_nod(grazmicro_tot, partit) + call exchange_nod(grazmicro_n, partit) + call exchange_nod(grazmicro_d, partit) + if (enable_coccos) then + call exchange_nod(grazmicro_c, partit) + call exchange_nod(grazmicro_p, partit) + endif + endif endif do n=1, benthos_num call exchange_nod(GlodecayBenthos(:,n), partit) end do + do n=1, 6 + call exchange_nod(Sed_2_Ocean_Flux(:,n), partit) ! Diagnose the flux back from Sediment to Ocean - R2OMIP + end do + call exchange_nod(GloHplus, partit) call exchange_nod(AtmFeInput, partit) call exchange_nod(AtmNInput, partit) @@ -412,6 +731,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) call exchange_nod(OmegaC3D, partit) call exchange_nod(kspc3D, partit) call exchange_nod(rhoSW3D, partit) + end subroutine recom ! ====================================================================================== @@ -425,8 +745,8 @@ subroutine bio_fluxes(tracers, partit, mesh) use recom_config use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use mod_tracer use g_config @@ -496,4 +816,4 @@ subroutine bio_fluxes(tracers, partit, mesh) relax_alk=relax_alk-net/ocean_area ! at ocean surface layer -end subroutine bio_fluxes \ No newline at end of file +end subroutine bio_fluxes diff --git a/src/int_recom/recom_modules.F90 b/src/int_recom/recom_modules.F90 index c4113377c..763e82c98 100644 --- a/src/int_recom/recom_modules.F90 +++ b/src/int_recom/recom_modules.F90 @@ -30,69 +30,53 @@ module recom_config isi = 18, ife = 19, iphycal = 20, idetcal = 21, & ioxy = 22 -#if defined (__3Zoo2Det) -! ******************* -! CASE 2phy 2zoo 2det -! ******************* Integer :: izoo2n = 23, izoo2c = 24, idetz2n = 25, & idetz2c = 26, idetz2si = 27, idetz2calc = 28 -#endif -#if defined (__coccos) & defined (__3Zoo2Det) -! ******************* -! CASE 3phy 2zoo 2det -! ******************* - Integer :: icocn = 29, icocc = 30, icchl = 31 + ! Microzooplankton (third zooplankton group) + integer :: imiczoon = 0 ! Microzooplankton Nitrogen (set below) + integer :: imiczooc = 0 ! Microzooplankton Carbon (set below) -#elif defined (__coccos) & !defined (__3Zoo2Det) -! ******************* -! CASE 3phy 1zoo 1det -! ******************* - Integer :: icocn = 23, icocc = 24, icchl = 25 -#endif + ! --------------------------------------------------------------------------- + ! PHYTOPLANKTON GROUPS (coccos configuration) + ! --------------------------------------------------------------------------- + ! Coccolithophores and Phaeocystis when enable_coccos = .true. -#if defined (__coccos) & defined (__3Zoo2Det) -! ******************* -! CASE 3phy 3zoo 2det -! ******************* - Integer :: imiczoon = 32, imiczooc = 33 + integer :: icocn = 0 ! Coccolithophore Nitrogen (set below) + integer :: icocc = 0 ! Coccolithophore Carbon (set below) + integer :: icchl = 0 ! Coccolithophore Chlorophyll (set below) -#elif !defined (__coccos) & defined (__3Zoo2Det) -! ******************* -! CASE 2phy 3zoo 2det -! ******************* - Integer :: imiczoon = 29, imiczooc = 30 -#endif + integer :: iphan = 0 ! Phaeocystis Nitrogen (set below) + integer :: iphac = 0 ! Phaeocystis Carbon (set below) + integer :: iphachl = 0 ! Phaeocystis Chlorophyll (set below) + + ! Terrestrial DOC input (when useRivers is enabled) + integer :: idoct = 0 !============================================================================= - Integer :: ivphy = 1, ivdia = 2, ivdet = 3, ivdetsc = 4, ivcoc = 5 - + Integer :: ivphy = 1, ivdia = 2, ivdet = 3, ivdetsc = 4, ivcoc = 5, ivpha = 6 + !============================================================================= integer, dimension(8) :: recom_remin_tracer_id = (/1001, 1002, 1003, 1018, 1019, 1022, 1302, 1402/) ! OG ! Todo: Make recom_sinking_tracer_id case sensitive - integer, dimension(29) :: recom_sinking_tracer_id = (/1007, 1008, 1017, 1021, 1004, 1005, 1020, 1006, & + integer, dimension(32) :: recom_sinking_tracer_id = (/1007, 1008, 1017, 1021, 1004, 1005, 1020, 1006, & 1013, 1014, 1016, 1015, 1025, 1026, 1027, 1028, & 1029, 1030, 1031, & + 1032, 1033, 1034, & 1308, 1321, 1305, 1320, & 1314, 1408, 1421, 1405, 1420, 1414/) integer, dimension(8) :: recom_det_tracer_id = (/1007, 1008, 1017, 1021, 1308, 1321, 1408, 1421/) integer, dimension(8) :: recom_phy_tracer_id = (/1004, 1005, 1020, 1305, 1320, 1405, 1420, 1006/) integer, dimension(6) :: recom_dia_tracer_id = (/1013, 1014, 1314, 1414, 1016, 1015/) -#if defined (__coccos) & defined (__3Zoo2Det) - integer, dimension(3) :: recom_cocco_tracer_id = (/1029, 1030, 1031/) - -#elif defined (__coccos) & !defined (__3Zoo2Det) - integer, dimension(3) :: recom_cocco_tracer_id = (/1023, 1024, 1025/) -#endif - -#if defined (__3Zoo2Det) - integer, dimension(4) :: recom_det2_tracer_id = (/1025, 1026, 1027, 1028/) -#endif + ! Configuration-dependent tracer arrays (allocated during initialization) + integer, dimension(3) :: recom_cocco_tracer_id + integer, dimension(3) :: recom_phaeo_tracer_id + integer, dimension(4) :: recom_det2_tracer_id !============================================================================= @@ -104,19 +88,25 @@ module recom_config Real(kind=8) :: Pa2atm = 101325.d0 ! [Pa/atm] Real(kind=8) :: redO2C = 1.453 ! O2:C ratio Anderson and Sarmiento, 1994 +!! *** REcoM setup *** + Logical :: enable_3zoo2det = .false. ! Control extended zooplankton variables + Logical :: enable_coccos = .false. ! Control coccolithophore variables + namelist /parecomsetup/ enable_3zoo2det, enable_coccos + !! *** General configuration *** Logical :: use_REcoM = .true. Logical :: REcoM_restart = .false. - Integer :: bgc_num = 33 ! NEW increased the number from 28 to 34 (added coccos and respiration) ! NEW 3Zoo changed from 31 to 33 + Integer :: bgc_num = 36 ! NEW increased the number from 28 to 34 (added coccos and respiration) ! NEW 3Zoo changed from 31 to 33 ! added phaeocystis: changed from 33 to 36 integer :: bgc_base_num = 22 ! standard tracers - Integer :: diags3d_num = 28 ! Number of diagnostic 3d tracers to be saved + Integer :: diags3d_num = 31 ! Number of diagnostic 3d tracers to be saved Real(kind=8) :: VDet = 20.d0 ! Sinking velocity, constant through the water column and positive downwards Real(kind=8) :: VDet_zoo2 = 200.d0 ! Sinking velocity, constant through the water column Real(kind=8) :: VPhy = 0.d0 !!! If the number of sinking velocities are different from 3, code needs to be changed !!! Real(kind=8) :: VDia = 0.d0 Real(kind=8) :: VCocco = 0.d0 ! NEW + Real(kind=8) :: VPhaeo = 0.d0 ! Phaeocystis Logical :: allow_var_sinking = .true. Integer :: biostep = 1 ! Number of times biology should be stepped forward for each time step Logical :: REcoM_Geider_limiter = .false. ! Decides what routine should be used to calculate limiters in sms @@ -141,6 +131,7 @@ module recom_config character(100) :: REcoMDataPath = '/albedo/work/projects/MarESys/ogurses/input/mesh_CORE2_finaltopo_mean/' logical :: restore_alkalinity = .true. logical :: useRivers = .false. + logical :: constant_PI_Rivers = .true. logical :: useRivFe = .false. ! river input of Fe logical :: useErosion = .false. logical :: NitrogenSS = .false. ! This one only activates rivers! And in principle denitrification, but denitrification is commented out. When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) @@ -168,6 +159,7 @@ module recom_config bgc_num, diags3d_num, bgc_base_num, & VDet, VDet_zoo2, & VPhy, VDia, VCocco, & + VPhaeo, & allow_var_sinking, biostep, REcoM_Geider_limiter, & REcoM_Grazing_Variable_Preference, & Grazing_detritus, & @@ -178,7 +170,8 @@ module recom_config Diags , constant_CO2, & UseFeDust, UseDustClim, UseDustClimAlbani, & use_photodamage, HetRespFlux_plus, REcoMDataPath, & - restore_alkalinity, useRivers, useRivFe, & + restore_alkalinity, useRivers, constant_PI_Rivers, & + useRivFe, & useErosion, NitrogenSS, useAeolianN, & firstyearoffesomcycle, lastyearoffesomcycle, numofCO2cycles, & currentCO2cycle, DIC_PI, Nmocsy, & @@ -201,13 +194,31 @@ module recom_config namelist /painitialization_N/ cPhyN, cHetN, cZoo2N !!------------------------------------------------------------------------------ -!! *** Arrhenius function *** +!! *** Temperature and Arrhenius functions *** Real(kind=8) :: recom_Tref = 288.15d0 ! [K] Real(kind=8) :: C2K = 273.15d0 ! Conversion from degrees C to K Real(kind=8) :: Ae = 4500.d0 ! [K] Slope of the linear part of the Arrhenius function + +!! *** Temperature variables for Blanchard function *** + Real(kind=8) :: Tmax_phaeo = 16d0 ! [degC] For Blanchard temp fxn: maximum temperature + Real(kind=8) :: Topt_phaeo = 7.5272d0 ! [degC] For Blanchard temp fxn: optimum temperature + Real(kind=8) :: uopt_phaeo = 0.7328d0 ! [1/day] For Blanchard function: optimum growth date + Real(kind=8) :: beta_phaeo = 0.7829d0 ! [unitless] For Blanchard function + +! NEW MODIFIED parameters + Real(kind=8) :: ord_d = -0.2216d0 ! parameters for diatom temperature function + Real(kind=8) :: expon_d = 0.0406d0 ! diatom exponent + Real(kind=8) :: ord_phy = -1.2154d0 ! small phyto ordonnee + Real(kind=8) :: expon_phy = 0.0599d0 ! small phyto exponent + Real(kind=8) :: ord_cocco = -0.2310d0 ! coccolith ordonnee + Real(kind=8) :: expon_cocco = 0.0327d0 ! small phyto ordonnee + Real(kind=8) :: ord_phaeo = -0.2310d0 ! phaeocystis ordonnee + Real(kind=8) :: expon_phaeo = 0.0327d0 ! phaeocystis ordonnee + Real(kind=8) :: reminSi = 0.02d0 Real(kind=8) :: 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 - namelist /paArrhenius/ recom_Tref, C2K, Ae, reminSi, k_o2_remin + namelist /paArrhenius/ recom_Tref, C2K, Ae, Tmax_phaeo, Topt_phaeo, uopt_phaeo, beta_phaeo, ord_d, expon_d, ord_phy, expon_phy, ord_cocco, expon_cocco, ord_phaeo, expon_phaeo, reminSi, k_o2_remin + !!------------------------------------------------------------------------------ !! *** For limiter function *** Real(kind=8) :: NMinSlope = 50.d0 @@ -215,15 +226,19 @@ module recom_config Real(kind=8) :: NCmin = 0.04d0 Real(kind=8) :: NCmin_d = 0.04d0 Real(kind=8) :: NCmin_c = 0.04d0 ! NEW + Real(kind=8) :: NCmin_p = 0.04d0 ! Phaeocystis Real(kind=8) :: SiCmin = 0.04d0 Real(kind=8) :: k_Fe = 0.04d0 Real(kind=8) :: k_Fe_d = 0.12d0 Real(kind=8) :: k_Fe_c = 0.04 ! NEW + Real(kind=8) :: k_Fe_p = 0.09 ! Phaeocystis (to be tuned) Real(kind=8) :: k_si = 4.d0 Real(kind=8) :: P_cm = 3.0d0 ! [1/day] the rate of C-specific photosynthesis Real(kind=8) :: P_cm_d = 3.5d0 Real(kind=8) :: P_cm_c = 3.3d0 ! NEW - namelist /palimiter_function/ NMinSlope, SiMinSlope, NCmin, NCmin_d, NCmin_c, SiCmin, k_Fe, k_Fe_d, k_Fe_c, k_si, P_cm, P_cm_d, P_cm_c + Real(kind=8) :: P_cm_p = 3.4d0 ! NEW for Phaeocystis ( to be tuned) + namelist /palimiter_function/ NMinSlope, SiMinSlope, NCmin, NCmin_d, NCmin_c, NCmin_p, SiCmin, k_Fe, k_Fe_d, k_Fe_c, k_Fe_p, k_si, P_cm, P_cm_d, P_cm_c, P_cm_p + !!------------------------------------------------------------------------------ !! *** For light calculations *** Real(kind=8) :: k_w = 0.04d0 ! [1/m] Light attenuation coefficient @@ -231,40 +246,47 @@ module recom_config namelist /palight_calculations/ k_w, a_chl !!------------------------------------------------------------------------------ !! *** Photosynthesis *** - Real(kind=8) :: alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] + Real(kind=8) :: alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] Real(kind=8) :: alfa_d = 0.19d0 ! An initial slope of the P-I curve Real(kind=8) :: alfa_c = 0.10d0 ! NEW + Real(kind=8) :: alfa_p = 0.10d0 ! Phaeocystis (to be tuned) Real(kind=8) :: parFrac = 0.43d0 - namelist /paphotosynthesis/ alfa, alfa_d, alfa_c, parFrac + namelist /paphotosynthesis/ alfa, alfa_d, alfa_c, alfa_p, parFrac !!------------------------------------------------------------------------------ !! *** Assimilation *** Real(kind=8) :: V_cm_fact = 0.7d0 ! scaling factor for temperature dependent maximum of C-specific N-uptake Real(kind=8) :: V_cm_fact_d = 0.7d0 - Real(kind=8) :: V_cm_fact_c = 0.7d0 ! NEW + Real(kind=8) :: V_cm_fact_c = 0.7d0 ! NEW + Real(kind=8) :: V_cm_fact_p = 0.7d0 ! Phaeocystis Real(kind=8) :: NMaxSlope = 1000.d0 ! Max slope for limiting function Real(kind=8) :: SiMaxSlope = 1000.d0 Real(kind=8) :: NCmax = 0.2d0 ! [mmol N/mmol C] Maximum cell quota of nitrogen (N:C) Real(kind=8) :: NCmax_d = 0.2d0 Real(kind=8) :: NCmax_c = 0.15d0 ! NEW + Real(kind=8) :: NCmax_p = 0.1d0 ! Phaeocystis (to be tuned) Real(kind=8) :: SiCmax = 0.8d0 Real(kind=8) :: NCuptakeRatio = 0.2d0 ! [mmol N/mmol C] Maximum uptake ratio of N:C Real(kind=8) :: NCUptakeRatio_d = 0.2d0 Real(kind=8) :: NCUptakeRatio_c = 0.2d0 ! NEW + Real(kind=8) :: NCUptakeRatio_p = 0.2d0 ! Phaeocystis Real(kind=8) :: SiCUptakeRatio = 0.2d0 Real(kind=8) :: k_din = 0.55d0 ! [mmol N/m3] Half-saturation constant for nitrate uptake Real(kind=8) :: k_din_d = 1.0d0 Real(kind=8) :: k_din_c = 0.55d0 ! NEW + Real(kind=8) :: k_din_p = 0.55d0 ! Phaeocystis (to be tuned) Real(kind=8) :: Chl2N_max = 3.15d0 ! [mg CHL/mmol N] Maximum CHL a : N ratio = 0.3 gCHL gN^-1 Real(kind=8) :: Chl2N_max_d = 4.2d0 Real(kind=8) :: Chl2N_max_c = 3.5d0 ! NEW + Real(kind=8) :: Chl2N_max_p = 3.5d0 ! Phaeocystis (to be tuned (?)) Real(kind=8) :: res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant Real(kind=8) :: res_phy_d = 0.01d0 Real(kind=8) :: res_phy_c = 0.0075d0 ! NEW + Real(kind=8) :: res_phy_p = 0.008d0 ! Phaeocystis (to be tuned (?)) Real(kind=8) :: biosynth = 2.33d0 ! [mmol C/mmol N] Cost of biosynthesis Real(kind=8) :: biosynthSi = 0.d0 - namelist /paassimilation/ V_cm_fact, V_cm_fact_d, V_cm_fact_c, NMaxSlope, SiMaxSlope, NCmax, NCmax_d, NCmax_c, SiCmax, & - NCuptakeRatio, NCUptakeRatio_d, NCUptakeRatio_c, SiCUptakeRatio, k_din, k_din_d, k_din_c, & - Chl2N_max, Chl2N_max_d, Chl2N_max_c, res_phy, res_phy_d, res_phy_c, biosynth, biosynthSi + namelist /paassimilation/ V_cm_fact, V_cm_fact_d, V_cm_fact_c, V_cm_fact_p, NMaxSlope, SiMaxSlope, NCmax, NCmax_d, NCmax_c, NCmax_p, SiCmax, & + NCuptakeRatio, NCUptakeRatio_d, NCUptakeRatio_c, NCUptakeRatio_p, SiCUptakeRatio, k_din, k_din_d, k_din_c, k_din_p, & + Chl2N_max, Chl2N_max_d, Chl2N_max_c, Chl2N_max_p, res_phy, res_phy_d, res_phy_c, res_phy_p, biosynth, biosynthSi !!------------------------------------------------------------------------------ !! *** Iron chemistry *** Real(kind=8) :: totalligand = 1.d0 ! [mumol/m3] order 1. Total free ligand @@ -283,26 +305,30 @@ module recom_config Real(kind=8) :: sPhyNsq = 0.d0 Real(kind=8) :: pzCocco = 0.5d0 ! NEW (value is just a guess) Real(kind=8) :: sCoccoNsq = 0.d0 ! NEW + Real(kind=8) :: pzPhaeo = 1.0d0 ! Phaeocystis (to be tuned) + Real(kind=8) :: sPhaeoNsq = 0.d0 ! Phaeocystis Real(kind=8) :: pzMicZoo = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference Real(kind=8) :: sMicZooNsq = 0.d0 ! NEW 3Zoo real(kind=8) :: tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. - namelist /pazooplankton/ graz_max, epsilonr, res_het, Redfield, loss_het, pzDia, sDiaNsq, pzPhy, sPhyNsq, pzCocco, sCoccoNsq, pzMicZoo, sMicZooNsq, tiny_het + namelist /pazooplankton/ graz_max, epsilonr, res_het, Redfield, loss_het, pzDia, sDiaNsq, pzPhy, sPhyNsq, pzCocco, sCoccoNsq, pzPhaeo, sPhaeoNsq, pzMicZoo, sMicZooNsq, tiny_het !!------------------------------------------------------------------------------- -!! *** SecondZooplankton *** +!! *** SecondZooplankton (Macrozooplankton) *** Real(kind=8) :: graz_max2 = 0.1d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter Real(kind=8) :: epsilon2 = 0.0144d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss Real(kind=8) :: res_zoo2 = 0.0107d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) Real(kind=8) :: loss_zoo2 = 0.003d0 ! [1/day] Temperature dependent N degradation of extracellular organic N - Real(kind=8) :: fecal_rate_n = 0.13d0 + Real(kind=8) :: fecal_rate_n = 0.13d0 Real(kind=8) :: fecal_rate_c = 0.295d0 Real(kind=8) :: fecal_rate_n_mes = 0.25d0 ! NEW 3Zoo - Real(kind=8) :: fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo + Real(kind=8) :: fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo Real(kind=8) :: pzDia2 = 1.d0 ! Maximum diatom preference Real(kind=8) :: sDiaNsq2 = 0.d0 Real(kind=8) :: pzPhy2 = 0.5d0 ! Maximum diatom preference Real(kind=8) :: sPhyNsq2 = 0.d0 Real(kind=8) :: pzCocco2 = 0.2d0 ! NEW (value is just a guess) Real(kind=8) :: sCoccoNsq2 = 0.d0 ! NEW + Real(kind=8) :: pzPhaeo2 = 0.5d0 ! Phaeocystis (to be tuned) + Real(kind=8) :: sPhaeoNsq2 = 0.d0 ! Phaeocystis Real(kind=8) :: pzHet = 0.8d0 ! Maximum diatom preference Real(kind=8) :: sHetNsq = 0.d0 Real(kind=8) :: pzMicZoo2 = 0.8d0 ! NEW Zoo3 Maximum microzooplankton preference @@ -313,7 +339,7 @@ module recom_config Real(kind=8) :: t4_zoo2 = 274.15d0 ! Krill temp. function constant3 namelist /pasecondzooplankton/ graz_max2, epsilon2, res_zoo2, & loss_zoo2, fecal_rate_n, fecal_rate_c, fecal_rate_n_mes, fecal_rate_c_mes, & ! NEW 3Zoo - pzDia2, sDiaNsq2, pzPhy2, sPhyNsq2, pzCocco2, sCoccoNsq2, pzHet, sHetNsq, & + pzDia2, sDiaNsq2, pzPhy2, sPhyNsq2, pzCocco2, sCoccoNsq2, pzPhaeo2, sPhaeoNsq2, pzHet, sHetNsq, & pzMicZoo2, sMicZooNsq2, & t1_zoo2, t2_zoo2, t3_zoo2, t4_zoo2 !------------------------------------------------------------------------------- @@ -328,7 +354,9 @@ module recom_config Real(kind=8) :: sPhyNsq3 = 0.d0 ! NEW 3Zoo Real(kind=8) :: pzCocco3 = 0.d0 ! NEW 3Zoo Maximum coccolithophore preference ! ATTENTION: This value needs to be tuned; I start with zero preference! Real(kind=8) :: sCoccoNsq3 = 0.d0 ! NEW 3Zoo - namelist /pathirdzooplankton/ graz_max3, epsilon3, loss_miczoo, res_miczoo, pzDia3, sDiaNsq3, pzPhy3, sPhyNsq3, pzCocco3, sCoccoNsq3 + Real(kind=8) :: pzPhaeo3 = 1.0d0 ! Phaeocystis 3Zoo Maximum phaeocystis preference (to be tuned (?)) + Real(kind=8) :: sPhaeoNsq3 = 0.d0 ! Phaeocystis 3Zoo + namelist /pathirdzooplankton/ graz_max3, epsilon3, loss_miczoo, res_miczoo, pzDia3, sDiaNsq3, pzPhy3, sPhyNsq3, pzCocco3, sCoccoNsq3, pzPhaeo3, sPhaeoNsq3 !------------------------------------------------------------------------------- !! *** Detritus Grazing Params *** @@ -350,29 +378,34 @@ module recom_config !!------------------------------------------------------------------------------ !! *** DIN *** Real(kind=8) :: rho_N = 0.11d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) (Remineralization of DON) - namelist /padin_rho_N/ rho_N + Real(kind=8) :: rho_Nt = 0.67d0 ! [1/day] terrestrial N degradation of extracellular organic N (DONt) (Remineralization of terrestrial DON) ~ scale of 1.5 years ! R2OMIP + namelist /padin_rho_N/ rho_N, rho_Nt !!------------------------------------------------------------------------------ !! *** DIC *** Real(kind=8) :: rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradation of extracellular organic C (EOC) - namelist /padic_rho_C1/ rho_C1 + Real(kind=8) :: rho_C1t = 0.0018d0 ! [1/day] terrestrial C degradation of extracellular organic C (EOC) + namelist /padic_rho_C1/ rho_C1, rho_C1t !!------------------------------------------------------------------------------ !! *** Phytoplankton N *** Real(kind=8) :: lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds Real(kind=8) :: lossN_d = 0.05d0 - Real(kind=8) :: lossN_c = 0.05d0 - namelist /paphytoplankton_N/ lossN, lossN_d, lossN_c + Real(kind=8) :: lossN_c = 0.05d0 + Real(kind=8) :: lossN_p = 0.05d0 ! Phaeocystis + namelist /paphytoplankton_N/ lossN, lossN_d, lossN_c, lossN_p !!------------------------------------------------------------------------------ !! *** Phytoplankton C *** Real(kind=8) :: lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon Real(kind=8) :: lossC_d = 0.10d0 - Real(kind=8) :: lossC_c = 0.10d0 - namelist /paphytoplankton_C/ lossC, lossC_d, lossC_c + Real(kind=8) :: lossC_c = 0.10d0 + Real(kind=8) :: lossC_p = 0.10d0 ! Phaeocystis + namelist /paphytoplankton_C/ lossC, lossC_d, lossC_c, lossC_p !!------------------------------------------------------------------------------ !! *** Phytoplankton ChlA *** Real(8) :: deg_Chl = 0.25d0 ! [1/day] Real(kind=8) :: deg_Chl_d = 0.25d0 Real(kind=8) :: deg_Chl_c = 0.20d0 ! (value is just a guess) - namelist /paphytoplankton_ChlA/ deg_Chl, deg_Chl_d, deg_Chl_c + Real(kind=8) :: deg_Chl_p = 0.25d0 ! Phaeocystis + namelist /paphytoplankton_ChlA/ deg_Chl, deg_Chl_d, deg_Chl_c, deg_Chl_p !!------------------------------------------------------------------------------ !! *** Detritus N *** Real(kind=8) :: gfin = 0.3d0 ! 3Zoo [] Grazing efficiency (fraction of grazing flux into zooplankton pool) @@ -405,32 +438,36 @@ module recom_config Real(kind=8) :: Cunits = 976.5625 ! Conversion factor between [mol/m3] (model) and [umol/kg] (function): (1000 * 1000) / 1024 Real(kind=8) :: a_co2_phy = 1.162e+00 ! [unitless] - Real(kind=8) :: a_co2_dia = 1.040e+00 ! [unitless] - Real(kind=8) :: a_co2_cocco = 1.109e+00 ! [unitless] - Real(kind=8) :: a_co2_calc = 1.102e+00 ! [unitless] - Real(kind=8) :: b_co2_phy = 4.888e+01 ! [mol/kg] + Real(kind=8) :: a_co2_dia = 1.040e+00 ! [unitless] + Real(kind=8) :: a_co2_cocco = 1.109e+00 ! [unitless] + Real(kind=8) :: a_co2_phaeo = 1.162e+00 ! [unitless] + Real(kind=8) :: a_co2_calc = 1.102e+00 ! [unitless] + Real(kind=8) :: b_co2_phy = 4.888e+01 ! [mol/kg] Real(kind=8) :: b_co2_dia = 2.890e+01 ! [mol/kg] Real(kind=8) :: b_co2_cocco = 3.767e+01 ! [mol/kg] + Real(kind=8) :: b_co2_phaeo = 4.888e+01 ! [mol/kg] Real(kind=8) :: b_co2_calc = 4.238e+01 ! [mol/kg] Real(kind=8) :: c_co2_phy = 2.255e-01 ! [kg/mol] - Real(kind=8) :: c_co2_dia = 8.778e-01 ! [kg/mol] - Real(kind=8) :: c_co2_cocco = 3.912e-01 ! [kg/mol] - Real(kind=8) :: c_co2_calc = 7.079e-01 ! [kg/mol] - Real(kind=8) :: d_co2_phy = 1.023e+07 ! [kg/mol] - Real(kind=8) :: d_co2_dia = 2.640e+06 ! [kg/mol] - Real(kind=8) :: d_co2_cocco = 9.450e+06 ! [kg/mol] - Real(kind=8) :: d_co2_calc = 1.343e+07 ! [kg/mol] - namelist /paco2lim/ Cunits, a_co2_phy, a_co2_dia, a_co2_cocco, a_co2_calc, & - b_co2_phy, b_co2_dia, b_co2_cocco, b_co2_calc, & - c_co2_phy, c_co2_dia, c_co2_cocco, c_co2_calc, & - d_co2_phy, d_co2_dia, d_co2_cocco, d_co2_calc + Real(kind=8) :: c_co2_dia = 8.778e-01 ! [kg/mol] + Real(kind=8) :: c_co2_cocco = 3.912e-01 ! [kg/mol] + Real(kind=8) :: c_co2_phaeo = 2.255e-01 ! [kg/mol] + Real(kind=8) :: c_co2_calc = 7.079e-01 ! [kg/mol] + Real(kind=8) :: d_co2_phy = 1.023e+07 ! [kg/mol] + Real(kind=8) :: d_co2_dia = 2.640e+06 ! [kg/mol] + Real(kind=8) :: d_co2_cocco = 9.450e+06 ! [kg/mol] + Real(kind=8) :: d_co2_phaeo = 1.023e+07 ! [kg/mol] + Real(kind=8) :: d_co2_calc = 1.343e+07 ! [kg/mol] + namelist /paco2lim/ Cunits, a_co2_phy, a_co2_dia, a_co2_cocco, a_co2_phaeo, a_co2_calc, & + b_co2_phy, b_co2_dia, b_co2_cocco, b_co2_phaeo, b_co2_calc, & + c_co2_phy, c_co2_dia, c_co2_cocco, c_co2_phaeo, c_co2_calc, & + d_co2_phy, d_co2_dia, d_co2_cocco, d_co2_phaeo, d_co2_calc !!------------------------------------------------------------------------------ !! *** Iron *** Real(kind=8) :: Fe2N = 0.033d0 ! Fe2C * 6.625 (Fe2C = 0.005d0) Real(kind=8) :: Fe2N_benthos = 0.15d0 ! default was 0.14 Fe2C_benthos (=0.02125=0.68d0/32.d0) * 6.625 - will have to be tuned. [umol/m2/day] Real(kind=8) :: kScavFe = 0.07d0 Real(kind=8) :: dust_sol = 0.02d0 !Dissolution of Dust for bioavaliable - Real(kind=8) :: RiverFeConc = 100d0 ! mean DFe concentration in rivers + Real(kind=8) :: RiverFeConc = 100d0 ! mean DFe concentration in rivers namelist /pairon/ Fe2N, Fe2N_benthos, kScavFe, dust_sol, RiverFeConc !!------------------------------------------------------------------------------ !! *** Calcification *** @@ -477,6 +514,728 @@ module recom_config namelist /paballasting/ rho_POC, rho_PON, rho_CaCO3, rho_opal, rho_ref_part, & rho_ref_water, visc_ref_water, w_ref1, w_ref2, depth_scaling1, & depth_scaling2, max_sinking_velocity + +contains + + ! --------------------------------------------------------------------------- + ! SUBROUTINE: initialize_tracer_indices + ! --------------------------------------------------------------------------- + ! Purpose: Set up tracer indices based on model configuration + ! --------------------------------------------------------------------------- + subroutine initialize_tracer_indices() + implicit none + + if (enable_3zoo2det .and. enable_coccos) then + ! ======================================================================= + ! CASE: 4 phytoplankton + 3 zooplankton + 2 detritus + ! ======================================================================= + ! Phytoplankton: small phyto, diatoms, coccolithophores, phaeocystis + ! Zooplankton: mesozoo, macrozoo, microzoo + ! Detritus: det1, det2 + + icocn = 29 + icocc = 30 + icchl = 31 + iphan = 32 + iphac = 33 + iphachl = 34 + imiczoon = 35 + imiczooc = 36 + + ! Terrestrial DOC input (when useRivers is enabled) + if (useRivers) then + idoct = 37 + end if + +! allocate(recom_cocco_tracer_id(3)) + recom_cocco_tracer_id = (/1029, 1030, 1031/) + +! allocate(recom_phaeo_tracer_id(3)) + recom_phaeo_tracer_id = (/1032, 1033, 1034/) + +! allocate(recom_det2_tracer_id(4)) + recom_det2_tracer_id = (/1025, 1026, 1027, 1028/) + + else if (enable_coccos .and. .not. enable_3zoo2det) then + ! ======================================================================= + ! CASE: 4 phytoplankton + 1 zooplankton + 1 detritus + ! ======================================================================= + ! Phytoplankton: small phyto, diatoms, coccolithophores, phaeocystis + ! Zooplankton: mesozoo only + ! Detritus: det1 only + + icocn = 23 + icocc = 24 + icchl = 25 + iphan = 26 + iphac = 27 + iphachl = 28 + + ! Terrestrial DOC input (when useRivers is enabled) + if (useRivers) then + idoct = 29 + end if + +! allocate(recom_cocco_tracer_id(3)) + recom_cocco_tracer_id = (/1023, 1024, 1025/) + +! allocate(recom_phaeo_tracer_id(3)) + recom_phaeo_tracer_id = (/1026, 1027, 1028/) + + else if (enable_3zoo2det .and. .not. enable_coccos) then + ! ======================================================================= + ! CASE: 2 phytoplankton + 3 zooplankton + 2 detritus + ! ======================================================================= + ! Phytoplankton: small phyto, diatoms only + ! Zooplankton: mesozoo, macrozoo, microzoo + ! Detritus: det1, det2 + + imiczoon = 29 + imiczooc = 30 + + ! Terrestrial DOC input (when useRivers is enabled) + if (useRivers) then + idoct = 31 + end if + +! allocate(recom_det2_tracer_id(4)) + recom_det2_tracer_id = (/1025, 1026, 1027, 1028/) + else + ! ======================================================================= + ! CASE: 2 phytoplankton + 1 zooplankton + 1 detritus (BASE CONFIGURATION) + ! ======================================================================= + ! Phytoplankton: small phyto, diatoms only + ! Zooplankton: mesozoo only + ! Detritus: det1 only + ! (All indices already set to default values) + + ! Terrestrial DOC input (when useRivers is enabled) + if (useRivers) then + idoct = 23 + end if + endif + end subroutine initialize_tracer_indices + +! ============================================================================== +! SUBROUTINE: validate_recom_tracers +! ============================================================================== +! Purpose: Validate consistency between namelist tracer configuration and +! biogeochemical model setup (enable_3zoo2det, enable_coccos) +! ============================================================================== +subroutine validate_recom_tracers(num_tracers, mype) + + use g_forcing_param, only: use_age_tracer !---age-code + + implicit none + + ! Arguments + integer, intent(in) :: num_tracers ! Total number of tracers from namelist + integer, intent(in) :: mype ! MPI rank + + ! Local variables + integer :: expected_bgc_num + integer :: actual_bgc_num + integer :: expected_total_tracers + integer :: num_physical_tracers + integer :: doc_tracers + logical :: config_error + character(len=200) :: error_msg + + ! For tracer ID validation + integer :: i, tracer_id + integer, dimension(:), allocatable :: expected_tracer_ids + logical, dimension(:), allocatable :: tracer_found + integer :: num_expected_tracers + logical :: id_error + + ! Physical tracers (temperature, salinity, etc.) - typically first 2 + num_physical_tracers = 2 + + ! DOC tracers count + if (useRivers) then + doc_tracers = 1 + else + doc_tracers = 0 + end if + + ! Calculate actual BGC tracer count from namelist + actual_bgc_num = num_tracers - num_physical_tracers + + ! =========================================================================== + ! Determine expected BGC tracer count based on configuration + ! =========================================================================== + config_error = .false. + + if (enable_3zoo2det .and. enable_coccos) then + ! --------------------------------------------------------------------------- + ! Configuration 4: Full model (4 phyto + 3 zoo + 2 detritus) + ! --------------------------------------------------------------------------- + ! Base: 22 tracers (1001-1022) + ! Additional 3zoo2det: 4 tracers for det2 (1025-1028) + ! Additional coccos: 6 tracers for coccos (1029-1031) + ! Additional phaeocystis: 3 tracers (1032-1034) + ! Additional microzoo: 2 tracers (1035-1036) + ! Total: 22 + 4 + 6 + 3 + 2 = 36 (actually 22 + 14 = 36) + ! Plus DOC: +1 if useRivers + expected_bgc_num = 36 + doc_tracers + + else if (enable_coccos .and. .not. enable_3zoo2det) then + ! --------------------------------------------------------------------------- + ! Configuration 3: Coccos only (4 phyto + 1 zoo + 1 detritus) + ! --------------------------------------------------------------------------- + ! Base: 22 tracers (1001-1022) + ! Additional coccos: 3 tracers (1023-1025) + ! Additional phaeocystis: 3 tracers (1026-1028) + ! Total: 22 + 6 = 28 + ! Plus DOC: +1 if useRivers + expected_bgc_num = 28 + doc_tracers + + else if (enable_3zoo2det .and. .not. enable_coccos) then + ! --------------------------------------------------------------------------- + ! Configuration 2: 3Zoo2Det only (2 phyto + 3 zoo + 2 detritus) + ! --------------------------------------------------------------------------- + ! Base: 22 tracers (1001-1022) + ! Additional zoo2: 2 tracers (1023-1024) + ! Additional det2: 4 tracers (1025-1028) + ! Additional microzoo: 2 tracers (1029-1030) + ! Total: 22 + 8 = 30 + ! Plus DOC: +1 if useRivers + expected_bgc_num = 30 + doc_tracers + + else + ! --------------------------------------------------------------------------- + ! Configuration 1: Base model (2 phyto + 1 zoo + 1 detritus) + ! --------------------------------------------------------------------------- + ! Base: 22 tracers (1001-1022) + ! Plus DOC: +1 if useRivers + expected_bgc_num = 22 + doc_tracers + + end if + + if (use_age_tracer) then + expected_bgc_num = expected_bgc_num + 1 + end if + + expected_total_tracers = num_physical_tracers + expected_bgc_num + + ! =========================================================================== + ! Build expected tracer ID list for current configuration + ! =========================================================================== + + ! Determine total expected tracers + num_expected_tracers = expected_total_tracers + allocate(expected_tracer_ids(num_expected_tracers)) + allocate(tracer_found(num_expected_tracers)) + tracer_found = .false. + + ! Physical tracers (always present) + expected_tracer_ids(1) = 1 ! Temperature + expected_tracer_ids(2) = 2 ! Salinity + + ! Base BGC tracers (always present for all configurations) + do i = 1, 22 + expected_tracer_ids(num_physical_tracers + i) = 1000 + i + end do + + ! Configuration-specific tracers + if (enable_3zoo2det .and. enable_coccos) then + ! Full model: 1001-1022 (base) + 1023-1024 (zoo2) + 1025-1028 (det2) + 1029-1036 (coccos+phaeo+zoo3) + expected_tracer_ids(25) = 1023 ! Zoo2N + expected_tracer_ids(26) = 1024 ! Zoo2C + expected_tracer_ids(27) = 1025 ! DetZ2N + expected_tracer_ids(28) = 1026 ! DetZ2C + expected_tracer_ids(29) = 1027 ! DetZ2Si + expected_tracer_ids(30) = 1028 ! DetZ2Calc + expected_tracer_ids(31) = 1029 ! CoccoN + expected_tracer_ids(32) = 1030 ! CoccoC + expected_tracer_ids(33) = 1031 ! CoccoChl + expected_tracer_ids(34) = 1032 ! PhaeoN + expected_tracer_ids(35) = 1033 ! PhaeoC + expected_tracer_ids(36) = 1034 ! PhaeoChl + expected_tracer_ids(37) = 1035 ! Zoo3N + expected_tracer_ids(38) = 1036 ! Zoo3C + if (useRivers) then + expected_tracer_ids(39) = 1037 ! DOCt (terrestrial DOC) + end if + + else if (enable_coccos .and. .not. enable_3zoo2det) then + ! Coccos only: 1001-1022 (base) + 1023-1028 (coccos+phaeo) + expected_tracer_ids(25) = 1023 ! CoccoN + expected_tracer_ids(26) = 1024 ! CoccoC + expected_tracer_ids(27) = 1025 ! CoccoChl + expected_tracer_ids(28) = 1026 ! PhaeoN + expected_tracer_ids(29) = 1027 ! PhaeoC + expected_tracer_ids(30) = 1028 ! PhaeoChl + if (useRivers) then + expected_tracer_ids(31) = 1029 ! DOCt (terrestrial DOC) + end if + + else if (enable_3zoo2det .and. .not. enable_coccos) then + ! 3Zoo2Det only: 1001-1022 (base) + 1023-1030 (zoo2+det2+zoo3) + expected_tracer_ids(25) = 1023 ! Zoo2N + expected_tracer_ids(26) = 1024 ! Zoo2C + expected_tracer_ids(27) = 1025 ! DetZ2N + expected_tracer_ids(28) = 1026 ! DetZ2C + expected_tracer_ids(29) = 1027 ! DetZ2Si + expected_tracer_ids(30) = 1028 ! DetZ2Calc + expected_tracer_ids(31) = 1029 ! Zoo3N + expected_tracer_ids(32) = 1030 ! Zoo3C + if (useRivers) then + expected_tracer_ids(33) = 1031 ! DOCt (terrestrial DOC) + end if + + else + ! Base configuration: only tracers 1, 2, 1001-1022 + if (useRivers) then + expected_tracer_ids(25) = 1023 ! DOCt (terrestrial DOC) + end if + end if + + if (use_age_tracer) then + expected_tracer_ids(num_expected_tracers) = 100 + end if + + ! else: base configuration only needs tracers 1, 2, 1001-1022 + + ! =========================================================================== + ! Perform validation checks + ! =========================================================================== + + if (mype == 0) then + write(*,*) '' + write(*,*) '==========================================================================' + write(*,*) 'REcoM TRACER CONFIGURATION VALIDATION' + write(*,*) '==========================================================================' + write(*,*) 'Model configuration:' + write(*,*) ' enable_3zoo2det = ', enable_3zoo2det + write(*,*) ' enable_coccos = ', enable_coccos + write(*,*) ' useRivers = ', useRivers + write(*,*) '' + write(*,*) 'Tracer counts:' + write(*,*) ' Physical tracers (T, S, ...) = ', num_physical_tracers + write(*,*) ' DOC tracers (terrestrial input) = ', doc_tracers + write(*,*) ' Expected BGC tracers = ', expected_bgc_num + write(*,*) ' Expected TOTAL tracers = ', expected_total_tracers + write(*,*) ' Actual tracers from namelist = ', num_tracers + write(*,*) ' Actual BGC tracers from namelist = ', actual_bgc_num + write(*,*) '' + end if + + ! Check for inconsistencies + if (actual_bgc_num /= expected_bgc_num) then + config_error = .true. + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'ERROR: TRACER COUNT MISMATCH!' + write(*,*) '==========================================================================' + write(*,*) 'The number of BGC tracers in the namelist does not match' + write(*,*) 'the expected count for the current configuration.' + write(*,*) '' + write(*,*) ' Expected BGC tracers: ', expected_bgc_num + write(*,*) ' Actual BGC tracers: ', actual_bgc_num + write(*,*) ' Difference: ', actual_bgc_num - expected_bgc_num + write(*,*) '' + write(*,*) 'Required tracer IDs for current configuration:' + write(*,*) ' Base tracers (always): 1001-1022 (22 tracers)' + + if (enable_3zoo2det .and. .not. enable_coccos) then + write(*,*) ' 3Zoo2Det extension: 1023-1030 (8 tracers)' + write(*,*) ' - Zoo2N, Zoo2C: 1023-1024' + write(*,*) ' - DetZ2 pool: 1025-1028' + write(*,*) ' - MicZooN, MicZooC: 1029-1030' + if (useRivers) then + write(*,*) ' Terrestrial DOC: 1031 (1 tracer)' + end if + else if (enable_coccos .and. .not. enable_3zoo2det) then + write(*,*) ' Coccos extension: 1023-1028 (6 tracers)' + write(*,*) ' - CoccoN, C, Chl: 1023-1025' + write(*,*) ' - PhaeoN, C, Chl: 1026-1028' + if (useRivers) then + write(*,*) ' Terrestrial DOC: 1029 (1 tracer)' + end if + else if (enable_3zoo2det .and. enable_coccos) then + write(*,*) ' - Zoo2N, Zoo2C: 1023-1024' + write(*,*) ' 3Zoo2Det extension: 1025-1028 (4 tracers for det2)' + write(*,*) ' Coccos extension: 1029-1034 (6 tracers)' + write(*,*) ' - CoccoN, C, Chl: 1029-1031' + write(*,*) ' - PhaeoN, C, Chl: 1032-1034' + write(*,*) ' MicroZoo extension: 1035-1036 (2 tracers)' + if (useRivers) then + write(*,*) ' Terrestrial DOC: 1037 (1 tracer)' + end if + else + if (useRivers) then + write(*,*) ' Terrestrial DOC: 1023 (1 tracer)' + end if + end if + + write(*,*) '' + write(*,*) 'ACTION REQUIRED:' + write(*,*) ' 1. Check your namelist.config tracer_list section' + write(*,*) ' 2. Ensure enable_3zoo2det, enable_coccos, and useRivers match your setup' + write(*,*) ' 3. Add/remove tracers to match the expected configuration' + write(*,*) '==========================================================================' + write(*,*) '' + end if + else + ! Validation passed + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'VALIDATION PASSED: Tracer configuration is consistent!' + write(*,*) '==========================================================================' + write(*,*) '' + end if + end if + + ! =========================================================================== + ! Additional sanity check: verify bgc_num variable matches + ! =========================================================================== + if (bgc_num /= expected_bgc_num) then + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'WARNING: bgc_num variable inconsistency!' + write(*,*) '==========================================================================' + write(*,*) 'The bgc_num parameter does not match the expected value.' + write(*,*) ' Current bgc_num value: ', bgc_num + write(*,*) ' Expected value: ', expected_bgc_num + write(*,*) '' + write(*,*) 'This may indicate that bgc_num was not updated after changing' + write(*,*) 'enable_3zoo2det, enable_coccos flags, or useRivers flags.' + write(*,*) '==========================================================================' + write(*,*) '' + end if + config_error = .true. + end if + + ! =========================================================================== + ! Validate tracer IDs: Check for correct IDs and detect clashes + ! =========================================================================== + id_error = .false. + + ! This check requires access to the actual tracer IDs from the namelist + ! We'll validate against the expected list + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'VALIDATING TRACER IDs' + write(*,*) '==========================================================================' + write(*,*) 'Expected tracer ID sequence:' + write(*,*) '' + + ! Display expected IDs in a readable format + write(*,*) 'Physical tracers:' + write(*,*) ' ', expected_tracer_ids(1:num_physical_tracers) + write(*,*) '' + write(*,*) 'Base BGC tracers (1001-1022):' + write(*,*) ' ', expected_tracer_ids(3:24) + write(*,*) '' + + if (expected_bgc_num > 22) then + write(*,*) 'Extended configuration tracers:' + write(*,*) ' ', expected_tracer_ids(25:num_expected_tracers) + write(*,*) '' + end if + + write(*,*) 'CRITICAL: The tracer IDs in your namelist MUST match this sequence' + write(*,*) ' exactly, in the same order!' + write(*,*) '' + write(*,*) 'Common errors to avoid:' + write(*,*) ' - Using wrong tracer ID numbers (e.g., 1023 instead of 1025)' + write(*,*) ' - Tracer ID clashes between configurations' + write(*,*) ' - Incorrect order of tracer IDs in namelist' + write(*,*) ' - Missing or duplicate tracer IDs' + write(*,*) ' - Forgetting to add DOCt tracer when useRivers is enabled' + write(*,*) '' + + ! Configuration-specific warnings + if (enable_3zoo2det .and. enable_coccos) then + write(*,*) 'IMPORTANT for FULL MODEL (3zoo2det + coccos):' + ! write(*,*) ' - Tracers 1023-1024 are NOT used (reserved for other configs)' + write(*,*) ' - Zoo2 uses: 1023-1024' + write(*,*) ' - Det2 pool uses: 1025-1028' + write(*,*) ' - Coccos uses: 1029-1031' + write(*,*) ' - Phaeocystis uses: 1032-1034' + write(*,*) ' - Microzooplankton: 1035-1036' + if (useRivers) then + write(*,*) ' - Terrestrial DOC: 1037' + end if + write(*,*) '' + else if (enable_coccos .and. .not. enable_3zoo2det) then + write(*,*) 'IMPORTANT for COCCOS-ONLY configuration:' + write(*,*) ' - Coccos uses: 1023-1025 (NOT 1029-1031)' + write(*,*) ' - Phaeocystis uses: 1026-1028 (NOT 1032-1034)' + if (useRivers) then + write(*,*) ' - Terrestrial DOC: 1029' + write(*,*) ' - Tracers 1030+ are NOT used in this configuration' + else + write(*,*) ' - Tracers 1029+ are NOT used in this configuration' + end if + write(*,*) '' + else if (enable_3zoo2det .and. .not. enable_coccos) then + write(*,*) 'IMPORTANT for 3ZOO2DET-ONLY configuration:' + write(*,*) ' - Zoo2 uses: 1023-1024' + write(*,*) ' - Det2 pool uses: 1025-1028' + write(*,*) ' - Microzoo uses: 1029-1030 (NOT 1035-1036)' + if (useRivers) then + write(*,*) ' - Terrestrial DOC: 1031' + write(*,*) ' - Tracers 1032+ are NOT used in this configuration' + else + write(*,*) ' - Tracers 1031+ are NOT used in this configuration' + end if + write(*,*) '' + else + write(*,*) 'IMPORTANT for BASE configuration:' + write(*,*) ' - Only tracers 1-2, 1001-1022 should be present' + if (useRivers) then + write(*,*) ' - Plus terrestrial DOC: 1023' + write(*,*) ' - Tracers 1024+ are NOT used in base configuration' + else + write(*,*) ' - Tracers 1023+ are NOT used in base configuration' + endif + end if + write(*,*) '' + write(*,*) '==========================================================================' + write(*,*) '' + end if + + ! =========================================================================== + ! Check for tracer ID clashes based on configuration + ! =========================================================================== + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'CHECKING FOR TRACER ID CONFLICTS' + write(*,*) '==========================================================================' + + ! Warn about potential clashes between configurations + if (enable_3zoo2det .and. enable_coccos) then + write(*,*) 'Full model configuration active.' + ! write(*,*) 'Ensure you are NOT using tracer IDs 1023-1024 in your namelist!' + ! write(*,*) 'These are reserved for configurations WITHOUT full model.' + else if (enable_coccos) then + write(*,*) 'Coccos-only configuration active.' + write(*,*) 'Coccos MUST use IDs 1023-1025 (NOT 1029-1031).' + write(*,*) 'Phaeocystis MUST use IDs 1026-1028 (NOT 1032-1034).' + else if (enable_3zoo2det) then + write(*,*) '3Zoo2Det-only configuration active.' + write(*,*) 'Microzoo MUST use IDs 1029-1030 (NOT 1035-1036).' + end if + + if (useRivers) then + write(*,*) '' + write(*,*) 'Rivers enabled (useRivers = .true.)' + write(*,*) 'Terrestrial DOC tracer is REQUIRED as the last BGC tracer.' + end if + + write(*,*) '' + ! write(*,*) 'No automated clash detection available without tracer array access.' + write(*,*) 'Please manually verify your namelist tracer_list against the' + write(*,*) 'expected sequence shown above.' + write(*,*) '==========================================================================' + write(*,*) '' + end if + + ! =========================================================================== + ! Stop execution if configuration error detected + ! =========================================================================== + if (config_error) then + if (mype == 0) then + write(*,*) '' + write(*,*) '******************************************************************' + write(*,*) '*** FATAL ERROR: MODEL CONFIGURATION INCONSISTENCY DETECTED ***' + write(*,*) '*** MODEL EXECUTION STOPPED ***' + write(*,*) '******************************************************************' + write(*,*) '' + end if + deallocate(expected_tracer_ids, tracer_found) + call par_ex(0) ! Stop execution (use appropriate stop routine for your model) + stop + end if + + ! Clean up + deallocate(expected_tracer_ids, tracer_found) + +end subroutine validate_recom_tracers + +! ============================================================================== +! SUBROUTINE: validate_tracer_id_sequence +! ============================================================================== +! Purpose: Validate that actual tracer IDs from namelist match expected sequence +! Call this after reading the tracer namelist +! ============================================================================== +subroutine validate_tracer_id_sequence(tracer_ids, num_tracers, mype) + + use g_forcing_param, only: use_age_tracer !---age-code + + implicit none + + ! Arguments + integer, dimension(:), intent(in) :: tracer_ids ! Actual IDs from namelist + integer, intent(in) :: num_tracers ! Number of tracers + integer, intent(in) :: mype ! MPI rank + + ! Local variables + integer :: i, j + integer, dimension(:), allocatable :: expected_ids + integer :: num_expected + logical :: error_found + logical :: duplicate_found + integer :: num_physical_tracers + integer :: doc_tracers + + error_found = .false. + duplicate_found = .false. + num_physical_tracers = 2 + + ! DOC tracers count + if (useRivers) then + doc_tracers = 1 + else + doc_tracers = 0 + end if + + ! Allocate expected IDs array + allocate(expected_ids(num_tracers)) + + ! Build expected ID sequence + expected_ids(1) = 1 + expected_ids(2) = 2 + + do i = 1, 22 + expected_ids(num_physical_tracers + i) = 1000 + i + end do + + if (enable_3zoo2det .and. enable_coccos) then + ! Full model configuration + expected_ids(25:30) = (/1023, 1024, 1025, 1026, 1027, 1028/) + expected_ids(31:36) = (/1029, 1030, 1031, 1032, 1033, 1034/) + expected_ids(37:38) = (/1035, 1036/) + if (useRivers) then + expected_ids(39) = 1037 ! DOCt + end if + + else if (enable_coccos .and. .not. enable_3zoo2det) then + expected_ids(25:30) = (/1023, 1024, 1025, 1026, 1027, 1028/) + if (useRivers) then + expected_ids(31) = 1029 ! DOCt + end if + + else if (enable_3zoo2det .and. .not. enable_coccos) then + expected_ids(25:32) = (/1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030/) + if (useRivers) then + expected_ids(33) = 1031 ! DOCt + end if + + else + ! Base configuration + if (useRivers) then + expected_ids(25) = 1023 ! DOCt + end if + end if + + if (use_age_tracer) then + expected_ids(num_tracers) = 100 + end if + + ! =========================================================================== + ! Check 1: Compare actual vs expected tracer IDs + ! =========================================================================== + if (mype == 0) then + write(*,*) '' + write(*,*) '==========================================================================' + write(*,*) 'VALIDATING TRACER ID SEQUENCE FROM NAMELIST' + write(*,*) '==========================================================================' + end if + + do i = 1, num_tracers + if (tracer_ids(i) /= expected_ids(i)) then + error_found = .true. + if (mype == 0) then + write(*,*) 'ERROR at position ', i, ':' + write(*,*) ' Expected tracer ID: ', expected_ids(i) + write(*,*) ' Found tracer ID: ', tracer_ids(i) + write(*,*) '' + end if + end if + end do + + ! =========================================================================== + ! Check 2: Detect duplicate tracer IDs + ! =========================================================================== + do i = 1, num_tracers - 1 + do j = i + 1, num_tracers + if (tracer_ids(i) == tracer_ids(j)) then + duplicate_found = .true. + if (mype == 0) then + write(*,*) 'ERROR: Duplicate tracer ID detected!' + write(*,*) ' Tracer ID ', tracer_ids(i), ' appears at positions ', i, ' and ', j + write(*,*) '' + end if + end if + end do + end do + + ! =========================================================================== + ! Check 3: Detect forbidden tracer IDs for current configuration + ! =========================================================================== + !if (enable_3zoo2det .and. enable_coccos) then + ! Check for forbidden IDs 1023-1024 in full model + !do i = 1, num_tracers + !if (tracer_ids(i) == 1023 .or. tracer_ids(i) == 1024) then + !error_found = .true. + !if (mype == 0) then + !write(*,*) 'ERROR: Forbidden tracer ID in full model configuration!' + !write(*,*) ' Tracer ID ', tracer_ids(i), ' at position ', i + !write(*,*) ' IDs 1023-1024 are NOT used when both flags are enabled' + !write(*,*) '' + !end if + !end if + !end do + !end if + + ! =========================================================================== + ! Report results + ! =========================================================================== + if (error_found .or. duplicate_found) then + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'TRACER ID VALIDATION FAILED!' + write(*,*) '==========================================================================' + write(*,*) '' + write(*,*) 'Expected tracer ID sequence for current configuration:' + write(*,*) expected_ids + write(*,*) '' + write(*,*) 'Actual tracer ID sequence from namelist:' + write(*,*) tracer_ids + write(*,*) '' + write(*,*) 'ACTION REQUIRED:' + write(*,*) ' Correct the tracer IDs in your namelist.config file' + write(*,*) ' Ensure the sequence matches exactly as expected' + write(*,*) '==========================================================================' + write(*,*) '' + write(*,*) '******************************************************************' + write(*,*) '*** FATAL ERROR: INVALID TRACER ID SEQUENCE ***' + write(*,*) '*** MODEL EXECUTION STOPPED ***' + write(*,*) '******************************************************************' + write(*,*) '' + end if + deallocate(expected_ids) + call par_ex(0) + stop + else + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'TRACER ID VALIDATION PASSED!' + write(*,*) 'All tracer IDs match expected sequence - no clashes detected.' + write(*,*) '==========================================================================' + write(*,*) '' + end if + end if + + deallocate(expected_ids) + +end subroutine validate_tracer_id_sequence + + + end module recom_config ! !=============================================================================== @@ -489,16 +1248,22 @@ Module REcoM_declarations Real(kind=8) :: tiny_N ! Min PhyN Real(kind=8) :: tiny_N_d ! Min DiaN Real(kind=8) :: tiny_N_c ! Min CocN ! NEW + Real(kind=8) :: tiny_N_p ! Min PhaN ! Phaeocystis Real(kind=8) :: tiny_C ! Min PhyC Real(kind=8) :: tiny_C_d ! Min DiaC Real(kind=8) :: tiny_C_c ! Min CocC ! NEW + Real(kind=8) :: tiny_C_p ! Min PhaC ! Phaeocystis Real(kind=8) :: tiny_Si ! Min DiaSi !!------------------------------------------------------------------------------ !! *** Temperature dependence of rates *** Real(kind=8) :: rTref ! [1/K] Reciproque value of reference temp for Arrhenius function Real(kind=8) :: rTloc ! [1/K] Reciproque of local ocean temp - Real(kind=8) :: arrFunc ! [] Temp dependence of rates + Real(kind=8) :: arrFunc ! [] Temp dependence of rates (also for Phaeocystis) Real(kind=8) :: CoccoTFunc ! [] Temp dependence of coccolithophores + Real(kind=8) :: Temp_diatoms ! [] Temp dependence of diatoms + Real(kind=8) :: Temp_phyto ! [] Temp dependence of small phyto + Real(kind=8) :: Temp_cocco ! [] Temp dependence of coccolithophores + Real(kind=8) :: Temp_phaeo ! [] Temp dependence of phaeocystis Real(kind=8) :: arrFuncZoo2 ! [] Temperature function for krill Real(kind=8) :: q10_mic ! 3Zoo Real(kind=8) :: q10_mic_res ! 3Zoo @@ -515,13 +1280,15 @@ Module REcoM_declarations Real(kind=8) :: CoccoCO2 Real(kind=8) :: DiaCO2 Real(kind=8) :: PhyCO2 + Real(kind=8) :: PhaeoCO2 + !!------------------------------------------------------------------------------ !! *** Quotas *** - Real(kind=8) :: quota, quota_dia, quota_cocco ! [mmol N/mmol C] Quota between phytoplankton N and C (NEW changed term) - Real(kind=8) :: recipQuota, recipQuota_dia, recipQuota_cocco ! [mmol C/mmol N] Reciproque of 'quota' (NEW changed term) - Real(kind=8) :: Chl2C, Chl2C_dia, Chl2C_cocco ! [mg ChlA/mmol C] Quota between phytoplankton ChlA and C (NEW changed term) - Real(kind=8) :: Chl2C_plast, Chl2C_plast_dia, CHL2C_plast_cocco ! [mg ChlA/mmol C] needed for photodamage (NEW changed term) - Real(kind=8) :: Chl2N, Chl2N_dia, Chl2N_cocco ! [mg ChlA/mmol N] Quota between phytoplankton ChlA and N (NEW changed term) + Real(kind=8) :: quota, quota_dia, quota_cocco, quota_phaeo ! [mmol N/mmol C] Quota between phytoplankton N and C (NEW changed term) + Real(kind=8) :: recipQuota, recipQuota_dia, recipQuota_cocco, recipQuota_phaeo ! [mmol C/mmol N] Reciproque of 'quota' (NEW changed term) + Real(kind=8) :: Chl2C, Chl2C_dia, Chl2C_cocco, Chl2C_phaeo ! [mg ChlA/mmol C] Quota between phytoplankton ChlA and C (NEW changed term) + Real(kind=8) :: Chl2C_plast, Chl2C_plast_dia, CHL2C_plast_cocco, CHL2C_plast_phaeo ! [mg ChlA/mmol C] needed for photodamage (NEW changed term) + Real(kind=8) :: Chl2N, Chl2N_dia, Chl2N_cocco, Chl2N_phaeo ! [mg ChlA/mmol N] Quota between phytoplankton ChlA and N (NEW changed term) Real(kind=8) :: qSiC Real(kind=8) :: qSiN Real(kind=8) :: recipQZoo ! [mmol C/mmol N] Quota between heterotrophic C and N @@ -535,8 +1302,8 @@ Module REcoM_declarations !! *** For limiter function *** Real(kind=8) :: qlimitFac, qlimitFacTmp ! Factor that regulates photosynthesis Real(kind=8),external :: recom_limiter ! Function calculating qlimitFac - Real(kind=8) :: FeLimitFac ! [Mumol/m3] Half sat constant for iron - Real(kind=8) :: pMax, pMax_dia, pMax_cocco ! [1/day] Maximum rate of C-specific photosynthesis + Real(kind=8) :: FeLimitFac ! [Mumol/m3] Half sat constant for iron + Real(kind=8) :: pMax, pMax_dia, pMax_cocco, pMax_phaeo ! [1/day] Maximum rate of C-specific photosynthesis !!------------------------------------------------------------------------------ !! *** Light *** Real(kind=8) :: kappar ! [1/m] Light attenuation coefficient modified by chla @@ -548,48 +1315,59 @@ Module REcoM_declarations Real(kind=8) :: PARave ! [?] Average light in the control volumes !!------------------------------------------------------------------------------ !! *** Photosynthesis *** - Real(kind=8) :: Cphot, Cphot_dia, Cphot_cocco ! [1/day] C-specific rate of photosynthesis + Real(kind=8) :: Cphot, Cphot_dia, Cphot_cocco, Cphot_phaeo ! [1/day] C-specific rate of photosynthesis !!------------------------------------------------------------------------------ !! *** Assimilation *** Real(kind=8) :: V_cm ! scaling factor for temperature dependent maximum of C-specific N-uptake - Real(kind=8) :: limitFacN,limitFacN_dia,limitFacN_cocco ! Factor that regulates N-assimilation. Calc from function recom_limiter + Real(kind=8) :: limitFacN,limitFacN_dia,limitFacN_cocco, limitFacN_phaeo ! Factor that regulates N-assimilation. Calc from function recom_limiter Real(kind=8) :: limitFacSi - Real(kind=8) :: N_assim, N_assim_dia, N_assim_Cocco ! [mmol N/(mmol C * day)] C specific N utilization rate + Real(kind=8) :: N_assim, N_assim_dia, N_assim_Cocco, N_assim_phaeo ! [mmol N/(mmol C * day)] C specific N utilization rate Real(kind=8) :: Si_assim !!------------------------------------------------------------------------------ !! *** Chlorophyll *** - Real(kind=8) :: ChlSynth, ChlSynth_dia, ChlSynth_cocco ! [mg CHL/ mmol N] CHL a synthesis regulation term - Real(kind=8) :: phyRespRate, phyRespRate_dia, phyRespRate_cocco ! [1/day] Phytoplankton respiration rate - Real(kind=8) :: KOchl, KOchl_dia, KOchl_cocco ! coefficient for damage to the photosynthetic apparatus + Real(kind=8) :: ChlSynth, ChlSynth_dia, ChlSynth_cocco, ChlSynth_phaeo ! [mg CHL/ mmol N] CHL a synthesis regulation term + Real(kind=8) :: phyRespRate, phyRespRate_dia, phyRespRate_cocco, phyRespRate_phaeo ! [1/day] Phytoplankton respiration rate + Real(kind=8) :: KOchl, KOchl_dia, KOchl_cocco, KOchl_phaeo ! coefficient for damage to the photosynthetic apparatus +!!------------------------------------------------------------------------------ +!! *** Vertical only Decomposition of phytoplankton growth components *** + Real(kind=8),allocatable,dimension(:) :: VTTemp_diatoms, VTTemp_phyto, VTTemp_cocco, VTTemp_phaeo ! Vertical 1D temperature effect on phytoplankton photosynthesis + Real(kind=8),allocatable,dimension(:) :: VTPhyCO2, VTDiaCO2, VTCoccoCO2, VTPhaeoCO2 ! CO2 effect + Real(kind=8),allocatable,dimension(:) :: VTqlimitFac_phyto, VTqlimitFac_diatoms, VTqlimitFac_cocco, VTqlimitFac_phaeo ! nutrient effect + Real(kind=8),allocatable,dimension(:) :: VTCphotLigLim_phyto, VTCphotLigLim_diatoms, VTCphotLigLim_cocco, VTCphotLigLim_phaeo ! light limitation + Real(kind=8),allocatable,dimension(:) :: VTCphot_phyto, VTCphot_diatoms, VTCphot_cocco, VTCphot_phaeo + Real(kind=8),allocatable,dimension(:) :: VTSi_assimDia + !!------------------------------------------------------------------------------ !! *** Iron chemistry *** Real(kind=8),external :: iron_chemistry, iron_chemistry_2ligands - Real(kind=8) :: logK1, logK2, Klig1, Klig2 + Real(kind=8) :: logK1, logK2, Klig1, Klig2 !!------------------------------------------------------------------------------ !! *** Zooplankton *** Real(kind=8) :: DiaNsq - Real(kind=8) :: varpzdia, fDiaN ! Part of Diatoms available for food - Real(kind=8) :: PhyNsq - Real(kind=8) :: varpzPhy, fPhyN ! Part of Nano available for food - Real(kind=8) :: CoccoNsq ! NEW - Real(kind=8) :: varpzCocco,fCoccoN ! NEW - Real(kind=8) :: MicZooNsq ! NEW 3Zoo - Real(kind=8) :: varpzMicZoo, fMicZooN ! NEW 3Zoo Part of microzooplankton available for food - Real(kind=8) :: food, foodsq ! [(mmol N)2/m6] - Real(kind=8) :: grazingFlux_phy, grazingFlux_Dia, grazingFlux_Cocco ! [mmol N / (m3 * day)] (NEW changed term) - Real(kind=8) :: grazingFlux_miczoo ! NEW 3Zoo + Real(kind=8) :: varpzdia, fDiaN ! Part of Diatoms available for food + Real(kind=8) :: PhyNsq + Real(kind=8) :: varpzPhy, fPhyN ! Part of Nano available for food + Real(kind=8) :: CoccoNsq + Real(kind=8) :: varpzCocco,fCoccoN + Real(kind=8) :: PhaeoNsq + Real(kind=8) :: varpzPhaeo,fPhaeoN + Real(kind=8) :: MicZooNsq ! NEW 3Zoo + Real(kind=8) :: varpzMicZoo, fMicZooN ! NEW 3Zoo Part of microzooplankton available for food + Real(kind=8) :: food, foodsq ! [(mmol N)2/m6] + Real(kind=8) :: grazingFlux_phy, grazingFlux_Dia, grazingFlux_Cocco, grazingFlux_Phaeo ! [mmol N / (m3 * day)] (NEW changed term) + Real(kind=8) :: grazingFlux_miczoo ! NEW 3Zoo Real(kind=8) :: grazingFlux - Real(kind=8) :: grazEff ! NEW 3Zoo + Real(kind=8) :: grazEff ! NEW 3Zoo Real(kind=8) :: HetRespFlux ! Zooplankton respiration Real(kind=8) :: HetLossFlux ! [(mmol N)2/(m6 * day)] Zooplankton mortality (quadratic loss) !!------------------------------------------------------------------------------ !! *** Second Zooplankton *** - Real(kind=8) :: DiaNsq2, PhyNsq2, CoccoNsq2, HetNsq ! NEW (changed term) - Real(kind=8) :: varpzDia2, fDiaN2, varpzPhy2, fPhyN2, varpzCocco2, fCoccoN2, varpzHet, fHetN ! Part of Diatoms available for food + Real(kind=8) :: DiaNsq2, PhyNsq2, CoccoNsq2, PhaeoNsq2, HetNsq ! NEW (changed term) + Real(kind=8) :: varpzDia2, fDiaN2, varpzPhy2, fPhyN2, varpzCocco2, fCoccoN2, varpzPhaeo2, fPhaeoN2, varpzHet, fHetN ! Part of Diatoms available for food Real(kind=8) :: MicZooNsq2 ! NEW Zoo3 Real(kind=8) :: varpzMicZoo2, fMicZooN2 ! NEW Zoo3 - Real(kind=8) :: food2, foodsq2 ! [(mmol N)2/m6] - Real(kind=8) :: grazingFlux_phy2, grazingFlux_Dia2, grazingFlux_Cocco2, grazingFlux_het2 ! [mmol N / (m3 * day) (NEW changed term) + Real(kind=8) :: food2, foodsq2 ! [(mmol N)2/m6] + Real(kind=8) :: grazingFlux_phy2, grazingFlux_Dia2, grazingFlux_Cocco2, grazingFlux_Phaeo2, grazingFlux_het2 ! [mmol N / (m3 * day) (NEW changed term) Real(kind=8) :: grazingFlux_miczoo2 ! NEW Zoo3 Real(kind=8) :: grazingFlux2 Real(kind=8) :: Zoo2RespFlux ! Zooplankton respiration @@ -615,8 +1393,10 @@ Module REcoM_declarations Real(kind=8) :: varpzPhy3, fPhyN3 ! Part of small phytoplankton available for food Real(kind=8) :: CoccoNsq3 Real(kind=8) :: varpzCocco3, fCoccoN3 ! Part of coccolithophores available for food + Real(kind=8) :: PhaeoNsq3 + Real(kind=8) :: varpzPhaeo3, fPhaeoN3 ! Part of phaeocystis available for food Real(kind=8) :: food3, foodsq3 ! [(mmol N)2/m6] - Real(kind=8) :: grazingFlux_phy3, grazingFlux_Dia3, grazingFlux_Cocco3 ! [mmol N / (m3 * day)] + Real(kind=8) :: grazingFlux_phy3, grazingFlux_Dia3, grazingFlux_Cocco3, grazingFlux_Phaeo3 ! [mmol N / (m3 * day)] Real(kind=8) :: grazingFlux3 Real(kind=8) :: MicZooRespFlux ! Zooplankton respiration Real(kind=8) :: MicZooLossFlux ! [(mmol N)2/(m6 * day)] Zooplankton mortality (quadratic loss) @@ -640,18 +1420,85 @@ Module REcoM_declarations !! *** Diagnostics *** Real(kind=8) :: recipbiostep ! 1/number of steps per recom cycle Real(kind=8),allocatable,dimension(:,:) :: Diags3Dloc - Real(kind=8) :: locNPPn, locGPPn, locNNAn, locChldegn - Real(kind=8) :: locNPPd, locGPPd, locNNAd, locChldegd - Real(kind=8) :: locNPPc, locGPPc, locNNAc, locChldegc + + ! ================================================================== + ! SMALL PHYTOPLANKTON (n suffix) + ! ================================================================== + Real(kind=8) :: locNPPn, locGPPn, locNNAn, locChldegn Real(kind=8),allocatable,dimension(:) :: vertNPPn, vertGPPn, vertNNAn, vertChldegn + Real(kind=8),allocatable,dimension(:) :: vertrespn + Real(kind=8),allocatable,dimension(:) :: vertdocexn + Real(kind=8),allocatable,dimension(:) :: vertaggn + + ! ================================================================== + ! DIATOMS (d suffix) + ! ================================================================== + Real(kind=8) :: locNPPd, locGPPd, locNNAd, locChldegd Real(kind=8),allocatable,dimension(:) :: vertNPPd, vertGPPd, vertNNAd, vertChldegd + Real(kind=8),allocatable,dimension(:) :: vertrespd + Real(kind=8),allocatable,dimension(:) :: vertdocexd + Real(kind=8),allocatable,dimension(:) :: vertaggd + + ! ================================================================== + ! COCCOLITHOPHORES (c suffix) + ! ================================================================== + Real(kind=8) :: locNPPc, locGPPc, locNNAc, locChldegc Real(kind=8),allocatable,dimension(:) :: vertNPPc, vertGPPc, vertNNAc, vertChldegc - Real(kind=8),allocatable,dimension(:) :: vertgrazmeso_tot, vertgrazmeso_n, vertgrazmeso_d, vertgrazmeso_c - Real(kind=8),allocatable,dimension(:) :: vertrespmeso, vertrespmacro, vertrespmicro + Real(kind=8),allocatable,dimension(:) :: vertrespc + Real(kind=8),allocatable,dimension(:) :: vertdocexc + Real(kind=8),allocatable,dimension(:) :: vertaggc Real(kind=8),allocatable,dimension(:) :: vertcalcdiss, vertcalcif - Real(kind=8),allocatable,dimension(:) :: vertaggn, vertaggd, vertaggc - Real(kind=8),allocatable,dimension(:) :: vertdocexn, vertdocexd, vertdocexc - Real(kind=8),allocatable,dimension(:) :: vertrespn, vertrespd, vertrespc + + ! ================================================================== + ! PHAEOCYSTIS (p suffix) + ! ================================================================== + Real(kind=8) :: locNPPp, locGPPp, locNNAp, locChldegp + Real(kind=8),allocatable,dimension(:) :: vertNPPp, vertGPPp, vertNNAp, vertChldegp + Real(kind=8),allocatable,dimension(:) :: vertrespp + Real(kind=8),allocatable,dimension(:) :: vertdocexp + Real(kind=8),allocatable,dimension(:) :: vertaggp + + ! ================================================================== + ! MICROZOOPLANKTON + ! ================================================================== + Real(kind=8) :: locgrazmicro_tot, locgrazmicro_n, locgrazmicro_d, locgrazmicro_c, locgrazmicro_p + Real(kind=8),allocatable,dimension(:) :: vertgrazmicro_tot, vertgrazmicro_n, vertgrazmicro_d, vertgrazmicro_c, vertgrazmicro_p + Real(kind=8),allocatable,dimension(:) :: vertrespmicro + + ! ================================================================== + ! MESOZOOPLANKTON + ! ================================================================== + Real(kind=8) :: locgrazmeso_tot, locgrazmeso_n, locgrazmeso_d, locgrazmeso_c, locgrazmeso_p + Real(kind=8) :: locgrazmeso_det, locgrazmeso_mic, locgrazmeso_det2 + Real(kind=8),allocatable,dimension(:) :: vertgrazmeso_tot, vertgrazmeso_n, vertgrazmeso_d, vertgrazmeso_c, vertgrazmeso_p + Real(kind=8),allocatable,dimension(:) :: vertgrazmeso_det, vertgrazmeso_mic, vertgrazmeso_det2 + Real(kind=8),allocatable,dimension(:) :: vertrespmeso + + ! ================================================================== + ! MACROZOOPLANKTON + ! ================================================================== + Real(kind=8) :: locgrazmacro_tot, locgrazmacro_n, locgrazmacro_d, locgrazmacro_c, locgrazmacro_p + Real(kind=8) :: locgrazmacro_mes, locgrazmacro_det, locgrazmacro_mic, locgrazmacro_det2 + Real(kind=8),allocatable,dimension(:) :: vertgrazmacro_tot, vertgrazmacro_n, vertgrazmacro_d, vertgrazmacro_c, vertgrazmacro_p + Real(kind=8),allocatable,dimension(:) :: vertgrazmacro_mes, vertgrazmacro_det, vertgrazmacro_mic, vertgrazmacro_det2 + Real(kind=8),allocatable,dimension(:) :: vertrespmacro + + Real(kind=8),allocatable,dimension(:) :: vertfastcdis + Real(kind=8),allocatable,dimension(:) :: vertphotn, vertphotd, vertphotc, vertphotp !Phytoplankton photosynthesis terms + Real(kind=8),allocatable,dimension(:) :: vertmesocdis, vertmicrocdis, vertmacrocdis !Additional zooplankton calcium dissolution terms + Real(kind=8),allocatable,dimension(:) :: vertNassimn, vertNassimd, vertNassimc, vertNassimp !N assimilation by phytoplanktons + Real(kind=8),allocatable,dimension(:) :: vertDONremin !DON remineralization term + Real(kind=8),allocatable,dimension(:) :: vertDOCremin !DOC remineralization term + Real(kind=8),allocatable,dimension(:,:,:) :: dtr_bf_din ! Diagnostics for DIN bottom flux RP on 26.09.2025 + Real(kind=8),allocatable,dimension(:,:,:) :: dtr_bf_dic ! Diagnostics for DIC bottom flux + Real(kind=8),allocatable,dimension(:,:,:) :: dtr_bf_alk ! Diagnostics for Alk bottom flux + Real(kind=8),allocatable,dimension(:,:,:) :: dtr_bf_dsi ! Diagnostics for DSi bottom flux + + !=================================================================== + ! DISSOLUTION AND REMINERALIZATION ! R2OMIP + !=================================================================== + Real(kind=8) :: locDISSOC, locDISSON, locDISSOSi, locREMOC, locREMOCt, locREMON + Real(kind=8),allocatable,dimension(:) :: vertDISSOC, vertDISSON, vertDISSOSi, vertREMOC, vertREMOCt, vertREMON !!------------------------------------------------------------------------------ !! *** Benthos *** Real(kind=8),allocatable,dimension(:) :: decayBenthos ! [1/day] Decay rate of detritus in the benthic layer @@ -659,11 +1506,13 @@ Module REcoM_declarations Real(kind=8),allocatable,dimension(:) :: wFluxPhy ! [mmol/(m2 * day)] Flux of N,C, calc and chl through sinking of phytoplankton Real(kind=8),allocatable,dimension(:) :: wFluxDia ! [mmol/(m2 * day)] Flux of N,C, Si and chl through sinking of diatoms Real(kind=8),allocatable,dimension(:) :: wFluxCocco ! NEW [mmol/(m2 * day)] Flux of N,C, calc and chl through sinking of coccos + Real(kind=8),allocatable,dimension(:) :: wFluxPhaeo ! NEW [mmol/(m2 * day)] Flux of N,C, calc and chl through sinking of Phaeocystis Real(kind=8) :: Vben_det ! [m/day] speed of sinking into benthos from water column Real(kind=8) :: Vben_det_seczoo !second zooplankton sinking benthos Real(kind=8) :: Vben_phy Real(kind=8) :: Vben_dia Real(kind=8) :: Vben_coc + Real(kind=8) :: Vben_pha ! Phaeocystis Real(kind=8) :: Ironflux ! [umol Fe/(m2*day)] Flux of Fe from sediment to water !_______________________________________________________________________________ ! Arrays added for RECOM implementation: @@ -678,6 +1527,9 @@ Module REcoM_declarations real(kind=8) :: is_riverinput real(kind=8) :: is_erosioninput +real(kind=8) :: is_3zoo2det +real(kind=8) :: is_coccos + end module REcoM_declarations !=============================================================================== @@ -686,13 +1538,14 @@ end module REcoM_declarations Module REcoM_GloVar implicit none save - + Real(kind=8),allocatable,dimension(:,:) :: Benthos ! 4 types of benthos-tracers with size [4 n2d] Real(kind=8),allocatable,dimension(:,:,:) :: Benthos_tr ! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel Real(kind=8),allocatable,dimension(:) :: GloFeDust ! [umol/m2/s] Monthly 2D field of iron soluted in surface water from dust Real(kind=8),allocatable,dimension(:) :: GloNDust ! [mmol/m2/s] 10-year mean 2D fields of nitrogen soluted in surface water from dust Real(kind=8),dimension(12) :: AtmCO2 ! [uatm] Atmospheric CO2 partial pressure. One value for the whole planet for each month + Real(kind=8),allocatable,dimension(:) :: OmegaC_bottom !< calcite saturation state at the ocean bottom !R2OMIP Real(kind=8),allocatable,dimension(:) :: AtmFeInput ! [umol/m2/s] Includes ice, but is, other than that identlical to GloFeDust Real(kind=8),allocatable,dimension(:) :: AtmNInput ! [umol/m2/s] Includes ice, but is, other than that identlical to GloNDust @@ -721,11 +1574,17 @@ Module REcoM_GloVar Real(kind=8),allocatable,dimension(:) :: GlodPCO2surf ! [mmol/m2/day] ocean-atmosphere Real(kind=8),allocatable,dimension(:,:) :: GlodecayBenthos ! [1/day] Decay rate of detritus in the benthic layer saved for oce_ale_tracer.F90 + Real(kind=8),allocatable,dimension(:,:) :: Sed_2_Ocean_Flux ! Flux from the sediment back to the bottom ocean ! R2OMIP + Real(kind=8),allocatable,dimension(:,:) :: Ocean_2_Sed_Flux ! Flux from the bottom ocean to the sediment ! R2OMIP + Real(kind=8),allocatable,dimension(:,:) :: Burial ! Benthic permanent burial Field in 2D [n2d 1] ! R2OMIP + Real(kind=8),allocatable,dimension(:) :: PistonVelocity ! [m s-1] + Real(kind=8),allocatable,dimension(:) :: alphaCO2 ! [mol L-1 atm-1] Real(kind=8),allocatable,dimension(:,:) :: GlowFluxDet ! Real(kind=8),allocatable,dimension(:,:) :: GlowFluxPhy ! Real(kind=8),allocatable,dimension(:,:) :: GlowFluxDia ! - Real(kind=8),allocatable,dimension(:,:) :: GlowFluxCocco ! + Real(kind=8),allocatable,dimension(:,:) :: GlowFluxCocco ! + Real(kind=8),allocatable,dimension(:,:) :: GlowFluxPhaeo ! Real(kind=8),allocatable,dimension(:,:) :: diags2D ! Diagnostics in 2D [8 n2d] Real(kind=8),allocatable,dimension(:) :: NPPn @@ -740,10 +1599,38 @@ Module REcoM_GloVar Real(kind=8),allocatable,dimension(:) :: GPPc Real(kind=8),allocatable,dimension(:) :: NNAc Real(kind=8),allocatable,dimension(:) :: Chldegc - Real(kind=8),allocatable,dimension(:,:) :: grazmeso_tot - Real(kind=8),allocatable,dimension(:,:) :: grazmeso_n - Real(kind=8),allocatable,dimension(:,:) :: grazmeso_d - Real(kind=8),allocatable,dimension(:,:) :: grazmeso_c + Real(kind=8),allocatable,dimension(:) :: NPPp ! Phaeocystis + Real(kind=8),allocatable,dimension(:) :: GPPp + Real(kind=8),allocatable,dimension(:) :: NNAp + Real(kind=8),allocatable,dimension(:) :: Chldegp + Real(kind=8),allocatable,dimension(:) :: grazmeso_tot + Real(kind=8),allocatable,dimension(:) :: grazmeso_n + Real(kind=8),allocatable,dimension(:) :: grazmeso_d + Real(kind=8),allocatable,dimension(:) :: grazmeso_c + Real(kind=8),allocatable,dimension(:) :: grazmeso_p + Real(kind=8),allocatable,dimension(:) :: grazmeso_det + Real(kind=8),allocatable,dimension(:) :: grazmeso_mic + Real(kind=8),allocatable,dimension(:) :: grazmeso_det2 + Real(kind=8),allocatable,dimension(:) :: grazmacro_tot + Real(kind=8),allocatable,dimension(:) :: grazmacro_n + Real(kind=8),allocatable,dimension(:) :: grazmacro_d + Real(kind=8),allocatable,dimension(:) :: grazmacro_c + Real(kind=8),allocatable,dimension(:) :: grazmacro_p + Real(kind=8),allocatable,dimension(:) :: grazmacro_mes + Real(kind=8),allocatable,dimension(:) :: grazmacro_det + Real(kind=8),allocatable,dimension(:) :: grazmacro_mic + Real(kind=8),allocatable,dimension(:) :: grazmacro_det2 + Real(kind=8),allocatable,dimension(:) :: grazmicro_tot + Real(kind=8),allocatable,dimension(:) :: grazmicro_n + Real(kind=8),allocatable,dimension(:) :: grazmicro_d + Real(kind=8),allocatable,dimension(:) :: grazmicro_c + Real(kind=8),allocatable,dimension(:) :: grazmicro_p + Real(kind=8),allocatable,dimension(:) :: DISSOC + Real(kind=8),allocatable,dimension(:) :: DISSON + Real(kind=8),allocatable,dimension(:) :: DISSOSi + Real(kind=8),allocatable,dimension(:) :: REMOC + Real(kind=8),allocatable,dimension(:) :: REMOCt + Real(kind=8),allocatable,dimension(:) :: REMON Real(kind=8),allocatable,dimension(:,:) :: respmeso Real(kind=8),allocatable,dimension(:,:) :: respmacro Real(kind=8),allocatable,dimension(:,:) :: respmicro @@ -752,15 +1639,56 @@ Module REcoM_GloVar Real(kind=8),allocatable,dimension(:,:) :: aggn Real(kind=8),allocatable,dimension(:,:) :: aggd Real(kind=8),allocatable,dimension(:,:) :: aggc + Real(kind=8),allocatable,dimension(:,:) :: aggp ! Phaeocystis Real(kind=8),allocatable,dimension(:,:) :: docexn Real(kind=8),allocatable,dimension(:,:) :: docexd Real(kind=8),allocatable,dimension(:,:) :: docexc + Real(kind=8),allocatable,dimension(:,:) :: docexp ! Phaeocystis Real(kind=8),allocatable,dimension(:,:) :: respn Real(kind=8),allocatable,dimension(:,:) :: respd Real(kind=8),allocatable,dimension(:,:) :: respc + Real(kind=8),allocatable,dimension(:,:) :: respp ! Phaeocystis Real(kind=8),allocatable,dimension(:,:) :: NPPn3D Real(kind=8),allocatable,dimension(:,:) :: NPPd3D Real(kind=8),allocatable,dimension(:,:) :: NPPc3D + Real(kind=8),allocatable,dimension(:,:) :: NPPp3D ! Phaeocystis + + Real(kind=8),allocatable,dimension(:,:) :: photn + Real(kind=8),allocatable,dimension(:,:) :: photd + Real(kind=8),allocatable,dimension(:,:) :: photc + Real(kind=8),allocatable,dimension(:,:) :: photp + Real(kind=8),allocatable,dimension(:,:) :: DOCremin + Real(kind=8),allocatable,dimension(:,:) :: Nassimn + Real(kind=8),allocatable,dimension(:,:) :: Nassimd + Real(kind=8),allocatable,dimension(:,:) :: Nassimc + Real(kind=8),allocatable,dimension(:,:) :: Nassimp + Real(kind=8),allocatable,dimension(:,:) :: DONremin + Real(kind=8),allocatable,dimension(:,:) :: fastcdis + Real(kind=8),allocatable,dimension(:,:) :: mesocdis + Real(kind=8),allocatable,dimension(:,:) :: microcdis + Real(kind=8),allocatable,dimension(:,:) :: macrocdis + + Real(kind=8),allocatable,dimension(:,:) :: TTemp_diatoms ! my new variables to track + Real(kind=8),allocatable,dimension(:,:) :: TTemp_phyto ! new Temperature effect + Real(kind=8),allocatable,dimension(:,:) :: TTemp_cocco ! new + Real(kind=8),allocatable,dimension(:,:) :: TTemp_phaeo ! new + Real(kind=8),allocatable,dimension(:,:) :: TPhyCO2 ! new CO2 effect + Real(kind=8),allocatable,dimension(:,:) :: TDiaCO2 + Real(kind=8),allocatable,dimension(:,:) :: TCoccoCO2 + Real(kind=8),allocatable,dimension(:,:) :: TPhaeoCO2 + Real(kind=8),allocatable,dimension(:,:) :: TqlimitFac_phyto ! new nutrient limitation + Real(kind=8),allocatable,dimension(:,:) :: TqlimitFac_diatoms + Real(kind=8),allocatable,dimension(:,:) :: TqlimitFac_cocco + Real(kind=8),allocatable,dimension(:,:) :: TqlimitFac_phaeo + Real(kind=8),allocatable,dimension(:,:) :: TCphotLigLim_phyto ! new light limitation + Real(kind=8),allocatable,dimension(:,:) :: TCphot_phyto ! new + Real(kind=8),allocatable,dimension(:,:) :: TCphotLigLim_diatoms ! new light limitation + Real(kind=8),allocatable,dimension(:,:) :: TCphot_diatoms + Real(kind=8),allocatable,dimension(:,:) :: TCphotLigLim_cocco ! new light limitation + Real(kind=8),allocatable,dimension(:,:) :: TCphot_cocco + Real(kind=8),allocatable,dimension(:,:) :: TCphotLigLim_phaeo ! new light limitation + Real(kind=8),allocatable,dimension(:,:) :: TCphot_phaeo + Real(kind=8),allocatable,dimension(:,:) :: TSi_assimDia ! tracking the assimilation of Si by Diatoms Real(kind=8),allocatable,dimension(:) :: DenitBen ! Benthic denitrification Field in 2D [n2d 1] @@ -770,13 +1698,17 @@ Module REcoM_GloVar Real(kind=8),allocatable,dimension(:,:) :: Sinkingvel1 ! Diagnostics for vertical sinking Real(kind=8),allocatable,dimension(:,:) :: Sinkingvel2 ! Diagnostics for vertical sinking Real(kind=8),allocatable,dimension(:,:,:) :: Sinkvel1_tr ! Sinking speed of particle class 1 OG 16.03.23 - Real(kind=8),allocatable,dimension(:,:,:) :: Sinkvel2_tr ! Sinking speed of particle class 2 OG 16.03.23 + Real(kind=8),allocatable,dimension(:,:,:) :: Sinkvel2_tr ! Sinking speed of particle class 2 OG 16.03.23 + Real(kind=8),allocatable,dimension(:,:) :: dtr_bflux_din ! Diagnostics for DIN bottom flux RP on 30.09.2025 + Real(kind=8),allocatable,dimension(:,:) :: dtr_bflux_dic ! Diagnostics for DIC bottom flux + Real(kind=8),allocatable,dimension(:,:) :: dtr_bflux_alk ! Diagnostics for Alk bottom flux + Real(kind=8),allocatable,dimension(:,:) :: dtr_bflux_dsi ! Diagnostics for DSi bottom flux Real(kind=8),allocatable,dimension(:,:) :: GloSed ! Yearly input into bottom water from sediments [n2d 5] or [n2d 7] with ciso Real(kind=8),allocatable,dimension(:,:) :: lb_flux ! Yearly burial from medusa: [n2d 5] or [n2d 9] with ciso_14 ! atmospheric box model: - real(kind=8),allocatable,dimension(:) :: x_co2atm ! atmospheric CO2 mixing ratio (mole fraction) + Real(kind=8),allocatable,dimension(:) :: x_co2atm ! atmospheric CO2 mixing ratio (mole fraction) Real(kind=8), allocatable,dimension(:) :: Alk_surf ! Surface alkalinity field used for restoring Real(kind=8), allocatable,dimension(:) :: relax_alk @@ -784,7 +1716,12 @@ Module REcoM_GloVar real(kind=8), allocatable,dimension(:,:) :: PAR3D ! Light in the water column [nl-1 n2d] real(kind=8), allocatable,dimension(:) :: RiverineLonOrig, RiverineLatOrig, RiverineDINOrig, RiverineDONOrig, RiverineDOCOrig, RiverineDSiOrig ! Variables to save original values for riverine nutrients - real(kind=8), allocatable,dimension(:) :: RiverDIN2D, RiverDON2D, RiverDOC2D, RiverDSi2D, RiverAlk2D, RiverDIC2D, RiverFe + real(kind=8), allocatable,dimension(:) :: RiverDIC2D, RiverDIN2D, RiverDOCl2D, RiverDOCsl2D, RiverPOC2D, RiverFe + real(kind=8), allocatable,dimension(:) :: RiverDON2D, RiverDSi2D, RiverAlk2D ! RiverDOC2D + Real(kind=8),allocatable,dimension(:) :: LocDenit + Real(kind=8),allocatable,dimension(:,:) :: LocBurial ! R2OMIP + Real(kind=8),allocatable,dimension(:) :: BurialBen ! R2OMIP + real(kind=8), allocatable,dimension(:) :: ErosionTSi2D, ErosionTON2D, ErosionTOC2D !! Cobeta, Cos(Angle of incidence) Real(kind=8), allocatable,dimension(:) :: cosAI @@ -865,7 +1802,7 @@ Module REcoM_locVar Real(kind=8) :: PICPOCN ! (to make calcification dependent on N-limitation) Real(kind=8) :: calc_prod_final ! (added to make the calcification dependent on nutrients (N, Fe), after Krumhardt et al. 2017/2019) Integer :: currentCO2year - + end module REcoM_LocVar !=============================================================================== ! Specific declarations related to carbon isotope simulations @@ -1167,3 +2104,496 @@ end function wind_10 end module REcoM_ciso + + +module recom_diags_management + use recom_config + implicit none + +contains + +! ============================================================================== +! SUBROUTINE: allocate_and_init_diags +! Purpose: Allocate and initialize all diagnostic arrays for a water column +! ============================================================================== +subroutine allocate_and_init_diags(nl) + use recom_locvar + use REcoM_declarations + implicit none + + integer, intent(in) :: nl ! Number of vertical levels + + ! -------------------------------------------------------------------------- + ! Small Phytoplankton + ! -------------------------------------------------------------------------- + allocate(vertNPPn(nl-1), vertGPPn(nl-1), vertNNAn(nl-1), vertChldegn(nl-1)) + allocate(vertrespn(nl-1), vertdocexn(nl-1), vertaggn(nl-1)) + + vertNPPn = 0.d0 + vertGPPn = 0.d0 + vertNNAn = 0.d0 + vertChldegn = 0.d0 + vertrespn = 0.d0 + vertdocexn = 0.d0 + vertaggn = 0.d0 + + ! -------------------------------------------------------------------------- + ! Diatoms + ! -------------------------------------------------------------------------- + allocate(vertNPPd(nl-1), vertGPPd(nl-1), vertNNAd(nl-1), vertChldegd(nl-1)) + allocate(vertrespd(nl-1), vertdocexd(nl-1), vertaggd(nl-1)) + + vertNPPd = 0.d0 + vertGPPd = 0.d0 + vertNNAd = 0.d0 + vertChldegd = 0.d0 + vertrespd = 0.d0 + vertdocexd = 0.d0 + vertaggd = 0.d0 + + ! -------------------------------------------------------------------------- + ! Coccolithophores (if enabled) + ! -------------------------------------------------------------------------- + if (enable_coccos) then + allocate(vertNPPc(nl-1), vertGPPc(nl-1), vertNNAc(nl-1), vertChldegc(nl-1)) + allocate(vertrespc(nl-1), vertdocexc(nl-1), vertaggc(nl-1)) + allocate(vertcalcdiss(nl-1), vertcalcif(nl-1)) + + vertNPPc = 0.d0 + vertGPPc = 0.d0 + vertNNAc = 0.d0 + vertChldegc = 0.d0 + vertrespc = 0.d0 + vertdocexc = 0.d0 + vertaggc = 0.d0 + vertcalcdiss = 0.d0 + vertcalcif = 0.d0 + + ! ---------------------------------------------------------------------- + ! Phaeocystis + ! ---------------------------------------------------------------------- + allocate(vertNPPp(nl-1), vertGPPp(nl-1), vertNNAp(nl-1), vertChldegp(nl-1)) + allocate(vertrespp(nl-1), vertdocexp(nl-1), vertaggp(nl-1)) + + vertNPPp = 0.d0 + vertGPPp = 0.d0 + vertNNAp = 0.d0 + vertChldegp = 0.d0 + vertrespp = 0.d0 + vertdocexp = 0.d0 + vertaggp = 0.d0 + else + ! Allocate calcification arrays even if coccos are disabled + allocate(vertcalcdiss(nl-1), vertcalcif(nl-1)) + vertcalcdiss = 0.d0 + vertcalcif = 0.d0 + endif + + ! -------------------------------------------------------------------------- + ! Zooplankton Grazing (if enabled) + ! -------------------------------------------------------------------------- + if (Grazing_detritus) then + + ! Mesozooplankton + allocate(vertgrazmeso_tot(nl-1), vertgrazmeso_n(nl-1), vertgrazmeso_d(nl-1)) + allocate(vertgrazmeso_det(nl-1)) + allocate(vertrespmeso(nl-1)) + vertgrazmeso_tot = 0.d0 + vertgrazmeso_n = 0.d0 + vertgrazmeso_d = 0.d0 + vertgrazmeso_det = 0.d0 + vertrespmeso = 0.d0 + + if (enable_3zoo2det) then + ! Microzooplankton + allocate(vertgrazmicro_tot(nl-1), vertgrazmicro_n(nl-1), vertgrazmicro_d(nl-1)) + allocate(vertrespmicro(nl-1)) + + vertgrazmicro_tot = 0.d0 + vertgrazmicro_n = 0.d0 + vertgrazmicro_d = 0.d0 + vertrespmicro = 0.d0 + + ! Mesozooplankton + + allocate(vertgrazmeso_mic(nl-1), vertgrazmeso_det2(nl-1)) + vertgrazmeso_mic = 0.d0 + vertgrazmeso_det2 = 0.d0 + + if (enable_coccos) then + allocate(vertgrazmicro_c(nl-1), vertgrazmicro_p(nl-1)) + allocate(vertgrazmeso_c(nl-1), vertgrazmeso_p(nl-1)) + + vertgrazmicro_c = 0.d0 + vertgrazmicro_p = 0.d0 + vertgrazmeso_c = 0.d0 + vertgrazmeso_p = 0.d0 + endif + + ! Macrozooplankton + allocate(vertgrazmacro_tot(nl-1), vertgrazmacro_n(nl-1), vertgrazmacro_d(nl-1)) + allocate(vertgrazmacro_mes(nl-1), vertgrazmacro_det(nl-1)) + allocate(vertgrazmacro_mic(nl-1), vertgrazmacro_det2(nl-1)) + allocate(vertrespmacro(nl-1)) + + vertgrazmacro_tot = 0.d0 + vertgrazmacro_n = 0.d0 + vertgrazmacro_d = 0.d0 + vertgrazmacro_mes = 0.d0 + vertgrazmacro_det = 0.d0 + vertgrazmacro_mic = 0.d0 + vertgrazmacro_det2 = 0.d0 + vertrespmacro = 0.d0 + + if (enable_coccos) then + allocate(vertgrazmacro_c(nl-1), vertgrazmacro_p(nl-1)) + vertgrazmacro_c = 0.d0 + vertgrazmacro_p = 0.d0 + endif + endif + endif + + ! Dissolution and remineralization ! R2OMIP + allocate(vertDISSOC(nl-1), vertDISSON(nl-1), vertDISSOSi(nl-1), vertREMOC(nl-1), vertREMOCt(nl-1), vertREMON(nl-1)) + vertDISSOC = 0.d0 + vertDISSON = 0.d0 + vertDISSOSi = 0.d0 + vertREMOC = 0.d0 + vertREMOCt = 0.d0 + vertREMON = 0.d0 + + ! -------------------------------------------------------------------------- + ! Temperature and Photosynthesis Tracking Variables + ! -------------------------------------------------------------------------- + + allocate(VTPhyCO2(nl-1), VTDiaCO2(nl-1)) + VTPhyCO2 = 0.d0 + VTDiaCO2 = 0.d0 + + allocate(VTCphotLigLim_phyto(nl-1), VTCphotLigLim_diatoms(nl-1)) + VTCphotLigLim_phyto = 0.d0 + VTCphotLigLim_diatoms = 0.d0 + + allocate(VTCphot_phyto(nl-1), VTCphot_diatoms(nl-1)) + VTCphot_phyto = 0.d0 + VTCphot_diatoms = 0.d0 + + allocate(VTTemp_diatoms(nl-1), VTTemp_phyto(nl-1)) + VTTemp_diatoms = 0.d0 + VTTemp_phyto = 0.d0 + + allocate(VTqlimitFac_phyto(nl-1), VTqlimitFac_diatoms(nl-1)) + VTqlimitFac_phyto = 0.d0 + VTqlimitFac_diatoms = 0.d0 + + allocate(VTSi_assimDia(nl-1)) + VTSi_assimDia = 0.d0 + + if (enable_coccos) then + ! -------------------------------------------------------------------------- + ! Coccolithophores and Phaeocystis Tracking (if enabled) + ! -------------------------------------------------------------------------- + + allocate(VTTemp_cocco(nl-1), VTTemp_phaeo(nl-1)) + VTTemp_cocco = 0.d0 + VTTemp_phaeo = 0.d0 + + allocate(VTCoccoCO2(nl-1), VTPhaeoCO2(nl-1)) + VTCoccoCO2 = 0.d0 + VTPhaeoCO2 = 0.d0 + + allocate(VTqlimitFac_cocco(nl-1), VTqlimitFac_phaeo(nl-1)) + VTqlimitFac_cocco = 0.d0 + VTqlimitFac_phaeo = 0.d0 + + allocate(VTCphotLigLim_cocco(nl-1), VTCphotLigLim_phaeo(nl-1)) + VTCphotLigLim_cocco = 0.d0 + VTCphotLigLim_phaeo = 0.d0 + + allocate(VTCphot_cocco(nl-1), VTCphot_phaeo(nl-1)) + VTCphot_cocco = 0.d0 + VTCphot_phaeo = 0.d0 + + endif + +end subroutine allocate_and_init_diags + +! ============================================================================== +! SUBROUTINE: update_2d_diags +! Purpose: Transfer local diagnostic values to 2D global arrays +! ============================================================================== +subroutine update_2d_diags(n) + use recom_locvar + use recom_glovar + use REcoM_declarations + implicit none + + integer, intent(in) :: n ! Node index + + ! -------------------------------------------------------------------------- + ! Small Phytoplankton + ! -------------------------------------------------------------------------- + NPPn(n) = locNPPn + GPPn(n) = locGPPn + NNAn(n) = locNNAn + Chldegn(n) = locChldegn + + ! -------------------------------------------------------------------------- + ! Diatoms + ! -------------------------------------------------------------------------- + NPPd(n) = locNPPd + GPPd(n) = locGPPd + NNAd(n) = locNNAd + Chldegd(n) = locChldegd + + ! -------------------------------------------------------------------------- + ! Coccolithophores and Phaeocystis (if enabled) + ! -------------------------------------------------------------------------- + if (enable_coccos) then + NPPc(n) = locNPPc + GPPc(n) = locGPPc + NNAc(n) = locNNAc + Chldegc(n) = locChldegc + + NPPp(n) = locNPPp + GPPp(n) = locGPPp + NNAp(n) = locNNAp + Chldegp(n) = locChldegp + endif + + ! -------------------------------------------------------------------------- + ! Zooplankton Grazing (if enabled) + ! -------------------------------------------------------------------------- + if (Grazing_detritus) then + ! Mesozooplankton + grazmeso_tot(n) = locgrazmeso_tot + grazmeso_n(n) = locgrazmeso_n + grazmeso_d(n) = locgrazmeso_d + grazmeso_det(n) = locgrazmeso_det + + if (enable_coccos) then + grazmeso_c(n) = locgrazmeso_c + grazmeso_p(n) = locgrazmeso_p + endif + + if (enable_3zoo2det) then + grazmeso_mic(n) = locgrazmeso_mic + grazmeso_det2(n) = locgrazmeso_det2 + + ! Macrozooplankton + grazmacro_tot(n) = locgrazmacro_tot + grazmacro_n(n) = locgrazmacro_n + grazmacro_d(n) = locgrazmacro_d + grazmacro_mes(n) = locgrazmacro_mes + grazmacro_det(n) = locgrazmacro_det + grazmacro_mic(n) = locgrazmacro_mic + grazmacro_det2(n) = locgrazmacro_det2 + + if (enable_coccos) then + grazmacro_c(n) = locgrazmacro_c + grazmacro_p(n) = locgrazmacro_p + endif + + ! Microzooplankton + grazmicro_tot(n) = locgrazmicro_tot + grazmicro_n(n) = locgrazmicro_n + grazmicro_d(n) = locgrazmicro_d + + if (enable_coccos) then + grazmicro_c(n) = locgrazmicro_c + grazmicro_p(n) = locgrazmicro_p + endif + endif + endif + + ! Dissolution and remineralization ! R2OMIP + DISSOC(n) = locDISSOC + DISSON(n) = locDISSON + DISSOSi(n) = locDISSOSi + REMOC(n) = locREMOC + REMOCt(n) = locREMOCt + REMON(n) = locREMON + +end subroutine update_2d_diags + +! ============================================================================== +! SUBROUTINE: update_3d_diags +! Purpose: Transfer vertical profile diagnostic values to 3D global arrays +! ============================================================================== +subroutine update_3d_diags(n, nzmax) + use recom_locvar + use recom_glovar + use REcoM_declarations + implicit none + + integer, intent(in) :: n ! Node index + integer, intent(in) :: nzmax ! Maximum vertical level for this node + + ! -------------------------------------------------------------------------- + ! Small Phytoplankton + ! -------------------------------------------------------------------------- + aggn(1:nzmax,n) = vertaggn(1:nzmax) + docexn(1:nzmax,n) = vertdocexn(1:nzmax) + respn(1:nzmax,n) = vertrespn(1:nzmax) + NPPn3D(1:nzmax,n) = vertNPPn(1:nzmax) + + ! -------------------------------------------------------------------------- + ! Diatoms + ! -------------------------------------------------------------------------- + aggd(1:nzmax,n) = vertaggd(1:nzmax) + docexd(1:nzmax,n) = vertdocexd(1:nzmax) + respd(1:nzmax,n) = vertrespd(1:nzmax) + NPPd3D(1:nzmax,n) = vertNPPd(1:nzmax) + + ! -------------------------------------------------------------------------- + ! Coccolithophores and Phaeocystis (if enabled) + ! -------------------------------------------------------------------------- + if (enable_coccos) then + aggc(1:nzmax,n) = vertaggc(1:nzmax) + docexc(1:nzmax,n) = vertdocexc(1:nzmax) + respc(1:nzmax,n) = vertrespc(1:nzmax) + NPPc3D(1:nzmax,n) = vertNPPc(1:nzmax) + + aggp(1:nzmax,n) = vertaggp(1:nzmax) + docexp(1:nzmax,n) = vertdocexp(1:nzmax) + respp(1:nzmax,n) = vertrespp(1:nzmax) + NPPp3D(1:nzmax,n) = vertNPPp(1:nzmax) + endif + + ! -------------------------------------------------------------------------- + ! Calcification + ! -------------------------------------------------------------------------- + calcdiss(1:nzmax,n) = vertcalcdiss(1:nzmax) + calcif(1:nzmax,n) = vertcalcif(1:nzmax) + + ! -------------------------------------------------------------------------- + ! Zooplankton Respiration + ! -------------------------------------------------------------------------- + respmeso(1:nzmax,n) = vertrespmeso(1:nzmax) + + if (enable_3zoo2det) then + respmacro(1:nzmax,n) = vertrespmacro(1:nzmax) + respmicro(1:nzmax,n) = vertrespmicro(1:nzmax) + endif + + TPhyCO2(1:nzmax,n) = VTPhyCO2(1:nzmax) + TDiaCO2(1:nzmax,n) = VTDiaCO2(1:nzmax) + TCphotLigLim_phyto(1:nzmax,n) = VTCphotLigLim_phyto(1:nzmax) + TCphot_phyto(1:nzmax,n) = VTCphot_phyto(1:nzmax) + TCphotLigLim_diatoms(1:nzmax,n)= VTCphotLigLim_diatoms(1:nzmax) + TCphot_diatoms(1:nzmax,n) = VTCphot_diatoms(1:nzmax) + + if (enable_coccos) then + ! -------------------------------------------------------------------------- + ! Temperature and Photosynthesis Tracking - Phytoplankton + ! -------------------------------------------------------------------------- + TTemp_phyto(1:nzmax,n) = VTTemp_phyto(1:nzmax) + TqlimitFac_phyto(1:nzmax,n) = VTqlimitFac_phyto(1:nzmax) + + ! -------------------------------------------------------------------------- + ! Temperature and Photosynthesis Tracking - Diatoms + ! -------------------------------------------------------------------------- + TTemp_diatoms(1:nzmax,n) = VTTemp_diatoms(1:nzmax) + TqlimitFac_diatoms(1:nzmax,n) = VTqlimitFac_diatoms(1:nzmax) + TSi_assimDia(1:nzmax,n) = VTSi_assimDia(1:nzmax) + + ! -------------------------------------------------------------------------- + ! Temperature and Photosynthesis Tracking - Coccos/Phaeo (if enabled) + ! -------------------------------------------------------------------------- + + TTemp_cocco(1:nzmax,n) = VTTemp_cocco(1:nzmax) + TCoccoCO2(1:nzmax,n) = VTCoccoCO2(1:nzmax) + TqlimitFac_cocco(1:nzmax,n) = VTqlimitFac_cocco(1:nzmax) + TCphotLigLim_cocco(1:nzmax,n) = VTCphotLigLim_cocco(1:nzmax) + TCphot_cocco(1:nzmax,n) = VTCphot_cocco(1:nzmax) + + TTemp_phaeo(1:nzmax,n) = VTTemp_phaeo(1:nzmax) + TPhaeoCO2(1:nzmax,n) = VTPhaeoCO2(1:nzmax) + TqlimitFac_phaeo(1:nzmax,n) = VTqlimitFac_phaeo(1:nzmax) + TCphotLigLim_phaeo(1:nzmax,n) = VTCphotLigLim_phaeo(1:nzmax) + TCphot_phaeo(1:nzmax,n) = VTCphot_phaeo(1:nzmax) + endif + +end subroutine update_3d_diags + +! ============================================================================== +! SUBROUTINE: deallocate_diags +! Purpose: Deallocate all diagnostic arrays +! ============================================================================== +subroutine deallocate_diags() + use recom_locvar + use REcoM_declarations + implicit none + + ! -------------------------------------------------------------------------- + ! Small Phytoplankton + ! -------------------------------------------------------------------------- + deallocate(vertNPPn, vertGPPn, vertNNAn, vertChldegn) + deallocate(vertaggn, vertdocexn, vertrespn) + deallocate(VTPhyCO2, VTCphotLigLim_phyto, VTCphot_phyto) + + ! -------------------------------------------------------------------------- + ! Diatoms + ! -------------------------------------------------------------------------- + deallocate(vertNPPd, vertGPPd, vertNNAd, vertChldegd) + deallocate(vertaggd, vertdocexd, vertrespd) + deallocate(VTDiaCO2, VTCphotLigLim_diatoms, VTCphot_diatoms) + + deallocate(VTTemp_phyto, VTqlimitFac_phyto) + deallocate(VTTemp_diatoms, VTqlimitFac_diatoms) + deallocate(VTSi_assimDia) + deallocate(vertcalcdiss, vertcalcif) + + if (enable_coccos) then + ! -------------------------------------------------------------------------- + ! Coccolithophores and Phaeocystis (if enabled) + ! -------------------------------------------------------------------------- + deallocate(vertNPPc, vertGPPc, vertNNAc, vertChldegc) + deallocate(vertaggc, vertdocexc, vertrespc) + deallocate(VTTemp_cocco, VTCoccoCO2, VTqlimitFac_cocco) + deallocate(VTCphotLigLim_cocco, VTCphot_cocco) + + deallocate(vertNPPp, vertGPPp, vertNNAp, vertChldegp) + deallocate(vertaggp, vertdocexp, vertrespp) + deallocate(VTTemp_phaeo, VTPhaeoCO2, VTqlimitFac_phaeo) + deallocate(VTCphotLigLim_phaeo, VTCphot_phaeo) + endif + + ! -------------------------------------------------------------------------- + ! Zooplankton Grazing (if enabled) + ! -------------------------------------------------------------------------- + if (Grazing_detritus) then + deallocate(vertgrazmeso_tot, vertgrazmeso_n, vertgrazmeso_d) + deallocate(vertgrazmeso_det, vertrespmeso) + + if (enable_coccos) then + deallocate(vertgrazmeso_c, vertgrazmeso_p) + endif + + if (enable_3zoo2det) then + deallocate(vertgrazmeso_mic, vertgrazmeso_det2) + + deallocate(vertgrazmacro_tot, vertgrazmacro_n, vertgrazmacro_d) + deallocate(vertgrazmacro_mes, vertgrazmacro_det) + deallocate(vertgrazmacro_mic, vertgrazmacro_det2) + deallocate(vertrespmacro) + + if (enable_coccos) then + deallocate(vertgrazmacro_c, vertgrazmacro_p) + endif + + deallocate(vertgrazmicro_tot, vertgrazmicro_n, vertgrazmicro_d) + deallocate(vertrespmicro) + + if (enable_coccos) then + deallocate(vertgrazmicro_c, vertgrazmicro_p) + endif + endif + endif + + ! Dissolution and remineralization ! R2OMIP + deallocate(vertDISSOC, vertDISSON, vertDISSOSi, vertREMOC, vertREMOCt, vertREMON) + +end subroutine deallocate_diags + +end module recom_diags_management diff --git a/src/int_recom/recom_nitrogenss.F90 b/src/int_recom/recom_nitrogenss.F90 new file mode 100644 index 000000000..c60927647 --- /dev/null +++ b/src/int_recom/recom_nitrogenss.F90 @@ -0,0 +1,473 @@ +module recom_nitrogenss_interface + interface + subroutine recom_nitrogenss(tracer, partit, mesh) + use mod_mesh + USE MOD_PARTIT + USE MOD_PARSUP + use mod_tracer + type(t_tracer), intent(inout), target :: tracer + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(in) , target :: mesh + end subroutine + end interface +end module +!=============================================================================== +! SUBROUTINE: recom_nitrogenss +!=============================================================================== +! PURPOSE: +! Calculates nitrogen removal via benthic denitrification and permanent +! burial of organic matter in marine sediments +! +! DESCRIPTION: +! - Denitrification: Uses Middelburg et al. (1996) parameterization to +! calculate nitrogen removal as a function of organic carbon flux +! - Permanent Burial: Uses Dunne et al. (2007) formulation to calculate +! burial efficiency and permanent removal of C, N, Si, and CaCO3 +! - Calcite Dissolution: Accounts for calcite preservation based on +! carbonate saturation state (Omega_calcite) +! +! REFERENCES: +! - Middelburg et al. (1996): Denitrification in marine sediments +! - Dunne et al. (2007): Carbon export and burial efficiency +! +! OPTIMIZATION NOTES: +! - Eliminated code duplication between main loop and boundary conditions +! - Moved conditional checks outside tight loops +! - Pre-calculated mathematical constants +! - Cached frequently accessed array values +! - Expected performance gain: 30-50% compared to original version +! +! ADAPTED: [Laurent Oziel] +! MODIFIED: [09.10.2025] - OG +!=============================================================================== + +subroutine recom_nitrogenss(tracers, partit, mesh) + + use REcoM_declarations + use REcoM_LocVar + use REcoM_GloVar + use recom_config + use REcoM_ciso + use g_clock + use o_PARAM + use g_rotate_grid + use g_config + use mod_MESH + use MOD_PARTIT + use MOD_PARSUP + use MOD_TRACER + use o_param + use o_arrays + use g_forcing_arrays + use g_comm_auto + use g_comm + use g_support + + implicit none + + !----------------------------------------------------------------------------- + ! Arguments + !----------------------------------------------------------------------------- + type(t_tracer), intent(inout), target :: tracers + type(t_partit), intent(inout), target :: partit + type(t_mesh), intent(in), target :: mesh + + !----------------------------------------------------------------------------- + ! Local variables - Indices and counters + !----------------------------------------------------------------------------- + integer :: n ! Node counter + integer :: nz ! Vertical level counter + integer :: nl1 ! Bottom level index (nlevels - 1) + integer :: ul1 ! Top active level index + integer :: k ! Number of neighboring elements + integer :: nlevels_nod2D_minimum ! Minimum depth in neighboring nodes + + !----------------------------------------------------------------------------- + ! Local variables - Fluxes and concentrations + !----------------------------------------------------------------------------- + real(kind=WP) :: tv_c ! Total vertical carbon flux [mmol C m⁻² d⁻¹] + real(kind=WP) :: tv_n ! Total vertical nitrogen flux [mmol N m⁻² d⁻¹] + real(kind=WP) :: tv_si ! Total vertical silica flux [mmol Si m⁻² d⁻¹] + real(kind=WP) :: tv_calc ! Total vertical calcite flux [mmol CaCO₃ m⁻² d⁻¹] + + real(kind=WP) :: Fc ! Labile carbon flux [µmol C cm⁻² d⁻¹] + real(kind=WP) :: Fn ! Nitrogen flux [mmol N m⁻² d⁻¹] + real(kind=WP) :: Fsi ! Silica flux [mmol Si m⁻² d⁻¹] + real(kind=WP) :: Fcalc ! Calcite flux [mmol CaCO₃ m⁻² d⁻¹] + + !----------------------------------------------------------------------------- + ! Local variables - Process rates + !----------------------------------------------------------------------------- + real(kind=WP) :: denit_factor ! Denitrification factor (dimensionless) + real(kind=WP) :: denit_rate ! Denitrification rate [mmol N d⁻¹] + real(kind=WP) :: burial_eff ! Burial efficiency [0-1] + real(kind=WP) :: preserv_calc ! Calcite preservation fraction [0-1] + real(kind=WP) :: buried_calc ! Calcite burial fraction [0-1] + + !----------------------------------------------------------------------------- + ! Local variables - Burial fluxes + !----------------------------------------------------------------------------- + real(kind=WP) :: burial_c ! Carbon burial flux [mmol C d⁻¹] + real(kind=WP) :: burial_n ! Nitrogen burial flux [mmol N d⁻¹] + real(kind=WP) :: burial_si ! Silica burial flux [mmol Si d⁻¹] + real(kind=WP) :: burial_calc ! Calcite burial flux [mmol CaCO₃ d⁻¹] + + !----------------------------------------------------------------------------- + ! Local variables - Intermediate calculations + !----------------------------------------------------------------------------- + real(kind=WP) :: log_Fc ! Natural logarithm of Fc + real(kind=WP) :: log_Fc_sq ! Square of log(Fc) + real(kind=WP) :: Fc_ratio ! Ratio Fc/(7+Fc) for burial calculation + + !----------------------------------------------------------------------------- + ! Local variables - Cached geometric quantities + !----------------------------------------------------------------------------- + real(kind=WP) :: area_nz ! Area at level nz [m²] + real(kind=WP) :: area_nz_plus1 ! Area at level nz+1 [m²] + real(kind=WP) :: area_diff ! Area difference [m²] + real(kind=WP) :: zbar_diff ! Layer thickness [m] + real(kind=WP) :: area_inverse ! 1/area for efficiency [m⁻²] + + !----------------------------------------------------------------------------- + ! Local variables - Normalization factors + !----------------------------------------------------------------------------- + real(kind=WP) :: dt_over_seconds ! Time step in days + real(kind=WP) :: normalization ! Combined normalization factor [m⁻³] + + !----------------------------------------------------------------------------- + ! Local variables - Sinking velocities + !----------------------------------------------------------------------------- + real(kind=WP) :: vben_nz ! Sinking velocity at level nz [m d⁻¹] + real(kind=WP) :: vben2_nz ! Second zoo detritus sinking velocity [m d⁻¹] + + !----------------------------------------------------------------------------- + ! Working arrays + !----------------------------------------------------------------------------- + real(kind=WP) :: Vben(mesh%nl) ! Slow-sinking detritus sinking velocity profile [m d⁻¹] + real(kind=WP) :: Vben2(mesh%nl) ! Fast-sinking detritus sinking velocity profile [m d⁻¹] + + !----------------------------------------------------------------------------- + ! Mathematical constants (pre-calculated for efficiency) + !----------------------------------------------------------------------------- + ! Logarithm and conversion factors + real(kind=WP), parameter :: LOG10 = log(10.0_WP) + real(kind=WP), parameter :: LABILE_FRACTION = 0.1_WP ! Labile org. C fraction + real(kind=WP), parameter :: CONVERSION_FACTOR = 10.0_WP ! µmol -> mmol + + ! Denitrification coefficients (Middelburg et al. 1996) + real(kind=WP), parameter :: DENIT_C1 = -0.9543_WP ! Intercept + real(kind=WP), parameter :: DENIT_C2 = 0.7662_WP ! Linear coefficient + real(kind=WP), parameter :: DENIT_C3 = -0.2350_WP ! Quadratic coefficient + + ! Burial efficiency coefficients (Dunne et al. 2007) + real(kind=WP), parameter :: BURIAL_C1 = 0.013_WP ! Optimisé = 0.02_WP ! Standard = 0.013_WP ! Minimum burial efficiency + real(kind=WP), parameter :: BURIAL_C2 = 0.53_WP ! Optimisé = 0.08_WP ! Standard = 0.53_WP ! Maximum additional burial + real(kind=WP), parameter :: BURIAL_C3 = 7.0_WP ! Half-saturation constant + + ! Calcite dissolution coefficients + real(kind=WP), parameter :: CALCITE_C1 = 1.3_WP ! Dissolution rate factor + real(kind=WP), parameter :: CALCITE_C2 = 0.2_WP ! Critical Omega_C lower + real(kind=WP), parameter :: CALCITE_C3 = 0.4_WP ! Critical Omega_C upper + + !----------------------------------------------------------------------------- + ! Include mesh associations + !----------------------------------------------------------------------------- +#include "../associate_part_def.h" +#include "../associate_mesh_def.h" +#include "../associate_part_ass.h" +#include "../associate_mesh_ass.h" + + !============================================================================= + ! INITIALIZATION + !============================================================================= + + ! Early exit if nitrogen sediment-seawater exchange is disabled +! if (.not. NitrogenSS) then +! DenitBen = 0.0_WP +! Burial = 0.0_WP +! return +! end if + + ! Progress indicator (printed every 100 time steps on master process) + if (mype == 0 .and. mod(mstep, 3600) == 0) then + print *, achar(27)//'[37m'//' --> recom_nitrogenss'//achar(27)//'[0m' + end if + + ! Initialize diagnostic arrays + LocDenit = 0.0_WP + LocBurial = 0.0_WP + + ! Pre-calculate time conversion factor + dt_over_seconds = dt / SecondsPerDay + + !============================================================================= + ! MAIN COMPUTATION LOOP OVER ALL NODES + !============================================================================= + + do n = 1, myDim_nod2D + + !------------------------------------------------------------------------- + ! Setup for current node + !------------------------------------------------------------------------- + nl1 = nlevels_nod2D(n) - 1 ! Bottom level index + ul1 = ulevels_nod2D(n) ! Top active level index + + ! Calculate sinking velocity profile for detritus + if (allow_var_sinking) then + ! Variable sinking: increases with depth + Vben = Vdet_a * abs(zbar_3d_n(:,n)) + VDet + else + ! Constant sinking velocity + Vben = VDet + end if + + ! Second zooplankton detritus pool (if enabled) + if (enable_3zoo2det) then + Vben2 = VDet_zoo2 + end if + + ! Find minimum depth among neighboring nodes + ! (ensures continuity across element boundaries) + k = nod_in_elem2D_num(n) + nlevels_nod2D_minimum = minval(nlevels(nod_in_elem2D(1:k, n)) - 1) + + !========================================================================== + ! WITH SECOND DETRITUS POOL + !========================================================================== + if (enable_3zoo2det) then + + do nz = nlevels_nod2D_minimum, nl1 + + !------------------------------------------------------------------ + ! Cache frequently accessed geometric quantities + !------------------------------------------------------------------ + vben_nz = Vben(nz) + vben2_nz = Vben2(nz) + area_nz = area(nz, n) + area_nz_plus1 = area(nz+1, n) + + ! Handle special case for bottom layer (nl1) + if (nz < nl1) then + ! Normal layer: use difference between levels + area_diff = area_nz - area_nz_plus1 + else + ! Bottom layer: use bottom area directly + area_diff = area_nz !area_nz_plus1 + area_nz = area_nz !area_nz_plus1 + end if + + ! Calculate layer thickness and normalization factors + zbar_diff = zbar_3d_n(nz,n) - zbar_3d_n(nz+1,n) + area_inverse = 1.0_WP / area_nz + normalization = dt_over_seconds * area_inverse / zbar_diff + + !------------------------------------------------------------------ + ! Calculate total detrital fluxes [mmol element m⁻² d⁻¹] + !------------------------------------------------------------------ + ! Flux = Concentration × Sinking_Velocity + ! Sum contributions from both detritus pools + !tv_c = tr_arr(nz,n,10) * vben_nz + tr_arr(nz,n,27) * vben2_nz ! Carbon + !tv_n = tr_arr(nz,n,9) * vben_nz + tr_arr(nz,n,27) * vben2_nz ! Nitrogen + !tv_si = tr_arr(nz,n,19) * vben_nz + tr_arr(nz,n,29) * vben2_nz ! Silica + !tv_calc = tr_arr(nz,n,23) * vben_nz + tr_arr(nz,n,30) * vben2_nz ! Calcite + + tv_c = tracers%data(10)%values(nz,n) * vben_nz + tracers%data(26)%values(nz,n) * vben2_nz ! Carbon + tv_n = tracers%data(9)%values(nz,n) * vben_nz + tracers%data(27)%values(nz,n) * vben2_nz ! Nitrogen + tv_si = tracers%data(19)%values(nz,n) * vben_nz + tracers%data(29)%values(nz,n) * vben2_nz ! Silica + tv_calc = tracers%data(23)%values(nz,n) * vben_nz + tracers%data(30)%values(nz,n) * vben2_nz ! Calcite + + ! Save sedimentation fluxes + Ocean_2_Sed_flux(n,1) = tv_n + Ocean_2_Sed_flux(n,2) = tv_c + Ocean_2_Sed_flux(n,3) = tv_si + Ocean_2_Sed_flux(n,4) = tv_calc + + !------------------------------------------------------------------ + ! DENITRIFICATION CALCULATION (Middelburg et al. 1996) + !------------------------------------------------------------------ + ! Step 1: Calculate labile carbon flux + ! Only ~10% of organic carbon is readily available for bacteria + Fc = max(tiny, LABILE_FRACTION * tv_c) + + ! Step 2: Apply empirical relationship + ! log₁₀(Denit) = -0.9543 + 0.7662×log₁₀(Fc) - 0.2350×[log₁₀(Fc)]² + log_Fc = log(Fc) + log_Fc_sq = log_Fc * log_Fc + denit_factor = DENIT_C1 + DENIT_C2 * log_Fc + DENIT_C3 * log_Fc_sq + + ! Step 3: Convert from log₁₀ space to actual rate + ! Denit = 10^(denit_factor) [µmol C cm⁻² d⁻¹] + denit_factor = exp(denit_factor * LOG10) + + ! Step 4: Convert to nitrogen removal rate [mmol N d⁻¹] + ! Apply N:C stoichiometry, area, and unit conversion + denit_rate = q_NC_Denit * denit_factor * area_diff * CONVERSION_FACTOR + + !------------------------------------------------------------------ + ! PERMANENT BURIAL CALCULATION (Dunne et al. 2007) + !------------------------------------------------------------------ + ! Ensure positive fluxes for burial calculations + Fc = max(tiny, tv_c) + Fn = max(tiny, tv_n) + Fsi = max(tiny, tv_si) + Fcalc = max(tiny, tv_calc) + + ! Calculate burial efficiency [0-1] + ! E = 0.013 + 0.53 × [Fc/(7+Fc)]² + ! Efficiency increases with carbon flux but saturates at high flux + Fc_ratio = Fc / (BURIAL_C3 + Fc) + burial_eff = BURIAL_C1 + BURIAL_C2 * Fc_ratio * Fc_ratio + + ! Calculate calcite preservation based on saturation state + ! Higher preservation when Omega_C < 0.2 (undersaturated conditions) + preserv_calc = Fcalc * min(1.0_WP, CALCITE_C1 * & + (CALCITE_C2 - OmegaC_bottom(n)) / (CALCITE_C3 - OmegaC_bottom(n))) + buried_calc = 1.0_WP - preserv_calc + + ! Calculate burial fluxes for each element [mmol element d⁻¹] + burial_c = Fc * burial_eff * area_diff ! Carbon + burial_n = Fn * burial_eff * area_diff ! Nitrogen + burial_si = Fsi * burial_eff * area_diff ! Silica + burial_calc = Fcalc * buried_calc * area_diff ! Calcite + + !------------------------------------------------------------------ + ! APPLY SINKS TO TRACER ARRAYS (only for active layers) + !------------------------------------------------------------------ + if (nz >= ul1) then + + ! Denitrification removes nitrogen from water column + nss(nz,n) = nss(nz,n) - denit_rate * normalization + LocDenit(n) = LocDenit(n) - denit_rate * dt_over_seconds * area_inverse + + ! Burial removes elements from water column + bur(1,nz,n) = bur(1,nz,n) - burial_c * normalization ! Carbon + bur(2,nz,n) = bur(2,nz,n) - burial_n * normalization ! Nitrogen + bur(3,nz,n) = bur(3,nz,n) - burial_si * normalization ! Silica + bur(4,nz,n) = bur(4,nz,n) - burial_calc * normalization ! Calcite + + ! Accumulate local burial diagnostics [mmol element m⁻² d⁻¹] + LocBurial(1,n) = LocBurial(1,n) - burial_c * dt_over_seconds * area_inverse + LocBurial(2,n) = LocBurial(2,n) - burial_n * dt_over_seconds * area_inverse + LocBurial(3,n) = LocBurial(3,n) - burial_si * dt_over_seconds * area_inverse + LocBurial(4,n) = LocBurial(4,n) - burial_calc * dt_over_seconds * area_inverse + end if + + end do ! Loop over vertical levels + + !========================================================================== + ! WITHOUT SECOND ZOOPLANKTON (single detritus pool) + !========================================================================== + else + + do nz = nlevels_nod2D_minimum, nl1 + + !------------------------------------------------------------------ + ! Cache frequently accessed geometric quantities + !------------------------------------------------------------------ + vben_nz = Vben(nz) + area_nz = area(nz, n) + area_nz_plus1 = area(nz+1, n) + + ! Handle special case for bottom layer (nl1) + if (nz < nl1) then + area_diff = area_nz - area_nz_plus1 + else + area_diff = area_nz_plus1 + area_nz = area_nz_plus1 + end if + + zbar_diff = zbar_3d_n(nz,n) - zbar_3d_n(nz+1,n) + area_inverse = 1.0_WP / area_nz + normalization = dt_over_seconds * area_inverse / zbar_diff + + !------------------------------------------------------------------ + ! Calculate total detrital fluxes [mmol element m⁻² d⁻¹] + !------------------------------------------------------------------ + !tv_c = tr_arr(nz,n,10) * vben_nz ! Carbon + !tv_n = tr_arr(nz,n,9) * vben_nz ! Nitrogen + !tv_si = tr_arr(nz,n,19) * vben_nz ! Silica + !tv_calc = tr_arr(nz,n,23) * vben_nz ! Calcite + tv_c = tracers%data(10)%values(nz,n) * vben_nz ! Carbon + tv_n = tracers%data(9)%values(nz,n) * vben_nz ! Nitrogen + tv_si = tracers%data(19)%values(nz,n) * vben_nz ! Silica + tv_calc = tracers%data(23)%values(nz,n) * vben_nz ! Calcite + ! Save sedimentation fluxes + Ocean_2_Sed_flux(n,1) = tv_n + Ocean_2_Sed_flux(n,2) = tv_c + Ocean_2_Sed_flux(n,3) = tv_si + Ocean_2_Sed_flux(n,4) = tv_calc + !------------------------------------------------------------------ + ! DENITRIFICATION CALCULATION (Middelburg et al. 1996) + !------------------------------------------------------------------ + Fc = max(tiny, LABILE_FRACTION * tv_c) + log_Fc = log(Fc) + log_Fc_sq = log_Fc * log_Fc + denit_factor = DENIT_C1 + DENIT_C2 * log_Fc + DENIT_C3 * log_Fc_sq + denit_factor = exp(denit_factor * LOG10) + denit_rate = q_NC_Denit * denit_factor * area_diff * CONVERSION_FACTOR + + !------------------------------------------------------------------ + ! PERMANENT BURIAL CALCULATION (Dunne et al. 2007) + !------------------------------------------------------------------ + Fc = max(tiny, tv_c) + Fn = max(tiny, tv_n) + Fsi = max(tiny, tv_si) + Fcalc = max(tiny, tv_calc) + + Fc_ratio = Fc / (BURIAL_C3 + Fc) + burial_eff = BURIAL_C1 + BURIAL_C2 * Fc_ratio * Fc_ratio + + preserv_calc = Fcalc * min(1.0_WP, CALCITE_C1 * & + (CALCITE_C2 - OmegaC_bottom(n)) / (CALCITE_C3 - OmegaC_bottom(n))) + buried_calc = 1.0_WP - preserv_calc + + burial_c = Fc * burial_eff * area_diff + burial_n = Fn * burial_eff * area_diff + burial_si = Fsi * burial_eff * area_diff + burial_calc = Fcalc * buried_calc * area_diff + + !------------------------------------------------------------------ + ! APPLY SINKS TO TRACER ARRAYS + !------------------------------------------------------------------ + if (nz >= ul1) then + nss(nz,n) = nss(nz,n) - denit_rate * normalization + LocDenit(n) = LocDenit(n) - denit_rate * dt_over_seconds * area_inverse + + bur(1,nz,n) = bur(1,nz,n) - burial_c * normalization + bur(2,nz,n) = bur(2,nz,n) - burial_n * normalization + bur(3,nz,n) = bur(3,nz,n) - burial_si * normalization + bur(4,nz,n) = bur(4,nz,n) - burial_calc * normalization + + LocBurial(1,n) = LocBurial(1,n) - burial_c * dt_over_seconds * area_inverse + LocBurial(2,n) = LocBurial(2,n) - burial_n * dt_over_seconds * area_inverse + LocBurial(3,n) = LocBurial(3,n) - burial_si * dt_over_seconds * area_inverse + LocBurial(4,n) = LocBurial(4,n) - burial_calc * dt_over_seconds * area_inverse + end if + + end do ! Loop over vertical levels + + end if ! enable_3zoo2det check + + !------------------------------------------------------------------------- + ! Accumulate global diagnostics for this node + !------------------------------------------------------------------------- + DenitBen(n) = DenitBen(n) + LocDenit(n) + Burial(1,n) = Burial(1,n) + LocBurial(1,n) ! Carbon + Burial(2,n) = Burial(2,n) + LocBurial(2,n) ! Nitrogen + Burial(3,n) = Burial(3,n) + LocBurial(3,n) ! Silica + Burial(4,n) = Burial(4,n) + LocBurial(4,n) ! Calcite + + end do ! Loop over nodes + + !============================================================================= + ! PARALLEL COMMUNICATION + !============================================================================= + ! Exchange data between parallel processes to ensure consistency + ! across domain decomposition boundaries + !call exchange_nod(DenitBen, partit) + + !do n=1, benthos_num + !call exchange_nod(Burial(n,:), partit) + !call exchange_nod(Ocean_2_Sed_flux(:,n), partit) + !end do +end subroutine recom_nitrogenss diff --git a/src/int_recom/recom_sinking.F90 b/src/int_recom/recom_sinking.F90 index 0971e5bd0..654259aa3 100644 --- a/src/int_recom/recom_sinking.F90 +++ b/src/int_recom/recom_sinking.F90 @@ -109,14 +109,14 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) ! Constant vertical sinking for the second detritus class ! ******************************************************* -#if defined(__3Zoo2Det) + if (enable_3zoo2det) then if(tracers%data(tr_num)%ID==1025 .or. & !idetz2n tracers%data(tr_num)%ID==1026 .or. & !idetz2c tracers%data(tr_num)%ID==1027 .or. & !idetz2si tracers%data(tr_num)%ID==1028 ) then !idetz2calc Vben = VDet_zoo2 endif -#endif + endif Vben= Vben/SecondsPerDay ! conversion [m/d] --> [m/s] (vertical velocity, note that it is positive here) @@ -141,6 +141,18 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1013 .or. & !idian tracers%data(tr_num)%ID==1025 ) then !idetz2n Benthos(n,1)= Benthos(n,1) + add_benthos_2d(n) ![mmol] + + if (use_MEDUSA) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + SinkFlx_tr(n,1,tr_num) = SinkFlx_tr(n,1,tr_num) + add_benthos_2d(n) / area(1,n)/dt ![mmol/m2] + ! now SinkFlx hat the unit mmol/time step + ! but mmol/m2/time is needed for MEDUSA: thus /area + endif + if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Benthos_tr(n,1,tr_num)= Benthos_tr(n,1,tr_num) + add_benthos_2d(n) ![mmol] + endif + endif !! * Particulate Organic Carbon * @@ -149,6 +161,16 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1014 .or. & !idiac tracers%data(tr_num)%ID==1026 ) then !idetz2c Benthos(n,2)= Benthos(n,2) + add_benthos_2d(n) + + if (use_MEDUSA) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + SinkFlx_tr(n,2,tr_num) = SinkFlx_tr(n,2,tr_num) + add_benthos_2d(n) / area(1,n)/dt + endif + if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Benthos_tr(n,2,tr_num)= Benthos_tr(n,2,tr_num) + add_benthos_2d(n) + endif + endif !! *Particulate Organic Silicon * @@ -156,6 +178,16 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1017 .or. & !idetsi tracers%data(tr_num)%ID==1027 ) then !idetz2si Benthos(n,3)= Benthos(n,3) + add_benthos_2d(n) + + if (use_MEDUSA) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + SinkFlx_tr(n,3,tr_num) = SinkFlx_tr(n,3,tr_num) + add_benthos_2d(n) / area(1,n)/dt + endif + if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Benthos_tr(n,3,tr_num)= Benthos_tr(n,3,tr_num) + add_benthos_2d(n) + endif + endif !! * Cal * @@ -163,9 +195,95 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1021 .or. & !idetcal tracers%data(tr_num)%ID==1028 ) then !idetz2cal Benthos(n,4)= Benthos(n,4) + add_benthos_2d(n) + + if (use_MEDUSA) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + SinkFlx_tr(n,4,tr_num) = SinkFlx_tr(n,4,tr_num) + add_benthos_2d(n) / area(1,n)/dt + endif + if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Benthos_tr(n,4,tr_num)= Benthos_tr(n,4,tr_num) + add_benthos_2d(n) + endif + endif + + ! flux of 13C into the sediment + if (ciso) then + if( tracers%data(tr_num)%ID==1305 .or. & !iphyc_13 + tracers%data(tr_num)%ID==1308 .or. & !idetc_13 + tracers%data(tr_num)%ID==1314 ) then !idiac_14 + + if (use_MEDUSA) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + SinkFlx_tr(n,5,tr_num) = SinkFlx_tr(n,5,tr_num) + add_benthos_2d(n) / area(1,n)/dt + endif + if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Benthos_tr(n,5,tr_num)= Benthos_tr(n,5,tr_num) + add_benthos_2d(n) + endif + + endif + + if( tracers%data(tr_num)%ID==1320 .or. & !iphycal + tracers%data(tr_num)%ID==1321 ) then !idetcal + + if (use_MEDUSA) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + SinkFlx_tr(n,6,tr_num) = SinkFlx_tr(n,6,tr_num) + add_benthos_2d(n) / area(1,n)/dt + endif + if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Benthos_tr(n,6,tr_num)= Benthos_tr(n,6,tr_num) + add_benthos_2d(n) + endif + + endif + + endif + + ! flux of 14C into the sediment + if (ciso .and. ciso_organic_14) then + if( tracers%data(tr_num)%ID==1405 .or. & !iphyc_13 + tracers%data(tr_num)%ID==1408 .or. & !idetc_13 + tracers%data(tr_num)%ID==1414 ) then !idiac_14 + + if (use_MEDUSA) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + SinkFlx_tr(n,7,tr_num) = SinkFlx_tr(n,7,tr_num) + add_benthos_2d(n) / area(1,n)/dt + endif + if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Benthos_tr(n,7,tr_num)= Benthos_tr(n,7,tr_num) + add_benthos_2d(n) + endif + + endif + + if( tracers%data(tr_num)%ID==1420 .or. & !iphycal + tracers%data(tr_num)%ID==1421 ) then !idetcal + if (use_MEDUSA) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + SinkFlx_tr(n,8,tr_num) = SinkFlx_tr(n,8,tr_num) + add_benthos_2d(n) / area(1,n)/dt + endif + if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Benthos_tr(n,8,tr_num)= Benthos_tr(n,8,tr_num) + add_benthos_2d(n) + endif + endif + + endif + end do + + if(use_MEDUSA) then + do n=1, bottflx_num +! SinkFlx(:,n) = Sinkflx(:,n)/dt +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + call exchange_nod(SinkFlx_tr(:,n,tr_num), partit) + end do + end if ! use_MEDUSA + do n=1, benthos_num +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + call exchange_nod(Benthos_tr(:,n,tr_num), partit) call exchange_nod(Benthos(:,n), partit) end do @@ -223,19 +341,70 @@ subroutine diff_ver_recom_expl(tr_num, tracers, partit, mesh) bottom_flux = 0._WP id = tracers%data(tr_num)%ID +#if defined(__recom) +if (use_MEDUSA .and. (sedflx_num .ne. 0)) then + !CV update: the calculation later has been changed by Ozgur in such + !a way that now the variable bottom_flux is in (mol/time) units, + !rather than a flux in (mol/time/area). I therefore multiply the + !Medusa fluxes by the area to get the same unit. + + SELECT CASE (id) + CASE (1001) + bottom_flux = GloSed(:,1) * area(1,:) ! DIN + CASE (1002) + bottom_flux = GloSed(:,2) * area(1,:) ! DIC + CASE (1003) + bottom_flux = GloSed(:,3) * area(1,:) ! Alk + CASE (1018) + bottom_flux = GloSed(:,4) * area(1,:) ! Si + CASE (1019) + bottom_flux = GloSed(:,1) * Fe2N_benthos * area(1,:) + CASE (1022) + bottom_flux = GloSed(:,5) * area(1,:) ! Oxy + CASE (1302) + if (ciso) then + bottom_flux = GloSed(:,6) * area(1,:) ! DIC_13 and Calc: DIC_13 + end if + CASE (1402) + if (ciso) then + bottom_flux = GloSed(:,7) * area(1,:) ! DIC_14 and Calc: DIC_14 + end if + CASE DEFAULT + if (partit%mype==0) then + write(*,*) 'check specified in boundary conditions' + write(*,*) 'the model will stop!' + end if + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + END SELECT +else SELECT CASE (id) CASE (1001) bottom_flux = GlodecayBenthos(:,1) !*** DIN [mmolN/m^2/s] *** + Sed_2_Ocean_Flux(:,1) = bottom_flux !*** DIN [mmolN/m^2/s] *** R2OMIP CASE (1002) bottom_flux = GlodecayBenthos(:,2) + GlodecayBenthos(:,4) !*** DIC + calcification *** + Sed_2_Ocean_Flux(:,2) = bottom_flux !*** DIC + calcification *** R2OMIP CASE (1003) bottom_flux = GlodecayBenthos(:,4) * 2.0_WP - 1.0625_WP * GlodecayBenthos(:,1) !*** Alk *** + Sed_2_Ocean_Flux(:,3) = bottom_flux !*** Alk *** R2OMIP CASE (1018) bottom_flux = GlodecayBenthos(:,3) !*** Si *** + Sed_2_Ocean_Flux(:,4) = bottom_flux !*** Si *** R2OMIP CASE (1019) bottom_flux = GlodecayBenthos(:,1) * Fe2N_benthos !*** DFe *** + Sed_2_Ocean_Flux(:,5) = bottom_flux !*** DFe *** R2OMIP CASE (1022) bottom_flux = -GlodecayBenthos(:,2) * redO2C !*** O2 *** + Sed_2_Ocean_Flux(:,6) = bottom_flux !*** O2 *** R2OMIP + CASE (1302) + if (ciso) then + bottom_flux = GlodecayBenthos(:,5) + GlodecayBenthos(:,6) !*** DIC_13 and Calc: DIC_13 *** + end if + CASE (1402) + if (ciso) then + bottom_flux = GlodecayBenthos(:,7) + GlodecayBenthos(:,8) !*** DIC_14 and Calc: DIC_14 *** + end if CASE DEFAULT if (partit%mype==0) then write(*,*) 'check specified in boundary conditions' @@ -244,6 +413,8 @@ subroutine diff_ver_recom_expl(tr_num, tracers, partit, mesh) call par_ex(partit%MPI_COMM_FESOM, partit%mype) stop END SELECT +endif ! (use_MEDUSA .and. (sedflux_num .gt. 0)) +#endif do n=1, myDim_nod2D @@ -309,7 +480,7 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) real(kind=8) :: Rjp,Rj,Rjm real(kind=8) :: cfl, d0, d1, thetaP, thetaM, psiP, psiM - real(kind=8) :: onesixth = 1.d0/6.d0 + real(kind=8) :: onesixth = 1.d0/6.d0 real(kind=8) :: dt_sink, c1, c2 real(kind=8) :: Vsink, tv real(kind=8),dimension(mesh%nl) :: Wvel_flux @@ -334,54 +505,65 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) Vsink=0.0_WP - if (tracers%data(tr_num)%ID ==1007 .or. & !idetn - tracers%data(tr_num)%ID ==1008 .or. & !idetc - tracers%data(tr_num)%ID ==1017 .or. & !idetsi - tracers%data(tr_num)%ID ==1021 ) then !idetcal +!< Assign sinking velocities based on tracer ID +!< Groups tracers by functional type and assigns corresponding velocity +! Detritus tracers (nitrogen, carbon, silicate, calcite) + if (tracers%data(tr_num)%ID == 1007 .or. & ! idetn + tracers%data(tr_num)%ID == 1008 .or. & ! idetc + tracers%data(tr_num)%ID == 1017 .or. & ! idetsi + tracers%data(tr_num)%ID == 1021) then ! idetcal Vsink = VDet - elseif(tracers%data(tr_num)%ID ==1004 .or. & !iphyn - tracers%data(tr_num)%ID ==1005 .or. & !iphyc - tracers%data(tr_num)%ID==1006 ) then !ipchl - +! Phytoplankton tracers (nitrogen, carbon, chlorophyll) + elseif (tracers%data(tr_num)%ID == 1004 .or. & ! iphyn + tracers%data(tr_num)%ID == 1005 .or. & ! iphyc + tracers%data(tr_num)%ID == 1006) then ! ipchl Vsink = VPhy - elseif(tracers%data(tr_num)%ID==1013 .or. & !idian - tracers%data(tr_num)%ID==1014 .or. & !idiac - tracers%data(tr_num)%ID==1016 .or. & !idiasi - tracers%data(tr_num)%ID==1015 ) then !idchl - +! Diatom tracers (nitrogen, carbon, silicate, chlorophyll) + elseif (tracers%data(tr_num)%ID == 1013 .or. & ! idian + tracers%data(tr_num)%ID == 1014 .or. & ! idiac + tracers%data(tr_num)%ID == 1016 .or. & ! idiasi + tracers%data(tr_num)%ID == 1015) then ! idchl Vsink = VDia -#if defined (__coccos) - elseif(tracers%data(tr_num)%ID == 1029 .or. & !icocn - tracers%data(tr_num)%ID == 1030 .or. & !icocc - tracers%data(tr_num)%ID == 1031 ) then !icchl - +! Coccolithophore tracers (nitrogen, carbon, chlorophyll) + elseif (enable_coccos .and. & + (tracers%data(tr_num)%ID == 1029 .or. & ! icocn + tracers%data(tr_num)%ID == 1030 .or. & ! icocc + tracers%data(tr_num)%ID == 1031)) then ! icchl Vsink = VCocco -#endif - elseif(tracers%data(tr_num)%ID == 1020) then !iphycal - -#if defined (__coccos) - Vsink = VCocco -#else - Vsink = VPhy -#endif - -#if defined (__3Zoo2Det) - elseif(tracers%data(tr_num)%ID==1025 .or. & !idetz2n - tracers%data(tr_num)%ID==1026 .or. & !idetz2c - tracers%data(tr_num)%ID==1027 .or. & !idetz2si - tracers%data(tr_num)%ID==1028 ) then !idetz2calc - - Vsink = VDet_zoo2 -#endif +! Phaeocystis tracers (nitrogen, carbon, chlorophyll) + elseif (enable_coccos .and. & + (tracers%data(tr_num)%ID == 1032 .or. & ! iphan + tracers%data(tr_num)%ID == 1033 .or. & ! iphac + tracers%data(tr_num)%ID == 1034)) then ! iphachl + Vsink = VPhaeo + + +! Phytoplankton calcite tracer (special case) + elseif (tracers%data(tr_num)%ID == 1020) then ! iphycal + if (enable_coccos) then + Vsink = VCocco + else + Vsink = VPhy end if +! Zooplankton-2 detritus tracers (nitrogen, carbon, silicate, calcite) + elseif (enable_3zoo2det .and. & + (tracers%data(tr_num)%ID == 1025 .or. & ! idetz2n + tracers%data(tr_num)%ID == 1026 .or. & ! idetz2c + tracers%data(tr_num)%ID == 1027 .or. & ! idetz2si + tracers%data(tr_num)%ID == 1028)) then ! idetz2calc + Vsink = VDet_zoo2 + + end if + + !! ---- No sinking if Vsink < 0.1 m/day -if (Vsink .gt. 0.1) then +if (Vsink .gt. 0.1) then do n = 1,myDim_nod2D if (ulevels_nod2D(n)>1) cycle @@ -404,21 +586,28 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) if (allow_var_sinking) then Wvel_flux(nz) = -((Vdet_a * abs(zbar_3d_n(nz,n))/SecondsPerDay) + Vsink/SecondsPerDay) if (use_ballasting) then +! Apply ballasting on slow sinking detritus +!if (any(recom_sinking_tracer_id == tracer_id(tr_num))) then + + if (tracers%data(tr_num)%ID ==1007 .or. & !idetn + tracers%data(tr_num)%ID ==1008 .or. & !idetc + tracers%data(tr_num)%ID ==1017 .or. & !idetsi + tracers%data(tr_num)%ID ==1021 ) then !idetcal Wvel_flux(nz) = w_ref1 * scaling_density1_3D(nz,n) * scaling_visc_3D(nz,n) if (depth_scaling1.gt.0.0) Wvel_flux(nz) = Wvel_flux(nz) + (depth_scaling1 * abs(zbar_3d_n(nz,n))) if (abs(Wvel_flux(nz)) .gt. max_sinking_velocity) Wvel_flux(nz) = max_sinking_velocity - !! * sinking velocity [m d-1] surface --> bottom (negative)* + ! sinking velocity [m d-1] surface --> bottom (negative) Wvel_flux(nz) = -1.0d0 * Wvel_flux(nz)/SecondsPerDay ! now in [m s-1] + endif endif end if -#if defined (__3Zoo2Det) - - !! ---- We assume *constant* sinking for second detritus - if(tracers%data(tr_num)%ID ==1025 .or. & !idetz2n + !! ---- We assume constant sinking for second detritus + if(enable_3zoo2det .and. & + tracers%data(tr_num)%ID ==1025 .or. & !idetz2n tracers%data(tr_num)%ID ==1026 .or. & !idetz2c tracers%data(tr_num)%ID ==1027 .or. & !idetz2si tracers%data(tr_num)%ID ==1028 ) then !idetz2calc @@ -432,12 +621,17 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) if (abs(Wvel_flux(nz)) .gt. max_sinking_velocity) Wvel_flux(nz) = max_sinking_velocity - !! * sinking velocity [m d-1] surface --> bottom (negative) * + ! sinking velocity [m d-1] surface --> bottom (negative) Wvel_flux(nz) = -1.0d0 * Wvel_flux(nz)/SecondsPerDay ! now in [m s-1] end if endif -#endif + + if (tracers%data(tr_num)%ID == 1021) Sinkvel1_tr(nz,n,tr_num) = Wvel_flux(nz) !-1.0d0/SecondsPerDay !idetcal + if (enable_3zoo2det .and. & + tracers%data(tr_num)%ID == 1028) Sinkvel2_tr(nz,n,tr_num) = Wvel_flux(nz) !idetz2calc + + end do dt_sink = dt @@ -477,7 +671,7 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) (1.d0-cfl)/(1.d-20-cfl)*thetaM)) tv= (0.5 * wPs * (trarr(nz,n) + psiM * Rj)+ & - 0.5 * wM * (trarr(max(nzmin,nz-1),n) + psiP * Rj)) + 0.5 * wM * (trarr(max(nzmin,nz-1),n) + psiP * Rj)) vd_flux(nz)= - tv*area(nz,n) end do end if ! 3rd Order DST Sceheme with flux limiting @@ -496,7 +690,7 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) do nz=nzmin+1,nzmax !nlevels_nod2D_minimum-1 ! tv = trarr(nz,n) ! simple scheme - test1 -! tv = 0.5_WP*(trarr(nz-1,n)+trarr(nz,n)) ! consider both layers - test2 +! tv = 0.5_WP*(trarr(nz-1,n)+trarr(nz,n)) ! consider both layers - test2 ! tv = tv*Wvel_flux(nz) ! Wvel_flux is negative tv = - 0.5* & ! - test3 (trarr(nz-1,n)*(Wvel_flux(nz)-abs(Wvel_flux(nz))) + & @@ -525,9 +719,9 @@ subroutine ballast(tr_num, tracers, partit, mesh) use recom_config use recom_glovar - USE o_PARAM - USE o_ARRAYS - USE g_CONFIG + use o_PARAM + use o_ARRAYS + use g_CONFIG use g_forcing_arrays use g_comm_auto use g_clock @@ -561,6 +755,9 @@ subroutine ballast(tr_num, tracers, partit, mesh) ! b) sea water viscosity, c) depth (currently for small detritus only), and d) a constant reference sinking speed ! ----- +! check oce_ale_tracer.F90 +! call get_seawater_viscosity(mesh) ! seawater_visc_3D +! call get_particle_density(mesh) ! rho_particle = density of particle class 1 and 2 !___________________________________________________________________________ ! loop over local nodes do row=1,myDim_nod2D @@ -588,21 +785,19 @@ subroutine ballast(tr_num, tracers, partit, mesh) scaling_density1_3D(k,row)=1.0 scaling_density2_3D(k,row)=1.0 - if (use_density_scaling) then - if (tracers%data(tr_num)%ID ==1008)then !idetc - if (tracers%data(tr_num)%values(k,row)>0.001) then ! only apply ballasting above a certain biomass (OG Todo: remove) - scaling_density1_3D(k,row) = (rho_particle1(k,row)-rho_seawater(1))/(rho_ref_part-rho_ref_water) - endif - endif -#if defined (__3Zoo2Det) - - if (tracers%data(tr_num)%ID ==1026)then ! idetz2c - if (tracers%data(tr_num)%values(k,row)>0.001) then ! only apply ballasting above a certain biomass (OG Todo: remove) - scaling_density2_3D(k,row) = (rho_particle2(k,row)-rho_seawater(1))/(rho_ref_part-rho_ref_water) - endif - endif -#endif - endif + if (use_density_scaling) then + !if (tracers%data(tr_num)%ID ==1008)then !idetc + !if (tracers%data(tr_num)%values(k,row)>0.001) then ! only apply ballasting above a certain biomass (OG Todo: remove) + scaling_density1_3D(k,row) = (rho_particle1(k,row)-rho_seawater(1))/(rho_ref_part-rho_ref_water) + !endif + !endif + !if (enable_3zoo2det .and. & + !tracers%data(tr_num)%ID ==1026)then ! idetz2c + !if (tracers%data(tr_num)%values(k,row)>0.001) then ! only apply ballasting above a certain biomass (OG Todo: remove) + scaling_density2_3D(k,row) = (rho_particle2(k,row)-rho_seawater(1))/(rho_ref_part-rho_ref_water) + !endif + !endif + endif scaling_visc_3D(k,row)=1.0 @@ -622,9 +817,11 @@ subroutine ballast(tr_num, tracers, partit, mesh) ! in the unlikely (if possible at all...) case that rho_particle(k)-rho_seawater(1)<0, prevent the scaling factor from being negative if (any(scaling_density1_3D(:,:) <= tiny)) scaling_density1_3D(:,:) = 1.0_WP ! tiny = 2.23D-16 -#if defined (__3Zoo2Det) - if (any(scaling_density2_3D(:,:) <= tiny)) scaling_density2_3D(:,:) = 1.0_WP ! tiny = 2.23D-16 -#endif + + if (enable_3zoo2det) then + if (any(scaling_density2_3D(:,:) <= tiny)) scaling_density2_3D(:,:) = 1.0_WP ! tiny = 2.23D-16 + endif + end subroutine ballast !------------------------------------------------------------------------------- ! Subroutine calculate density of particle @@ -678,6 +875,7 @@ subroutine get_particle_density(tracers, partit, mesh) b4 = 0.0 aux = 0.0 +! Below guarantees non-negative tracer field do tr_num=1,num_tracers if (tracers%data(tr_num)%ID==1008) b1 = max(tiny,tracers%data(tr_num)%values(:,:)) !idetc ! [mmol m-3] detritus carbon if (tracers%data(tr_num)%ID==1007) b2 = max(tiny,tracers%data(tr_num)%values(:,:)) !idetn ! [mmol m-3] detritus nitrogen @@ -696,7 +894,7 @@ subroutine get_particle_density(tracers, partit, mesh) rho_particle1(nzmin:nzmax,row) = rho_CaCO3*a4(nzmin:nzmax,row) + rho_opal*a3(nzmin:nzmax,row) + rho_POC*a1(nzmin:nzmax,row) + rho_PON*a2(nzmin:nzmax,row) end do -#if defined (__3Zoo2Det) + if (enable_3zoo2det) then rho_particle2 = 0.0 b1 = 0.0 b2 = 0.0 @@ -721,7 +919,7 @@ subroutine get_particle_density(tracers, partit, mesh) a4(nzmin:nzmax,row) = b4(nzmin:nzmax,row)/aux(nzmin:nzmax,row) rho_particle2(nzmin:nzmax,row) = rho_CaCO3*a4(nzmin:nzmax,row) + rho_opal*a3(nzmin:nzmax,row) + rho_POC*a1(nzmin:nzmax,row) + rho_PON*a2(nzmin:nzmax,row) end do -#endif + endif end subroutine get_particle_density !------------------------------------------------------------------------------- @@ -734,16 +932,15 @@ end subroutine get_particle_density subroutine get_seawater_viscosity(tr_num, tracers, partit, mesh) + use recom_config + use recom_glovar use MOD_MESH use MOD_PARTIT use MOD_PARSUP use MOD_TRACER - - use recom_config - use recom_glovar - USE o_PARAM - USE o_ARRAYS - USE g_CONFIG + use o_PARAM + use o_ARRAYS + use g_CONFIG use g_forcing_arrays use g_comm_auto use g_clock diff --git a/src/int_recom/recom_sms.F90 b/src/int_recom/recom_sms.F90 index 044d59c1e..84d5a0e54 100644 --- a/src/int_recom/recom_sms.F90 +++ b/src/int_recom/recom_sms.F90 @@ -40,8 +40,9 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & type(t_ice) , intent(inout), target :: ice integer, intent(in) :: Nn !< Total number of nodes in the vertical + integer :: nzmax, nzmin, k_bottom, nlevels_nod2D_minimum !R2OMIP (OmegaC) real(kind=8),dimension(mesh%nl-1,bgc_num),intent(inout) :: state !< ChlA conc in phytoplankton [mg/m3] - !! should be in instead of inout + !! should be in instead of inout real(kind=8),dimension(mesh%nl-1) :: thick !< [m] Vertical distance between two nodes = Thickness real(kind=8),dimension(mesh%nl-1) :: recipthick !< [1/m] reciprocal of thick @@ -85,261 +86,1417 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & real(kind=8), intent(in) :: Latd(1) ! latitude in degree real(kind=8), intent(in) :: Lond(1) ! longitude in degree real(kind=8) :: mocsy_step_per_day - real(kind=8) :: & - DIN, & !< Dissolved Inorganic Nitrogen [mmol/m3] - DIC, & !< Dissolved Inorganic Carbon [mmol/m3] - Alk, & !< Total Alkalinity [mmol/m3] - PhyN, & !< Intracellular conc of Nitrogen in small phytoplankton [mmol/m3] - PhyC, & !< Intracellular conc of Carbon in small phytoplankton [mmol/m3] - PhyChl, & !< Current intracellular ChlA conc. [mg/m3] - DetN, & !< Conc of N in Detritus [mmol/m3] - DetC, & !< Conc of C in Detritus [mmol/m3] - HetN, & !< Conc of N in heterotrophs [mmol/m3] - HetC, & !< Conc of C in heterotrophs [mmol/m3] - DON, & !< Dissolved organic N in the water [mmol/m3] - EOC, & !< Extracellular Organic C conc [mmol/m3] - DiaN, & - DiaC, & - DiaChl, & - DiaSi, & - DetSi, & -#if defined (__coccos) - CoccoN, & - CoccoC, & - CoccoChl,& -#endif - Si, & - Fe, & - PhyCalc, & - DetCalc, & -#if defined (__3Zoo2Det) - Zoo2N, & - Zoo2C, & - DetZ2N, & - DetZ2C, & - DetZ2Si, & - DetZ2Calc,& - MicZooN, & ! 3Zoo - MicZooC, & ! 3Zoo -#endif - FreeFe, & - O2 + +! --- Biogeochemical state variables --- + real(kind=8) :: & + DIN, & ! [mmol/m3] Dissolved inorganic nitrogen + DIC, & ! [mmol/m3] Dissolved inorganic carbon + Alk, & ! [mmol/m3] Total alkalinity + PhyN, & ! [mmol/m3] Phytoplankton nitrogen (small) + PhyC, & ! [mmol/m3] Phytoplankton carbon (small) + PhyChl, & ! [mg/m3] Phytoplankton chlorophyll + DetN, & ! [mmol/m3] Detrital nitrogen + DetC, & ! [mmol/m3] Detrital carbon + HetN, & ! [mmol/m3] Heterotroph nitrogen + HetC, & ! [mmol/m3] Heterotroph carbon + DON, & ! [mmol/m3] Dissolved organic nitrogen + EOC, & ! [mmol/m3] Extracellular organic carbon + DOCt, & ! [mmol/m3] terrestrial DOC ! R2OMIP + DiaN, & ! [mmol/m3] Diatom nitrogen + DiaC, & ! [mmol/m3] Diatom carbon + DiaChl, & ! [mg/m3] Diatom chlorophyll + DiaSi, & ! [mmol/m3] Diatom silicate + DetSi, & ! [mmol/m3] Detrital silicate + Si, & ! [mmol/m3] Dissolved silicate + Fe, & ! [mmol/m3] Dissolved iron + PhyCalc, & ! [mmol/m3] Phytoplankton calcite + DetCalc, & ! [mmol/m3] Detrital calcite + FreeFe, & ! [mmol/m3] Free iron + O2 ! [mmol/m3] Dissolved oxygen + +! Coccolithophore variables (conditionally used based on namelist) +real(kind=8) :: & + CoccoN, & ! [mmol/m3] Coccolithophore nitrogen + CoccoC, & ! [mmol/m3] Coccolithophore carbon + CoccoChl, & ! [mg/m3] Coccolithophore chlorophyll + PhaeoN, & ! [mmol/m3] Phaeocystis nitrogen + PhaeoC, & ! [mmol/m3] Phaeocystis carbon + PhaeoChl ! [mg/m3] Phaeocystis chlorophyll + +! Extended zooplankton variables (conditionally used based on namelist) +real(kind=8) :: & + Zoo2N, & ! [mmol/m3] Zooplankton type 2 nitrogen + Zoo2C, & ! [mmol/m3] Zooplankton type 2 carbon + DetZ2N, & ! [mmol/m3] Zooplankton detritus nitrogen + DetZ2C, & ! [mmol/m3] Zooplankton detritus carbon + DetZ2Si, & ! [mmol/m3] Zooplankton detritus silicate + DetZ2Calc, & ! [mmol/m3] Zooplankton detritus calcite + MicZooN, & ! [mmol/m3] Microzooplankton nitrogen + MicZooC ! [mmol/m3] Microzooplankton carbon #include "../associate_part_def.h" #include "../associate_mesh_def.h" #include "../associate_part_ass.h" #include "../associate_mesh_ass.h" - sms = zero ! double precision - tiny_N = tiny_chl/chl2N_max !< 0.00001/ 3.15d0 Chl2N_max [mg CHL/mmol N] Maximum CHL a : N ratio = 0.3 gCHL gN^-1 - tiny_N_d = tiny_chl/chl2N_max_d !< 0.00001/ 4.2d0 + ! =========================================================================== + ! VARIABLE DECLARATIONS AND INITIALIZATION + ! =========================================================================== + + !=============================================================================== + ! INITIALIZATION AND SETUP + !=============================================================================== + ! Initializes arrays, calculates minimum thresholds, and sets up time stepping. + ! + ! Variables: + ! sms : Source-minus-sink array for tracer updates [mmol m-3 day-1] + ! zero : Double precision zero (0.0d0) + ! tiny : Very small positive number (numerical stability) + ! tiny_chl : Minimum chlorophyll concentration [mgChl m-3] + ! + ! Source-Minus-Sink (SMS) Array: + ! - Accumulates all biogeochemical fluxes + ! - Dimension: (vertical_levels, number_of_tracers) + ! - Updated throughout biological calculations + ! - Applied to state variables at end of time step + ! - Units: concentration per day [mmol m-3 day-1] + !------------------------------------------------------------------------------- + + ! Initialize source-minus-sink array + ! Sets all biogeochemical fluxes to zero at start of time step + sms = zero + + !=============================================================================== + ! MINIMUM THRESHOLD VALUES + !=============================================================================== + ! Calculates minimum allowable concentrations for all biological state variables. + ! Prevents division by zero and ensures numerical stability. + ! + ! Threshold Calculation Strategy: + ! - Based on physiological maximum ratios + ! - Works backward from minimum chlorophyll + ! - Ensures stoichiometric consistency + ! - Species-specific values + ! + ! Rationale for Minimum Thresholds: + ! - Division by zero prevention in quota calculations + ! - Numerical stability in resource limitation terms + ! - Prevents spurious negative values + ! - Represents detection limits or "ghost populations" + ! + ! Typical Minimum Values: + ! - Chlorophyll: ~0.001-0.01 mgChl m-3 + ! - Nitrogen: ~0.001-0.01 mmolN m-3 + ! - Carbon: ~0.01-0.1 mmolC m-3 + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Small Phytoplankton Thresholds + !------------------------------------------------------------------------------- + ! Variables: + ! tiny_N : Minimum small phyto nitrogen [mmolN m-3] + ! tiny_C : Minimum small phyto carbon [mmolC m-3] + ! tiny_chl : Minimum chlorophyll (set externally) [mgChl m-3] + ! chl2N_max : Maximum Chlorophyll:Nitrogen ratio [mgChl mmolN-1] + ! NCmax : Maximum Nitrogen:Carbon quota [mmolN mmolC-1] + ! + ! Calculation Logic: + ! 1. Start with minimum observable Chl (tiny_chl) + ! 2. Calculate minimum N using maximum Chl:N ratio + ! 3. Calculate minimum C using maximum N:C quota + ! + ! Typical Values: + ! chl2N_max = 3.15 mgChl/mmolN (high Chl per N, low light acclimation) + ! NCmax = 0.2 mmolN/mmolC (luxury N consumption maximum) + + ! Minimum nitrogen based on minimum chlorophyll and maximum Chl:N ratio + tiny_N = tiny_chl / chl2N_max + + ! Minimum carbon based on minimum nitrogen and maximum N:C quota + tiny_C = tiny_N / NCmax + + !------------------------------------------------------------------------------- + ! Diatom Thresholds + !------------------------------------------------------------------------------- + ! Variables: + ! tiny_N_d : Minimum diatom nitrogen [mmolN m-3] + ! tiny_C_d : Minimum diatom carbon [mmolC m-3] + ! tiny_Si : Minimum diatom silicate [mmolSi m-3] + ! chl2N_max_d : Maximum diatom Chl:N ratio [mgChl mmolN-1] + ! NCmax_d : Maximum diatom N:C quota [mmolN mmolC-1] + ! SiCmax : Maximum diatom Si:C quota [mmolSi mmolC-1] + ! + ! Typical Values: + ! chl2N_max_d = 4.2 mgChl/mmolN (diatoms can have higher Chl:N) + ! NCmax_d = 0.2 mmolN/mmolC + ! SiCmax = 0.8 mmolSi/mmolC (heavily silicified frustules) + ! + ! Silicon Requirement: + ! - Unique to diatoms (frustule formation) + ! - Calculated from minimum carbon and maximum Si:C ratio + + ! Minimum diatom nitrogen + tiny_N_d = tiny_chl / chl2N_max_d + + ! Minimum diatom carbon + tiny_C_d = tiny_N_d / NCmax_d + + ! Minimum silicate (based on diatom carbon and maximum Si:C quota) + tiny_Si = tiny_C_d / SiCmax + + !------------------------------------------------------------------------------- + ! Coccolithophore and Phaeocystis Thresholds (Optional) + !------------------------------------------------------------------------------- + ! Only calculated when 4-plankton functional type model is enabled + + if (enable_coccos) then + + ! Coccolithophore thresholds + ! Variables: + ! tiny_N_c : Minimum cocco nitrogen [mmolN m-3] + ! tiny_C_c : Minimum cocco carbon [mmolC m-3] + ! chl2N_max_c : Maximum cocco Chl:N ratio [mgChl mmolN-1] + ! NCmax_c : Maximum cocco N:C quota [mmolN mmolC-1] + + tiny_N_c = tiny_chl / chl2N_max_c + tiny_C_c = tiny_N_c / NCmax_c + + ! Phaeocystis thresholds + ! Variables: + ! tiny_N_p : Minimum Phaeo nitrogen [mmolN m-3] + ! tiny_C_p : Minimum Phaeo carbon [mmolC m-3] + ! chl2N_max_p : Maximum Phaeo Chl:N ratio [mgChl mmolN-1] + ! NCmax_p : Maximum Phaeo N:C quota [mmolN mmolC-1] + + tiny_N_p = tiny_chl / chl2N_max_p + tiny_C_p = tiny_N_p / NCmax_p - tiny_C = tiny_N /NCmax !< NCmax = 0.2d0 [mmol N/mmol C] Maximum cell quota of nitrogen (N:C) - tiny_C_d = tiny_N_d/NCmax_d !< NCmax_d = 0.2d0 + endif - tiny_Si = tiny_C_d/SiCmax !< SiCmax = 0.8d0 + ! Reciprocal of heterotroph respiration rate + ! Used in Redfield-based respiration calculations + ! Variable: + ! recip_res_het : Reciprocal respiration parameter [day] + ! res_het : Heterotroph respiration rate [day-1] + ! Typical value: res_het = 0.01 day-1 (combined respiration + mortality) + recip_res_het = 1.d0 / res_het + + ! Atmospheric pressure conversion for carbonate chemistry + ! MOCSY requires pressure in atmospheres + ! Variables: + ! Patm_depth : Atmospheric pressure [atm] + ! Loc_slp : Local sea level pressure [Pa] + ! Pa2atm : Pascal to atmosphere conversion factor [Pa atm-1] + Patm_depth = Loc_slp / Pa2atm + + !=============================================================================== + ! TIME STEPPING SETUP + !=============================================================================== + ! Converts time steps and sets up sub-cycling for biogeochemistry. + ! + ! Time Step Hierarchy: + ! 1. FESOM physics time step (dt) [seconds] + ! 2. Daily time step (dt_d) [days] + ! 3. REcoM biogeochemistry sub-step (dt_b) [days] + ! + ! Sub-Cycling Rationale: + ! - Physics: Slow (hours to days) + ! - Fast biology: Minutes to hours (phytoplankton growth, grazing) + ! - Allows finer temporal resolution for biological processes + ! - Improves numerical stability for stiff biological systems + ! + ! Variables: + ! rTref : Reciprocal reference temperature [K-1] + ! recom_Tref : Reference temperature (typically 288.15 K = 15degC) [K] + ! dt : FESOM physics time step [seconds] + ! dt_d : Physics time step in days [days] + ! dt_b : REcoM biogeochemistry sub-time step [days] + ! SecondsPerDay : Conversion factor (86400) [s day-1] + ! biostep : Number of biogeochemistry steps per physics step [-] + ! + ! Typical Configuration: + ! dt = 3600 s (1 hour physics step) + ! biostep = 4 (15-minute biogeochemistry steps) + ! dt_b = 0.25/24 = 0.0104 days + !------------------------------------------------------------------------------- + + ! Convert FESOM physics time step to days + dt_d = dt / SecondsPerDay + + ! Calculate biogeochemistry sub-time step + ! Divides physics step into smaller biogeochemical steps + dt_b = dt_d / real(biostep) + + ! Reciprocal reference temperature for Arrhenius calculations + ! Reference: 288.15 K (15degC) used in temperature dependence functions + rTref = real(one) / recom_Tref + + !=============================================================================== + ! MAIN TIME INTEGRATION LOOP + !=============================================================================== + ! Iterates through biogeochemical sub-time steps within each physics time step. + ! Allows fine temporal resolution for fast biological processes. + ! + ! Loop Structure: + ! - Outer loop: Biogeochemistry sub-steps (biostep iterations) + ! - Inner loop: Vertical layers (surface to bottom) + ! + ! Variables: + ! step : Current biogeochemistry sub-step counter [-] + ! biostep : Total number of sub-steps per physics step [-] + ! kdzUpper : Cumulative light attenuation from surface [dimensionless] + ! sms : Source-minus-sink flux array [mmol m-3 day-1] + ! tiny : Threshold for negligible fluxes [mmol m-3 day-1] + ! + ! Numerical Cleanup: + ! - Removes negligible SMS values before applying + ! - Prevents accumulation of numerical noise + ! - Improves computational efficiency + !------------------------------------------------------------------------------- + + do step = one, biostep + + ! Reset upper light attenuation (top of the cell) at start of each sub-step + ! Light attenuation integrates downward through water column + kdzUpper = 0.d0 + + ! Clean up negligible SMS values to prevent numerical issues + ! Sets very small fluxes to exactly zero + if (any(abs(sms(:, :)) <= tiny)) sms(:, :) = zero + + !=========================================================================== + ! VERTICAL LOOP THROUGH WATER COLUMN + !=========================================================================== + ! Processes each vertical layer from surface to bottom. + ! Updates state variables and enforces constraints. + ! + ! Variables: + ! k : Current vertical level index [-] + ! nn : Number of vertical levels in water column [-] + ! + ! Note: Alternative loop configurations commented out: + ! - nzmin, nzmax: Min/max active levels (for dry cells) + ! - myDim_nod2D: Horizontal dimension (for 3D unstructured grids) + !--------------------------------------------------------------------------- + + do k = one, nn + ! Alternative loop structures (commented out): + ! do n = 1, myDim_nod2D + ! Nn = nlevels_nod2D(n) - 1 + ! nzmin = ulevels_nod2D(row) + ! nzmax = nlevels_nod2D(row) + + !----------------------------------------------------------------------- + ! DISSOLVED INORGANIC NUTRIENTS + !----------------------------------------------------------------------- + ! Update nutrient concentrations: state(previous) + SMS(fluxes) + ! Enforce minimum values for numerical stability + ! + ! Variables: + ! DIN : Dissolved inorganic nitrogen (NO3- + NH4+) [mmolN m-3] + ! Si : Dissolved silicate (Si(OH)4) [mmolSi m-3] + ! Fe : Dissolved iron (bioavailable Fe) [mmolFe m-3] + ! + ! max() function ensures non-negative concentrations + !----------------------------------------------------------------------- + + DIN = max(tiny, state(k, idin) + sms(k, idin)) + Si = max(tiny, state(k, isi) + sms(k, isi)) + Fe = max(tiny, state(k, ife) + sms(k, ife)) + + !----------------------------------------------------------------------- + ! CARBON SYSTEM VARIABLES + !----------------------------------------------------------------------- + ! Variables: + ! DIC : Dissolved inorganic carbon (CO2 + HCO3- + CO3--) [mmolC m-3] + ! ALK : Total alkalinity [meq m-3] + ! O2 : Dissolved oxygen [mmolO2 m-3] + !----------------------------------------------------------------------- + + DIC = max(tiny, state(k, idic) + sms(k, idic)) + ALK = max(tiny, state(k, ialk) + sms(k, ialk)) + O2 = max(tiny, state(k, ioxy) + sms(k, ioxy)) + + !----------------------------------------------------------------------- + ! DISSOLVED ORGANIC MATTER + !----------------------------------------------------------------------- + ! Variables: + ! DON : Dissolved organic nitrogen (labile + semi-labile) [mmolN m-3] + ! EOC : Dissolved organic carbon (labile + semi-labile) [mmolC m-3] + ! + ! Note: EOC naming convention (Enhanced Organic Carbon) is historical + !----------------------------------------------------------------------- + + DON = max(tiny, state(k, idon) + sms(k, idon)) + EOC = max(tiny, state(k, idoc) + sms(k, idoc)) + + if (useRivers) then + DOCt= max(tiny, state(k,idoct) + sms(k, idoct)) ! R2OMIP + end if + !----------------------------------------------------------------------- + ! SMALL PHYTOPLANKTON + !----------------------------------------------------------------------- + ! General phytoplankton functional type + ! Variables: + ! PhyN : Small phyto nitrogen [mmolN m-3] + ! PhyC : Small phyto carbon [mmolC m-3] + ! PhyChl : Small phyto chlorophyll [mgChl m-3] + ! PhyCalc : Small phyto calcite (if calcifying) [mmolC m-3] + !----------------------------------------------------------------------- + + PhyN = max(tiny_N, state(k, iphyn) + sms(k, iphyn)) + PhyC = max(tiny_C, state(k, iphyc) + sms(k, iphyc)) + PhyChl = max(tiny_chl, state(k, ipchl) + sms(k, ipchl)) + PhyCalc = max(tiny, state(k, iphycal) + sms(k, iphycal)) + + !----------------------------------------------------------------------- + ! DIATOMS (SILICIFYING PHYTOPLANKTON) + !----------------------------------------------------------------------- + ! Large phytoplankton with silica frustules + ! Variables: + ! DiaN : Diatom nitrogen [mmolN m-3] + ! DiaC : Diatom carbon [mmolC m-3] + ! DiaChl : Diatom chlorophyll [mgChl m-3] + ! DiaSi : Diatom silicate (frustule) [mmolSi m-3] + !----------------------------------------------------------------------- + + DiaN = max(tiny_N_d, state(k, idian) + sms(k, idian)) + DiaC = max(tiny_C_d, state(k, idiac) + sms(k, idiac)) + DiaChl = max(tiny_chl, state(k, idchl) + sms(k, idchl)) + DiaSi = max(tiny_si, state(k, idiasi) + sms(k, idiasi)) + + if (enable_coccos) then + + !------------------------------------------------------------------- + ! COCCOLITHOPHORES (CALCIFYING PHYTOPLANKTON) + !------------------------------------------------------------------- + ! Variables: + ! CoccoN : Cocco nitrogen [mmolN m-3] + ! CoccoC : Cocco carbon [mmolC m-3] + ! CoccoChl : Cocco chlorophyll [mgChl m-3] + !------------------------------------------------------------------- + + CoccoN = max(tiny_N_c, state(k, icocn) + sms(k, icocn)) + CoccoC = max(tiny_C_c, state(k, icocc) + sms(k, icocc)) + CoccoChl = max(tiny_chl, state(k, icchl) + sms(k, icchl)) + + !------------------------------------------------------------------- + ! PHAEOCYSTIS (COLONIAL PHYTOPLANKTON) + !------------------------------------------------------------------- + ! Variables: + ! PhaeoN : Phaeo nitrogen [mmolN m-3] + ! PhaeoC : Phaeo carbon [mmolC m-3] + ! PhaeoChl : Phaeo chlorophyll [mgChl m-3] + !------------------------------------------------------------------- + + PhaeoN = max(tiny_N_p, state(k, iphan) + sms(k, iphan)) + PhaeoC = max(tiny_C_p, state(k, iphac) + sms(k, iphac)) + PhaeoChl = max(tiny_chl, state(k, iphachl) + sms(k, iphachl)) -#if defined (__coccos) - tiny_N_c = tiny_chl/chl2N_max_c - tiny_C_c = tiny_N_c/NCmax_c -#endif + end if - recip_res_het = 1.d0/res_het !< res_het = 0.01d0 [1/day] Respiration by heterotrophs and mortality (loss to detritus) + !----------------------------------------------------------------------- + ! HETEROTROPHS (ZOOPLANKTON) + !----------------------------------------------------------------------- + ! Primary grazers (mesozooplankton) + ! Variables: + ! HetN : Mesozooplankton nitrogen [mmolN m-3] + ! HetC : Mesozooplankton carbon [mmolC m-3] + !----------------------------------------------------------------------- + + HetN = max(tiny, state(k, ihetn) + sms(k, ihetn)) + HetC = max(tiny, state(k, ihetc) + sms(k, ihetc)) + + if (enable_3zoo2det) then + + !------------------------------------------------------------------- + ! ADDITIONAL ZOOPLANKTON (3-ZOOPLANKTON MODEL) + !------------------------------------------------------------------- + ! Macrozooplankton (e.g., krill) + ! Variables: + ! Zoo2N : Macrozooplankton nitrogen [mmolN m-3] + ! Zoo2C : Macrozooplankton carbon [mmolC m-3] + Zoo2N = max(tiny, state(k, izoo2n) + sms(k, izoo2n)) + Zoo2C = max(tiny, state(k, izoo2c) + sms(k, izoo2c)) + + ! Microzooplankton (e.g., ciliates, heterotrophic dinoflagellates) + ! Variables: + ! MicZooN : Microzooplankton nitrogen [mmolN m-3] + ! MicZooC : Microzooplankton carbon [mmolC m-3] + MicZooN = max(tiny, state(k, imiczoon) + sms(k, imiczoon)) + MicZooC = max(tiny, state(k, imiczooc) + sms(k, imiczooc)) - Patm_depth = Loc_slp/Pa2atm ! MOCSY convert from Pa to atm. + end if -!------------------------------------------------------------------------------- -!> REcoM time steps [day] -!------------------------------------------------------------------------------- + !----------------------------------------------------------------------- + ! DETRITUS (DEAD ORGANIC MATTER) + !----------------------------------------------------------------------- + ! Slow-sinking detritus pools + ! Variables: + ! DetN : Detrital nitrogen [mmolN m-3] + ! DetC : Detrital carbon [mmolC m-3] + ! DetSi : Detrital silicate [mmolSi m-3] + ! DetCalc : Detrital calcite [mmolC m-3] + !----------------------------------------------------------------------- + + DetN = max(tiny, state(k, idetn) + sms(k, idetn)) + DetC = max(tiny, state(k, idetc) + sms(k, idetc)) + DetSi = max(tiny, state(k, idetsi) + sms(k, idetsi)) + DetCalc = max(tiny, state(k, idetcal) + sms(k, idetcal)) + + if (enable_3zoo2det) then + + !------------------------------------------------------------------- + ! FAST-SINKING DETRITUS (FECAL PELLETS) + !------------------------------------------------------------------- + ! Large, rapidly sinking particles + ! Variables: + ! DetZ2N : Fast detritus nitrogen [mmolN m-3] + ! DetZ2C : Fast detritus carbon [mmolC m-3] + ! DetZ2Si : Fast detritus silicate [mmolSi m-3] + ! DetZ2Calc : Fast detritus calcite [mmolC m-3] + !------------------------------------------------------------------- + + DetZ2N = max(tiny, state(k, idetz2n) + sms(k, idetz2n)) + DetZ2C = max(tiny, state(k, idetz2c) + sms(k, idetz2c)) + DetZ2Si = max(tiny, state(k, idetz2si) + sms(k, idetz2si)) + DetZ2Calc = max(tiny, state(k, idetz2calc) + sms(k, idetz2calc)) - rTref = real(one)/recom_Tref - - dt_d = dt/SecondsPerDay !< Size of FESOM time step [day] - dt_b = dt_d/real(biostep) !< Size of REcoM time step [day] + end if -!------------------------------------------------------------------------------- -!Main time loop starts - do step = one,biostep + !----------------------------------------------------------------------- + ! FREE IRON INITIALIZATION + !----------------------------------------------------------------------- + ! Free iron will be calculated later from total iron budget + ! Accounts for scavenging, complexation, and biological uptake + !----------------------------------------------------------------------- - kdzUpper = 0.d0 !< Upper light attenuation of top cell is set to zero + FreeFe = zero - if (any(abs(sms(:,:)) <= tiny)) sms(:,:) = zero ! tiny = 2.23D-16 + !======================================================================= + ! PHYSICAL ENVIRONMENT CONSTRAINTS FOR CARBONATE CHEMISTRY + !======================================================================= + ! Validates and constrains physical parameters for MOCSY carbonate + ! system calculations. Ensures inputs are within valid ranges. + ! + ! MOCSY Valid Ranges (Lueker K1/K2 formulation): + ! Temperature: 2-35degC + ! Salinity: 19-43 psu + ! + ! Rationale for Constraints: + ! - Equilibrium constants are empirical fits + ! - Extrapolation outside valid range introduces errors + ! - Numerical instability at extreme values + ! - Ice formation creates low-salinity issues + !----------------------------------------------------------------------- + + !----------------------------------------------------------------------- + ! Temperature Constraints + !----------------------------------------------------------------------- + ! Variables: + ! REcoM_T_depth : Constrained temperature for MOCSY [degC] + ! Temp(k) : Actual temperature at depth k [degC] + ! + ! Constraints: + ! Minimum: 2degC (prevents extrapolation below calibration range) + ! Maximum: 40degC (safety limit, ocean rarely exceeds 35degC) + ! + ! Note: K1/K2 Lueker formulation valid for 2-35degC + !----------------------------------------------------------------------- + + REcoM_T_depth = max(2.d0, Temp(k)) ! Apply minimum + REcoM_T_depth = min(REcoM_T_depth, 40.d0) ! Apply maximum + + !----------------------------------------------------------------------- + ! Salinity Constraints + !----------------------------------------------------------------------- + ! Variables: + ! REcoM_S_depth : Constrained salinity for MOCSY [psu] + ! Sali_depth(k) : Actual salinity at depth k [psu] + ! + ! Constraints: + ! Minimum: 21 psu (increased from 19 to avoid numerical issues) + ! Maximum: 43 psu (upper limit of calibration range) + ! + ! Problematic Conditions: + ! - Salinity 19-21 psu with ice concentration > 97% + ! - Causes numerical instability in MOCSY + ! - Conservative constraint (21 psu minimum) prevents issues + ! + ! Note: Brackish water and ice-covered regions require special care + !----------------------------------------------------------------------- + + REcoM_S_depth = max(21.d0, Sali_depth(k)) ! Apply minimum + REcoM_S_depth = min(REcoM_S_depth, 43.d0) ! Apply maximum + + !----------------------------------------------------------------------- + ! Unit Conversions for MOCSY + !----------------------------------------------------------------------- + ! MOCSY requires concentrations in mol/m3 (not mmol/m3) + ! Conversion factor: 1e-3 (mmol -> mol) + ! + ! Variables (output): + ! REcoM_DIC_depth : DIC for MOCSY [mol m-3] + ! REcoM_Alk_depth : Alkalinity for MOCSY [mol m-3] + ! REcoM_Si_depth : Silicate for MOCSY [mol m-3] + ! REcoM_Phos_depth : Phosphate for MOCSY [mol m-3] + ! + ! Sources: + ! state(k, idic) + sms(k, idic) : DIC [mmol m-3] + ! state(k, ialk) + sms(k, ialk) : Alkalinity [mmol m-3] + ! state(k, isi) + sms(k, isi) : Silicate [mmol m-3] + ! state(k, idin) + sms(k, idin) : DIN -> Phosphate via Redfield + !----------------------------------------------------------------------- + + ! Dissolved inorganic carbon [mol m-3] + REcoM_DIC_depth = max(tiny * 1e-3, state(k, idic) * 1e-3 + sms(k, idic) * 1e-3) + + ! Total alkalinity [mol m-3] + REcoM_Alk_depth = max(tiny * 1e-3, state(k, ialk) * 1e-3 + sms(k, ialk) * 1e-3) + + ! Silicate [mol m-3] + REcoM_Si_depth = max(tiny * 1e-3, state(k, isi) * 1e-3 + sms(k, isi) * 1e-3) + + ! Phosphate [mol m-3] + ! Calculated from nitrogen using Redfield ratio (N:P = 16:1) + ! Model tracks nitrogen but MOCSY needs phosphate + REcoM_Phos_depth = max(tiny * 1e-3, state(k, idin) * 1e-3 + sms(k, idin) * 1e-3) / 16.d0 + + ! =================================================================== + ! CELLULAR QUOTAS AND RATIOS CALCULATIONS + ! =================================================================== + + !=============================================================================== + ! Small Phytoplankton Quotas + !=============================================================================== + ! Calculates stoichiometric ratios for the small phytoplankton functional type. + ! Represents diverse group of small flagellates and picophytoplankton. + ! + ! Variables: + ! quota : Nitrogen:Carbon quota [mmolN mmolC-1] + ! recipquota : Carbon:Nitrogen ratio [mmolC mmolN-1] + ! Chl2C : Chlorophyll:Carbon ratio [mgChl mmolC-1] + ! Chl2N : Chlorophyll:Nitrogen ratio [mgChl mmolN-1] + ! CHL2C_plast : Plastidic Chlorophyll:Carbon ratio [mgChl mmolC-1] + ! PhyN : Small phytoplankton nitrogen [mmolN m-3] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! PhyChl : Small phytoplankton chlorophyll [mgChl m-3] + ! NCmin : Minimum N:C quota (subsistence quota) [mmolN mmolC-1] + ! + ! Quota Interpretation: + ! - High quota (N:C > 0.15): Nutrient replete, luxury consumption + ! - Medium quota (N:C ≈ 0.10): Balanced growth + ! - Low quota (N:C < 0.06): Severely N-limited, near subsistence + ! - Minimum quota (NCmin ≈ 0.04): Zero growth threshold + ! + ! Plastidic Chlorophyll Concept: + ! - Total Chl includes storage and structural chlorophyll + ! - Plastidic Chl represents functional photosynthetic apparatus + ! - Correction factor: quota/(quota - NCmin) + ! - Higher correction when quota approaches minimum (more Chl in chloroplasts) + !------------------------------------------------------------------------------- + + ! Nitrogen:Carbon quota (cellular N:C ratio) + ! Controls growth rate via Droop limitation + quota = PhyN / PhyC + + ! Carbon:Nitrogen ratio (reciprocal) + ! Used for converting N-based fluxes to carbon + recipquota = real(one) / quota + + ! Chlorophyll:Carbon ratio + ! Reflects photoacclimation state (higher in low light) + Chl2C = PhyChl / PhyC + + ! Chlorophyll:Nitrogen ratio + ! Links photosynthetic machinery to nitrogen investment + Chl2N = PhyChl / PhyN + + ! Plastidic Chlorophyll:Carbon ratio + ! Estimates chlorophyll in active photosynthetic apparatus + ! Correction accounts for non-photosynthetic N (structural proteins, storage) + ! Formula: Chl2C x (quota / (quota - NCmin)) + ! As quota -> NCmin, more N is in photosynthetic machinery + CHL2C_plast = Chl2C * (quota / (quota - NCmin)) + + !=============================================================================== + ! Diatom Quotas + !=============================================================================== + ! Calculates stoichiometric ratios for diatoms (large phytoplankton with + ! silica frustules). Includes unique silicon quotas. + ! + ! Variables: + ! quota_dia : Diatom N:C quota [mmolN mmolC-1] + ! recipQuota_dia : Diatom C:N ratio [mmolC mmolN-1] + ! Chl2C_dia : Diatom Chl:C ratio [mgChl mmolC-1] + ! Chl2N_dia : Diatom Chl:N ratio [mgChl mmolN-1] + ! CHL2C_plast_dia : Diatom plastidic Chl:C ratio [mgChl mmolC-1] + ! qSiC : Diatom Si:C quota [mmolSi mmolC-1] + ! qSiN : Diatom Si:N quota [mmolSi mmolN-1] + ! DiaN : Diatom nitrogen [mmolN m-3] + ! DiaC : Diatom carbon [mmolC m-3] + ! DiaChl : Diatom chlorophyll [mgChl m-3] + ! DiaSi : Diatom silicon [mmolSi m-3] + ! NCmin_d : Minimum diatom N:C quota [mmolN mmolC-1] + ! + ! Silicon Quota Significance: + ! - Required for frustule (shell) formation + ! - Typical Si:C ≈ 0.13 (Brzezinski 1985) + ! - Low Si:C -> thin frustules, increased sinking mortality + ! - High Si:C -> thick frustules, enhanced sinking + ! - Si limitation can occur even when N is abundant + ! + ! Diatom-Specific Features: + ! - Generally lower Chl:C than small phytoplankton (package effect) + ! - Higher maximum growth rates when nutrient replete + ! - Bloom-forming under high-nutrient conditions + !------------------------------------------------------------------------------- + + ! Nitrogen:Carbon quota + quota_dia = DiaN / DiaC + + ! Carbon:Nitrogen ratio (reciprocal) + recipQuota_dia = real(one) / quota_dia + + ! Chlorophyll:Carbon ratio + ! Generally lower than small phytoplankton due to large cell size (package effect) + Chl2C_dia = DiaChl / DiaC + + ! Chlorophyll:Nitrogen ratio + Chl2N_dia = DiaChl / DiaN + + ! Plastidic Chlorophyll:Carbon ratio + ! Corrected for non-photosynthetic nitrogen allocation + CHL2C_plast_dia = Chl2C_dia * (quota_dia / (quota_dia - NCmin_d)) + + ! Silicon:Carbon quota + ! Critical for frustule formation and diatom physiology + ! Low Si:C indicates silicon limitation + qSiC = DiaSi / DiaC + + ! Silicon:Nitrogen quota + ! Alternative measure of silicon status relative to cellular nitrogen + qSiN = DiaSi / DiaN + + !=============================================================================== + ! Additional Phytoplankton Quotas (OPTIONAL) + !=============================================================================== + ! Calculates quotas for coccolithophores and Phaeocystis when enabled. + ! These groups have distinct biogeochemical roles. + ! + ! Coccolithophores: + ! - Calcifying phytoplankton (produce CaCO3 plates) + ! - Warm-water adapted + ! - Important for carbonate counter-pump + ! + ! Phaeocystis: + ! - Colonial phytoplankton (can form large blooms) + ! - Produces mucilaginous matrix + ! - Cold-water species (polar and temperate) + ! - High aggregation potential + !------------------------------------------------------------------------------- + + if (enable_coccos) then + + !=========================================================================== + ! Coccolithophore Quotas + !=========================================================================== + ! Calcifying phytoplankton with calcium carbonate plates (coccoliths) + ! + ! Variables: + ! quota_cocco : Cocco N:C quota [mmolN mmolC-1] + ! recipQuota_cocco : Cocco C:N ratio [mmolC mmolN-1] + ! Chl2C_cocco : Cocco Chl:C ratio [mgChl mmolC-1] + ! Chl2N_cocco : Cocco Chl:N ratio [mgChl mmolN-1] + ! CHL2C_plast_cocco : Cocco plastidic Chl:C ratio [mgChl mmolC-1] + ! CoccoN : Coccolithophore nitrogen [mmolN m-3] + ! CoccoC : Coccolithophore carbon [mmolC m-3] + ! CoccoChl : Coccolithophore chlorophyll [mgChl m-3] + ! NCmin_c : Minimum cocco N:C quota [mmolN mmolC-1] + ! + ! Note: Additional calcite quotas (CaCO3:C) calculated in calcification module + !--------------------------------------------------------------------------- + + ! Nitrogen:Carbon quota + quota_cocco = CoccoN / CoccoC + + ! Carbon:Nitrogen ratio + recipQuota_cocco = real(one) / quota_cocco + + ! Chlorophyll:Carbon ratio + Chl2C_cocco = CoccoChl / CoccoC + + ! Chlorophyll:Nitrogen ratio + Chl2N_cocco = CoccoChl / CoccoN + + ! Plastidic Chlorophyll:Carbon ratio + CHL2C_plast_cocco = Chl2C_cocco * (quota_cocco / (quota_cocco - NCmin_c)) + + !=========================================================================== + ! Phaeocystis Quotas + !=========================================================================== + ! Colonial phytoplankton that forms large blooms in cold waters + ! + ! Variables: + ! quota_phaeo : Phaeo N:C quota [mmolN mmolC-1] + ! recipQuota_phaeo : Phaeo C:N ratio [mmolC mmolN-1] + ! Chl2C_phaeo : Phaeo Chl:C ratio [mgChl mmolC-1] + ! Chl2N_phaeo : Phaeo Chl:N ratio [mgChl mmolN-1] + ! CHL2C_plast_phaeo : Phaeo plastidic Chl:C ratio [mgChl mmolC-1] + ! PhaeoN : Phaeocystis nitrogen [mmolN m-3] + ! PhaeoC : Phaeocystis carbon [mmolC m-3] + ! PhaeoChl : Phaeocystis chlorophyll [mgChl m-3] + ! NCmin_p : Minimum Phaeo N:C quota [mmolN mmolC-1] + ! + ! Ecological Notes: + ! - Forms colonial mucilaginous matrix (contributes to DOM) + ! - Can dominate Arctic/Antarctic spring blooms + ! - Enhanced aggregation and export potential + !--------------------------------------------------------------------------- + + ! Nitrogen:Carbon quota + quota_phaeo = PhaeoN / PhaeoC + + ! Carbon:Nitrogen ratio + recipQuota_phaeo = real(one) / quota_phaeo + + ! Chlorophyll:Carbon ratio + Chl2C_phaeo = PhaeoChl / PhaeoC + + ! Chlorophyll:Nitrogen ratio + Chl2N_phaeo = PhaeoChl / PhaeoN + + ! Plastidic Chlorophyll:Carbon ratio + CHL2C_plast_phaeo = Chl2C_phaeo * (quota_phaeo / (quota_phaeo - NCmin_p)) -!------------------------------------------------------------------------------- -! Main vertical loop starts - do k = one,Nn ! nzmin, nzmax -! do n=1, myDim_nod2D!+eDim_nod2D -! Nn=nlevels_nod2D(n)-1 !nzmax -! nzmin = ulevels_nod2D(row) -! nzmax = nlevels_nod2D(row) - DIN = max(tiny,state(k,idin) + sms(k,idin )) !< Avoids division by zero - DIC = max(tiny,state(k,idic) + sms(k,idic )) !! and updates Conc between - ALK = max(tiny,state(k,ialk) + sms(k,ialk )) !! local steps in REcoM when - PhyN = max(tiny_N,state(k,iphyn) + sms(k,iphyn )) !! biostep > 1 - PhyC = max(tiny_C,state(k,iphyc) + sms(k,iphyc )) - PhyChl = max(tiny_chl,state(k,ipchl) + sms(k,ipchl )) - DetN = max(tiny,state(k,idetn) + sms(k,idetn )) - DetC = max(tiny,state(k,idetc) + sms(k,idetc )) - HetN = max(tiny,state(k,ihetn) + sms(k,ihetn )) - HetC = max(tiny,state(k,ihetc) + sms(k,ihetc )) -#if defined (__3Zoo2Det) - Zoo2N = max(tiny,state(k,izoo2n) + sms(k,izoo2n)) - Zoo2C = max(tiny,state(k,izoo2c) + sms(k,izoo2c)) - DetZ2N = max(tiny,state(k,idetz2n) + sms(k,idetz2n)) - DetZ2C = max(tiny,state(k,idetz2c) + sms(k,idetz2c)) - DetZ2Si = max(tiny,state(k,idetz2si) + sms(k,idetz2si)) - DetZ2Calc = max(tiny,state(k,idetz2calc) + sms(k,idetz2calc)) - MicZooN = max(tiny,state(k,imiczoon) + sms(k,imiczoon)) - MicZooC = max(tiny,state(k,imiczooc) + sms(k,imiczooc)) -#endif - DON = max(tiny,state(k,idon) + sms(k,idon )) - EOC = max(tiny,state(k,idoc) + sms(k,idoc )) - DiaN = max(tiny_N_d,state(k,idian) + sms(k,idian )) - DiaC = max(tiny_C_d,state(k,idiac) + sms(k,idiac )) - DiaChl = max(tiny_chl,state(k,idchl) + sms(k,idchl )) - DiaSi = max(tiny_si,state(k,idiasi) + sms(k,idiasi)) - DetSi = max(tiny,state(k,idetsi) + sms(k,idetsi)) - Si = max(tiny,state(k,isi) + sms(k,isi )) -#if defined (__coccos) - CoccoN = max(tiny_N_c,state(k,icocn) + sms(k,icocn )) - CoccoC = max(tiny_C_c,state(k,icocc) + sms(k,icocc )) - CoccoChl = max(tiny_chl,state(k,icchl) + sms(k,icchl )) -#endif - Fe = max(tiny,state(k,ife) + sms(k,ife )) - O2 = max(tiny,state(k,ioxy) + sms(k,ioxy)) - FreeFe = zero + end if -! For Mocsy - REcoM_T_depth = max(2.d0, Temp(k)) ! minimum set to 2 degC: K1/K2 Lueker valid between 2degC-35degC and 19-43psu - REcoM_T_depth = min(REcoM_T_depth, 40.d0) ! maximum set to 40 degC: K1/K2 Lueker valid between 2degC-35degC and 19-43psu - REcoM_S_depth = max(21.d0, Sali_depth(k)) ! minimum set to 21: K1/K2 Lueker valid between 2degC-35degC and 19-43psu, else causes trouble in regions with S between 19 and 21 and ice conc above 97% - REcoM_S_depth = min(REcoM_S_depth, 43.d0) ! maximum set to 43: K1/K2 Lueker valid between 2degC-35degC and 19-43psu, else causes trouble - REcoM_DIC_depth = max(tiny*1e-3,state(k,idic)*1e-3 + sms(k,idic )*1e-3) - REcoM_Alk_depth = max(tiny*1e-3,state(k,ialk)*1e-3 + sms(k,ialk )*1e-3) - REcoM_Si_depth = max(tiny*1e-3,state(k,isi)*1e-3 + sms(k,isi )*1e-3) - - REcoM_Phos_depth = max(tiny*1e-3,state(k,idin)*1e-3 + sms(k,idin )*1e-3) /16 ! convert N to P with Redfield [mol/m3] - - PhyCalc = max(tiny,state(k,iphycal) + sms(k,iphycal)) - DetCalc = max(tiny,state(k,idetcal) + sms(k,idetcal)) - -!!------------------------------------------------------------------------------ -!< Quotas - ! *** Small phytoplankton - quota = PhyN / PhyC ! include variability of the N: C ratio, cellular chemical composition - recipquota = real(one) / quota - Chl2C = PhyChl / PhyC ! Chl a:phytoplankton carbon ratio, cellular chemical composition [gCHL gC^-1] - Chl2N = PhyChl / PhyN ! Chl a:phytoplankton nitrogen ratio, cellular chemical composition [gCHL gN^-1] - CHL2C_plast = Chl2C * (quota/(quota - NCmin)) - - ! *** Diatoms - quota_dia = DiaN / DiaC - recipQuota_dia = real(one)/quota_dia - Chl2C_dia = DiaChl / DiaC - Chl2N_dia = DiaChl / DiaN - CHL2C_plast_dia = Chl2C_dia * (quota_dia/(quota_dia - NCmin_d)) - qSiC = DiaSi / DiaC - qSiN = DiaSi / DiaN - -#if defined (__coccos) - quota_cocco = CoccoN / CoccoC - recipQuota_cocco = real(one)/quota_cocco - Chl2C_cocco = CoccoChl / CoccoC - Chl2N_cocco = CoccoChl / CoccoN - CHL2C_plast_cocco = Chl2C_cocco * (quota_cocco/(quota_cocco - NCmin_c)) -#endif - recipQZoo = HetC / HetN - recip_hetN_plus = 1.d0 / (HetN + tiny_het) ! MB's addition for more stable zoo respiration - if (Grazing_detritus) recipDet = DetC / DetN -#if defined (__3Zoo2Det) - recipQZoo2 = Zoo2C / Zoo2N - recipQZoo3 = MicZooC / MicZooN - if (Grazing_detritus) recipDet2 = DetZ2C / DetZ2N -#endif + !=============================================================================== + ! Zooplankton and Detritus Quotas + !=============================================================================== + ! Calculates carbon:nitrogen ratios for consumers and detrital pools. + ! These ratios are more constrained than phytoplankton (less variable). + ! + ! Zooplankton C:N ratios: + ! - Typically near Redfield ratio (C:N ≈ 6.6) + ! - Less variable than phytoplankton (homeostatic regulation) + ! - Important for grazer nutrition and trophic transfer efficiency + ! + ! Detritus C:N ratios: + ! - Reflects source material composition + ! - Can increase with depth (preferential N remineralization) + ! - Affects remineralization stoichiometry + ! + ! Variables: + ! recipQZoo : Mesozooplankton C:N ratio [mmolC mmolN-1] + ! recipQZoo2 : Macrozooplankton C:N ratio [mmolC mmolN-1] + ! recipQZoo3 : Microzooplankton C:N ratio [mmolC mmolN-1] + ! recipDet : Slow-sinking detritus C:N ratio [mmolC mmolN-1] + ! recipDet2 : Fast-sinking detritus C:N ratio [mmolC mmolN-1] + ! recip_hetN_plus : Stable divisor for respiration calculations [mmolN-1 m3] + ! HetC, HetN : Mesozooplankton carbon and nitrogen [mmol m-3] + ! Zoo2C, Zoo2N : Macrozooplankton carbon and nitrogen [mmol m-3] + ! MicZooC, MicZooN: Microzooplankton carbon and nitrogen [mmol m-3] + ! DetC, DetN : Detritus carbon and nitrogen [mmol m-3] + ! DetZ2C, DetZ2N : Fast-sinking detritus carbon and nitrogen [mmol m-3] + ! tiny_het : Small number to prevent division by zero [mmolN m-3] + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Mesozooplankton (Primary Heterotroph) Quotas + !------------------------------------------------------------------------------- + ! Primary grazer consuming phytoplankton and microzooplankton + + ! Carbon:Nitrogen ratio + ! Used for converting nitrogen-based grazing to carbon fluxes + recipQZoo = HetC / HetN + + ! Stable reciprocal for respiration calculations + ! Prevents division by zero when zooplankton biomass is very low + ! Used in Redfield-based respiration formulation + recip_hetN_plus = 1.d0 / (HetN + tiny_het) + + !------------------------------------------------------------------------------- + ! Detritus Quotas + !------------------------------------------------------------------------------- + ! Organic matter pools with variable C:N ratios -!------------------------------------------------------------------------------- -!> Temperature dependence of rates -!------------------------------------------------------------------------------- -!< Schourup 2013 Eq. A54 -!< Temperature dependence of metabolic rate, fT, dimensionless -!< Ae: Slope of the linear region of the Arrhenius plot -!< rTloc: Inverse of local temperature in [1/Kelvin] -!< rTref=288.15 (15 degC): Reference temperature for Arrhenius equation [1/Kelvin] -!< See Figure A1 -!< Other functions can be used for temperature dependency (Eppley 1972; Li 1980; Ahlgren 1987) - - rTloc = real(one)/(Temp(k) + C2K) - arrFunc = exp(-Ae * ( rTloc - rTref)) -#if defined (__coccos) - CoccoTFunc = max(0.1419d0 * Temp(k)**0.8151d0,tiny) ! Function from Fielding 2013; is based on observational GR, but range fits best to ours -#endif - -#if defined (__3Zoo2Det) - arrFuncZoo2 = exp(t1_zoo2/t2_zoo2 - t1_zoo2*rTloc)/(1 + exp(t3_zoo2/t4_zoo2 - t3_zoo2*rTloc)) ! 2Zoo - q10_mes = 1.0242**(Temp(k)) ! 3Zoo - q10_mic = 1.04**(Temp(k)) ! 3Zoo - q10_mes_res = 1.0887**(Temp(k)) ! 3Zoo - q10_mic_res = 1.0897**(Temp(k)) ! 3Zoo -#endif - -!< Silicate temperature dependence -! reminSiT = min(1.32e16 * exp(-11200.d0 * rTloc),reminSi) !! arrFunc control, reminSi=0.02d0 ! Kamatani (1982) -! reminSiT = reminSi - reminSiT = max(0.023d0 * 2.6d0**((Temp(k)-10.)/10.),reminSi) + if (Grazing_detritus) then + ! Slow-sinking detritus C:N ratio + ! Source: Unassimilated food, mortality, aggregation + ! Generally close to Redfield but can be elevated + recipDet = DetC / DetN + endif -!------------------------------------------------------------------------------- -!> O2 dependence of rates -!------------------------------------------------------------------------------- -!! O2 dependency of organic matter remineralization -!! O2Func [0.0, 1.0] -!! k_o2_remin = 15.d0 mmol m-3; Table 1 in Cram 2018 cites -!! DeVries & Weber 2017 for a range of 0-30 mmol m-3 - - O2Func = 1.d0 ! in this case, remin. rates only depend on temperature - if (O2dep_remin) O2Func = O2/(k_o2_remin + O2) ! O2remin - -!< *** Light *** -!< ************* -!! Has to be calculated here already to use the 1%PAR depth. - if (k==1) then - PARave = max(tiny,SurfSR) - PAR(k) = PARave - - chl_upper = (PhyChl + DiaChl) -#if defined (__coccos) - chl_upper = chl_upper + CoccoChl -#endif - else - chl_lower = PhyChl + DiaChl -#if defined (__coccos) - chl_lower = chl_lower + CoccoChl -#endif - Chlave = (chl_upper+chl_lower)*0.5 - - kappa = k_w + a_chl * (Chlave) - kappastar = kappa / cosAI(n) - kdzLower = kdzUpper + kappastar * thick(k-1) - Lowerlight = SurfSR * exp(-kdzLower) - Lowerlight = max(tiny,Lowerlight) - PARave = Lowerlight - PAR(k) = PARave - chl_upper = chl_lower - kdzUpper = kdzLower - end if + if (enable_3zoo2det) then -!------------------------------------------------------------------------------- -! Depth component of Mocsy (see http://ocmip5.ipsl.jussieu.fr/mocsy/pyth.html) -!------------------------------------------------------------------------------- + !--------------------------------------------------------------------------- + ! Additional Zooplankton Quotas (3-Zooplankton Model) + !--------------------------------------------------------------------------- + + ! Macrozooplankton (e.g., krill) C:N ratio + ! Larger organisms with potentially different stoichiometry + recipQZoo2 = Zoo2C / Zoo2N + + ! Microzooplankton (e.g., ciliates, heterotrophic dinoflagellates) C:N ratio + ! Smallest heterotrophs, link to microbial loop + recipQZoo3 = MicZooC / MicZooN + + if (Grazing_detritus) then + !----------------------------------------------------------------------- + ! Fast-Sinking Detritus (Fecal Pellets) + !----------------------------------------------------------------------- + ! Large, rapidly sinking particles + ! Source: Zooplankton fecal pellets, large aggregates + ! Important for biological pump and carbon export -! Calculate the carbonate system for the very first time step of the first year of the run - !if (mocsy_restart==.false. .and. recom_istep==1) then ! r_restart is defined in gen_modules_clock in fesom_cpl. + recipDet2 = DetZ2C / DetZ2N + endif + + endif + + ! =================================================================== + ! CARBON ISOTOPE TRACERS (if enabled) + ! =================================================================== + + if (ciso) then + ! 13C isotope tracers + DIC_13 = max(tiny, state(k, idic_13) + sms(k, idic_13)) + PhyC_13 = max(tiny_C, state(k, iphyc_13) + sms(k, iphyc_13)) + DetC_13 = max(tiny, state(k, idetc_13) + sms(k, idetc_13)) + HetC_13 = max(tiny, state(k, ihetc_13) + sms(k, ihetc_13)) + EOC_13 = max(tiny, state(k, idoc_13) + sms(k, idoc_13)) + DiaC_13 = max(tiny_C, state(k, idiac_13) + sms(k, idiac_13)) + PhyCalc_13 = max(tiny, state(k, iphycal_13) + sms(k, iphycal_13)) + DetCalc_13 = max(tiny, state(k, idetcal_13) + sms(k, idetcal_13)) + + ! 13C calcite dissolution with fractionation + calc_diss_13 = alpha_dcal_13 * calc_diss + + ! 13C quotas + quota_13 = PhyN / PhyC_13 + recipQuota_13 = real(one) / quota_13 + quota_dia_13 = DiaN / DiaC_13 + recipQuota_dia_13 = real(one) / quota_dia_13 + recipQZoo_13 = HetC_13 / HetN + + ! 14C radiocarbon tracers (if enabled) + if (ciso_14) then + DIC_14 = max(tiny, state(k,idic_14) + sms(k, idic_14)) + + if (ciso_organic_14) then + PhyC_14 = max(tiny_C, state(k,iphyc_14) + sms(k, iphyc_14)) + DetC_14 = max(tiny, state(k,idetc_14) + sms(k, idetc_14)) + HetC_14 = max(tiny, state(k,ihetc_14) + sms(k, ihetc_14)) + EOC_14 = max(tiny, state(k,idoc_14) + sms(k, idoc_14)) + DiaC_14 = max(tiny_C, state(k,idiac_14) + sms(k, idiac_14)) + PhyCalc_14 = max(tiny, state(k,iphycal_14) + sms(k, iphycal_14)) + DetCalc_14 = max(tiny, state(k,idetcal_14) + sms(k, idetcal_14)) + + calc_diss_14 = alpha_dcal_14 * calc_diss + + quota_14 = PhyN / PhyC_14 + recipQuota_14 = real(one) / quota_14 + quota_dia_14 = DiaN / DiaC_14 + recipQuota_dia_14 = real(one) / quota_dia_14 + recipQZoo_14 = HetC_14 / HetN + end if ! ciso_organic_14 + end if ! ciso_14 + end if ! ciso + + !=============================================================================== + ! TEMPERATURE DEPENDENCE OF METABOLIC RATES + !=============================================================================== + ! Calculates how temperature affects biological rates using multiple + ! formulations appropriate for different organism groups. + ! + ! General Principle: + ! - Metabolic rates increase exponentially with temperature (Q10 rule) + ! - Different organisms have different thermal optima and tolerances + ! - Cold-adapted vs warm-adapted species + ! + ! Variables (Arrhenius): + ! rTloc : Inverse of local absolute temperature [K-1] + ! arrFunc : Arrhenius temperature function [-] + ! Temp(k) : Temperature at depth k [degC] + ! C2K : Celsius to Kelvin conversion (273.15) [K] + ! Ae : Activation energy parameter [K] + ! rTref : Inverse reference temperature (1/288.15 K at 15degC) [K-1] + ! + ! Alternative Formulations (commented in code): + ! - Eppley (1972): Log-linear for phytoplankton + ! - Li (1980): Parabolic curve + ! - Ahlgren (1987): Optimum curve + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Standard Arrhenius Function + !------------------------------------------------------------------------------- + ! General metabolic rate temperature dependence (Schourup 2013, Eq. A54) + ! Exponential increase with temperature (no upper thermal limit) + ! + ! Equation: + ! f(T) = exp(-Ae × (1/T - 1/Tref)) + ! + ! Where: + ! - Ae: Slope of Arrhenius plot (activation energy/gas constant) + ! - Tref: Reference temperature (typically 15degC = 288.15 K) + ! - T: Absolute temperature [K] + ! + ! Used for: Most metabolic processes without strong thermal limits + ! (e.g., remineralization, basal metabolism) + + ! Calculate inverse absolute temperature + rTloc = real(one) / (Temp(k) + C2K) + + ! Calculate Arrhenius function + arrFunc = exp(-Ae * (rTloc - rTref)) + + !------------------------------------------------------------------------------- + ! Phytoplankton-Specific Temperature Functions + !------------------------------------------------------------------------------- + ! Species-specific exponential and optimum-curve temperature responses + ! Tuned for 4-plankton functional type version (small phyto, diatoms, coccos, Phaeocystis) + ! + ! Note: New functions require calibration if adapted to 2-plankton version + !------------------------------------------------------------------------------- + + ! Old coccolithophore temperature function (commented out): + ! Power law form from Fielding (2013) based on observational growth rates + ! if (enable_coccos) then + ! CoccoTFunc = max(0.1419d0 * Temp(k)**0.8151d0, tiny) + ! endif + + if (enable_coccos) then + + !--------------------------------------------------------------------------- + ! Small Phytoplankton + !--------------------------------------------------------------------------- + ! Exponential temperature response: f(T) = exp(a + b×T) + ! Represents diverse group with broad thermal tolerance + ! Monotonic increase with temperature (no upper limit in this formulation) + + Temp_phyto = exp(ord_phy + expon_phy * Temp(k)) + VTTemp_phyto(k) = Temp_phyto ! Store for diagnostics + + !--------------------------------------------------------------------------- + ! Diatoms + !--------------------------------------------------------------------------- + ! Large phytoplankton with silica frustules + ! Exponential form with different parameters than small phyto + ! Generally favored by cooler, nutrient-rich conditions + + Temp_diatoms = exp(ord_d + expon_d * Temp(k)) + VTTemp_diatoms(k) = Temp_diatoms ! Store for diagnostics + + !--------------------------------------------------------------------------- + ! Coccolithophores + !--------------------------------------------------------------------------- + ! Calcifying phytoplankton with minimum temperature threshold + ! Cold-intolerant: minimal growth below 5degC + ! Exponential increase above threshold temperature + ! + ! Ecological rationale: Coccos typically dominate in warm, stratified waters + + if (Temp(k) < 5.0) then + ! Below threshold: minimal metabolic activity + Temp_cocco = tiny + else + ! Above threshold: exponential response + Temp_cocco = exp(ord_cocco + expon_cocco * Temp(k)) + Temp_cocco = max(Temp_cocco, tiny) ! Ensure positive values + end if + VTTemp_cocco(k) = Temp_cocco ! Store for diagnostics + + !--------------------------------------------------------------------------- + ! Phaeocystis + !--------------------------------------------------------------------------- + ! Colonial phytoplankton with bell-shaped temperature response + ! Blanchard function from Grimaud et al. (2017) + ! Has optimal temperature with decline at high and low temperatures + ! + ! Equation: f(T) = uopt × ((Tmax-T)/(Tmax-Topt))^β × exp(-β×(Topt-T)/(Tmax-Topt)) + ! + ! Where: + ! - uopt: Maximum growth rate at optimal temperature [day-1] + ! - Topt: Optimal temperature [degC] + ! - Tmax: Maximum temperature (growth = 0) [degC] + ! - β: Shape parameter (steepness of curve) [-] + ! + ! Ecological rationale: Phaeocystis blooms occur at specific temperature ranges + ! (typically cold-temperate waters, 0-10degC) + + Temp_phaeo = uopt_phaeo * ((Tmax_phaeo - Temp(k)) / (Tmax_phaeo - Topt_phaeo))**beta_phaeo & + * exp(-beta_phaeo * (Topt_phaeo - Temp(k)) / (Tmax_phaeo - Topt_phaeo)) + Temp_phaeo = max(Temp_phaeo, tiny) ! Ensure positive values + VTTemp_phaeo(k) = Temp_phaeo ! Store for diagnostics + + endif + + !------------------------------------------------------------------------------- + ! Zooplankton Temperature Dependencies + !------------------------------------------------------------------------------- + ! Temperature functions for different zooplankton types with thermal limits + ! Q10 formulations: exponential increase with ~doubling per 10degC + + if (enable_3zoo2det) then + + !--------------------------------------------------------------------------- + ! Macrozooplankton (Krill) Temperature Function + !--------------------------------------------------------------------------- + ! Sigmoid function with upper thermal limit + ! Accounts for thermal stress at high temperatures + ! + ! Equation: f(T) = exp(t1/t2 - t1/T) / (1 + exp(t3/t4 - t3/T)) + ! + ! Numerator: Exponential increase with temperature + ! Denominator: Sigmoid decline at high temperatures (thermal stress) + ! + ! Ecological rationale: Macrozooplankton have defined thermal niches + ! (e.g., Antarctic krill prefer cold water, decline above ~4degC) + + arrFuncZoo2 = exp(t1_zoo2 / t2_zoo2 - t1_zoo2 * rTloc) / & + (1.0 + exp(t3_zoo2 / t4_zoo2 - t3_zoo2 * rTloc)) + + !--------------------------------------------------------------------------- + ! Q10 Temperature Coefficients + !--------------------------------------------------------------------------- + ! Q10 formulation: rate = Q10^(T/10) + ! Simple exponential increase with temperature + ! + ! Q10 values: + ! - ~1.02-1.04: Moderate temperature sensitivity (typical for metabolism) + ! - ~1.09: Higher sensitivity (respiration processes) + ! + ! Ecological interpretation: + ! - Smaller organisms (microzooplankton) often have higher Q10 + ! - Respiration Q10 > growth Q10 (maintenance costs increase faster) + + q10_mes = 1.0242**(Temp(k)) ! Mesozooplankton metabolism + q10_mic = 1.04**(Temp(k)) ! Microzooplankton metabolism + q10_mes_res = 1.0887**(Temp(k)) ! Mesozooplankton respiration + q10_mic_res = 1.0897**(Temp(k)) ! Microzooplankton respiration + + endif + + !------------------------------------------------------------------------------- + ! Silicate Dissolution Temperature Dependence + !------------------------------------------------------------------------------- + ! Temperature effect on biogenic silica (diatom frustule) dissolution + ! Higher temperatures accelerate chemical dissolution kinetics + ! + ! Variables: + ! reminSiT : Temperature-dependent Si dissolution rate [day-1] + ! reminSi : Minimum dissolution rate [day-1] + ! + ! Exponential formulation: 2.6× increase per 10degC + ! Reference temperature: 10degC + ! + + reminSiT = max(0.023d0 * 2.6d0**((Temp(k) - 10.0) / 10.0), reminSi) + + ! Alternative Kamatani (1982) function (commented out): + ! reminSiT = min(1.32e16 * exp(-11200.d0 * rTloc), reminSi) + + !=============================================================================== + ! 2. OXYGEN DEPENDENCE OF REMINERALIZATION + !=============================================================================== + ! Calculates oxygen limitation effects on aerobic organic matter decomposition. + ! Important for oxygen minimum zones (OMZs) and suboxic/anoxic environments. + ! + ! Variables: + ! O2Func : Oxygen limitation factor [0-1, 0=anoxic, 1=oxic] + ! O2 : Dissolved oxygen concentration [mmolO2 m-3] + ! k_o2_remin : Half-saturation for O2-limited remineralization [mmolO2 m-3] + ! O2dep_remin : Flag to enable O2-dependent remineralization [logical] + ! + ! Michaelis-Menten Formulation: + ! f(O2) = O2 / (k_O2 + O2) + ! + ! Parameter Value: + ! k_o2_remin = 15 mmolO2 m-3 (half-saturation constant) + ! Range: 0-30 mmolO2 m-3 based on DeVries & Weber (2017), cited in Cram (2018) + ! + ! Ecological/Biogeochemical Significance: + ! - Aerobic respiration dominates in oxic waters (O2 > 30 mmol m-3) + ! - Suboxic/anoxic metabolism (denitrification, sulfate reduction) in OMZs + ! - Reduced remineralization efficiency in low-O2 environments + ! - Important for nutrient cycling and carbon export in OMZs + ! + ! Note: When O2 < 0.1 mmol m-3, consider switching to anaerobic pathways + ! (not implemented in this version) + !------------------------------------------------------------------------------- + + ! Default: no oxygen limitation (fully oxic conditions) + O2Func = 1.d0 + + if (O2dep_remin) then + ! Enable oxygen-dependent remineralization + ! Michaelis-Menten type limitation + ! Becomes significant when O2 < ~30 mmol m-3 + O2Func = O2 / (k_o2_remin + O2) + endif + + !=============================================================================== + ! LIGHT AVAILABILITY CALCULATION + !=============================================================================== + ! Calculates photosynthetically available radiation (PAR) through the water + ! column using Beer-Lambert law with chlorophyll-based attenuation. + ! + ! Light Attenuation Components: + ! 1. Water attenuation (k_w): Clear water absorption and scattering + ! 2. Chlorophyll attenuation (a_chl): Phytoplankton self-shading + ! + ! Variables: + ! PARave : Average PAR at depth k [W m-2] + ! PAR(k) : Stored PAR for layer k [W m-2] + ! SurfSR : Surface solar radiation [W m-2] + ! chl_upper : Chlorophyll at upper layer boundary [mgChl m-3] + ! chl_lower : Chlorophyll at lower layer boundary [mgChl m-3] + ! Chlave : Average chlorophyll in layer [mgChl m-3] + ! kappa : Total attenuation coefficient [m-1] + ! kappastar : Angle-corrected attenuation coefficient [m-1] + ! k_w : Water attenuation coefficient [m-1] + ! a_chl : Chlorophyll-specific attenuation [(m2 mgChl-1)] + ! cosAI(n) : Cosine of solar zenith angle [-] + ! thick(k) : Layer thickness [m] + ! kdzLower : Cumulative optical depth [dimensionless] + ! kdzUpper : Cumulative optical depth at upper boundary [dimensionless] + ! + ! Beer-Lambert Law: + ! I(z) = I0 × exp(-κ×z) + ! where κ = k_w + a_chl×[Chl] + ! + ! Self-Shading Effect: + ! - High chlorophyll reduces light penetration + ! - Limits bloom depth and total biomass + ! - Creates trade-off between cell density and light availability + ! + ! Ecological Significance: + ! - Defines euphotic zone depth (1% surface light) + ! - Controls vertical distribution of primary production + ! - Self-shading is key negative feedback on bloom magnitude + !------------------------------------------------------------------------------- + + if (k == 1) then + + !=========================================================================== + ! SURFACE LAYER INITIALIZATION + !=========================================================================== + ! Surface layer receives full incident solar radiation + ! Initialize chlorophyll and optical depth for subsurface calculations + !--------------------------------------------------------------------------- + + ! Surface PAR equals incident solar radiation + PARave = max(tiny, SurfSR) + PAR(k) = PARave + + ! Initialize surface chlorophyll for attenuation calculation + ! Sum all phytoplankton functional types + chl_upper = (PhyChl + DiaChl) ! Base groups (always present) + + if (enable_coccos) then + ! Add coccolithophores and Phaeocystis if enabled + chl_upper = chl_upper + CoccoChl + PhaeoChl + endif + else + + !=========================================================================== + ! SUBSURFACE LIGHT ATTENUATION + !=========================================================================== + ! Calculate light penetration through water column using Beer-Lambert law + ! with chlorophyll-based self-shading + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Calculate Current Layer Chlorophyll + !--------------------------------------------------------------------------- + + chl_lower = PhyChl + DiaChl + + if (enable_coccos) then + chl_lower = chl_lower + CoccoChl + PhaeoChl + endif + + ! Average chlorophyll between layer boundaries + ! Assumes linear interpolation within layer + Chlave = (chl_upper + chl_lower) * 0.5 + + !--------------------------------------------------------------------------- + ! Calculate Attenuation Coefficient + !--------------------------------------------------------------------------- + + ! Total attenuation coefficient + ! k_w: Clear water absorption (~0.04 m-1 in ocean) + ! a_chl: Chlorophyll-specific attenuation (~0.03-0.05 m2 mgChl-1) + kappa = k_w + a_chl * Chlave + + ! Correct for solar zenith angle (path length through water) + ! Lower sun angle -> longer path -> more attenuation + kappastar = kappa / cosAI(n) + + ! Cumulative optical depth (dimensionless) + ! Integrates attenuation over depth + kdzLower = kdzUpper + kappastar * thick(k - 1) + + !--------------------------------------------------------------------------- + ! Calculate Light at Layer + !--------------------------------------------------------------------------- + + ! Beer-Lambert law: exponential decay with optical depth + Lowerlight = SurfSR * exp(-kdzLower) + Lowerlight = max(tiny, Lowerlight) ! Ensure positive value + + ! Store PAR for this layer + PARave = Lowerlight + PAR(k) = PARave + + ! Update variables for next layer + chl_upper = chl_lower ! Current lower becomes next upper + kdzUpper = kdzLower ! Current cumulative depth for next layer + + end if + + !=============================================================================== + ! MARINE CARBONATE SYSTEM CALCULATIONS (MOCSY) + !=============================================================================== + ! Calculates complete marine carbonate chemistry using the MOCSY package + ! (Marine Ocean Carbon System Solver). + ! + ! This module calculates: + ! 1. Carbonate system speciation (CO2, HCO3-, CO3--) + ! 2. pH and partial pressure of CO2 (pCO2) + ! 3. Carbonate saturation states (Omega for calcite and aragonite) + ! 4. Solubility products and seawater properties + ! + ! Key Features: + ! - Adaptive update frequency (depth-dependent) + ! - Euphotic zone: Weekly updates (high biological activity) + ! - Deep waters: Monthly updates (slower changes) + ! - Complete thermodynamic consistency + ! - Pressure correction for depth + ! + ! MOCSY Package: + ! - Developed for OCMIP5 project + ! - Solves carbonate system from two known parameters + ! - Accounts for temperature, salinity, pressure effects + ! - Multiple equilibrium constant formulations available + ! + ! Update Strategy: + ! - Initialize on first time step (mstep = 1) + ! - Euphotic zone (PAR > 1% surface): 7-day updates + ! - Deep waters (PAR < 1% surface): 30-day updates + ! - Rationale: Biological activity drives rapid changes near surface + ! + ! Input Parameters: + ! - Temperature, Salinity (from physical model) + ! - DIC, Alkalinity (from biogeochemical tracers) + ! - Silicate, Phosphate (affects equilibrium constants) + ! - Atmospheric pressure, Latitude (for gas exchange) + ! + ! Output Variables: + ! - pH, pCO2, fCO2 (CO2 partial and fugacity) + ! - CO2, HCO3-, CO3-- (carbonate species concentrations) + ! - OmegaC, OmegaA (calcite and aragonite saturation) + ! - Solubility products, seawater density + ! + ! Ecological/Biogeochemical Significance: + ! - Controls CO2 uptake/release (air-sea exchange) + ! - Regulates calcification and dissolution rates + ! - Affects phytoplankton carbon acquisition + ! - Critical for ocean acidification studies + ! + ! References: + ! - MOCSY: http://ocmip5.ipsl.jussieu.fr/mocsy/ + ! - Orr & Epitalon (2015) - MOCSY 2.0 user guide + !=============================================================================== + + !=============================================================================== + ! PREPARATION AND INITIALIZATION + !=============================================================================== + ! Prepares input data and initializes carbonate system on first time step. + ! + ! Variables: + ! dpos(1) : Depth for pressure calculations [m, positive down] + ! zF(k) : Model depth coordinate [m, negative down] + ! mstep : Model time step counter [-] + ! k : Vertical layer index [-] + ! + ! Input Arrays for MOCSY: + ! REcoM_T_depth : Temperature [degC, potential temperature] + ! REcoM_S_depth : Salinity [psu, practical salinity] + ! REcoM_Alk_depth : Total alkalinity [mol m-3] + ! REcoM_DIC_depth : Dissolved inorganic carbon [mol m-3] + ! REcoM_Si_depth : Silicate concentration [mol m-3] + ! REcoM_Phos_depth : Phosphate concentration [mol m-3] + ! Patm_depth : Atmospheric pressure [atm] + ! Latd : Latitude [degrees] + ! Nmocsy : Number of points (1 for single depth) + ! + ! Note: Depth convention conversion required (model uses negative depths) + !------------------------------------------------------------------------------- + + ! Convert model depth coordinate to positive depth for MOCSY + ! Model convention: zF(k) is negative (e.g., -100 m) + ! MOCSY convention: depth is positive (e.g., 100 m) dpos(1) = -zF(k) - if (mstep==1) then - call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & - rhoSW_depth, p_depth, tempis_depth, & - REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & - optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + !=============================================================================== + ! INITIAL CARBONATE SYSTEM CALCULATION + !=============================================================================== + ! Calculates complete carbonate system on first model time step. + ! Provides initial conditions for all carbonate chemistry variables. + ! + ! Output Variables (from MOCSY): + ! ph_depth(1) : pH on total scale [-] + ! pco2_depth(1) : Partial pressure of CO2 [μatm] + ! fco2_depth(1) : Fugacity of CO2 [μatm] + ! co2_depth(1) : Dissolved CO2 concentration [mol m-3] + ! hco3_depth(1) : Bicarbonate concentration [mol m-3] + ! co3_depth(1) : Carbonate ion concentration [mol m-3] + ! OmegaA_depth(1) : Aragonite saturation state [-] + ! OmegaC_depth(1) : Calcite saturation state [-] + ! kspc_depth(1) : Calcite solubility product [mol2 kg-2] + ! BetaD_depth(1) : Revelle factor (buffer capacity) [-] + ! rhoSW_depth(1) : Seawater density [kg m-3] + ! p_depth(1) : Pressure [bar] + ! tempis_depth(1) : In situ temperature [degC] + ! + ! Water Column Storage: + ! CO2_watercolumn(k) : Stored CO2 for biological calculations [mol m-3] + ! pH_watercolumn(k) : Stored pH [-] + ! pCO2_watercolumn(k) : Stored pCO2 [μatm] + ! HCO3_watercolumn(k) : Stored bicarbonate [mol m-3] + ! CO3_watercolumn(k) : Stored carbonate [mol m-3] + ! OmegaC_watercolumn(k) : Stored calcite saturation [-] + ! kspc_watercolumn(k) : Stored solubility product [mol2 kg-2] + ! rhoSW_watercolumn(k) : Stored seawater density [kg m-3] + ! + ! MOCSY Options: + ! optCON='mol/m3' : Concentration units (mol/m3) + ! optT='Tpot ' : Temperature is potential temperature + ! optP='m ' : Pressure given as depth in meters + ! optB='u74' : Boron:Salinity ratio from Uppström (1974) + ! optK1K2='l ' : Carbonic acid constants from Lueker et al. (2000) + ! optKf='dg' : HF constant from Dickson & Goyet (1994) + ! optGAS='Pinsitu' : Pressure is in situ (accounts for depth) + ! optS='Sprc' : Salinity on practical scale + !------------------------------------------------------------------------------- + + if (mstep == 1) then + + ! Call MOCSY to solve carbonate system + ! Uses DIC and Alkalinity as input pair (most common in ocean models) + call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, & + OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & + rhoSW_depth, p_depth, tempis_depth, & + REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, & + REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & + optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', & + optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + ! Store results in water column arrays for use in biogeochemical calculations CO2_watercolumn(k) = co2_depth(1) pH_watercolumn(k) = ph_depth(1) pCO2_watercolumn(k) = pco2_depth(1) @@ -348,18 +1505,72 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & OmegaC_watercolumn(k) = OmegaC_depth(1) kspc_watercolumn(k) = kspc_depth(1) rhoSW_watercolumn(k) = rhoSW_depth(1) - endif - -!! Calculate carbonate system every 7 days for depths < 1%PAR, and every 30 days for the depths below. - mocsy_step_per_day = 1/dt_b ! NEW ms: time steps per day in recom -> is that correct? Not necessary to define in namelist? - logfile_outfreq_7 = mocsy_step_per_day*7 - logfile_outfreq_30 = mocsy_step_per_day*30 - - if (PARave > 0.01*SurfSR .and. mod(mstep,logfile_outfreq_7)==0) then - call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & - rhoSW_depth, p_depth, tempis_depth, & - REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & - optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + endif + + !=============================================================================== + ! ADAPTIVE CARBONATE SYSTEM UPDATE FREQUENCY + !=============================================================================== + ! Determines how often to recalculate carbonate system based on depth. + ! More frequent updates where biological activity drives rapid changes. + ! + ! Variables: + ! mocsy_step_per_day : Number of model time steps per day [-] + ! dt_b : Model time step [days] + ! logfile_outfreq_7 : Number of steps in 7 days [-] + ! logfile_outfreq_30 : Number of steps in 30 days [-] + ! PARave : Average photosynthetically active radiation [W m-2] + ! SurfSR : Surface solar radiation [W m-2] + ! + ! Update Strategy: + ! - Euphotic zone (PAR > 1% surface): 7-day updates + ! * High photosynthesis rates alter DIC and pH rapidly + ! * Important for accurate phytoplankton CO2 responses + ! - Deep waters (PAR < 1% surface): 30-day updates + ! * Slower changes dominated by remineralization and mixing + ! * Reduces computational cost while maintaining accuracy + ! + ! Computational Cost Considerations: + ! - Carbonate system solving is computationally expensive + ! - Adaptive frequency balances accuracy and performance + ! - Typical speedup: 4× faster than daily updates everywhere + !------------------------------------------------------------------------------- + + ! Calculate update frequencies based on model time step + mocsy_step_per_day = 1.0 / dt_b + logfile_outfreq_7 = mocsy_step_per_day * 7.0 ! Steps in 7 days + logfile_outfreq_30 = mocsy_step_per_day * 30.0 ! Steps in 30 days + + !=============================================================================== + ! EUPHOTIC ZONE UPDATES (WEEKLY) + !=============================================================================== + ! Frequent updates in sunlit surface waters where biological activity is high. + ! Euphotic zone defined as PAR > 1% of surface irradiance. + ! + ! Biological Drivers: + ! - Photosynthesis removes DIC, increases pH + ! - Respiration/remineralization adds DIC, decreases pH + ! - Calcification removes alkalinity + ! - Rapid daily and seasonal cycles + ! + ! Why 7-day updates? + ! - Captures weekly-scale biological dynamics + ! - Adequate for phytoplankton bloom progression + ! - Reasonable computational cost + !------------------------------------------------------------------------------- + + if (PARave > 0.01 * SurfSR .and. mod(mstep, logfile_outfreq_7) == 0) then + + ! Weekly updates in euphotic zone (high biological activity) + call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, & + OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & + rhoSW_depth, p_depth, tempis_depth, & + REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, & + REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & + optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', & + optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + ! Update water column arrays with new carbonate chemistry CO2_watercolumn(k) = co2_depth(1) pH_watercolumn(k) = ph_depth(1) pCO2_watercolumn(k) = pco2_depth(1) @@ -369,11 +1580,39 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & kspc_watercolumn(k) = kspc_depth(1) rhoSW_watercolumn(k) = rhoSW_depth(1) - elseif (PARave < 0.01*SurfSR .and. mod(mstep,logfile_outfreq_30)==0) then - call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & - rhoSW_depth, p_depth, tempis_depth, & - REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & - optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + !=============================================================================== + ! DEEP WATER UPDATES (MONTHLY) + !=============================================================================== + ! Less frequent updates in dark deep waters where changes are slower. + ! Deep waters defined as PAR < 1% of surface irradiance. + ! + ! Physical/Chemical Drivers: + ! - Slow remineralization of sinking organic matter + ! - Calcite dissolution (below saturation horizon) + ! - Mixing and advection + ! - No photosynthesis to drive rapid changes + ! + ! Why 30-day updates? + ! - Changes occur on monthly to seasonal timescales + ! - Dominated by physical transport and slow remineralization + ! - Significant computational savings with minimal accuracy loss + ! + ! Note: Below permanent pycnocline, even longer update intervals + ! could be justified (e.g., seasonal) + !------------------------------------------------------------------------------- + + elseif (PARave < 0.01 * SurfSR .and. mod(mstep, logfile_outfreq_30) == 0) then + + ! Monthly updates in deep waters (low biological activity) + call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, & + OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & + rhoSW_depth, p_depth, tempis_depth, & + REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, & + REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & + optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', & + optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + ! Update water column arrays with new carbonate chemistry CO2_watercolumn(k) = co2_depth(1) pH_watercolumn(k) = ph_depth(1) pCO2_watercolumn(k) = pco2_depth(1) @@ -382,741 +1621,2408 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & OmegaC_watercolumn(k) = OmegaC_depth(1) kspc_watercolumn(k) = kspc_depth(1) rhoSW_watercolumn(k) = rhoSW_depth(1) + endif -!------------------------------------------------------------------------------- -! CO2 dependence of rates ! NEW CO2 -!------------------------------------------------------------------------------- -! Convert pH to proton concentration - h_depth(1) = 10.**(-ph_depth(1)) -! Conversion factor Cunits not needed for [H], because in model and function derived from pH and therefore in [mol/L] + if (NitrogenSS) then + ! This part has been developpes for R2OMIP for calculating bottom ocean OmegaC + nzmax=nlevels_nod2D(n)-1 + nzmin=ulevels_nod2D(n) + k_bottom=nod_in_elem2D_num(n) + + ! Screening minimum depth in neigbouring nodes around node n + nlevels_nod2D_minimum=minval(nlevels(nod_in_elem2D(1:k_bottom, n))-1) + + if (k >= nlevels_nod2D_minimum .and. k < nzmax) then + OmegaC_bottom(n) = (OmegaC_depth(1) * (area(k,n)-area(k+1,n)) / area(k,n)) + + else if (k == nzmax) then + OmegaC_bottom(n) = (OmegaC_depth(1) * (area(k+1,n) / area(k,n))) + else + OmegaC_bottom(n) = 0.0_WP + end if + endif + + !=============================================================================== + ! CO2 EFFECTS AND CALCITE DISSOLUTION + !=============================================================================== + ! Simulates ocean acidification impacts on phytoplankton growth and calcium + ! carbonate dissolution in the water column. + ! + ! This module calculates: + ! 1. CO2/pH effects on phytoplankton photosynthesis (species-specific) + ! 2. Calcite dissolution rates (saturation-state or depth-dependent) + ! + ! Key Features: + ! - Multi-component CO2 response (HCO3- benefit, CO2 toxicity, pH stress) + ! - Species-specific sensitivities to ocean acidification + ! - Two dissolution mechanisms (thermodynamic vs empirical) + ! - Velocity-dependent dissolution for sinking particles + ! + ! CO2 Response Function: + ! f(CO2) = a×[HCO3-]/(b+[HCO3-]) - exp(-c×[CO2]) - d×[H+] + ! + ! Three competing effects: + ! 1. HCO3- availability (substrate for carbon fixation) - POSITIVE + ! 2. High CO2 concentration (toxicity/stress) - NEGATIVE + ! 3. Low pH (proton stress on enzymes) - NEGATIVE + ! + ! Phytoplankton Groups: + ! - Small phytoplankton: Moderate sensitivity + ! - Diatoms: Generally tolerant + ! - Coccolithophores: High sensitivity (calcifying organisms) + ! - Phaeocystis: Variable sensitivity + ! + ! Dissolution Mechanisms: + ! A) Saturation-state dependent (OmegaC_diss = TRUE) + ! - Thermodynamically based on carbonate saturation + ! - Aumont et al. (2015) parameterization + ! B) Depth-dependent (OmegaC_diss = FALSE) + ! - Empirical dissolution rates scaled by sinking velocity + ! + ! Ecological/Biogeochemical Significance: + ! - Ocean acidification reduces calcification and alters competitive balance + ! - Dissolution releases CO2 and alkalinity back to seawater + ! - Critical for understanding climate change impacts on marine ecosystems + ! + ! References: + ! - Aumont et al. (2015) - Saturation-state dependent dissolution + ! - Schourup-Kristensen et al. (2013) - REcoM model description + !=============================================================================== + + !=============================================================================== + ! CO2 EFFECTS ON PHYTOPLANKTON GROWTH + !=============================================================================== + ! Calculates how ocean acidification (elevated CO2, reduced pH) affects + ! phytoplankton photosynthesis rates through a complex response function. + ! + ! Response Function Components: + ! 1. Michaelis-Menten HCO3- uptake (carbonate benefit) + ! 2. Exponential CO2 inhibition (high CO2 toxicity) + ! 3. Linear H+ inhibition (pH stress on cellular processes) + ! + ! Variables (Small Phytoplankton): + ! PhyCO2 : CO2 effect modifier for small phyto [0-3] + ! a_co2_phy : HCO3- uptake parameter [-] + ! b_co2_phy : HCO3- half-saturation [mmolC m-3] + ! c_co2_phy : CO2 inhibition coefficient [m3 mmolC-1] + ! d_co2_phy : H+ stress coefficient [L mol-1] + ! HCO3_watercolumn(k) : Bicarbonate concentration [mmolC m-3] + ! CO2_watercolumn(k) : Dissolved CO2 concentration [mmolC m-3] + ! pH_watercolumn(k) : Water column pH [-] + ! Cunits : Concentration units conversion factor [-] + ! h_depth(1) : Proton concentration at surface [mol L-1] + ! VTPhyCO2(k) : Diagnostic output for CO2 effect [-] + ! + ! Constraints: + ! - Upper limit: 3× enhancement (April 2022 modification) + ! - Lower limit: 0 (no negative values, July 2022 modification) + ! + ! Note: Similar calculations for diatoms, coccolithophores, and Phaeocystis + ! with species-specific parameters reflecting different sensitivities + !------------------------------------------------------------------------------- + + ! Convert pH to proton concentration for calculations + ! pH = -log10[H+], therefore [H+] = 10^(-pH) + h_depth(1) = 10.d0**(-ph_depth(1)) + + ! Note: Cunits conversion not needed for [H+] because pH is already in mol/L + + !------------------------------------------------------------------------------- + ! Small Phytoplankton CO2 Response + !------------------------------------------------------------------------------- + ! Moderate sensitivity to ocean acidification + ! Represents diverse group with varied carbon acquisition strategies -! Small phytoplankton PhyCO2 = a_co2_phy * HCO3_watercolumn(k) * Cunits / (b_co2_phy + HCO3_watercolumn(k) * Cunits) & - - exp(-c_co2_phy * CO2_watercolumn(k) * Cunits) - d_co2_phy * 10.**(-pH_watercolumn(k)) - PhyCO2 = min(PhyCO2,3.d0) ! April 2022: limitation to 3 - PhyCO2 = max(0.d0,PhyCO2) ! July 2022: limitation to zero + - exp(-c_co2_phy * CO2_watercolumn(k) * Cunits) & + - d_co2_phy * 10.d0**(-pH_watercolumn(k)) + + ! Apply empirical constraints based on observations + PhyCO2 = min(PhyCO2, 3.d0) ! Upper limit: maximum 3x enhancement + PhyCO2 = max(0.d0, PhyCO2) ! Lower limit: prevent negative growth response + + ! Store for diagnostics and output + VTPhyCO2(k) = PhyCO2 + + !------------------------------------------------------------------------------- + ! Diatoms CO2 Response + !------------------------------------------------------------------------------- + ! Generally tolerant to elevated CO2 + ! Efficient carbon concentrating mechanisms (CCMs) -! Diatoms DiaCO2 = a_co2_dia * HCO3_watercolumn(k) * Cunits / (b_co2_dia + HCO3_watercolumn(k) * Cunits) & - - exp(-c_co2_dia * CO2_watercolumn(k) * Cunits) - d_co2_dia * 10.**(-pH_watercolumn(k)) - DiaCO2 = min(DiaCO2,3.d0) ! April 2022: limitation to 3 - DiaCO2 = max(0.d0,DiaCO2) ! July 2022: limitation to zero - -#if defined (__coccos) -! Coccolithophores - CoccoCO2 = a_co2_cocco * HCO3_watercolumn(k) * Cunits / (b_co2_cocco + HCO3_watercolumn(k) * Cunits) & - - exp(-c_co2_cocco * CO2_watercolumn(k) * Cunits) - d_co2_cocco * 10.**(-pH_watercolumn(k)) - CoccoCO2 = min(CoccoCO2,3.d0) ! April 2022: limitation to 3 - CoccoCO2 = max(0.d0,CoccoCO2) ! July 2022: limitation to zero -#endif - - -!------------------------------------------------------------------------------ -! Calcite dissolution dependent on OmegaC ! DISS -!------------------------------------------------------------------------------ - Sink_Vel = Vdet_a* abs(zF(k)) + Vdet - - if (OmegaC_diss) then ! Calcdiss dependent on carbonate saturation - Ca = (0.02128d0/40.078d0) * Sali_depth(k)/1.80655d0 ! Calcium ion concentration [mol/kg], function from varsolver.f90 - CO3_sat = (kspc_watercolumn(k) / Ca) * rhoSW_watercolumn(k) ! Saturated carbonate ion concentration, converted to [mol/m3] - calc_diss = calc_diss_omegac * max(zero,(1-(CO3_watercolumn(k)/CO3_sat)))**(calc_diss_exp) ! Dissolution rate scaled by carbonate ratio, after Aumont et al. 2015 -#if defined (__3Zoo2Det) - calc_diss2 = calc_diss -#endif - calc_diss_ben = calc_diss - else ! Calcdiss dependent on depth - - calc_diss = calc_diss_rate * Sink_Vel/20.d0 ! Dissolution rate of CaCO3 scaled by the sinking velocity at the current depth -#if defined (__3Zoo2Det) -! calc_diss2 = calc_diss_rate2 ! Dissolution rate of CaCO3 scaled by the sinking velocity at the current depth seczoo - calc_diss2 = calc_diss_rate2* Sink_Vel/20.d0 -#endif - calc_diss_ben = calc_diss_rate * Sink_Vel/20.d0 ! DISS added the variable calc_diss_ben to keep the calcite dissolution in the benthos with the old formulation + - exp(-c_co2_dia * CO2_watercolumn(k) * Cunits) & + - d_co2_dia * 10.d0**(-pH_watercolumn(k)) + + ! Apply constraints + DiaCO2 = min(DiaCO2, 3.d0) ! Upper limit: 3x enhancement + DiaCO2 = max(0.d0, DiaCO2) ! Lower limit: no negative effect + + ! Store for diagnostics + VTDiaCO2(k) = DiaCO2 + + if (enable_coccos) then + + !--------------------------------------------------------------------------- + ! Coccolithophores CO2 Response + !--------------------------------------------------------------------------- + ! Calcifying phytoplankton - highly sensitive to ocean acidification + ! Both photosynthesis and calcification affected by carbonate chemistry + ! May be disadvantaged under future high-CO2 conditions + + CoccoCO2 = a_co2_cocco * HCO3_watercolumn(k) * Cunits / (b_co2_cocco + HCO3_watercolumn(k) * Cunits) & + - exp(-c_co2_cocco * CO2_watercolumn(k) * Cunits) & + - d_co2_cocco * 10.d0**(-pH_watercolumn(k)) + + ! Apply constraints + CoccoCO2 = min(CoccoCO2, 3.d0) ! Upper limit: 3x enhancement + CoccoCO2 = max(0.d0, CoccoCO2) ! Lower limit: no negative effect + + ! Store for diagnostics + VTCoccoCO2(k) = CoccoCO2 + + !--------------------------------------------------------------------------- + ! Phaeocystis CO2 Response + !--------------------------------------------------------------------------- + ! Colonial phytoplankton with variable CO2 sensitivity + ! Response may depend on bloom stage and environmental conditions + + PhaeoCO2 = a_co2_phaeo * HCO3_watercolumn(k) * Cunits / (b_co2_phaeo + HCO3_watercolumn(k) * Cunits) & + - exp(-c_co2_phaeo * CO2_watercolumn(k) * Cunits) & + - d_co2_phaeo * 10.d0**(-pH_watercolumn(k)) + + ! Apply constraints + PhaeoCO2 = min(PhaeoCO2, 3.d0) ! Upper limit: 3× enhancement + PhaeoCO2 = max(0.d0, PhaeoCO2) ! Lower limit: no negative effect + + ! Store for diagnostics + VTPhaeoCO2(k) = PhaeoCO2 + endif -!------------------------------------------------------------------------------- -!> Photosynthesis section, light parameters and rates -!------------------------------------------------------------------------------- -!< Schourup 2013 Appendix A6.2 -!< Intracellular regulation of C uptake -!< qlimitFac, qlimitFacTmp: Factor that regulates photosynthesis -!< NMinSlope: 50.d0 -!< NCmin: 0.04d0 -!< quota: PhyN/PhyC -!< qlimitFac [0.0, 1.0] -!< if quota < NCmin qlimitFac=0 -!< if quota > ≈ 9 * NCmin qlimitFac=1 -!< P_cm: 3.0d0 [1/day], Rate of C-specific photosynthesis - -!< pMax = The carbon-specific, light-saturated rate of photosynthesis [day^-1] -!< Nutrient limited environment -!< Small pyhtoplankton is limited by iron and nitrogen -!< Diatoms are additionally limited by silicon - -!< *** Small phytoplankton *** -!< *************************** - qlimitFac = recom_limiter(NMinSlope, NCmin, quota) ! Eqn A55 - feLimitFac = Fe/(k_Fe + Fe) ! Use Michaelis–Menten kinetics - qlimitFac = min(qlimitFac, feLimitFac) ! Liebig law of the minimum - pMax = P_cm * qlimitFac * arrFunc ! Maximum value of C-specific rate of photosynthesis - -!< *** Diatoms *** -!< *************** - qlimitFac = recom_limiter(NMinSlope, NCmin_d, quota_dia) + + !=============================================================================== + ! CALCITE DISSOLUTION + !=============================================================================== + ! Calculates dissolution rates of calcium carbonate (CaCO3) in seawater. + ! Dissolution depends on carbonate saturation state or depth (two modes). + ! + ! Carbonate Saturation State (Omega): + ! Ω = [CO3²⁻] / [CO3²⁻]sat + ! - Ω > 1: Supersaturated (favors precipitation, slow dissolution) + ! - Ω < 1: Undersaturated (favors dissolution) + ! + ! Variables (Saturation-dependent mode): + ! calc_diss : Primary detritus dissolution rate [day-1] + ! calc_diss2 : Secondary detritus dissolution rate [day-1] + ! calc_diss_ben : Benthic dissolution rate [day-1] + ! calc_diss_omegac : Base dissolution rate coefficient [day-1] + ! calc_diss_exp : Dissolution order exponent [-] + ! Ca : Calcium ion concentration [mol kg-1] + ! CO3_sat : Saturated carbonate concentration [mol m-3] + ! CO3_watercolumn(k) : Actual carbonate concentration [mol m-3] + ! kspc_watercolumn(k) : Solubility product for calcite [mol2 kg-2] + ! rhoSW_watercolumn(k): Seawater density [kg m-3] + ! Sali_depth(k) : Salinity [psu] + ! + ! Variables (Depth-dependent mode): + ! calc_diss_rate : Primary dissolution rate constant [day-1] + ! calc_diss_rate2 : Secondary dissolution rate constant [day-1] + ! Sink_Vel : Particle sinking velocity [m day-1] + ! Vdet_a : Depth-dependent sinking coefficient [day-1] + ! Vdet : Base sinking velocity [m day-1] + ! zF(k) : Depth at layer k [m] + ! + ! Note: Dissolution releases CO2 and alkalinity, affecting carbonate chemistry + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Calculate Sinking Velocity + !------------------------------------------------------------------------------- + ! Sinking velocity increases with depth (particle compaction, reduced drag) + + Sink_Vel = Vdet_a * abs(zF(k)) + Vdet + + if (OmegaC_diss) then + + !=========================================================================== + ! SATURATION-STATE DEPENDENT DISSOLUTION + !=========================================================================== + ! Thermodynamically-based dissolution using carbonate saturation state + ! Based on Aumont et al. (2015) parameterization + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Calculate Calcium Ion Concentration + !--------------------------------------------------------------------------- + ! Conservative element: scales linearly with salinity + ! Reference: 0.02128 mol/kg at salinity 35 psu + + Ca = (0.02128d0 / 40.078d0) * Sali_depth(k) / 1.80655d0 + + !--------------------------------------------------------------------------- + ! Calculate Saturated Carbonate Ion Concentration + !--------------------------------------------------------------------------- + ! [CO3²⁻]sat = Ksp / [Ca²+] + ! Where Ksp is the solubility product for calcite + ! Convert from mol/kg to mol/m3 using seawater density + + CO3_sat = (kspc_watercolumn(k) / Ca) * rhoSW_watercolumn(k) + + !--------------------------------------------------------------------------- + ! Calculate Dissolution Rate + !--------------------------------------------------------------------------- + ! Dissolution increases with undersaturation (Ω < 1) + ! Power law relationship: rate ∝ (1 - Ω)^n + ! Exponent (n) typically 1-4 depending on calcite form + + calc_diss = calc_diss_omegac * max(zero, (1.0 - (CO3_watercolumn(k) / CO3_sat)))**(calc_diss_exp) + + ! Apply same dissolution rate to all detritus types + ! Assumes similar calcite characteristics regardless of source + if (enable_3zoo2det) then + calc_diss2 = calc_diss ! Fast-sinking detritus + endif + calc_diss_ben = calc_diss ! Benthic detritus + + else + + !=========================================================================== + ! DEPTH-DEPENDENT DISSOLUTION + !=========================================================================== + ! Empirical dissolution rates scaled by sinking velocity + ! Simpler approach when carbonate chemistry is not fully resolved + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Primary Detritus Dissolution + !--------------------------------------------------------------------------- + ! Dissolution rate scales with sinking velocity + ! Faster sinking -> less time for dissolution per unit depth + ! Reference velocity: 20 m/day + + calc_diss = calc_diss_rate * Sink_Vel / 20.d0 + + if (enable_3zoo2det) then + !----------------------------------------------------------------------- + ! Secondary Detritus Dissolution (Fast-sinking) + !----------------------------------------------------------------------- + ! May have different dissolution characteristics than primary detritus + ! (e.g., more compact, different organic coating) + + calc_diss2 = calc_diss_rate2 * Sink_Vel / 20.d0 + endif + + !--------------------------------------------------------------------------- + ! Benthic Dissolution + !--------------------------------------------------------------------------- + ! Calcite reaching the sediment interface + ! Uses same rate as primary detritus + + calc_diss_ben = calc_diss_rate * Sink_Vel / 20.d0 + + endif + + !=============================================================================== + ! PHOTOSYNTHESIS LIMITATION FACTORS + !=============================================================================== + ! Calculates how nutrients, iron, and temperature limit maximum photosynthesis + ! rates using intracellular quota-based regulation (Droop model). + ! + ! Limitation Approach: + ! - Intracellular regulation through N:C, Si:C quotas + ! - Michaelis-Menten iron limitation + ! - Liebig's law: most limiting factor controls growth + ! + ! Variables (Small Phytoplankton): + ! qlimitFac : Combined nutrient limitation factor [0-1, 0=limited, 1=replete] + ! feLimitFac : Iron limitation factor [0-1] + ! quota : Phytoplankton N:C ratio [mmolN mmolC-1] + ! NCmin : Minimum N:C ratio (subsistence quota) [mmolN mmolC-1] + ! NMinSlope : Steepness of limitation curve [-] + ! Fe : Dissolved iron concentration [mmolFe m-3] + ! k_Fe : Half-saturation for Fe uptake [mmolFe m-3] + ! pMax : Maximum photosynthesis rate [day-1] + ! P_cm : Maximum rate constant [day-1] + ! Temp_phyto : Temperature function for small phyto [-] + ! arrFunc : Arrhenius temperature function [-] + ! + ! recom_limiter Function: + ! Returns limitation factor based on quota: + ! - Returns ~0 when quota near minimum (severely limited) + ! - Returns ~1 when quota is high (nutrient replete) + ! - Smooth transition controlled by slope parameter + ! + ! Note: Similar calculations for diatoms, coccolithophores, and Phaeocystis + ! with species-specific parameters and additional Si limitation for diatoms + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Small Phytoplankton + !------------------------------------------------------------------------------- + ! Limited by nitrogen and iron + ! Represents small flagellates, small cyanobacteria, etc. + + ! Nitrogen limitation based on intracellular N:C quota + qlimitFac = recom_limiter(NMinSlope, NCmin, quota) + + ! Iron limitation using Michaelis-Menten kinetics + ! Iron is often the limiting micronutrient in HNLC regions + feLimitFac = Fe / (k_Fe + Fe) + + ! Apply Liebig's law: most limiting nutrient controls photosynthesis + qlimitFac = min(qlimitFac, feLimitFac) + + ! Track limitation + VTqlimitFac_phyto(k) = qlimitFac + + ! Calculate maximum photosynthesis rate with temperature correction + if (enable_coccos) then + ! Use species-specific temperature function (when cocco module active) + pMax = qlimitFac * Temp_phyto + else + ! Use standard Arrhenius temperature function + pMax = P_cm * qlimitFac * arrFunc + endif + + !------------------------------------------------------------------------------- + ! Diatoms + !------------------------------------------------------------------------------- + ! Limited by nitrogen, silicon, and iron + ! Large phytoplankton with silica frustules (shells) + + ! Nitrogen limitation + qlimitFac = recom_limiter(NMinSlope, NCmin_d, quota_dia) + + ! Silicon limitation (unique to diatoms) + ! Required for frustule formation - critical for diatom growth qlimitFacTmp = recom_limiter(SiMinSlope, SiCmin, qSiC) - qlimitFac = min(qLimitFac, qlimitFacTmp) - feLimitFac = Fe/(k_Fe_d + Fe) - qlimitFac = min(qlimitFac, feLimitFac) - pMax_dia = P_cm_d * qlimitFac * arrFunc - -!< *** Coccolithophores *** -!< ************************ -#if defined (__coccos) - qlimitFac = recom_limiter(NMinSlope, NCmin_c, quota_cocco) - feLimitFac = Fe/(k_Fe_c + Fe) - qlimitFac = min(qlimitFac, feLimitFac) - pMax_cocco = P_cm_c * qlimitFac * CoccoTFunc ! Here the T dependency is changed -#endif -!------------------------------------------------------------------------------- -!< *** Small phytoplankton photosynthesis rate *** -!< *********************************************** - if (pMax .lt. tiny .OR. PARave /= PARave .OR. CHL2C /= CHL2C) then ! OG in case of only respiration, i.e. darkness?? + qlimitFac = min(qlimitFac, qlimitFacTmp) + + ! Iron limitation + feLimitFac = Fe / (k_Fe_d + Fe) + qlimitFac = min(qlimitFac, feLimitFac) + + ! Track limitation + VTqlimitFac_diatoms(k) = qlimitFac + + ! Calculate maximum photosynthesis rate + if (enable_coccos) then + pMax_dia = qlimitFac * Temp_diatoms + else + pMax_dia = P_cm_d * qlimitFac * arrFunc + endif + + !------------------------------------------------------------------------------- + ! Coccolithophores (Optional) + !------------------------------------------------------------------------------- + ! Limited by nitrogen and iron + ! Calcifying phytoplankton that produce calcite plates + + if (enable_coccos) then + + ! Nitrogen limitation + qlimitFac = recom_limiter(NMinSlope, NCmin_c, quota_cocco) + + ! Iron limitation + feLimitFac = Fe / (k_Fe_c + Fe) + qlimitFac = min(qlimitFac, feLimitFac) + + ! Track limitation + VTqlimitFac_cocco(k) = qlimitFac + + ! Calculate maximum photosynthesis rate + pMax_cocco = qlimitFac * Temp_cocco + + !--------------------------------------------------------------------------- + ! Phaeocystis (Optional) + !--------------------------------------------------------------------------- + ! Limited by nitrogen and iron + ! Colonial phytoplankton that can form large blooms + + ! Nitrogen limitation + qlimitFac = recom_limiter(NMinSlope, NCmin_p, quota_phaeo) + + ! Iron limitation + feLimitFac = Fe / (k_Fe_p + Fe) + qlimitFac = min(qlimitFac, feLimitFac) + + ! Track limitation + VTqlimitFac_phaeo(k) = qlimitFac + + ! Calculate maximum photosynthesis rate + pMax_phaeo = qlimitFac * Temp_phaeo + + endif + + !=============================================================================== + ! LIGHT-DEPENDENT PHOTOSYNTHESIS RATE CALCULATIONS + !=============================================================================== + ! Calculates actual photosynthesis rates using photosynthesis-irradiance (P-I) + ! curves. Uses exponential saturation model (no photoinhibition). + ! + ! P-I Curve Model: + ! P = Pmax × (1 - exp(-α × Chl:C × PAR / Pmax)) + ! + ! Where: + ! P : Actual photosynthesis rate [day-1] + ! Pmax : Maximum rate (nutrient and temperature limited) [day-1] + ! α : Initial slope of P-I curve (photosynthetic efficiency) [-] + ! Chl:C : Chlorophyll to carbon ratio [mgChl mmolC-1] + ! PAR : Photosynthetically active radiation [W m-2] + ! + ! Variables (Small Phytoplankton): + ! Cphot : Carbon-specific photosynthesis rate [day-1] + ! PARave : Average PAR in mixed layer [W m-2] + ! alfa : Initial slope parameter [-] + ! Chl2C : Chlorophyll:Carbon ratio [mgChl mmolC-1] + ! PhyCO2 : CO2 limitation factor [0-1] + ! VTCphotLigLim_phyto : Light limitation factor for diagnostics [0-1] + ! VTCphot_phyto : Final photosynthesis rate for diagnostics [day-1] + ! + ! Safety Checks: + ! - Check for darkness (pMax < tiny) + ! - Check for NaN values (PARave /= PARave) + ! - Check for valid Chl:C ratios + ! + ! Note: Similar calculations for all phytoplankton types + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Small Phytoplankton Photosynthesis + !------------------------------------------------------------------------------- + + if (pMax < tiny .OR. PARave /= PARave .OR. CHL2C /= CHL2C) then + ! No photosynthesis in darkness or under invalid conditions Cphot = zero else - Cphot = pMax*(real(one) - exp(-alfa * Chl2C * PARave / pMax)) - if (CO2lim) Cphot = Cphot * PhyCO2 ! Added the CO2 dependence - end if - if (Cphot .lt. tiny) Cphot = zero + ! Calculate photosynthesis using exponential P-I curve + ! Model saturates at high light (no photoinhibition) + Cphot = pMax * (1.0d0 - exp(-alfa * Chl2C * PARave / pMax)) + + ! Store light limitation factor for diagnostics + ! Ratio of actual to maximum rate indicates light limitation severity + VTCphotLigLim_phyto(k) = Cphot / pMax + + ! Apply CO2 limitation if ocean acidification sensitivity is enabled + if (CO2lim) Cphot = Cphot * PhyCO2 + endif + + ! Ensure non-negative values (numerical safety) + if (Cphot < tiny) Cphot = zero + + ! Store final photosynthesis rate for diagnostics and output + VTCphot_phyto(k) = Cphot -!< *** Diatom photosynthesis rate *** -!< ********************************** - if ( pMax_dia .lt. tiny .OR. PARave /= PARave .OR. CHL2C_dia /= CHL2C_dia) then + !------------------------------------------------------------------------------- + ! Diatom Photosynthesis + !------------------------------------------------------------------------------- + + if (pMax_dia < tiny .OR. PARave /= PARave .OR. CHL2C_dia /= CHL2C_dia) then Cphot_dia = zero else - Cphot_dia = pMax_dia * (real(one) - exp(-alfa_d * Chl2C_dia * PARave / pMax_dia)) - if (CO2lim) Cphot_dia = Cphot_dia * DiaCO2 ! Added the CO2 dependence - end if - if (Cphot_dia .lt. tiny) Cphot_dia = zero - -!< *** Coccolithophore photosynthesis rate *** -!< ******************************************* -#if defined (__coccos) - if ( pMax_cocco .lt. tiny .OR. Parave /= Parave .OR. CHL2C_cocco /= CHL2C_cocco) then - Cphot_cocco = zero - else - Cphot_cocco = pMax_cocco * (real(one) - exp( -alfa_c * Chl2C_cocco * PARave / pMax_cocco)) - if (CO2lim) Cphot_cocco = Cphot_cocco * CoccoCO2 ! Added the CO2 dependence - end if - if (Cphot_cocco .lt. tiny) Cphot_cocco = zero -#endif -!------------------------------------------------------------------------------- -!< chlorophyll degradation -!------------------------------------------------------------------------------- - KOchl = deg_Chl - KOchl_dia = deg_Chl_d -#if defined (__coccos) - KOchl_cocco = deg_Chl_c -#endif - + ! Diatom P-I curve with species-specific parameters + Cphot_dia = pMax_dia * (1.0 - exp(-alfa_d * Chl2C_dia * PARave / pMax_dia)) + + ! Store light limitation diagnostic + VTCphotLigLim_diatoms(k) = Cphot_dia / pMax_dia + + ! Apply CO2 limitation + if (CO2lim) Cphot_dia = Cphot_dia * DiaCO2 + endif + + if (Cphot_dia < tiny) Cphot_dia = zero + VTCphot_diatoms(k) = Cphot_dia + + !------------------------------------------------------------------------------- + ! Coccolithophore Photosynthesis (Optional) + !------------------------------------------------------------------------------- + + if (enable_coccos) then + + if (pMax_cocco < tiny .OR. PARave /= PARave .OR. CHL2C_cocco /= CHL2C_cocco) then + Cphot_cocco = zero + else + ! Coccolithophore P-I curve + Cphot_cocco = pMax_cocco * (1.0 - exp(-alfa_c * Chl2C_cocco * PARave / pMax_cocco)) + + ! Store light limitation diagnostic + VTCphotLigLim_cocco(k) = Cphot_cocco / pMax_cocco + + ! Apply CO2 limitation + if (CO2lim) Cphot_cocco = Cphot_cocco * CoccoCO2 + endif + + if (Cphot_cocco < tiny) Cphot_cocco = zero + VTCphot_cocco(k) = Cphot_cocco + + !--------------------------------------------------------------------------- + ! Phaeocystis Photosynthesis (Optional) + !--------------------------------------------------------------------------- + + if (pMax_phaeo < tiny .OR. PARave /= PARave .OR. CHL2C_phaeo /= CHL2C_phaeo) then + Cphot_phaeo = zero + else + ! Phaeocystis P-I curve + Cphot_phaeo = pMax_phaeo * (1.0 - exp(-alfa_p * Chl2C_phaeo * PARave / pMax_phaeo)) + + ! Store light limitation diagnostic + VTCphotLigLim_phaeo(k) = Cphot_phaeo / pMax_phaeo + + ! Apply CO2 limitation + if (CO2lim) Cphot_phaeo = Cphot_phaeo * PhaeoCO2 + endif + + if (Cphot_phaeo < tiny) Cphot_phaeo = zero + VTCphot_phaeo(k) = Cphot_phaeo + + endif + + !=============================================================================== + ! CHLOROPHYLL DEGRADATION + !=============================================================================== + ! Calculates chlorophyll degradation rates with optional photodamage effects. + ! Chlorophyll degrades due to senescence and light-induced damage. + ! + ! Two Modes: + ! A) Base degradation: Constant rate (use_photodamage = FALSE) + ! B) Photodamage-dependent: Light-dependent rate (use_photodamage = TRUE) + ! + ! Variables: + ! KOchl : Chlorophyll degradation rate for small phyto [day-1] + ! KOchl_dia : Chlorophyll degradation rate for diatoms [day-1] + ! KOchl_cocco : Chlorophyll degradation rate for coccos [day-1] + ! KOchl_phaeo : Chlorophyll degradation rate for Phaeocystis [day-1] + ! deg_Chl : Base degradation rate constant [day-1] + ! CHL2C_plast : Chlorophyll:Carbon ratio in plastids [mgChl mmolC-1] + ! alfa : P-I curve initial slope [-] + ! PARave : Average PAR [W m-2] + ! pMax : Maximum photosynthesis rate [day-1] + ! + ! Photodamage Model: + ! - High light damages photosystem II and degrades chlorophyll + ! - Uses same exponential form as P-I curve (saturating damage) + ! - Minimum degradation rate (10% of base) in darkness + ! - No upper cap (commented out safety constraint) + ! + ! Note: Photodamage increases chlorophyll turnover at high light + ! This helps prevent photoinhibition and photooxidative stress + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Set Base Chlorophyll Degradation Rates + !------------------------------------------------------------------------------- + ! Constant degradation rates independent of light (senescence) + + KOchl = deg_Chl ! Small phytoplankton + KOchl_dia = deg_Chl_d ! Diatoms + + if (enable_coccos) then + KOchl_cocco = deg_Chl_c ! Coccolithophores + KOchl_phaeo = deg_Chl_p ! Phaeocystis + endif + if (use_photodamage) then -!< add a minimum value for photodamage -!< *** Phytoplankton Chla loss *** -!< ******************************* - if (pMax .lt. tiny .OR. PARave /= PARave .OR. CHL2C_plast /= CHL2C_plast) then - KOchl = deg_Chl*0.1d0 + + !=========================================================================== + ! PHOTODAMAGE-DEPENDENT DEGRADATION + !=========================================================================== + ! Light-dependent chlorophyll degradation using saturation model + ! Higher light intensity increases chlorophyll turnover + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Small Phytoplankton Chlorophyll Loss + !--------------------------------------------------------------------------- + + if (pMax < tiny .OR. PARave /= PARave .OR. CHL2C_plast /= CHL2C_plast) then + ! Minimum degradation in darkness (10% of base rate) + KOchl = deg_Chl * 0.1d0 else - KOchl = deg_Chl*(real(one) - exp(-alfa * CHL2C_plast * PARave / pMax)) - KOchl = max((deg_Chl*0.1d0), KOchl) + ! Saturation model: degradation increases with light + ! Uses same exponential form as P-I curve + KOchl = deg_Chl * (real(one) - exp(-alfa * CHL2C_plast * PARave / pMax)) + + !< Alternative linear model (commented out): + !< Degradation directly proportional to light intensity + !KOchl = deg_Chl * CHL2C_plast * PARave + + ! Ensure minimum degradation rate (10% of base) + KOchl = max((deg_Chl * 0.1d0), KOchl) + + !< Safety constraint (commented out): + !< Caps maximum degradation at 0.3 day-1 + !KOchl = min(KOchl, 0.3d0) end if -!< *** Diatoms Chla loss *** -!< ************************* - if (pMax_dia .lt. tiny .OR. PARave /= PARave .OR. CHL2C_plast_dia /= CHL2C_plast_dia) then - KOchl_dia = deg_Chl_d*0.1d0 + + !--------------------------------------------------------------------------- + ! Diatom Chlorophyll Loss + !--------------------------------------------------------------------------- + + if (pMax_dia < tiny .OR. PARave /= PARave .OR. CHL2C_plast_dia /= CHL2C_plast_dia) then + KOchl_dia = deg_Chl_d * 0.1d0 else - KOchl_dia = deg_Chl_d * (real(one) - exp(-alfa_d * CHL2C_plast_dia * PARave / pMax_dia )) - KOchl_dia = max((deg_Chl_d*0.1d0), KOchl_dia) - end if -!< *** Coccolithophores chla loss *** -!< ********************************** -#if defined (__coccos) - if (pMax_cocco .lt. tiny .OR. PARave /= Parave .OR. CHL2C_plast_cocco /= CHL2C_plast_cocco) then - KOchl_cocco = deg_Chl_c*0.1d0 - else - KOchl_cocco = deg_Chl_c * (real(one) - exp( -alfa_c * CHL2C_plast_cocco * PARave / pMax_cocco )) - KOchl_cocco = max((deg_Chl_c*0.1d0), KOchl_cocco) - end if -#endif - if (KOchl /= KOchl) then - print*,' KOchl is ', KOchl - print*,' deg_Chl is ', deg_Chl - print*,' alfa is ', alfa - print*,' CHL2C is ', CHL2C_plast - print*,' PARave is ', PARave - print*,' pMax is ', pMax - stop + ! Diatom-specific photodamage model + KOchl_dia = deg_Chl_d * (real(one) - exp(-alfa_d * CHL2C_plast_dia * PARave / pMax_dia)) + + !KOchl_dia = deg_Chl_d * CHL2C_plast_dia * PARave + + KOchl_dia = max((deg_Chl_d * 0.1d0), KOchl_dia) + !KOchl_dia = min(KOchl_dia, 0.3d0) end if - if (KOchl_dia /= KOchl_dia) then - print*,' KOchl_dia is ', KOchl_dia - print*,' deg_Chl_d is ', deg_Chl_d - print*,' alfa_d is ', alfa_d - print*,' CHL2C_d is ', CHL2C_plast_dia - print*,' PARave is ', PARave - print*,' pMax_d is ', pMax_dia + + if (enable_coccos) then + + !----------------------------------------------------------------------- + ! Coccolithophore Chlorophyll Loss + !----------------------------------------------------------------------- + + if (pMax_cocco < tiny .OR. PARave /= PARave .OR. CHL2C_plast_cocco /= CHL2C_plast_cocco) then + KOchl_cocco = deg_Chl_c * 0.1d0 + else + ! Coccolithophore-specific photodamage model + KOchl_cocco = deg_Chl_c * (real(one) - exp(-alfa_c * CHL2C_plast_cocco * PARave / pMax_cocco)) + + !KOchl_cocco = deg_Chl_c * CHL2C_plast_cocco * PARave + + KOchl_cocco = max((deg_Chl_c * 0.1d0), KOchl_cocco) + !KOchl_cocco = min(KOchl_cocco, 0.3d0) + end if + + !----------------------------------------------------------------------- + ! Phaeocystis Chlorophyll Loss + !----------------------------------------------------------------------- + + if (pMax_phaeo < tiny .OR. PARave /= PARave .OR. CHL2C_plast_phaeo /= CHL2C_plast_phaeo) then + KOchl_phaeo = deg_Chl_p * 0.1d0 + else + ! Phaeocystis-specific photodamage model + KOchl_phaeo = deg_Chl_p * (real(one) - exp(-alfa_p * CHL2C_plast_phaeo * PARave / pMax_phaeo)) + + !KOchl_phaeo = deg_Chl_p * CHL2C_plast_phaeo * PARave + + KOchl_phaeo = max((deg_Chl_p * 0.1d0), KOchl_phaeo) + !KOchl_phaeo = min(KOchl_phaeo, 0.3d0) + end if + + endif ! enable_coccos + + endif ! use_photodamage + + !--------------------------------------------------------------------------- + ! ERROR CHECKING AND DEBUGGING + ! Check for NaN values in chlorophyll degradation rates + !--------------------------------------------------------------------------- + + ! Small phytoplankton + if (KOchl /= KOchl) then + print*, 'ERROR: KOchl is NaN' + print*, ' deg_Chl =', deg_Chl + print*, ' alfa =', alfa + print*, ' CHL2C_plast =', CHL2C_plast + print*, ' PARave =', PARave + print*, ' pMax =', pMax + stop + end if + + ! Diatoms + if (KOchl_dia /= KOchl_dia) then + print*, 'ERROR: KOchl_dia is NaN' + print*, ' deg_Chl_d =', deg_Chl_d + print*, ' alfa_d =', alfa_d + print*, ' CHL2C_plast_dia =', CHL2C_plast_dia + print*, ' PARave =', PARave + print*, ' pMax_dia =', pMax_dia + stop + end if + + ! Additional species (if enabled) + if (enable_coccos) then + if (KOchl_cocco /= KOchl_cocco) then + print*, 'ERROR: KOchl_cocco is NaN' + print*, ' deg_Chl_c =', deg_Chl_c + print*, ' alfa_c =', alfa_c + print*, ' CHL2C_plast_cocco =', CHL2C_plast_cocco + print*, ' PARave =', PARave + print*, ' pMax_cocco =', pMax_cocco stop end if -#if defined (__coccos) - if (KOchl_cocco /= KOchl_cocco) then - print*,' KOchl_cocco is ', KOchl_cocco - print*,' deg_Chl_c is ', deg_Chl_c - print*,' alfa_c is ', alfa_c - print*,' CHL2C_c is ', CHL2C_plast_cocco - print*,' PARave is ', PARave - print*,' pMax_c is ', pMax_cocco + + if (KOchl_phaeo /= KOchl_phaeo) then + print*, 'ERROR: KOchl_phaeo is NaN' + print*, ' deg_Chl_p =', deg_Chl_p + print*, ' alfa_p =', alfa_p + print*, ' CHL2C_plast_phaeo =', CHL2C_plast_phaeo + print*, ' PARave =', PARave + print*, ' pMax_phaeo =', pMax_phaeo stop - end if -#endif - end if ! photodamage - -!------------------------------------------------------------------------------- -!> Assimilation section -!------------------------------------------------------------------------------- + end if + endif -!< Nitrogen and silicon part -!< Compute assimilation from Geider et al 1998 -!< V_cm: Scaling factor for C-specific N uptake, dimensionless -!< NCmax: Maximum cell quota of nitrogen (N:C) [mmol N/mmol C] -!< NMaxSlope: Max slope for limiting function -!< NCuptakeRatio: Maximum uptake ratio N:C [mmol N mmol C−1] -!< SiCUptakeRatio: Maximum uptake ratio Si : C [mmol Si mmol C−1 ] -!< The N:C ratio is taken into account, as a -!! too high ratio indicates that the intracellular -!! concentration of energy rich carbon molecules becomes too low to -!! use energy on silicon uptake. - - V_cm = V_cm_fact - limitFacN = recom_limiter(NMaxSlope, quota, NCmax) - N_assim = V_cm * pMax * NCuptakeRatio & ! [mmol N / (mmol C * day)] - * limitFacN * (DIN/(DIN + k_din)) ! Michaelis–Menten kinetics - - V_cm = V_cm_fact_d - limitFacN_dia = recom_limiter(NMaxSlope, quota_dia, NCmax_d) - N_assim_dia = V_cm * pMax_dia * NCUptakeRatio_d & - * limitFacN_dia * DIN/(DIN + k_din_d) - -#if defined (__coccos) - V_cm = V_cm_fact_c + !=============================================================================== + ! PHYTOPLANKTON ASSIMILATION SECTION + !=============================================================================== + ! Computes nutrient uptake, chlorophyll synthesis, and respiration rates + ! for multiple phytoplankton functional types following Geider et al. 1998 + !=============================================================================== + + !=============================================================================== + ! NITROGEN ASSIMILATION + !=============================================================================== + ! Calculates nitrogen uptake rates for all phytoplankton groups based on + ! nutrient availability, cell quota status, and maximum uptake capacity + ! + ! Key Parameters: + ! V_cm_fact : Scaling factor for C-specific N uptake [-] + ! NCmax : Maximum cell quota of nitrogen (N:C) [mmolN mmolC-1] + ! NMaxSlope : Maximum slope for quota limiting function [-] + ! NCuptakeRatio : Maximum uptake ratio N:C [mmolN mmolC-1] + ! k_din : Half-saturation constant for DIN uptake [mmolN m-3] + ! pMax : Maximum photosynthesis rate [day-1] + ! + ! Note: Cell quota limiting function prevents luxury N uptake when internal + ! N:C ratio approaches maximum capacity + !------------------------------------------------------------------------------- + + ! --- Small phytoplankton Nitrogen Uptake --- + V_cm = V_cm_fact + limitFacN = recom_limiter(NMaxSlope, quota, NCmax) + N_assim = V_cm * pMax * NCuptakeRatio * limitFacN * (DIN/(DIN + k_din)) + + ! --- Diatom Nitrogen Uptake --- + V_cm = V_cm_fact_d + limitFacN_dia = recom_limiter(NMaxSlope, quota_dia, NCmax_d) + N_assim_dia = V_cm * pMax_dia * NCUptakeRatio_d * limitFacN_dia * DIN/(DIN + k_din_d) + + ! --- Optional Coccolithophore and Phaeocystis Groups --- + if (enable_coccos) then + ! Coccolithophore nitrogen uptake + V_cm = V_cm_fact_c limitFacN_cocco = recom_limiter(NMaxSlope, quota_cocco, NCmax_c) - N_assim_cocco = V_cm * pMax_cocco * NCUptakeRatio_c & - * limitFacN_cocco * DIN/(DIN + k_din_c) -#endif + N_assim_cocco = V_cm * pMax_cocco * NCUptakeRatio_c * limitFacN_cocco * & + DIN/(DIN + k_din_c) + + ! Phaeocystis nitrogen uptake + V_cm = V_cm_fact_p + limitFacN_phaeo = recom_limiter(NMaxSlope, quota_phaeo, NCmax_p) + N_assim_phaeo = V_cm * pMax_phaeo * NCUptakeRatio_p * limitFacN_phaeo * & + DIN/(DIN + k_din_p) + endif - limitFacSi = recom_limiter(SiMaxSlope, qSiC, SiCmax) & - * limitFacN_dia - Si_assim = V_cm_fact_d * P_cm_d * arrFunc * SiCUptakeRatio & - * limitFacSi * Si/(Si + k_si) + !=============================================================================== + ! SILICON ASSIMILATION (DIATOMS ONLY) + !=============================================================================== + ! Calculates silicate uptake for diatom frustule formation + ! + ! Key Parameters: + ! SiCUptakeRatio : Maximum uptake ratio Si:C [mmolSi mmolC-1] + ! SiCmax : Maximum cell quota of silicon (Si:C) [mmolSi mmolC-1] + ! SiMaxSlope : Maximum slope for Si quota limiting function [-] + ! k_si : Half-saturation constant for Si uptake [mmolSi m-3] + ! P_cm_d : Maximum photosynthesis rate for diatoms [day-1] + ! + ! Note: Silicon uptake is coupled to nitrogen status - high N:C ratios indicate + ! low intracellular energy reserves, limiting energy-intensive Si uptake + !------------------------------------------------------------------------------- + + limitFacSi = recom_limiter(SiMaxSlope, qSiC, SiCmax) * limitFacN_dia + + if (.NOT. enable_coccos) then + ! Standard silicon assimilation formulation + Si_assim = V_cm_fact_d * P_cm_d * arrFunc * SiCUptakeRatio * limitFacSi * & + Si/(Si + k_si) + else + ! Alternative formulation with temperature dependence + Si_assim = V_cm_fact_d * Temp_diatoms * SiCUptakeRatio * limitFacSi * & + Si/(Si + k_si) + VTSi_assimDia(k) = Si_assim + endif -!------------------------------------------------------------------------------- -!< *** Iron chemistry *** -!< ********************** -! select the method to calculate freeFe - freeFe = iron_chemistry(Fe,totalligand,ligandStabConst) -!------------------------------------------------------------------------------- -!< *** Chlorophyll synthesis *** -!< ***************************** + !=============================================================================== + ! 3. IRON CHEMISTRY + !=============================================================================== + ! Computes free (bioavailable) iron concentration from total dissolved iron + ! accounting for complexation with organic ligands + ! + ! Variables: + ! Fe : Total dissolved iron [µmol m-3] + ! totalligand : Total organic ligand concentration [µmol m-3] + ! ligandStabConst : Conditional stability constant [M-1] + ! freeFe : Free (inorganic) iron concentration [µmol m-3] + !------------------------------------------------------------------------------- + + freeFe = iron_chemistry(Fe, totalligand, ligandStabConst) + + !=============================================================================== + ! 4. CHLOROPHYLL SYNTHESIS + !=============================================================================== + ! Calculates chlorophyll production coupled to nitrogen assimilation + ! following photoacclimation theory (Geider et al. 1998) + ! + ! Key Parameters: + ! Chl2N_max : Maximum Chl:N ratio [mg Chl mmolN-1] + ! Chl2C : Chlorophyll to carbon ratio [mg Chl mmolC-1] + ! alfa : Initial slope of P-I curve [mmolC (mg Chl)-1 m2 µmol-1 day-1] + ! Cphot : Carbon-specific photosynthesis rate [day-1] + ! PARave : Depth-averaged photosynthetically available radiation [µmol m-2 s-1] + ! + ! Note: Chlorophyll synthesis is down-regulated when light is sufficient, + ! preventing over-investment in light-harvesting machinery + !------------------------------------------------------------------------------- + + ! --- Small phytoplankton Chlorophyll Synthesis --- + chlSynth = zero + if (PARave >= tiny .AND. PARave == PARave) then + chlSynth = N_assim * Chl2N_max * & + min(real(one), Cphot/(alfa * Chl2C * PARave)) + endif -!< Coupled to N uptake -!< Converted to chlorophyll units with a maximum Chl:N ratio, Chl2N_max -!< Chl2N_max: Maximum Chl:N ratio for phytoplankton [mg Chl mmol N−1 ] + ! --- Diatom Chlorophyll Synthesis --- + ChlSynth_dia = zero + if (PARave >= tiny .AND. PARave == PARave) then + ChlSynth_dia = N_assim_dia * Chl2N_max_d * & + min(real(one), Cphot_dia / (alfa_d * Chl2C_dia * PARave)) + end if - chlSynth = zero - if (PARave .ge. tiny .AND. PARave .eq. PARave) then - chlSynth = N_assim * Chl2N_max & - * min(real(one),Cphot/(alfa * Chl2C * PARave)) - end if - ChlSynth_dia = zero - if (PARave .ge. tiny .AND. PARave .eq. PARave) then - ChlSynth_dia = N_assim_dia * Chl2N_max_d & - * min(real(one),Cphot_dia /(alfa_d * Chl2C_dia * PARave)) - end if + ! --- Optional Coccolithophore and Phaeocystis Chlorophyll Synthesis --- + if (enable_coccos) then + ! Coccolithophore chlorophyll synthesis ChlSynth_cocco = zero -#if defined (__coccos) - if (PARave .ge. tiny .AND. PARave .eq. PARave) then - ChlSynth_cocco = N_assim_cocco * Chl2N_max_c & - * min(real(one),Cphot_cocco /(alfa_c * Chl2C_cocco * PARave)) - end if -#endif -!------------------------------------------------------------------------------- -!< *** Phytoplankton respiraion rate *** -!< ************************************* + if (PARave >= tiny .AND. PARave == PARave) then + ChlSynth_cocco = N_assim_cocco * Chl2N_max_c * & + min(real(one), Cphot_cocco / (alfa_c * Chl2C_cocco * PARave)) + end if -!< res_phy: Maintenance respiration rate constant [day−1 ] -!< biosynth: The cost of biosynthesis of N [mmol C mmol N−1 ] + ! Phaeocystis chlorophyll synthesis + ChlSynth_phaeo = zero + if (PARave >= tiny .AND. PARave == PARave) then + ChlSynth_phaeo = N_assim_phaeo * Chl2N_max_p * & + min(real(one), Cphot_phaeo/(alfa_p * Chl2C_phaeo * PARave)) + end if + endif - phyRespRate = res_phy * limitFacN + biosynth * N_assim - phyRespRate_dia = res_phy_d * limitFacN_dia + biosynth * N_assim_dia + biosynthSi * Si_assim -#if defined (__coccos) + !=============================================================================== + ! 5. PHYTOPLANKTON RESPIRATION RATES + !=============================================================================== + ! Computes carbon loss through maintenance respiration and biosynthetic costs + ! + ! Key Parameters: + ! res_phy : Maintenance respiration rate constant [day-1] + ! biosynth : Biosynthetic cost of nitrogen assimilation [mmolC mmolN-1] + ! biosynthSi : Biosynthetic cost of silicon assimilation [mmolC mmolSi-1] + ! + ! Components: + ! 1. Maintenance respiration: Quota-dependent baseline metabolic cost + ! 2. Biosynthetic costs: Additional respiration for nutrient assimilation + ! + ! Equation: R = res_phy * limitFacN + biosynth * N_assim + biosynthSi * Si_assim + !------------------------------------------------------------------------------- + + ! --- Small phytoplankton Respiration --- + phyRespRate = res_phy * limitFacN + biosynth * N_assim + + ! --- Diatom Respiration (includes silicon biosynthesis cost) --- + phyRespRate_dia = res_phy_d * limitFacN_dia + biosynth * N_assim_dia + & + biosynthSi * Si_assim + + ! --- Optional Coccolithophore and Phaeocystis Respiration --- + if (enable_coccos) then phyRespRate_cocco = res_phy_c * limitFacN_cocco + biosynth * N_assim_cocco -#endif + phyRespRate_phaeo = res_phy_p * limitFacN_phaeo + biosynth * N_assim_phaeo + endif -!------------------------------------------------------------------------------- -! Mesozooplankton -!------------------------------------------------------------------------------- -!< Grazing on small phytoplankton, diatoms, coccolithophore (optional), -!< microzooplankton (optional), slow- and fast-sinking detritus - -!< *** Food availability *** -!< ************************* -!< pzPhy: Maximum nanophytoplankton preference -!< pzDia: Maximum diatom preference -!< pzCocco: Maximum coccolithophore preference -!< pzDet: Maximum slow-sinking detritus prefence by first zooplankton -!< pzDetZ2: Maximum fast-sinking detritus preference by first zooplankton -!< pzMicZoo: Maximum microzooplankton preference by first zooplankton - - if (REcoM_Grazing_Variable_Preference) then ! CHECK ONUR - aux = pzPhy*PhyN + pzDia*DiaN - if (Grazing_detritus) aux = aux + PzDet*DetN -#if defined (__3Zoo2Det) - if (Grazing_detritus) aux = aux + pzDetZ2*DetZ2N ! 2Det - aux = aux + pzMicZoo*MicZooN ! 3Zoo -#endif -#if defined (__coccos) - aux = aux + pzCocco*CoccoN -#endif -! ****************************************************************************** - varpzPhy = (pzPhy*PhyN)/aux - varpzDia = (pzDia*DiaN)/aux - if (Grazing_detritus) varpzDet = (pzDet*DetN)/aux -#if defined (__3Zoo2Det) - if (Grazing_detritus) varpzDetZ2 = (pzDetZ2*DetZ2N)/aux ! 2Det - varpzMicZoo = (pzMicZoo*MicZooN)/aux ! 3Zoo -#endif -#if defined (__coccos) - varpzCocco = (pzCocco*CoccoN)/aux -#endif -! ****************************************************************************** - fDiaN = varpzDia * DiaN - fPhyN = varpzPhy * PhyN - if (Grazing_detritus) fDetN = varpzDet * DetN -#if defined (__3Zoo2Det) - if (Grazing_detritus) fDetZ2N = varpzDetZ2 * DetZ2N ! 2Det - fMicZooN = varpzMicZoo * MicZooN ! 3Zoo -#endif -#if defined (__coccos) - fCoccoN = varpzCocco * CoccoN -#endif - else ! REcoM_Grazing_Variable_Preference = .false. - fPhyN = pzPhy * PhyN - fDiaN = pzDia * DiaN - if (Grazing_detritus) fDetN = pzDet * DetN -#if defined (__3Zoo2Det) - if (Grazing_detritus) fDetZ2N = pzDetZ2 * DetZ2N ! 2Det - fMicZooN = pzMicZoo * MicZooN ! 3Zoo -#endif -#if defined (__coccos) - fCoccoN = pzCocco * CoccoN -#endif - end if ! REcoM_Grazing_Variable_Preference + !=============================================================================== + ! MESOZOOPLANKTON GRAZING + !=============================================================================== + ! Simulates mesozooplankton grazing on multiple prey types using a Holling + ! Type III functional response with food-dependent preferences and efficiency. + ! + ! This module calculates: + ! 1. Food availability and grazing preferences (fixed or variable) + ! 2. Total grazing flux with Holling Type III response + ! 3. Distribution of grazing among prey types + ! 4. Food-dependent grazing efficiency + ! 5. Carbon flux from grazed prey to mesozooplankton + ! + ! Key Features: + ! - Variable or fixed prey preferences + ! - Optional prey types (coccolithophores, microzooplankton, detritus) + ! - Temperature-dependent grazing rate (Q10 or Arrhenius) + ! - Food-dependent assimilation efficiency + ! + ! References: + ! - Schourup-Kristensen et al. (2013) - REcoM model description + !=============================================================================== + + !=============================================================================== + ! 1. FOOD AVAILABILITY AND GRAZING PREFERENCES + !=============================================================================== + ! Calculates which prey types are available and their relative preferences. + ! Two modes: + ! - Variable preferences: Adjust based on relative prey abundance + ! - Fixed preferences: Use constant maximum preference values + ! + ! Variables: + ! pzPhy, pzDia : Max preference for small phyto and diatoms [-] + ! pzCocco, pzPhaeo: Max preference for coccoliths and Phaeocystis [-] + ! pzDet, pzDetZ2 : Max preference for slow/fast sinking detritus [-] + ! pzMicZoo : Max preference for microzooplankton [-] + ! PhyN, DiaN : Small phytoplankton and diatom nitrogen [mmolN m-3] + ! CoccoN, PhaeoN : Coccolithophore and Phaeocystis nitrogen [mmolN m-3] + ! DetN, DetZ2N : Slow and fast sinking detritus nitrogen [mmolN m-3] + ! MicZooN : Microzooplankton nitrogen [mmolN m-3] + ! varpz* : Variable preferences (calculated from availability) [-] + ! f*N : Available food pools (preference × concentration) [mmolN m-3] + ! aux : Total weighted food availability [mmolN m-3] + ! + ! Logic: + ! IF variable preferences: varpz_i = (pz_i × prey_i) / Σ(pz_j × prey_j) + ! ELSE: Use fixed maximum preferences (pz_i) + ! Food pools: f_i = preference_i × prey_i + !------------------------------------------------------------------------------- + + if (REcoM_Grazing_Variable_Preference) then + !--------------------------------------------------------------------------- + ! VARIABLE PREFERENCE MODE + ! Preferences scale with relative abundance of each prey type + !--------------------------------------------------------------------------- + + ! Calculate total weighted food availability (denominator) + aux = pzPhy * PhyN + pzDia * DiaN -!< *** Grazing fluxes *** -!< ********************** - food = fPhyN + fDiaN - if (Grazing_detritus) food = food + fDetN -#if defined (__3Zoo2Det) - if (Grazing_detritus) food = food + fDetZ2N - food = food + fMicZooN ! 3Zoo -#endif -#if defined (__coccos) - food = food + fCoccoN -#endif -! ****************************************************************************** - foodsq = food**2 - grazingFlux = (Graz_max * foodsq)/(epsilonr + foodsq) * HetN * arrFunc -#if defined (__3Zoo2Det) - grazingFlux = (Graz_max * foodsq)/(epsilonr + foodsq) * HetN * q10_mes -#endif - grazingFlux_phy = grazingFlux * fphyN / food - grazingFlux_Dia = grazingFlux * fDiaN / food - if (Grazing_detritus) grazingFlux_Det = grazingFlux * fDetN / food -#if defined (__3Zoo2Det) - if (Grazing_detritus) grazingFlux_DetZ2 = grazingFlux * fDetZ2N / food - grazingFlux_miczoo = grazingFlux * fMicZooN / food ! 3Zoo -#endif -#if defined (__coccos) - grazingFlux_Cocco = grazingFlux * fCoccoN / food -#endif - -!< *** Grazing efficiency *** -!< ************************** - grazEff = gfin + 1/(0.2*food + 2) - - grazingFluxcarbon_mes = (grazingFlux_phy * recipQuota * grazEff) & - + (grazingFlux_Dia * recipQuota_Dia * grazEff) - - if (Grazing_detritus) grazingFluxcarbon_mes = grazingFluxcarbon_mes & - + (grazingFlux_Det * recipDet * grazEff) -#if defined (__3Zoo2Det) - if (Grazing_detritus) grazingFluxcarbon_mes = grazingFluxcarbon_mes & - + (grazingFlux_DetZ2 * recipDet2 * grazEff) - grazingFluxcarbon_mes = grazingFluxcarbon_mes & - + (grazingFlux_miczoo * recipQZoo3 * grazEff) ! 3Zoo -#endif -#if defined (__coccos) - grazingFluxcarbon_mes = grazingFluxcarbon_mes & - + (grazingFlux_Cocco * recipQuota_Cocco * grazEff) -#endif + if (Grazing_detritus) then + aux = aux + pzDet * DetN + endif -!------------------------------------------------------------------------------- -! Second Zooplankton -!------------------------------------------------------------------------------- -!< Grazing on small phytoplankton, diatoms, coccolithophore (optional), -!< heterotrophs, slow- and fast-sinking detritus - -!< *** Food availability *** -!< ************************* -!< pzPhy2: Maximum nanophytoplankton preference -!< pzDia2: Maximum diatom preference -!< pzCocco2: Maximum coccolithophore preference -!< pzDet2: Maximum slow-sinking detritus prefence -!< pzDetZ22: Maximum fast-sinking detritus preference -!< pzHet: Maximum mesozooplankton preference -!< pzMicZoo2: Maximum microzooplankton preference - -#if defined (__3Zoo2Det) - if (REcoM_Grazing_Variable_Preference) then - aux = pzPhy2 * PhyN + PzDia2 * DiaN + pzHet * HetN - if (Grazing_detritus) aux = aux + pzDet2 * DetN + pzDetZ22 * DetZ2N - aux = aux + pzMicZoo2 * MicZooN ! 3Zoo -#if defined (__coccos) - aux = aux + pzCocco2 * CoccoN -#endif -! ****************************************************************************** - varpzPhy2 = (pzPhy2 * PhyN)/aux - varpzDia2 = (pzDia2 * DiaN)/aux - varpzMicZoo2 = (pzMicZoo2 * MicZooN)/aux ! 3Zoo - -#if defined (__coccos) - varpzCocco2 = (pzCocco2 * CoccoN)/aux -#endif - varpzHet = (pzHet * HetN)/aux - if (Grazing_detritus) then - varpzDet2 = (pzDet2 * DetN)/aux - varpzDetZ22 = (pzDetZ22 * DetZ2N)/aux - end if -! ****************************************************************************** - fDiaN2 = varpzDia2 * DiaN - fPhyN2 = varpzPhy2 * PhyN - fMicZooN2 = varpzMicZoo2 * MicZooN ! 3Zoo -#if defined (__coccos) - fCoccoN2 = varpzCocco2 * CoccoN -#endif - fHetN = varpzHet * HetN - if (Grazing_detritus) then - fDetN2 = varpzDet2 * DetN - fDetZ2N2 = varpzDetZ22 * DetZ2N - end if - else ! REcoM_Grazing_Variable_Preference = .false. - - fDiaN2 = pzDia2 * DiaN - fPhyN2 = pzPhy2 * PhyN - fMicZooN2 = pzMicZoo2 * MicZooN ! 3Zoo -#if defined (__coccos) - fCoccoN2 = pzCocco2 * CoccoN -#endif - fHetN = pzHet * HetN - if (Grazing_detritus) then - fDetN2 = pzDet2 * DetN - fDetZ2N2 = pzDetZ22 * DetZ2N - end if - end if ! REcoM_Grazing_Variable_Preference + if (enable_3zoo2det) then + if (Grazing_detritus) aux = aux + pzDetZ2 * DetZ2N ! Fast-sinking detritus + aux = aux + pzMicZoo * MicZooN ! Microzooplankton + endif -!< *** Grazing fluxes *** -!< ********************** - food2 = fPhyN2 + fDiaN2 + fHetN - if (Grazing_detritus) food2 = food2 + fDetN2 + fDetZ2N2 - food2 = food2 + fMicZooN2 ! 3Zoo -#if defined (__coccos) - food2 = food2 + fCoccoN2 -#endif -! ****************************************************************************** - foodsq2 = food2**2 - grazingFlux2 = (Graz_max2 * foodsq2)/(epsilon2 + foodsq2) * Zoo2N * arrFuncZoo2 + if (enable_coccos) then + aux = aux + pzCocco * CoccoN + pzPhaeo * PhaeoN + endif - grazingFlux_phy2 = (grazingFlux2 * fphyN2)/food2 - grazingFlux_Dia2 = (grazingFlux2 * fDiaN2)/food2 - grazingFlux_miczoo2 = (grazingFlux2 * fMicZooN2)/food2 ! 3Zoo + ! Calculate variable preferences (normalized by total availability) + varpzPhy = (pzPhy * PhyN) / aux + varpzDia = (pzDia * DiaN) / aux -#if defined (__coccos) - grazingFlux_Cocco2 = (grazingFlux2 * fCoccoN2)/food2 -#endif - grazingFlux_het2 = (grazingFlux2 * fHetN)/food2 if (Grazing_detritus) then - grazingFlux_Det2 = (grazingFlux2 * fDetN2)/food2 - grazingFlux_DetZ22 = (grazingFlux2 * fDetZ2N2)/food2 - end if + varpzDet = (pzDet * DetN) / aux + endif + + if (enable_3zoo2det) then + if (Grazing_detritus) varpzDetZ2 = (pzDetZ2 * DetZ2N) / aux + varpzMicZoo = (pzMicZoo * MicZooN) / aux + endif + + if (enable_coccos) then + varpzCocco = (pzCocco * CoccoN) / aux + varpzPhaeo = (pzPhaeo * PhaeoN) / aux + endif + + ! Calculate available food pools (preference × concentration) + fPhyN = varpzPhy * PhyN + fDiaN = varpzDia * DiaN - grazingFluxcarbonzoo2 = (grazingFlux_phy2 * recipQuota * grazEff2) & - + (grazingFlux_Dia2 * recipQuota_Dia * grazEff2) & - + (grazingFlux_het2 * recipQZoo * grazEff2) if (Grazing_detritus) then - grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & - + (grazingFlux_Det2 * recipDet * grazEff2) & - + (grazingFlux_DetZ22 * recipDet2 * grazEff2) - end if - grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & - + (grazingFlux_miczoo2 * recipQZoo3 * grazEff2) ! 3Zoo -#if defined (__coccos) - grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & - + (grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2) -#endif + fDetN = varpzDet * DetN + endif -!------------------------------------------------------------------------------- -! Third Zooplankton (Microzooplankton) -!------------------------------------------------------------------------------- -!< Grazing on small phytoplankton, diatoms and coccolithophore (optional) + if (enable_3zoo2det) then + if (Grazing_detritus) fDetZ2N = varpzDetZ2 * DetZ2N + fMicZooN = varpzMicZoo * MicZooN + endif -!< *** Food availability *** -!< ************************* -!< pzPhy3: Maximum nanophytoplankton preference -!< pzDia3: Maximum diatom preference -!< pzCocco3: Maximum coccolithophore preference + if (enable_coccos) then + fCoccoN = varpzCocco * CoccoN + fPhaeoN = varpzPhaeo * PhaeoN + endif - if (REcoM_Grazing_Variable_Preference) then - aux = pzPhy3 * PhyN + pzDia3 * DiaN -#if defined (__coccos) - aux = aux + pzCocco3 * CoccoN -#endif -! ****************************************************************************** - varpzPhy3 = (pzPhy3 * PhyN)/aux - varpzDia3 = (pzDia3 * DiaN)/aux -#if defined (__coccos) - varpzCocco3 = (pzCocco3 * CoccoN)/aux -#endif -! ****************************************************************************** - fPhyN3 = varpzPhy3 * PhyN - fDiaN3 = varpzDia3 * DiaN -#if defined (__coccos) - fCoccoN3 = varpzCocco3 * CoccoN -#endif - else ! REcoM_Grazing_Variable_Preference = .false. - - fPhyN3 = pzPhy3 * PhyN - fDiaN3 = pzDia3 * DiaN -#if defined (__coccos) - fCoccoN3 = pzCocco3 * CoccoN -#endif - endif !REcoM_Grazing_Variable_Preference - -!< *** Grazing fluxes *** -!< ********************** - food3 = fPhyN3 + fDiaN3 -#if defined (__coccos) - food3 = food3 + fCoccoN3 -#endif -! ****************************************************************************** - foodsq3 = food3**2 - grazingFlux3 = (Graz_max3 * foodsq3)/(epsilon3 + foodsq3) * MicZooN * q10_mic - grazingFlux_phy3 = (grazingFlux3 * fphyN3)/food3 - grazingFlux_Dia3 = (grazingFlux3 * fDiaN3)/food3 -#if defined (__coccos) - grazingFlux_Cocco3 = (grazingFlux3 * fCoccoN3)/food3 -#endif -#endif + else + !--------------------------------------------------------------------------- + ! FIXED PREFERENCE MODE + ! Use constant maximum preference values + !--------------------------------------------------------------------------- -!------------------------------------------------------------------------------- -!< Heterotrophic respiration is assumed to drive zooplankton back to -!< Redfield C:N if their C:N becomes higher than Redfield -!< res_het: Timescale for zooplankton respiration [day−1 ] - - if (het_resp_noredfield) then -#if defined (__3Zoo2Det) - HetRespFlux = res_het * q10_mes_res * HetC ! 3Zoo -#else - HetRespFlux = res_het * arrFunc * HetC ! tau * f_T [HetC] -#endif - else - HetRespFlux = recip_res_het * arrFunc * (hetC * recip_hetN_plus - redfield) * HetC - HetRespFlux = max(zero, HetRespFlux) !!!!!!!! CHECK Judith Valid for het_resp_noredfield case as well ???????? Then move it below + fPhyN = pzPhy * PhyN + fDiaN = pzDia * DiaN + + if (Grazing_detritus) then + fDetN = pzDet * DetN endif + if (enable_3zoo2det) then + if (Grazing_detritus) fDetZ2N = pzDetZ2 * DetZ2N + fMicZooN = pzMicZoo * MicZooN + endif -!------------------------------------------------------------------------------- -!< Zooplanton mortality (Quadratic) + if (enable_coccos) then + fCoccoN = pzCocco * CoccoN + fPhaeoN = pzPhaeo * PhaeoN + endif - hetLossFlux = loss_het * HetN * HetN + endif ! REcoM_Grazing_Variable_Preference + + !=============================================================================== + ! 2. TOTAL GRAZING FLUX (HOLLING TYPE III) + !=============================================================================== + ! Calculates total grazing rate using a sigmoidal (Type III) functional response. + ! This creates a threshold effect where grazing accelerates at higher food levels. + ! + ! Variables: + ! food : Total available food [mmolN m-3] + ! foodsq : Squared food concentration [mmolN2 m-6] + ! grazingFlux : Total N grazing rate [mmolN m-3 day-1] + ! Graz_max : Maximum specific grazing rate [day-1] + ! epsilonr : Half-saturation constant squared [mmolN2 m-6] + ! HetN : Mesozooplankton nitrogen concentration [mmolN m-3] + ! q10_mes : Q10 temperature function for mesozooplankton [-] + ! arrFunc : Arrhenius temperature function [-] + ! + ! Equation: Holling Type III + ! grazingFlux = (Graz_max × food²) / (epsilonr + food²) × HetN × T_func + ! + ! Note: Uses Q10 when 3-zoo/2-detritus enabled, otherwise uses Arrhenius + !------------------------------------------------------------------------------- + + ! Sum all available food pools + food = fPhyN + fDiaN -#if defined (__3Zoo2Det) -!------------------------------------------------------------------------------- -!< Second zooplankton respiration + if (Grazing_detritus) then + food = food + fDetN + endif - call krill_resp(n, partit, mesh) + if (enable_3zoo2det) then + if (Grazing_detritus) food = food + fDetZ2N + food = food + fMicZooN + endif - if((grazingFluxcarbonzoo2/Zoo2C) <= 0.1)then - res_zoo2_f = 0.1*(grazingFluxcarbonzoo2/Zoo2C*100) - else - res_zoo2_f = 1. - end if - recip_res_zoo22 = res_zoo2*(1.+ res_zoo2_f + res_zoo2_a) - Zoo2RespFlux = recip_res_zoo22 * Zoo2C -!------------------------------------------------------------------------------- -!< Second zooplankton mortality (Quadratic) + if (enable_coccos) then + food = food + fCoccoN + fPhaeoN + endif - Zoo2LossFlux = loss_zoo2 * zoo2N * zoo2N + ! Calculate grazing flux with Holling Type III functional response + foodsq = food**2 -!------------------------------------------------------------------------------- -!< Second zooplankton fecal pellets + if (enable_3zoo2det) then + grazingFlux = (Graz_max * foodsq) / (epsilonr + foodsq) * HetN * q10_mes + else + grazingFlux = (Graz_max * foodsq) / (epsilonr + foodsq) * HetN * arrFunc + endif - Zoo2fecalloss_n = fecal_rate_n * grazingFlux2 - Zoo2fecalloss_c = fecal_rate_c * grazingFluxcarbonzoo2 + !=============================================================================== + ! 3. GRAZING FLUX DISTRIBUTION + !=============================================================================== + ! Partitions total grazing among prey types proportional to their availability. + ! + ! Variables: + ! grazingFlux_phy : Grazing on small phytoplankton [mmolN m-3 day-1] + ! grazingFlux_Dia : Grazing on diatoms [mmolN m-3 day-1] + ! grazingFlux_Det : Grazing on slow-sinking detritus [mmolN m-3 day-1] + ! grazingFlux_DetZ2 : Grazing on fast-sinking detritus [mmolN m-3 day-1] + ! grazingFlux_miczoo : Grazing on microzooplankton [mmolN m-3 day-1] + ! grazingFlux_Cocco : Grazing on coccolithophores [mmolN m-3 day-1] + ! grazingFlux_Phaeo : Grazing on Phaeocystis [mmolN m-3 day-1] + ! + ! Equation for each prey type i: + ! grazingFlux_i = grazingFlux × (f_i / total_food) + !------------------------------------------------------------------------------- + + grazingFlux_phy = grazingFlux * fPhyN / food + grazingFlux_Dia = grazingFlux * fDiaN / food -!------------------------------------------------------------------------------- -!< Mesozooplankton fecal pellets + if (Grazing_detritus) then + grazingFlux_Det = grazingFlux * fDetN / food + endif - mesfecalloss_n = fecal_rate_n_mes * grazingFlux - mesfecalloss_c = fecal_rate_c_mes * grazingFluxcarbon_mes + if (enable_3zoo2det) then + if (Grazing_detritus) grazingFlux_DetZ2 = grazingFlux * fDetZ2N / food + grazingFlux_miczoo = grazingFlux * fMicZooN / food + endif -!------------------------------------------------------------------------------- -! Third zooplankton, microzooplankton, respiration ! 3Zoo + if (enable_coccos) then + grazingFlux_Cocco = grazingFlux * fCoccoN / food + grazingFlux_Phaeo = grazingFlux * fPhaeoN / food + endif - MicZooRespFlux = res_miczoo * q10_mic_res * MicZooC -!------------------------------------------------------------------------------- -! Third zooplankton, microzooplankton, mortality (Quadratic) ! 3Zoo + !=============================================================================== + ! 4. GRAZING EFFICIENCY AND CARBON FLUX + !=============================================================================== + ! Calculates food-dependent assimilation efficiency and converts grazed nitrogen + ! to carbon flux using prey-specific C:N ratios. + ! + ! Variables: + ! grazEff : Grazing/assimilation efficiency [-] + ! gfin : Baseline grazing efficiency [-] + ! grazingFluxcarbon_mes : Total carbon flux to mesozooplankton [mmolC m-3 day-1] + ! recipQuota : Small phytoplankton C:N ratio [mmolC mmolN-1] + ! recipQuota_Dia : Diatom C:N ratio [mmolC mmolN-1] + ! recipQuota_Cocco : Coccolithophore C:N ratio [mmolC mmolN-1] + ! recipQuota_phaeo : Phaeocystis C:N ratio [mmolC mmolN-1] + ! recipDet, recipDet2 : Detritus C:N ratios [mmolC mmolN-1] + ! recipQZoo3 : Microzooplankton C:N ratio [mmolC mmolN-1] + ! + ! Grazing Efficiency Equation: + ! grazEff = gfin + 1/(0.2×food + 2) + ! Higher food -> higher efficiency (asymptotes to gfin + 0.5) + ! + ! Carbon Flux Equation: + ! C_flux = Σ(grazingFlux_i × C:N_ratio_i × grazEff) + !------------------------------------------------------------------------------- + + ! Calculate food-dependent grazing efficiency + ! Increases with food availability, representing improved assimilation at higher rations + grazEff = gfin + 1.0 / (0.2 * food + 2.0) + + ! Convert grazed nitrogen to carbon flux using prey C:N ratios + grazingFluxcarbon_mes = (grazingFlux_phy * recipQuota * grazEff) + & + (grazingFlux_Dia * recipQuota_Dia * grazEff) - MicZooLossFlux = loss_miczoo * MicZooN * MicZooN -#endif + if (Grazing_detritus) then + grazingFluxcarbon_mes = grazingFluxcarbon_mes + & + (grazingFlux_Det * recipDet * grazEff) + endif -!------------------------------------------------------------------------------- -! Phytoplankton and detritus aggregation -!------------------------------------------------------------------------------- - if (diatom_mucus) then - qlimitFac = recom_limiter(NMinSlope, NCmin_d, quota_dia) - qlimitFacTmp = recom_limiter(SiMinSlope, SiCmin, qSiC) - qlimitFac = min(qLimitFac, qlimitFacTmp) - feLimitFac= Fe/(k_Fe_d + Fe) - qlimitFac = min(qlimitFac, feLimitFac) - aggregationrate = agg_PP * (1 - qlimitFac) * DiaN - else - aggregationrate = agg_PP * DiaN + if (enable_3zoo2det) then + if (Grazing_detritus) then + grazingFluxcarbon_mes = grazingFluxcarbon_mes + & + (grazingFlux_DetZ2 * recipDet2 * grazEff) endif - - aggregationrate = aggregationrate + agg_PD * DetN + agg_PP * PhyN - -#if defined (__3Zoo2Det) - aggregationrate = aggregationrate + agg_PD * DetZ2N ! 2Det -#endif -#if defined (__coccos) - aggregationrate = aggregationrate + agg_PP * CoccoN -#endif - -!------------------------------------------------------------------------------- -! Calcification -!------------------------------------------------------------------------------- -! Terms required for the formation and dissolution of CaCO3 -! Without this, calcification is performed by a fraction of small phytoplankton + grazingFluxcarbon_mes = grazingFluxcarbon_mes + & + (grazingFlux_miczoo * recipQZoo3 * grazEff) + endif + + if (enable_coccos) then + grazingFluxcarbon_mes = grazingFluxcarbon_mes + & + (grazingFlux_Cocco * recipQuota_Cocco * grazEff) + & + (grazingFlux_Phaeo * recipQuota_phaeo * grazEff) + endif + + !=============================================================================== + ! MACROZOOPLANKTON GRAZING + !=============================================================================== + ! Simulates macrozooplankton (second zooplankton) grazing on multiple prey types + ! using a Holling Type II functional response with food-dependent preferences. + ! + ! This module calculates: + ! 1. Food availability and grazing preferences (fixed or variable) + ! 2. Total grazing flux with Holling Type II response + ! 3. Distribution of grazing among prey types + ! 4. Carbon assimilation from grazed prey using C:N ratios + ! + ! Key Features: + ! - Carnivorous feeding: grazes on mesozooplankton and microzooplankton + ! - Herbivorous feeding: grazes on phytoplankton, diatoms, coccolithophores + ! - Detritivorous feeding: optional grazing on slow/fast-sinking detritus + ! - Variable or fixed prey preferences + ! - Temperature-dependent grazing rate (Arrhenius) + ! - Constant assimilation efficiency (grazEff2) + ! + ! Prey Types: + ! - Primary: Mesozooplankton, microzooplankton, small phyto, diatoms + ! - Optional: Coccolithophores, Phaeocystis, slow/fast-sinking detritus + ! + ! References: + ! - Schourup-Kristensen et al. (2013) - REcoM model description + !=============================================================================== + + if (enable_3zoo2det) then + + !=========================================================================== + ! 1. FOOD AVAILABILITY AND GRAZING PREFERENCES + !=========================================================================== + ! Calculates which prey types are available and their relative preferences. + ! Two modes: + ! - Variable preferences: Adjust based on relative prey abundance + ! - Fixed preferences: Use constant maximum preference values + ! + ! Variables: + ! pzPhy2, pzDia2 : Max preference for small phyto and diatoms [-] + ! pzCocco2, pzPhaeo2: Max preference for coccoliths and Phaeocystis [-] + ! pzHet : Max preference for mesozooplankton [-] + ! pzMicZoo2 : Max preference for microzooplankton [-] + ! pzDet2, pzDetZ22 : Max preference for slow/fast sinking detritus [-] + ! PhyN, DiaN : Small phytoplankton and diatom nitrogen [mmolN m-3] + ! CoccoN, PhaeoN : Coccolithophore and Phaeocystis nitrogen [mmolN m-3] + ! HetN : Mesozooplankton nitrogen [mmolN m-3] + ! MicZooN : Microzooplankton nitrogen [mmolN m-3] + ! DetN, DetZ2N : Slow and fast sinking detritus nitrogen [mmolN m-3] + ! varpz*2, varpzHet: Variable preferences (calculated from availability) [-] + ! f*N2, fHetN : Available food pools (preference × concentration) [mmolN m-3] + ! aux : Total weighted food availability [mmolN m-3] + ! + ! Logic: + ! IF variable preferences: varpz_i = (pz_i × prey_i) / Σ(pz_j × prey_j) + ! ELSE: Use fixed maximum preferences (pz_i) + ! Food pools: f_i = preference_i × prey_i + !--------------------------------------------------------------------------- + + if (REcoM_Grazing_Variable_Preference) then + !----------------------------------------------------------------------- + ! VARIABLE PREFERENCE MODE + ! Preferences scale with relative abundance of each prey type + !----------------------------------------------------------------------- + + ! Calculate total weighted food availability (denominator) + ! Core prey: phytoplankton, diatoms, meso- and microzooplankton + aux = pzPhy2 * PhyN + pzDia2 * DiaN + pzHet * HetN + pzMicZoo2 * MicZooN + + ! Add detritus pools if detrital grazing is enabled + if (Grazing_detritus) then + aux = aux + pzDet2 * DetN + pzDetZ22 * DetZ2N + endif + + ! Add coccolithophores and Phaeocystis if enabled + if (enable_coccos) then + aux = aux + pzCocco2 * CoccoN + pzPhaeo2 * PhaeoN + endif + + ! Calculate variable preferences (normalized by total availability) + ! Each preference = (max_pref × prey_conc) / total_weighted_food + varpzPhy2 = (pzPhy2 * PhyN) / aux + varpzDia2 = (pzDia2 * DiaN) / aux + varpzMicZoo2 = (pzMicZoo2 * MicZooN) / aux + varpzHet = (pzHet * HetN) / aux + + if (enable_coccos) then + varpzCocco2 = (pzCocco2 * CoccoN) / aux + varpzPhaeo2 = (pzPhaeo2 * PhaeoN) / aux + endif + + if (Grazing_detritus) then + varpzDet2 = (pzDet2 * DetN) / aux + varpzDetZ22 = (pzDetZ22 * DetZ2N) / aux + end if + + ! Calculate available food pools (preference × concentration) + fPhyN2 = varpzPhy2 * PhyN + fDiaN2 = varpzDia2 * DiaN + fMicZooN2 = varpzMicZoo2 * MicZooN + fHetN = varpzHet * HetN + + if (enable_coccos) then + fCoccoN2 = varpzCocco2 * CoccoN + fPhaeoN2 = varpzPhaeo2 * PhaeoN + endif + + if (Grazing_detritus) then + fDetN2 = varpzDet2 * DetN + fDetZ2N2 = varpzDetZ22 * DetZ2N + end if -#if defined (__coccos) - if (Temp(k) < 10.6) then ! (PICPOC definition after Krumhardt et al. 2017, 2019; Temp(k) because we need degC here) - PICPOCtemp = 0.104d0 * Temp(k) - 0.108d0 else - PICPOCtemp = 1.0d0 - end if - PICPOCtemp = max(tiny,PICPOCtemp) - - PICPOCCO2 = a_co2_calc * HCO3_watercolumn(k) * Cunits / (b_co2_calc + HCO3_watercolumn(k) * Cunits) - exp(-c_co2_calc * CO2_watercolumn(k) * Cunits) - d_co2_calc * 10.**(-pH_watercolumn(k)) - PICPOCCO2 = min(PICPOCCO2,3.d0) ! April 2022: limitation to 3 - PICPOCCO2 = max(0.d0,PICPOCCO2) ! July 2022: limitation to zero - - PICPOCN = -0.31 * (DIN/(DIN + k_din_c)) + 1.31 - PICPOCN = max(tiny,PICPOCN) - - calcification = 1.d0 * Cphot_cocco * CoccoC * PICPOCtemp * PICPOCN - if (CO2lim) calcification = calcification * PICPOCCO2 - -#else -!< calc_prod_ratio: Calcite production ratio, dimensionless - calcification = calc_prod_ratio * Cphot * PhyC ! Z in equations -#endif - - calc_loss_agg = aggregationrate * PhyCalc - -#if defined (__coccos) -!< *** Coccolithophores *** -!< ************************ - aux = recipQuota_Cocco/(CoccoC + tiny) * PhyCalc - calc_loss_gra = grazingFlux_Cocco * aux -#if defined (__3Zoo2Det) - calc_loss_gra2 = grazingFlux_Cocco2 * aux - calc_loss_gra3 = grazingFlux_Cocco3 * aux ! 3Zoo -#endif - -#else -!< *** Small phytoplankton *** -!< *************************** - aux = recipQuota/(PhyC + tiny) * PhyCalc - calc_loss_gra = grazingFlux_phy * aux -#if defined (__3Zoo2Det) - calc_loss_gra2 = grazingFlux_phy2 * aux - calc_loss_gra3 = grazingFlux_phy3 * aux ! 3Zoo -#endif -#endif -!------------------------------------------------------------------------------- -! Sources minus sinks (SMS) -!------------------------------------------------------------------------------- + !----------------------------------------------------------------------- + ! FIXED PREFERENCE MODE + ! Use constant maximum preference values + !----------------------------------------------------------------------- + + fPhyN2 = pzPhy2 * PhyN + fDiaN2 = pzDia2 * DiaN + fMicZooN2 = pzMicZoo2 * MicZooN + fHetN = pzHet * HetN -!< *** DIN *** -!< *********** - -!< N_assim: N assimilation rate for nanophytoplankton [mmolN mmolC-1 day-1] -!< PhyC: Intracellular carbon concentration in nanophytoplankton [mmolC m-3] -!< N_assim_Dia: N assimilation rate for diatoms [mmolN mmolC-1 day-1] -!< DiaC: Intracellular carbon concentration in diatoms [mmolC m-3] -!< N_assim_Cocco: N assimilation rate for coccolithophore [mmolN mmolC-1 day-1] -!< CoccoC: Intracellular carbon concentration in coccolithophore [mmolC m-3] -!< rho_N*arrFunc: Remineralization rate and temperature dependency which is calculated with arrFunc [day^-1] -!< O2Func: O2 dependency of organic matter remineralization -!< DON: Extracellular dissolved organic nitrogen [mmolN m-3] -!< dt_b: REcoM time step [day] - -!! Schourup 2013 Eq. A2 - - sms(k,idin) = ( & - - N_assim * PhyC & ! --> N assimilation Nanophytoplankton, [mmol N/(mmol C * day)] C specific N utilization rate - - N_assim_Dia * DiaC & ! --> N assimilation Diatoms -#if defined (__coccos) - - N_assim_Cocco * CoccoC & ! --> N assimilation Coccolithophore -#endif - + rho_N * arrFunc * O2Func * DON & ! --> DON remineralization, temperature dependent [day^-1 * mmol/m3] ! O2remin - ) * dt_b + sms(k,idin) - -!< *** DIC *** -!< *********** - -!< rho_C1: Temperature dependent C degradation of extracellular organic C (EOC) [day^-1] - - sms(k,idic) = ( & - - Cphot * PhyC & ! --> Small pyhtoplankton photosynthesis - + phyRespRate * PhyC & ! --> Small pyhtoplankton respiration - - Cphot_Dia * DiaC & ! --> Diatom photosynthesis - + phyRespRate_Dia * DiaC & ! --> Diatom respiration -#if defined (__coccos) - - Cphot_Cocco * CoccoC & ! --> Coccolithophore photosynthesis - + phyRespRate_Cocco * CoccoC & ! --> Coccolithophore respiration -#endif - + rho_C1 * arrFunc * O2Func * EOC & ! --> Remineralization of DOC ! NEW O2remin - + HetRespFlux & ! --> Mesozooplankton respiration -#if defined (__3Zoo2Det) - + Zoo2RespFlux & ! --> Macrozooplankton respiration - + MicZooRespFlux & ! --> Microzooplankton respiration -#endif - + calc_diss * DetCalc & ! --> Calcite dissolution from slow-sinking detritus - + calc_loss_gra * calc_diss_guts & ! --> Additional dissolution in mesozooplankton guts -#if defined (__3Zoo2Det) - + calc_loss_gra2 * calc_diss_guts & ! --> Additional dissolution in macrozooplankton guts - + calc_loss_gra3 * calc_diss_guts & ! --> Additional dissolution in microzooplankton guts - + calc_diss2 * DetZ2Calc & ! --> Calcite dissolution from fast-sinking detritus -#endif - - calcification & ! --> Calcification - ) * dt_b + sms(k,idic) + if (enable_coccos) then + fCoccoN2 = pzCocco2 * CoccoN + fPhaeoN2 = pzPhaeo2 * PhaeoN + endif + + if (Grazing_detritus) then + fDetN2 = pzDet2 * DetN + fDetZ2N2 = pzDetZ22 * DetZ2N + end if + + end if ! REcoM_Grazing_Variable_Preference + + !=========================================================================== + ! 2. TOTAL GRAZING FLUX (HOLLING TYPE II) + !=========================================================================== + ! Calculates total grazing rate using a hyperbolic (Type II) functional + ! response. This creates saturating grazing at high food concentrations. + ! + ! Variables: + ! food2 : Total available food [mmolN m-3] + ! foodsq2 : Squared food concentration [mmolN2 m-6] + ! grazingFlux2 : Total N grazing rate [mmolN m-3 day-1] + ! Graz_max2 : Maximum specific grazing rate [day-1] + ! epsilon2 : Half-saturation constant squared [mmolN2 m-6] + ! Zoo2N : Macrozooplankton nitrogen concentration [mmolN m-3] + ! arrFuncZoo2 : Arrhenius temperature function for macrozooplankton [-] + ! + ! Equation: Holling Type II + ! grazingFlux2 = (Graz_max2 × food²) / (epsilon2 + food²) × Zoo2N × T_func + ! + ! Note: Uses Arrhenius temperature dependency (arrFuncZoo2) + !--------------------------------------------------------------------------- + + ! Sum all available food pools + food2 = fPhyN2 + fDiaN2 + fHetN + fMicZooN2 + + if (Grazing_detritus) then + food2 = food2 + fDetN2 + fDetZ2N2 + endif + + if (enable_coccos) then + food2 = food2 + fCoccoN2 + fPhaeoN2 + endif + + ! Calculate grazing flux with Holling Type II functional response + ! Type II uses squared food (similar to Type III but with different parameters) + foodsq2 = food2**2 + grazingFlux2 = (Graz_max2 * foodsq2) / (epsilon2 + foodsq2) * Zoo2N * arrFuncZoo2 + + !=========================================================================== + ! 3. GRAZING FLUX DISTRIBUTION + !=========================================================================== + ! Partitions total grazing among prey types proportional to their availability. + ! + ! Variables: + ! grazingFlux_phy2 : Grazing on small phytoplankton [mmolN m-3 day-1] + ! grazingFlux_Dia2 : Grazing on diatoms [mmolN m-3 day-1] + ! grazingFlux_miczoo2 : Grazing on microzooplankton [mmolN m-3 day-1] + ! grazingFlux_het2 : Grazing on mesozooplankton [mmolN m-3 day-1] + ! grazingFlux_Cocco2 : Grazing on coccolithophores [mmolN m-3 day-1] + ! grazingFlux_Phaeo2 : Grazing on Phaeocystis [mmolN m-3 day-1] + ! grazingFlux_Det2 : Grazing on slow-sinking detritus [mmolN m-3 day-1] + ! grazingFlux_DetZ22 : Grazing on fast-sinking detritus [mmolN m-3 day-1] + ! + ! Equation for each prey type i: + ! grazingFlux_i = grazingFlux2 × (f_i / total_food) + !--------------------------------------------------------------------------- + + ! Distribute total grazing among prey types proportionally + grazingFlux_phy2 = (grazingFlux2 * fPhyN2) / food2 + grazingFlux_Dia2 = (grazingFlux2 * fDiaN2) / food2 + grazingFlux_miczoo2 = (grazingFlux2 * fMicZooN2) / food2 + grazingFlux_het2 = (grazingFlux2 * fHetN) / food2 + + if (enable_coccos) then + grazingFlux_Cocco2 = (grazingFlux2 * fCoccoN2) / food2 + grazingFlux_Phaeo2 = (grazingFlux2 * fPhaeoN2) / food2 + endif + + if (Grazing_detritus) then + grazingFlux_Det2 = (grazingFlux2 * fDetN2) / food2 + grazingFlux_DetZ22 = (grazingFlux2 * fDetZ2N2) / food2 + end if + + !=========================================================================== + ! 4. CARBON ASSIMILATION + !=========================================================================== + ! Converts grazed nitrogen to assimilated carbon flux using prey-specific + ! C:N ratios and constant grazing efficiency. + ! + ! Variables: + ! grazingFluxcarbonzoo2 : Total carbon flux to macrozooplankton [mmolC m-3 day-1] + ! grazEff2 : Macrozooplankton grazing efficiency (constant) [-] + ! recipQuota : Small phytoplankton C:N ratio [mmolC mmolN-1] + ! recipQuota_Dia : Diatom C:N ratio [mmolC mmolN-1] + ! recipQuota_Cocco : Coccolithophore C:N ratio [mmolC mmolN-1] + ! recipQuota_Phaeo : Phaeocystis C:N ratio [mmolC mmolN-1] + ! recipQZoo : Mesozooplankton C:N ratio [mmolC mmolN-1] + ! recipQZoo3 : Microzooplankton C:N ratio [mmolC mmolN-1] + ! recipDet, recipDet2 : Detritus C:N ratios [mmolC mmolN-1] + ! + ! Carbon Flux Equation: + ! C_flux = Σ(grazingFlux_i × C:N_ratio_i × grazEff2) + ! + ! Note: Unlike mesozooplankton, macrozooplankton uses constant efficiency + ! (grazEff2) rather than food-dependent efficiency + !--------------------------------------------------------------------------- + + ! Convert grazed nitrogen to carbon flux using prey C:N ratios + ! Start with core prey types (always present) + grazingFluxcarbonzoo2 = (grazingFlux_phy2 * recipQuota * grazEff2) + & + (grazingFlux_Dia2 * recipQuota_Dia * grazEff2) + & + (grazingFlux_het2 * recipQZoo * grazEff2) + & + (grazingFlux_miczoo2 * recipQZoo3 * grazEff2) + + ! Add detritus contribution if detrital grazing is enabled + if (Grazing_detritus) then + grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & + (grazingFlux_Det2 * recipDet * grazEff2) + & + (grazingFlux_DetZ22 * recipDet2 * grazEff2) + end if + + ! Add coccolithophore and Phaeocystis contribution if enabled + if (enable_coccos) then + grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & + (grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2) + & + (grazingFlux_Phaeo2 * recipQuota_Phaeo * grazEff2) + endif + + endif ! enable_3zoo2det + + !=============================================================================== + ! MICROZOOPLANKTON GRAZING + !=============================================================================== + ! Simulates microzooplankton (third zooplankton) grazing on phytoplankton prey + ! using a Holling Type II functional response with food-dependent preferences. + ! + ! This module calculates: + ! 1. Food availability and grazing preferences (fixed or variable) + ! 2. Total grazing flux with Holling Type II response + ! 3. Distribution of grazing among prey types + ! 4. Carbon assimilation from grazed prey (calculated elsewhere) + ! + ! Key Features: + ! - Strictly herbivorous: only grazes on phytoplankton groups + ! - No carnivory: does not graze on other zooplankton + ! - No detritivory: does not graze on detritus + ! - Variable or fixed prey preferences + ! - Temperature-dependent grazing rate (Q10) + ! - Smallest zooplankton size class (fastest response to phytoplankton) + ! + ! Prey Types: + ! - Primary: Small phytoplankton, diatoms + ! - Optional: Coccolithophores, Phaeocystis + ! + ! Ecological Role: + ! - Links small phytoplankton to higher trophic levels + ! - Prey for mesozooplankton and macrozooplankton + ! - Rapid response to phytoplankton blooms + ! + ! References: + ! - Schourup-Kristensen et al. (2013) - REcoM model description + !=============================================================================== + + if (enable_3zoo2det) then + + !=========================================================================== + ! 1. FOOD AVAILABILITY AND GRAZING PREFERENCES + !=========================================================================== + ! Calculates which phytoplankton prey types are available and their + ! relative preferences. + ! Two modes: + ! - Variable preferences: Adjust based on relative prey abundance + ! - Fixed preferences: Use constant maximum preference values + ! + ! Variables: + ! pzPhy3, pzDia3 : Max preference for small phyto and diatoms [-] + ! pzCocco3, pzPhaeo3 : Max preference for coccoliths and Phaeocystis [-] + ! PhyN, DiaN : Small phytoplankton and diatom nitrogen [mmolN m-3] + ! CoccoN, PhaeoN : Coccolithophore and Phaeocystis nitrogen [mmolN m-3] + ! varpzPhy3, varpzDia3: Variable preferences (calculated from availability) [-] + ! varpzCocco3, varpzPhaeo3: Variable preferences for coccos/phaeo [-] + ! fPhyN3, fDiaN3 : Available food pools (preference × concentration) [mmolN m-3] + ! fCoccoN3, fPhaeoN3 : Available coccolithophore/Phaeocystis pools [mmolN m-3] + ! aux : Total weighted food availability [mmolN m-3] + ! + ! Logic: + ! IF variable preferences: varpz_i = (pz_i × prey_i) / Σ(pz_j × prey_j) + ! ELSE: Use fixed maximum preferences (pz_i) + ! Food pools: f_i = preference_i × prey_i + ! + ! Note: Microzooplankton have simpler feeding than meso/macrozooplankton + ! - No carnivory (no zooplankton prey) + ! - No detritivory (no detritus grazing) + !--------------------------------------------------------------------------- + + if (REcoM_Grazing_Variable_Preference) then + !----------------------------------------------------------------------- + ! VARIABLE PREFERENCE MODE + ! Preferences scale with relative abundance of each phytoplankton type + !----------------------------------------------------------------------- + + ! Calculate total weighted food availability (denominator) + ! Core phytoplankton prey: small phytoplankton and diatoms + aux = pzPhy3 * PhyN + pzDia3 * DiaN + + ! Add coccolithophores and Phaeocystis if enabled + if (enable_coccos) then + aux = aux + pzCocco3 * CoccoN + pzPhaeo3 * PhaeoN + endif + + ! Calculate variable preferences (normalized by total availability) + ! Each preference = (max_pref × prey_conc) / total_weighted_food + varpzPhy3 = (pzPhy3 * PhyN) / aux + varpzDia3 = (pzDia3 * DiaN) / aux + + if (enable_coccos) then + varpzCocco3 = (pzCocco3 * CoccoN) / aux + varpzPhaeo3 = (pzPhaeo3 * PhaeoN) / aux + endif + + ! Calculate available food pools (preference × concentration) + fPhyN3 = varpzPhy3 * PhyN + fDiaN3 = varpzDia3 * DiaN + + if (enable_coccos) then + fCoccoN3 = varpzCocco3 * CoccoN + fPhaeoN3 = varpzPhaeo3 * PhaeoN + endif + + else + !----------------------------------------------------------------------- + ! FIXED PREFERENCE MODE + ! Use constant maximum preference values + !----------------------------------------------------------------------- + + fPhyN3 = pzPhy3 * PhyN + fDiaN3 = pzDia3 * DiaN + + if (enable_coccos) then + fCoccoN3 = pzCocco3 * CoccoN + fPhaeoN3 = pzPhaeo3 * PhaeoN + endif + + endif ! REcoM_Grazing_Variable_Preference + + !=========================================================================== + ! 2. TOTAL GRAZING FLUX (HOLLING TYPE II) + !=========================================================================== + ! Calculates total grazing rate using a hyperbolic (Type II) functional + ! response. This creates saturating grazing at high phytoplankton + ! concentrations. + ! + ! Variables: + ! food3 : Total available phytoplankton food [mmolN m-3] + ! foodsq3 : Squared food concentration [mmolN2 m-6] + ! grazingFlux3 : Total N grazing rate [mmolN m-3 day-1] + ! Graz_max3 : Maximum specific grazing rate [day-1] + ! epsilon3 : Half-saturation constant squared [mmolN2 m-6] + ! MicZooN : Microzooplankton nitrogen concentration [mmolN m-3] + ! q10_mic : Q10 temperature function for microzooplankton [-] + ! + ! Equation: Holling Type II + ! grazingFlux3 = (Graz_max3 × food³) / (epsilon3 + food²) × MicZooN × T_func + ! + ! Note: Uses Q10 temperature dependency (q10_mic) for rapid metabolic response + ! Smaller organisms typically have higher Q10 sensitivity + !--------------------------------------------------------------------------- + + ! Sum all available phytoplankton food pools + food3 = fPhyN3 + fDiaN3 + + if (enable_coccos) then + food3 = food3 + fCoccoN3 + fPhaeoN3 + endif + + ! Calculate grazing flux with Holling Type II functional response + ! Type II creates hyperbolic saturation: grazing rate increases rapidly + ! at low food, then saturates at high food concentrations + foodsq3 = food3**2 + grazingFlux3 = (Graz_max3 * foodsq3) / (epsilon3 + foodsq3) * MicZooN * q10_mic + + !=========================================================================== + ! 3. GRAZING FLUX DISTRIBUTION + !=========================================================================== + ! Partitions total grazing among phytoplankton prey types proportional + ! to their availability. + ! + ! Variables: + ! grazingFlux_phy3 : Grazing on small phytoplankton [mmolN m-3 day-1] + ! grazingFlux_Dia3 : Grazing on diatoms [mmolN m-3 day-1] + ! grazingFlux_Cocco3 : Grazing on coccolithophores [mmolN m-3 day-1] + ! grazingFlux_Phaeo3 : Grazing on Phaeocystis [mmolN m-3 day-1] + ! + ! Equation for each prey type i: + ! grazingFlux_i = grazingFlux3 × (f_i / total_food) + ! + ! Note: This proportional distribution ensures conservation of mass + ! The sum of all distributed fluxes equals the total grazing flux + !--------------------------------------------------------------------------- + + ! Distribute total grazing among phytoplankton prey types proportionally + grazingFlux_phy3 = (grazingFlux3 * fPhyN3) / food3 + grazingFlux_Dia3 = (grazingFlux3 * fDiaN3) / food3 + + if (enable_coccos) then + grazingFlux_Cocco3 = (grazingFlux3 * fCoccoN3) / food3 + grazingFlux_Phaeo3 = (grazingFlux3 * fPhaeoN3) / food3 + endif + + !=========================================================================== + ! 4. CARBON ASSIMILATION + !=========================================================================== + ! Carbon flux calculation for microzooplankton is handled elsewhere in the + ! model code using the nitrogen grazing fluxes calculated above and + ! prey-specific C:N ratios. + ! + ! The carbon assimilation follows the general pattern: + ! C_flux = Σ(grazingFlux_i × C:N_ratio_i × grazEff3) + ! + ! Where: + ! grazEff3 = Microzooplankton grazing efficiency (constant) [-] + ! C:N ratios for each phytoplankton prey type [mmolC mmolN-1] + ! + ! This calculation is performed in the carbon balance section of the model + ! to maintain consistency with other carbon flux calculations. + !=========================================================================== + + endif ! enable_3zoo2det + + !=============================================================================== + ! MESOZOOPLANKTON RESPIRATION + !=============================================================================== + ! Calculates mesozooplankton carbon respiration using either simple temperature- + ! dependent respiration or Redfield-based respiration that accounts for C:N + ! stoichiometry deviations. + ! + ! Two respiration modes: + ! A) Simple mode: Constant specific rate with temperature correction + ! B) Redfield mode: Respirate excess carbon above Redfield C:N ratio + ! + ! Variables: + ! HetRespFlux : Mesozooplankton respiration rate [mmolC m-3 day-1] + ! res_het : Baseline respiration rate constant [day-1] + ! HetC : Mesozooplankton carbon concentration [mmolC m-3] + ! HetN : Mesozooplankton nitrogen concentration [mmolN m-3] + ! q10_mes_res : Q10 temperature function for meso respiration [-] + ! arrFunc : Arrhenius temperature function [-] + ! recip_hetN_plus : Reciprocal of (HetN + small number) [mmolN-1 m3] + ! redfield : Redfield C:N ratio (106:16 ≈ 6.625) [mmolC mmolN-1] + ! recip_res_het : Reciprocal respiration parameter [day-1] + ! + ! Logic: + ! IF simple mode: RespFlux = res_het × T_func × HetC + ! ELSE Redfield mode: RespFlux = recip_res_het × T_func × (C:N - Redfield) × HetC + ! Redfield mode respirates excess carbon when C:N > Redfield ratio + ! + ! Note: Redfield-based respiration maintains stoichiometric homeostasis + !------------------------------------------------------------------------------- + + if (het_resp_noredfield) then + !--------------------------------------------------------------------------- + ! SIMPLE RESPIRATION MODE + ! Constant specific rate with temperature dependency + !--------------------------------------------------------------------------- + + if (enable_3zoo2det) then + ! Use Q10 temperature function (exponential temperature sensitivity) + HetRespFlux = res_het * q10_mes_res * HetC + else + ! Use Arrhenius temperature function + HetRespFlux = res_het * arrFunc * HetC + endif + + else + !--------------------------------------------------------------------------- + ! REDFIELD-BASED RESPIRATION MODE + ! Respirate excess carbon above Redfield C:N ratio + !--------------------------------------------------------------------------- + + ! Calculate respiration based on deviation from Redfield ratio + ! When C:N > Redfield, organism has excess carbon that must be respired + ! This maintains stoichiometric balance in the organism + HetRespFlux = recip_res_het * arrFunc * (HetC * recip_hetN_plus - redfield) * HetC + + ! Ensure non-negative flux (no respiration when C:N ≤ Redfield) + HetRespFlux = max(zero, HetRespFlux) + + endif + + !=============================================================================== + ! CARBON ISOTOPE TRACKING (OPTIONAL) + !=============================================================================== + ! Tracks respiration fluxes of carbon isotopes (13C and 14C) for paleoclimate + ! and carbon cycle studies. + ! + ! Variables: + ! HetRespFlux_13 : 13C respiration flux [mmol13C m-3 day-1] + ! HetRespFlux_14 : 14C respiration flux [mmol14C m-3 day-1] + ! HetC_13 : Mesozooplankton 13C concentration [mmol13C m-3] + ! HetC_14 : Mesozooplankton 14C concentration [mmol14C m-3] + ! HetC : Total mesozooplankton carbon [mmolC m-3] + ! ciso : Flag for 13C isotope tracking [logical] + ! ciso_14 : Flag for 14C isotope tracking [logical] + ! ciso_organic_14 : Flag for 14C in organic matter [logical] + ! + ! Equation: + ! IsotopeFlux = TotalFlux × (Isotope_C / Total_C) + ! Assumes isotope ratios are conserved during respiration + !------------------------------------------------------------------------------- + + if (ciso) then + ! Track 13C respiration proportional to 13C:12C ratio in biomass + HetRespFlux_13 = HetRespFlux * HetC_13 / HetC + + if (ciso_14 .and. ciso_organic_14) then + ! Track 14C respiration (for radiocarbon dating applications) + ! Used to study carbon residence times and ocean circulation + HetRespFlux_14 = HetRespFlux * HetC_14 / HetC + end if + end if + + !=============================================================================== + ! MESOZOOPLANKTON MORTALITY + !=============================================================================== + ! Calculates density-dependent mortality using quadratic formulation. + ! Higher densities lead to disproportionately higher mortality. + ! + ! Variables: + ! hetLossFlux : Mesozooplankton mortality flux [mmolN m-3 day-1] + ! loss_het : Mortality rate constant [day-1 (mmolN m-3)-1] + ! HetN : Mesozooplankton nitrogen concentration [mmolN m-3] + ! + ! Equation: Quadratic Mortality + ! Mortality = loss_het × HetN² + ! + ! Ecological Rationale: + ! - Linear term represents background mortality (disease, senescence) + ! - Quadratic term represents density-dependent processes: + ! * Increased predation pressure at high densities + ! * Disease transmission (increases with encounter rate) + ! * Intraspecific competition for resources + ! + ! Note: Mortality products go to detritus pool (recycling pathway) + !------------------------------------------------------------------------------- + + hetLossFlux = loss_het * HetN * HetN + + if (enable_3zoo2det) then + + !=========================================================================== + ! MACROZOOPLANKTON RESPIRATION (KRILL) + !=========================================================================== + ! Calculates macrozooplankton respiration with feeding-dependent stress + ! response. Poor feeding conditions increase metabolic costs. + ! + ! Variables: + ! Zoo2RespFlux : Macrozooplankton respiration [mmolC m-3 day-1] + ! res_zoo2 : Baseline respiration rate [day-1] + ! res_zoo2_f : Feeding success modifier [-] + ! res_zoo2_a : Additional respiration factor [-] + ! recip_res_zoo22 : Combined respiration coefficient [day-1] + ! Zoo2C : Macrozooplankton carbon concentration [mmolC m-3] + ! grazingFluxcarbonzoo2: Carbon ingestion rate [mmolC m-3 day-1] + ! + ! Feeding Success Response: + ! - IF specific ingestion < 0.1 day-1: Stress response activated + ! * Increases metabolic costs (searching, maintenance) + ! * res_zoo2_f scales linearly with feeding rate + ! - ELSE: Normal feeding conditions (res_zoo2_f = 1.0) + ! + ! Total Respiration: + ! RespFlux = res_zoo2 × (1 + res_zoo2_f + res_zoo2_a) × Zoo2C + ! + ! Note: Calls external subroutine krill_resp() for detailed metabolism + !--------------------------------------------------------------------------- + + ! Call detailed krill respiration subroutine + ! Handles additional physiological processes (e.g., molting, reproduction) + call krill_resp(n, partit, mesh) + + ! Calculate feeding success modifier + ! Low feeding rates trigger stress response with elevated respiration + if ((grazingFluxcarbonzoo2 / Zoo2C) <= 0.1) then + ! Stress response: metabolic costs increase linearly with feeding deficit + ! Factor of 0.1 converts to percentage basis + res_zoo2_f = 0.1 * (grazingFluxcarbonzoo2 / Zoo2C * 100.0) + else + ! Normal feeding: no additional metabolic stress + res_zoo2_f = 1.0 + end if + + ! Calculate combined respiration coefficient + ! Includes baseline + feeding stress + additional factors + recip_res_zoo22 = res_zoo2 * (1.0 + res_zoo2_f + res_zoo2_a) + + ! Calculate total respiration flux + Zoo2RespFlux = recip_res_zoo22 * Zoo2C + + !=========================================================================== + ! MACROZOOPLANKTON MORTALITY + !=========================================================================== + ! Quadratic density-dependent mortality for macrozooplankton. + ! + ! Variables: + ! Zoo2LossFlux : Macrozooplankton mortality flux [mmolN m-3 day-1] + ! loss_zoo2 : Mortality rate constant [day-1 (mmolN m-3)-1] + ! zoo2N : Macrozooplankton nitrogen concentration [mmolN m-3] + ! + ! Equation: Quadratic Mortality + ! Mortality = loss_zoo2 × zoo2N² + !--------------------------------------------------------------------------- + + Zoo2LossFlux = loss_zoo2 * zoo2N * zoo2N + + !=========================================================================== + ! MICROZOOPLANKTON RESPIRATION AND MORTALITY + !=========================================================================== + ! Calculates microzooplankton respiration and mortality. + ! Simpler than macro/mesozooplankton (no feeding-dependent stress). + ! + ! Variables: + ! MicZooRespFlux : Microzooplankton respiration [mmolC m-3 day-1] + ! MicZooLossFlux : Microzooplankton mortality [mmolN m-3 day-1] + ! res_miczoo : Respiration rate constant [day-1] + ! loss_miczoo : Mortality rate constant [day-1 (mmolN m-3)-1] + ! q10_mic_res : Q10 temperature function for micro respiration [-] + ! MicZooC : Microzooplankton carbon concentration [mmolC m-3] + ! MicZooN : Microzooplankton nitrogen concentration [mmolN m-3] + ! + ! Respiration Equation: + ! RespFlux = res_miczoo × q10_mic_res × MicZooC + ! + ! Mortality Equation: + ! Mortality = loss_miczoo × MicZooN² + !--------------------------------------------------------------------------- + + ! Temperature-dependent respiration (Q10 formulation) + ! Smaller organisms typically have higher temperature sensitivity + MicZooRespFlux = res_miczoo * q10_mic_res * MicZooC + + ! Quadratic density-dependent mortality + MicZooLossFlux = loss_miczoo * MicZooN * MicZooN + + endif ! enable_3zoo2det + + !=============================================================================== + ! FECAL PELLET PRODUCTION + !=============================================================================== + ! Calculates fecal pellet production from mesozooplankton and macrozooplankton. + ! Fecal pellets are key to the biological carbon pump due to fast sinking. + ! + ! Fecal pellets represent: + ! - Undigested/unassimilated food material + ! - Packaged waste with high sinking velocity (100-1000 m/day) + ! - Major pathway for carbon export to deep ocean + ! - Important food source for deep-sea organisms + ! + ! Variables: + ! Zoo2fecalloss_n : Macrozooplankton fecal N [mmolN m-3 day-1] + ! Zoo2fecalloss_c : Macrozooplankton fecal C [mmolC m-3 day-1] + ! mesfecalloss_n : Mesozooplankton fecal N [mmolN m-3 day-1] + ! mesfecalloss_c : Mesozooplankton fecal C [mmolC m-3 day-1] + ! fecal_rate_n : Fecal production rate for N [fraction of ingestion] + ! fecal_rate_c : Fecal production rate for C [fraction of ingestion] + ! fecal_rate_n_mes : Mesozooplankton N fecal rate [-] + ! fecal_rate_c_mes : Mesozooplankton C fecal rate [-] + ! grazingFlux2 : Macrozooplankton N ingestion [mmolN m-3 day-1] + ! grazingFlux : Mesozooplankton N ingestion [mmolN m-3 day-1] + ! grazingFluxcarbonzoo2 : Macro C ingestion [mmolC m-3 day-1] + ! grazingFluxcarbon_mes : Meso C ingestion [mmolC m-3 day-1] + ! + ! Equation: + ! Fecal_flux = fecal_rate × ingestion_flux + ! Fecal rate typically 10-30% of ingestion (remainder is assimilated) + ! + ! Note: Fecal C:N ratio may differ from prey due to selective digestion + !------------------------------------------------------------------------------- + + if (enable_3zoo2det) then + + !--------------------------------------------------------------------------- + ! Macrozooplankton Fecal Pellet Production + !--------------------------------------------------------------------------- + ! Larger zooplankton produce larger, faster-sinking fecal pellets + + Zoo2fecalloss_n = fecal_rate_n * grazingFlux2 ! Nitrogen + Zoo2fecalloss_c = fecal_rate_c * grazingFluxcarbonzoo2 ! Carbon + + !--------------------------------------------------------------------------- + ! Mesozooplankton Fecal Pellet Production + !--------------------------------------------------------------------------- + ! Smaller fecal pellets than macrozooplankton but still fast-sinking + + mesfecalloss_n = fecal_rate_n_mes * grazingFlux ! Nitrogen + mesfecalloss_c = fecal_rate_c_mes * grazingFluxcarbon_mes ! Carbon + + endif ! enable_3zoo2det + + !=============================================================================== + ! PHYTOPLANKTON AND DETRITUS AGGREGATION + !=============================================================================== + ! Calculates particle aggregation that forms larger, faster-sinking particles. + ! Critical process for biological carbon pump and export production. + ! + ! Aggregation mechanisms: + ! - Particle collision and sticking (Brownian motion, shear, settling) + ! - Diatom mucus production enhances aggregation (nutrient stress response) + ! - Transparent exopolymer particles (TEP) glue particles together + ! + ! Variables: + ! aggregationrate : Total particle aggregation rate [mmolN m-3 day-1] + ! agg_PP : Phytoplankton-phytoplankton aggregation rate [day-1] + ! agg_PD : Phytoplankton-detritus aggregation rate [day-1] + ! PhyN, DiaN : Phytoplankton nitrogen concentrations [mmolN m-3] + ! CoccoN, PhaeoN : Coccolithophore and Phaeocystis N [mmolN m-3] + ! DetN, DetZ2N : Slow and fast-sinking detritus N [mmolN m-3] + ! qlimitFac : Nutrient limitation factor (0=replete, 1=limited) [-] + ! feLimitFac : Iron limitation factor [-] + ! quota_dia : Diatom N:C quota [mmolN mmolC-1] + ! qSiC : Diatom Si:C quota [mmolSi mmolC-1] + ! + ! Note: Aggregation products enter fast-sinking detritus pool (DetZ2N) + !------------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Diatom Mucus-Enhanced Aggregation (Optional) + !--------------------------------------------------------------------------- + ! Nutrient limitation triggers diatom mucus production, enhancing aggregation + ! and forming large, rapidly-sinking marine snow aggregates. + + if (diatom_mucus) then + + !----------------------------------------------------------------------- + ! Calculate nutrient limitation factors + !----------------------------------------------------------------------- + + ! Nitrogen limitation factor + ! Uses limiter function: returns 0 when quota is high (replete) + ! returns 1 when quota is low (limited) + qlimitFac = recom_limiter(NMinSlope, NCmin_d, quota_dia) + + ! Silicon limitation factor + ! Diatoms require silica for frustule (shell) formation + qlimitFacTmp = recom_limiter(SiMinSlope, SiCmin, qSiC) + qlimitFac = min(qlimitFac, qlimitFacTmp) ! Most limiting nutrient + + ! Iron limitation factor + ! Iron is essential for photosynthesis and often limiting in ocean + feLimitFac = Fe / (k_Fe_d + Fe) + qlimitFac = min(qlimitFac, feLimitFac) ! Most limiting of all nutrients + + ! Calculate mucus-enhanced aggregation rate + ! Aggregation increases with nutrient stress (high limitation factor) + ! Factor (1 - qlimitFac): 0 when replete, 1 when severely limited + aggregationrate = agg_PP * (1.0 - qlimitFac) * DiaN + + else + + !----------------------------------------------------------------------- + ! Simple aggregation without nutrient limitation effect + !----------------------------------------------------------------------- + aggregationrate = agg_PP * DiaN + + endif + + !--------------------------------------------------------------------------- + ! Total Aggregation Rate + !--------------------------------------------------------------------------- + ! Sum contributions from all particle types + ! Each particle type can aggregate with itself and other particles + + ! Add small phytoplankton and detritus aggregation + aggregationrate = aggregationrate + agg_PD * DetN + agg_PP * PhyN + + if (enable_3zoo2det) then + ! Add fast-sinking detritus aggregation + aggregationrate = aggregationrate + agg_PD * DetZ2N + endif + + if (enable_coccos) then + ! Add coccolithophore and Phaeocystis aggregation + ! These can form large blooms with high aggregation potential + aggregationrate = aggregationrate + agg_PP * CoccoN + agg_PP * PhaeoN + endif + + !=============================================================================== + ! MARINE CALCIFICATION + !=============================================================================== + ! Simulates the formation and dissolution of calcium carbonate (CaCO3) in + ! marine environments, primarily through phytoplankton calcification. + ! + ! This module calculates: + ! 1. Calcification rates (organism-specific or general) + ! 2. Environmental controls on calcification (temperature, CO2, nutrients) + ! 3. Loss processes (grazing, aggregation) + ! 4. Carbon isotope fractionation (13C, 14C - optional) + ! + ! Key Features: + ! - Explicit coccolithophore calcification (temperature, CO2, nutrient effects) + ! - General small phytoplankton calcification (simplified) + ! - Ocean acidification sensitivity (CO2/carbonate chemistry effects) + ! - PIC:POC ratio variability (environmental controls on calcite production) + ! - Isotope fractionation during calcification + ! + ! Calcification Scenarios: + ! A) enable_coccos = TRUE: Explicit coccolithophore model + ! - Temperature-dependent PIC:POC ratios (Krumhardt et al. 2017, 2019) + ! - CO2/carbonate chemistry effects (ocean acidification) + ! - Nitrogen limitation effects + ! B) enable_coccos = FALSE: General small phytoplankton + ! - Fixed fraction of photosynthesis goes to calcification + ! + ! Ecological/Biogeochemical Significance: + ! - Produces ballast that increases particle sinking (biological pump) + ! - Releases CO2 during calcification (carbonate counter-pump) + ! - Major component of ocean alkalinity cycle + ! - Sensitive to ocean acidification (climate change impact) + ! + ! References: + ! - Krumhardt et al. (2017, 2019) - Coccolithophore parameterization + ! - Gürses et al. (2023) - REcoM2 model description + !=============================================================================== + + !=============================================================================== + ! CALCIFICATION RATE CALCULATION + !=============================================================================== + ! Calculates the rate at which calcium carbonate (CaCO3) is formed by marine + ! organisms, with environmental modulation of the PIC:POC ratio. + ! + ! PIC = Particulate Inorganic Carbon (CaCO3) + ! POC = Particulate Organic Carbon (photosynthetic biomass) + ! + ! Variables (Coccolithophore mode): + ! calcification : CaCO3 formation rate [mmolC m-3 day-1] + ! Cphot_cocco : Coccolithophore C-specific photosynthesis [day-1] + ! CoccoC : Coccolithophore carbon concentration [mmolC m-3] + ! PICPOCtemp : Temperature modifier for PIC:POC ratio [-] + ! PICPOCCO2 : CO2/carbonate chemistry modifier for PIC:POC [-] + ! PICPOCN : Nitrogen limitation modifier for PIC:POC [-] + ! Temp(k) : Temperature at depth k [degC] + ! HCO3_watercolumn: Bicarbonate concentration [mmolC m-3] + ! CO2_watercolumn : Dissolved CO2 concentration [mmolC m-3] + ! pH_watercolumn : Water column pH [-] + ! DIN : Dissolved inorganic nitrogen [mmolN m-3] + ! k_din_c : Half-saturation for DIN effect on calcification [mmolN m-3] + ! a,b,c,d_co2_calc: CO2 effect parameters [-] + ! Cunits : Conversion factor for units [-] + ! + ! Variables (General phytoplankton mode): + ! calc_prod_ratio : Fixed calcification:photosynthesis ratio [-] + ! Cphot : Small phytoplankton photosynthesis rate [day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + !------------------------------------------------------------------------------- + + if (enable_coccos) then + + !=========================================================================== + ! COCCOLITHOPHORE-SPECIFIC CALCIFICATION + !=========================================================================== + ! Coccolithophores are marine phytoplankton that produce calcite plates + ! (coccoliths) as an external protective covering. + ! + ! Environmental Controls: + ! - Temperature: Optimum calcification at warm temperatures (>10.6degC) + ! - CO2: Ocean acidification reduces calcification efficiency + ! - Nitrogen: High nutrient availability reduces PIC:POC ratio + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Temperature Effect on PIC:POC Ratio + !--------------------------------------------------------------------------- + ! Based on Krumhardt et al. (2017, 2019) parameterization + ! Warmer temperatures favor higher calcification efficiency + + if (Temp(k) < 10.6) then + ! Linear relationship for temperatures below 10.6degC + ! Calcification efficiency increases with temperature + PICPOCtemp = 0.104d0 * Temp(k) - 0.108d0 + else + ! Maximum efficiency at temperatures ≥ 10.6degC + ! Represents optimal conditions for coccolith formation + PICPOCtemp = 1.0d0 + end if + + ! Prevent negative values (can occur at very low temperatures) + PICPOCtemp = max(tiny, PICPOCtemp) + + !--------------------------------------------------------------------------- + ! CO2/Carbonate Chemistry Effect on PIC:POC Ratio + !--------------------------------------------------------------------------- + ! Complex function representing ocean acidification impacts + ! Three components: + ! 1. HCO3- availability (substrate for calcification) + ! 2. High CO2 inhibition (ocean acidification stress) + ! 3. Low pH inhibition (direct pH stress on calcification) + + PICPOCCO2 = a_co2_calc * HCO3_watercolumn(k) * Cunits / (b_co2_calc + HCO3_watercolumn(k) * Cunits) & + - exp(-c_co2_calc * CO2_watercolumn(k) * Cunits) & + - d_co2_calc * 10.d0**(-pH_watercolumn(k)) + + ! Apply empirical constraints to CO2 effect + PICPOCCO2 = min(PICPOCCO2, 3.d0) ! Upper limit (April 2022 modification) + PICPOCCO2 = max(0.d0, PICPOCCO2) ! Lower limit (July 2022 modification) + + !--------------------------------------------------------------------------- + ! Nitrogen Limitation Effect on PIC:POC Ratio + !--------------------------------------------------------------------------- + ! Higher DIN availability reduces calcification efficiency + ! Ecological rationale: Under nutrient replete conditions, organisms + ! allocate resources preferentially to organic carbon (growth) rather + ! than calcite plates (protection) + + PICPOCN = -0.31 * (DIN / (DIN + k_din_c)) + 1.31 + PICPOCN = max(tiny, PICPOCN) ! Prevent negative values + + !--------------------------------------------------------------------------- + ! Calculate Final Coccolithophore Calcification Rate + !--------------------------------------------------------------------------- + ! Combine photosynthesis rate with all environmental modifiers + ! Base rate × Temperature effect × Nutrient effect + + calcification = 1.d0 * Cphot_cocco * CoccoC * PICPOCtemp * PICPOCN + + ! Apply CO2 limitation if ocean acidification sensitivity is enabled + if (CO2lim) then + calcification = calcification * PICPOCCO2 + end if + + else + + !=========================================================================== + ! GENERAL SMALL PHYTOPLANKTON CALCIFICATION + !=========================================================================== + ! Simplified approach: calcification as a fixed fraction of photosynthesis + ! Used when coccolithophores are not explicitly represented + ! Represents calcification by other small calcifying organisms + !--------------------------------------------------------------------------- + + calcification = calc_prod_ratio * Cphot * PhyC + + endif + + !=============================================================================== + ! CALCIFICATION LOSS PROCESSES + !=============================================================================== + ! Calculates removal of calcified material through grazing and aggregation. + ! These processes transfer CaCO3 to zooplankton or sinking particles. + ! + ! Variables: + ! calc_loss_agg : CaCO3 loss through aggregation [mmolC m-3 day-1] + ! calc_loss_gra : CaCO3 loss to primary grazer [mmolC m-3 day-1] + ! calc_loss_gra2 : CaCO3 loss to secondary grazer [mmolC m-3 day-1] + ! calc_loss_gra3 : CaCO3 loss to tertiary grazer [mmolC m-3 day-1] + ! PhyCalc : Phytoplankton calcite content [mmolC m-3] + ! aggregationrate : Particle aggregation rate [mmolN m-3 day-1] + ! recipQuota : Small phytoplankton C:N ratio [mmolC mmolN-1] + ! recipQuota_Cocco: Coccolithophore C:N ratio [mmolC mmolN-1] + ! grazingFlux_* : Grazing rates on different prey [mmolN m-3 day-1] + ! aux : Auxiliary conversion factor [mmolC mmolN-1] + ! + ! Note: CaCO3 in grazed material can dissolve in zooplankton guts or + ! provide ballast for fecal pellets (enhancing sinking) + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Aggregation Loss + !------------------------------------------------------------------------------- + ! CaCO3 is incorporated into aggregates (marine snow) that sink rapidly + ! Provides ballast effect: increases particle density and sinking velocity + + calc_loss_agg = aggregationrate * PhyCalc + + if (enable_coccos) then + + !--------------------------------------------------------------------------- + ! Coccolithophore Grazing Losses + !--------------------------------------------------------------------------- + ! Calculate CaCO3 consumed by grazers feeding on coccolithophores + ! Requires conversion from nitrogen-based grazing to carbon flux + + ! Calculate auxiliary conversion factor (CaCO3:N ratio in coccolithophores) + aux = recipQuota_Cocco / (CoccoC + tiny) * PhyCalc + + ! Primary grazer (mesozooplankton) consumption + calc_loss_gra = grazingFlux_Cocco * aux + + if (enable_3zoo2det) then + ! Secondary grazer (macrozooplankton) consumption + calc_loss_gra2 = grazingFlux_Cocco2 * aux + + ! Tertiary grazer (microzooplankton) consumption + calc_loss_gra3 = grazingFlux_Cocco3 * aux + endif + + else + + !--------------------------------------------------------------------------- + ! Small Phytoplankton Grazing Losses + !--------------------------------------------------------------------------- + ! Calculate CaCO3 consumed by grazers feeding on calcifying small phytoplankton + + ! Calculate auxiliary conversion factor (CaCO3:N ratio in small phytoplankton) + aux = recipQuota / (PhyC + tiny) * PhyCalc + + ! Primary grazer (mesozooplankton) consumption + calc_loss_gra = grazingFlux_phy * aux + + if (enable_3zoo2det) then + ! Secondary grazer (macrozooplankton) consumption + calc_loss_gra2 = grazingFlux_phy2 * aux + + ! Tertiary grazer (microzooplankton) consumption + calc_loss_gra3 = grazingFlux_phy3 * aux + endif + + endif + + !=============================================================================== + ! CARBON ISOTOPE FRACTIONATION + !=============================================================================== + ! Handles carbon-13 and carbon-14 isotope fractionation during calcification + ! and loss processes. Used for paleoclimate reconstructions and carbon cycle + ! studies. + ! + ! Isotope Fractionation: + ! - Light isotopes (12C) are preferentially incorporated during calcification + ! - Fractionation factors (alpha) quantify this discrimination + ! - Different fractionation for 13C and 14C + ! + ! Variables: + ! calcification_13 : 13C calcification rate [mmol13C m-3 day-1] + ! calcification_14 : 14C calcification rate [mmol14C m-3 day-1] + ! alpha_calc_13 : 13C fractionation factor during calcification [-] + ! alpha_calc_14 : 14C fractionation factor during calcification [-] + ! calc_loss_agg_13/14 : Isotope losses through aggregation [mmol m-3 day-1] + ! calc_loss_gra_13/14 : Isotope losses through grazing [mmol m-3 day-1] + ! PhyCalc_13/14 : Phytoplankton calcite isotope content [mmol m-3] + ! PhyC_13/14 : Phytoplankton organic carbon isotopes [mmol m-3] + ! recipQuota_13/14 : Isotope-specific C:N ratios [mmol mmol-1] + ! + ! Applications: + ! - 13C: Paleoclimate proxies, carbon source tracing + ! - 14C: Radiocarbon dating, carbon residence times + ! + ! Note: Only executed if carbon isotope tracking is enabled (ciso = TRUE) + !------------------------------------------------------------------------------- + + if (ciso) then + + !=========================================================================== + ! Carbon-13 Isotope Calculations + !=========================================================================== + ! Track 13C through calcification and loss processes + !--------------------------------------------------------------------------- + + ! Calcification with isotopic fractionation + ! Alpha factor < 1 means light isotope (12C) is preferentially incorporated + calcification_13 = calcification * alpha_calc_13 + + ! Isotopic losses through aggregation + ! Assumes no fractionation during physical aggregation process + calc_loss_agg_13 = aggregationRate * PhyCalc_13 + + ! Isotopic losses through grazing + ! Requires isotope-specific conversion factor + calc_loss_gra_13 = grazingFlux_phy * recipQuota_13 / (PhyC_13 + tiny) * PhyCalc_13 + + if (ciso_14 .and. ciso_organic_14) then + + !======================================================================= + ! Carbon-14 Isotope Calculations + !======================================================================= + ! Track radiocarbon (14C) through calcification and loss processes + ! Used for determining carbon residence times and age dating + !----------------------------------------------------------------------- + + ! Calcification with 14C fractionation + ! 14C fractionation is approximately twice that of 13C + calcification_14 = calc_prod_ratio * Cphot * PhyC_14 * alpha_calc_14 + + ! 14C losses through aggregation + calc_loss_agg_14 = aggregationRate * PhyCalc_14 + + ! 14C losses through grazing + calc_loss_gra_14 = grazingFlux_phy * recipQuota_14 / (PhyC_14 + tiny) * PhyCalc_14 + + end if ! ciso_14 .and. ciso_organic_14 + + end if ! ciso + + !=============================================================================== + ! 1. DISSOLVED INORGANIC NITROGEN (DIN) + !=============================================================================== + ! Represents the pool of bioavailable nitrogen (nitrate + ammonium) + ! + ! Variables: + ! N_assim : N assimilation rate for small phytoplankton [mmolN mmolC-1 day-1] + ! N_assim_Dia : N assimilation rate for diatoms [mmolN mmolC-1 day-1] + ! N_assim_Cocco : N assimilation rate for coccolithophore [mmolN mmolC-1 day-1] + ! N_assim_Phaeo : N assimilation rate for Phaeocystis [mmolN mmolC-1 day-1] + ! PhyC, DiaC : Intracellular carbon concentration [mmolC m-3] + ! CoccoC, PhaeoC : Intracellular carbon concentration [mmolC m-3] + ! rho_N : Remineralization rate constant [day-1] + ! arrFunc : Arrhenius temperature dependency function [-] + ! O2Func : O2 dependency of organic matter remineralization [-] + ! DON : Dissolved organic nitrogen [mmolN m-3] + ! dt_b : REcoM time step [day] + ! + ! Equation Reference: Schourup-Kristensen 2013, Eq. A2 + + sms(k,idin) = ( & + !--------------------------------------------------------------------------- + ! SINKS: Nitrogen Uptake (decreases DIN) + !--------------------------------------------------------------------------- + ! Phytoplankton assimilation of NO3- and NH4+ + - N_assim * PhyC & ! Small phytoplankton + - N_assim_Dia * DiaC & ! Diatoms + - N_assim_Cocco * CoccoC * is_coccos & ! Coccolithophores + - N_assim_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SOURCES: Remineralization (increases DIN) + !--------------------------------------------------------------------------- + ! DON remineralization releases bioavailable nitrogen + + rho_N * arrFunc * O2Func * DON & ! Temperature and O2 dependent + ) * dt_b + sms(k,idin) + + !=============================================================================== + ! 2. DISSOLVED INORGANIC CARBON (DIC) + !=============================================================================== + ! Represents the pool of inorganic carbon (CO2 + HCO3- + CO3-2) + ! + ! Variables: + ! Cphot : Small phytoplankton photosynthesis rate [day-1] + ! Cphot_Dia : Diatom photosynthesis rate [day-1] + ! Cphot_Cocco : Coccolithophore photosynthesis rate [day-1] + ! Cphot_Phaeo : Phaeocystis photosynthesis rate [day-1] + ! phyRespRate : Small phytoplankton respiration rate [day-1] + ! phyRespRate_Dia : Diatom respiration rate [day-1] + ! phyRespRate_Cocco : Coccolithophore respiration rate [day-1] + ! phyRespRate_Phaeo : Phaeocystis respiration rate [day-1] + ! rho_C1 : Temperature-dependent DOC degradation rate [day-1] + ! EOC : Extracellular organic carbon [mmolC m-3] + ! HetRespFlux : Mesozooplankton respiration flux [mmolC m-3 day-1] + ! Zoo2RespFlux : Macrozooplankton respiration flux [mmolC m-3 day-1] + ! MicZooRespFlux : Microzooplankton respiration flux [mmolC m-3 day-1] + ! calc_diss : Slow-sinking calcite dissolution rate [day-1] + ! calc_diss2 : Fast-sinking calcite dissolution rate [day-1] + ! DetCalc : Slow-sinking calcite detritus pool [mmolC m-3] + ! DetZ2Calc : Fast-sinking calcite detritus pool [mmolC m-3] + ! calc_loss_gra : Calcite loss via mesozooplankton grazing [mmolC m-3 day-1] + ! calc_loss_gra2 : Calcite loss via macrozooplankton grazing [mmolC m-3 day-1] + ! calc_loss_gra3 : Calcite loss via microzooplankton grazing [mmolC m-3 day-1] + ! calc_diss_guts : Calcite dissolution rate in zooplankton guts [-] + ! calcification : Rate of CaCO3 formation [mmolC m-3 day-1] + + sms(k,idic) = ( & + !--------------------------------------------------------------------------- + ! SINKS: Carbon Fixation (decreases DIC) + !--------------------------------------------------------------------------- + ! Photosynthetic uptake of CO2 by phytoplankton + - Cphot * PhyC & ! Small phytoplankton + - Cphot_Dia * DiaC & ! Diatoms + - Cphot_Cocco * CoccoC * is_coccos & ! Coccolithophores + - Cphot_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SINKS: Calcification (decreases DIC) + !--------------------------------------------------------------------------- + ! CaCO3 formation: Ca2+ + CO3-2 -> CaCO3 + - calcification & + !--------------------------------------------------------------------------- + ! SOURCES: Phytoplankton Respiration (increases DIC) + !--------------------------------------------------------------------------- + ! Release of CO2 through autotrophic respiration + + phyRespRate * PhyC & ! Small phytoplankton + + phyRespRate_Dia * DiaC & ! Diatoms + + phyRespRate_Cocco * CoccoC * is_coccos & ! Coccolithophores + + phyRespRate_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SOURCES: DOC Remineralization (increases DIC) + !--------------------------------------------------------------------------- + ! Microbial degradation of dissolved organic carbon + + rho_C1 * arrFunc * O2Func * EOC & ! Temperature and O2 dependent + + rho_C1t * DOCt * is_riverinput & ! --> Remineralization of terrestrial DOC ! R2OMIP + !--------------------------------------------------------------------------- + ! SOURCES: Zooplankton Respiration (increases DIC) + !--------------------------------------------------------------------------- + ! Release of CO2 through heterotrophic respiration + + HetRespFlux & ! Mesozooplankton + + Zoo2RespFlux * is_3zoo2det & ! Macrozooplankton + + MicZooRespFlux * is_3zoo2det & ! Microzooplankton + !--------------------------------------------------------------------------- + ! SOURCES: Calcite Dissolution (increases DIC) + !--------------------------------------------------------------------------- + ! Reaction: CaCO3 + CO2 + H2O -> Ca2+ + 2HCO3- + + calc_diss * DetCalc & ! Slow-sinking calcite + + calc_loss_gra * calc_diss_guts & ! Mesozooplankton gut + + calc_loss_gra2 * calc_diss_guts * is_3zoo2det & ! Macrozooplankton gut + + calc_loss_gra3 * calc_diss_guts * is_3zoo2det & ! Microzooplankton gut + + calc_diss2 * DetZ2Calc * is_3zoo2det & ! Fast-sinking calcite + ) * dt_b + sms(k,idic) ! if((Latd(1)<-45.0) .and. ((state(k,idic)+sms(k,idic))>2500)) then ! !co2flux(1)=0.0 @@ -1135,1048 +4041,3515 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! stop ! endif -!< *** Alk *** -!< *********** - -!< Alkalinity (Assumes that N:P follows a constant Redfield ratio -!< N_assimC: 1.0625 = 1/16 + 1 - - sms(k,ialk) = ( & - + 1.0625 * N_assim * PhyC & - + 1.0625 * N_assim_Dia * DiaC & -#if defined (__coccos) - + 1.0625 * N_assim_Cocco * CoccoC & -#endif - - 1.0625 * rho_N * arrFunc * O2Func * DON & ! O2remin - + 2.d0 * calc_diss * DetCalc & - + 2.d0 * calc_loss_gra * calc_diss_guts & -#if defined (__3Zoo2Det) - + 2.d0 * calc_loss_gra2 * calc_diss_guts & - + 2.d0 * calc_loss_gra3 * calc_diss_guts & ! 3Zoo - + 2.d0 * calc_diss2 * DetZ2Calc & -#endif - - 2.d0 * calcification & - ) * dt_b + sms(k,ialk) -!< *** Small Phytoplankton *** -!< *************************** - -!____________________________________________________________ -!< Small phytoplankton N - -!< lossN: Phytoplankton loss of organic N compounds [day^-1] - - sms(k,iphyn) = ( & - + N_assim * PhyC & ! --> N assimilation - - lossN * limitFacN * PhyN & ! --> DON excretion - - aggregationRate * PhyN & ! --> Aggregation loss - - grazingFlux_phy & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_phy2 & - - grazingFlux_phy3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphyn) -!____________________________________________________________ -!< Small phytoplankton C - -!< lossC: Phytoplankton loss of carbon [day^-1] -!< When N : C ratio becomes too high, excretion of DOC is downregulated -!< by the limiter function limitFacN -!< aggregationRate transfers C to the detritus pool - - sms(k,iphyc) = ( & - + Cphot * PhyC & ! --> Photosynthesis ---->/ - - lossC * limitFacN * PhyC & ! --> Excretion of DOC / Net photosynthesis - - phyRespRate * PhyC & ! --> Respiration ----->/ - - aggregationRate * PhyC & ! --> Aggregation loss - - grazingFlux_phy * recipQuota & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_phy2 * recipQuota & - - grazingFlux_phy3 * recipQuota & ! 3Zoo -#endif - ) * dt_b + sms(k,iphyc) -!____________________________________________________________ -! Phytoplankton ChlA - -!< Chl2N: Conversion factor from mmolN to mgChla -!< Chl2N = PhyChl/PhyN - - sms(k,ipchl) = ( & - + chlSynth * PhyC & ! --> Chl-a synthesis - - KOchl * PhyChl & ! --> Degradation loss - - aggregationRate * PhyChl & ! --> Aggregation loss - - grazingFlux_phy * Chl2N & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_phy2 * Chl2N & - - grazingFlux_phy3 * Chl2N & ! 3Zoo -#endif - ) * dt_b + sms(k,ipchl) - -!< *** Slow-sinking Detritus *** -!< ***************************** - -!____________________________________________________________ -! Detritus N - if (Grazing_detritus) then -#if defined (__3Zoo2Det) - sms(k,idetn) = ( & - + grazingFlux_phy3 & - - grazingFlux_phy3 * grazEff3 & - + grazingFlux_dia3 & - - grazingFlux_dia3 * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 & - - grazingFlux_Cocco3 * grazEff3 & - + aggregationRate * CoccoN & -#endif - - grazingFlux_Det * grazEff & - - grazingFlux_Det2 * grazEff2 & ! --> okay, grazing of second zoo on first detritus - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + miczooLossFlux & - - reminN * arrFunc * O2Func * DetN & ! O2remin - ) * dt_b + sms(k,idetn) -#else - sms(k,idetn) = ( & - + grazingFlux_phy & - - grazingFlux_phy * grazEff & - + grazingFlux_dia & - - grazingFlux_dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco & - - grazingFlux_Cocco * grazEff & - + aggregationRate * CoccoN & -#endif - - grazingFlux_Det * grazEff & ! Sloppy feeding is thought because of grazing flux multiplied with grazeff - - grazingFlux_Det2 * grazEff2 & !!!!!!!!!!CHECK - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + hetLossFlux & - - reminN * arrFunc * O2Func * DetN & ! O2remin - ) * dt_b + sms(k,idetn) -#endif - else -#if defined (__3Zoo2Det) - sms(k,idetn) = ( & - + grazingFlux_phy3 & - + grazingFlux_dia3 & -#if defined (__coccos) - + grazingFlux_Cocco3 & - + aggregationRate * CoccoN & -#endif - - grazingFlux * grazEff3 & - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + miczooLossFlux & - - reminN * arrFunc * O2Func * DetN & ! O2remin - ) * dt_b + sms(k,idetn) -#else - sms(k,idetn) = ( & - + grazingFlux_phy & - + grazingFlux_dia & -#if defined (__coccos) - + grazingFlux_Cocco & - + aggregationRate * CoccoN & -#endif - - grazingFlux * grazEff & - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + hetLossFlux & - - reminN * arrFunc * O2Func * DetN & ! O2remin - ) * dt_b + sms(k,idetn) -#endif - end if - -!____________________________________________________________ -! Detritus C - if (Grazing_detritus) then -#if defined (__3Zoo2Det) - sms(k,idetc) = ( & - + grazingFlux_phy3 * recipQuota & - - grazingFlux_phy3 * recipQuota * grazEff3 & - + grazingFlux_Dia3 * recipQuota_Dia & - - grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 * recipQuota_Cocco & - - grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & - + aggregationRate * CoccoC & -#endif - - grazingFlux_Det * recipDet * grazEff & - - grazingFlux_Det2 * recipDet2 * grazEff2 & - + aggregationRate * PhyC & - + aggregationRate * DiaC & - + miczooLossFlux * recipQZoo3 & - - reminC * arrFunc * O2Func * DetC & ! O2remin - ) * dt_b + sms(k,idetc) -#else - sms(k,idetc) = ( & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + aggregationRate * CoccoC & -#endif - - grazingFlux_Det * recipDet * grazEff & - - grazingFlux_Det2 * recipDet2 * grazEff & !!!!!! CHECK - + aggregationRate * phyC & - + aggregationRate * DiaC & - + hetLossFlux * recipQZoo & - - reminC * arrFunc * O2Func * DetC & ! O2remin - ) * dt_b + sms(k,idetc) -#endif - else -#if defined (__3Zoo2Det) - sms(k,idetc) = ( & - + grazingFlux_phy3 * recipQuota & - - grazingFlux_phy3 * recipQuota * grazEff3 & - + grazingFlux_Dia3 * recipQuota_Dia & - - grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 * recipQuota_Cocco & - - grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & - + aggregationRate * CoccoC & -#endif - + aggregationRate * PhyC & - + aggregationRate * DiaC & - + miczooLossFlux * recipQZoo3 & - - reminC * arrFunc * O2Func * DetC & ! O2remin - ) * dt_b + sms(k,idetc) -#else - sms(k,idetc) = ( & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + aggregationRate * CoccoC & -#endif - + aggregationRate * phyC & - + aggregationRate * DiaC & - + hetLossFlux * recipQZoo & - - reminC * arrFunc * O2Func * DetC & ! O2remin - ) * dt_b + sms(k,idetc) -#endif - end if - -!< *** Mesozooplankton *** -!< *********************** - -!____________________________________________________________ -!< Heterotrophic N - sms(k,ihetn) = ( & - + grazingFlux * grazEff & ! --> Grazing on phytoplankton -> okay, because of recipQuota -#if defined (__3Zoo2Det) - - grazingFlux_het2 & - - Mesfecalloss_n & ! 3Zoo -#endif - - hetLossFlux & ! --> Mortality - - lossN_z * HetN & ! --> Excretion of DON - ) * dt_b + sms(k,ihetn) -!____________________________________________________________ -!< Heterotrophic C + !=============================================================================== + ! 3. ALKALINITY (Alk) + !=============================================================================== + ! Total alkalinity affects ocean pH and CO2 uptake capacity + ! Assumes constant Redfield N:P ratio + ! + ! Key coefficient: 1.0625 = (1/16) + 1 + ! - Represents the change in alkalinity per mole of nitrogen + ! - Includes both nitrate reduction (+ charge) and phosphate uptake + + sms(k,ialk) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Nutrient Uptake (increases alkalinity) + !--------------------------------------------------------------------------- + ! Phytoplankton uptake of NO3- increases alkalinity + + 1.0625 * N_assim * PhyC & ! Small phytoplankton + + 1.0625 * N_assim_Dia * DiaC & ! Diatoms + + 1.0625 * N_assim_Cocco * CoccoC * is_coccos & ! Coccolithophores + + 1.0625 * N_assim_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + + !--------------------------------------------------------------------------- + ! SINKS: Remineralization (decreases alkalinity) + !--------------------------------------------------------------------------- + ! DON remineralization releases H+ and decreases alkalinity + - 1.0625 * rho_N * arrFunc * O2Func * DON & + !--------------------------------------------------------------------------- + ! SOURCES: Calcite Dissolution (increases alkalinity) + !--------------------------------------------------------------------------- + ! Reaction: CaCO3 + CO2 + H2O -> Ca2+ + 2HCO3- + ! Increases alkalinity by 2 equivalents per mole CaCO3 + + 2.d0 * calc_diss * DetCalc & ! Slow-sinking calcite + + 2.d0 * calc_loss_gra * calc_diss_guts & ! Mesozooplankton gut + + 2.d0 * calc_loss_gra2 * calc_diss_guts * is_3zoo2det & ! Macrozooplankton gut + + 2.d0 * calc_loss_gra3 * calc_diss_guts * is_3zoo2det & ! Microzooplankton gut + + 2.d0 * calc_diss2 * DetZ2Calc * is_3zoo2det & ! Fast-sinking calcite + + !--------------------------------------------------------------------------- + ! SINKS: Calcification (decreases alkalinity) + !--------------------------------------------------------------------------- + ! CaCO3 formation removes 2 equivalents of alkalinity + - 2.d0 * calcification & + ) * dt_b + sms(k,ialk) + + !=============================================================================== + ! SMALL PHYTOPLANKTON NITROGEN (PhyN) + !=============================================================================== + ! Tracks the nitrogen content of small phytoplankton + ! + ! Variables: + ! N_assim : N assimilation rate [day-1] + ! lossN : N loss rate [day-1] + ! limitFacN : Limiter function for N:C ratio regulation [-] + ! aggregationRate : Aggregation to detritus [day-1] + ! grazingFlux_phy : Mesozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_phy2 : Macrozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_phy3 : Microzooplankton grazing [mmolN m-3 day-1] + + sms(k,iphyn) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Nitrogen Assimilation + !--------------------------------------------------------------------------- + + N_assim * PhyC & + !--------------------------------------------------------------------------- + ! SINKS: Losses + !--------------------------------------------------------------------------- + - lossN * limitFacN * PhyN & ! DON excretion (N:C regulated) + - aggregationRate * PhyN & ! Aggregation to detritus + - grazingFlux_phy & ! Mesozooplankton + - grazingFlux_phy2 * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phy3 * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphyn) + + !=============================================================================== + ! 5. SMALL PHYTOPLANKTON CARBON (PhyC) + !=============================================================================== + ! Tracks the carbon content of small phytoplankton. + ! + ! Variables: + ! Cphot : Gross photosynthesis rate [day-1] + ! phyRespRate : Autotrophic respiration rate [day-1] + ! lossC : C loss rate [day-1] + ! recipQuota : Reciprocal of N:C quota (for N->C conversion) [-] + ! + ! Note: DOC excretion is downregulated by limitFacN when N:C ratio is too high + + sms(k,iphyc) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Net Photosynthesis + !--------------------------------------------------------------------------- + + Cphot * PhyC & ! Gross photosynthesis + - phyRespRate * PhyC & ! Autotrophic respiration + !--------------------------------------------------------------------------- + ! SINKS: Losses + !--------------------------------------------------------------------------- + - lossC * limitFacN * PhyC & ! DOC excretion (regulated) + - aggregationRate * PhyC & ! Aggregation to detritus + - grazingFlux_phy * recipQuota & ! Mesozooplankton (N->C) + - grazingFlux_phy2 * recipQuota * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phy3 * recipQuota * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphyc) + + !=============================================================================== + ! 6. PHYTOPLANKTON CHLOROPHYLL-A (PhyChl) + !=============================================================================== + ! Tracks chlorophyll-a content for light harvesting and photoacclimation + ! + ! Variables: + ! chlSynth : Chlorophyll synthesis rate [mgChl mmolC-1 day-1] + ! KOchl : Chlorophyll degradation rate constant [day-1] + ! Chl2N : Chl:N ratio = PhyChl/PhyN [mgChl mmolN-1] + + sms(k,ipchl) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Chlorophyll Synthesis + !--------------------------------------------------------------------------- + + chlSynth * PhyC & ! Photoacclimation + !--------------------------------------------------------------------------- + ! SINKS: Degradation and Losses + !--------------------------------------------------------------------------- + + - KOchl * PhyChl & ! Natural degradation + - aggregationRate * PhyChl & ! Aggregation to detritus + - grazingFlux_phy * Chl2N & ! Mesozooplankton + - grazingFlux_phy2 * Chl2N * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phy3 * Chl2N * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,ipchl) + + !=============================================================================== + ! 7. DETRITUS NITROGEN (DetN) + !=============================================================================== + ! Tracks nitrogen content in slow-sinking organic particles. + ! + ! Key Concepts: + ! - Sloppy Feeding: Not all grazed material is assimilated + ! Net detritus = Total grazing × (1 - grazing efficiency) + ! - Four Configurations: Based on Grazing_detritus and enable_3zoo2det flags + ! + ! Variables: + ! grazEff, grazEff2, grazEff3 : Grazing efficiency (assimilation) [-] + ! aggregationRate : Aggregation rate [day-1] + ! hetLossFlux, miczooLossFlux : Zooplankton mortality [mmolN m-3 day-1] + ! reminN : Remineralization rate [day-1] + ! arrFunc : Arrhenius temperature function [-] + ! O2Func : Oxygen limitation function [-] + ! grazingFlux_phy3, grazingFlux_dia3 : Grazing by microzooplankton [mmolN m-3 day-1] + ! grazingFlux_phy, grazingFlux_dia : Grazing by mesozooplankton [mmolN m-3 day-1] + ! DetN : Detrital nitrogen concentration [mmolN m-3] + ! dt_b : Time step [day] + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Configuration 1: WITH Detritus Grazing + 3 Zooplankton Types + !------------------------------------------------------------------------------- + if (Grazing_detritus) then - sms(k,ihetc) = ( & - + grazingFlux_phy * recipQuota * grazEff & ! --> Grazing on small phytoplankton - + grazingFlux_Dia * recipQuota_Dia * grazEff & ! --> Grazing on diatom -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco * grazEff & -#endif -#if defined (__3Zoo2Det) - + grazingFlux_miczoo * recipQZoo3 * grazEff & ! 3Zoo - + grazingFlux_DetZ2 * recipDet2 * grazEff & - - grazingFlux_het2 * recipQZoo & - - Mesfecalloss_c & ! 3Zoo -#endif - + grazingFlux_Det * recipDet * grazEff & ! --> Grazing on detritus - - hetLossFlux * recipQZoo & ! --> Mortality loss - - lossC_z * HetC & ! --> Excretion loss - - hetRespFlux & ! --> REspiration loss - ) * dt_b + sms(k,ihetc) + if (enable_3zoo2det) then + sms(k,idetn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Microzooplankton + !----------------------------------------------------------------------- + ! Net flux = Total grazing - Assimilated portion + + grazingFlux_phy3 - grazingFlux_phy3 * grazEff3 & ! Small phytoplankton + + grazingFlux_dia3 - grazingFlux_dia3 * grazEff3 & ! Diatoms + + (grazingFlux_Cocco3 - grazingFlux_Cocco3 * grazEff3) * is_coccos & ! Coccolithophores + + (grazingFlux_Phaeo3 - grazingFlux_Phaeo3 * grazEff3) * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation + !----------------------------------------------------------------------- + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + aggregationRate * CoccoN * is_coccos & + + aggregationRate * PhaeoN * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + miczooLossFlux & + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption + !----------------------------------------------------------------------- + - grazingFlux_Det * grazEff & ! Mesozooplankton + - grazingFlux_Det2 * grazEff2 & ! Macrozooplankton + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetN & ! Bacterial decomposition + ) * dt_b + sms(k,idetn) + !------------------------------------------------------------------------------- + ! Configuration 2: WITH Detritus Grazing + 2 Zooplankton Types (Standard) + !------------------------------------------------------------------------------- + else + sms(k,idetn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy - grazingFlux_phy * grazEff & ! Small phytoplankton + + grazingFlux_dia - grazingFlux_dia * grazEff & ! Diatoms + + (grazingFlux_Cocco - grazingFlux_Cocco * grazEff) * is_coccos & ! Coccolithophores + + (grazingFlux_Phaeo - grazingFlux_Phaeo * grazEff) * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation + !----------------------------------------------------------------------- + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + aggregationRate * CoccoN * is_coccos & + + aggregationRate * PhaeoN * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + hetLossFlux & + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption + !----------------------------------------------------------------------- + - grazingFlux_Det * grazEff & ! Mesozooplankton + - grazingFlux_Det2 * grazEff2 & ! Macrozooplankton + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetN & + ) * dt_b + sms(k,idetn) + endif + !------------------------------------------------------------------------------- + ! Configuration 3: WITHOUT Detritus Grazing + 3 Zooplankton Types + !------------------------------------------------------------------------------- else - sms(k,ihetc) = ( & - + grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco * grazEff & -#endif -#if defined (__3Zoo2Det) - + grazingFlux_miczoo * recipQZoo3 * grazEff & ! 3Zoo - - grazingFlux_het2 * recipQZoo & - - Mesfecalloss_c & ! 3Zoo -#endif - - hetLossFlux * recipQZoo & - - lossC_z * HetC & - - hetRespFlux & - ) * dt_b + sms(k,ihetc) - endif - -!< *** Macrozooplankton *** -!< ************************ - -#if defined (__3Zoo2Det) -!____________________________________________________________ -!< Second Zooplankton N - sms(k,izoo2n) = ( & - + grazingFlux2 * grazEff2 & - - Zoo2LossFlux & - - lossN_z2 * Zoo2N & - - Zoo2fecalloss_n & - ) * dt_b + sms(k,izoo2n) - -!____________________________________________________________ -!< Second Zooplankton C - if (Grazing_detritus) then - - sms(k,izoo2c) = ( & - + grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo - + grazingFlux_Det2 * recipDet * grazEff2 & - + grazingFlux_DetZ22 * recipDet2 * grazEff2 & - - zoo2LossFlux * recipQZoo2 & - - lossC_z2 * Zoo2C & - - Zoo2RespFlux & - - Zoo2fecalloss_c & - ) * dt_b + sms(k,izoo2c) - else - sms(k,izoo2c) = ( & - + grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo - - zoo2LossFlux * recipQZoo2 & - - lossC_z2 * Zoo2C & - - Zoo2RespFlux & - - Zoo2fecalloss_c & - ) * dt_b + sms(k,izoo2c) - end if - -!< *** Microzooplankton *** -!< ************************ - -!____________________________________________________________ -!< Third Zooplankton N - sms(k,imiczoon) = ( & - + grazingFlux3 * grazEff3 & - - grazingFlux_miczoo & - - grazingFlux_miczoo2 & - - MicZooLossFlux & - - lossN_z3 * MicZooN & - ) * dt_b + sms(k,imiczoon) - -!____________________________________________________________ -!< Third Zooplankton C - sms(k,imiczooc) = ( & - + grazingFlux_phy3 * recipQuota * grazEff3 & - + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & -#endif - - MicZooLossFlux * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 & - - lossC_z3 * MicZooC & - - MicZooRespFlux & - ) * dt_b + sms(k,imiczooc) - -!< *** Fast-sinking Detritus *** -!< ***************************** - -!____________________________________________________________ -!< Second Zooplankton Detritus N - if (Grazing_detritus) then - sms(k,idetz2n) = ( & - + grazingFlux_phy2 & - - grazingFlux_phy2 * grazEff2 & - + grazingFlux_dia2 & - - grazingFlux_dia2 * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco & - - grazingFlux_Cocco * grazEff & - + grazingFlux_Cocco2 & - - grazingFlux_Cocco2 * grazEff2 & -#endif - + grazingFlux_het2 & - - grazingFlux_het2 * grazEff2 & - + grazingFlux_miczoo2 & - - grazingFlux_miczoo2 * grazEff2 & - + grazingFlux_phy & - - grazingFlux_phy * grazEff & - + grazingFlux_dia & - - grazingFlux_dia * grazEff & - + grazingFlux_miczoo & - - grazingFlux_miczoo * grazEff & - - grazingFlux_DetZ2 * grazEff & - - grazingFlux_DetZ22 * grazEff2 & - + Zoo2LossFlux & - + hetLossFlux & - + Zoo2fecalloss_n & - + Mesfecalloss_n & - - reminN * arrFunc * O2Func * DetZ2N & ! O2remin - ) * dt_b + sms(k,idetz2n) - else - sms(k,idetz2n) = ( & - + grazingFlux_phy2 & - + grazingFlux_dia2 & -#if defined (__coccos) - + grazingFlux_Cocco & - + grazingFlux_Cocco2 & -#endif - + grazingFlux_het2 & - + grazingFlux_miczoo2 & - - grazingFlux2 * grazEff2 & - + grazingFlux_phy & - + grazingFlux_dia & - + grazingFlux_miczoo & - - grazingFlux * grazEff & - + Zoo2LossFlux & - + hetLossFlux & - + Zoo2fecalloss_n & - + Mesfecalloss_n & - - reminN * arrFunc * O2Func * DetZ2N & ! O2remin - ) * dt_b + sms(k,idetz2n) - end if - -!____________________________________________________________ -!< Second Zooplankton Detritus C - if (Grazing_detritus) then - sms(k,idetz2c) = ( & - + grazingFlux_phy2 * recipQuota & - - grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia & - - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + grazingFlux_Cocco2 * recipQuota_Cocco & - - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo & - - grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2 * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & - + grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 * grazEff & - - grazingFlux_DetZ2 * recipDet2 * grazEff & - - grazingFlux_DetZ22 * recipDet2 * grazEff2 & - + Zoo2LossFlux * recipQZoo2 & - + hetLossFlux * recipQZoo & - + Zoo2fecalloss_c & - + Mesfecalloss_c & - - reminC * arrFunc * O2Func * DetZ2C & ! O2remin - ) * dt_b + sms(k,idetz2c) - else - sms(k,idetz2c) = ( & - + grazingFlux_phy2 * recipQuota & - - grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia & - - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + grazingFlux_Cocco2 * recipQuota_Cocco & - - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo & - - grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2 * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & - + grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 * grazEff & - + Zoo2LossFlux * recipQZoo2 & - + hetLossFlux * recipQZoo & - + Zoo2fecalloss_c & - + Mesfecalloss_c & - - reminC * arrFunc * O2Func * DetZ2C & ! O2remin - ) * dt_b + sms(k,idetz2c) - end if - -!____________________________________________________________ -!< Second Zooplankton Detritus Si - sms(k,idetz2si) = ( & - + grazingFlux_dia2 * qSiN & ! --> qSin convert N to Si - + grazingFlux_dia * qSiN & - - reminSiT * DetZ2Si & - ) * dt_b + sms(k,idetz2si) - -!____________________________________________________________ -!< Second Zooplankton Detritus calcite - sms(k,idetz2calc) = ( & - + calc_loss_gra2 & - - calc_loss_gra2 * calc_diss_guts & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss2 * DetZ2Calc & - ) * dt_b + sms(k,idetz2calc) -#endif - -!< *** DOM *** -!< *********** - -!____________________________________________________________ -!< DON (Extracellular organic N) - - sms(k,idon) = ( & - + lossN * limitFacN * phyN & - + lossN_d * limitFacN_Dia * DiaN & -#if defined (__coccos) - + lossN_c * limitFacN_Cocco * CoccoN & -#endif - + reminN * arrFunc * O2Func * DetN & - + lossN_z * HetN & -#if defined (__3Zoo2Det) - + reminN * arrFunc * O2Func * DetZ2N & - + lossN_z2 * Zoo2N & - + lossN_z3 * MicZooN & ! 3Zoo -#endif - - rho_N * arrFunc * O2Func * DON & ! O2remin - ) * dt_b + sms(k,idon) - -!____________________________________________________________ -!< EOC - - sms(k,idoc) = ( & - + lossC * limitFacN * phyC & - + lossC_d * limitFacN_dia * DiaC & -#if defined (__coccos) - + lossC_c * limitFacN_cocco * CoccoC & -#endif - + reminC * arrFunc * O2Func * DetC & - + lossC_z * HetC & -#if defined (__3Zoo2Det) - + reminC * arrFunc * O2Func * DetZ2C & - + lossC_z2 * Zoo2C & - + lossC_z3 * MicZooC & ! 3Zoo -#endif - - rho_c1 * arrFunc * O2Func * EOC & ! O2remin - ) * dt_b + sms(k,idoc) - -!< *** Diatoms *** -!< *************** - -!____________________________________________________________ -!< Diatom N - -!< lossN: Diatom loss of organic N compounds [day^-1] -!< When N : C ratio becomes too high, excretion of DON is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers N to the detritus pool - - sms(k,idian) = ( & - + N_assim_dia * DiaC & ! --> N assimilation - - lossN_d * limitFacN_dia * DiaN & ! --> DON excretion - - aggregationRate * DiaN & ! --> Aggregation loss - - grazingFlux_Dia & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_Dia2 & - - grazingFlux_Dia3 & ! 3Zoo -#endif - ) * dt_b + sms(k,idian) - -!____________________________________________________________ -!< Diatom C - -!< lossC_d: Diatom loss of carbon [day^-1] -!< When N : C ratio becomes too high, excretion of DOC is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers C to the detritus pool - - sms(k,idiac) = ( & - + Cphot_dia * DiaC & ! -- Photosynthesis ---->/ - - lossC_d * limitFacN_dia * DiaC & ! -- Excretion of DOC --/ Net Photosynthesis - - phyRespRate_dia * DiaC & ! -- Respiration ----->/ - - aggregationRate * DiaC & - - grazingFlux_dia * recipQuota_dia & -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * recipQuota_dia & - - grazingFlux_dia3 * recipQuota_dia & ! 3Zoo -#endif - ) * dt_b + sms(k,idiac) - -!____________________________________________________________ -!< Diatom Chl - - sms(k,idchl) = ( & - + chlSynth_dia * DiaC & ! --> Chl a synthesis - - KOchl_dia * DiaChl & ! --> Degradation loss - - aggregationRate * DiaChl & ! --> Aggregation loss - - grazingFlux_dia * Chl2N_dia & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * Chl2N_dia & - - grazingFlux_dia3 * Chl2N_dia & ! 3Zoo -#endif - ) * dt_b + sms(k,idchl) - -!____________________________________________________________ -!< Diatom Si - -!< lossN_d: Diatom loss of organic nitrogen compunds [day^-1] -!< When N : C ratio becomes too high, excretion is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers Si to the detritus pool - - sms(k,idiasi) = ( & - + Si_assim * DiaC & ! -- Diatom silicon assimilation - - lossN_d * limitFacN_dia * DiaSi & ! -- Excretion to detritus - - aggregationRate * DiaSi & ! -- Aggregation loss - - grazingFlux_dia * qSiN & ! -- Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * qSiN & - - grazingFlux_dia3 * qSiN & ! 3Zoo -#endif - ) * dt_b + sms(k,idiasi) - -!< *** Coccolithophore *** -!< *********************** - -#if defined (__coccos) -!____________________________________________________________ -!< Coccolithophore N - sms(k,icocn) = ( & - + N_assim_cocco * CoccoC & - - lossN_c * limitFacN_cocco * CoccoN & - - aggregationRate * CoccoN & - - grazingFlux_Cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 & - - grazingFlux_Cocco3 & ! 3Zoo -#endif - ) * dt_b + sms(k,icocn) - -!____________________________________________________________ -!< Coccolithophore C - - sms(k,icocc) = ( & - + Cphot_cocco * CoccoC & - - lossC_c * limitFacN_cocco * CoccoC & - - phyRespRate_cocco * CoccoC & - - aggregationRate * CoccoC & - - grazingFlux_cocco * recipQuota_cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 * recipQuota_cocco & - - grazingFlux_Cocco3 * recipQuota_cocco & ! 3Zoo -#endif - ) * dt_b + sms(k,icocc) - - if(sms(k,icocc)>100) then - print*,'ERROR: strange CoccoC !' - print*,'k= ', k - print*,'dt= ', dt - print*,'dt_b= ', dt_b - print*,'state(k,icocc): ', state(k,icocc) - print*,'sms CoccoC: ', CoccoC - print*,'sms CoccoN: ', CoccoN - print*,'sms Cphot cocco: ', Cphot_cocco*CoccoC - print*,'sms lossC_c: ', lossC_c - print*,'sms limitFacN_cocco: ', limitFacN_cocco - print*,'sms phyRespRate_cocco: ', phyRespRate_cocco - print*,'sms grazingFlux_cocco: ', grazingFlux_cocco - print*,'sms grazingFlux_cocco2: ', grazingFlux_Cocco2 - print*,'sms grazingFlux_cocco3: ', grazingFlux_Cocco3 - print*,'sms recipQuota_cocco: ', recipQuota_cocco - - print*,'sms recipQuota_cocco: ', recipQuota_cocco - call par_ex(partit%MPI_COMM_FESOM, partit%mype) - stop - endif - -!____________________________________________________________ -!< Coccolithophore Chl - - sms(k,icchl) = ( & - + ChlSynth_cocco * CoccoC & - - KOchl_cocco * CoccoChl & - - aggregationRate * CoccoChl & - - grazingFlux_cocco * Chl2N_cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 * Chl2N_cocco & - - grazingFlux_Cocco3 * Chl2N_cocco & ! 3Zoo -#endif - ) * dt_b + sms(k,icchl) -#endif - -!< *** Silicate *** -!< **************** - -!____________________________________________________________ -!< Detritus Si -#if defined (__3Zoo2Det) - sms(k,idetsi) = ( & - + aggregationRate * DiaSi & - + lossN_d * limitFacN_dia * DiaSi & - + grazingFlux_dia3 * qSiN & - - reminSiT * DetSi & - ) * dt_b + sms(k,idetsi) -#else - sms(k,idetsi) = ( & - + aggregationRate * DiaSi & - + lossN_d * limitFacN_dia * DiaSi & - + grazingFlux_dia * qSiN & - - reminSiT * DetSi & - ) * dt_b + sms(k,idetsi) -#endif -!____________________________________________________________ -!< DSi, Silicate - -!< DiaC: Intracellular carbon concentration in diatoms [mmolC m-3] -!< DetSi: Detritus silicon concentration [mmolSi m-3] -!< Si_assim: Si assimilation rate for diatoms [mmolSi mmolC-1 day-1] -!< reminSiT: Remineralization rate of silicon, temperature dependency [day-1] -!< dt_b: REcoM time step [day] - -!! Schourup 2013 Eq. A3 - - sms(k,isi) = ( & - - Si_assim * DiaC & ! --> Si assimilation of diatoms - + reminSiT * DetSi & ! --> Remineralization of detritus, temperature dependent -#if defined (__3Zoo2Det) - + reminSiT * DetZ2Si & -#endif - ) * dt_b + sms(k,isi) -!< *** Iron *** -!< ************ - -!____________________________________________________________ -!< Fe - -!< Fe2N: Intracellular Fe : N ratio [μmol Fe mmol N^-1] Fe2N = Fe2C * 6.625 -!< PhyC: Intracellular carbon concentration in nanophytoplankton [mmolCm^-3] -!< Cphot: C-specific actual rate of photosynthesis for nanopyhtoplankton [day^-1] -!< DiaC: Intracellular carbon concentration in diatoms [mmol C m^-3 ] -!< Cphot_dia: C-specific actual rate of photosynthesis for diatom [day^-1] -!< phyRespRate: Nanopyhtoplankton respiration rate [day^-1] -!< phyRespRate_dia: Diatom respiration rate [day^-1] -!< lossC: Nanopyhtoplankton excretion of organic C [day^-1] -!< limitFacN: limiting factor -!< lossC_d: Diatom excretion of organic C [day^-1] -!< limitFacN_dia: limiting factor -!< detC: Detritus carbon concentration [mmol C m^-3] -!< reminC: Temperature dependent remineralisation rate of detritus [day^-1] -!< arrFunc: Arrhenius function -!< hetC: Zooplankton carbon concentration [mmol C m^-3 ] -!< lossC_z: Zooplankton excretion of organic C [day^-1 ] -!< hetRespFlux: Zooplankton respiration rate [day^-1] -!< kScavFe: Scavenging rate of iron [m3 mmol C^-1 day^-1] - - sms(k,ife) = ( Fe2N * ( & - - N_assim * PhyC & ! --> N assimilation Nanophytoplankton, [mmol N/(mmol C * day)] C specific N utilization rate - - N_assim_dia * DiaC & ! --> N assimilation Diatom -#if defined (__coccos) - - N_assim_cocco * CoccoC & - + lossN_c * limitFacN_cocco * CoccoN & -#endif - + lossN * limitFacN * PhyN & ! --> Excretion from small pythoplankton - + lossN_d * limitFacN_dia * DiaN & ! --> Excretion from diatom - + reminN * arrFunc * O2Func * DetN & ! --> Remineralization of detritus ! NEW O2remin - + lossN_z * HetN & ! --> Excretion from zooplankton -#if defined (__3Zoo2Det) - + reminN * arrFunc * O2Func * DetZ2N & ! O2remin - + lossN_z2 * Zoo2N & - + lossN_z3 * MicZooN & ! 3Zoo -#endif - ) & - - kScavFe * DetC * FreeFe & -#if defined (__3Zoo2Det) - - kScavFe * DetZ2C * FreeFe & -#endif - ) * dt_b + sms(k,ife) - -!< *** Calcification *** -!< ********************* - -!____________________________________________________________ -!< Small phytoplankton calcite - -#if defined (__coccos) - sms(k,iphycal) = ( & - + calcification & ! --> Calcification - - lossC_c * limitFacN_cocco * PhyCalc & ! --> Excretion loss - - phyRespRate_cocco * PhyCalc & ! --> Respiration - - calc_loss_agg & ! --> Aggregation loss - - calc_loss_gra & ! --> Grazing loss -#if defined (__3Zoo2Det) - - calc_loss_gra2 & - - calc_loss_gra3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphycal) -#else - sms(k,iphycal) = ( & - + calcification & ! --> Calcification - - lossC * limitFacN * PhyCalc & ! --> Excretion loss - - phyRespRate * PhyCalc & ! --> Respiration - - calc_loss_agg & ! --> Aggregation loss - - calc_loss_gra & ! --> Grazing loss -#if defined (__3Zoo2Det) - - calc_loss_gra2 & - - calc_loss_gra3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphycal) -#endif - -!____________________________________________________________ -! Detritus calcite -#if defined (__coccos) - -#if defined (__3Zoo2Det) - sms(k,idetcal) = ( & - + lossC_c * limitFacN_cocco * PhyCalc & - + phyRespRate_cocco * PhyCalc & - + calc_loss_agg & - + calc_loss_gra3 & - - calc_loss_gra3 * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) - -#else - sms(k,idetcal) = ( & - + lossC_c * limitFacN_cocco * PhyCalc & - + phyRespRate_cocco * PhyCalc & - + calc_loss_agg & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) - -#endif - -#else - -#if defined (__3Zoo2Det) - sms(k,idetcal) = ( & - + lossC * limitFacN * PhyCalc & - + phyRespRate * PhyCalc & - + calc_loss_agg & - + calc_loss_gra3 & - - calc_loss_gra3 * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) -#else - sms(k,idetcal) = ( & - + lossC * limitFacN * PhyCalc & - + phyRespRate * PhyCalc & - + calc_loss_agg & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) -#endif -#endif - -!____________________________________________________________ -! Oxygen - - sms(k,ioxy) = ( & - + Cphot * phyC & - - phyRespRate * phyC & - + Cphot_dia * diaC & - - phyRespRate_dia * diaC & -#if defined (__coccos) - + Cphot_cocco * CoccoC & - - phyRespRate_cocco * CoccoC & -#endif - - rho_C1 * arrFunc * O2Func * EOC & ! O2remin - - hetRespFlux & -#if defined (__3Zoo2Det) - - Zoo2RespFlux & - - MicZooRespFlux & ! 3Zoo -#endif - ) * redO2C * dt_b + sms(k,ioxy) -! -!------------------------------------------------------------------------------- -! Diagnostics: Averaged rates - - recipbiostep = 1.d0/real(biostep) -if (Diags) then -!*** Net primary production [mmol C /(m3 * day)] - vertNPPn(k) = vertNPPn(k) + ( & - + Cphot * PhyC & - - PhyRespRate * PhyC & - ) * recipbiostep - - vertNPPd(k) = vertNPPd(k) + ( & - + Cphot_dia * DiaC & - - PhyRespRate_dia * DiaC & - ) * recipbiostep + if (enable_3zoo2det) then + sms(k,idetn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Direct Transfer from Grazing + !----------------------------------------------------------------------- + ! All grazed material enters detritus (no detritus grazing) + + grazingFlux_phy3 & ! Microzooplankton->small phyto !OG added + + grazingFlux_dia3 & ! Microzooplankton->diatoms + + grazingFlux_Cocco3 * is_coccos & ! Microzooplankton->coccoliths + + grazingFlux_Phaeo3 * is_coccos & ! Microzooplankton->Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation + !----------------------------------------------------------------------- + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + aggregationRate * CoccoN * is_coccos & + + aggregationRate * PhaeoN * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + miczooLossFlux & + !----------------------------------------------------------------------- + ! SINKS: Generic Zooplankton Consumption + !----------------------------------------------------------------------- + - grazingFlux * grazEff3 & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetN & + ) * dt_b + sms(k,idetn) + + !------------------------------------------------------------------------------- + ! Configuration 4: WITHOUT Detritus Grazing + 2 Zooplankton Types + !------------------------------------------------------------------------------- + else + sms(k,idetn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Direct Transfer from Grazing + !----------------------------------------------------------------------- + + grazingFlux_phy & ! Mesozooplankton->small phyto + + grazingFlux_dia & ! Mesozooplankton->diatoms + + grazingFlux_Cocco * is_coccos & ! Mesozooplankton->coccoliths + + grazingFlux_Phaeo * is_coccos & ! Mesozooplankton->Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation + !----------------------------------------------------------------------- + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + aggregationRate * CoccoN * is_coccos & + + aggregationRate * PhaeoN * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + hetLossFlux & + !----------------------------------------------------------------------- + ! SINKS: Generic Zooplankton Consumption + !----------------------------------------------------------------------- + - grazingFlux * grazEff & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetN & + ) * dt_b + sms(k,idetn) + endif + end if + + !=============================================================================== + ! 8. DETRITUS CARBON (DetC) + !=============================================================================== + ! Tracks carbon content in slow-sinking organic particles + ! + ! Key Concepts: + ! - Stoichiometric Conversion: N-based fluxes -> C-based fluxes + ! Uses reciprocal quotas (recipQuota = C:N ratio) for conversion + ! - Sloppy Feeding: Net detritus = Total grazing × (1 - efficiency) + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N quotas for phytoplankton [-] + ! recipDet, recipDet2 : C:N ratios in detritus [-] + ! recipQZoo, recipQZoo2, recipQZoo3: C:N ratios in zooplankton [-] + ! reminC : C remineralization rate [day-1] + ! +!=============================================================================== +! KEY CONCEPTS: +!=============================================================================== +! 1. SLOPPY FEEDING: Not all grazed material is assimilated +! - Net detritus production = Total grazing × (1 - grazing efficiency) +! - Represents fecal pellets and inefficient consumption +! +! 2. STOICHIOMETRIC CONVERSION: N-based fluxes -> C-based fluxes +! - recipQuota = C:N ratio of phytoplankton +! - recipDet = C:N ratio of detritus +! - recipQZoo = C:N ratio of zooplankton +! +! 3. FOOD WEB CONFIGURATIONS: +! - Grazing_detritus ON: Zooplankton can feed on detritus (coprophagy) +! - Grazing_detritus OFF: Detritus only forms from grazing/mortality +! - enable_3zoo2det: Adds microzooplankton + fast-sinking detritus +! +! 4. REMINERALIZATION: Temperature and oxygen dependent +! - arrFunc: Increases with temperature (Arrhenius kinetics) +! - O2Func: Decreases under low oxygen (anaerobic conditions) +!=============================================================================== + !------------------------------------------------------------------------------- + ! Configuration 1: WITH Detritus Grazing + 3 Zooplankton Types + !------------------------------------------------------------------------------- + if (Grazing_detritus) then + if (enable_3zoo2det) then + sms(k,idetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Microzooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy3 * recipQuota * (1.d0 - grazEff3) & ! Small phyto + + grazingFlux_Dia3 * recipQuota_Dia * (1.d0 - grazEff3) & ! Diatoms + + grazingFlux_Cocco3 * recipQuota_Cocco * (1.d0 - grazEff3) * is_coccos & ! Coccoliths + + grazingFlux_Phaeo3 * recipQuota_Phaeo * (1.d0 - grazEff3) * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation (C-basis) + !----------------------------------------------------------------------- + + aggregationRate * PhyC & + + aggregationRate * DiaC & + + aggregationRate * CoccoC * is_coccos & + + aggregationRate * PhaeoC * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + miczooLossFlux * recipQZoo3 & ! N->C conversion + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_Det * recipDet * grazEff & ! Mesozooplankton + - grazingFlux_Det2 * recipDet * grazEff2 & ! Macrozooplankton ! corrected recipDet2 -> recipDet + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetC & ! Bacterial respiration + ) * dt_b + sms(k,idetc) + + !------------------------------------------------------------------------------- + ! Configuration 2: WITH Detritus Grazing + 2 Zooplankton Types (Standard) + !------------------------------------------------------------------------------- + else + sms(k,idetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * (1.d0 - grazEff) & + + grazingFlux_Dia * recipQuota_Dia * (1.d0 - grazEff) & + + grazingFlux_Cocco * recipQuota_Cocco * (1.d0 - grazEff) * is_coccos & + + grazingFlux_Phaeo * recipQuota_Phaeo * (1.d0 - grazEff) * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation (C-basis) + !----------------------------------------------------------------------- + + aggregationRate * phyC & + + aggregationRate * DiaC & + + aggregationRate * CoccoC * is_coccos & + + aggregationRate * PhaeoC * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + hetLossFlux * recipQZoo & + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_Det * recipDet * grazEff & + ! - grazingFlux_Det2 * recipDet2 * grazEff & !!!!!! CHECK + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetC & + ) * dt_b + sms(k,idetc) -#if defined (__coccos) - vertNPPc(k) = vertNPPc(k) + ( & - + Cphot_cocco * CoccoC & - - PhyRespRate_cocco * CoccoC & - ) * recipbiostep -#endif + endif -!*** Gross primary production [mmol C /(m3 * day)] - vertGPPn(k) = vertGPPn(k) + ( & - + Cphot * PhyC & - ) * recipbiostep + !------------------------------------------------------------------------------- + ! Configuration 3: WITHOUT Detritus Grazing + 3 Zooplankton Types + !------------------------------------------------------------------------------- + else + if (enable_3zoo2det) then + sms(k,idetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Microzooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy3 * recipQuota * (1.d0 - grazEff3) & + + grazingFlux_Dia3 * recipQuota_Dia * (1.d0 - grazEff3) & + + grazingFlux_Cocco3 * recipQuota_Cocco * (1.d0 - grazEff3) * is_coccos & + + grazingFlux_Phaeo3 * recipQuota_Phaeo * (1.d0 - grazEff3) * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation (C-basis) + !----------------------------------------------------------------------- + + aggregationRate * PhyC & + + aggregationRate * DiaC & + + aggregationRate * CoccoC * is_coccos & + + aggregationRate * PhaeoC * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + miczooLossFlux * recipQZoo3 & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetC & + ) * dt_b + sms(k,idetc) + + !------------------------------------------------------------------------------- + ! Configuration 4: WITHOUT Detritus Grazing + 2 Zooplankton Types + !------------------------------------------------------------------------------- + else + sms(k,idetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * (1.d0 - grazEff) & + + grazingFlux_Dia * recipQuota_Dia * (1.d0 - grazEff) & + + grazingFlux_Cocco * recipQuota_Cocco * (1.d0 - grazEff) * is_coccos & + + grazingFlux_Phaeo * recipQuota_Phaeo * (1.d0 - grazEff) * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation (C-basis) + !----------------------------------------------------------------------- + + aggregationRate * phyC & + + aggregationRate * DiaC & + + aggregationRate * CoccoC * is_coccos & + + aggregationRate * PhaeoC * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + hetLossFlux * recipQZoo & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetC & + ) * dt_b + sms(k,idetc) - vertGPPd(k) = vertGPPd(k) + ( & - + Cphot_dia * DiaC & - ) * recipbiostep + endif + end if + + !=============================================================================== + ! 9. MESOZOOPLANKTON NITROGEN (HetN) + !=============================================================================== + ! Primary herbivorous/omnivorous grazers that feed on phytoplankton and + ! smaller prey items. + ! + ! Variables: + ! grazingFlux : Total N grazing rate [mmolN m-3 day-1] + ! grazEff : Grazing/assimilation efficiency [-] + ! grazingFlux_het2 : Predation by macrozooplankton [mmolN m-3 day-1] + ! Mesfecalloss_n : Fecal pellet production [mmolN m-3 day-1] + ! hetLossFlux : Mortality flux [mmolN m-3 day-1] + ! lossN_z : DON excretion rate [day-1] + !------------------------------------------------------------------------------- + + sms(k,ihetn) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Grazing + !--------------------------------------------------------------------------- + + grazingFlux * grazEff & ! Assimilated N + !--------------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Excretion + !--------------------------------------------------------------------------- + - grazingFlux_het2 * is_3zoo2det & ! Predation by macrozooplankton + - Mesfecalloss_n * is_3zoo2det & ! Fecal pellets + - hetLossFlux & ! Mortality + - lossN_z * HetN & ! DON excretion + ) * dt_b + sms(k,ihetn) + + !=============================================================================== + ! 10. MESOZOOPLANKTON CARBON (HetC) + !=============================================================================== + ! Carbon budget uses reciprocal quotas (C:N ratios) to convert N-based + ! grazing rates to carbon equivalents. + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N ratios of prey items [-] + ! recipDet, recipDet2 : C:N ratios of detritus [-] + ! recipQZoo, recipQZoo3 : C:N ratios of zooplankton [-] + ! hetRespFlux : Respiration to CO2 [mmolC m-3 day-1] + ! lossC_z : DOC excretion rate [day-1] + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Configuration: Mesozooplankton CAN Graze on Detritus + !------------------------------------------------------------------------------- + if (Grazing_detritus) then + sms(k,ihetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * grazEff & ! Small phytoplankton + + grazingFlux_Dia * recipQuota_Dia * grazEff & ! Diatoms + + grazingFlux_Cocco * recipQuota_Cocco * grazEff * is_coccos & ! Coccolithophores + + grazingFlux_Phaeo * recipQuota_Phaeo * grazEff * is_coccos & ! Phaeocystis + + grazingFlux_miczoo * recipQZoo3 * grazEff * is_3zoo2det & ! Microzooplankton + + grazingFlux_DetZ2 * recipDet2 * grazEff * is_3zoo2det & ! Fast-sinking detritus + + grazingFlux_Det * recipDet * grazEff & ! Slow-sinking detritus + !----------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Respiration, Excretion + !----------------------------------------------------------------------- + - grazingFlux_het2 * recipQZoo * is_3zoo2det & ! Predation + - Mesfecalloss_c * is_3zoo2det & ! Fecal pellets + - hetLossFlux * recipQZoo & ! Mortality + - lossC_z * HetC & ! DOC excretion + - hetRespFlux & ! Respiration to CO2 + ) * dt_b + sms(k,ihetc) + + !------------------------------------------------------------------------------- + ! Configuration: Mesozooplankton CANNOT Graze on Detritus + !------------------------------------------------------------------------------- + else + sms(k,ihetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis, herbivorous diet only) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia * grazEff & + + grazingFlux_Cocco * recipQuota_Cocco * grazEff * is_coccos & + + grazingFlux_Phaeo * recipQuota_Phaeo * grazEff * is_coccos & + + grazingFlux_miczoo * recipQZoo3 * grazEff * is_3zoo2det & + !----------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Respiration, Excretion + !----------------------------------------------------------------------- + - grazingFlux_het2 * recipQZoo * is_3zoo2det & + - Mesfecalloss_c * is_3zoo2det & + - hetLossFlux * recipQZoo & + - lossC_z * HetC & + - hetRespFlux & + ) * dt_b + sms(k,ihetc) + endif -#if defined (__coccos) - vertGPPc(k) = vertGPPc(k) + ( & - + Cphot_cocco * CoccoC & - ) * recipbiostep -#endif + !=============================================================================== + ! 11. MACROZOOPLANKTON NITROGEN (Zoo2N) + !=============================================================================== + ! Larger predatory zooplankton that feed on mesozooplankton, microzooplankton, + ! and phytoplankton. Only active when enable_3zoo2det = .true. + ! + ! Variables: + ! grazingFlux2 : Total N grazing rate [mmolN m-3 day-1] + ! grazEff2 : Grazing/assimilation efficiency [-] + ! Zoo2LossFlux : Mortality flux [mmolN m-3 day-1] + ! lossN_z2 : DON excretion rate [day-1] + ! Zoo2fecalloss_n : Fecal pellet production [mmolN m-3 day-1] + !------------------------------------------------------------------------------- + + if (enable_3zoo2det) then + sms(k,izoo2n) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing + !----------------------------------------------------------------------- + + grazingFlux2 * grazEff2 & ! Assimilated N + !----------------------------------------------------------------------- + ! SINKS: Mortality, Excretion, Fecal Pellets + !----------------------------------------------------------------------- + - Zoo2LossFlux & ! Mortality + - lossN_z2 * Zoo2N & ! DON excretion + - Zoo2fecalloss_n & ! Fecal pellets + ) * dt_b + sms(k,izoo2n) + + !=============================================================================== + ! 12. MACROZOOPLANKTON CARBON (Zoo2C) + !=============================================================================== + ! Carbon budget for macrozooplankton with stoichiometric conversions. + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N ratios of prey [-] + ! recipDet, recipDet2 : C:N ratios of detritus [-] + ! recipQZoo, recipQZoo2, recipQZoo3: C:N ratios of zooplankton [-] + ! Zoo2RespFlux : Respiration to CO2 [mmolC m-3 day-1] + ! lossC_z2 : DOC excretion rate [day-1] + !------------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Configuration: Macrozooplankton CAN Graze on Detritus + !--------------------------------------------------------------------------- -!*** Net N-assimilation [mmol N/(m3 * day)] - vertNNAn(k) = vertNNAn(k) + ( & - + N_assim * PhyC & - - lossN * limitFacN * PhyN & - ) * recipbiostep + if (Grazing_detritus) then + sms(k,izoo2c) = ( & + !------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis) + !------------------------------------------------------------------- + + grazingFlux_phy2 * recipQuota * grazEff2 & ! Small phytoplankton + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & ! Diatoms + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 * is_coccos & ! Coccolithophores + + grazingFlux_Phaeo2 * recipQuota_Phaeo * grazEff2 * is_coccos & ! Phaeocystis + + grazingFlux_het2 * recipQZoo * grazEff2 & ! Mesozooplankton (predation) + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! Microzooplankton + + grazingFlux_Det2 * recipDet * grazEff2 & ! Slow-sinking detritus + + grazingFlux_DetZ22 * recipDet2 * grazEff2 & ! Fast-sinking detritus + !------------------------------------------------------------------- + ! SINKS: Mortality, Respiration, Excretion, Fecal Pellets + !------------------------------------------------------------------- + - zoo2LossFlux * recipQZoo2 & ! Mortality + - lossC_z2 * Zoo2C & ! DOC excretion + - Zoo2RespFlux & ! Respiration to CO2 + - Zoo2fecalloss_c & ! Fecal pellets + ) * dt_b + sms(k,izoo2c) + + !--------------------------------------------------------------------------- + ! Configuration: Macrozooplankton CANNOT Graze on Detritus + !--------------------------------------------------------------------------- + else + sms(k,izoo2c) = ( & + !------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis, no detritus feeding) + !------------------------------------------------------------------- + + grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 * is_coccos & + + grazingFlux_Phaeo2 * recipQuota_Phaeo * grazEff2 * is_coccos & + + grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & + !------------------------------------------------------------------- + ! SINKS: Mortality, Respiration, Excretion, Fecal Pellets + !------------------------------------------------------------------- + - zoo2LossFlux * recipQZoo2 & + - lossC_z2 * Zoo2C & + - Zoo2RespFlux & + - Zoo2fecalloss_c & + ) * dt_b + sms(k,izoo2c) - vertNNAd(k) = vertNNAd(k) + ( & - + N_assim_dia * DiaC & - - lossN * limitFacN_dia * DiaN & - ) * recipbiostep + end if -#if defined (__coccos) - vertNNAc(k) = vertNNAc(k) + ( & - + N_assim_cocco * CoccoC & - - lossN * limitFacN_cocco * CoccoN & - ) * recipbiostep -#endif + !=============================================================================== + ! 13. MICROZOOPLANKTON NITROGEN (MicZooN) + !=============================================================================== + ! Small heterotrophic protists that graze on phytoplankton and are prey for + ! meso- and macrozooplankton. + ! + ! Variables: + ! grazingFlux3 : Total N grazing rate [mmolN m-3 day-1] + ! grazEff3 : Grazing/assimilation efficiency [-] + ! grazingFlux_miczoo : Predation by mesozooplankton [mmolN m-3 day-1] + ! grazingFlux_miczoo2: Predation by macrozooplankton [mmolN m-3 day-1] + ! MicZooLossFlux : Mortality flux [mmolN m-3 day-1] + ! lossN_z3 : DON excretion rate [day-1] + !------------------------------------------------------------------------------- + + sms(k,imiczoon) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing + !----------------------------------------------------------------------- + + grazingFlux3 * grazEff3 & ! Assimilated N + !----------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Excretion + !----------------------------------------------------------------------- + - grazingFlux_miczoo & ! Predation by mesozooplankton + - grazingFlux_miczoo2 & ! Predation by macrozooplankton + - MicZooLossFlux & ! Mortality + - lossN_z3 * MicZooN & ! DON excretion + ) * dt_b + sms(k,imiczoon) + + !=============================================================================== + ! 14. MICROZOOPLANKTON CARBON (MicZooC) + !=============================================================================== + ! Carbon budget for microzooplankton with stoichiometric conversions. + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N ratios of prey [-] + ! recipQZoo3 : C:N ratio of microzooplankton [-] + ! MicZooRespFlux : Respiration to CO2 [mmolC m-3 day-1] + ! lossC_z3 : DOC excretion rate [day-1] + !------------------------------------------------------------------------------- + + sms(k,imiczooc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy3 * recipQuota * grazEff3 & ! Small phytoplankton + + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & ! Diatoms + + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 * is_coccos & ! Coccolithophores + + grazingFlux_Phaeo3 * recipQuota_Phaeo * grazEff3 * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Respiration, Excretion + !----------------------------------------------------------------------- + - MicZooLossFlux * recipQZoo3 & ! Mortality + - grazingFlux_miczoo * recipQZoo3 & ! Predation by mesozooplankton + - grazingFlux_miczoo2 * recipQZoo3 & ! Predation by macrozooplankton + - lossC_z3 * MicZooC & ! DOC excretion + - MicZooRespFlux & ! Respiration to CO2 + ) * dt_b + sms(k,imiczooc) + + end if + + !=============================================================================== + ! 15. FAST-SINKING DETRITUS NITROGEN (DetZ2N) + !=============================================================================== + ! Particulate organic matter produced from zooplankton mortality, fecal pellets, + ! and unassimilated grazing. Sinks faster than regular detritus. + ! Only active when enable_3zoo2det = .true. + ! + ! Variables: + ! grazingFlux_phy, grazingFlux_phy2 : Grazing on small phyto [mmolN m-3 day-1] + ! grazingFlux_dia, grazingFlux_dia2 : Grazing on diatoms [mmolN m-3 day-1] + ! grazingFlux_het2 : Predation on mesozooplankton [mmolN m-3 day-1] + ! grazingFlux_miczoo, grazingFlux_miczoo2 : Grazing on microzooplankton [mmolN m-3 day-1] + ! grazingFlux_DetZ2, grazingFlux_DetZ22 : Grazing on fast detritus [mmolN m-3 day-1] + ! Zoo2LossFlux, hetLossFlux : Zooplankton mortality [mmolN m-3 day-1] + ! Zoo2fecalloss_n, Mesfecalloss_n : Fecal pellet production [mmolN m-3 day-1] + ! reminN : Remineralization rate [day-1] + !------------------------------------------------------------------------------- + + if (enable_3zoo2det) then + + !--------------------------------------------------------------------------- + ! Configuration: Zooplankton CAN Graze on Fast-Sinking Detritus + !--------------------------------------------------------------------------- + if (Grazing_detritus) then + sms(k,idetz2n) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Macrozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy2 * (1.d0 - grazEff2) & ! Small phytoplankton + + grazingFlux_dia2 * (1.d0 - grazEff2) & ! Diatoms + + grazingFlux_Cocco * (1.d0 - grazEff) * is_coccos & ! Coccoliths (meso) ! grazEff2 --> grazEff + + grazingFlux_Cocco2 * (1.d0 - grazEff2) * is_coccos & ! Coccoliths (macro) + + grazingFlux_Phaeo * (1.d0 - grazEff) * is_coccos & ! Phaeocystis (meso) + + grazingFlux_Phaeo2 * (1.d0 - grazEff2) * is_coccos & ! Phaeocystis (macro) + + grazingFlux_het2 * (1.d0 - grazEff2) & ! Mesozooplankton (predation) + + grazingFlux_miczoo2 * (1.d0 - grazEff2) & ! Microzooplankton + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy * (1.d0 - grazEff) & ! Small phytoplankton + + grazingFlux_dia * (1.d0 - grazEff) & ! Diatoms + + grazingFlux_miczoo * (1.d0 - grazEff) & ! Microzooplankton + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + Zoo2LossFlux & ! Macrozooplankton + + hetLossFlux & ! Mesozooplankton + !----------------------------------------------------------------------- + ! SOURCES: Fecal Pellet Production + !----------------------------------------------------------------------- + + Zoo2fecalloss_n & ! Macrozooplankton + + Mesfecalloss_n & ! Mesozooplankton + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption (Coprophagy) + !----------------------------------------------------------------------- + - grazingFlux_DetZ2 * grazEff & ! Mesozooplankton + - grazingFlux_DetZ22 * grazEff2 & ! Macrozooplankton + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetZ2N & ! Bacterial decomposition + ) * dt_b + sms(k,idetz2n) + + !--------------------------------------------------------------------------- + ! Configuration: Zooplankton CANNOT Graze on Fast-Sinking Detritus + !--------------------------------------------------------------------------- + else + sms(k,idetz2n) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Macrozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy2 & ! All grazing enters detritus + + grazingFlux_dia2 & + + grazingFlux_Cocco * is_coccos & + + grazingFlux_Cocco2 * is_coccos & + + grazingFlux_Phaeo * is_coccos & + + grazingFlux_Phaeo2 * is_coccos & + + grazingFlux_het2 & + + grazingFlux_miczoo2 & + - grazingFlux2 * grazEff2 & ! Minus assimilated portion + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy & + + grazingFlux_dia & + + grazingFlux_miczoo & + - grazingFlux * grazEff & ! Minus assimilated portion + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + Zoo2LossFlux & + + hetLossFlux & + !----------------------------------------------------------------------- + ! SOURCES: Fecal Pellet Production + !----------------------------------------------------------------------- + + Zoo2fecalloss_n & + + Mesfecalloss_n & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetZ2N & + ) * dt_b + sms(k,idetz2n) + end if + !=============================================================================== + ! 16. FAST-SINKING DETRITUS CARBON (DetZ2C) + !=============================================================================== + ! Carbon budget for fast-sinking detritus with stoichiometric conversions. + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N ratios of phytoplankton [-] + ! recipQZoo, recipQZoo2, recipQZoo3: C:N ratios of zooplankton [-] + ! recipDet2 : C:N ratio of fast-sinking detritus [-] + ! reminC : C remineralization rate [day-1] + !------------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Configuration: Zooplankton CAN Graze on Fast-Sinking Detritus + !--------------------------------------------------------------------------- + if (Grazing_detritus) then + sms(k,idetz2c) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Macrozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy2 * recipQuota * (1.d0 - grazEff2) & ! Small phyto + + grazingFlux_Dia2 * recipQuota_Dia * (1.d0 - grazEff2) & ! Diatoms + + grazingFlux_Cocco * recipQuota_Cocco * (1.d0 - grazEff) * is_coccos & ! Coccoliths (meso) + + grazingFlux_Cocco2 * recipQuota_Cocco * (1.d0 - grazEff2) * is_coccos & ! Coccoliths (macro) + + grazingFlux_Phaeo * recipQuota_Phaeo * (1.d0 - grazEff) * is_coccos & ! Phaeocystis (meso) + + grazingFlux_Phaeo2 * recipQuota_Phaeo * (1.d0 - grazEff2) * is_coccos & ! Phaeocystis (macro) + + grazingFlux_het2 * recipQZoo * (1.d0 - grazEff2) & ! Mesozooplankton + + grazingFlux_miczoo2 * recipQZoo3 * (1.d0 - grazEff2) & ! Microzooplankton + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * (1.d0 - grazEff) & ! Small phyto + + grazingFlux_Dia * recipQuota_Dia * (1.d0 - grazEff) & ! Diatoms + + grazingFlux_miczoo * recipQZoo3 * (1.d0 - grazEff) & ! Microzooplankton + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + Zoo2LossFlux * recipQZoo2 & ! Macrozooplankton (N->C) + + hetLossFlux * recipQZoo & ! Mesozooplankton (N->C) + !----------------------------------------------------------------------- + ! SOURCES: Fecal Pellet Production (C-basis) + !----------------------------------------------------------------------- + + Zoo2fecalloss_c & ! Macrozooplankton + + Mesfecalloss_c & ! Mesozooplankton + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_DetZ2 * recipDet2 * grazEff & ! Mesozooplankton + - grazingFlux_DetZ22 * recipDet2 * grazEff2 & ! Macrozooplankton + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetZ2C & ! Bacterial respiration + ) * dt_b + sms(k,idetz2c) + + !--------------------------------------------------------------------------- + ! Configuration: Zooplankton CANNOT Graze on Fast-Sinking Detritus + !--------------------------------------------------------------------------- + else + sms(k,idetz2c) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Macrozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy2 * recipQuota * (1.d0 - grazEff2) & + + grazingFlux_Dia2 * recipQuota_Dia * (1.d0 - grazEff2) & + + grazingFlux_Cocco * recipQuota_Cocco * (1.d0 - grazEff) * is_coccos & + + grazingFlux_Cocco2 * recipQuota_Cocco * (1.d0 - grazEff2) * is_coccos & ! grazEff -> grazEff2 + + grazingFlux_Phaeo * recipQuota_Phaeo * (1.d0 - grazEff) * is_coccos & + + grazingFlux_Phaeo2 * recipQuota_Phaeo * (1.d0 - grazEff2) * is_coccos & + + grazingFlux_het2 * recipQZoo * (1.d0 - grazEff2) & + + grazingFlux_miczoo2 * recipQZoo3 * (1.d0 - grazEff2) & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * (1.d0 - grazEff) & + + grazingFlux_Dia * recipQuota_Dia * (1.d0 - grazEff) & + + grazingFlux_miczoo * recipQZoo3 * (1.d0 - grazEff) & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + Zoo2LossFlux * recipQZoo2 & + + hetLossFlux * recipQZoo & + !----------------------------------------------------------------------- + ! SOURCES: Fecal Pellet Production (C-basis) + !----------------------------------------------------------------------- + + Zoo2fecalloss_c & + + Mesfecalloss_c & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetZ2C & + ) * dt_b + sms(k,idetz2c) + end if -!*** Changed to chlorophyll degradation (commented out gross N-assimilation below) - vertChldegn(k) = vertChldegn(k) + ( & - + KOchl & - ) * recipbiostep + !=============================================================================== + ! 17. FAST-SINKING DETRITUS SILICA (DetZ2Si) + !=============================================================================== + ! Biogenic silica from diatom frustules in fast-sinking detritus. + ! + ! Variables: + ! grazingFlux_dia, grazingFlux_dia2 : Grazing on diatoms [mmolN m-3 day-1] + ! qSiN : Si:N ratio in diatoms [mmolSi mmolN-1] + ! reminSiT : Temperature-dependent dissolution [day-1] + !------------------------------------------------------------------------------- + + sms(k,idetz2si) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing on Diatoms + !----------------------------------------------------------------------- + + grazingFlux_dia2 * qSiN & ! Macrozooplankton grazing + + grazingFlux_dia * qSiN & ! Mesozooplankton grazing + !----------------------------------------------------------------------- + ! SINKS: Dissolution + !----------------------------------------------------------------------- + - reminSiT * DetZ2Si & ! Temperature-dependent + ) * dt_b + sms(k,idetz2si) + + !=============================================================================== + ! 18. FAST-SINKING DETRITUS CALCITE (DetZ2Calc) + !=============================================================================== + ! Calcite particles from coccolithophore shells in fast-sinking detritus. + ! + ! Variables: + ! calc_loss_gra, calc_loss_gra2 : Calcite from grazing [mmolCaCO3 m-3 day-1] + ! calc_diss_guts : Gut dissolution fraction [-] + ! calc_diss2 : Water column dissolution rate [day-1] + !------------------------------------------------------------------------------- + + sms(k,idetz2calc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing on Calcifying Phytoplankton + !----------------------------------------------------------------------- + + calc_loss_gra2 * (1.d0 - calc_diss_guts) & ! Macrozooplankton (net) + + calc_loss_gra * (1.d0 - calc_diss_guts) & ! Mesozooplankton (net) + !----------------------------------------------------------------------- + ! SINKS: Dissolution in Water Column + !----------------------------------------------------------------------- + - calc_diss2 * DetZ2Calc & ! CaCO3 dissolution + ) * dt_b + sms(k,idetz2calc) + + endif ! enable_3zoo2det + + !=============================================================================== + ! 19. DISSOLVED ORGANIC NITROGEN (DON) + !=============================================================================== + ! Dissolved organic nitrogen pool from phytoplankton excretion, zooplankton + ! metabolism, and detrital remineralization. + ! + ! Variables: + ! lossN, lossN_d, lossN_c, lossN_p : Phytoplankton DON excretion rates [day-1] + ! limitFacN, limitFacN_Dia, etc. : N:C ratio limiters (regulate excretion) [-] + ! reminN : Detrital N remineralization rate [day-1] + ! rho_N : DON remineralization rate [day-1] + ! lossN_z, lossN_z2, lossN_z3 : Zooplankton DON excretion rates [day-1] + ! arrFunc : Arrhenius temperature function [-] + ! O2Func : Oxygen limitation function [-] + !------------------------------------------------------------------------------- + + sms(k,idon) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Phytoplankton Excretion + !--------------------------------------------------------------------------- + + lossN * limitFacN * phyN & ! Small phytoplankton + + lossN_d * limitFacN_Dia * DiaN & ! Diatoms + + lossN_c * limitFacN_Cocco * CoccoN * is_coccos & ! Coccolithophores + + lossN_p * limitFacN_Phaeo * PhaeoN * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SOURCES: Detrital Remineralization + !--------------------------------------------------------------------------- + + reminN * arrFunc * O2Func * DetN & ! Slow-sinking detritus + + reminN * arrFunc * O2Func * DetZ2N * is_3zoo2det & ! Fast-sinking detritus + !--------------------------------------------------------------------------- + ! SOURCES: Zooplankton Excretion + !--------------------------------------------------------------------------- + + lossN_z * HetN & ! Mesozooplankton + + lossN_z2 * Zoo2N * is_3zoo2det & ! Macrozooplankton + + lossN_z3 * MicZooN * is_3zoo2det & ! Microzooplankton + !--------------------------------------------------------------------------- + ! SINKS: Remineralization to NH4 + !--------------------------------------------------------------------------- + - rho_N * arrFunc * O2Func * DON & ! Bacterial remineralization + ) * dt_b + sms(k,idon) + + !=============================================================================== + ! 20. EXTRACELLULAR ORGANIC CARBON (EOC / DOC) + !=============================================================================== + ! Dissolved organic carbon pool from phytoplankton excretion, zooplankton + ! metabolism, and detrital remineralization. + ! + ! Variables: + ! lossC, lossC_d, lossC_c, lossC_p : Phytoplankton DOC excretion rates [day-1] + ! limitFacN, limitFacN_dia, etc. : N:C ratio limiters (regulate excretion) [-] + ! reminC : Detrital C remineralization rate [day-1] + ! rho_c1 : DOC remineralization rate [day-1] + ! lossC_z, lossC_z2, lossC_z3 : Zooplankton DOC excretion rates [day-1] + !------------------------------------------------------------------------------- + + sms(k,idoc) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Phytoplankton Excretion + !--------------------------------------------------------------------------- + + lossC * limitFacN * phyC & ! Small phytoplankton + + lossC_d * limitFacN_dia * DiaC & ! Diatoms + + lossC_c * limitFacN_cocco * CoccoC * is_coccos & ! Coccolithophores + + lossC_p * limitFacN_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SOURCES: Detrital Remineralization + !--------------------------------------------------------------------------- + + reminC * arrFunc * O2Func * DetC & ! Slow-sinking detritus + + reminC * arrFunc * O2Func * DetZ2C * is_3zoo2det & ! Fast-sinking detritus + !--------------------------------------------------------------------------- + ! SOURCES: Zooplankton Excretion + !--------------------------------------------------------------------------- + + lossC_z * HetC & ! Mesozooplankton + + lossC_z2 * Zoo2C * is_3zoo2det & ! Macrozooplankton + + lossC_z3 * MicZooC * is_3zoo2det & ! Microzooplankton + !--------------------------------------------------------------------------- + ! SINKS: Remineralization to CO2 + !--------------------------------------------------------------------------- + - rho_c1 * arrFunc * O2Func * EOC & ! Bacterial respiration + ) * dt_b + sms(k,idoc) + if (useRivers) then + ! R2OMIP - terrestrial DOC + sms(k,idoct) = ( & + - rho_C1t * DOCt & + ) * dt_b + sms(k,idoct) + end if + !=============================================================================== + ! 21. DIATOM NITROGEN (DiaN) + !=============================================================================== + ! Tracks nitrogen content of diatoms (large phytoplankton with silica frustules). + ! + ! Variables: + ! N_assim_dia : N assimilation rate [day-1] + ! lossN_d : N loss rate [day-1] + ! limitFacN_dia : Limiter function for N:C ratio regulation [-] + ! aggregationRate : Aggregation to detritus [day-1] + ! grazingFlux_Dia : Mesozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_Dia2 : Macrozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_Dia3 : Microzooplankton grazing [mmolN m-3 day-1] + !------------------------------------------------------------------------------- + + sms(k,idian) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Nitrogen Assimilation + !--------------------------------------------------------------------------- + + N_assim_dia * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: DON Excretion + !--------------------------------------------------------------------------- + - lossN_d * limitFacN_dia * DiaN & + !--------------------------------------------------------------------------- + ! SINKS: Aggregation + !--------------------------------------------------------------------------- + - aggregationRate * DiaN & + !--------------------------------------------------------------------------- + ! SINKS: Grazing + !--------------------------------------------------------------------------- + - grazingFlux_Dia & ! Mesozooplankton + - grazingFlux_Dia2 * is_3zoo2det & ! Macrozooplankton + - grazingFlux_Dia3 * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,idian) + + !=============================================================================== + ! 22. DIATOM CARBON (DiaC) + !=============================================================================== + ! Tracks carbon content of diatoms. + ! + ! Variables: + ! Cphot_dia : Gross photosynthesis rate [day-1] + ! phyRespRate_dia : Autotrophic respiration rate [day-1] + ! lossC_d : C loss rate [day-1] + ! recipQuota_dia : Reciprocal of N:C quota (for N->C conversion) [-] + !------------------------------------------------------------------------------- + + sms(k,idiac) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Net Photosynthesis + !--------------------------------------------------------------------------- + + Cphot_dia * DiaC & ! Gross photosynthesis + !--------------------------------------------------------------------------- + ! SINKS: DOC Excretion + !--------------------------------------------------------------------------- + - lossC_d * limitFacN_dia * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: Respiration + !--------------------------------------------------------------------------- + - phyRespRate_dia * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: Aggregation + !--------------------------------------------------------------------------- + - aggregationRate * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: Grazing (C-basis) + !--------------------------------------------------------------------------- + - grazingFlux_dia * recipQuota_dia & ! Mesozooplankton (N->C) + - grazingFlux_dia2 * recipQuota_dia * is_3zoo2det & ! Macrozooplankton + - grazingFlux_dia3 * recipQuota_dia * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,idiac) + + !=============================================================================== + ! 23. DIATOM CHLOROPHYLL-A (DiaChl) + !=============================================================================== + ! Tracks chlorophyll-a content for light harvesting and photoacclimation. + ! + ! Variables: + ! chlSynth_dia : Chlorophyll synthesis rate [mgChl mmolC-1 day-1] + ! KOchl_dia : Chlorophyll degradation rate [day-1] + ! Chl2N_dia : Chl:N ratio = DiaChl/DiaN [mgChl mmolN-1] + !------------------------------------------------------------------------------- + + sms(k,idchl) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Chlorophyll Synthesis + !--------------------------------------------------------------------------- + + chlSynth_dia * DiaC & ! Photoacclimation + !--------------------------------------------------------------------------- + ! SINKS: Photo-oxidation + !--------------------------------------------------------------------------- + - KOchl_dia * DiaChl & + !--------------------------------------------------------------------------- + ! SINKS: Aggregation + !--------------------------------------------------------------------------- + - aggregationRate * DiaChl & + !--------------------------------------------------------------------------- + ! SINKS: Grazing (Chl-basis) + !--------------------------------------------------------------------------- + - grazingFlux_dia * Chl2N_dia & ! Mesozooplankton (N->Chl) + - grazingFlux_dia2 * Chl2N_dia * is_3zoo2det & ! Macrozooplankton + - grazingFlux_dia3 * Chl2N_dia * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,idchl) + + !=============================================================================== + ! 24. DIATOM SILICA (DiaSi) + !=============================================================================== + ! Tracks biogenic silica content in diatom frustules. + ! + ! Variables: + ! Si_assim : Silicic acid assimilation rate [day-1] + ! qSiN : Si:N ratio in diatoms [mmolSi mmolN-1] + !------------------------------------------------------------------------------- + + sms(k,idiasi) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Silicon Assimilation + !--------------------------------------------------------------------------- + + Si_assim * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: Silicon Excretion + !--------------------------------------------------------------------------- + - lossN_d * limitFacN_dia * DiaSi & + !--------------------------------------------------------------------------- + ! SINKS: Aggregation + !--------------------------------------------------------------------------- + - aggregationRate * DiaSi & + !--------------------------------------------------------------------------- + ! SINKS: Grazing (Si-basis) + !--------------------------------------------------------------------------- + - grazingFlux_dia * qSiN & ! Mesozooplankton (N->Si) + - grazingFlux_dia2 * qSiN * is_3zoo2det & ! Macrozooplankton + - grazingFlux_dia3 * qSiN * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,idiasi) + + !=============================================================================== + ! 25. COCCOLITHOPHORE NITROGEN (CoccoN) + !=============================================================================== + ! Tracks nitrogen content of coccolithophores (calcifying small phytoplankton). + ! Only active when enable_coccos = .true. + ! + ! Variables: + ! N_assim_cocco : N assimilation rate [day-1] + ! lossN_c : N loss rate [day-1] + ! limitFacN_cocco : Limiter function for N:C ratio regulation [-] + ! aggregationRate : Aggregation to detritus [day-1] + ! grazingFlux_Cocco : Mesozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_Cocco2 : Macrozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_Cocco3 : Microzooplankton grazing [mmolN m-3 day-1] + !------------------------------------------------------------------------------- + + if (enable_coccos) then + sms(k,icocn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Nitrogen Assimilation + !----------------------------------------------------------------------- + + N_assim_cocco * CoccoC & + !----------------------------------------------------------------------- + ! SINKS: DON Excretion + !----------------------------------------------------------------------- + - lossN_c * limitFacN_cocco * CoccoN & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * CoccoN & + !----------------------------------------------------------------------- + ! SINKS: Grazing + !----------------------------------------------------------------------- + - grazingFlux_Cocco & ! Mesozooplankton + - grazingFlux_Cocco2 * is_3zoo2det & ! Macrozooplankton + - grazingFlux_Cocco3 * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,icocn) + + !=============================================================================== + ! 26. COCCOLITHOPHORE CARBON (CoccoC) + !=============================================================================== + ! Tracks carbon content of coccolithophores. + ! + ! Variables: + ! Cphot_cocco : Gross photosynthesis rate [day-1] + ! phyRespRate_cocco : Autotrophic respiration rate [day-1] + ! lossC_c : C loss rate [day-1] + ! recipQuota_cocco : Reciprocal of N:C quota (for N->C conversion) [-] + !------------------------------------------------------------------------------- + + sms(k,icocc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Net Photosynthesis + !----------------------------------------------------------------------- + + Cphot_cocco * CoccoC & ! Gross photosynthesis + !----------------------------------------------------------------------- + ! SINKS: DOC Excretion + !----------------------------------------------------------------------- + - lossC_c * limitFacN_cocco * CoccoC & + !----------------------------------------------------------------------- + ! SINKS: Respiration + !----------------------------------------------------------------------- + - phyRespRate_cocco * CoccoC & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * CoccoC & + !----------------------------------------------------------------------- + ! SINKS: Grazing (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_cocco * recipQuota_cocco & ! Mesozooplankton (N->C) + - grazingFlux_Cocco2 * recipQuota_cocco * is_3zoo2det & ! Macrozooplankton + - grazingFlux_Cocco3 * recipQuota_cocco * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,icocc) + + !--------------------------------------------------------------------------- + ! Error Check: Unrealistic CoccoC Growth + !--------------------------------------------------------------------------- + if(sms(k,icocc) > 100) then + print*,'ERROR: Unrealistic CoccoC growth detected!' + print*,'k= ', k + print*,'dt= ', dt + print*,'dt_b= ', dt_b + print*,'state(k,icocc): ', state(k,icocc) + print*,'CoccoC: ', CoccoC + print*,'CoccoN: ', CoccoN + print*,'Cphot_cocco: ', Cphot_cocco*CoccoC + print*,'lossC_c: ', lossC_c + print*,'limitFacN_cocco: ', limitFacN_cocco + print*,'phyRespRate_cocco: ', phyRespRate_cocco + print*,'grazingFlux_cocco: ', grazingFlux_cocco + print*,'grazingFlux_Cocco2: ', grazingFlux_Cocco2 + print*,'grazingFlux_Cocco3: ', grazingFlux_Cocco3 + print*,'recipQuota_cocco: ', recipQuota_cocco + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + endif - vertChldegd(k) = vertChldegd(k) + ( & - + KOchl_dia & - ) * recipbiostep + !=============================================================================== + ! 27. COCCOLITHOPHORE CHLOROPHYLL-A (CoccoChl) + !=============================================================================== + ! Tracks chlorophyll-a content for light harvesting and photoacclimation. + ! + ! Variables: + ! ChlSynth_cocco : Chlorophyll synthesis rate [mgChl mmolC-1 day-1] + ! KOchl_cocco : Chlorophyll degradation rate [day-1] + ! Chl2N_cocco : Chl:N ratio = CoccoChl/CoccoN [mgChl mmolN-1] + !------------------------------------------------------------------------------- + + sms(k,icchl) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Chlorophyll Synthesis + !----------------------------------------------------------------------- + + ChlSynth_cocco * CoccoC & ! Photoacclimation + !----------------------------------------------------------------------- + ! SINKS: Photo-oxidation + !----------------------------------------------------------------------- + - KOchl_cocco * CoccoChl & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * CoccoChl & + !----------------------------------------------------------------------- + ! SINKS: Grazing (Chl-basis) + !----------------------------------------------------------------------- + - grazingFlux_cocco * Chl2N_cocco & ! Mesozooplankton (N->Chl) + - grazingFlux_Cocco2 * Chl2N_cocco * is_3zoo2det & ! Macrozooplankton + - grazingFlux_Cocco3 * Chl2N_cocco * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,icchl) + + !=============================================================================== + ! 28. PHAEOCYSTIS NITROGEN (PhaeoN) + !=============================================================================== + ! Tracks nitrogen content of Phaeocystis (colony-forming phytoplankton). + ! Only active when enable_coccos = .true. + ! + ! Variables: + ! N_assim_phaeo : N assimilation rate [day-1] + ! lossN_p : N loss rate [day-1] + ! limitFacN_phaeo : Limiter function for N:C ratio regulation [-] + ! aggregationRate : Aggregation to detritus [day-1] + ! grazingFlux_phaeo : Mesozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_phaeo2 : Macrozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_phaeo3 : Microzooplankton grazing [mmolN m-3 day-1] + !------------------------------------------------------------------------------- + + sms(k,iphan) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Nitrogen Assimilation + !----------------------------------------------------------------------- + + N_assim_phaeo * PhaeoC & + !----------------------------------------------------------------------- + ! SINKS: DON Excretion + !----------------------------------------------------------------------- + - lossN_p * limitFacN_phaeo * PhaeoN & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * PhaeoN & + !----------------------------------------------------------------------- + ! SINKS: Grazing + !----------------------------------------------------------------------- + - grazingFlux_phaeo & ! Mesozooplankton + - grazingFlux_phaeo2 * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phaeo3 * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphan) + + !=============================================================================== + ! 29. PHAEOCYSTIS CARBON (PhaeoC) + !=============================================================================== + ! Tracks carbon content of Phaeocystis. + ! + ! Variables: + ! Cphot_phaeo : Gross photosynthesis rate [day-1] + ! phyRespRate_phaeo : Autotrophic respiration rate [day-1] + ! lossC_p : C loss rate [day-1] + ! recipQuota_phaeo : Reciprocal of N:C quota (for N->C conversion) [-] + !------------------------------------------------------------------------------- + + sms(k,iphac) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Net Photosynthesis + !----------------------------------------------------------------------- + + Cphot_phaeo * PhaeoC & ! Gross photosynthesis + !----------------------------------------------------------------------- + ! SINKS: DOC Excretion + !----------------------------------------------------------------------- + - lossC_p * limitFacN_phaeo * PhaeoC & + !----------------------------------------------------------------------- + ! SINKS: Respiration + !----------------------------------------------------------------------- + - phyRespRate_phaeo * PhaeoC & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * PhaeoC & + !----------------------------------------------------------------------- + ! SINKS: Grazing (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_phaeo * recipQuota_phaeo & ! Mesozooplankton (N->C) + - grazingFlux_phaeo2 * recipQuota_phaeo * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phaeo3 * recipQuota_phaeo * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphac) + + !=============================================================================== + ! 30. PHAEOCYSTIS CHLOROPHYLL-A (PhaeoChl) + !=============================================================================== + ! Tracks chlorophyll-a content for light harvesting and photoacclimation. + ! + ! Variables: + ! chlSynth_phaeo : Chlorophyll synthesis rate [mgChl mmolC-1 day-1] + ! KOchl_phaeo : Chlorophyll degradation rate [day-1] + ! Chl2N_phaeo : Chl:N ratio = PhaeoChl/PhaeoN [mgChl mmolN-1] + !------------------------------------------------------------------------------- + + sms(k,iphachl) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Chlorophyll Synthesis + !----------------------------------------------------------------------- + + chlSynth_phaeo * PhaeoC & ! Photoacclimation + !----------------------------------------------------------------------- + ! SINKS: Photo-oxidation + !----------------------------------------------------------------------- + - KOchl_phaeo * PhaeoChl & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * PhaeoChl & + !----------------------------------------------------------------------- + ! SINKS: Grazing (Chl-basis) + !----------------------------------------------------------------------- + - grazingFlux_phaeo * Chl2N_phaeo & ! Mesozooplankton (N->Chl) + - grazingFlux_phaeo2 * Chl2N_phaeo * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phaeo3 * Chl2N_phaeo * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphachl) + + endif ! enable_coccos + + !=============================================================================== + ! 31. DETRITAL SILICA (DetSi) + !=============================================================================== + ! Biogenic silica from diatom frustules in slow-sinking detritus. + ! + ! Variables: + ! aggregationRate : Diatom aggregation rate [day-1] + ! lossN_d : Diatom mortality/excretion rate [day-1] + ! grazingFlux_dia, grazingFlux_dia3 : Grazing on diatoms [mmolN m-3 day-1] + ! qSiN : Si:N ratio in diatoms [mmolSi mmolN-1] + ! reminSiT : Temperature-dependent dissolution [day-1] + !------------------------------------------------------------------------------- + + sms(k,idetsi) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Diatom Aggregation + !--------------------------------------------------------------------------- + + aggregationRate * DiaSi & + !--------------------------------------------------------------------------- + ! SOURCES: Diatom Excretion/Mortality + !--------------------------------------------------------------------------- + + lossN_d * limitFacN_dia * DiaSi & + !--------------------------------------------------------------------------- + ! SOURCES: Grazing on Diatoms (Si-basis) + !--------------------------------------------------------------------------- + + grazingFlux_dia3 * qSiN * is_3zoo2det & ! Microzooplankton + + grazingFlux_dia * qSiN * (1.0 - is_3zoo2det) & ! Mesozooplankton (when 3zoo disabled) + !--------------------------------------------------------------------------- + ! SINKS: Dissolution + !--------------------------------------------------------------------------- + - reminSiT * DetSi & ! Temperature-dependent + ) * dt_b + sms(k,idetsi) + + !=============================================================================== + ! 32. DISSOLVED SILICATE (DSi) + !=============================================================================== + ! Dissolved silicate available for diatom uptake. + ! Based on Schourup 2013 Eq. A3 + ! + ! Variables: + ! Si_assim : Silicic acid assimilation by diatoms [day-1] + ! reminSiT : Temperature-dependent dissolution [day-1] + ! DetSi, DetZ2Si : Detrital silica pools [mmolSi m-3] + !------------------------------------------------------------------------------- + + sms(k,isi) = ( & + !--------------------------------------------------------------------------- + ! SINKS: Biological Uptake + !--------------------------------------------------------------------------- + - Si_assim * DiaC & + !--------------------------------------------------------------------------- + ! SOURCES: Remineralization + !--------------------------------------------------------------------------- + + reminSiT * DetSi & ! Slow-sinking detritus + + reminSiT * DetZ2Si * is_3zoo2det & ! Fast-sinking detritus + ) * dt_b + sms(k,isi) + + !=============================================================================== + ! 33. DISSOLVED IRON (Fe) + !=============================================================================== + ! Tracks dissolved iron, a limiting micronutrient for phytoplankton growth. + ! + ! Key Concept: Iron cycling is coupled to nitrogen via the Fe:N ratio (Fe2N) + ! All N-based fluxes are converted to Fe equivalents + ! + ! Variables: + ! Fe2N : Intracellular Fe:N ratio [μmol Fe mmol N-1] + ! Note: Fe2N = Fe2C × 6.625 (Redfield conversion) + ! N_assim, N_assim_dia, etc. : N assimilation rates [mmol N mmol C-1 day-1] + ! lossN, lossN_d, etc. : N excretion rates [day-1] + ! limitFacN, etc. : Nutrient limitation factors [-] + ! reminN : Temperature-dependent remineralization [day-1] + ! kScavFe : Iron scavenging rate [m3 mmol C-1 day-1] + ! FreeFe : Free dissolved iron [μmol Fe m-3] + !------------------------------------------------------------------------------- + + sms(k,ife) = ( & + !--------------------------------------------------------------------------- + ! Iron Uptake/Release Coupled to Nitrogen Cycling (via Fe:N ratio) + !--------------------------------------------------------------------------- + Fe2N * ( & + !----------------------------------------------------------------------- + ! SINKS: Phytoplankton Assimilation + !----------------------------------------------------------------------- + - N_assim * PhyC & ! Small phytoplankton + - N_assim_dia * DiaC & ! Diatoms + - N_assim_cocco * CoccoC * is_coccos & ! Coccolithophores + - N_assim_phaeo * PhaeoC * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Excretion + !----------------------------------------------------------------------- + + lossN * limitFacN * PhyN & ! Small phytoplankton + + lossN_d * limitFacN_dia * DiaN & ! Diatoms + + lossN_c * limitFacN_cocco * CoccoN * is_coccos & ! Coccolithophores + + lossN_p * limitFacN_phaeo * PhaeoN * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Detrital Remineralization + !----------------------------------------------------------------------- + + reminN * arrFunc * O2Func * DetN & ! Slow-sinking detritus + + reminN * arrFunc * O2Func * DetZ2N * is_3zoo2det & ! Fast-sinking detritus + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Excretion + !----------------------------------------------------------------------- + + lossN_z * HetN & ! Mesozooplankton + + lossN_z2 * Zoo2N * is_3zoo2det & ! Macrozooplankton + + lossN_z3 * MicZooN * is_3zoo2det & ! Microzooplankton + ) & + !--------------------------------------------------------------------------- + ! SINKS: Abiotic Iron Scavenging onto Particles + !--------------------------------------------------------------------------- + - kScavFe * DetC * FreeFe & ! Slow-sinking detritus + - kScavFe * DetZ2C * FreeFe * is_3zoo2det & ! Fast-sinking detritus + ) * dt_b + sms(k,ife) + + !=============================================================================== + ! 34. PHYTOPLANKTON CALCITE (PhyCalc) + !=============================================================================== + ! Tracks calcium carbonate in living phytoplankton (coccoliths). + ! + ! Variables: + ! calcification : CaCO3 production rate [mmolCaCO3 m-3 day-1] + ! calc_loss_agg : Calcite loss to aggregation [mmolCaCO3 m-3 day-1] + ! calc_loss_gra, calc_loss_gra2, calc_loss_gra3 : Calcite loss to grazing [mmolCaCO3 m-3 day-1] + ! lossC, lossC_c : C excretion rates [day-1] + ! phyRespRate, phyRespRate_cocco : Respiration rates [day-1] + ! limitFacN, limitFacN_cocco : N:C ratio limiters [-] + !------------------------------------------------------------------------------- + + if (enable_coccos) then + !--------------------------------------------------------------------------- + ! Configuration: Coccolithophore-Specific Calcite Dynamics + !--------------------------------------------------------------------------- + sms(k,iphycal) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Calcification + !----------------------------------------------------------------------- + + calcification & ! New CaCO3 production + !----------------------------------------------------------------------- + ! SINKS: Losses from Living Cells + !----------------------------------------------------------------------- + - lossC_c * limitFacN_cocco * PhyCalc & ! Excretion/exudation + - phyRespRate_cocco * PhyCalc & ! Respiration-associated loss + - calc_loss_agg & ! Aggregation/sinking + - calc_loss_gra & ! Mesozooplankton grazing + - calc_loss_gra2 * is_3zoo2det & ! Macrozooplankton grazing + - calc_loss_gra3 * is_3zoo2det & ! Microzooplankton grazing + ) * dt_b + sms(k,iphycal) + else + !--------------------------------------------------------------------------- + ! Configuration: Generic Phytoplankton Calcite (Small Calcifiers) + !--------------------------------------------------------------------------- + sms(k,iphycal) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Calcification + !----------------------------------------------------------------------- + + calcification & + !----------------------------------------------------------------------- + ! SINKS: Losses from Living Cells + !----------------------------------------------------------------------- + - lossC * limitFacN * PhyCalc & + - phyRespRate * PhyCalc & + - calc_loss_agg & + - calc_loss_gra & + - calc_loss_gra2 * is_3zoo2det & + - calc_loss_gra3 * is_3zoo2det & + ) * dt_b + sms(k,iphycal) + endif -#if defined (__coccos) - vertChldegc(k) = vertChldegc(k) + ( & - + KOchl_cocco & - ) * recipbiostep -#endif + !=============================================================================== + ! 35. DETRITAL CALCITE (DetCalc) + !=============================================================================== + ! Tracks calcium carbonate in slow-sinking organic particles. + ! + ! Variables: + ! calc_loss_agg : Calcite from aggregation [mmolCaCO3 m-3 day-1] + ! calc_loss_gra, calc_loss_gra3 : Calcite from grazing [mmolCaCO3 m-3 day-1] + ! calc_diss_guts : Gut dissolution fraction [-] + ! calc_diss : Water column dissolution rate [day-1] + !------------------------------------------------------------------------------- + + if (enable_coccos) then + if (enable_3zoo2det) then + !----------------------------------------------------------------------- + ! Configuration: Coccolithophore Calcite with 3-Zooplankton Model + !----------------------------------------------------------------------- + sms(k,idetcal) = ( & + !------------------------------------------------------------------- + ! SOURCES: Transfer from Living Cells + !------------------------------------------------------------------- + + lossC_c * limitFacN_cocco * PhyCalc & ! Excretion + + phyRespRate_cocco * PhyCalc & ! Respiration products + + calc_loss_agg & ! Aggregation products + + calc_loss_gra3 & ! Microzooplankton grazing + !------------------------------------------------------------------- + ! SINKS: Dissolution + !------------------------------------------------------------------- + - calc_loss_gra3 * calc_diss_guts & ! Gut dissolution + - calc_diss * DetCalc & ! Water column dissolution + ) * dt_b + sms(k,idetcal) + else + !----------------------------------------------------------------------- + ! Configuration: Coccolithophore Calcite with Standard Zooplankton + !----------------------------------------------------------------------- + sms(k,idetcal) = ( & + !------------------------------------------------------------------- + ! SOURCES: Transfer from Living Cells + !------------------------------------------------------------------- + + lossC_c * limitFacN_cocco * PhyCalc & + + phyRespRate_cocco * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + !------------------------------------------------------------------- + ! SINKS: Dissolution + !------------------------------------------------------------------- + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + endif + else + if (enable_3zoo2det) then + !----------------------------------------------------------------------- + ! Configuration: Generic Phytoplankton Calcite with 3-Zooplankton + !----------------------------------------------------------------------- + sms(k,idetcal) = ( & + !------------------------------------------------------------------- + ! SOURCES: Transfer from Living Cells + !------------------------------------------------------------------- + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra3 & + !------------------------------------------------------------------- + ! SINKS: Dissolution + !------------------------------------------------------------------- + - calc_loss_gra3 * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + else + !----------------------------------------------------------------------- + ! Configuration: Generic Phytoplankton Calcite with Standard Zooplankton + !----------------------------------------------------------------------- + sms(k,idetcal) = ( & + !------------------------------------------------------------------- + ! SOURCES: Transfer from Living Cells + !------------------------------------------------------------------- + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + !------------------------------------------------------------------- + ! SINKS: Dissolution + !------------------------------------------------------------------- + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + endif + endif -!*** zooplankton1 respiration - vertrespmeso(k) = vertrespmeso(k) + ( & - + HetRespFlux & - ) * recipbiostep -#if defined (__3Zoo2Det) -!*** zooplankton2 respiration - vertrespmacro(k) = vertrespmacro(k) + ( & - + Zoo2RespFlux & - ) * recipbiostep + !=============================================================================== + ! 36. DISSOLVED OXYGEN (O2) + !=============================================================================== + ! Tracks oxygen production (photosynthesis) and consumption (respiration, + ! remineralization). + ! + ! Variables: + ! Cphot, Cphot_dia, etc. : Gross photosynthesis rates [day-1] + ! phyRespRate, phyRespRate_dia, etc. : Autotrophic respiration rates [day-1] + ! rho_C1 : DOC remineralization rate [day-1] + ! hetRespFlux, Zoo2RespFlux, MicZooRespFlux : Zooplankton respiration [mmolC m-3 day-1] + ! redO2C : O2:C stoichiometric ratio (Redfield) [-] + ! Typically ~170/122 = 1.39 mol O2/mol C + !------------------------------------------------------------------------------- + + sms(k,ioxy) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Photosynthetic Oxygen Production + !--------------------------------------------------------------------------- + + Cphot * phyC & ! Small phytoplankton + + Cphot_dia * diaC & ! Diatoms + + Cphot_cocco * CoccoC * is_coccos & ! Coccolithophores + + Cphot_phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SINKS: Autotrophic Respiration + !--------------------------------------------------------------------------- + - phyRespRate * phyC & ! Small phytoplankton + - phyRespRate_dia * diaC & ! Diatoms + - phyRespRate_cocco * CoccoC * is_coccos & ! Coccolithophores + - phyRespRate_phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SINKS: Heterotrophic Respiration and Remineralization + !--------------------------------------------------------------------------- + - rho_C1 * arrFunc * O2Func * EOC & ! DOC remineralization + - rho_C1t * DOCt * is_riverinput & + - hetRespFlux & ! Mesozooplankton + - Zoo2RespFlux * is_3zoo2det & ! Macrozooplankton + - MicZooRespFlux * is_3zoo2det & ! Microzooplankton + ) * redO2C * dt_b + sms(k,ioxy) + ! Note: redO2C converts carbon-based rates to oxygen equivalents + ! using the Redfield ratio (typically ~170/122 = 1.39 mol O2/mol C) + + if (ciso) then + + !=========================================================================== + ! 1. CARBON-13 (13C) BUDGETS + !=========================================================================== + ! Calculates 13C budgets for all carbon pools with isotope fractionation. + ! Parallel structure to total carbon budgets. + !--------------------------------------------------------------------------- + + !=========================================================================== + ! DISSOLVED INORGANIC CARBON (DIC_13) + !=========================================================================== + ! Source-minus-sink budget for 13C in dissolved inorganic carbon pool. + ! + ! SOURCES (+): + ! - Phytoplankton respiration (returns 13C to DIC) + ! - Diatom respiration + ! - DOC remineralization (aerobic respiration) + ! - Heterotroph respiration + ! - Calcite dissolution (releases 13C from CaCO3) + ! - Calcite dissolution in grazer guts + ! + ! SINKS (-): + ! - Phytoplankton photosynthesis (fixes 13C into organic matter) + ! - Diatom photosynthesis + ! - Calcification (removes 13C for CaCO3 formation) + ! + ! Variables: + ! Cphot, Cphot_Dia : Photosynthesis rates [day-1] + ! PhyC_13, DiaC_13 : Phytoplankton 13C pools [mmol13C m-3] + ! phyRespRate : Phytoplankton respiration rates [day-1] + ! rho_C1 : DOC remineralization rate [day-1] + ! arrFunc : Temperature function [-] + ! EOC_13 : Dissolved organic 13C [mmol13C m-3] + ! HetRespFlux_13 : Heterotroph respiration flux [mmol13C m-3 day-1] + ! calc_diss_13 : Calcite dissolution rate [day-1] + ! DetCalc_13 : Detrital calcite 13C [mmol13C m-3] + ! calc_loss_gra_13 : Calcite grazing flux [mmol13C m-3 day-1] + ! calc_diss_guts : Gut dissolution fraction [-] + ! calcification_13 : Calcification flux [mmol13C m-3 day-1] + ! dt_b : Biogeochemistry time step [day] + ! + ! Note: Photosynthesis preferentially takes up 12C, leaving DIC enriched in 13C + ! Respiration returns carbon with original isotopic composition + !--------------------------------------------------------------------------- + + sms(k, idic_13) = ( & + !----------------------------------------------------------------------- + ! SINKS: Carbon fixation (removes 13C-DIC) + !----------------------------------------------------------------------- + - Cphot * PhyC_13 & ! Small phyto photosynthesis + - Cphot_Dia * DiaC_13 & ! Diatom photosynthesis + ! + !----------------------------------------------------------------------- + ! SOURCES: Respiration and remineralization (returns 13C to DIC) + !----------------------------------------------------------------------- + + phyRespRate * PhyC_13 & ! Small phyto respiration + + phyRespRate_Dia * DiaC_13 & ! Diatom respiration + + rho_C1 * arrFunc * EOC_13 & ! DOC remineralization + + HetRespFlux_13 & ! Heterotroph respiration + ! + !----------------------------------------------------------------------- + ! SOURCES: Calcite dissolution (releases 13C from CaCO3) + !----------------------------------------------------------------------- + + calc_diss_13 * DetCalc_13 & ! Water column dissolution + + calc_loss_gra_13 * calc_diss_guts & ! Gut dissolution + ! + !----------------------------------------------------------------------- + ! SINKS: Calcification (removes 13C for CaCO3 formation) + !----------------------------------------------------------------------- + - calcification_13 & ! CaCO3 precipitation + ! + ) * dt_b + sms(k, idic_13) + + !=========================================================================== + ! SMALL PHYTOPLANKTON ORGANIC CARBON (PhyC_13) + !=========================================================================== + ! 13C budget for small phytoplankton biomass. + ! + ! SOURCES (+): + ! - Photosynthesis (fixes 13C-DIC into biomass) + ! + ! SINKS (-): + ! - Nutrient-stress mortality (lysis) + ! - Respiration (maintenance costs) + ! - Aggregation (particle formation) + ! - Grazing by zooplankton + ! + ! Variables: + ! lossC : Mortality rate constant [day-1] + ! limitFacN : Nutrient limitation factor [0-1] + ! aggregationRate : Aggregation rate [day-1] + ! grazingFlux_phy : Grazing flux on small phyto [mmolN m-3 day-1] + ! recipQuota_13 : 13C:N ratio [mmol13C mmolN-1] + ! + ! Note: Grazing uses recipQuota_13 to convert N-based flux to 13C flux + !--------------------------------------------------------------------------- + + sms(k, iphyc_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Photosynthetic production + !----------------------------------------------------------------------- + + Cphot * PhyC_13 & ! 13C fixation + ! + !----------------------------------------------------------------------- + ! SINKS: Mortality, respiration, and losses + !----------------------------------------------------------------------- + - lossC * limitFacN * PhyC_13 & ! Nutrient-stress mortality + - phyRespRate * PhyC_13 & ! Respiration + - aggregationRate * PhyC_13 & ! Aggregation loss + - grazingFlux_phy * recipQuota_13 & ! Grazing loss (N->C conversion) + ! + ) * dt_b + sms(k, iphyc_13) + + !=========================================================================== + ! DETRITAL ORGANIC CARBON (DetC_13) + !=========================================================================== + ! 13C budget for dead organic matter (detritus pool). + ! + ! SOURCES (+): + ! - Unassimilated grazing (sloppy feeding + egestion) + ! - Phytoplankton aggregation + ! - Diatom aggregation + ! - Heterotroph mortality + ! + ! SINKS (-): + ! - Remineralization (aerobic respiration) + ! - Assimilated grazing (efficient consumption) + ! + ! Variables: + ! grazEff : Grazing efficiency (fraction assimilated) [-] + ! hetLossFlux : Heterotroph mortality flux [mmolN m-3 day-1] + ! recipQZoo_13 : Heterotroph 13C:N ratio [mmol13C mmolN-1] + ! reminC : Detritus remineralization rate [day-1] + ! + ! Grazing Partitioning: + ! Total ingestion = Assimilated + Unassimilated + ! Assimilated: Goes to heterotroph biomass (grazEff × flux) + ! Unassimilated: Goes to detritus ((1-grazEff) × flux) + !--------------------------------------------------------------------------- + + sms(k, idetc_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Unassimilated grazing (sloppy feeding) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota_13 & ! Total small phyto grazing + - grazingFlux_phy * recipQuota_13 * grazEff & ! Minus assimilated portion + + grazingFlux_Dia * recipQuota_dia_13 & ! Total diatom grazing + - grazingFlux_Dia * recipQuota_dia_13 * grazEff & ! Minus assimilated portion + ! + !----------------------------------------------------------------------- + ! SOURCES: Aggregation and mortality + !----------------------------------------------------------------------- + + aggregationRate * phyC_13 & ! Small phyto aggregation + + aggregationRate * DiaC_13 & ! Diatom aggregation + + hetLossFlux * recipQZoo_13 & ! Heterotroph mortality + ! + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * DetC_13 & ! Aerobic respiration + ! + ) * dt_b + sms(k, idetc_13) + + !=========================================================================== + ! HETEROTROPH ORGANIC CARBON (HetC_13) + !=========================================================================== + ! 13C budget for zooplankton biomass. + ! + ! SOURCES (+): + ! - Assimilated grazing on phytoplankton + ! - Assimilated grazing on diatoms + ! + ! SINKS (-): + ! - Mortality (density-dependent) + ! - Non-predatory losses (diseases, senescence) + ! - Respiration (metabolic costs) + ! + ! Variables: + ! lossC_z : Non-predatory loss rate [day-1] + ! hetRespFlux_13: Heterotroph respiration flux [mmol13C m-3 day-1] + ! + ! Note: Grazing efficiency (grazEff) determines assimilation fraction + ! Typical values: 0.6-0.8 (60-80% assimilated) + !--------------------------------------------------------------------------- + + sms(k, ihetc_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Assimilated food + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota_13 * grazEff & ! Small phyto consumption + + grazingFlux_Dia * recipQuota_dia_13 * grazEff & ! Diatom consumption + ! + !----------------------------------------------------------------------- + ! SINKS: Mortality and respiration + !----------------------------------------------------------------------- + - hetLossFlux * recipQZoo_13 & ! Mortality flux + - lossC_z * HetC_13 & ! Non-predatory losses + - hetRespFlux_13 & ! Respiration + ! + ) * dt_b + sms(k, ihetc_13) + + !=========================================================================== + ! DISSOLVED ORGANIC CARBON (EOC_13) + !=========================================================================== + ! 13C budget for dissolved organic carbon pool. + ! + ! SOURCES (+): + ! - Phytoplankton exudation (nutrient-stress losses) + ! - Diatom exudation + ! - Detritus remineralization (solubilization) + ! - Heterotroph exudation (sloppy feeding, excretion) + ! - River input (terrestrial DOC) + ! + ! SINKS (-): + ! - Remineralization (microbial respiration) + ! + ! Variables: + ! lossC, lossC_d : Exudation rate constants [day-1] + ! limitFacN : Nutrient limitation factors [0-1] + ! LocRiverDOC : River DOC input flux [mmolC m-3 day-1] + ! r_iorg_13 : River 13C:12C ratio (isotopic signature) [-] + ! + ! DOC Pool Characteristics: + ! - Labile fraction: Days to weeks turnover + ! - Semi-labile fraction: Months to years turnover + ! - Model uses bulk DOC with single remineralization rate + ! + ! River Isotope Signature: + ! - Terrestrial organic matter typically depleted in 13C + ! - δ13C ≈ -27‰ for C3 plants, -13‰ for C4 plants + ! - Marine phytoplankton: δ13C ≈ -20 to -22‰ + !--------------------------------------------------------------------------- + + sms(k, idoc_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Exudation and solubilization + !----------------------------------------------------------------------- + + lossC * limitFacN * phyC_13 & ! Small phyto exudation + + lossC_d * limitFacN_dia * DiaC_13 & ! Diatom exudation + + reminC * arrFunc * DetC_13 & ! Detritus solubilization + + lossC_z * HetC_13 & ! Heterotroph exudation + ! + !----------------------------------------------------------------------- + ! SOURCES: River input (terrestrial DOC) + !----------------------------------------------------------------------- + + LocRiverDOC * r_iorg_13 & ! River 13C input + ! + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - rho_c1 * arrFunc * EOC_13 & ! Microbial respiration + ! + ) * dt_b + sms(k, idoc_13) + + !=========================================================================== + ! DIATOM ORGANIC CARBON (DiaC_13) + !=========================================================================== + ! 13C budget for diatom biomass (large phytoplankton). + ! + ! Structure identical to small phytoplankton (section 1.2) + ! with diatom-specific parameters and fluxes. + !--------------------------------------------------------------------------- + + sms(k, idiac_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Photosynthetic production + !----------------------------------------------------------------------- + + Cphot_dia * DiaC_13 & ! 13C fixation + ! + !----------------------------------------------------------------------- + ! SINKS: Mortality, respiration, and losses + !----------------------------------------------------------------------- + - lossC_d * limitFacN_dia * DiaC_13 & ! Nutrient-stress mortality + - phyRespRate_dia * DiaC_13 & ! Respiration + - aggregationRate * DiaC_13 & ! Aggregation loss + - grazingFlux_dia * recipQuota_dia_13 & ! Grazing loss + ! + ) * dt_b + sms(k, idiac_13) + + !=========================================================================== + ! PHYTOPLANKTON CALCITE (PhyCalc_13) + !=========================================================================== + ! 13C budget for calcium carbonate associated with living phytoplankton. + ! + ! SOURCES (+): + ! - Calcification (CaCO3 precipitation on cells) + ! + ! SINKS (-): + ! - Nutrient-stress mortality (CaCO3 to detritus) + ! - Cell death respiration (CaCO3 to detritus) + ! - Aggregation (CaCO3 incorporated in aggregates) + ! - Grazing (CaCO3 consumed with cells) + ! + ! Variables: + ! calcification_13 : 13C calcification flux [mmol13C m-3 day-1] + ! phyCalc_13 : Phytoplankton calcite 13C [mmol13C m-3] + ! calc_loss_agg_13 : Aggregation loss flux [mmol13C m-3 day-1] + ! calc_loss_gra_13 : Grazing loss flux [mmol13C m-3 day-1] + ! + ! Calcite Isotope Fractionation: + ! - Small enrichment in 13C relative to DIC (~+1‰) + ! - Temperature-dependent fractionation + ! - Important for paleoclimate proxies (foraminifera, coccoliths) + !--------------------------------------------------------------------------- + + sms(k, iphycal_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Calcification + !----------------------------------------------------------------------- + + calcification_13 & ! CaCO3 precipitation + ! + !----------------------------------------------------------------------- + ! SINKS: Mortality and losses + !----------------------------------------------------------------------- + - lossC * limitFacN * phyCalc_13 & ! Mortality to detritus + - phyRespRate * phyCalc_13 & ! Death to detritus + - calc_loss_agg_13 & ! Aggregation + - calc_loss_gra_13 & ! Grazing + ! + ) * dt_b + sms(k, iphycal_13) + + !=========================================================================== + ! DETRITAL CALCITE (DetCalc_13) + !=========================================================================== + ! 13C budget for calcium carbonate in detritus/particles. + ! + ! SOURCES (+): + ! - Phytoplankton mortality (CaCO3 from dead cells) + ! - Cell death (respiratory loss to detritus) + ! - Aggregation (CaCO3 in aggregates) + ! - Grazing (CaCO3 in fecal pellets) + ! + ! SINKS (-): + ! - Dissolution in water column + ! - Dissolution in grazer guts + ! + ! Variables: + ! calc_diss_guts : Fraction dissolved in guts (typically 0.1-0.5) [-] + ! + ! Calcite Dissolution: + ! - Thermodynamically driven (saturation state dependent) + ! - Faster in undersaturated waters (deep ocean, high CO2) + ! - Gut dissolution: Acidic environment accelerates dissolution + ! - Returns 13C to DIC pool (source for DIC_13 budget) + !--------------------------------------------------------------------------- + + sms(k, idetcal_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Mortality and transfer from living cells + !----------------------------------------------------------------------- + + lossC * limitFacN * phyCalc_13 & ! Mortality + + phyRespRate * phyCalc_13 & ! Death + + calc_loss_agg_13 & ! Aggregation + + calc_loss_gra_13 & ! Grazing (to fecal pellets) + ! + !----------------------------------------------------------------------- + ! SINKS: Dissolution + !----------------------------------------------------------------------- + - calc_loss_gra_13 * calc_diss_guts & ! Gut dissolution + - calc_diss_13 * DetCalc_13 & ! Water column dissolution + ! + ) * dt_b + sms(k, idetcal_13) + + if (ciso_14) then + + if (ciso_organic_14) then + + !=================================================================== + ! CARBON-14 (14C) BUDGETS + !=================================================================== + ! Calculates 14C budgets for radiocarbon applications. + ! Structure identical to 13C budgets (sections 1.1-1.8). + ! + ! Additional Consideration: + ! - Radioactive decay (half-life 5,730 years) + ! - Decay term handled separately in forcing module + ! - Bomb radiocarbon (anthropogenic 14C pulse) + ! + ! Applications: + ! - Ocean ventilation age (Δ14C) + ! - Carbon residence time + ! - Mixing timescales + ! - Model validation (WOCE/CLIVAR 14C data) + ! + ! Notation: + ! All variables end in _14 (e.g., PhyC_14, DiaC_14) + ! Structure parallels 13C budgets exactly + !------------------------------------------------------------------- + + !=================================================================== + ! DIC_14 + !=================================================================== + sms(k, idic_14) = ( & + - Cphot * PhyC_14 & + + phyRespRate * PhyC_14 & + - Cphot_Dia * DiaC_14 & + + phyRespRate_Dia * DiaC_14 & + + rho_C1 * arrFunc * EOC_14 & + + HetRespFlux_14 & + + calc_diss_14 * DetCalc_14 & + + calc_loss_gra_14 * calc_diss_guts & + - calcification_14 & + ) * dt_b + sms(k, idic_14) + + !=================================================================== + ! PhyC_14 + !=================================================================== + sms(k, iphyc_14) = ( & + + Cphot * PhyC_14 & + - lossC * limitFacN * PhyC_14 & + - phyRespRate * PhyC_14 & + - aggregationRate * PhyC_14 & + - grazingFlux_phy * recipQuota_14 & + ) * dt_b + sms(k, iphyc_14) + + !=================================================================== + ! DetC_14 + !=================================================================== + sms(k, idetc_14) = ( & + + grazingFlux_phy * recipQuota_14 & + - grazingFlux_phy * recipQuota_14 * grazEff & + + grazingFlux_Dia * recipQuota_dia_14 & + - grazingFlux_Dia * recipQuota_dia_14 * grazEff & + + aggregationRate * phyC_14 & + + aggregationRate * DiaC_14 & + + hetLossFlux * recipQZoo_14 & + - reminC * arrFunc * DetC_14 & + ) * dt_b + sms(k, idetc_14) + + !=================================================================== + ! HetC_14 + !=================================================================== + sms(k, ihetc_14) = ( & + + grazingFlux_phy * recipQuota_14 * grazEff & + + grazingFlux_Dia * recipQuota_dia_14 * grazEff & + - hetLossFlux * recipQZoo_14 & + - lossC_z * HetC_14 & + - hetRespFlux_14 & + ) * dt_b + sms(k, ihetc_14) + + !=================================================================== + ! EOC_14 + !=================================================================== + sms(k, idoc_14) = ( & + + lossC * limitFacN * phyC_14 & + + lossC_d * limitFacN_dia * DiaC_14 & + + reminC * arrFunc * DetC_14 & + + lossC_z * HetC_14 & + - rho_c1 * arrFunc * EOC_14 & + + LocRiverDOC * r_iorg_14 & + ) * dt_b + sms(k, idoc_14) + + !=================================================================== + ! DiaC_14 + !=================================================================== + sms(k, idiac_14) = ( & + + Cphot_dia * DiaC_14 & + - lossC_d * limitFacN_dia * DiaC_14 & + - phyRespRate_dia * DiaC_14 & + - aggregationRate * DiaC_14 & + - grazingFlux_dia * recipQuota_dia_14 & + ) * dt_b + sms(k, idiac_14) + + !=================================================================== + ! PhyCalc_14 + !=================================================================== + sms(k, iphycal_14) = ( & + + calcification_14 & + - lossC * limitFacN * phyCalc_14 & + - phyRespRate * phyCalc_14 & + - calc_loss_agg_14 & + - calc_loss_gra_14 & + ) * dt_b + sms(k, iphycal_14) + + !=================================================================== + ! DetCalc_14 + !=================================================================== + sms(k, idetcal_14) = ( & + + lossC * limitFacN * phyCalc_14 & + + phyRespRate * phyCalc_14 & + + calc_loss_agg_14 & + + calc_loss_gra_14 & + - calc_loss_gra_14 * calc_diss_guts & + - calc_diss_14 * DetCalc_14 & + ) * dt_b + sms(k, idetcal_14) + + else + + !=================================================================== + ! ABIOTIC DIC_14 (SIMPLIFIED MODE) + !=================================================================== + ! "Abiotic" 14C tracking without explicit organic pools + ! DIC_14 tracks total carbon with radioactive decay only + ! + ! Use Case: + ! - Simplified radiocarbon tracer + ! - Tracks ventilation/mixing without biology + ! - Computationally efficient + ! - Decay handled in forcing module (recom_forcing) + ! + ! Equation: + ! DIC_14 changes identically to DIC (conservative tracer) + ! Plus: Radioactive decay (handled separately) + ! + ! Limitation: + ! - No isotope fractionation during biological processes + ! - Cannot capture biological isotope signals + ! - Suitable only for physical circulation studies + !------------------------------------------------------------------- + + sms(k, idic_14) = sms(k, idic) + + end if ! ciso_organic_14 + + end if ! ciso_14 + + end if ! ciso + + !------------------------------------------------------------------------------- + ! DIAGNOSTIC ACCUMULATION INITIALIZATION + !------------------------------------------------------------------------------- + ! Calculate averaging weight for accumulating diagnostics over biogeochemical + ! sub-time steps. + ! + ! Variables: + ! recipbiostep : Reciprocal of number of bio sub-steps (averaging weight) [-] + ! biostep : Number of biogeochemistry steps per physics step [-] + ! + ! Averaging Approach: + ! Each sub-step contributes: (1/biostep) × rate + ! After biostep iterations: average rate over physics time step + ! + ! Example: + ! If biostep = 4 (4 bio steps per physics step) + ! recipbiostep = 0.25 + ! Each contribution weighted by 0.25 + ! Sum of 4 contributions = time-averaged rate + !------------------------------------------------------------------------------- + + recipbiostep = 1.d0 / real(biostep) + + if (Diags) then + + !=========================================================================== + ! PRIMARY PRODUCTION DIAGNOSTICS + !=========================================================================== + ! Net Primary Production (NPP) = Gross Production - Autotrophic Respiration + ! Gross Primary Production (GPP) = Photosynthetic carbon fixation only + ! + ! NPP represents carbon available for: + ! - Growth (biomass increase) + ! - Exudation (DOC production) + ! - Grazing by herbivores + ! + ! Units: mmolC m-3 day-1 + !--------------------------------------------------------------------------- + + !=========================================================================== + ! NET PRIMARY PRODUCTION (NPP) + !=========================================================================== + ! NPP = Photosynthesis - Respiration + ! Carbon available after meeting metabolic maintenance costs + ! + ! Variables (Small phytoplankton): + ! vertNPPn(k) : Time-averaged NPP for small phyto [mmolC m-3 day-1] + ! Cphot : Carbon-specific photosynthesis rate [day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! PhyRespRate : Respiration rate [day-1] + ! + ! Ecological Interpretation: + ! High NPP: Nutrient replete, optimal growth conditions + ! Low NPP: Nutrient/light limited, high respiration costs + ! Negative NPP: Respiration exceeds photosynthesis (rare, stress) + ! + ! Validation Targets: + ! - 14C uptake measurements + ! - Satellite-based NPP estimates (VGPM, CbPM, CAFE) + ! - Time series stations (HOT, BATS) + ! - Typical range: 0.1-10 mmolC m-3 day-1 (surface) + !--------------------------------------------------------------------------- + + ! Small phytoplankton NPP + vertNPPn(k) = vertNPPn(k) + ( & + + Cphot * PhyC & ! Photosynthetic production + - PhyRespRate * PhyC & ! Minus respiration costs + ) * recipbiostep + + ! Diatom NPP + vertNPPd(k) = vertNPPd(k) + ( & + + Cphot_dia * DiaC & + - PhyRespRate_dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore NPP + vertNPPc(k) = vertNPPc(k) + ( & + + Cphot_cocco * CoccoC & + - PhyRespRate_cocco * CoccoC & + ) * recipbiostep + + ! Phaeocystis NPP + vertNPPp(k) = vertNPPp(k) + ( & + + Cphot_phaeo * PhaeoC & + - PhyRespRate_phaeo * PhaeoC & + ) * recipbiostep + endif + + !=========================================================================== + ! GROSS PRIMARY PRODUCTION (GPP) + !=========================================================================== + ! GPP = Total photosynthetic carbon fixation (before respiration) + ! Represents maximum potential carbon uptake + ! + ! Relationship: + ! GPP = NPP + Respiration + ! Growth efficiency = NPP / GPP (typically 0.6-0.8) + ! + ! Uses: + ! - Calculate carbon use efficiency + ! - Compare to oxygen evolution (photosynthetic quotient) + ! - Understand temperature effects (GPP and R differ) + ! + ! Typical Values: + ! Surface: 1-20 mmolC m-3 day-1 + ! Deep chlorophyll max: 0.1-5 mmolC m-3 day-1 + ! Below euphotic zone: <0.01 mmolC m-3 day-1 + !--------------------------------------------------------------------------- + + ! Small phytoplankton GPP + vertGPPn(k) = vertGPPn(k) + ( & + + Cphot * PhyC & ! Total photosynthetic fixation + ) * recipbiostep + + ! Diatom GPP + vertGPPd(k) = vertGPPd(k) + ( & + + Cphot_dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore GPP + vertGPPc(k) = vertGPPc(k) + ( & + + Cphot_cocco * CoccoC & + ) * recipbiostep + + ! Phaeocystis GPP + vertGPPp(k) = vertGPPp(k) + ( & + + Cphot_phaeo * PhaeoC & + ) * recipbiostep + endif + + !=========================================================================== + ! NET NITROGEN ASSIMILATION + !=========================================================================== + ! Net nitrogen uptake = Assimilation - Exudation losses + ! Represents nitrogen incorporation into biomass + ! + ! Variables (Small phytoplankton): + ! vertNNAn(k) : Net N assimilation for small phyto [mmolN m-3 day-1] + ! N_assim : N-specific assimilation rate [mmolN mmolC-1 day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! lossN : N exudation rate constant [day-1] + ! limitFacN : Nutrient limitation factor [0-1] + ! PhyN : Small phytoplankton nitrogen [mmolN m-3] + ! + ! Ecological Interpretation: + ! Positive: Net nitrogen accumulation (growth) + ! Negative: Net nitrogen loss (stress-induced exudation) + ! Zero: Balanced uptake and loss (steady state) + ! + ! Relationship to C:N Ratio: + ! Net N assimilation / NPP = change in N:C quota + ! High ratio -> decreasing C:N (N accumulation) + ! Low ratio -> increasing C:N (N limitation) + ! + ! Validation: + ! - 15N tracer studies + ! - Nutrient depletion experiments + ! - Typical range: 0.01-2 mmolN m-3 day-1 + !--------------------------------------------------------------------------- + + ! Small phytoplankton net N assimilation + vertNNAn(k) = vertNNAn(k) + ( & + + N_assim * PhyC & ! Nitrogen uptake from DIN + - lossN * limitFacN * PhyN & ! Minus exudation (stress-induced) + ) * recipbiostep + + ! Diatom net N assimilation + vertNNAd(k) = vertNNAd(k) + ( & + + N_assim_dia * DiaC & + - lossN * limitFacN_dia * DiaN & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore net N assimilation + vertNNAc(k) = vertNNAc(k) + ( & + + N_assim_cocco * CoccoC & + - lossN * limitFacN_cocco * CoccoN & + ) * recipbiostep + + ! Phaeocystis net N assimilation + vertNNAp(k) = vertNNAp(k) + ( & + + N_assim_phaeo * PhaeoC & + - lossN * limitFacN_phaeo * PhaeoN & + ) * recipbiostep + endif + + !=========================================================================== + ! CHLOROPHYLL DEGRADATION RATES + !=========================================================================== + ! Tracks chlorophyll turnover rates (photodamage + senescence) + ! Important for understanding chlorophyll:carbon dynamics + ! + ! Variables: + ! vertChldegn(k) : Small phyto Chl degradation rate [day-1] + ! KOchl : Chlorophyll degradation rate coefficient [day-1] + ! + ! Rate Components: + ! - Base degradation: Constant senescence (~0.01-0.05 day-1) + ! - Photodamage: Light-dependent additional degradation + ! - Total: KOchl = base + photodamage component + ! + ! Ecological Significance: + ! - High rates: Photodamage stress, high light + ! - Low rates: Low light, minimal photoinhibition + ! - Affects Chl:C ratio and satellite retrievals + ! + ! Applications: + ! - Understand Chl:C variability + ! - Validate photoacclimation dynamics + ! - Interpret satellite chlorophyll trends + ! + ! Note: Changed from gross N-assimilation diagnostic (previous version) + !--------------------------------------------------------------------------- + + ! Small phytoplankton Chl degradation + vertChldegn(k) = vertChldegn(k) + ( & + + KOchl & ! Degradation rate [day-1] + ) * recipbiostep + + ! Diatom Chl degradation + vertChldegd(k) = vertChldegd(k) + ( & + + KOchl_dia & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore Chl degradation + vertChldegc(k) = vertChldegc(k) + ( & + + KOchl_cocco & + ) * recipbiostep + + ! Phaeocystis Chl degradation + vertChldegp(k) = vertChldegp(k) + ( & + + KOchl_phaeo & + ) * recipbiostep + endif + +!-------------------------------------------------------------------------------------------------------------------------------------- + +! GRAZING FLUXES +! Only for the case with detritus grazing, not without detritus grazing, because this output is probably anyway not needed as a default. +! diagnostics, combined from Onur and Cara, modified by Miriam -!*** zooplankton3 respiration - vertrespmicro(k) = vertrespmicro(k) + ( & - + MicZooRespFlux & - ) * recipbiostep -#endif -!*** calc_diss - vertcalcdiss(k) = vertcalcdiss(k) + ( & - + calc_diss * DetCalc & - ) * recipbiostep + if (Grazing_detritus) then -!*** aggregation by small phytoplankton - vertaggn(k) = vertaggn(k) + ( & - + aggregationrate * PhyC & +!=========================================================================== +! MESOZOOPLANKTON GRAZING +!=========================================================================== +! Tracks grazing by mesozooplankton (100-2000 μm) on multiple prey types +! Central trophic link connecting primary producers to higher consumers +! +! Variables: +! vertgrazmeso_tot(k) : Total assimilated grazing [mmolC m-3 day-1] +! vertgrazmeso_n(k) : Grazing on nanophytoplankton [mmolC m-3 day-1] +! vertgrazmeso_d(k) : Grazing on diatoms [mmolC m-3 day-1] +! vertgrazmeso_c(k) : Grazing on coccolithophores [mmolC m-3 day-1] +! vertgrazmeso_p(k) : Grazing on Phaeocystis [mmolC m-3 day-1] +! vertgrazmeso_det(k) : Grazing on detritus 1 [mmolC m-3 day-1] +! vertgrazmeso_det2(k) : Grazing on detritus 2 [mmolC m-3 day-1] +! vertgrazmeso_mic(k) : Grazing on microzooplankton [mmolC m-3 day-1] +! +! Prey Composition: +! PHY : Nanophytoplankton (2-20 μm) - primary prey +! DIA : Diatoms (>20 μm) - silicified cells +! COCCO : Coccolithophores - calcifying cells (optional) +! PHAEO : Phaeocystis colonies (optional) +! DET : Detritus type 1 - particulate organic matter +! DET2 : Detritus type 2 - larger particles (optional) +! MICZOO : Microzooplankton - intraguild predation (optional) +! +! Ecological Significance: +! - Grazing efficiency (grazEff): 30-70%, rest to fecal pellets +! - Prey selection via Holling Type II/III functional response +! - Major pathway for carbon export via fecal pellets +! - Controls phytoplankton bloom magnitude/duration +! +! Validation: +! - Gut content analysis & pigment measurements +! - Dilution experiments (Landry-Hassett method) +! - Typical rates: 0.01-10 mmolC m-3 day-1 +! - Clearance rates: 1-100 mL ind-1 day-1 +!--------------------------------------------------------------------------- + + ! Total assimilated grazing (with efficiency applied) + vertgrazmeso_tot(k) = vertgrazmeso_tot(k) + ( & + + grazingFlux_phy * recipQuota * grazEff & ! Nanophytoplankton + + grazingFlux_Dia * recipQuota_Dia * grazEff & ! Diatoms + + grazingFlux_Det * recipDet * grazEff & ! Detritus 1 ) * recipbiostep + + if (enable_coccos) then + vertgrazmeso_tot(k) = vertgrazmeso_tot(k) + ( & + + grazingFlux_Cocco * recipQuota_Cocco * grazEff & ! Coccolithophores + + grazingFlux_Phaeo * recipQuota_Phaeo * grazEff & ! Phaeocystis + ) * recipbiostep + endif -!*** aggregation by diatoms - vertaggd(k) = vertaggd(k) + ( & - + aggregationrate * DiaC & - ) * recipbiostep + if (enable_3zoo2det) then + vertgrazmeso_tot(k) = vertgrazmeso_tot(k) + ( & + + GrazingFlux_DetZ2 * recipDet2 * grazEff & ! Detritus 2 + + grazingFlux_miczoo * recipQZoo3 * grazEff & ! Microzooplankton + ) * recipbiostep + endif -#if defined (__coccos) -!*** aggregation by coccolithophores - vertaggc(k) = vertaggc(k) + ( & - + aggregationrate * CoccoC & + ! Prey-specific mortality (loss terms, no efficiency applied) + ! These track carbon removal from each prey population + + ! Small phytoplankton mortality + vertgrazmeso_n(k) = vertgrazmeso_n(k) + ( & + + grazingFlux_phy * recipQuota & ) * recipbiostep -#endif - -!*** excrection of DOC by phytoplankton - vertdocexn(k) = vertdocexn(k) + ( & - + lossC * limitFacN * phyC & + + ! Diatom mortality + vertgrazmeso_d(k) = vertgrazmeso_d(k) + ( & + + grazingFlux_dia * recipQuota_dia & ) * recipbiostep -!*** excrection of DOC by diatoms - vertdocexd(k) = vertdocexd(k) + ( & - + lossC_d * limitFacN_dia * DiaC & - ) * recipbiostep - -#if defined (__coccos) -!*** excretion of DOC by coccolithophores - vertdocexc(k) = vertdocexc(k) + ( & - + lossC_c * limitFacN_cocco * CoccoC & - ) * recipbiostep -#endif + if (enable_coccos) then + ! Coccolithophore mortality + vertgrazmeso_c(k) = vertgrazmeso_c(k) + ( & + + grazingFlux_Cocco * recipQuota_cocco & + ) * recipbiostep -!*** calcification - vertcalcif(k) = vertcalcif(k) + ( & - + calcification & - ) * recipbiostep + ! Phaeocystis mortality + vertgrazmeso_p(k) = vertgrazmeso_p(k) + ( & + + grazingFlux_Phaeo * recipQuota_Phaeo & + ) * recipbiostep + endif -! phy respiration - vertrespn(k) = vertrespn(k) + ( & - + PhyRespRate * PhyC & + ! Detritus 1 consumption + vertgrazmeso_det(k) = vertgrazmeso_det(k) + ( & + + grazingFlux_Det * recipDet & ) * recipbiostep + + if (enable_3zoo2det) then + ! Microzooplankton mortality (intraguild predation) + vertgrazmeso_mic(k) = vertgrazmeso_mic(k) + ( & + + grazingFlux_miczoo * recipQZoo3 & + ) * recipbiostep + + ! Detritus 2 consumption + vertgrazmeso_det2(k) = vertgrazmeso_det2(k) + ( & + + GrazingFlux_DetZ2 * recipDet2 & + ) * recipbiostep + endif -! dia respiration - vertrespd(k) = vertrespd(k) + ( & - + PhyRespRate_dia * DiaC & - ) * recipbiostep - -#if defined (__coccos) -! cocco resipration - vertrespc(k) = vertrespc(k) + ( & - + PhyRespRate_cocco * CoccoC & - ) * recipbiostep -#endif -endif - end do ! Main vertikal loop ends -!------------------------------------------------------------------------------- -! Remineralization from the sediments into the bottom layer -!*** DIN *** -!< decayRateBenN: Remineralization rate for benthic N [day^-1] -!< LocBenthos(1): Vertically integrated N concentration in benthos (1 layer) [mmolN/m^2] - decayBenthos(1) = decayRateBenN * LocBenthos(1) - LocBenthos(1) = LocBenthos(1) - decaybenthos(1) * dt_b ! remove from benthos (flux) +!=========================================================================== +! MACROZOOPLANKTON GRAZING (KRILL) +!=========================================================================== +! Tracks grazing by macrozooplankton (2-20 mm), often dominated by krill +! Top mesozooplankton predator with omnivorous feeding strategy +! +! Variables: +! vertgrazmacro_tot(k) : Total assimilated grazing [mmolC m-3 day-1] +! vertgrazmacro_n(k) : Grazing on small phytoplankton [mmolC m-3 day-1] +! vertgrazmacro_d(k) : Grazing on diatoms [mmolC m-3 day-1] +! vertgrazmacro_c(k) : Grazing on coccolithophores [mmolC m-3 day-1] +! vertgrazmacro_p(k) : Grazing on Phaeocystis [mmolC m-3 day-1] +! vertgrazmacro_mes(k) : Grazing on mesozooplankton [mmolC m-3 day-1] +! vertgrazmacro_mic(k) : Grazing on microzooplankton [mmolC m-3 day-1] +! vertgrazmacro_det(k) : Grazing on detritus 1 [mmolC m-3 day-1] +! vertgrazmacro_det2(k) : Grazing on detritus 2 [mmolC m-3 day-1] +! +! Prey Composition: +! PHY : Small phytoplankton - supplementary prey +! DIA : Diatoms - preferred prey in productive waters +! COCCO : Coccolithophores (optional) +! PHAEO : Phaeocystis colonies (optional) +! HET : Mesozooplankton - carnivory/cannibalism +! MICZOO : Microzooplankton - smaller zooplankton +! DET : Detritus 1 - opportunistic feeding +! DET2 : Detritus 2 - larger particles +! +! Ecological Significance: +! - Grazing efficiency (grazEff2): typically 30-60% +! - Major prey for fish, seabirds, marine mammals +! - Produces large, fast-sinking fecal pellets +! - Vertical migration enhances carbon export +! - Key species: Antarctic krill (Euphausia superba) +! +! Validation: +! - Net tows & acoustic surveys for biomass +! - Feeding experiments with size-fractionated prey +! - Typical rates: 0.1-50 mmolC m-3 day-1 +! - Individual ingestion: 10-100% body C day-1 +!--------------------------------------------------------------------------- + + if (enable_3zoo2det) then + + ! Total assimilated grazing (with efficiency applied) + vertgrazmacro_tot(k) = vertgrazmacro_tot(k) + ( & + + grazingFlux_phy2 * recipQuota * grazEff2 & ! Small phytoplankton + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & ! Diatoms + + grazingFlux_het2 * recipQZoo * grazEff2 & ! Mesozooplankton + + grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & ! Microzooplankton + + grazingFlux_Det2 * recipDet * grazEff2 & ! Detritus 1 + + grazingFlux_DetZ22 * recipDet2 * grazEff2 & ! Detritus 2 + ) * recipbiostep + + if (enable_coccos) then + vertgrazmacro_tot(k) = vertgrazmacro_tot(k) + ( & + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & ! Coccolithophores + + grazingFlux_Phaeo2 * recipQuota_Phaeo * grazEff2 & ! Phaeocystis + ) * recipbiostep + endif -!*** DIC *** -!< decayRateBenC: Remineralization rate for benthic C [day^-1] -!< LocBenthos(2): Vertically integrated C concentration in benthos (1 layer) [mmolC/m^2] - decayBenthos(2) = decayRateBenC * LocBenthos(2) - LocBenthos(2) = LocBenthos(2) - decaybenthos(2) * dt_b + ! Prey-specific mortality (loss terms, no efficiency applied) + ! These track carbon removal from each prey population + + ! Small phytoplankton mortality + vertgrazmacro_n(k) = vertgrazmacro_n(k) + ( & + + grazingFlux_phy2 * recipQuota & + ) * recipbiostep + + ! Diatom mortality + vertgrazmacro_d(k) = vertgrazmacro_d(k) + ( & + + grazingFlux_Dia2 * recipQuota_Dia & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore mortality + vertgrazmacro_c(k) = vertgrazmacro_c(k) + ( & + + grazingFlux_Cocco2 * recipQuota_cocco & + ) * recipbiostep + + ! Phaeocystis mortality + vertgrazmacro_p(k) = vertgrazmacro_p(k) + ( & + + grazingFlux_Phaeo2 * recipQuota_Phaeo & + ) * recipbiostep + endif + + ! Mesozooplankton mortality (carnivory) + vertgrazmacro_mes(k) = vertgrazmacro_mes(k) + ( & + + grazingFlux_het2 * recipQZoo & + ) * recipbiostep + + ! Detritus 1 consumption + vertgrazmacro_det(k) = vertgrazmacro_det(k) + ( & + + grazingFlux_Det2 * recipDet & + ) * recipbiostep + + ! Microzooplankton mortality + vertgrazmacro_mic(k) = vertgrazmacro_mic(k) + ( & + + grazingFlux_miczoo2 * recipQZoo3 & + ) * recipbiostep + + ! Detritus 2 consumption + vertgrazmacro_det2(k) = vertgrazmacro_det2(k) + ( & + + GrazingFlux_DetZ22 * recipDet2 & + ) * recipbiostep + + endif -!*** Si *** -!< decayRateBenSi: Remineralization rate for benthic Si [day^-1] -!< LocBenthos(3) : Vertically integrated N concentration in benthos (1 layer) [mmolSi/m^2] - decayBenthos(3) = decayRateBenSi * LocBenthos(3) ! [1/day] * [mmolSi/m2] -> [mmolSi/m2/day] - LocBenthos(3) = LocBenthos(3) - decaybenthos(3) * dt_b +!=========================================================================== +! MICROZOOPLANKTON GRAZING +!=========================================================================== +! Tracks grazing by microzooplankton (20-200 μm), mainly ciliates/dinoflagellates +! Critical link between picoplankton and mesozooplankton +! +! Variables: +! vertgrazmicro_tot(k) : Total assimilated grazing [mmolC m-3 day-1] +! vertgrazmicro_n(k) : Grazing on nanophytoplankton [mmolC m-3 day-1] +! vertgrazmicro_d(k) : Grazing on diatoms [mmolC m-3 day-1] +! vertgrazmicro_c(k) : Grazing on coccolithophores [mmolC m-3 day-1] +! vertgrazmicro_p(k) : Grazing on Phaeocystis [mmolC m-3 day-1] +! +! Prey Composition: +! PHY : Snall phytoplankton (2-20 μm) - primary prey +! DIA : Small diatoms - when available +! COCCO : Coccolithophores - calcifying prey (optional) +! PHAEO : Phaeocystis colonies/single cells (optional) +! +! Ecological Significance: +! - Grazing efficiency (grazEff3): typically 40-70% +! - Consumes 60-100% of primary production in oligotrophic waters +! - High growth rates (1-2 doublings day-1 at 20°C) +! - Size-selective feeding (optimal prey 10-50% predator size) +! - Regenerates nutrients in upper water column +! +! Validation: +! - Dilution experiments (most common method) +! - Epifluorescence microscopy for biomass +! - Typical rates: 0.01-5 mmolC m-3 day-1 +! - Clearance rates: 10-10,000 nL ind-1 hour-1 +!--------------------------------------------------------------------------- + + if (enable_3zoo2det) then + + ! Total assimilated grazing (with efficiency applied) + vertgrazmicro_tot(k) = vertgrazmicro_tot(k) + ( & + + grazingFlux_phy3 * recipQuota * grazEff3 & ! Small phytoplankton + + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & ! Diatoms + ) * recipbiostep + + if (enable_coccos) then + vertgrazmicro_tot(k) = vertgrazmicro_tot(k) + ( & + + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & ! Coccolithophores + + grazingFlux_Phaeo3 * recipQuota_Phaeo * grazEff3 & ! Phaeocystis + ) * recipbiostep + endif + + ! Prey-specific mortality (loss terms, no efficiency applied) + ! These track carbon removal from each prey population + + ! Small phytoplankton mortality + vertgrazmicro_n(k) = vertgrazmicro_n(k) + ( & + + grazingFlux_phy3 * recipQuota & + ) * recipbiostep + + ! Diatom mortality + vertgrazmicro_d(k) = vertgrazmicro_d(k) + ( & + + grazingFlux_Dia3 * recipQuota_Dia & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore mortality + vertgrazmicro_c(k) = vertgrazmicro_c(k) + ( & + + grazingFlux_Cocco3 * recipQuota_cocco & + ) * recipbiostep + + ! Phaeocystis mortality + vertgrazmicro_p(k) = vertgrazmicro_p(k) + ( & + + grazingFlux_Phaeo3 * recipQuota_Phaeo & + ) * recipbiostep + endif + + endif + + end if ! Grazing_detritus + +!=========================================================================== +! DISSOLUTION AND REMINERALIZATION ! R2OMIP +!=========================================================================== + + vertDISSOC(k) = vertDISSOC(k) + ( & + + reminC * arrFunc * O2Func * DetC & ! Slow-sinking detritus dissolution + + reminC * arrFunc * O2Func * DetZ2C * is_3zoo2det & ! Fast-sinking detritus dissolution + ) * recipbiostep + + vertDISSON(k) = vertDISSON(k) + ( & + + reminN * arrFunc * O2Func * DetN & ! Slow-sinking detritus dissolution + + reminN * arrFunc * O2Func * DetZ2N * is_3zoo2det & ! Fast-sinking detritus dissolution + ) * recipbiostep + + vertDISSOSi(k) = vertDISSOSi(k) + ( & + + reminSiT * DetSi & ! Slow-sinking detritus dissolution + ) * recipbiostep + + vertREMOC(k) = vertREMOC(k) + ( & + + rho_c1 * arrFunc * O2Func * EOC & ! Bacterial respiration / remineralization of oceanic DOC +! + rho_C1t * DOCt & ! Bacterial respiration / remineralization of terrestriel DOC + ) * recipbiostep + +! vertREMOCt(k) = vertREMOCt(k) + ( & +! + rho_C1t * DOCt & ! Bacterial respiration / remineralization of terrestriel DOC +! ) * recipbiostep + + vertREMON(k) = vertREMON(k) + ( & + + rho_N * arrFunc * O2Func * DON & ! Bacterial respiration / remineralization + ) * recipbiostep + + !=========================================================================== + ! ZOOPLANKTON RESPIRATION + !=========================================================================== + ! Tracks heterotrophic respiration (metabolic CO2 release) + ! Key component of carbon cycling and food web energetics + ! + ! Variables: + ! vertrespmeso(k) : Mesozooplankton respiration [mmolC m-3 day-1] + ! HetRespFlux : Meso respiration flux [mmolC m-3 day-1] + ! + ! Ecological Significance: + ! - Represents metabolic carbon loss + ! - Typically 20-40% of ingested carbon + ! - Temperature-dependent (Q10 ≈ 2-3) + ! - Increases with activity level + ! + ! Validation: + ! - Incubation experiments (O2 consumption) + ! - ETS (electron transport system) measurements + ! - Typical range: 0.01-1 mmolC m-3 day-1 + !--------------------------------------------------------------------------- + + ! Mesozooplankton respiration + vertrespmeso(k) = vertrespmeso(k) + ( & + + HetRespFlux & ! Carbon respiration flux + ) * recipbiostep + + if (enable_3zoo2det) then + ! Macrozooplankton (krill) respiration + vertrespmacro(k) = vertrespmacro(k) + ( & + + Zoo2RespFlux & + ) * recipbiostep + + ! Microzooplankton respiration + vertrespmicro(k) = vertrespmicro(k) + ( & + + MicZooRespFlux & + ) * recipbiostep + endif + + !=========================================================================== + ! CALCITE DISSOLUTION + !=========================================================================== + ! Tracks calcium carbonate dissolution in water column + ! Critical for carbonate counter-pump and alkalinity cycling + ! + ! Variables: + ! vertcalcdiss(k) : Calcite dissolution rate [mmolC m-3 day-1] + ! calc_diss : Dissolution rate coefficient [day-1] + ! DetCalc : Detrital calcite concentration [mmolC m-3] + ! + ! Process: + ! CaCO3 -> Ca²⁺ + CO3²⁻ + ! Releases DIC (+1) and alkalinity (+2) + ! + ! Controls: + ! - Saturation state (Ω < 1 favors dissolution) + ! - Temperature (higher T -> faster kinetics) + ! - Pressure (higher P -> lower Ω) + ! + ! Depth Pattern: + ! - Surface: Minimal (supersaturated, Ω > 1) + ! - Intermediate: Moderate (Ω ≈ 1) + ! - Deep: High (undersaturated, Ω < 1) + ! + ! Applications: + ! - Ocean acidification impacts + ! - Carbon export efficiency + ! - Sediment CaCO3 preservation + !--------------------------------------------------------------------------- + + vertcalcdiss(k) = vertcalcdiss(k) + ( & + + calc_diss * DetCalc & ! Dissolution flux + ) * recipbiostep + + !*** meso-zooplankton dissolution !RP 14.07.2025 + vertmesocdis(k) = vertmesocdis(k) + ( & + + calc_loss_gra * calc_diss_guts & + ) * recipbiostep + + if (enable_3zoo2det) then + !*** micro-zooplankton dissolution !RP 14.07.2025 + vertmicrocdis(k) = vertmicrocdis(k) + ( & + + calc_loss_gra2 * calc_diss_guts & + ) * recipbiostep + + !*** macro-zooplankton dissolution !RP 14.07.2025 + vertmacrocdis(k) = vertmacrocdis(k) + ( & + + calc_loss_gra3 * calc_diss_guts & + ) * recipbiostep + + !*** calc_diss by fast-sinking detritus !RP 14.07.2025 + vertfastcdis(k) = vertfastcdis(k) + ( & + + calc_diss2 * DetZ2Calc & + ) * recipbiostep + + endif + !=========================================================================== + ! PARTICLE AGGREGATION + !=========================================================================== + ! Tracks formation of large particles through aggregation + ! Key process for biological pump and carbon export + ! + ! Variables: + ! vertaggn(k) : Small phyto aggregation [mmolC m-3 day-1] + ! aggregationrate : Aggregation rate coefficient [day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! + ! Aggregation Mechanisms: + ! - Brownian motion (small particles) + ! - Differential settling (size-dependent) + ! - Shear aggregation (turbulence) + ! - Mucus/TEP gluing (especially diatoms) + ! + ! Enhancement Factors: + ! - High phytoplankton concentration + ! - Nutrient limitation (mucus production) + ! - Turbulence (increased collision rate) + ! - Sticky exudates (TEP, polysaccharides) + ! + ! Ecological Significance: + ! - Increases sinking velocity (export) + ! - Forms marine snow + ! - Provides food for deep-sea organisms + ! - Removes surface biomass + ! + ! Typical Rates: + ! - Low aggregation: <0.01 day-1 + ! - Moderate: 0.01-0.1 day-1 + ! - High (bloom collapse): >0.1 day-1 + !--------------------------------------------------------------------------- + + ! Small phytoplankton aggregation + vertaggn(k) = vertaggn(k) + ( & + + aggregationrate * PhyC & ! Aggregate formation + ) * recipbiostep + + ! Diatom aggregation + vertaggd(k) = vertaggd(k) + ( & + + aggregationrate * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore aggregation + vertaggc(k) = vertaggc(k) + ( & + + aggregationrate * CoccoC & + ) * recipbiostep + + ! Phaeocystis aggregation + vertaggp(k) = vertaggp(k) + ( & + + aggregationrate * PhaeoC & + ) * recipbiostep + endif + + !=========================================================================== + ! N ASSIMILATION and REMINERALIZATION + !=========================================================================== + + !*** N assim by small phytoplankton !RP 15.07.2025 + vertNassimn(k) = vertNassimn(k) + ( & + + N_assim * PhyC & + ) * recipbiostep + + !*** N assim by diatoms !RP 15.07.2025 + vertNassimd(k) = vertNassimd(k) + ( & + + N_assim_Dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + !*** N assim by coccolithophores !RP 15.07.2025 + vertNassimc(k) = vertNassimc(k) + ( & + + N_assim_Cocco * CoccoC & + ) * recipbiostep + + !*** N assim by phaeocystis !OG 08.01.2026 + vertNassimp(k) = vertNassimp(k) + ( & + + N_assim_Phaeo * PhaeoC & + ) * recipbiostep + endif + + !*** DON remineralization !RP 15.07.2025 + vertDONremin(k) = vertDONremin(k) + ( & + + rho_N * arrFunc * O2Func * DON & + ) * recipbiostep + + !*** DOC remineralization !RP 15.07.2025 + vertDOCremin(k) = vertDOCremin(k) + ( & + + rho_C1 * arrFunc * O2Func * EOC & + ) * recipbiostep + + !=========================================================================== + ! DOC EXCRETION + !=========================================================================== + ! Tracks dissolved organic carbon release by phytoplankton + ! Important for microbial loop and carbon cycling + ! + ! Variables: + ! vertdocexn(k) : Small phyto DOC excretion [mmolC m-3 day-1] + ! lossC : Carbon exudation rate constant [day-1] + ! limitFacN : Nutrient limitation factor [0-1] + ! phyC : Small phytoplankton carbon [mmolC m-3] + ! + ! Exudation Mechanisms: + ! - Passive leakage (diffusion across membranes) + ! - Overflow metabolism (excess photosynthate) + ! - Stress response (nutrient limitation) + ! - Viral lysis (cell breakage) + ! + ! Nutrient Stress Effect: + ! - High limitFacN (replete): Low exudation + ! - Low limitFacN (limited): High exudation + ! - C:N imbalance drives carbon overflow + ! + ! DOC Fate: + ! - Labile fraction: Rapid bacterial uptake (hours-days) + ! - Semi-labile: Slower degradation (weeks-months) + ! - Refractory: Accumulates (years-millennia) + ! + ! Ecological Role: + ! - Fuels microbial loop + ! - Carbon loss without grazing + ! - Nutrient regeneration (after remineralization) + ! + ! Typical Rates: + ! - Percent of GPP: 5-30% + ! - Higher under nutrient stress + ! - Lower for healthy, growing cells + !--------------------------------------------------------------------------- + + ! Small phytoplankton DOC excretion + vertdocexn(k) = vertdocexn(k) + ( & + + lossC * limitFacN * phyC & ! Stress-induced exudation + ) * recipbiostep + + ! Diatom DOC excretion + vertdocexd(k) = vertdocexd(k) + ( & + + lossC_d * limitFacN_dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore DOC excretion + vertdocexc(k) = vertdocexc(k) + ( & + + lossC_c * limitFacN_cocco * CoccoC & + ) * recipbiostep + + ! Phaeocystis DOC excretion + vertdocexp(k) = vertdocexp(k) + ( & + + lossC_p * limitFacN_phaeo * PhaeoC & + ) * recipbiostep + endif + + !=========================================================================== + ! CALCIFICATION + !=========================================================================== + ! Tracks calcium carbonate precipitation by phytoplankton + ! Key process for carbonate counter-pump + ! + ! Variables: + ! vertcalcif(k) : Calcification rate [mmolC m-3 day-1] + ! calcification : CaCO3 precipitation flux [mmolC m-3 day-1] + ! + ! Process: + ! Ca²⁺ + 2HCO3⁻ -> CaCO3 + CO2 + H2O + ! Consumes DIC (-1) and alkalinity (-2) + ! Releases CO2 (carbonate counter-pump) + ! + ! Organisms: + ! - Coccolithophores (calcite plates) + ! - Foraminifera (calcite shells) + ! - Pteropods (aragonite shells - not in this model) + ! + ! Environmental Controls: + ! - Temperature (warmer favors calcification) + ! - Carbonate saturation (Ω > 1 required) + ! - pH/CO2 (ocean acidification reduces rate) + ! - Nutrient availability (affects PIC:POC ratio) + ! + ! Ecological Significance: + ! - Ballast for sinking (increases export) + ! - Protection from grazers + ! - CO2 source (opposite to photosynthesis) + ! - Sensitive to ocean acidification + ! + ! Typical Rates: + ! - Surface (bloom): 0.1-2 mmolC m-3 day-1 + ! - Background: 0.001-0.05 mmolC m-3 day-1 + !--------------------------------------------------------------------------- + + vertcalcif(k) = vertcalcif(k) + ( & + + calcification & ! CaCO3 precipitation + ) * recipbiostep + + !=========================================================================== + ! PHYTOPLANKTON PHOTOSYNTHESIS + !=========================================================================== + + ! phy photosynthesis !RP 14.07.2025 + vertphotn(k) = vertphotn(k) + ( & + + Cphot * PhyC & + ) * recipbiostep + + ! dia photosynthesis !RP 14.07.2025 + vertphotd(k) = vertphotd(k) + ( & + + Cphot_Dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! cocco photosynthesis !RP 14.07.2025 + vertphotc(k) = vertphotc(k) + ( & + + Cphot_Cocco * CoccoC & + ) * recipbiostep + + ! phaeocystis photosynthesis !OG 08.01.2026 + vertphotp(k) = vertphotp(k) + ( & + + Cphot_Phaeo * PhaeoC & + ) * recipbiostep + + endif + !=========================================================================== + ! PHYTOPLANKTON RESPIRATION + !=========================================================================== + ! Tracks autotrophic respiration (maintenance costs) + ! Component of community respiration, complement to GPP + ! + ! Variables: + ! vertrespn(k) : Small phyto respiration [mmolC m-3 day-1] + ! PhyRespRate : Respiration rate coefficient [day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! + ! Respiration Components: + ! - Basal metabolism: Maintenance of cellular machinery + ! - Biosynthesis: Costs of growth (protein synthesis, etc.) + ! - Active transport: Nutrient uptake against gradients + ! - Photorespiration: Oxygenase activity of Rubisco + ! + ! Temperature Dependence: + ! - Q10 ≈ 2-3 (doubles per 10degC increase) + ! - Often higher than photosynthesis Q10 + ! - Creates temperature-dependent growth efficiency + ! + ! Relationship to NPP: + ! GPP = NPP + Respiration + ! Growth efficiency = NPP/GPP = 1 - (Resp/GPP) + ! Typical: 0.6-0.8 (60-80% efficiency) + ! + ! Ecological Patterns: + ! - Increases with biomass (proportional) + ! - Higher in warm waters (temperature effect) + ! - Lower in nutrient-replete conditions (efficient growth) + ! - Higher during stress (maintenance costs) + !--------------------------------------------------------------------------- + + ! Small phytoplankton respiration + vertrespn(k) = vertrespn(k) + ( & + + PhyRespRate * PhyC & ! Maintenance respiration + ) * recipbiostep + + ! Diatom respiration + vertrespd(k) = vertrespd(k) + ( & + + PhyRespRate_dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore respiration + vertrespc(k) = vertrespc(k) + ( & + + PhyRespRate_cocco * CoccoC & + ) * recipbiostep + + ! Phaeocystis respiration + vertrespp(k) = vertrespp(k) + ( & + + PhyRespRate_phaeo * PhaeoC & + ) * recipbiostep + endif + + endif ! Diags + + end do ! Main vertikal loop ends + + !=============================================================================== + ! BENTHIC REMINERALIZATION + !=============================================================================== + ! Simulates nutrient return from sediments to the bottom water layer through + ! remineralization of organic matter and calcite dissolution. + ! + ! This part calculates: + ! 1. Remineralization of benthic organic matter (N, C, Si) + ! 2. Dissolution of benthic calcite (CaCO3) + ! 3. Carbon isotope remineralization (13C, 14C - optional) + ! 4. Nutrient flux from sediments to bottom water + ! + ! Key Features: + ! - Single benthic layer (vertically integrated) + ! - First-order decay kinetics for remineralization + ! - Separate rates for N, C, Si, and calcite + ! - Optional MEDUSA sediment flux forcing + ! - Isotope fractionation during remineralization + ! - Conservative tracer return to water column + ! + ! Benthic Processes: + ! - Aerobic respiration: Organic matter -> DIN + DIC + ! - Silica dissolution: Biogenic SiO2 -> Si(OH)4 + ! - Calcite dissolution: CaCO3 -> Ca²⁺ + CO3²⁻ (affects DIC + Alk) + ! - Denitrification: In anoxic sediments (not explicitly modeled) + ! + ! Model Structure: + ! - Benthos as single well-mixed compartment + ! - Area-integrated concentrations [mmol m-2] + ! - Decay rates calibrated to observations + ! - Instant return to bottom water layer + ! + ! Ecological/Biogeochemical Significance: + ! - Closes nutrient cycles (prevents accumulation in benthos) + ! - Critical for shallow shelf ecosystems + ! - Supports benthic-pelagic coupling + ! - Affects bottom water oxygen and pH + ! - Important for coastal carbon budgets + ! + ! Limitations: + ! - No explicit burial (all material eventually remineralized) + ! - No bioturbation or bioirrigation + ! - No redox zonation in sediments + ! - Simplified single-layer representation + ! + ! References: + ! - Schourup-Kristensen et al. (2013) - REcoM benthic module + ! - MEDUSA forcing for data-constrained sediment fluxes + !=============================================================================== + + !=============================================================================== + ! REMINERALIZATION MODE SELECTION + !=============================================================================== + ! Determines whether to use MEDUSA sediment flux forcing or internal + ! benthic remineralization calculations. + ! + ! Variables: + ! use_MEDUSA : Flag to enable MEDUSA sediment forcing [logical] + ! sedflx_num : Number of MEDUSA sediment flux entries [-] + ! mype : Processor ID for parallel output [integer] + ! + ! MEDUSA Mode: + ! - Uses observationally-constrained sediment fluxes + ! - Overrides internal benthic calculations + ! - Typically used for hindcast simulations + ! - Requires external data file + ! + ! Internal Mode: + ! - Uses prognostic benthic compartment + ! - First-order decay kinetics + ! - Suitable for future projections + ! - No external data required + !------------------------------------------------------------------------------- + + if (use_MEDUSA .and. (sedflx_num /= 0)) then + + !=========================================================================== + ! MEDUSA SEDIMENT FLUX FORCING MODE + !=========================================================================== + ! Use externally prescribed sediment nutrient fluxes + ! This overrides all internal benthic calculations + !--------------------------------------------------------------------------- + + if (mype == 0) then + ! Print message only on master processor (parallel computing) + write(*, *) ' --> Sedimentary input of nutrients through MEDUSA' + endif -!*** Calc: DIC, Alk *** ! OG calc_diss_ben is taken from the deepest level - decayBenthos(4) = calc_diss_ben * LocBenthos(4) ! NEW DISS changed calc_diss to calc_diss_ben to not make the dissolution omega dependent when using the switch OmegaC_diss - LocBenthos(4) = LocBenthos(4) - decayBenthos(4) * dt_b + ! Note: MEDUSA fluxes are applied elsewhere in the code + ! This section simply skips internal benthic calculations - end do ! Main time loop ends + else + !=========================================================================== + ! INTERNAL BENTHIC REMINERALIZATION (DEFAULT MODE) + !=========================================================================== + ! Calculates nutrient return from benthic compartment using first-order + ! decay kinetics for each element. + !--------------------------------------------------------------------------- + + !=========================================================================== + ! DISSOLVED INORGANIC NITROGEN (DIN) REMINERALIZATION + !=========================================================================== + ! Aerobic remineralization of organic nitrogen in sediments releases + ! bioavailable nitrogen (NH4+ and NO3-) back to the water column. + ! Burial for R2OMIP + ! + ! Variables: + ! decayBenthos(1) : N remineralization flux [mmolN m-2 day-1] + ! decayRateBenN : Benthic N remineralization rate [day-1] + ! LocBenthos(1) : Benthic N pool (area-integrated) [mmolN m-2] + ! dt_b : REcoM time step [day] + ! + ! Equation: + ! Flux = decayRateBenN × LocBenthos(1) + ! LocBenthos(1)_new = LocBenthos(1)_old - Flux × dt_b + ! + ! Process Representation: + ! Organic N (proteins, amino acids, etc.) -> NH4+ -> NO3- + ! First-order decay: rate proportional to benthic N pool + ! + ! Typical Values: + ! decayRateBenN ~ 0.01-0.1 day-1 (10-100 day turnover) + ! Higher rates in warm, oxygenated sediments + !--------------------------------------------------------------------------- + + ! Calculate N remineralization flux [mmolN m-2 day-1] + decayBenthos(1) = decayRateBenN * LocBenthos(1) + + ! Update benthic N pool (remove remineralized N) + LocBenthos(1) = LocBenthos(1) - decayBenthos(1) * dt_b - BurialBen(1) !R2OMIP (Burial) remove from benthos (flux) + + !=========================================================================== + ! DISSOLVED INORGANIC CARBON (DIC) REMINERALIZATION + !=========================================================================== + ! Aerobic respiration of organic carbon releases CO2 to bottom water. + ! Affects carbonate system (pH, pCO2, saturation state). + ! Burial for R2OMIP + ! + ! Variables: + ! decayBenthos(2) : C remineralization flux [mmolC m-2 day-1] + ! decayRateBenC : Benthic C remineralization rate [day-1] + ! LocBenthos(2) : Benthic C pool (area-integrated) [mmolC m-2] + ! + ! Process Representation: + ! Organic C (carbohydrates, lipids, etc.) + O2 -> CO2 + H2O + ! Releases DIC and consumes O2 (not explicitly tracked) + ! + ! Stoichiometry: + ! C:N remineralization ratio typically near Redfield (6.6:1) + ! Can vary with organic matter source and degradation state + ! + ! Typical Values: + ! decayRateBenC ~ 0.01-0.1 day-1 + ! May differ from N rate due to preferential degradation + !--------------------------------------------------------------------------- + + ! Calculate C remineralization flux [mmolC m-2 day-1] + decayBenthos(2) = decayRateBenC * LocBenthos(2) + + ! Update benthic C pool + LocBenthos(2) = LocBenthos(2) - decayBenthos(2) * dt_b - BurialBen(2) !R2OMIP (Burial) + + !=========================================================================== + ! SILICATE (Si) DISSOLUTION + !=========================================================================== + ! Dissolution of biogenic silica (diatom frustules) releases Si(OH)4. + ! Temperature-dependent process (faster in warm water). + ! Burial for R2OMIP + ! + ! Variables: + ! decayBenthos(3) : Si dissolution flux [mmolSi m-2 day-1] + ! decayRateBenSi : Benthic Si dissolution rate [day-1] + ! LocBenthos(3) : Benthic Si pool (area-integrated) [mmolSi m-2] + ! + ! Process Representation: + ! Biogenic SiO2 (opal) + H2O -> Si(OH)4 (silicic acid) + ! Thermodynamically driven dissolution (opal undersaturated in seawater) + ! + ! Typical Values: + ! decayRateBenSi ~ 0.001-0.01 day-1 (100-1000 day turnover) + ! Slower than organic matter (opal is recalcitrant) + ! Temperature-dependent (see reminSiT calculation earlier) + ! + ! Ecological Significance: + ! - Returns Si to support diatom production + ! - Critical in Si-limited regions + ! - Permanent burial in deep sediments affects long-term Si cycle + !--------------------------------------------------------------------------- + + ! Calculate Si dissolution flux [mmolSi m-2 day-1] + decayBenthos(3) = decayRateBenSi * LocBenthos(3) + + ! Update benthic Si pool + LocBenthos(3) = LocBenthos(3) - decayBenthos(3) * dt_b - BurialBen(3) !R2OMIP (Burial) + + !=========================================================================== + ! CALCITE (CaCO3) DISSOLUTION + !=========================================================================== + ! Dissolution of calcium carbonate affects both DIC and alkalinity. + ! Rate depends on saturation state (calculated in deepest water layer). + ! Burial for R2OMIP + ! + ! Variables: + ! decayBenthos(4) : Calcite dissolution flux [mmolC m-2 day-1] + ! calc_diss_ben : Benthic calcite dissolution rate [day-1] + ! LocBenthos(4) : Benthic calcite pool [mmolC m-2] + ! + ! Process Representation: + ! CaCO3 + CO2 + H2O ⇌ Ca²⁺ + 2HCO3- + ! Increases DIC (+1) and alkalinity (+2) + ! + ! Rate Determination: + ! calc_diss_ben taken from deepest water layer + ! Uses either saturation-state or depth-dependent formulation + ! (see calcite dissolution module earlier in code) + ! + ! Carbonate Chemistry Effect: + ! - Raises pH (consumes CO2) + ! - Increases carbonate saturation + ! - Buffers ocean acidification locally + ! + ! Note: Changed from calc_diss to calc_diss_ben to allow independent + ! control when using OmegaC_diss switch + !--------------------------------------------------------------------------- + + ! Calculate calcite dissolution flux [mmolC m-2 day-1] + decayBenthos(4) = calc_diss_ben * LocBenthos(4) + + ! Update benthic calcite pool + LocBenthos(4) = LocBenthos(4) - decayBenthos(4) * dt_b - BurialBen(4) !R2OMIP (Burial) + + if (ciso) then + + !======================================================================= + ! CARBON ISOTOPE REMINERALIZATION (OPTIONAL) + !======================================================================= + ! Tracks 13C and 14C through benthic remineralization processes. + ! Important for paleoclimate reconstructions and carbon cycle studies. + !----------------------------------------------------------------------- + + !======================================================================= + ! Carbon-13 (13C) Remineralization + !======================================================================= + ! Organic matter remineralization with isotopic fractionation + ! + ! Variables: + ! decayBenthos(5) : 13C remineralization flux [mmol13C m-2 day-1] + ! alpha_dcal_13 : 13C fractionation factor for remineralization [-] + ! LocBenthos(5) : Benthic 13C pool [mmol13C m-2] + ! + ! Note: Assumes same decay rate as total carbon (decayRateBenC) + ! Fractionation factor typically near 1.0 (minimal fractionation) + !----------------------------------------------------------------------- + + ! Calculate 13C remineralization flux + ! Ignores isotopic fractionation during remineralization (alpha ≈ 1) + decayBenthos(5) = alpha_dcal_13 * decayRateBenC * LocBenthos(5) + + ! Update benthic 13C pool + LocBenthos(5) = LocBenthos(5) - decayBenthos(5) * dt_b + + !======================================================================= + ! Carbon-13 Calcite Dissolution + !======================================================================= + ! Dissolution of 13C-containing calcite + ! + ! Variables: + ! decayBenthos(6) : 13C calcite dissolution flux [mmol13C m-2 day-1] + ! calc_diss_13 : 13C calcite dissolution rate [day-1] + ! LocBenthos(6) : Benthic 13C-calcite pool [mmol13C m-2] + !----------------------------------------------------------------------- + + ! Calculate 13C calcite dissolution flux + decayBenthos(6) = calc_diss_13 * LocBenthos(6) + + ! Update benthic 13C-calcite pool + LocBenthos(6) = LocBenthos(6) - decayBenthos(6) * dt_b + + if (ciso_14) then + + if (ciso_organic_14) then + + !=============================================================== + ! Carbon-14 (14C) Remineralization + !=============================================================== + ! Radiocarbon remineralization for age dating and residence times + ! + ! Variables: + ! decayBenthos(7) : 14C remineralization flux [mmol14C m-2 day-1] + ! alpha_dcal_14 : 14C fractionation factor [-] + ! LocBenthos(7) : Benthic 14C pool [mmol14C m-2] + ! + ! Note: 14C also subject to radioactive decay (half-life ~5730 years) + ! This is typically handled separately in full carbon cycle models + !--------------------------------------------------------------- + + ! Calculate 14C remineralization flux + ! Ignores isotopic fractionation during remineralization + decayBenthos(7) = alpha_dcal_14 * decayRateBenC * LocBenthos(7) + + ! Update benthic 14C pool + LocBenthos(7) = LocBenthos(7) - decayBenthos(7) * dt_b + + !=============================================================== + ! 3.4 Carbon-14 Calcite Dissolution + !=============================================================== + ! Dissolution of 14C-containing calcite + ! + ! Variables: + ! decayBenthos(8) : 14C calcite dissolution flux [mmol14C m-2 day-1] + ! calc_diss_14 : 14C calcite dissolution rate [day-1] + ! LocBenthos(8) : Benthic 14C-calcite pool [mmol14C m-2] + !--------------------------------------------------------------- + + ! Calculate 14C calcite dissolution flux + decayBenthos(8) = calc_diss_14 * LocBenthos(8) + + ! Update benthic 14C-calcite pool + LocBenthos(8) = LocBenthos(8) - decayBenthos(8) * dt_b + + else + !--------------------------------------------------------------- + ! Alternative 14C handling + !--------------------------------------------------------------- + ! When ciso_organic_14 = FALSE: + ! 14C defined as proportional to total DIC elsewhere in code + ! No separate remineralization calculation needed + ! (sms(idic_14) = sms(idic) × isotope_ratio) + !--------------------------------------------------------------- + + end if ! ciso_organic_14 + + end if ! ciso_14 + + end if ! ciso + + endif ! use_MEDUSA + + end do ! Main time loop ends end subroutine REcoM_sms @@ -2190,7 +7563,7 @@ function recom_limiter(slope,qa,qb) Real(kind=8) :: recom_limiter Real(kind=8) :: slope, qa, qb Real(kind=8) :: dq - + dq = qa - qb if (REcoM_Geider_limiter) then recom_limiter = max(min( -slope*dq, 1.d0),0.d0) @@ -2259,7 +7632,7 @@ function iron_chemistry(Fe, totalLigand, ligandStabConst) b = ligandstabConst * (Fe - totalLigand) + 1.d0 c = -totalLigand discrim = b*b - 4.d0 * a * c - + if (a .ne. 0.d0 .and. discrim .ge. 0.d0) then ligand = ( -b + sqrt(discrim) ) / (2.d0 * a) FeL = totalLigand - ligand diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index fba00c3d8..362d979fe 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -570,125 +570,1061 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) ! output RECOM 2D #if defined(__recom) +!=============================================================================== +! RECOM BIOGEOCHEMICAL MODEL - OUTPUT VARIABLE DEFINITIONS +!=============================================================================== +! This module defines output streams for the REcoM (Regulated Ecosystem Model) +! biogeochemical tracer variables. Variables are organized by functional groups. +!=============================================================================== + +! ===================================================================== +! CARBONATE CHEMISTRY & AIR-SEA GAS EXCHANGE +! ===================================================================== +! These variables control and diagnose the exchange of CO2 and O2 between +! the ocean and atmosphere, as well as ocean acidification processes. +! ===================================================================== + +CASE ('alphaCO2 ') + ! ===================================================================== + ! Variable: alphaCO2 + ! Description: CO2 solubility coefficient (Henry's Law constant) + ! Function: Determines how much CO2 dissolves in seawater at equilibrium + ! Dependencies: Temperature and salinity dependent + ! Units: mol/kg/atm + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'alphaCO2', 'CO2 solubility', 'mol/kg/atm', alphaCO2(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('Kw ') + ! ===================================================================== + ! Variable: Kw (also known as k660 or gas transfer velocity) + ! Description: Air-sea piston velocity for gas exchange + ! Function: Controls the rate of gas transfer across the air-sea interface + ! Dependencies: Wind speed, sea state, and gas-specific Schmidt number + ! Units: m/s + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'Kw', 'Air-sea piston velocity', 'm/s', PistonVelocity(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + CASE ('dpCO2s ') + ! ===================================================================== + ! Variable: dpCO2s (Delta pCO2) + ! Description: Air-sea pCO2 gradient (ocean minus atmosphere) + ! Function: Driving force for CO2 flux; positive = ocean supersaturated + ! Sign convention: Positive when ocean releases CO2 to atmosphere + ! Units: μatm (microatmospheres) + ! ===================================================================== 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) + 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) end if CASE ('pCO2s ') + ! ===================================================================== + ! Variable: pCO2s + ! Description: Oceanic partial pressure of CO2 at the surface + ! Function: Measures CO2 concentration in surface waters + ! Context: Atmospheric pCO2 ≈ 420 μatm (as of 2024) + ! Units: μatm (microatmospheres) + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'pCO2s', 'Partial pressure of oceanic CO2', 'uatm', GloPCO2surf(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'pCO2s', 'Partial pressure of oceanic CO2', 'uatm', GloPCO2surf(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('CO2f ') + ! ===================================================================== + ! Variable: CO2f + ! Description: Net CO2 flux across the air-sea interface + ! Function: Quantifies ocean carbon uptake (or release) + ! Sign convention: Positive = flux into ocean (ocean is a CO2 sink) + ! Calculation: Flux = Kw × alphaCO2 × dpCO2s + ! Units: mmolC/m²/d (millimoles carbon per square meter per day) + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'CO2f', 'CO2-flux into the surface water', 'mmolC/m2/d', GloCO2flux(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'CO2f', 'CO2-flux into the surface water', 'mmolC/m2/d', GloCO2flux(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('O2f ') + ! ===================================================================== + ! Variable: O2f + ! Description: Net O2 flux across the air-sea interface + ! Function: Balances photosynthetic O2 production and respiratory consumption + ! Sign convention: Positive = flux into ocean + ! Context: Opposite sign to CO2 flux in productive regions + ! Units: mmolO/m²/d (millimoles oxygen per square meter per day) + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'O2f', 'O2-flux into the surface water', 'mmolO/m2/d', GloO2flux(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'O2f', 'O2-flux into the surface water', 'mmolO/m2/d', GloO2flux(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('Hp ') + ! ===================================================================== + ! Variable: Hp (H⁺ concentration) + ! Description: Hydrogen ion concentration in surface water + ! Function: Direct measure of ocean acidity (pH = -log₁₀[H⁺]) + ! Context: pH ≈ 8.1 in modern ocean → [H⁺] ≈ 10⁻⁸·¹ mol/kg + ! Relevance: Ocean acidification monitoring + ! Units: mol/kg + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'Hp', 'Mean of H-plus ions in the surface water', 'mol/kg', GloHplus(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'Hp', 'Mean of H-plus ions in the surface water', 'mol/kg', GloHplus(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if +! ===================================================================== +! ATMOSPHERIC DEPOSITION +! ===================================================================== +! External nutrient inputs to the ocean surface from atmospheric sources +! ===================================================================== + CASE ('aFe ') + ! ===================================================================== + ! Variable: aFe + ! Description: Atmospheric iron deposition flux + ! Function: Primary iron source for open ocean phytoplankton + ! Sources: Mineral dust (especially from deserts), combustion aerosols + ! Importance: Iron limits primary production in HNLC regions + ! Units: μmolFe/m²/s (micromoles iron per square meter per second) + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'aFe','Atmospheric iron input','umolFe/m2/s', AtmFeInput(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'aFe', 'Atmospheric iron input', 'umolFe/m2/s', AtmFeInput(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('aN ') + ! ===================================================================== + ! Variable: aN + ! Description: Atmospheric dissolved inorganic nitrogen (DIN) deposition + ! Function: External nitrogen input to surface ocean + ! Sources: NOₓ from combustion, ammonia from agriculture, natural sources + ! Forms: Primarily nitrate (NO₃⁻) and ammonium (NH₄⁺) + ! Units: mmolN/m²/s (millimoles nitrogen per square meter per second) + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'aN', 'Atmospheric DIN input', 'mmolN/m2/s', AtmNInput(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('riverDIN ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'riverDIN','riverine DIN input','mmolN/m2/s', RiverDIN2D(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('riverDIC ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'riverDIC','riverine DIC input','mmolC/m2/s', RiverDIC2D(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('riverDOCsl ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'riverDOCsl','riverine semi-labile DOC input','mmolC/m2/s', RiverDOCsl2D(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('riverDOCl ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'riverDOCl','riverine labile DOC input','mmolC/m2/s', RiverDOCl2D(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('riverPOC ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'riverPOC','riverine POC input','mmolC/m2/s', RiverPOC2D(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('riverDFe ') if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'aN','Atmospheric DIN input','mmolN/m2/s', AtmNInput(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, 'riverDFe','riverine DFe input','mmolC/m2/s', RiverFe(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if + +! ===================================================================== +! BENTHIC (SEAFLOOR) POOLS +! ===================================================================== +! Accumulation of particulate organic and inorganic material in sediments +! These pools act as temporary storage before remineralization/burial +! ===================================================================== + CASE ('benN ') + ! ===================================================================== + ! Variable: benN + ! Description: Benthic nitrogen pool + ! Function: Sedimentary organic nitrogen awaiting remineralization + ! Process: Sinking particles → benthos → remineralization → DIN + ! Role: Nutrient recycling in shallow waters; burial in deep ocean + ! Units: mmol (millimoles per grid cell) + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'benN','Benthos Nitrogen','mmol', Benthos(:,1), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'benN', 'Benthos Nitrogen', 'mmol', Benthos(:,1), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('benC ') + ! ===================================================================== + ! Variable: benC + ! Description: Benthic carbon pool + ! Function: Sedimentary organic carbon storage + ! Process: POC sinking → benthic accumulation → remineralization/burial + ! Importance: Long-term carbon sequestration pathway + ! Units: mmol (millimoles per grid cell) + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'benC','Benthos Carbon','mmol', Benthos(:,2), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'benC', 'Benthos Carbon', 'mmol', Benthos(:,2), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('benSi ') + ! ===================================================================== + ! Variable: benSi + ! Description: Benthic silicon pool (biogenic silica) + ! Function: Opal (SiO₂) from diatom frustules in sediments + ! Process: Diatom mortality → opal dissolution in water column/benthos + ! Fate: Slow dissolution returns Si to dissolved silicate pool + ! Units: mmol (millimoles per grid cell) + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'benSi','Benthos silicon','mmol', Benthos(:,3), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'benSi', 'Benthos silicon', 'mmol', Benthos(:,3), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('benCalc ') + ! ===================================================================== + ! Variable: benCalc + ! Description: Benthic calcite pool (calcium carbonate) + ! Function: CaCO₃ from coccolithophore shells and other sources + ! Process: Calcifier mortality → CaCO₃ sinking → accumulation/dissolution + ! Importance: Carbonate chemistry buffering; geological carbon burial + ! Units: mmol (millimoles per grid cell) + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'benCalc','Benthos calcite','mmol', Benthos(:,4), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'benCalc','Benthos calcite','mmol', Benthos(:,4), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -CASE ('NPPn ') + +CASE ('denb ') + ! Variable: denb + ! Description: Benthic denitrification rate + ! Function: Conversion of nitrate to N₂ gas in anoxic sediments + ! Process: NO₃⁻ → NO₂⁻ → NO → N₂O → N₂ (anaerobic respiration pathway) + ! Role: Permanent nitrogen loss from ocean; regulates ocean N inventory + ! Units: mmol/m² (millimoles per square meter) if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'NPPn','Mean NPP nanophytoplankton','mmolC/m2/d', NPPn, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'denb', 'Benthic denitrification rate', 'mmol/m2', DenitBen(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -CASE ('NPPd ') +! ===================================================================== +! BURIAL FLUXES +! ===================================================================== +CASE ('BurialN ') + ! Variable: BurialN + ! Description: Nitrogen burial rate + ! Function: Permanent removal of nitrogen from biogeochemical cycling + ! Process: Benthic N → deep sediments → geological timescale storage + ! Role: Long-term nitrogen sink; reduces ocean fixed-N inventory + ! Units: mmolN/m² (millimoles nitrogen per square meter) if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'NPPd','Mean NPP diatoms','mmolC/m2/d', NPPd, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'BurialN', 'Benthic Burial rate of Nitrogen', 'mmolN/m2', Burial(1,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -CASE ('GPPn ') +CASE ('BurialC ') + ! Variable: BurialC + ! Description: Carbon burial rate + ! Function: Permanent sequestration of organic carbon in sediments + ! Process: Benthic C → deep sediments → long-term CO₂ drawdown + ! Role: Major carbon sink; climate regulation on geological timescales + ! Units: mmolC/m² (millimoles carbon per square meter) if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'GPPn','Mean GPP nanophytoplankton','mmolC/m2/d', GPPn, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'BurialC', 'Benthic Burial rate of Carbon', 'mmolC/m2', Burial(2,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -CASE ('GPPd ') +CASE ('BurialSi ') + ! Variable: BurialSi + ! Description: Biogenic silica burial rate + ! Function: Permanent removal of opal from dissolution-precipitation cycle + ! Process: Benthic opal → deep sediments → geological storage + ! Role: Silicon sink; sedimentary opal record of diatom productivity + ! Units: mmolSi/m² (millimoles silicon per square meter) if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'GPPd','Mean GPP diatoms','mmolC/m2/d', GPPd, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'BurialSi', 'Benthic Burial rate', 'mmolSi/m2', Burial(3,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -CASE ('NNAn ') +CASE ('BurialCalc ') + ! Variable: BurialCalc + ! Description: Calcite burial rate + ! Function: Permanent sequestration of CaCO₃ in sediments + ! Process: Benthic calcite → deep sediments → limestone formation + ! Role: Long-term alkalinity/DIC sink; carbonate compensation depth control + ! Units: mmolC/m² (millimoles carbon as CaCO₃ per square meter) if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'NNAn','Net N-assimilation nanophytoplankton','mmolN/m2/d', NNAn, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'BurialCalc', 'Benthic Burial rate of Calcite', 'mmolC/m2', Burial(4,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -CASE ('NNAd ') +! ===================================================================== +! OCEAN → SEDIMENT FLUXES +! ===================================================================== +CASE ('wFNb ') + ! Variable: wFNb + ! Description: Sinking particulate nitrogen flux to benthos + ! Function: Downward transport of organic nitrogen to seafloor + ! Process: Detritus/phytoplankton → sinking → benthic deposition + ! Role: Primary nitrogen input to sediments; fuels benthic remineralization + ! Units: mmolN/(m²·d) (millimoles nitrogen per square meter per day) + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'wFNb', 'Sinking flux into benthic N', 'mmolN/(m2*d)', Ocean_2_Sed_flux(:,1), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('wFCb ') + ! Variable: wFCb + ! Description: Sinking particulate organic carbon flux to benthos + ! Function: Downward transport of organic carbon to seafloor + ! Process: POC/phytoplankton → sinking → benthic deposition + ! Role: Primary carbon input to sediments; energy source for benthos + ! Units: mmolC/(m²·d) (millimoles carbon per square meter per day) + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'wFCb', 'Sinking flux into benthic C', 'mmolC/(m2*d)', Ocean_2_Sed_flux(:,2), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('wFSib ') + ! Variable: wFSib + ! Description: Sinking biogenic silica flux to benthos + ! Function: Downward transport of opal (diatom frustules) to seafloor + ! Process: Diatom detritus → sinking → benthic deposition + ! Role: Primary silicon input to sediments; creates opal-rich sediments + ! Units: mmolSi/(m²·d) (millimoles silicon per square meter per day) + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'wFSib', 'Sinking flux into benthic Si', 'mmolSi/(m2*d)', Ocean_2_Sed_flux(:,3), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('wFCalcb ') + ! Variable: wFCalcb + ! Description: Sinking calcite flux to benthos + ! Function: Downward transport of CaCO₃ (coccoliths, foraminifera) to seafloor + ! Process: Calcifying organisms → sinking → benthic deposition + ! Role: Primary carbonate input; lysocline/CCD depth control + ! Units: mmolC/(m²·d) (millimoles carbon as CaCO₃ per square meter per day) + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'wFCalcb', 'Sinking flux into benthic Carb', 'mmolC/(m2*d)', Ocean_2_Sed_flux(:,4), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +! ===================================================================== +! SEDIMENT → OCEAN FLUXES (REMINERALIZATION/DISSOLUTION) +! ===================================================================== +CASE ('ReNb ') + ! Variable: ReNb + ! Description: Benthic nitrogen remineralization flux + ! Function: Release of dissolved inorganic nitrogen from sediments + ! Process: Benthic organic N → bacterial degradation → NH₄⁺/NO₃⁻ → ocean + ! Role: Nutrient regeneration; supports primary production in shallow waters + ! Units: mmolN/(m²·s) (millimoles nitrogen per square meter per second) if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'NNAd','Net N-assimilation diatoms','mmolN/m2/d', NNAd, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'ReNb', 'benthic N release to the ocean (remineralization)', 'mmolN/(m2*s)', & + Sed_2_Ocean_Flux(:,1), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('ReCb ') + ! Variable: ReCb + ! Description: Benthic carbon remineralization + calcite dissolution flux + ! Function: Release of dissolved inorganic carbon from sediments + ! Process: Organic C → remineralization → DIC + CaCO₃ dissolution → ocean + ! Role: CO₂ source; carbonate system buffering; alkalinity regulation + ! Units: mmolC/(m²·s) (millimoles carbon per square meter per second) + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'ReCb', 'benthic C release to the ocean (remineralization + calcification)', & + 'mmolC/(m2*s)', Sed_2_Ocean_Flux(:,2), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('ReSib ') + ! Variable: ReSib + ! Description: Benthic silica dissolution flux + ! Function: Release of dissolved silicon from opal dissolution + ! Process: Benthic opal → porewater dissolution → Si(OH)₄ → ocean + ! Role: Silicon regeneration; supports diatom productivity + ! Units: mmolSi/(m²·s) (millimoles silicon per square meter per second) + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'ReSib', 'benthic Si release to the ocean (dissolution)', 'mmolSi/(m2*s)', & + Sed_2_Ocean_Flux(:,4), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('ReAlkb ') + ! Variable: ReAlkb + ! Description: Benthic alkalinity flux + ! Function: Release of alkalinity from organic matter and CaCO₃ processing + ! Process: Denitrification + sulfate reduction + CaCO₃ dissolution → Alk + ! Role: pH buffering; carbonate system regulation; CO₂ uptake capacity + ! Units: mmolC-eq/(m²·s) (millimole carbon-equivalents per square meter per second) + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'ReAlkb', 'benthic Alk release to the ocean', 'mmolC-eq/(m2*s)', & + Sed_2_Ocean_Flux(:,3), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('ReFeb ') + ! Variable: ReFeb + ! Description: Benthic iron flux + ! Function: Release of dissolved iron from reducing sediments + ! Process: Benthic Fe-oxides → anoxic reduction → Fe²⁺ → ocean + ! Role: Micronutrient supply; supports primary production in Fe-limited regions + ! Units: mmolFe/(m²·s) (millimoles iron per square meter per second) + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'ReFeb', 'benthic Fe release to the ocean', 'mmolFe/(m2*s)', & + Sed_2_Ocean_Flux(:,5), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('ReO2b ') + ! Variable: ReO2b + ! Description: Benthic oxygen consumption flux + ! Function: Oxygen demand from aerobic remineralization in sediments + ! Process: Organic matter + O₂ → CO₂ + nutrients (negative flux = consumption) + ! Role: Sediment oxygen demand; creates anoxic conditions; hypoxia indicator + ! Units: mmolO₂/(m²·s) (millimoles oxygen per square meter per second) + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'ReO2b', 'benthic O2 release to the ocean', 'mmolO2/(m2*s)', & + Sed_2_Ocean_Flux(:,6), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +! ===================================================================== +! PHYTOPLANKTON PRIMARY PRODUCTION +! ===================================================================== +! Production and nutrient assimilation by different phytoplankton groups +! NPP = Net Primary Production (photosynthesis - respiration) +! GPP = Gross Primary Production (total photosynthesis) +! NNA = Net Nitrogen Assimilation (nitrogen uptake - excretion) +! ChlDeg = Chlorophyll degradation rate +! ===================================================================== + +! --------------------------------------------------------------------- +! SMALL PHYTOPLANKTON +! --------------------------------------------------------------------- +! Small phytoplankton (typically < 20 μm; e.g., small flagellates) +! Ecological role: Dominant in oligotrophic (nutrient-poor) regions +! --------------------------------------------------------------------- + +CASE ('NPPn ') + ! ===================================================================== + ! Variable: NPPn + ! Description: Net Primary Production of nanophytoplankton + ! Function: Carbon fixation minus autotrophic respiration + ! Integration: Vertically integrated over water column + ! Units: mmolC/m²/d (millimoles carbon per square meter per day) + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'NPPn', 'Mean NPP nanophytoplankton', 'mmolC/m2/d', NPPn, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('GPPn ') + ! ===================================================================== + ! Variable: GPPn + ! Description: Gross Primary Production of nanophytoplankton + ! Function: Total photosynthetic carbon fixation (before respiration) + ! Relationship: GPPn = NPPn + autotrophic respiration + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'GPPn', 'Mean GPP nanophytoplankton', 'mmolC/m2/d', GPPn, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('NNAn ') + ! ===================================================================== + ! Variable: NNAn + ! Description: Net Nitrogen Assimilation by nanophytoplankton + ! Function: Nitrogen uptake (NO₃⁻, NH₄⁺) minus excretion + ! Stoichiometry: Related to NPPn via Redfield ratio (C:N ≈ 6.6:1) + ! Units: mmolN/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'NNAn', 'Net N-assimilation nanophytoplankton', 'mmolN/m2/d', NNAn, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('Chldegn ') + ! ===================================================================== + ! Variable: Chldegn + ! Description: Chlorophyll degradation rate for nanophytoplankton + ! Function: Loss rate of chlorophyll (photopigment bleaching) + ! Causes: Photo-oxidation, senescence, nutrient stress + ! Application: Chlorophyll evolution = synthesis - degradation + ! Units: 1/d (per day; first-order rate constant) + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'ChlDegn', 'Chlorophyll degradation nanophytoplankton', '1/d', Chldegn, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +! --------------------------------------------------------------------- +! DIATOMS +! --------------------------------------------------------------------- +! Silica-shelled phytoplankton (typically 20-200 μm) +! Ecological role: Bloom formers in nutrient-rich upwelling regions +! Requirement: Need silicate (Si(OH)₄) for frustule construction +! --------------------------------------------------------------------- + +CASE ('NPPd ') + ! ===================================================================== + ! Variable: NPPd + ! Description: Net Primary Production of diatoms + ! Function: Diatom carbon fixation minus respiration + ! Ecological context: Dominates spring blooms, coastal upwelling + ! Units: mmolC/m²/d + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'ChlDegn','Chlorophyll degradation nanophytoplankton','1/d', Chldegn, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'NPPd', 'Mean NPP diatoms', 'mmolC/m2/d', NPPd, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('GPPd ') + ! ===================================================================== + ! Variable: GPPd + ! Description: Gross Primary Production of diatoms + ! Function: Total diatom photosynthesis + ! Importance: Major contributor to biological carbon pump + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'GPPd', 'Mean GPP diatoms', 'mmolC/m2/d', GPPd, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('NNAd ') + ! ===================================================================== + ! Variable: NNAd + ! Description: Net Nitrogen Assimilation by diatoms + ! Function: Diatom nitrogen uptake + ! Preference: Often prefer NH₄⁺ but can use NO₃⁻ + ! Units: mmolN/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'NNAd', 'Net N-assimilation diatoms', 'mmolN/m2/d', NNAd, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('Chldegd ') + ! ===================================================================== + ! Variable: Chldegd + ! Description: Chlorophyll degradation rate for diatoms + ! Function: Diatom chlorophyll loss rate + ! Context: Can be elevated during silicate stress + ! Units: 1/d + ! ===================================================================== if (use_REcoM) then - call def_stream(nod2D, myDim_nod2D, 'ChlDegd','Chlorophyll degradation diatoms','1/d', Chldegd, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, & + 'ChlDegd', 'Chlorophyll degradation diatoms', '1/d', Chldegd, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if + + +! --------------------------------------------------------------------- +! COCCOLITHOPHORES +! --------------------------------------------------------------------- +! Calcite-producing phytoplankton (e.g., Emiliania huxleyi) +! Ecological role: CaCO₃ production affects alkalinity and air-sea CO₂ +! Distribution: Temperate and subtropical regions +! --------------------------------------------------------------------- + CASE ('NPPc ') + ! ===================================================================== + ! Variable: NPPc + ! Description: Net Primary Production of coccolithophores + ! Function: Coccolith carbon fixation + ! Special feature: Both organic C (photosynthesis) and inorganic C (CaCO₃) + ! Units: mmolC/(m²*d) + ! ===================================================================== if (use_REcoM) then -! call def_stream(nod2D, myDim_nod2D, 'NPPc','Mean NPP coccolithophores','mmolC/(m2*d)', diags2D(:,9), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, mesh) ! NEW - call def_stream(nod2D, myDim_nod2D, 'NPPc','Mean NPP coccolithophores','mmolC/(m2*d)', NPPc, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW + call def_stream(nod2D, myDim_nod2D, & + 'NPPc', 'Mean NPP coccolithophores', 'mmolC/(m2*d)', NPPc, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('GPPc ') + ! ===================================================================== + ! Variable: GPPc + ! Description: Gross Primary Production of coccolithophores + ! Function: Total coccolith photosynthesis + ! Climate impact: Calcification increases surface pCO₂ (CO₂ source) + ! Units: mmolC/(m²*d) + ! ===================================================================== if (use_REcoM) then -! call def_stream(nod2D, myDim_nod2D, 'GPPc','Mean GPP coccolithophores','mmolC/(m2*d)', diags2D(:,10), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, mesh) ! NEW - call def_stream(nod2D, myDim_nod2D, 'GPPc','Mean GPP coccolithophores','mmolC/(m2*d)', GPPc, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW + call def_stream(nod2D, myDim_nod2D, & + 'GPPc', 'Mean GPP coccolithophores','mmolC/(m2*d)', GPPc, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if CASE ('NNAc ') + ! ===================================================================== + ! Variable: NNAc + ! Description: Net Nitrogen Assimilation by coccolithophores + ! Function: Coccolith nitrogen uptake + ! Competition: Less competitive for nutrients than diatoms + ! Units: mmolN/(m²*d) + ! ===================================================================== if (use_REcoM) then -! call def_stream(nod2D, myDim_nod2D, 'NNAc','Net N-assimilation coccolithophores','mmolN/(m2*d)', diags2D(:,11), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, mesh) ! NEW - call def_stream(nod2D, myDim_nod2D, 'NNAc','Net N-assimilation coccolithophores','mmolN/(m2*d)', NNAc, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) !NEW + call def_stream(nod2D, myDim_nod2D, & + 'NNAc', 'Net N-assimilation coccolithophores', 'mmolN/(m2*d)', NNAc, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif CASE ('Chldegc ') + ! ===================================================================== + ! Variable: Chldegc + ! Description: Chlorophyll degradation rate for coccolithophores + ! Function: Coccolith chlorophyll loss + ! Units: 1/d + ! ===================================================================== if (use_REcoM) then -! call def_stream(nod2D, myDim_nod2D, 'GNAc','Gross N-assimilation coccolithophores','mmolN/(m2*d)', diags2D(:,12), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, mesh) ! NEW - call def_stream(nod2D, myDim_nod2D, 'ChlDegc','Chlorophyll degradation coccolithophores','1/d', Chldegc, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW + call def_stream(nod2D, myDim_nod2D, & + 'ChlDegc', 'Chlorophyll degradation coccolithophores', '1/d', Chldegc, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif -#endif + +! --------------------------------------------------------------------- +! PHAEOCYSTIS +! --------------------------------------------------------------------- +! Colony-forming phytoplankton (Phaeocystis spp.) +! Ecological role: Forms massive blooms in polar/subpolar regions +! Unique feature: Can exist as single cells or large mucilaginous colonies +! --------------------------------------------------------------------- + +CASE ('NPPp ') + ! ===================================================================== + ! Variable: NPPp + ! Description: Net Primary Production of Phaeocystis + ! Function: Phaeocystis carbon fixation + ! Regional importance: Dominant in Southern Ocean, North Sea blooms + ! Units: mmolC/(m²*d) + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'NPPp', 'Mean NPP phaeocystis', 'mmolC/(m2*d)', NPPp, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('GPPp ') + ! ===================================================================== + ! Variable: GPPp + ! Description: Gross Primary Production of Phaeocystis + ! Function: Total Phaeocystis photosynthesis + ! Biogeochemical role: Colonial form less grazed; affects food web + ! Units: mmolC/(m²*d) + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'GPPp', 'Mean GPP phaeocystis', 'mmolC/(m2*d)', GPPp, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('NNAp ') + ! ===================================================================== + ! Variable: NNAp + ! Description: Net Nitrogen Assimilation by Phaeocystis + ! Function: Phaeocystis nitrogen uptake + ! Nutrient preference: Can efficiently use various N forms + ! Units: mmolN/(m²*d) + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'NNAp', 'Net N-assimilation phaeocystis', 'mmolN/(m2*d)', NNAp, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('Chldegp ') + ! ===================================================================== + ! Variable: Chldegp + ! Description: Chlorophyll degradation rate for Phaeocystis + ! Function: Phaeocystis chlorophyll loss + ! Units: 1/d + ! ===================================================================== + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, & + 'ChlDegp', 'Chlorophyll degradation phaeocystis', '1/d', Chldegp, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +! ===================================================================== +! ZOOPLANKTON GRAZING FLUXES +! ===================================================================== +! Predation fluxes by three zooplankton functional groups +! +! IMPORTANT DISTINCTION: +! - Fluxes "without grazing efficiency" = loss from prey's perspective +! (all carbon removed from prey pool) +! - "Total grazing" = actual ingestion by predator +! (accounts for grazing efficiency < 1; rest becomes detritus) +! +! Model structure: Three zooplankton size classes +! - Microzooplankton: Small (e.g., ciliates, heterotrophic flagellates) +! - Mesozooplankton: Medium (e.g., copepods) +! - Macrozooplankton: Large (e.g., euphausiids, large copepods) +! ===================================================================== + +! --------------------------------------------------------------------- +! MESOZOOPLANKTON GRAZING +! --------------------------------------------------------------------- +! Medium-sized zooplankton (typically copepods, 0.2-2 mm) +! Diet: Omnivorous - phytoplankton, microzooplankton, detritus +! Ecological role: Link between primary producers and fish +! --------------------------------------------------------------------- + +CASE ('grazmeso_tot') + ! ===================================================================== + ! Variable: grazmeso_tot + ! Description: Total mesozooplankton grazing (carbon ingested) + ! Function: Sum of all prey items × grazing efficiency + ! Fate of ingested C: Growth + respiration + excretion + egestion + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmeso_tot', 'Total grazing flux of mesozooplankton, dependent on grazing efficiency', 'mmolC/(m2d)', grazmeso_tot, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + +CASE ('grazmeso_n') + ! ===================================================================== + ! Variable: grazmeso_n + ! Description: Mesozooplankton grazing on nanophytoplankton + ! Function: Carbon loss from nanophyto pool due to mesozoo predation + ! Note: Includes both ingested and sloppy feeding (→ DOM/detritus) + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmeso_n', 'Grazing flux of mesozooplankton on small phytoplankton without grazing efficiency (i.e., = loss small phytoplankton)', 'mmolC/(m2d)', grazmeso_n, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmeso_d') + ! ===================================================================== + ! Variable: grazmeso_d + ! Description: Mesozooplankton grazing on diatoms + ! Function: Carbon loss from diatom pool + ! Ecological note: Copepods are major diatom grazers in blooms + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmeso_d', 'Grazing flux of mesozooplankton on diatoms without grazing efficiency (i.e., = loss diatoms)', 'mmolC/(m2d)', grazmeso_d, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmeso_c') + ! ===================================================================== + ! Variable: grazmeso_c + ! Description: Mesozooplankton grazing on coccolithophores + ! Function: Carbon loss from coccolithophore pool + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmeso_c', 'Grazing flux of mesozooplankton on coccolithophores without grazing efficiency (i.e., = loss coccolithophores)', 'mmolC/(m2d)', grazmeso_c, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmeso_p') + ! ===================================================================== + ! Variable: grazmeso_p + ! Description: Mesozooplankton grazing on Phaeocystis + ! Function: Carbon loss from Phaeocystis pool + ! Ecological note: Colonial Phaeocystis often poorly grazed + ! Units: mmolC/(m²*d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmeso_p', 'Grazing flux of mesozooplankton on phaeocystis without grazing efficiency (i.e., = loss phaeocystis)', 'mmolC/(m2*d)', grazmeso_p, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmeso_det') + ! ===================================================================== + ! Variable: grazmeso_det + ! Description: Mesozooplankton grazing on first detritus group + ! Function: Detritivory by mesozooplankton + ! Ecological role: Repackaging of detritus into fecal pellets + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmeso_det','Grazing flux of mesozooplankton on first detritus group without grazing efficiency (i.e., = loss first detritus group)', 'mmolC/(m2d)', grazmeso_det, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmeso_mic') + ! ===================================================================== + ! Variable: grazmeso_mic + ! Description: Mesozooplankton predation on microzooplankton + ! Function: Trophic transfer from micro- to mesozooplankton + ! Ecological significance: Microbial loop → classical food chain link + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmeso_mic', 'Grazing flux of mesozooplankton on microzooplankton without grazing efficiency (i.e., = loss microzooplankton)', 'mmolC/(m2d)', grazmeso_mic, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmeso_det2') + ! ===================================================================== + ! Variable: grazmeso_det2 + ! Description: Mesozooplankton grazing on second detritus group + ! Function: Feeding on different detritus pool (possibly larger/slower sinking) + ! Model structure: Multiple detritus pools represent different size classes + ! Units: mmolC/(m²*d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmeso_det2', 'Grazing flux of mesozooplankton on first detritus without grazing efficiency (i.e., = loss second detritus group)', 'mmolC/(m2*d)', grazmeso_det2, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +! --------------------------------------------------------------------- +! MACROZOOPLANKTON GRAZING +! --------------------------------------------------------------------- +! Large zooplankton (euphausiids/krill, large copepods, >2 mm) +! Diet: Phytoplankton, smaller zooplankton, detritus +! Ecological role: Major prey for fish, seabirds, marine mammals +! --------------------------------------------------------------------- + +CASE ('grazmacro_tot') + ! ===================================================================== + ! Variable: grazmacro_tot + ! Description: Total macrozooplankton grazing (carbon ingested) + ! Function: Total carbon intake by macrozooplankton + ! Ecological importance: Critical for upper trophic levels + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmacro_tot', 'Total grazing flux of macrozooplankton, dependent on grazing efficiency', 'mmolC/(m2d)', grazmacro_tot, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmacro_n') + ! ===================================================================== + ! Variable: grazmacro_n + ! Description: Macrozooplankton grazing on nanophytoplankton + ! Function: Loss from nanophyto due to macrozooplankton + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmacro_n','Grazing flux of macrozooplankton on small phytoplankton without grazing efficiency (i.e., = loss small phytoplankton)', 'mmolC/(m2d)', grazmacro_n, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmacro_d') + ! ===================================================================== + ! Variable: grazmacro_d + ! Description: Macrozooplankton grazing on diatoms + ! Function: Loss from diatoms due to macrozooplankton + ! Example: Antarctic krill feeding on diatom blooms + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmacro_d', 'Grazing flux of macrozooplankton on diatoms without grazing efficiency (i.e., = loss diatoms)','mmolC/(m2d)', grazmacro_d, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmacro_c') + ! ===================================================================== + ! Variable: grazmacro_c + ! Description: Macrozooplankton grazing on coccolithophores + ! Function: Loss from coccolithophores due to macrozooplankton + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmacro_c', 'Grazing flux of macrozooplankton on coccolithophores without grazing efficiency (i.e., = loss coccolithophores)','mmolC/(m2d)', grazmacro_c, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmacro_p') + ! ===================================================================== + ! Variable: grazmacro_p + ! Description: Macrozooplankton grazing on Phaeocystis + ! Function: Loss from Phaeocystis due to macrozooplankton + ! Units: mmolC/(m²*d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmacro_p', 'Grazing flux of macrozooplankton on phaeocystis without grazing efficiency (i.e., = loss phaeocystis)', 'mmolC/(m2*d)', grazmacro_p, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmacro_mes') + ! ===================================================================== + ! Variable: grazmacro_mes + ! Description: Macrozooplankton predation on mesozooplankton + ! Function: Carnivory - trophic transfer to higher level + ! Ecological note: Intraguild predation within zooplankton + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmacro_mes', 'Grazing flux of mesozooplankton on macrozooplankton without grazing efficiency (i.e., = loss mesozooplankton)', 'mmolC/(m2d)', grazmacro_mes, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmacro_det') + ! ===================================================================== + ! Variable: grazmacro_det + ! Description: Macrozooplankton grazing on first detritus group + ! Function: Detritivory by macrozooplankton + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmacro_det', 'Grazing flux of macrozooplankton on first detritus group without grazing efficiency (i.e., = loss first detritus group)', 'mmolC/(m2d)', grazmacro_det, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmacro_mic') + ! ===================================================================== + ! Variable: grazmacro_mic + ! Description: Macrozooplankton predation on microzooplankton + ! Function: Loss from microzooplankton to macrozooplankton + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmacro_mic', 'Grazing flux of macrozooplankton on microzooplankton without grazing efficiency (i.e., = loss microzooplankton)', 'mmolC/(m2d)', grazmacro_mic, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmacro_det2') + ! ===================================================================== + ! Variable: grazmacro_det2 + ! Description: Macrozooplankton grazing on second detritus group + ! Function: Feeding on alternative detritus pool + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmacro_det2', 'Grazing flux of macrozooplankton on first detritus without grazing efficiency (i.e., = loss second detritus group)', 'mmolC/(m2d)', grazmacro_det2, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +! --------------------------------------------------------------------- +! MICROZOOPLANKTON GRAZING +! --------------------------------------------------------------------- +! Small zooplankton (ciliates, heterotrophic flagellates, <200 μm) +! Diet: Primarily nanophytoplankton and bacteria +! Ecological role: Microbial loop - recycles nutrients rapidly +! --------------------------------------------------------------------- + +CASE ('grazmicro_tot') + ! ===================================================================== + ! Variable: grazmicro_tot + ! Description: Total microzooplankton grazing (carbon ingested) + ! Function: Total carbon intake by microzooplankton + ! Ecological importance: Dominant grazers in oligotrophic systems + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmicro_tot', 'Total grazing flux of microzooplankton, dependent on grazing efficiency', 'mmolC/(m2d)', grazmicro_tot, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmicro_n') + ! ===================================================================== + ! Variable: grazmicro_n + ! Description: Microzooplankton grazing on nanophytoplankton + ! Function: Primary grazing pressure on small phytoplankton + ! Ecological note: Can control nanophyto biomass in stratified waters + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmicro_n', 'Grazing flux of microzooplankton on small phytoplankton without grazing efficiency (i.e., = loss small phytoplankton)', 'mmolC/(m2d)', grazmicro_n, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmicro_d') + ! ===================================================================== + ! Variable: grazmicro_d + ! Description: Microzooplankton grazing on diatoms + ! Function: Microzoo predation on diatoms (less common, size-limited) + ! Note: Typically graze smaller diatom species/early stages + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmicro_d', 'Grazing flux of microzooplankton on diatoms without grazing efficiency (i.e., = loss diatoms)', 'mmolC/(m2d)', grazmicro_d, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmicro_c') + ! ===================================================================== + ! Variable: grazmicro_c + ! Description: Microzooplankton grazing on coccolithophores + ! Function: Microzoo predation on coccolithophores + ! Units: mmolC/(m²d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, 'grazmicro_c', & + 'Grazing flux of microzooplankton on coccolithophores without grazing efficiency (i.e., = loss coccolithophores)', 'mmolC/(m2d)', grazmicro_c, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('grazmicro_p') + ! ===================================================================== + ! Variable: grazmicro_p + ! Description: Microzooplankton grazing on Phaeocystis + ! Function: Microzoo predation on Phaeocystis + ! Note: Primarily graze solitary cells, not large colonies + ! Units: mmolC/(m²*d) + ! ===================================================================== + call def_stream(nod2D, myDim_nod2D, & + 'grazmicro_p', 'Grazing flux of microzooplankton on phaeocystis without grazing efficiency (i.e., = loss phaeocystis)', 'mmolC/(m2*d)', grazmicro_p, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('REMOC ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'REMOC','Total remineralization of DOC','mmolN/(m2*d)', REMOC, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('REMOCt ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'REMOCt','Remineralization of terrigenous DOC','mmolC/(m2*d)', REMOCt, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if +CASE ('REMON ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'REMON','Total remineralization of DON','mmolC/(m2*d)', REMON, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('DISSOSi ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'DISSOSi','Dissolution of Si','mmolSi/(m2*d)', DISSOSi, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('DISSOC ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'DISSOC','Dissolution of POC','mmolC/(m2*d)', DISSOC, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('DISSON ') + if (use_REcoM) then + call def_stream(nod2D, myDim_nod2D, 'DISSON','Dissolution of PON','mmolN/(m2*d)', DISSON, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +#endif + !___________________________________________________________________________________________________________________________________ !>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 3D streams <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< !___________________________________________________________________________________________________________________________________ @@ -699,122 +1635,1080 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) #if defined(__recom) +! ===================================================================== +! CARBONATE CHEMISTRY VARIABLES +! Description: Variables related to ocean carbon chemistry and pH +! ===================================================================== + CASE ('PAR ') + ! ===================================================================== + ! Variable: PAR + ! Description: Photosynthetically Active Radiation + ! Function: Light energy available for photosynthesis (400-700nm wavelength) + ! Role: Primary driver of phytoplankton growth + ! Units: W/m² + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'PAR', 'PAR', 'W/m2', PAR3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('CO2 ') + ! ===================================================================== + ! Variable: CO2 + ! Description: Aqueous CO2 concentration + ! Function: Dissolved CO2 in seawater, primary inorganic carbon form + ! Role: Substrate for phytoplankton photosynthesis, pH regulator + ! Units: mol/m³ + ! ===================================================================== if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PAR', 'PAR', 'W/m2', PAR3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'CO2', 'Aqueous CO2 concentration', 'mol/m3', CO23D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if +CASE ('pH ') + ! ===================================================================== + ! Variable: pH + ! Description: Acidity/alkalinity of seawater (total scale) + ! Function: Measure of hydrogen ion concentration + ! Role: Affects carbonate chemistry, organism physiology, calcification + ! Units: total scale (dimensionless, typically 7.5-8.5 in ocean) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'pH', 'pH', 'total scale', pH3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('pCO2 ') + ! ===================================================================== + ! Variable: pCO2 + ! Description: Partial pressure of CO2 in seawater + ! Function: CO2 fugacity in equilibrium with atmosphere + ! Role: Determines air-sea CO2 flux direction and magnitude + ! Units: μatm (microatmospheres) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'pCO2', 'CO2 partial pressure', 'uatm', pCO23D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('HCO3 ') + ! ===================================================================== + ! Variable: HCO3 + ! Description: Bicarbonate ion concentration + ! Function: Major dissolved inorganic carbon species (~90% of DIC) + ! Role: pH buffer, carbon source for some phytoplankton + ! Units: mol/m³ + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'HCO3', 'Bicarbonate ion concentration', 'mol/m3', HCO33D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('CO3 ') + ! ===================================================================== + ! Variable: CO3 + ! Description: Carbonate ion concentration + ! Function: Secondary dissolved inorganic carbon species + ! Role: Building block for calcium carbonate (CaCO3) formation + ! Units: mol/m³ + ! ===================================================================== + 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) + end if + +CASE ('OmegaC ') + ! ===================================================================== + ! Variable: OmegaC + ! Description: Calcite saturation state (Ω) + ! Function: Ratio of [Ca²⁺][CO3²⁻] to calcite solubility product + ! Role: Determines calcification vs dissolution; Ω>1 favors precipitation + ! Context: Ocean acidification reduces Ω, threatening calcifying organisms + ! Units: NN (dimensionless) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'OmegaC','calcite saturation state', 'NN', OmegaC3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('kspc ') + ! ===================================================================== + ! Variable: kspc + ! Description: Calcite solubility product + ! Function: Equilibrium constant for CaCO3 dissolution + ! Role: Temperature/pressure dependent; controls calcite stability + ! Units: mol²/kg² + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'kspc', 'calcite solubility product', 'mol^2/kg^2', kspc3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('rhoSW ') + ! ===================================================================== + ! Variable: rhoSW + ! Description: In-situ seawater density + ! Function: Density at ambient temperature, salinity, and pressure + ! Role: Physical property affecting stratification and mixing + ! Units: mol/m³ (CHECK: unusual units, typically kg/m³) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'rhoSW', 'in-situ density of seawater', 'mol/m3', rhoSW3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +! ===================================================================== +! PARTICLE DYNAMICS - DENSITY AND SINKING +! Description: Physical properties of detrital particles +! ===================================================================== + +CASE ('rho_det1 ') + ! ===================================================================== + ! Variable: rho_det1 + ! Description: Density of detrital particles in size class 1 + ! Function: Mass per unit volume of small/slow-sinking particles + ! Role: Determines sinking speed via Stokes' law + ! Context: Lower density = slower sinking = longer remineralization time + ! Units: kg/m³ + ! ===================================================================== + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'rho_det1', 'rho of particles in class 1', 'kg/m3', rho_particle1(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('rho_det2 ') + ! ===================================================================== + ! Variable: rho_det2 + ! Description: Density of detrital particles in size class 2 + ! Function: Mass per unit volume of large/fast-sinking particles + ! Role: Determines sinking speed via Stokes' law + ! Context: Higher density = faster sinking = efficient carbon export + ! Units: kg/m³ + ! ===================================================================== + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'rho_det2', 'rho of particles in class 2', 'kg/m3', rho_particle2(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('scaling_visc ') + ! ===================================================================== + ! Variable: scaling_visc + ! Description: Viscosity-based scaling factor for sinking speed + ! Function: Adjusts particle sinking based on water viscosity + ! Role: Temperature/salinity affect viscosity, thus sinking rates + ! Context: Warmer water = lower viscosity = faster sinking + ! Units: n.d. (non-dimensional scaling factor) + ! ===================================================================== + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'scaling_visc', 'scaling factor of particle sinking speed', 'n.d.', scaling_visc_3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('wsink_det1') + ! ===================================================================== + ! Variable: wsink_det1 + ! Description: Sinking velocity of particle class 1 + ! Function: Vertical descent rate of small detrital particles + ! Role: Controls residence time in euphotic zone, carbon export efficiency + ! Context: Typically 1-50 m/day for small aggregates + ! Units: m/s + ! ===================================================================== + call def_stream((/nl, nod2D/), (/nl, myDim_nod2D/), & + 'wsink_det1', 'sinking speed of particles in class 1', 'm s-1', Sinkingvel1(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('wsink_det2') + ! ===================================================================== + ! Variable: wsink_det2 + ! Description: Sinking velocity of particle class 2 + ! Function: Vertical descent rate of large detrital particles + ! Role: Fast export pathway for carbon to deep ocean + ! Context: Typically 50-200+ m/day for large aggregates/fecal pellets + ! Units: m/s + ! ===================================================================== + call def_stream((/nl, nod2D/), (/nl, myDim_nod2D/), & + 'wsink_det2', 'sinking speed of particles in class 2', 'm s-1', Sinkingvel2(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +! ===================================================================== +! BENTHIC NUTRIENT FLUXES +! Description: Sediment-water interface nutrient release +! ===================================================================== + +CASE ('DIC_bf') + ! ===================================================================== + ! Variable: DIC_bf + ! Description: Dissolved Inorganic Carbon bottom flux + ! Function: Release of CO2/HCO3/CO3 from sediment remineralization + ! Role: Recycles organic carbon back to water column + ! Context: Important in shallow seas, negligible in deep ocean + ! Units: mmolC/m³ + ! ===================================================================== + call def_stream((/nl, nod2D/), (/nl, myDim_nod2D/), & + 'DIC_bf', 'DIC bottom flux', 'mmolC/m3', dtr_bflux_dic(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('DIN_bf') + ! ===================================================================== + ! Variable: DIN_bf + ! Description: Dissolved Inorganic Nitrogen bottom flux + ! Function: Release of NH4⁺/NO3⁻ from sediment remineralization + ! Role: Nutrient regeneration supporting primary production + ! Context: Major N source in coastal/shelf systems + ! Units: mmolN/m³ + ! ===================================================================== + call def_stream((/nl, nod2D/), (/nl, myDim_nod2D/), & + 'DIN_bf', 'DIN bottom flux', 'mmolC/m3', dtr_bflux_din(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('Alk_bf') + ! ===================================================================== + ! Variable: Alk_bf + ! Description: Alkalinity bottom flux + ! Function: Release of acid-neutralizing capacity from sediments + ! Role: Affects pH and carbonate chemistry of bottom waters + ! Context: Dominated by NH4⁺ production and CaCO3 dissolution + ! Units: mmolC/m³ (CHECK: should be meq/m³) + ! ===================================================================== + call def_stream((/nl, nod2D/), (/nl, myDim_nod2D/), & + 'Alk_bf', 'Alk bottom flux', 'mmolC/m3', dtr_bflux_alk(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +CASE ('DSi_bf') + ! ===================================================================== + ! Variable: DSi_bf + ! Description: Dissolved Silicate bottom flux + ! Function: Release of Si(OH)4 from opal dissolution in sediments + ! Role: Critical nutrient for diatom growth + ! Context: Can control diatom vs non-diatom dominance + ! Units: mmolSi/m³ + ! ===================================================================== + call def_stream((/nl, nod2D/), (/nl, myDim_nod2D/), & + 'DSi_bf', 'DSi bottom flux', 'mmolC/m3', dtr_bflux_dsi(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + +! ===================================================================== +! ZOOPLANKTON RESPIRATION +! Description: Metabolic CO2 production by different zooplankton size classes +! ===================================================================== + CASE ('respmeso ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'respmeso','Respiration rate of mesozooplankton', 'mmolC/m2/d', respmeso(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: respmeso + ! Description: Respiration rate of mesozooplankton + ! Function: Metabolic CO2 release by medium-sized grazers (0.2-2 mm) + ! Role: Returns carbon to DIC pool, drives oxygen consumption + ! Taxa: Copepods, euphausiids, chaetognaths + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'respmeso', 'Respiration rate of mesozooplankton', 'mmolC/m2/d', respmeso(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('respmacro ') - if (use_REcoM) then ! .and. three_zoo_two_det) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'respmacro','Respiration rate of macrozooplankton', 'mmolC/m2/d', respmacro(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: respmacro + ! Description: Respiration rate of macrozooplankton + ! Function: Metabolic CO2 release by large grazers (>2 mm) + ! Role: Produces fast-sinking fecal pellets, vertical carbon transport + ! Taxa: Large euphausiids, amphipods, jellyfish + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'respmacro', 'Respiration rate of macrozooplankton', 'mmolC/m2/d', respmacro(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('respmicro ') - if (use_REcoM) then ! .and. three_zoo_two_det) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'respmicro','Respiration rate of microzooplankton', 'mmolC/m2/d', respmicro(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: respmicro + ! Description: Respiration rate of microzooplankton + ! Function: Metabolic CO2 release by small grazers (<0.2 mm) + ! Role: Rapid nutrient recycling in microbial loop + ! Taxa: Ciliates, heterotrophic dinoflagellates + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'respmicro', 'Respiration rate of microzooplankton', 'mmolC/m2/d', respmicro(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +! ===================================================================== +! SECTION 5: CALCIUM CARBONATE DYNAMICS +! Description: Calcification and dissolution processes +! ===================================================================== CASE ('calcdiss ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'calcdiss','Calcite dissolution', 'mmolC/m2/d', calcdiss(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: calcdiss + ! Description: Calcite (CaCO3) dissolution rate + ! Function: Conversion of solid CaCO3 back to dissolved Ca²⁺ and CO3²⁻ + ! Role: Increases alkalinity, releases CO2, occurs when Ω < 1 + ! Context: Accelerated by ocean acidification + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'calcdiss', 'Calcite dissolution', 'mmolC/m2/d', calcdiss(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('calcif ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'calcif','Calcification', 'mmolC/m2/d', calcif(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: calcif + ! Description: Calcification rate (CaCO3 formation) + ! Function: Precipitation of calcium carbonate shells/tests + ! Role: Decreases alkalinity, releases CO2, ballasts organic carbon + ! Organisms: Coccolithophores, foraminifera, pteropods + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'calcif', 'Calcification', 'mmolC/m2/d', calcif(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +! ===================================================================== +! PHYTOPLANKTON AGGREGATION +! Description: Formation of larger particles from small cells +! ===================================================================== CASE ('aggn ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'aggn','Aggregation of small phytoplankton', 'mmolC/m2/d', aggn(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: aggn + ! Description: Aggregation of small (nano) phytoplankton + ! Function: Collision-driven clumping of 2-20 μm cells + ! Role: Converts slow-sinking cells to faster-sinking aggregates + ! Context: Enhanced by stickiness (TEP), turbulence, high cell density + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'aggn', 'Aggregation of small phytoplankton', 'mmolC/m2/d', aggn(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('aggd ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'aggd','Aggregation of diatoms', 'mmolC/m2/d', aggd(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: aggd + ! Description: Aggregation of diatoms + ! Function: Formation of diatom-dominated marine snow + ! Role: Major pathway for carbon export during bloom collapse + ! Context: Si:C ballasting enhances sinking speed (100-200 m/day) + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'aggd', 'Aggregation of diatoms', 'mmolC/m2/d', aggd(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('aggc ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'aggc','Aggregation of coccolithophores', 'mmolC/m2/d', aggc(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: aggc + ! Description: Aggregation of coccolithophores + ! Function: Formation of coccolith-bearing aggregates + ! Role: CaCO3 ballasting enhances export efficiency + ! Context: Creates "white waters" visible from space during blooms + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'aggc', 'Aggregation of coccolithophores', 'mmolC/m2/d', aggc(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('aggp ') + ! ===================================================================== + ! Variable: aggp + ! Description: Aggregation of Phaeocystis + ! Function: Colony formation and aggregation of colonial haptophyte + ! Role: Forms mucilaginous colonies up to 3 cm, efficient export + ! Context: Dominant in polar/subpolar regions, nuisance blooms + ! Units: mmolC/(m²*d) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'aggp', 'Aggregation of phaeocystis', 'mmolC/(m2*d)', aggp(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +! ===================================================================== +! DISSOLVED ORGANIC CARBON (DOC) EXCRETION +! Description: Release of dissolved organics by phytoplankton +! ===================================================================== CASE ('docexn ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'docexn','DOC excretion by small phytoplankton', 'mmolC/m2/d', docexn(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: docexn + ! Description: DOC excretion by nanophytoplankton + ! Function: Passive/active release of dissolved organic compounds + ! Role: Fuels microbial loop, can be 5-20% of gross production + ! Context: Increases under nutrient stress or viral lysis + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'docexn', 'DOC excretion by small phytoplankton', 'mmolC/m2/d', docexn(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('docexd ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'docexd','DOC excretion by diatoms', 'mmolC/m2/d', docexd(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: docexd + ! Description: DOC excretion by diatoms + ! Function: Release of organic compounds from diatom metabolism + ! Role: Can be substantial during stationary phase or Si limitation + ! Context: Includes transparent exopolymer particles (TEP) + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'docexd', 'DOC excretion by diatoms', 'mmolC/m2/d', docexd(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('docexc ') + ! ===================================================================== + ! Variable: docexc + ! Description: DOC excretion by coccolithophores + ! Function: Release of organic compounds during calcification/growth + ! Role: Links organic and inorganic carbon cycles + ! Context: May increase under high pCO2 (ocean acidification) + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'docexc', 'DOC excretion by coccolithophores', 'mmolC/m2/d', docexc(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('docexp ') + ! ===================================================================== + ! Variable: docexp + ! Description: DOC excretion by Phaeocystis + ! Function: Release of polysaccharides forming colonial matrix + ! Role: Major mucus producer, can create foam on beaches + ! Context: High C:N ratio DOC, relatively refractory + ! Units: mmolC/(m²*d) + ! ===================================================================== if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'docexc','DOC excretion by coccolithophores', 'mmolC/m2/d', docexc(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'docexp', 'DOC excretion by phaeocystis', 'mmolC/(m2*d)', docexp(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif +! ===================================================================== +! PHYTOPLANKTON RESPIRATION +! Description: Metabolic CO2 release by autotrophs +! ===================================================================== + CASE ('respn ') + ! ===================================================================== + ! Variable: respn + ! Description: Respiration by nanophytoplankton + ! Function: Maintenance metabolism and biosynthesis costs + ! Role: Determines net vs gross primary production (NPP vs GPP) + ! Context: Typically 10-30% of GPP, increases with temperature + ! Units: mmolC/m²/d + ! ===================================================================== if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'respn','Respiration by small phytoplankton', 'mmolC/m2/d', respn(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'respn', 'Respiration by small phytoplankton', 'mmolC/m2/d', respn(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif CASE ('respd ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'respd','Respiration by diatoms', 'mmolC/m2/d', respd(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: respd + ! Description: Respiration by diatoms + ! Function: Metabolic costs of rapid growth and Si metabolism + ! Role: Higher in fast-growing bloom-forming species + ! Context: Can increase under nutrient limitation + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'respd', 'Respiration by diatoms', 'mmolC/m2/d', respd(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('respc ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'respc','Respiration by coccolithophores', 'mmolC/(m2*d)', respc(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: respc + ! Description: Respiration by coccolithophores + ! Function: Metabolic costs including calcification energy + ! Role: Calcification requires ~20% additional energy vs non-calcifiers + ! Context: May increase under ocean acidification stress + ! Units: mmolC/(m²*d) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'respc', 'Respiration by coccolithophores', 'mmolC/(m2*d)', respc(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('respp ') + ! ===================================================================== + ! Variable: respp + ! Description: Respiration by Phaeocystis + ! Function: Metabolic costs of colonial vs solitary forms + ! Role: Colonial forms may have lower specific respiration rates + ! Context: Life cycle shifts affect carbon cycling + ! Units: mmolC/(m²*d) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'respp', 'Respiration by phaeocystis', 'mmolC/(m2*d)', respp(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +! ===================================================================== +! NET PRIMARY PRODUCTION (NPP) BY FUNCTIONAL GROUP +! Description: Net carbon fixation after respiration losses +! ===================================================================== CASE ('NPPn3D ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'NPPn3D','Net primary production of small phytoplankton', 'mmolC/m2/d', NPPn3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: NPPn3D + ! Description: Net Primary Production of nanophytoplankton + ! Function: Gross photosynthesis minus respiration and exudation + ! Role: Sustained baseline production in oligotrophic waters + ! Ecology: Dominant in stratified, nutrient-poor conditions + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'NPPn3D', 'Net primary production of small phytoplankton', 'mmolC/m2/d', NPPn3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('NPPd3D ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'NPPd3D','Net primary production of diatoms', 'mmolC/m2/d', NPPd3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! Variable: NPPd3D + ! Description: Net Primary Production of diatoms + ! Function: Net carbon fixation by silicified phytoplankton + ! Role: Bloom-forming, episodic production pulses + ! Ecology: Dominant in upwelling, mixed, nutrient-rich waters + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'NPPd3D', 'Net primary production of diatoms', 'mmolC/m2/d', NPPd3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('NPPc3D ') + ! ===================================================================== + ! Variable: NPPc3D + ! Description: Net Primary Production of coccolithophores + ! Function: Net carbon fixation by calcifying haptophytes + ! Role: Links organic and inorganic carbon pumps + ! Ecology: Bloom in stratified, post-bloom nutrient-depleted waters + ! Units: mmolC/m²/d + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'NPPc3D', 'Net primary production of coccolithophores', 'mmolC/m2/d', NPPc3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('NPPp3D ') + ! ===================================================================== + ! Variable: NPPp3D + ! Description: Net Primary Production of Phaeocystis + ! Function: Net carbon fixation by colonial haptophyte + ! Role: High-latitude spring bloom specialist + ! Ecology: Tolerates low light, cold temperatures, ice-edge blooms + ! Units: mmolC/(m²*d) + ! ===================================================================== if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'NPPc3D','Net primary production of coccolithophores', 'mmolC/m2/d', NPPc3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, 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) endif -#endif -!CASE ('otracers ') -! do j=3, tracers%num_tracers -! write (id_string, "(I3.3)") tracers%data(j)%ID -! call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'tra_'//id_string, 'pasive tracer ID='//id_string, 'n/a', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) -! end do +! ===================================================================== +! TEMPERATURE EFFECTS ON PHOTOSYNTHESIS +! Description: Temperature-dependent growth rate modifiers +! ===================================================================== + +CASE ('TTemp_diatoms ') + ! ===================================================================== + ! Variable: TTemp_diatoms + ! Description: Temperature dependence factor for diatom photosynthesis + ! Function: Q10-based or Arrhenius growth rate modifier + ! Role: Accelerates growth in warmer waters + ! Context: Diatoms often have lower temperature optimum than flagellates + ! Units: per day (dimensionless multiplier) + ! ===================================================================== + 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) + endif + +CASE ('TTemp_phyto ') + ! ===================================================================== + ! Variable: TTemp_phyto + ! Description: Temperature dependence factor for nanophytoplankton + ! Function: Growth rate scaling with temperature + ! Role: Often have broader temperature tolerance than specialists + ! Context: May benefit from warming in temperate/tropical regions + ! Units: per day (dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TTemp_phyto', 'Temperature dependence of small phytoplankton PS', 'per day', TTemp_phyto(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TTemp_cocco ') + ! ===================================================================== + ! Variable: TTemp_cocco + ! Description: Temperature dependence factor for coccolithophores + ! Function: Growth rate and calcification temperature sensitivity + ! Role: Often have higher temperature optima than diatoms + ! Context: May expand poleward with warming + ! Units: per day (dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TTemp_cocco', 'Temperature dependence of coccolithophores PS', 'per day', TTemp_cocco(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TTemp_phaeo ') + ! ===================================================================== + ! Variable: TTemp_phaeo + ! Description: Temperature dependence factor for Phaeocystis + ! Function: Growth rate scaling in cold polar waters + ! Role: Adapted to low temperatures (0-10°C optimum) + ! Context: Climate warming may reduce competitive advantage + ! Units: per day (dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TTemp_phaeo', 'Temperature dependence of phaeocystis PS', 'per day', TTemp_phaeo(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +! ===================================================================== +! SECTION 11: CO2 EFFECTS ON PHOTOSYNTHESIS +! Description: pCO2-dependent growth modifiers (ocean acidification impacts) +! ===================================================================== + +CASE ('TPhyCO2 ') + ! ===================================================================== + ! Variable: TPhyCO2 + ! Description: Effect of CO2 on nanophytoplankton growth + ! Function: Carbon concentration mechanism (CCM) efficiency modifier + ! Role: Some species benefit from higher CO2 (reduced CCM energy cost) + ! Context: Generally small positive or neutral effect + ! Units: per day (dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TPhyCO2', 'Effect of CO2 of phyto growth/PS', 'per day', TPhyCO2(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TDiaCO2 ') + ! ===================================================================== + ! Variable: TDiaCO2 + ! Description: Effect of CO2 on diatom growth + ! Function: CCM efficiency and photorespiration modifier + ! Role: Mixed responses, some species C3-like, others have efficient CCMs + ! Context: High CO2 may reduce competitive advantage vs other groups + ! Units: per day (dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TDiaCO2', 'Effect of CO2 of phyto growth/PS', 'per day', TDiaCO2(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TCoccoCO2 ') + ! ===================================================================== + ! Variable: TCoccoCO2 + ! Description: Effect of CO2 on coccolithophore growth + ! Function: Photosynthesis vs calcification trade-off under high CO2 + ! Role: High pCO2 may benefit photosynthesis but impair calcification + ! Context: Net effect species-specific, generally negative at >1000 μatm + ! Units: per day (dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TCoccoCO2', 'Effect of CO2 of phyto growth/PS', 'per day', TCoccoCO2(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TPhaeoCO2 ') + ! ===================================================================== + ! Variable: TPhaeoCO2 + ! Description: Effect of CO2 on Phaeocystis growth + ! Function: CCM efficiency in high-latitude species + ! Role: May benefit from CO2 enrichment in cold waters + ! Context: Limited experimental data compared to other groups + ! Units: per day (dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TPhaeoCO2', 'Effect of CO2 of phyto growth/PS', 'per day', TPhaeoCO2(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +! ===================================================================== +! SECTION 12: NUTRIENT LIMITATION FACTORS +! Description: Multi-nutrient limitation of photosynthesis +! ===================================================================== + +CASE ('TqLF_phyto ') + ! ===================================================================== + ! Variable: TqLF_phyto + ! Description: Nutrient limitation factor for nanophytoplankton + ! Function: Minimum of N, P, Fe limitation (Liebig's Law) + ! Role: Determines realized vs maximum potential growth rate + ! Context: Often N-limited in stratified waters, Fe-limited in HNLC + ! Units: per day (0-1 dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TqLF_phyto', 'Nutrient limitation effect of phyto PS', 'per day', TqlimitFac_phyto(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TqLF_diatoms ') + ! ===================================================================== + ! Variable: TqLF_diatoms + ! Description: Nutrient limitation factor for diatoms + ! Function: Minimum of N, P, Si, Fe limitation + ! Role: Si limitation unique to diatoms, controls bloom termination + ! Context: Si:N ratio critical for diatom vs flagellate competition + ! Units: per day (0-1 dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TqLF_diatoms', 'Nutrient limitation effect of diatoms PS', 'per day', TqlimitFac_diatoms(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TqLF_cocco ') + ! ===================================================================== + ! Variable: TqLF_cocco + ! Description: Nutrient limitation factor for coccolithophores + ! Function: Minimum of N, P limitation (no Si requirement) + ! Role: Can exploit low-nutrient conditions after diatom bloom collapse + ! Context: High C:N, C:P ratios during severe limitation + ! Units: per day (0-1 dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'TqLF_cocco','Nutrient limitation effect of diatoms PS', 'per day',TqlimitFac_cocco(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TqLF_phaeo ') + ! ===================================================================== + ! Variable: TqLF_phaeo + ! Description: Nutrient limitation factor for Phaeocystis + ! Function: Minimum of N, P, Fe limitation + ! Role: Can form luxury nutrient reserves in colonial form + ! Context: Often blooms early when nutrients still replete + ! Units: per day (0-1 dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TqLF_phaeo', 'Nutrient limitation effect of diatoms PS', 'per day', TqlimitFac_phaeo(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +! ===================================================================== +! LIGHT LIMITATION FACTORS +! Description: Photosynthesis-irradiance relationship modifiers +! ===================================================================== + +CASE ('TCphotLL_phyto ') + ! ===================================================================== + ! Variable: TCphotLL_phyto + ! Description: Light limitation factor for nanophytoplankton + ! Function: P-I curve response (typically hyperbolic tangent or exponential) + ! Role: Reduces growth in low light, photoinhibition at high light + ! Context: Small cells acclimate faster to changing light + ! Units: per day (0-1 dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TCphotLL_phyto', 'Light limitation on phyto PS', 'per day', TCphotLigLim_phyto(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TCphotLL_dia ') + ! ===================================================================== + ! Variable: TCphotLL_dia + ! Description: Light limitation factor for diatoms + ! Function: P-I curve with potentially higher light saturation point + ! Role: Often shade-adapted in coastal turbid waters + ! Context: Larger cells = slower photoacclimation + ! Units: per day (0-1 dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TCphotLL_dia', 'Light limitation on diatoms PS', 'per day', TCphotLigLim_diatoms(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TCphotLL_cocco ') + ! ===================================================================== + ! Variable: TCphotLL_cocco + ! Description: Light limitation factor for coccolithophores + ! Function: P-I curve for high-light adapted species + ! Role: Often prefer high irradiance, stratified waters + ! Context: Bloom in clear waters with deep light penetration + ! Units: per day (0-1 dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TCphotLL_cocco', 'Light limitation on phyto PS', 'per day', TCphotLigLim_cocco(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TCphotLL_phaeo ') + ! ===================================================================== + ! Variable: TCphotLL_phaeo + ! Description: Light limitation factor for Phaeocystis + ! Function: P-I curve for low-light adapted polar species + ! Role: Low light saturation point, efficient in weak polar light + ! Context: Can grow under sea ice with <1% surface irradiance + ! Units: per day (0-1 dimensionless multiplier) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TCphotLL_phaeo', 'Light limitation on phyto PS', 'per day', TCphotLigLim_phaeo(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + + +! ===================================================================== +! CARBON-SPECIFIC PHOTOSYNTHESIS RATES +! Description: Actual photosynthetic carbon fixation rates +! ===================================================================== + +CASE ('TCphot_phyto ') + ! ===================================================================== + ! Variable: TCphot_phyto + ! Description: Carbon-specific photosynthesis rate of nanophytoplankton + ! Function: Gross carbon fixation per unit biomass + ! Role: Product of all limiting factors × maximum rate + ! Context: Typically 0.5-3.0 d⁻¹ in natural populations + ! Units: per day (d⁻¹) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TCphot_phyto', 'Light limitation on phyto PS', 'per day', TCphot_phyto(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TCphot_diatoms ') + ! ===================================================================== + ! Variable: TCphot_diatoms + ! Description: Carbon-specific photosynthesis rate of diatoms + ! Function: Gross carbon fixation per unit biomass + ! Role: Can reach very high rates (>5 d⁻¹) during blooms + ! Context: r-strategists with high maximum growth rates + ! Units: per day (d⁻¹) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TCphot_diatoms', 'Light limitation on phyto PS', 'per day', TCphot_diatoms(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TCphot_cocco ') + ! ===================================================================== + ! Variable: TCphot_cocco + ! Description: Carbon-specific photosynthesis rate of coccolithophores + ! Function: Gross carbon fixation including calcification costs + ! Role: Lower than diatoms but sustained in stratified conditions + ! Context: Additional energy for CaCO3 formation reduces net efficiency + ! Units: per day (d⁻¹) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TCphot_cocco', 'Light limitation on phyto PS', 'per day', TCphot_cocco(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +CASE ('TCphot_phaeo ') + ! ===================================================================== + ! Variable: TCphot_phaeo + ! Description: Carbon-specific photosynthesis rate of Phaeocystis + ! Function: Gross carbon fixation in colonial or solitary forms + ! Role: Efficient at low temperature and light + ! Context: Colonial forms may have lower per-cell rates but higher bloom biomass + ! Units: per day (d⁻¹) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TCphot_phaeo', 'Light limitation on phyto PS', 'per day', TCphot_phaeo(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +! ===================================================================== +! SILICATE ASSIMILATION +! Description: Diatom-specific nutrient uptake +! ===================================================================== + +CASE ('TSi_assimDia ') + ! ===================================================================== + ! Variable: TSi_assimDia + ! Description: Silicate assimilation rate by diatoms + ! Function: Uptake of Si(OH)4 for frustule (shell) construction + ! Role: Couples diatom growth to silicon cycle + ! Context: Si:C ratio varies 0.1-1.0 depending on species and conditions + ! Ecology: Si depletion terminates diatom blooms, shifts to flagellates + ! Units: per day (d⁻¹) + ! ===================================================================== + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'TSi_assimDia', 'Silicate assimilation', 'per day', TSi_assimDia(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + +#endif CASE ('otracers ') do j=3, tracers%num_tracers write (id_string, "(I4.4)") tracers%data(j)%ID #if defined(__recom) + ! ===================================================================== + ! Base tracers (always present in all configurations) + ! Tracer IDs: 1001-1022 (indices 3-24) + ! ===================================================================== if (tracers%data(j)%ID==1001) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN', 'Dissolved Inorganic Nitrogen', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif + + + if (tracers%data(j)%ltra_diag) then + ! horizontal advection + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN_hor_adv', 'Horizontal advection part of dissolved Inorganic N', '[mmol/m3]', tracers%work%tra_advhoriz(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + ! horizontal advection LO + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN_lo_hor_adv', 'LO Horizontal advection part of dissolved Inorganic N', '[mmol/m3]', tracers%work%tra_advhoriz_LO(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical advection + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN_ver_adv', 'Vertical advection part of dissolved Inorganic N', '[mmol/m3]', tracers%work%tra_advvert(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical advection LO + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN_lo_ver_adv', 'LO Vertical advection part of dissolved Inorganic N', '[mmol/m3]', tracers%work%tra_advvert_LO(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! horizontal diffusion + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN_tra_diff_part_hor_redi', 'Horizontal diffusion of dissolved Inorganic N (includes Redi diffusivity if Redi=.true.)', '[mmol/m3]', tracers%work%tra_diff_part_hor_redi(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + if (tracers%data(j)%i_vert_diff) then + ! vertical diffusion (Explicit) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN_tra_diff_part_ver_expl', 'Vertical diffusion of dissolved Inorganic N (Explicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + + ! projection of horizontal Redi diffussivity onto vertical + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN_tra_diff_part_ver_redi_expl', 'Projection of horizontal Redi diffussivity onto vertical for dissolved Inorganic N (Explicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_redi_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical diffusion (Implicit) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN_tra_diff_part_ver_impl', 'Vertical diffusion of dissolved Inorganic N (Implicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_impl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! recom_sms + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIN_recom_sms', 'Recom SMS', '[mmol/m3]', tracers%work%tra_recom_sms(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + + + + + + + + else if (tracers%data(j)%ID==1002) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC', 'Dissolved Inorganic C', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + if (tracers%data(j)%ltra_diag) then + ! horizontal advection + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC_hor_adv', 'Horizontal advection part of dissolved Inorganic C', '[mmol/m3]', tracers%work%tra_advhoriz(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + ! horizontal advection LO + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC_lo_hor_adv', 'LO Horizontal advection part of dissolved Inorganic C', '[mmol/m3]', tracers%work%tra_advhoriz_LO(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical advection + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC_ver_adv', 'Vertical advection part of dissolved Inorganic C', '[mmol/m3]', tracers%work%tra_advvert(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical advection LO + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC_lo_ver_adv', 'LO Vertical advection part of dissolved Inorganic C', '[mmol/m3]', tracers%work%tra_advvert_LO(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! horizontal diffusion + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC_tra_diff_part_hor_redi', 'Horizontal diffusion of dissolved Inorganic C (includes Redi diffusivity if Redi=.true.)', '[mmol/m3]', tracers%work%tra_diff_part_hor_redi(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + if (tracers%data(j)%i_vert_diff) then + ! vertical diffusion (Explicit) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC_tra_diff_part_ver_expl', 'Vertical diffusion of dissolved Inorganic C (Explicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + + ! projection of horizontal Redi diffussivity onto vertical + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC_tra_diff_part_ver_redi_expl', 'Projection of horizontal Redi diffussivity onto vertical for dissolved Inorganic C (Explicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_redi_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical diffusion (Implicit) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC_tra_diff_part_ver_impl', 'Vertical diffusion of dissolved Inorganic C (Implicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_impl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! recom_sms + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DIC_recom_sms', 'Recom SMS', '[mmol/m3]', tracers%work%tra_recom_sms(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + endif else if (tracers%data(j)%ID==1003) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Alk', 'Total Alkalinity', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) +!!!!24.06.2025 + if (tracers%data(j)%ltra_diag) then ! OG - tra_diag + ! horizontal advection + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Alk_hor_adv', 'Horizontal advection part of Total Alkalinity', '[mmol/m3]', tracers%work%tra_advhoriz(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + ! horizontal advection LO + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Alk_lo_hor_adv', 'LO Horizontal advection part of Total Alkalinity', '[mmol/m3]', tracers%work%tra_advhoriz_LO(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + ! vertical advection + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Alk_ver_adv', 'Vertical advection part of Total Alkalinity', '[mmol/m3]', tracers%work%tra_advvert(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! horizontal diffusion + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Alk_tra_diff_part_hor_redi', 'Horizontal diffusion of Total Alkalinity (includes Redi diffusivity if Redi=.true.)', '[mmol/m3]', tracers%work%tra_diff_part_hor_redi(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + if (.not. tracers%data(j)%i_vert_diff) then + ! vertical diffusion (Explicit) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Alk_tra_diff_part_ver_expl', 'Vertical diffusion of Total Alkalinity (Explicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + + ! projection of horizontal Redi diffussivity onto vertical + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Alk_tra_diff_part_ver_redi_expl', 'Projection of horizontal Redi diffussivity onto vertical for Total Alkalinity (Explicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_redi_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical diffusion (Implicit) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Alk_tra_diff_part_ver_impl', 'Vertical diffusion of Total Alkalinity (Implicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_impl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! recom_sms + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Alk_recom_sms', 'Recom SMS', '[mmol/m3]', tracers%work%tra_recom_sms(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + end if endif + ! ===================================================================== + ! Small phytoplankton + ! ===================================================================== else if (tracers%data(j)%ID==1004) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhyN', 'Intracellular conc of Nitrogen in small phytoplankton', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -830,6 +2724,9 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhyChl', 'Current intracellular ChlA conc.', '[mg/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif + ! ===================================================================== + ! Detritus 1 + ! ===================================================================== else if (tracers%data(j)%ID==1007) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DetN', 'Conc of N in Detritus', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -840,6 +2737,9 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DetC', 'Conc of C in Detritus', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif + ! ===================================================================== + ! Mesozooplankton + ! ===================================================================== else if (tracers%data(j)%ID==1009) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'HetN', 'Conc of N in heterotrophs', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -850,6 +2750,9 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'HetC', 'Conc of C in heterotrophs', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif + ! ===================================================================== + ! Dissolved organic matter + ! ===================================================================== else if (tracers%data(j)%ID==1011) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DON', 'Dissolved organic N in the water', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -860,6 +2763,10 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DOC', 'Dissolved Organic C in the water', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif + ! ===================================================================== + ! Diatoms + ! ===================================================================== + else if (tracers%data(j)%ID==1013) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DiaN', 'DiaN', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -880,6 +2787,10 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DiaSi', 'DiaSi', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif + ! ===================================================================== + ! Detrital silica and other base tracers + ! ===================================================================== + else if (tracers%data(j)%ID==1017) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DetSi', 'DetSi', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -890,6 +2801,43 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi', 'DSi', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif + + if (tracers%data(j)%ltra_diag) then + ! horizontal advection + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi_hor_adv', 'Horizontal advection part of dissolved Silicic Acid', '[mmol/m3]', tracers%work%tra_advhoriz(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + ! horizontal advection LO + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi_lo_hor_adv', 'LO Horizontal advection part of dissolved Silicic Acid', '[mmol/m3]', tracers%work%tra_advhoriz_LO(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical advection + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi_ver_adv', 'Vertical advection part of dissolved Silicic Acid', '[mmol/m3]', tracers%work%tra_advvert(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical advection LO + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi_lo_ver_adv', 'LO Vertical advection part of dissolved Silicic Acid', '[mmol/m3]', tracers%work%tra_advvert_LO(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! horizontal diffusion + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi_tra_diff_part_hor_redi', 'Horizontal diffusion of dissolved Silicic Acid (includes Redi diffusivity if Redi=.true.)', '[mmol/m3]', tracers%work%tra_diff_part_hor_redi(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + if (tracers%data(j)%i_vert_diff) then + ! vertical diffusion (Explicit) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi_tra_diff_part_ver_expl', 'Vertical diffusion of dissolved Silicic Acid (Explicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + + ! projection of horizontal Redi diffussivity onto vertical + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi_tra_diff_part_ver_redi_expl', 'Projection of horizontal Redi diffussivity onto vertical for dissolved Silicic Acid (Explicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_redi_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! vertical diffusion (Implicit) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi_tra_diff_part_ver_impl', 'Vertical diffusion of dissolved Silicic Acid (Implicit)', '[mmol/m3]', tracers%work%tra_diff_part_ver_impl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + + ! recom_sms + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DSi_recom_sms', 'Recom SMS', '[mmol/m3]', tracers%work%tra_recom_sms(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + + + + + + + else if (tracers%data(j)%ID==1019) then if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DFe', 'DFe', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -910,60 +2858,247 @@ 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 + ! ===================================================================== + ! CONFIGURATION-SPECIFIC TRACERS (IDs 1023+) + ! The meaning of these IDs changes based on model configuration! + ! ===================================================================== + + ! ===================================================================== + ! Tracer ID 1023: + ! - In COCCOS-ONLY config: CoccoN (Coccolithophore Nitrogen) + ! - In 3ZOO2DET configs: Zoo2N (Macrozooplankton Nitrogen) + ! - In BASE config with rivers: DOCt (Terrestrial DOC) + ! ===================================================================== else if (tracers%data(j)%ID==1023) 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) + if (use_REcoM .and. enable_coccos .and. .not. enable_3zoo2det) then + ! Coccos-only configuration: This is Coccolithophore Nitrogen + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CoccoN', 'Coccolithophore Nitrogen', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_3zoo2det) then + ! 3zoo2det configurations: This is Macrozooplankton Nitrogen + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo2N', 'Macrozooplankton Nitrogen', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. useRivers) then + ! Base configuration with rivers: This is Terrestrial DOC + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DOCt', 'Terrestrial Dissolved Organic Carbon', '[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 + !if (use_REcoM .and. enable_3zoo2det) 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 + + ! ===================================================================== + ! Tracer ID 1024: + ! - In COCCOS-ONLY config: CoccoC (Coccolithophore Carbon) + ! - In 3ZOO2DET configs: Zoo2C (Macrozooplankton Carbon) + ! ===================================================================== else if (tracers%data(j)%ID==1024) 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) + if (use_REcoM .and. enable_coccos .and. .not. enable_3zoo2det) then + ! Coccos-only configuration: This is Coccolithophore Carbon + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CoccoC', 'Coccolithophore Carbon', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_3zoo2det) then + ! 3zoo2det configurations: This is Macrozooplankton Carbon + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo2C', 'Macrozooplankton Carbon', '[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 + !if (use_REcoM .and. enable_3zoo2det) 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 + + ! ===================================================================== + ! Tracer ID 1025: + ! - In COCCOS-ONLY config: CoccoChl (Coccolithophore Chlorophyll) + ! - In 3ZOO2DET configs: Det2N (Second detritus pool Nitrogen) + ! ===================================================================== + else if (tracers%data(j)%ID==1025) 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) + if (use_REcoM .and. enable_coccos .and. .not. enable_3zoo2det) then + ! Coccos-only configuration: This is Coccolithophore Chlorophyll + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CoccoChl', 'Coccolithophore Chlorophyll', '[mg/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_3zoo2det) then + ! 3zoo2det configurations: This is second detritus pool Nitrogen + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Det2N', 'Conc of N in second detritus pool', '[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 + !if (use_REcoM .and. enable_3zoo2det) 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 + + ! ===================================================================== + ! Tracer ID 1026: + ! - In COCCOS-ONLY config: PhaeoN (Phaeocystis Nitrogen) + ! - In 3ZOO2DET configs: Det2C (Second detritus pool Carbon) + ! ===================================================================== else if (tracers%data(j)%ID==1026) 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) + if (use_REcoM .and. enable_coccos .and. .not. enable_3zoo2det) then + ! Coccos-only configuration: This is Phaeocystis Nitrogen + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoN', 'Phaeocystis Nitrogen', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_3zoo2det) then + ! 3zoo2det configurations: This is second detritus pool Carbon + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Det2C', 'Conc of C in second detritus pool', '[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 + !if (use_REcoM .and. enable_3zoo2det) 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 + + ! ===================================================================== + ! Tracer ID 1027: + ! - In COCCOS-ONLY config: PhaeoC (Phaeocystis Carbon) + ! - In 3ZOO2DET configs: Det2Si (Second detritus pool Silica) + ! ===================================================================== else if (tracers%data(j)%ID==1027) 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) + if (use_REcoM .and. enable_coccos .and. .not. enable_3zoo2det) then + ! Coccos-only configuration: This is Phaeocystis Carbon + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoC', 'Phaeocystis Carbon', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_3zoo2det) then + ! 3zoo2det configurations: This is second detritus pool Silica + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Det2Si', 'Conc of Si in second detritus pool', '[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 + !if (use_REcoM .and. enable_3zoo2det) 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 + + ! ===================================================================== + ! Tracer ID 1028: + ! - In COCCOS-ONLY config: PhaeoChl (Phaeocystis Chlorophyll) + ! - In 3ZOO2DET configs: Det2Calc (Second detritus pool Calcium) + ! ===================================================================== else if (tracers%data(j)%ID==1028) 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) + if (use_REcoM .and. enable_coccos .and. .not. enable_3zoo2det) then + ! Coccos-only configuration: This is Phaeocystis Chlorophyll + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoChl', 'Phaeocystis Chlorophyll', '[mg/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_3zoo2det) then + ! 3zoo2det configurations: This is second detritus pool Calcium + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Det2Calc', 'Conc of Calc in second detritus pool', '[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 + !if (use_REcoM .and. enable_3zoo2det) 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 + + ! ===================================================================== + ! Tracer ID 1029: + ! - In COCCOS-ONLY config with rivers: DOCt (Terrestrial DOC) + ! - In 3ZOO2DET-ONLY config: Zoo3N (Microzooplankton Nitrogen) + ! - In FULL model config: CoccoN (Coccolithophore Nitrogen) + ! ===================================================================== else if (tracers%data(j)%ID==1029) 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) + if (use_REcoM .and. enable_coccos .and. enable_3zoo2det) then + ! Full model: This is Coccolithophore Nitrogen + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CoccoN', 'Coccolithophore Nitrogen', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_3zoo2det .and. .not. enable_coccos) then + ! 3zoo2det-only configuration: This is Microzooplankton Nitrogen + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo3N', 'Microzooplankton Nitrogen', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_coccos .and. .not. enable_3zoo2det .and. useRivers) then + ! Coccos-only configuration with rivers: This is Terrestrial DOC + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DOCt', 'Terrestrial Dissolved Organic Carbon', '[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 + !if (use_REcoM .and. enable_coccos) 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 + + ! ===================================================================== + ! Tracer ID 1030: + ! - In 3ZOO2DET-ONLY config: Zoo3C (Microzooplankton Carbon) + ! - In FULL model config: CoccoC (Coccolithophore Carbon) + ! ===================================================================== else if (tracers%data(j)%ID==1030) 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) + if (use_REcoM .and. enable_coccos .and. enable_3zoo2det) then + ! Full model: This is Coccolithophore Carbon + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CoccoC', 'Coccolithophore Carbon', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_3zoo2det .and. .not. enable_coccos) then + ! 3zoo2det-only configuration: This is Microzooplankton Carbon + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo3C', 'Microzooplankton Carbon', '[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 + !if (use_REcoM .and. enable_coccos) 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 + + ! ===================================================================== + ! Tracer ID 1031: + ! - In 3ZOO2DET-ONLY config with rivers: DOCt (Terrestrial DOC) + ! - In FULL model config: CoccoChl (Coccolithophore Chlorophyll) + ! ===================================================================== else if (tracers%data(j)%ID==1031) 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) + if (use_REcoM .and. enable_coccos .and. enable_3zoo2det) then + ! Full model: This is Coccolithophore Chlorophyll + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CoccoChl', 'Coccolithophore Chlorophyll', '[mg/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + else if (use_REcoM .and. enable_3zoo2det .and. .not. enable_coccos .and. useRivers) then + ! 3zoo2det-only configuration with rivers: This is Terrestrial DOC + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DOCt', 'Terrestrial Dissolved Organic Carbon', '[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 + !if (use_REcoM .and. enable_coccos) 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 + + ! ===================================================================== + ! Tracer IDs 1032-1034: Only in FULL model configuration + ! These are Phaeocystis tracers + ! ===================================================================== else if (tracers%data(j)%ID==1032) 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) + if (use_REcoM .and. enable_coccos .and. enable_3zoo2det) then + ! Full model: This is Phaeocystis Nitrogen + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoN', 'Phaeocystis Nitrogen', '[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==1032) 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==1033) 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) + if (use_REcoM .and. enable_coccos .and. enable_3zoo2det) then + ! Full model: This is Phaeocystis Carbon + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoC', 'Phaeocystis Carbon', '[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==1033) 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 + + else if (tracers%data(j)%ID==1034) then + if (use_REcoM .and. enable_coccos .and. enable_3zoo2det) then + ! Full model: This is Phaeocystis Chlorophyll + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoChl', 'Phaeocystis Chlorophyll', '[mg/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif + + ! ===================================================================== + ! Tracer IDs 1035-1036: Only in FULL model configuration + ! These are Microzooplankton tracers + ! ===================================================================== + else if (tracers%data(j)%ID==1035) then + if (use_REcoM .and. enable_coccos .and. enable_3zoo2det) then + ! Full model: This is Microzooplankton Nitrogen + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo3N', 'Microzooplankton Nitrogen', '[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 + if (use_REcoM .and. enable_coccos .and. enable_3zoo2det) then + ! Full model: This is Microzooplankton Carbon + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo3C', 'Microzooplankton Carbon', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + ! ===================================================================== + ! Tracer ID 1037: Only in FULL model configuration with rivers + ! This is Terrestrial DOC + ! ===================================================================== + else if (tracers%data(j)%ID==1037) then + if (use_REcoM .and. enable_coccos .and. enable_3zoo2det .and. useRivers) then + ! Full model with rivers: This is Terrestrial DOC + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DOCt', 'Terrestrial Dissolved Organic Carbon', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif else #endif diff --git a/src/io_restart_file_group.F90 b/src/io_restart_file_group.F90 index 31c9263f5..78a24ff42 100644 --- a/src/io_restart_file_group.F90 +++ b/src/io_restart_file_group.F90 @@ -17,7 +17,7 @@ module restart_file_group_module type restart_file_group private - type(restart_file_type), public :: files(112) + type(restart_file_type), public :: files(200) ! was (112) before OG integer, public :: nfiles = 0 ! todo: allow dynamically allocated size without messing with shallow copied pointers contains diff --git a/src/oce_adv_tra_driver.F90 b/src/oce_adv_tra_driver.F90 index 9b9606ea8..482bc2e8e 100644 --- a/src/oce_adv_tra_driver.F90 +++ b/src/oce_adv_tra_driver.F90 @@ -22,14 +22,17 @@ end module oce_adv_tra_driver_interfaces module oce_tra_adv_flux2dtracer_interface interface - subroutine oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, flux_h, flux_v, partit, mesh, use_lo, ttf, lo) + subroutine oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, flux_h, flux_v, partit, mesh, use_lo, ttf, lo, tr_num, tracers) !update the solution for vertical and horizontal flux contributions use MOD_MESH + use MOD_TRACER USE MOD_PARTIT USE MOD_PARSUP real(kind=WP), intent(in), target :: dt + integer, intent(in) :: tr_num type(t_partit),intent(inout), target :: partit type(t_mesh), intent(in), target :: mesh + type(t_tracer), intent(inout), target :: tracers real(kind=WP), intent(inout) :: dttf_h(mesh%nl-1, partit%myDim_nod2D+partit%eDim_nod2D) real(kind=WP), intent(inout) :: dttf_v(mesh%nl-1, partit%myDim_nod2D+partit%eDim_nod2D) real(kind=WP), intent(inout) :: flux_h(mesh%nl-1, partit%myDim_edge2D) @@ -209,6 +212,27 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, #endif #endif + +! O:G - tra_diag +! LO solution +! fct_LO is zero before adv_flux_hor +! Up to now only horizontal +! contribution + + +!#if defined (__recom) + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ! Horizontal advection part for LO (FCT is .TRUE.) + tracers%work%tra_advhoriz_LO(nz,n,tr_num) = fct_LO(nz,n) * dt/areasvol(nz,n)/hnode_new(nz,n) + end do + end do + end if +!#endif + ! compute the low order upwind vertical flux (explicit part only) ! zero the input/output flux before computation call adv_tra_ver_upw1(we, ttf, partit, mesh, adv_flux_ver, o_init_zero=.true.) @@ -277,6 +301,24 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, end if +! O:G - tra_diag +! LO solution +! fct_LO is zero before adv_flux_ver +! vertical contribution + +!#if defined (__recom) + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ! Vertical advection part for LO (FCT is .TRUE.) + tracers%work%tra_advvert_LO (nz,n,tr_num) = (adv_flux_ver(nz, n)-adv_flux_ver(nz+1, n))*dt/areasvol(nz,n)/hnode_new(nz,n) + end do + end do + end if +!#endif + !_______________________________________________________________________ if (dynamics%use_wsplit) then !wvel/=wvel_e @@ -301,7 +343,7 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, ! do horizontal tracer advection, in case of FCT high order solution SELECT CASE(trim(tracers%data(tr_num)%tra_adv_hor)) CASE('MUSCL') - ! compute the untidiffusive horizontal flux (o_init_zero=.false.: input is the LO horizontal flux computed above) + ! compute the antidiffusive horizontal flux (o_init_zero=.false.: input is the LO horizontal flux computed above) call adv_tra_hor_muscl(vel, ttfAB, partit, mesh, opth, adv_flux_hor, edge_up_dn_grad, nboundary_lay, o_init_zero=do_zero_flux) CASE('MFCT') call adv_tra_hor_mfct(vel, ttfAB, partit, mesh, opth, adv_flux_hor, edge_up_dn_grad, o_init_zero=do_zero_flux) @@ -341,9 +383,9 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, if (trim(tracers%data(tr_num)%tra_adv_lim)=='FCT') then !edge_up_dn_grad will be used as an auxuary array here call oce_tra_adv_fct(dt, ttf, fct_LO, adv_flux_hor, adv_flux_ver, fct_ttf_min, fct_ttf_max, fct_plus, fct_minus, edge_up_dn_grad, partit, mesh) - call oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, adv_flux_hor, adv_flux_ver, partit, mesh, use_lo=.TRUE., ttf=ttf, lo=fct_LO) + call oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, adv_flux_hor, adv_flux_ver, partit, mesh, use_lo=.TRUE., ttf=ttf, lo=fct_LO, tr_num=tr_num, tracers=tracers) else - call oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, adv_flux_hor, adv_flux_ver, partit, mesh) + call oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, adv_flux_hor, adv_flux_ver, partit, mesh,tr_num=tr_num, tracers=tracers) end if !___________________________________________________________________________ @@ -416,12 +458,14 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, end if end if !-->if ((ldiag_DVD) .and. (tr_num<=2)) then + end subroutine do_oce_adv_tra ! ! !=============================================================================== -subroutine oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, flux_h, flux_v, partit, mesh, use_lo, ttf, lo) +subroutine oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, flux_h, flux_v, partit, mesh, use_lo, ttf, lo,tr_num, tracers) use MOD_MESH + use MOD_TRACER use o_ARRAYS USE MOD_PARTIT USE MOD_PARSUP @@ -430,6 +474,8 @@ subroutine oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, flux_h, flux_v, partit, real(kind=WP), intent(in), target :: dt type(t_partit),intent(inout), target :: partit type(t_mesh), intent(in), target :: mesh + integer, intent(in) :: tr_num !RP + type(t_tracer), intent(inout), target :: tracers !RP real(kind=WP), intent(inout) :: dttf_h(mesh%nl-1, partit%myDim_nod2D+partit%eDim_nod2D) real(kind=WP), intent(inout) :: dttf_v(mesh%nl-1, partit%myDim_nod2D+partit%eDim_nod2D) real(kind=WP), intent(inout) :: flux_h(mesh%nl-1, partit%myDim_edge2D) @@ -486,6 +532,17 @@ subroutine oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, flux_h, flux_v, partit, end do !$ACC END LOOP end do +#if defined (__recom) + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2d + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz=nu1,nl1-1 + tracers%work%tra_advvert(nz,n,tr_num) = dttf_v(nz,n) + end do + end do + end if +#endif #ifndef ENABLE_OPENACC !$OMP END DO #else @@ -548,6 +605,18 @@ subroutine oce_tra_adv_flux2dtracer(dt, dttf_h, dttf_v, flux_h, flux_v, partit, #endif dttf_h(nz,enodes(2))=dttf_h(nz,enodes(2))-flux_h(nz,edge)*dt/areasvol(nz,enodes(2)) end do +#if defined (__recom) + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2d + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz=nu1,nl1-1 + tracers%work%tra_advhoriz(nz,n,tr_num) = dttf_h(nz,n) + end do + end do + end if +#endif + #ifndef ENABLE_OPENACC #if defined(_OPENMP) && !defined(__openmp_reproducible) call omp_unset_lock(partit%plock(enodes(2))) diff --git a/src/oce_ale_tracer.F90 b/src/oce_ale_tracer.F90 index dd4ce9101..513212ae4 100644 --- a/src/oce_ale_tracer.F90 +++ b/src/oce_ale_tracer.F90 @@ -165,6 +165,9 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) type(t_mesh) , intent(in) , target :: mesh !___________________________________________________________________________ integer :: i, tr_num, node, elem, nzmax, nzmin + real(kind=WP) :: ttf_rhs_bak (mesh%nl-1, partit%myDim_nod2D+partit%eDim_elem2D) ! local variable + real(kind=WP) :: ttf_rhs_bak_tend (mesh%nl-1, partit%myDim_nod2D+partit%eDim_nod2D) + integer :: nz, n, nu1, nl1 !___________________________________________________________________________ ! pointer on necessary derived types real(kind=WP), dimension(:,:,:), pointer :: UV, fer_UV @@ -190,7 +193,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) call cal_rejected_salt(ice, partit, mesh) if (flag_debug .and. mype==0) print *, achar(27)//'[37m'//' --> call app_rejected_salt'//achar(27)//'[0m' call app_rejected_salt(tracers%data(2)%values, partit, mesh) - end if + end if !___________________________________________________________________________ ! update 3D velocities with the bolus velocities: @@ -210,6 +213,15 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) !$OMP END PARALLEL DO end if + ! Set advective and diffusive components of total tracer fluxes to zero + ! Before tr_num loop +!#if defined (__recom) ! not necessarily should belong to recom case +! tracers%work%tra_advhoriz = 0.0 ! O:G - tra_diag +! tracers%work%tra_advvert = 0.0 + ttf_rhs_bak = 0.0 + ttf_rhs_bak_tend = 0.0 +!#endif + !___________________________________________________________________________ ! loop over all tracers !$ACC UPDATE DEVICE(dynamics%w, dynamics%w_e, dynamics%uv) !!! async(1) @@ -217,13 +229,34 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) !$ACC UPDATE DEVICE (mesh%helem, mesh%hnode, mesh%hnode_new, mesh%zbar_3d_n, mesh%z_3d_n) do tr_num=1, tracers%num_tracers +#if defined(__recom) +!YY: sinkflx needs to be reset at each time step + if(use_MEDUSA) then + SinkFlx = 0.0d0 + endif + SinkingVel1 = 0.0d0 + SinkingVel2 = 0.0d0 +#endif ! do tracer AB (Adams-Bashfort) interpolation only for advectiv part ! needed if (flag_debug .and. mype==0) print *, achar(27)//'[37m'//' --> call init_tracers_AB'//achar(27)//'[0m' call init_tracers_AB(tr_num, tracers, partit, mesh) - + ! advect tracers if (flag_debug .and. mype==0) print *, achar(27)//'[37m'//' --> call adv_tracers_ale'//achar(27)//'[0m' + + !============================================================ + + if (tracers%data(tr_num)%ltra_diag) then ! OG - tra_diag + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ttf_rhs_bak_tend(nz,n) = tracers%data(tr_num)%values(nz,n) + end do + end do + end if + !============================================================ !here update only those initialized in the init_tracers. (values, valuesAB, edge_up_dn_grad, ...) !!$ACC UPDATE DEVICE(tracers%data(tr_num)%values, tracers%data(tr_num)%valuesAB, tracers%data(tr_num)%valuesold) !$ACC UPDATE DEVICE(tracers%work%edge_up_dn_grad) !!& @@ -246,6 +279,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) if (flag_debug .and. mype==0) print *, achar(27)//'[37m'//' --> call diff_tracers_ale'//achar(27)//'[0m' call diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) + !___________________________________________________________________________ ! Radioactive decay of 14C and 39Ar if (tracers%data(tr_num)%ID == 14) tracers%data(tr_num)%values(:,:) = tracers%data(tr_num)%values(:,:) * exp(-decay14 * dt) if (tracers%data(tr_num)%ID == 39) tracers%data(tr_num)%values(:,:) = tracers%data(tr_num)%values(:,:) * exp(-decay39 * dt) @@ -254,7 +288,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) ! relax to salt and temp climatology if (flag_debug .and. mype==0) print *, achar(27)//'[37m'//' --> call relax_to_clim'//achar(27)//'[0m' ! if ((toy_ocean) .AND. ((tr_num==1) .AND. (TRIM(which_toy)=="soufflet"))) then - if ((toy_ocean) .AND. ((TRIM(which_toy)=="soufflet"))) then + if ((toy_ocean) .AND. ((TRIM(which_toy)=="soufflet"))) then call relax_zonal_temp(tracers%data(1), partit, mesh) elseif ((toy_ocean) .AND. ((TRIM(which_toy)=="neverworld2"))) then @@ -272,6 +306,17 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) !!! !$ACC UPDATE HOST (tracers%work%fct_ttf_min, tracers%work%fct_ttf_max, tracers%work%fct_plus, tracers%work%fct_minus) & !!! !$ACC HOST (tracers%work%edge_up_dn_grad) +#if defined(__recom) + do tr_num = 1, tracers%num_tracers + if (use_MEDUSA) then + SinkFlx = SinkFlx + SinkFlx_tr(:, :, tr_num) + endif +! Benthos = Benthos + Benthos_tr(:, :, tr_num) + Sinkingvel1(:,:) = Sinkingvel1(:,:) + Sinkvel1_tr(:, :, tr_num) + Sinkingvel2(:,:) = Sinkingvel2(:,:) + Sinkvel2_tr(:, :, tr_num) + end do +#endif + !___________________________________________________________________________ ! 3D restoring for "passive" tracers !!!$OMPTODO: add OpenMP later, not needed right now! @@ -349,6 +394,7 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) use ver_sinking_recom_interface use diff_ver_recom_expl_interface use ver_sinking_recom_benthos_interface + use recom_nitrogenss_interface use recom_glovar use recom_config use g_comm_auto @@ -364,6 +410,8 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) type(t_mesh) , intent(in) , target :: mesh !___________________________________________________________________________ integer :: n, nzmax, nzmin + real(kind=WP) :: ttf_rhs_bak (mesh%nl-1, partit%myDim_nod2D+partit%eDim_nod2D) + integer :: nz, nu1, nl1 !___________________________________________________________________________ ! pointer on necessary derived types real(kind=WP), pointer :: del_ttf(:,:) @@ -378,21 +426,90 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) vert_sink = 0.0_WP #endif + ttf_rhs_bak = 0.0 + + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ttf_rhs_bak(nz,n) = del_ttf(nz,n) + end do + end do + end if !___________________________________________________________________________ - ! do horizontal diffusiion + ! do horizontal diffusion ! write there also horizontal diffusion rhs to del_ttf which is equal the R_T^n ! in danilovs srcipt ! includes Redi diffusivity if Redi=.true. call diff_part_hor_redi(tracers, partit, mesh) ! seems to be ~9% faster than diff_part_hor - + + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ! horizontal diffusion (w/out Redi) + tracers%work%tra_diff_part_hor_redi(nz,n,tr_num) = (del_ttf(nz,n) - ttf_rhs_bak(nz,n)) ! Unit [Conc] + !if (mype==0) print *, tracers%work%tra_diff_part_hor_redi(nz,n,tr_num) + end do + end do + end if + + if ((.not. tracers%data(tr_num)%i_vert_diff) .and. tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ttf_rhs_bak(nz,n) = del_ttf(nz,n) + end do + end do + end if !___________________________________________________________________________ ! do vertical diffusion: explicit if (.not. tracers%data(tr_num)%i_vert_diff) call diff_ver_part_expl_ale(tr_num, tracers, partit, mesh) - + + ! OG i_vert_diff = TRUE so, we dont call explicit scheme + ! If we use this, check surface forcing for recom variables (They are not updated) + if ((.not. tracers%data(tr_num)%i_vert_diff) .and. tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ! vertical diffusion: explicit + tracers%work%tra_diff_part_ver_expl(nz,n,tr_num) = (del_ttf(nz,n) - ttf_rhs_bak(nz,n)) ! Unit [Conc] + !if (mype==0) print *, tra_diff_part_ver_expl(:,:,tr_num) + end do + end do + end if + ! A projection of horizontal Redi diffussivity onto vertical. This par contains horizontal ! derivatives and has to be computed explicitly! + + if (tracers%data(tr_num)%ltra_diag .and. Redi) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ttf_rhs_bak(nz,n) = del_ttf(nz,n) + end do + end do + end if + if (Redi) call diff_ver_part_redi_expl(tracers, partit, mesh) + if (tracers%data(tr_num)%ltra_diag .and. Redi) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ! Redi diffussivity onto vertical: explicit + tracers%work%tra_diff_part_ver_redi_expl(nz,n,tr_num) = (del_ttf(nz,n) - ttf_rhs_bak(nz,n)) ! Unit [Conc] + !if (mype==0) print *, tra_diff_part_ver_redi_expl(:,:,tr_num) + end do + end do + end if + ! if (recom_debug .and. mype==0) print *, tracers%data(tr_num)%ID #if defined(__recom) @@ -404,14 +521,43 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) ! call bottom boundary call diff_ver_recom_expl(tr_num, tracers, partit, mesh) +! print*, 'Calling diff_ver_recom_expl and tr_num is:',tracers%data(tr_num)%ID + SELECT CASE (tracers%data(tr_num)%ID) + CASE (1001) ! DIN + dtr_bflux_din(:,:) = 0.0d0 !tracers%data(tr_num)%values(:,:)*0.0d0 + CASE (1002) ! DIC + dtr_bflux_dic(:,:) = 0.0d0 !tracers%data(tr_num)%values(:,:)*0.0d0 + CASE (1003) ! Alk + dtr_bflux_alk(:,:) = 0.0d0 !tracers%data(tr_num)%values(:,:)*0.0d0 + CASE (1018) ! DSi + dtr_bflux_dsi(:,:) = 0.0d0 !tracers%data(tr_num)%values(:,:)*0.0d0 + END SELECT ! update tracer fields do n=1, myDim_nod2D nzmax=nlevels_nod2D(n)-1 nzmin=ulevels_nod2D(n) -! tr_arr(nzmin:nzmax,n,tr_num)=tr_arr(nzmin:nzmax,n,tr_num)+ & -! dtr_bf(nzmin:nzmax,n) - tracers%data(tr_num)%values(nzmin:nzmax,n)=tracers%data(tr_num)%values(nzmin:nzmax,n)+ & + SELECT CASE (tracers%data(tr_num)%ID) + CASE (1001) ! DIN + tracers%data(tr_num)%values(nzmin:nzmax,n)=tracers%data(tr_num)%values(nzmin:nzmax,n)+ & + dtr_bf(nzmin:nzmax,n) + dtr_bflux_din(nzmin:nzmax,n) = dtr_bflux_din(nzmin:nzmax,n) + dtr_bf(nzmin:nzmax,n) + CASE (1002) ! DIC + tracers%data(tr_num)%values(nzmin:nzmax,n)=tracers%data(tr_num)%values(nzmin:nzmax,n)+ & + dtr_bf(nzmin:nzmax,n) + dtr_bflux_dic(nzmin:nzmax,n) = dtr_bflux_dic(nzmin:nzmax,n) + dtr_bf(nzmin:nzmax,n) + CASE (1003) ! Alk + tracers%data(tr_num)%values(nzmin:nzmax,n)=tracers%data(tr_num)%values(nzmin:nzmax,n)+ & dtr_bf(nzmin:nzmax,n) + dtr_bflux_alk(nzmin:nzmax,n) = dtr_bflux_alk(nzmin:nzmax,n) + dtr_bf(nzmin:nzmax,n) + CASE (1018) ! DSi + tracers%data(tr_num)%values(nzmin:nzmax,n)=tracers%data(tr_num)%values(nzmin:nzmax,n)+ & + dtr_bf(nzmin:nzmax,n) + dtr_bflux_dsi(nzmin:nzmax,n) = dtr_bflux_dsi(nzmin:nzmax,n) + dtr_bf(nzmin:nzmax,n) + + CASE DEFAULT + tracers%data(tr_num)%values(nzmin:nzmax,n)=tracers%data(tr_num)%values(nzmin:nzmax,n)+ & + dtr_bf(nzmin:nzmax,n) + END SELECT end do end if @@ -443,7 +589,7 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) call ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) !--- str_bf --- ! update tracer fields - +!print*, 'Calling ver_sinking_recom_benthos and tr_num is:',tracers%data(tr_num)%ID do n=1, myDim_nod2D nzmax=nlevels_nod2D(n)-1 nzmin=ulevels_nod2D(n) @@ -457,6 +603,18 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) str_bf(nzmin:nzmax,n) end do endif + +! 3) Nitrogen SS + if (NitrogenSS .and. tracers%data(tr_num)%ID==1008) then ! idetc + call recom_nitrogenss(tracers, partit, mesh) !--- nss for idetc --- + do n=1, myDim_nod2D + nzmax=nlevels_nod2D(n)-1 + nzmin=ulevels_nod2D(n) + tracers%data(3)%values(nzmin:nzmax,n)=tracers%data(3)%values(nzmin:nzmax,n)+ & ! tracer_id(tr_num)==1001 !idin + nss(nzmin:nzmax,n) + end do + end if + #endif !___________________________________________________________________________ ! Update tracers --> calculate T* see Danilov et al. (2017) @@ -479,15 +637,40 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) !___________________________________________________________________________ if (tracers%data(tr_num)%i_vert_diff) then ! do vertical diffusion: implicite + + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ttf_rhs_bak(nz,n) = tracers%data(tr_num)%values(nz,n) + end do + end do + end if + + ! (w/out Redi) call diff_ver_part_impl_ale(tr_num, dynamics, tracers, ice, partit, mesh) + + ! vertical diffusion: implicit + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + tracers%work%tra_diff_part_ver_impl(nz,n,tr_num) = tracers%data(tr_num)%values(nz,n) - ttf_rhs_bak(nz,n) + !if (mype==0) print *, tra_diff_part_ver_impl(:,:,tr_num) + end do + end do + end if + end if - + !We DO not set del_ttf to zero because it will not be used in this timestep anymore !init_tracers_AB will set it to zero for the next timestep if (tracers%data(tr_num)%smooth_bh_tra) then call diff_part_bh(tr_num, dynamics, tracers, partit, mesh) ! alpply biharmonic diffusion (implemented as filter) end if - + end subroutine diff_tracers_ale ! ! @@ -857,7 +1040,7 @@ subroutine diff_ver_part_impl_ale(tr_num, dynamics, tracers, ice, partit, mesh) a(nz)=a(nz)+min(0._WP, Wvel_i(nz, n))*v_adv b(nz)=b(nz)+max(0._WP, Wvel_i(nz, n))*v_adv end if - + !_______________________________________________________________________ ! the rhs (inhomogene part): --> rhs = K_33*dt*d/dz*Tstar --> Tstar...trarr ! solve difference quotient for rhs --> tr @@ -882,7 +1065,7 @@ subroutine diff_ver_part_impl_ale(tr_num, dynamics, tracers, ice, partit, mesh) nz=nzmax-1 dz=hnode_new(nz,n) tr(nz)=-a(nz)*trarr(nz-1,n)-(b(nz)-dz)*trarr(nz,n) - + !_______________________________________________________________________ ! Add KPP nonlocal fluxes to the rhs (only T and S currently) ! use here blmc or kpp_oblmixc instead of Kv, since Kv already contains @@ -985,7 +1168,7 @@ subroutine diff_ver_part_impl_ale(tr_num, dynamics, tracers, ice, partit, mesh) #endif end if end if ! --> if (use_kpp_nonlclflx) then - + !_______________________________________________________________________ ! case of activated shortwave penetration into the ocean, ad 3d contribution if (use_sw_pene .and. tracers%data(tr_num)%ID==1 .and. .not. toy_ocean) then @@ -1067,7 +1250,7 @@ subroutine diff_ver_part_impl_ale(tr_num, dynamics, tracers, ice, partit, mesh) do nz = nzmax-2, nzmin, -1 tr(nz) = tp(nz)-cp(nz)*tr(nz+1) end do - + !_______________________________________________________________________ ! update tracer ! tr ... dTnew = T^(n+0.5) - T* @@ -1482,6 +1665,10 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit, mesh, sst, sss, aice) #if defined (__recom) use recoM_declarations use recom_glovar + use recom_config +#endif +#if defined (__ciso) + use recom_ciso #endif use mod_transit use g_clock @@ -1515,7 +1702,7 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit, mesh, sst, sss, aice) !___temperature_____________________________________________________________ CASE (1) bc_surface=-dt*(heat_flux(n)/vcpw + sval*water_flux(n)*is_nonlinfs) - + !___salinity________________________________________________________________ CASE (2) ! --> real_salt_flux(:): salt flux due to containment/releasing of salt @@ -1609,38 +1796,125 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit, mesh, sst, sss, aice) !--- Done with boundary conditions for transient tracers. #if defined(__recom) CASE (1001) ! DIN + if (use_MEDUSA .and. add_loopback) then ! OG: add is_MEDUSA_loopback flag is_MEDUSA_loopback flag * lb_flux(n,1) + bc_surface= dt*(AtmNInput(n) + RiverDIN2D(n) * is_riverinput & + + ErosionTON2D(n) * is_erosioninput + lb_flux(n,1)) + else bc_surface= dt*(AtmNInput(n) + RiverDIN2D(n) * is_riverinput & + ErosionTON2D(n) * is_erosioninput) + end if + CASE (1002) ! DIC + if (use_MEDUSA .and. add_loopback) then + bc_surface= dt*(GloCO2flux_seaicemask(n) & + + RiverDIC2D(n) * is_riverinput & + + ErosionTOC2D(n) * is_erosioninput & + + lb_flux(n,2) + lb_flux(n,5)) + else bc_surface= dt*(GloCO2flux_seaicemask(n) & + RiverDIC2D(n) * is_riverinput & + + RiverDOCl2D(n) * is_riverinput & ! OG R2OMIP + ErosionTOC2D(n) * is_erosioninput) + end if + CASE (1003) ! Alk + if (use_MEDUSA .and. add_loopback) then bc_surface= dt*(virtual_alk(n) + relax_alk(n) & - + RiverAlk2D(n) * is_riverinput) - !bc_surface=0.0_WP - CASE (1004:1010) + + RiverDIC2D(n) * is_riverinput & + + lb_flux(n,3) + lb_flux(n,5)*2) !CaCO3:Alk burial=1:2 + else + bc_surface= dt*(virtual_alk(n) + relax_alk(n) & ! & + + RiverDIC2D(n) * is_riverinput) + end if + CASE (1004:1006) + bc_surface=0.0_WP + CASE (1007) ! PON / detN ! R2OMIP + bc_surface= (25/276)*dt*RiverPOC2D(n) * is_riverinput + CASE (1008) ! POC / detC ! R2OMIP + bc_surface= dt*RiverPOC2D(n) * is_riverinput + CASE (1009:1010) bc_surface=0.0_WP - CASE (1011) ! DON - bc_surface= dt*RiverDON2D(n) * is_riverinput + CASE (1011) ! DON ! R2OMIP + !bc_surface= dt*RiverDON2D(n) * is_riverinput + bc_surface= (103/2583)*dt*RiverDOCsl2D(n) * is_riverinput CASE (1012) ! DOC - bc_surface= dt*RiverDOC2D(n) * is_riverinput + !bc_surface= dt*RiverDOC2D(n) * is_riverinput + bc_surface= 0.0_WP CASE (1013:1017) bc_surface=0.0_WP - CASE (1018) ! DSi - bc_surface=dt*(RiverDSi2D(n) * is_riverinput + ErosionTSi2D(n) * is_erosioninput) + CASE (1018) ! DSi ! From Turner et al. 2003 ! R2OMIP + if (use_MEDUSA .and. add_loopback) then + !bc_surface=dt*(RiverDSi2D(n) * is_riverinput & + ! + ErosionTSi2D(n) * is_erosioninput & + ! + lb_flux(n,4)) + bc_surface=0.0_WP + else + !bc_surface=dt*(RiverDSi2D(n) * is_riverinput + ErosionTSi2D(n) * is_erosioninput) + bc_surface=dt*((194/16.2)*RiverDIN2D(n) * is_riverinput + ErosionTSi2D(n) * is_erosioninput) + end if + CASE (1019) ! Fe + if (useRivFe) then + bc_surface= dt*(AtmFeInput(n) + RiverFe(n)) + else bc_surface= dt*AtmFeInput(n) + !bc_surface= dt*AtmFeInput(n) + dt*(0.002*(RiverDOCsl2D(n)**(-1.616))) * is_riverinput ! From Tashiro et al. 2023 - R2OMIP (OG model explodes here) + end if CASE (1020:1021) ! Cal bc_surface=0.0_WP + CASE (1022) ! OXY bc_surface= dt*GloO2flux_seaicemask(n) ! bc_surface=0.0_WP - CASE (1023:1035) + CASE (1023:1030) bc_surface=0.0_WP ! OG added bc for recom fields + + CASE (1031) ! DOC terrigenous ! R2OMIP + bc_surface= dt*RiverDOCsl2D(n) * is_riverinput + !bc_surface=0.0_WP ! OG added bc for recom fields + CASE (1032:1036) + bc_surface=0.0_WP ! OG added bc for recom fields + + CASE (1302) ! Before (1037) ! DIC_13 + +#if defined (__ciso) + if (ciso) then + if (use_MEDUSA .and. add_loopback) then + bc_surface= dt*(GloCO2flux_seaicemask_13(n) & + + lb_flux(n,6) + lb_flux(n,7)) + else + bc_surface= dt*(GloCO2flux_seaicemask_13(n)) + end if + else + bc_surface=0.0_WP + end if #endif + + CASE (1305:1321) + bc_surface=0.0_WP ! organic 13C + + CASE (1402) ! Before (1034) ! DIC_14 +#if defined (__ciso) + if (ciso .and. ciso_14) then + if (use_MEDUSA .and. add_loopback .and. ciso_organic_14) then + bc_surface= dt*(GloCO2flux_seaicemask_14(n) & + + lb_flux(n,8) + lb_flux(n,9)) + else + bc_surface= dt*GloCO2flux_seaicemask_14(n) + end if + else + bc_surface=0.0_WP + end if +#endif + + CASE (1405:1421) + bc_surface=0.0_WP ! organic 14C +#endif + CASE (101) ! apply boundary conditions to tracer ID=101 bc_surface= dt*(prec_rain(n))! - real_salt_flux(n)*is_nonlinfs) +!---Transient tracers (case ##6,12,14,39) need additional input parameters +! and are considered in the separate function transit_bc_surface !---wiso-code CASE (102) ! apply boundary conditions to tracer ID=101 (H218O) bc_surface = dt*wiso_flux_oce(n,1) diff --git a/src/oce_modules.F90 b/src/oce_modules.F90 index a71f60758..477700ae7 100755 --- a/src/oce_modules.F90 +++ b/src/oce_modules.F90 @@ -250,6 +250,8 @@ MODULE o_ARRAYS #if defined(__recom) real(kind=WP), allocatable :: dtr_bf(:,:), str_bf(:,:) real(kind=WP), allocatable :: vert_sink(:,:) +real(kind=WP), allocatable :: nss(:,:) ! OG -> vertical sinking !R2OMIP (Burial) +real(kind=WP), allocatable :: bur(:,:,:) ! LO !R2OMIP (Burial) #endif !Viscosity and diff coefs diff --git a/src/oce_setup_step.F90 b/src/oce_setup_step.F90 index 18900f749..d436d2069 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -314,7 +314,7 @@ SUBROUTINE tracer_init(tracers, partit, mesh) !___________________________________________________________________________ ! define tracer namelist parameter integer :: num_tracers - logical :: i_vert_diff, smooth_bh_tra + logical :: i_vert_diff, smooth_bh_tra , ltra_diag real(kind=WP) :: gamma0_tra, gamma1_tra, gamma2_tra integer :: AB_order = 2 namelist /tracer_listsize/ num_tracers @@ -477,6 +477,7 @@ SUBROUTINE tracer_init(tracers, partit, mesh) tracers%data(n)%valuesAB = 0. tracers%data(n)%valuesold = 0. tracers%data(n)%i_vert_diff = i_vert_diff + tracers%data(n)%ltra_diag = ltra_diag end do allocate(tracers%work%del_ttf(nl-1,node_size)) allocate(tracers%work%del_ttf_advhoriz(nl-1,node_size),tracers%work%del_ttf_advvert(nl-1,node_size)) @@ -489,6 +490,24 @@ SUBROUTINE tracer_init(tracers, partit, mesh) tracers%work%dvd_trflx_hor = 0.0_WP tracers%work%dvd_trflx_ver = 0.0_WP end if + if (ltra_diag) then + allocate(tracers%work%tra_advhoriz(nl-1,node_size,num_tracers),tracers%work%tra_advvert(nl-1,node_size,num_tracers)) + tracers%work%tra_advhoriz = 0.0_WP + tracers%work%tra_advvert = 0.0_WP + allocate(tracers%work%tra_diff_part_hor_redi(nl-1,node_size,num_tracers),tracers%work%tra_diff_part_ver_expl(nl-1,node_size,num_tracers)) + allocate(tracers%work%tra_diff_part_ver_redi_expl(nl-1,node_size,num_tracers),tracers%work%tra_diff_part_ver_impl(nl-1,node_size,num_tracers)) + allocate(tracers%work%tra_recom_sms(nl-1,node_size,num_tracers)) + allocate(tracers%work%tra_advhoriz_LO(nl-1,node_size,num_tracers)) + allocate(tracers%work%tra_advvert_LO(nl-1,node_size,num_tracers)) + tracers%work%tra_diff_part_hor_redi = 0.0_WP + tracers%work%tra_diff_part_ver_expl = 0.0_WP + tracers%work%tra_diff_part_ver_redi_expl = 0.0_WP + tracers%work%tra_diff_part_ver_impl = 0.0_WP + tracers%work%tra_recom_sms = 0.0_WP + tracers%work%tra_advhoriz_LO = 0.0_WP + tracers%work%tra_advvert_LO = 0.0_WP + + end if END SUBROUTINE tracer_init ! ! @@ -873,6 +892,8 @@ SUBROUTINE arrays_init(num_tracers, partit, mesh) allocate(str_bf ( nl-1, node_size )) allocate(vert_sink ( nl-1, node_size )) allocate(Alk_surf ( node_size )) + allocate(nss ( nl-1, node_size )) !R2OMIP (Burial) + allocate(bur ( 1:benthos_num, nl-1, node_size )) ! LO !R2OMIP (Burial) #endif ! ================= ! Visc and Diff coefs @@ -985,6 +1006,8 @@ SUBROUTINE arrays_init(num_tracers, partit, mesh) str_bf = 0.0_WP vert_sink = 0.0_WP Alk_surf = 0.0_WP + nss = 0.0_WP !R2OMIP (Burial) + bur = 0.0_WP !R2OMIP (Burial) #endif ! init field for pressure force @@ -1189,7 +1212,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write (id_string, "(I4)") id write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if - CASE (1023:1033) + CASE (1023:1037) tracers%data(i)%values(:,:)=0.0_WP if (mype==0) then write (i_string, "(I4)") i diff --git a/test/input/recom/DustClimMonthlyAlbani_pimesh.nc b/test/input/recom/DustClimMonthlyAlbani_pimesh.nc new file mode 100644 index 000000000..01d17125e Binary files /dev/null and b/test/input/recom/DustClimMonthlyAlbani_pimesh.nc differ diff --git a/test/input/recom/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc b/test/input/recom/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc new file mode 100644 index 000000000..3c5292ae1 Binary files /dev/null and b/test/input/recom/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc differ diff --git a/test/input/recom/MonthlyAtmCO2_gcb2024.nc b/test/input/recom/MonthlyAtmCO2_gcb2024.nc new file mode 100644 index 000000000..1874cf8f3 Binary files /dev/null and b/test/input/recom/MonthlyAtmCO2_gcb2024.nc differ diff --git a/test/input/recom/din5deg.nc b/test/input/recom/din5deg.nc new file mode 100644 index 000000000..74d678dbc Binary files /dev/null and b/test/input/recom/din5deg.nc differ diff --git a/test/input/recom/fe5deg.nc b/test/input/recom/fe5deg.nc new file mode 100644 index 000000000..76d5c8e4b Binary files /dev/null and b/test/input/recom/fe5deg.nc differ diff --git a/test/input/recom/oxy5deg.nc b/test/input/recom/oxy5deg.nc new file mode 100644 index 000000000..6298ec1d2 Binary files /dev/null and b/test/input/recom/oxy5deg.nc differ diff --git a/test/input/recom/si5deg.nc b/test/input/recom/si5deg.nc new file mode 100644 index 000000000..a81e284b4 Binary files /dev/null and b/test/input/recom/si5deg.nc differ diff --git a/test/input/recom/talk5deg.nc b/test/input/recom/talk5deg.nc new file mode 100644 index 000000000..25fde4bdc Binary files /dev/null and b/test/input/recom/talk5deg.nc differ diff --git a/test/input/recom/tco2_5deg.nc b/test/input/recom/tco2_5deg.nc new file mode 100644 index 000000000..7fdad5948 Binary files /dev/null and b/test/input/recom/tco2_5deg.nc differ diff --git a/test/input/recom/woa18_netcdf_5deg.nc b/test/input/recom/woa18_netcdf_5deg.nc new file mode 100644 index 000000000..2215b266a Binary files /dev/null and b/test/input/recom/woa18_netcdf_5deg.nc differ