diff --git a/.github/workflows/fesom2_recom.yml b/.github/workflows/fesom2_recom.yml index c511a2c79..aa847e947 100644 --- a/.github/workflows/fesom2_recom.yml +++ b/.github/workflows/fesom2_recom.yml @@ -10,6 +10,9 @@ on: - reopened branches: - main +# Minimal permissions for the GITHUB_TOKEN +permissions: + contents: read # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: general_test: @@ -26,31 +29,29 @@ jobs: - name: Git safe directory run: | git config --global --add safe.directory ${PWD} - - name: Compile model with REcoM run: | ./configure.sh ubuntu -DRECOM_COUPLED=ON - - name: Create REcoM test run run: | mkrun recom test_pi_recom -m docker - + - name: Add REcoM namelists run: | # mkrun doesn't create namelist.recom, so copy from config and patch # Using 2p3z2d (30 tracers) - more complete/tested than 2p1z1d cp config/bin_2p3z2d/namelist.recom work_recom/ cp config/bin_2p3z2d/namelist.tra work_recom/ - - # Patch namelist.recom + + # Patch file paths in namelists to use local files cd work_recom - + # Remove nam_rsbc section (not used by code, causes parsing errors) sed -i '/^&nam_rsbc/,/^\//d' namelist.recom - + # Set REcoM_restart to false for initialization from climatology sed -i "s|REcoM_restart.*=.*\.true\.|REcoM_restart =.false.|" namelist.recom - + # Patch tracer file list in namelist.tra sed -i "s|fe_pisces_opa_eq_init_3D_changed_name\.nc|fe5deg.nc|" namelist.tra sed -i "s|woa18_all_o00_01_mmol_fesom2\.nc|oxy5deg.nc|" namelist.tra @@ -59,18 +60,18 @@ jobs: sed -i "s|GLODAPv2\.2016b\.TCO2_fesom2_mmol_fix_z_Fillvalue\.nc|tco2_5deg.nc|" namelist.tra sed -i "s|woa13_all_n00_01_fesom2\.nc|din5deg.nc|" namelist.tra sed -i "s|phc3\.0_winter\.nc|woa18_netcdf_5deg.nc|g" namelist.tra - + # Enable atmospheric pressure forcing for REcoM CO2 flux calculation sed -i "s|l_mslp *= *\.false\.|l_mslp=.true.|" namelist.forcing - + echo "--- Verifying patches ---" echo "REcoM restart: $(grep 'REcoM_restart' namelist.recom)" echo "Atmospheric pressure: $(grep 'l_mslp' namelist.forcing)" cd .. - + # Copy REcoM input data files cp test/input/recom/*.nc work_recom/ - + # Create dust file with expected name in the source directory # (code reads from ClimateDataPath, not work directory) cd test/input/recom @@ -81,14 +82,14 @@ jobs: cp test/input/global/*.1948.nc work_recom/ cp test/input/global/runoff.nc work_recom/ cp test/input/global/PHC2_salx.nc work_recom/ - + - name: FESOM2 REcoM test run run: | cd work_recom echo "--- Running REcoM test (32 timesteps, 1 day) ---" chmod +x job_docker_new ./job_docker_new - + - name: Check REcoM results run: |- cd work_recom diff --git a/.gitignore b/.gitignore index c7f681645..a603e9a29 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ lib/*.so Makefile.in mesh_part/build test/output_pi +src/cvmix_driver/CVMix-* +finished_config.yaml .claude/ diff --git a/RECOM_output_Variables.md b/RECOM_output_Variables.md new file mode 100644 index 000000000..2beb254b3 --- /dev/null +++ b/RECOM_output_Variables.md @@ -0,0 +1,394 @@ +# REcoM Model Output Variables + +This document provides a comprehensive list of output variables available in the REcoM (Regulated Ecosystem Model) biogeochemical ocean model. + +--- + +## Table of Contents + +1. [Air-Sea Gas Exchange](#air-sea-gas-exchange) +2. [Carbon Chemistry](#carbon-chemistry) +3. [Atmospheric Inputs](#atmospheric-inputs) +4. [Benthic Processes](#benthic-processes) +5. [Phytoplankton Primary Production](#phytoplankton-primary-production) + - [Nanophytoplankton](#nanophytoplankton) + - [Diatoms](#diatoms) + - [Coccolithophores](#coccolithophores) + - [Phaeocystis](#phaeocystis) +6. [Zooplankton Grazing](#zooplankton-grazing) + - [Microzooplankton](#microzooplankton) + - [Mesozooplankton](#mesozooplankton) + - [Macrozooplankton](#macrozooplankton) + +--- + +## Air-Sea Gas Exchange + +### CO2 Exchange + +| Variable | Description | Units | +|----------|-------------|-------| +| `alphaCO2` | CO2 solubility coefficient in seawater | mol/kg/atm | +| `Kw` | Air-sea piston velocity (gas transfer velocity) | m/s | +| `dpCO2s` | Difference between oceanic and atmospheric pCO2 (ocean - atmosphere) | μatm | +| `pCO2s` | Partial pressure of CO2 in surface ocean | μatm | +| `CO2f` | CO2 flux into surface water (positive = ocean uptake) | mmolC/m²/d | + +### O2 Exchange + +| Variable | Description | Units | +|----------|-------------|-------| +| `O2f` | O2 flux into surface water (positive = ocean uptake) | mmolO/m²/d | + +--- + +## Carbon Chemistry + +| Variable | Description | Units | +|----------|-------------|-------| +| `Hp` | Mean concentration of H⁺ ions in surface water (ocean acidity) | mol/kg | + +--- + +## Atmospheric Inputs + +| Variable | Description | Units | +|----------|-------------|-------| +| `aFe` | Atmospheric iron deposition flux | μmolFe/m²/s | +| `aN` | Atmospheric dissolved inorganic nitrogen (DIN) deposition flux | mmolN/m²/s | + +--- + +## Benthic Processes + +Benthic compartments represent material accumulated at the seafloor from sinking particulate matter. + +| Variable | Description | Units | +|----------|-------------|-------| +| `benN` | Nitrogen stored in benthic pool | mmol | +| `benC` | Carbon stored in benthic pool | mmol | +| `benSi` | Silicon stored in benthic pool | mmol | +| `benCalc` | Calcite (CaCO₃) stored in benthic pool | mmol | + +--- + +## Phytoplankton Primary Production + +### Nanophytoplankton + +Small phytoplankton cells (typically 2-20 μm), representing the general small phytoplankton community. + +| Variable | Description | Units | +|----------|-------------|-------| +| `NPPn` | Net primary production (carbon fixation minus respiration) | mmolC/m²/d | +| `GPPn` | Gross primary production (total carbon fixation) | mmolC/m²/d | +| `NNAn` | Net nitrogen assimilation rate | mmolN/m²/d | +| `Chldegn` | Chlorophyll degradation rate | 1/d | + +### Diatoms + +Large phytoplankton with silica frustules, important for export production. + +| Variable | Description | Units | +|----------|-------------|-------| +| `NPPd` | Net primary production | mmolC/m²/d | +| `GPPd` | Gross primary production | mmolC/m²/d | +| `NNAd` | Net nitrogen assimilation rate | mmolN/m²/d | +| `Chldegd` | Chlorophyll degradation rate | 1/d | + +### Coccolithophores + +Phytoplankton that produce calcite plates (coccoliths), important for calcium carbonate cycle. + +| Variable | Description | Units | +|----------|-------------|-------| +| `NPPc` | Net primary production | mmolC/m²/d | +| `GPPc` | Gross primary production | mmolC/m²/d | +| `NNAc` | Net nitrogen assimilation rate | mmolN/m²/d | +| `Chldegc` | Chlorophyll degradation rate | 1/d | + +### Phaeocystis + +Colonial phytoplankton forming gelatinous colonies, important in polar and coastal regions. + +| Variable | Description | Units | +|----------|-------------|-------| +| `NPPp` | Net primary production | mmolC/m²/d | +| `GPPp` | Gross primary production | mmolC/m²/d | +| `NNAp` | Net nitrogen assimilation rate | mmolN/m²/d | +| `Chldegp` | Chlorophyll degradation rate | 1/d | + +--- + +## Zooplankton Grazing + +Grazing fluxes represent carbon transfer through the food web. Fluxes are given both as total (accounting for grazing efficiency) and by prey type (representing actual prey loss). + +### Microzooplankton + +Small heterotrophic protists (typically 20-200 μm) that graze on small phytoplankton. + +| Variable | Description | Units | +|----------|-------------|-------| +| `grazmicro_tot` | Total grazing flux (accounting for grazing efficiency) | mmolC/m²/d | +| `grazmicro_n` | Grazing on nanophytoplankton (equals nanophyto loss to microzoo) | mmolC/m²/d | +| `grazmicro_d` | Grazing on diatoms (equals diatom loss to microzoo) | mmolC/m²/d | +| `grazmicro_c` | Grazing on coccolithophores (equals coccolith loss to microzoo) | mmolC/m²/d | +| `grazmicro_p` | Grazing on Phaeocystis (equals Phaeocystis loss to microzoo) | mmolC/m²/d | + +### Mesozooplankton + +Medium-sized zooplankton (typically 0.2-20 mm) including copepods and other crustaceans. + +| Variable | Description | Units | +|----------|-------------|-------| +| `grazmeso_tot` | Total grazing flux (accounting for grazing efficiency) | mmolC/m²/d | +| `grazmeso_n` | Grazing on nanophytoplankton (equals nanophyto loss to mesozoo) | mmolC/m²/d | +| `grazmeso_d` | Grazing on diatoms (equals diatom loss to mesozoo) | mmolC/m²/d | +| `grazmeso_c` | Grazing on coccolithophores (equals coccolith loss to mesozoo) | mmolC/m²/d | +| `grazmeso_p` | Grazing on Phaeocystis (equals Phaeocystis loss to mesozoo) | mmolC/m²/d | +| `grazmeso_det` | Grazing on detritus group 1 (equals detritus 1 loss to mesozoo) | mmolC/m²/d | +| `grazmeso_mic` | Grazing on microzooplankton (equals microzoo loss to mesozoo) | mmolC/m²/d | +| `grazmeso_det2` | Grazing on detritus group 2 (equals detritus 2 loss to mesozoo) | mmolC/m²/d | + +### Macrozooplankton + +Large zooplankton (typically >20 mm) including krill and larger crustaceans. + +| Variable | Description | Units | +|----------|-------------|-------| +| `grazmacro_tot` | Total grazing flux (accounting for grazing efficiency) | mmolC/m²/d | +| `grazmacro_n` | Grazing on nanophytoplankton (equals nanophyto loss to macrozoo) | mmolC/m²/d | +| `grazmacro_d` | Grazing on diatoms (equals diatom loss to macrozoo) | mmolC/m²/d | +| `grazmacro_c` | Grazing on coccolithophores (equals coccolith loss to macrozoo) | mmolC/m²/d | +| `grazmacro_p` | Grazing on Phaeocystis (equals Phaeocystis loss to macrozoo) | mmolC/m²/d | +| `grazmacro_mes` | Grazing on mesozooplankton (equals mesozoo loss to macrozoo) | mmolC/m²/d | +| `grazmacro_det` | Grazing on detritus group 1 (equals detritus 1 loss to macrozoo) | mmolC/m²/d | +| `grazmacro_mic` | Grazing on microzooplankton (equals microzoo loss to macrozoo) | mmolC/m²/d | +| `grazmacro_det2` | Grazing on detritus group 2 (equals detritus 2 loss to macrozoo) | mmolC/m²/d | + +--- + +## Notes + +### Variable Naming Convention +- Suffix `n` = nanophytoplankton +- Suffix `d` = diatoms +- Suffix `c` = coccolithophores +- Suffix `p` = Phaeocystis +- Suffix `mic` = microzooplankton +- Suffix `mes` = mesozooplankton +- Suffix `det` = detritus group 1 +- Suffix `det2` = detritus group 2 + +### Unit Abbreviations +- `μatm` = micro-atmospheres (10⁻⁶ atm) +- `mmol` = millimoles (10⁻³ mol) +- `μmol` = micromoles (10⁻⁶ mol) +- `/d` = per day +- `/s` = per second +- `m²` = square meter + +### Grazing Efficiency +Grazing fluxes without efficiency (`grazmeso_n`, `grazmicro_d`, etc.) represent the actual amount of prey consumed and therefore equal the loss rate of that prey type. The total grazing flux (`grazmeso_tot`, etc.) accounts for grazing efficiency, representing the carbon actually assimilated by the grazer (the rest becomes detritus or dissolved organic matter). + +--- + +## Carbonate Chemistry System (3D Variables) + +Detailed carbonate chemistry variables throughout the water column. + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `PAR` | Photosynthetically Active Radiation | W/m² | Light energy available for photosynthesis (400-700nm wavelength), primary driver of phytoplankton growth | +| `CO2` | Aqueous CO2 concentration | mol/m³ | Dissolved CO2 in seawater, primary inorganic carbon form and substrate for photosynthesis | +| `pH` | Seawater pH | total scale | Measure of hydrogen ion concentration, affects carbonate chemistry and organism physiology (typically 7.5-8.5 in ocean) | +| `pCO2` | Partial pressure of CO2 | µatm | CO2 fugacity in equilibrium with atmosphere, determines air-sea CO2 flux direction and magnitude | +| `HCO3` | Bicarbonate ion concentration | mol/m³ | Major dissolved inorganic carbon species (~90% of DIC), pH buffer | +| `CO3` | Carbonate ion concentration | mol/m³ | Secondary DIC species, building block for calcium carbonate (CaCO₃) formation | +| `OmegaC` | Calcite saturation state (Ω) | dimensionless | Ratio of [Ca²⁺][CO3²⁻] to calcite solubility product; Ω>1 favors precipitation, reduced by ocean acidification | +| `kspc` | Calcite solubility product | mol²/kg² | Equilibrium constant for CaCO₃ dissolution, temperature/pressure dependent | +| `rhoSW` | In-situ seawater density | kg/m³ | Density at ambient temperature, salinity, and pressure; affects stratification and mixing | + +--- + +## Particle Dynamics + +Physical properties and sinking behavior of detrital particles. + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `rho_det1` | Density of particle class 1 | kg/m³ | Mass per unit volume of small/slow-sinking particles; determines sinking speed via Stokes' law | +| `rho_det2` | Density of particle class 2 | kg/m³ | Mass per unit volume of large/fast-sinking particles; higher density = faster sinking = efficient carbon export | +| `scaling_visc` | Viscosity-based scaling factor | dimensionless | Adjusts particle sinking based on water viscosity (warmer water = lower viscosity = faster sinking) | +| `wsink_det1` | Sinking velocity of particle class 1 | m/s | Vertical descent rate of small detrital particles; typically 1-50 m/day for small aggregates | +| `wsink_det2` | Sinking velocity of particle class 2 | m/s | Vertical descent rate of large detrital particles; typically 50-200+ m/day for large aggregates/fecal pellets | + +--- + +## Benthic Nutrient Fluxes (Extended) + +Sediment-water interface nutrient release from remineralization processes. + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `DIC_bf` | Dissolved Inorganic Carbon bottom flux | mmolC/m³ | Release of CO2/HCO3/CO3 from sediment remineralization; important in shallow seas | +| `DIN_bf` | Dissolved Inorganic Nitrogen bottom flux | mmolN/m³ | Release of NH4⁺/NO3⁻ from sediment remineralization; major N source in coastal/shelf systems | +| `Alk_bf` | Alkalinity bottom flux | meq/m³ | Release of acid-neutralizing capacity; dominated by NH4⁺ production and CaCO₃ dissolution | +| `DSi_bf` | Dissolved Silicate bottom flux | mmolSi/m³ | Release of Si(OH)4 from opal dissolution; critical nutrient for diatom growth | + +--- + +## Zooplankton Respiration (Extended) + +Metabolic CO2 production by different zooplankton size classes. + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `respmicro` | Microzooplankton respiration rate | mmolC/m²/d | Small grazers (<0.2 mm): ciliates, heterotrophic dinoflagellates; rapid nutrient recycling | +| `respmeso` | Mesozooplankton respiration rate | mmolC/m²/d | Medium-sized grazers (0.2-2 mm): copepods, euphausiids, chaetognaths | +| `respmacro` | Macrozooplankton respiration rate | mmolC/m²/d | Large grazers (>2 mm): large euphausiids, amphipods, jellyfish; produces fast-sinking fecal pellets | + +--- + +## Calcium Carbonate Dynamics + +Calcification and dissolution processes. + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `calcdiss` | Calcite (CaCO₃) dissolution rate | mmolC/m²/d | Conversion of solid CaCO₃ to dissolved Ca²⁺ and CO3²⁻; increases alkalinity, accelerated by ocean acidification | +| `calcif` | Calcification rate | mmolC/m²/d | Precipitation of calcium carbonate shells/tests by coccolithophores, foraminifera, pteropods; decreases alkalinity | + +--- + +## Phytoplankton Aggregation + +Formation of larger particles from small cells, converting slow-sinking cells to faster-sinking aggregates. + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `aggn` | Nanophytoplankton aggregation | mmolC/m²/d | Collision-driven clumping of 2-20 µm cells; enhanced by stickiness (TEP), turbulence, high cell density | +| `aggd` | Diatom aggregation | mmolC/m²/d | Formation of diatom-dominated marine snow; major pathway for carbon export during bloom collapse; Si:C ballasting enhances sinking (100-200 m/day) | +| `aggc` | Coccolithophore aggregation | mmolC/m²/d | Formation of coccolith-bearing aggregates; CaCO₃ ballasting enhances export efficiency; creates "white waters" during blooms | +| `aggp` | Phaeocystis aggregation | mmolC/(m²*d) | Colony formation of colonial haptophyte; forms mucilaginous colonies up to 3 cm; dominant in polar/subpolar regions | + +--- + +## Dissolved Organic Carbon (DOC) Excretion + +Release of dissolved organic compounds by phytoplankton (passive/active release, typically 5-20% of gross production). + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `docexn` | Nanophytoplankton DOC excretion | mmolC/m²/d | Fuels microbial loop; increases under nutrient stress or viral lysis | +| `docexd` | Diatom DOC excretion | mmolC/m²/d | Can be substantial during stationary phase or Si limitation; includes transparent exopolymer particles (TEP) | +| `docexc` | Coccolithophore DOC excretion | mmolC/m²/d | Released during calcification/growth; links organic and inorganic carbon cycles; may increase under high pCO₂ | +| `docexp` | Phaeocystis DOC excretion | mmolC/(m²*d) | Release of polysaccharides forming colonial matrix; major mucus producer; high C:N ratio, relatively refractory | + +--- + +## Phytoplankton Respiration (Extended) + +Metabolic CO2 release by autotrophs (maintenance metabolism and biosynthesis costs). + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `respn` | Nanophytoplankton respiration | mmolC/m²/d | Determines net vs gross primary production; typically 10-30% of GPP, increases with temperature | +| `respd` | Diatom respiration | mmolC/m²/d | Metabolic costs of rapid growth and Si metabolism; higher in fast-growing bloom-forming species | +| `respc` | Coccolithophore respiration | mmolC/(m²*d) | Includes calcification energy costs (~20% additional energy vs non-calcifiers); may increase under acidification stress | +| `respp` | Phaeocystis respiration | mmolC/(m²*d) | Metabolic costs of colonial vs solitary forms; colonial forms may have lower specific respiration rates | + +--- + +## Net Primary Production by Functional Group (3D) + +Net carbon fixation after respiration losses (gross photosynthesis minus respiration and exudation). + +| Variable | Description | Units | Ecological Role | +|----------|-------------|-------|-----------------| +| `NPPn3D` | Nanophytoplankton NPP | mmolC/m³/d | Sustained baseline production in oligotrophic waters; dominant in stratified, nutrient-poor conditions | +| `NPPd3D` | Diatom NPP | mmolC/m³/d | Bloom-forming, episodic production pulses; dominant in upwelling, mixed, nutrient-rich waters; r-strategists | +| `NPPc3D` | Coccolithophore NPP | mmolC/m³/d | Links organic and inorganic carbon pumps; bloom in stratified, post-bloom nutrient-depleted waters | +| `NPPp3D` | Phaeocystis NPP | mmolC/(m³*d) | High-latitude spring bloom specialist; tolerates low light, cold temperatures, ice-edge blooms | + +--- + +## Temperature Effects on Photosynthesis + +Temperature-dependent growth rate modifiers (Q10-based or Arrhenius growth rate multipliers). + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `TTemp_phyto` | Nanophytoplankton temperature factor | per day | Growth rate scaling with temperature; often have broader temperature tolerance than specialists | +| `TTemp_diatoms` | Diatom temperature factor | per day | Accelerates growth in warmer waters; often have lower temperature optimum than flagellates | +| `TTemp_cocco` | Coccolithophore temperature factor | per day | Often have higher temperature optima than diatoms; may expand poleward with warming | +| `TTemp_phaeo` | Phaeocystis temperature factor | per day | Adapted to low temperatures (0-10°C optimum); climate warming may reduce competitive advantage | + +--- + +## CO2 Effects on Photosynthesis + +pCO2-dependent growth modifiers representing ocean acidification impacts on carbon concentration mechanisms (CCM). + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `TPhyCO2` | Nanophytoplankton CO2 effect | per day | Some species benefit from higher CO2 (reduced CCM energy cost); generally small positive or neutral effect | +| `TDiaCO2` | Diatom CO2 effect | per day | Mixed responses; some species C3-like, others have efficient CCMs; high CO2 may reduce competitive advantage | +| `TCoccoCO2` | Coccolithophore CO2 effect | per day | High pCO2 may benefit photosynthesis but impair calcification; net effect species-specific, generally negative at >1000 µatm | +| `TPhaeoCO2` | Phaeocystis CO2 effect | per day | May benefit from CO2 enrichment in cold waters; limited experimental data compared to other groups | + +--- + +## Nutrient Limitation Factors + +Multi-nutrient limitation of photosynthesis following Liebig's Law of the Minimum (0-1 dimensionless multipliers). + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `TqLF_phyto` | Nanophytoplankton nutrient limitation | per day | Minimum of N, P, Fe limitation; often N-limited in stratified waters, Fe-limited in HNLC regions | +| `TqLF_diatoms` | Diatom nutrient limitation | per day | Minimum of N, P, Si, Fe limitation; Si limitation unique to diatoms, controls bloom termination | +| `TqLF_cocco` | Coccolithophore nutrient limitation | per day | Minimum of N, P limitation (no Si requirement); can exploit low-nutrient conditions after diatom bloom collapse | +| `TqLF_phaeo` | Phaeocystis nutrient limitation | per day | Minimum of N, P, Fe limitation; can form luxury nutrient reserves in colonial form; often blooms early when nutrients replete | + +--- + +## Light Limitation Factors + +Photosynthesis-irradiance (P-I) curve response factors (0-1 dimensionless multipliers). + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `TCphotLL_phyto` | Nanophytoplankton light limitation | per day | Reduces growth in low light, photoinhibition at high light; small cells acclimate faster to changing light | +| `TCphotLL_dia` | Diatom light limitation | per day | P-I curve with potentially higher light saturation point; often shade-adapted in coastal turbid waters; larger cells = slower photoacclimation | +| `TCphotLL_cocco` | Coccolithophore light limitation | per day | P-I curve for high-light adapted species; often prefer high irradiance, stratified waters; bloom in clear waters with deep light penetration | +| `TCphotLL_phaeo` | Phaeocystis light limitation | per day | P-I curve for low-light adapted polar species; low light saturation point; can grow under sea ice with <1% surface irradiance | + +--- + +## Carbon-Specific Photosynthesis Rates + +Actual photosynthetic carbon fixation rates (product of all limiting factors × maximum rate). + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `TCphot_phyto` | Nanophytoplankton C-specific photosynthesis | per day (d⁻¹) | Gross carbon fixation per unit biomass; typically 0.5-3.0 d⁻¹ in natural populations | +| `TCphot_diatoms` | Diatom C-specific photosynthesis | per day (d⁻¹) | Can reach very high rates (>5 d⁻¹) during blooms; r-strategists with high maximum growth rates | +| `TCphot_cocco` | Coccolithophore C-specific photosynthesis | per day (d⁻¹) | Lower than diatoms but sustained in stratified conditions; additional energy for CaCO₃ formation reduces net efficiency | +| `TCphot_phaeo` | Phaeocystis C-specific photosynthesis | per day (d⁻¹) | Efficient at low temperature and light; colonial forms may have lower per-cell rates but higher bloom biomass | + +--- + +## Silicate Assimilation + +Diatom-specific nutrient uptake for frustule (shell) construction. + +| Variable | Description | Units | Notes | +|----------|-------------|-------|-------| +| `TSi_assimDia` | Diatom silicate assimilation rate | per day (d⁻¹) | Uptake of Si(OH)4; Si:C ratio varies 0.1-1.0 depending on species and conditions; Si depletion terminates diatom blooms and shifts community to flagellates | + +--- + +**Model Reference**: REcoM (Regulated Ecosystem Model) - Biogeochemical ocean model component +**Last Updated**: 2025 + diff --git a/config/bin_2p1z1d/job_albedo b/config/bin_2p1z1d/job_albedo index d735fd967..a3429ac9d 100755 --- a/config/bin_2p1z1d/job_albedo +++ b/config/bin_2p1z1d/job_albedo @@ -1,5 +1,5 @@ #!/bin/bash -#SBATCH --account=biogeo_model.biogeo_model +#SBATCH --account=biogeo_model.biogeo_model # edit your account #SBATCH --job-name=2p1z1d #SBATCH --partition=mpp #SBATCH -N 9 diff --git a/config/bin_2p1z1d/namelist.config b/config/bin_2p1z1d/namelist.config index ffff081c0..1af8eedad 100644 --- a/config/bin_2p1z1d/namelist.config +++ b/config/bin_2p1z1d/namelist.config @@ -1,76 +1,133 @@ -! This is the namelist file for model general configuration +! ============================================================================ +! ============ Namelist file for FESOM2 general configuration ================ +! ============================================================================ +! This file contains the main configuration parameters for FESOM2, including: +! - Model identification and run settings +! - Time stepping and simulation duration +! - Initial time/date settings +! - File paths for mesh, forcing, and output +! - Restart and logging configuration +! - Vertical coordinate system (ALE) +! - Grid geometry and rotation +! - Calendar settings +! - Model components (ice, cavities, etc.) +! - Parallel decomposition +! - Iceberg settings +! ============================================================================ +! ============================================================================ +! RUN IDENTIFICATION +! ============================================================================ &modelname -runid='fesom' +runid = 'fesom' ! run identifier (used in output filenames) / +! ============================================================================ +! TIME STEPPING AND RUN LENGTH +! ============================================================================ ×tep -step_per_day=32 !96 !96 !72 !72 !45 !72 !96 -run_length= 1 !62 !62 !62 !28 -run_length_unit='y' ! y, m, d, s +step_per_day = 36 ! number of time steps per day (determines dt = 86400/step_per_day seconds) + ! common values: 32 (45min), 48 (30min), 72 (20min), 96 (15min), 192 (7min 30sec), + ! 216 (6min 40sec), 240 (6min), 288 (5min), 360 (4min), 720 (2min), 1440 (1min), 2880 (30sec) +run_length = 1 ! total length of simulation run +run_length_unit = 'y' ! unit for run_length: 'y' (years), 'm' (months), 'd' (days), 's' (steps) / -&clockinit ! the model starts at -timenew=0.0 -daynew=1 -yearnew=1958 +! ============================================================================ +! INITIAL TIME/DATE SETTINGS +! ============================================================================ +&clockinit +timenew = 0.0 ! initial time within the day [seconds] (0.0 = midnight) +daynew = 1 ! initial day of the month (1-31) +yearnew = 1958 ! initial year / +! ============================================================================ +! MESH, INITIALIZATION & OUTPUT PATHS +! ============================================================================ &paths -MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' -ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' -ResultPath='/albedo/work/user/...' +MeshPath = '/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/work/user/...' / +! ============================================================================ +! 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_transit=.false. +use_ice = .true. ! enable sea ice model +use_cavity = .false. ! enable ice shelf cavities +use_cavity_partial_cell = .false. ! use partial cells in ice shelf cavities (not recommended) +use_floatice = .false. ! enable floating ice (icebergs) +use_sw_pene = .true. ! enable shortwave radiation penetration into ocean +flag_debug = .false. ! enable debug output (verbose logging) +use_transit = .false. ! enable transient tracer module (CFCs, SF6, etc.) / +! ============================================================================ +! PARALLEL DECOMPOSITION (DOMAIN PARTITIONING) +! ============================================================================ &machine -n_levels=2 -n_part= 12, 36 ! 432 number of partitions on each hierarchy level +n_levels = 2 ! number of hierarchy levels for domain decomposition +n_part = 2, 128 ! number of partitions at each level (total CPUs = product of n_part) + ! example: 2 x 128 = 256 MPI tasks + ! adjust based on mesh size and available compute resources + ! maximum scaling reached at ~300 FESOM2 2D nodes per CPU (see first line in nod2d.out for number of 2D nodes) / +! ============================================================================ +! ICEBERG SETTINGS +! ============================================================================ &icebergs -use_icesheet_coupling=.false. -ib_num=1 -use_icebergs=.false. -steps_per_ib_step=8 -ib_async_mode=0 +use_icesheet_coupling = .false. ! enable ice sheet model +ib_num = 1 ! number of iceberg classes +use_icebergs = .false. ! enable iceberg module +steps_per_ib_step = 8 ! ocean time steps per iceberg time step (iceberg subcycling) +ib_async_mode = 0 ! iceberg asynchronous mode (0=synchronous, 1=asynchronous) / diff --git a/config/bin_2p1z1d/namelist.io b/config/bin_2p1z1d/namelist.io index 990c90c2f..e3b3155a4 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 bcdea2e79..ea39a42f1 100644 --- a/config/bin_2p1z1d/namelist.recom +++ b/config/bin_2p1z1d/namelist.recom @@ -1,361 +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 (meso, macro/krill, micro) +! - 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' / +! ============================================================================ +! GENERAL MODEL CONFIGURATION +! ============================================================================ &parecomsetup -enable_3zoo2det = .true. -enable_coccos = .false. +enable_3zoo2det = .false. ! Enable 3 zooplankton + 2 detritus configuration (currently disabled) +enable_coccos = .false. ! Enable coccolithophores (currently disabled) +recom_coupled_to_atmosphere = .false. ! REcoM driven by coupled atmosphere +enable_R2OMIP = .false. ! Enable R2OMIP / +! ============================================================================ +! MAIN MODEL SWITCHES AND SETTINGS +! ============================================================================ +! --- Core Model Settings --- &pavariables -use_REcoM =.true. -REcoM_restart =.true. - -bgc_num = 22 !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 -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 = .true. ! O2remin Add option for O2 dependency of organic matter remineralization -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. +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. ! Turns dust input of iron off when set to.false. -UseDustClim = .true. -UseDustClimAlbani = .true. ! Use Albani dustclim field (If it is false Mahowald will be used) -use_photodamage = .true. ! use Alvarez et al (2018) for chlorophyll degradation -HetRespFlux_plus = .true. !MB More stable computation of zooplankton respiration fluxes adding a small number to HetN -REcoMDataPath = '/albedo/work/projects/MarESys/ogurses/input/mesh_CORE2_finaltopo_mean/' -restore_alkalinity = .true. -useRivers = .false. -useRivFe = .false. ! When set to true, riverine Fe source is activated -useErosion = .false. -NitrogenSS = .false. ! When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) -useAeolianN = .false. ! When set to true, aeolian nitrogen deposition is activated -firstyearoffesomcycle = 1958 ! The first year of the actual physical forcing (e.g. JRA-55) used -lastyearoffesomcycle = 2024 ! Last year of the actual physical forcing used -numofCO2cycles = 1 ! Number of cycles of the forcing planned -currentCO2cycle = 1 ! Which CO2 cycle we are currently running -DIC_PI = .true. -Nmocsy = 1 ! Length of the vector that is passed to mocsy (always one for recom) -recom_debug =.false. -ciso =.false. ! Main switch to enable/disable carbon isotopes (13|14C) -benthos_num = 4 ! number of benthic BGC tracers -> 8 if (ciso == .true.) otherwise -> 4 -use_MEDUSA = .false. ! Main switch for the sediment model MEDUSA -sedflx_num = 0 ! if 0: no file from MEDUSA is read but default sediment -bottflx_num = 4 ! if ciso&ciso_14: =8; if .not.ciso_14: =6; no ciso: =4 -use_atbox = .false. -add_loopback = .false. ! add loopback fluxes through rivers to the surface -lb_tscale = 1.0 ! /year: fraction of loopback fluxes yearly added to the surface -/ - +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 ! 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 -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 -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 -/ - +! --- 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 -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 -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 -SiCmax = 0.8d0 -NCuptakeRatio = 0.2d0 ! [mmol N/mmol C] Maximum uptake ratio of N:C -NCUptakeRatio_d = 0.2d0 -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 -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 -res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant -res_phy_d = 0.01d0 -res_phy_c = 0.01d0 -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] / +! ============================================================================ +! MESOZOOPLANKTON (FIRST ZOOPLANKTON) +! ============================================================================ &pazooplankton -graz_max = 2.4d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter -epsilonr = 0.35d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss -res_het = 0.01d0 ! [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.05d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) -pzDia = 0.5d0 ! Maximum diatom preference -sDiaNsq = 0.d0 -pzPhy = 1.0d0 ! Maximum small phytoplankton preference -sPhyNsq = 0.d0 -pzCocco = 0.4d0 ! Maximum coccolithophore preference ! will not be used in the 2p1z1d version -sCoccoNsq = 0.d0 -pzMicZoo = 1.0d0 ! Maximum microzooplankton preference ! will not be used in the 2p1z1d version -sMicZooNsq = 0.d0 -tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. -/ - -&pasecondzooplankton ! will not be used in the 2p1z1d version -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 -fecal_rate_c_mes = 0.32d0 -pzDia2 = 1.0d0 ! Maximum diatom preference -sDiaNsq2 = 0.d0 -pzPhy2 = 0.08d0 ! Maximum small phytoplankton preference -sPhyNsq2 = 0.d0 -pzCocco2 = 0.8d0 ! Maximum coccolithophore preference -sCoccoNsq2 = 0.d0 -pzHet = 1.5d0 ! Maximum mesozooplankton preference -sHetNsq = 0.d0 -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 -t3_zoo2 = 105234.d0 ! Krill temp. function constant3 -t4_zoo2 = 274.15d0 ! Krill temp. function constant3 -/ - -&pathirdzooplankton ! will not be used in the 2p1z1d version -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.01d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) -pzDia3 = 0.04d0 ! Maximum diatom preference -sDiaNsq3 = 0.d0 -pzPhy3 = 0.08d0 ! Maximum small phytoplankton preference -sPhyNsq3 = 0.d0 -pzCocco3 = 0.8d0 ! Maximum coccolithophore preference -sCoccoNsq3 = 0.d0 -/ - +graz_max = 0.31 ! Maximum grazing rate [1/day] +epsilonr = 0.09 ! Half-saturation constant [(mmol N)²/m⁶] +res_het = 0.028 ! Respiration [1/day] +Redfield = 6.625 ! C:N Redfield ratio [mmol C/mmol N] +loss_het = 0.04 ! The quadratic mortality rate (loss to detritus) [m3/(mmolN*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 +/ + +! ============================================================================ +! MACROZOOPLANKTON (SECOND ZOOPLANKTON) +! ============================================================================ +&pasecondzooplankton +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.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 (Mesozooplankton) --- +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 (Macrozooplankton) --- +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 +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 +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.075 !0.2d0 !0.25d0 ! [1/day] -deg_Chl_d = 0.075 !0.3d0 !0.15d0 -deg_Chl_c = 0.075 !0.2d0 +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 ! [] 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 ! [] 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.15d0 -lossC_z = 0.15d0 +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 -lossC_z3 = 0.05d0 +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 ! 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] +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 ! 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 ! 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 +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 = 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 ! 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 d6e379887..21de5f502 100755 --- a/config/bin_2p3z2d/job_albedo +++ b/config/bin_2p3z2d/job_albedo @@ -1,5 +1,5 @@ #!/bin/bash -#SBATCH --account=biogeo_model.biogeo_model +#SBATCH --account=biogeo_model.biogeo_model # edit your account #SBATCH --job-name=2p3z2d #SBATCH --partition=mpp #SBATCH -N 9 diff --git a/config/bin_2p3z2d/namelist.config b/config/bin_2p3z2d/namelist.config index ffff081c0..1af8eedad 100644 --- a/config/bin_2p3z2d/namelist.config +++ b/config/bin_2p3z2d/namelist.config @@ -1,76 +1,133 @@ -! This is the namelist file for model general configuration +! ============================================================================ +! ============ Namelist file for FESOM2 general configuration ================ +! ============================================================================ +! This file contains the main configuration parameters for FESOM2, including: +! - Model identification and run settings +! - Time stepping and simulation duration +! - Initial time/date settings +! - File paths for mesh, forcing, and output +! - Restart and logging configuration +! - Vertical coordinate system (ALE) +! - Grid geometry and rotation +! - Calendar settings +! - Model components (ice, cavities, etc.) +! - Parallel decomposition +! - Iceberg settings +! ============================================================================ +! ============================================================================ +! RUN IDENTIFICATION +! ============================================================================ &modelname -runid='fesom' +runid = 'fesom' ! run identifier (used in output filenames) / +! ============================================================================ +! TIME STEPPING AND RUN LENGTH +! ============================================================================ ×tep -step_per_day=32 !96 !96 !72 !72 !45 !72 !96 -run_length= 1 !62 !62 !62 !28 -run_length_unit='y' ! y, m, d, s +step_per_day = 36 ! number of time steps per day (determines dt = 86400/step_per_day seconds) + ! common values: 32 (45min), 48 (30min), 72 (20min), 96 (15min), 192 (7min 30sec), + ! 216 (6min 40sec), 240 (6min), 288 (5min), 360 (4min), 720 (2min), 1440 (1min), 2880 (30sec) +run_length = 1 ! total length of simulation run +run_length_unit = 'y' ! unit for run_length: 'y' (years), 'm' (months), 'd' (days), 's' (steps) / -&clockinit ! the model starts at -timenew=0.0 -daynew=1 -yearnew=1958 +! ============================================================================ +! INITIAL TIME/DATE SETTINGS +! ============================================================================ +&clockinit +timenew = 0.0 ! initial time within the day [seconds] (0.0 = midnight) +daynew = 1 ! initial day of the month (1-31) +yearnew = 1958 ! initial year / +! ============================================================================ +! MESH, INITIALIZATION & OUTPUT PATHS +! ============================================================================ &paths -MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' -ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' -ResultPath='/albedo/work/user/...' +MeshPath = '/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/work/user/...' / +! ============================================================================ +! 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_transit=.false. +use_ice = .true. ! enable sea ice model +use_cavity = .false. ! enable ice shelf cavities +use_cavity_partial_cell = .false. ! use partial cells in ice shelf cavities (not recommended) +use_floatice = .false. ! enable floating ice (icebergs) +use_sw_pene = .true. ! enable shortwave radiation penetration into ocean +flag_debug = .false. ! enable debug output (verbose logging) +use_transit = .false. ! enable transient tracer module (CFCs, SF6, etc.) / +! ============================================================================ +! PARALLEL DECOMPOSITION (DOMAIN PARTITIONING) +! ============================================================================ &machine -n_levels=2 -n_part= 12, 36 ! 432 number of partitions on each hierarchy level +n_levels = 2 ! number of hierarchy levels for domain decomposition +n_part = 2, 128 ! number of partitions at each level (total CPUs = product of n_part) + ! example: 2 x 128 = 256 MPI tasks + ! adjust based on mesh size and available compute resources + ! maximum scaling reached at ~300 FESOM2 2D nodes per CPU (see first line in nod2d.out for number of 2D nodes) / +! ============================================================================ +! ICEBERG SETTINGS +! ============================================================================ &icebergs -use_icesheet_coupling=.false. -ib_num=1 -use_icebergs=.false. -steps_per_ib_step=8 -ib_async_mode=0 +use_icesheet_coupling = .false. ! enable ice sheet model +ib_num = 1 ! number of iceberg classes +use_icebergs = .false. ! enable iceberg module +steps_per_ib_step = 8 ! ocean time steps per iceberg time step (iceberg subcycling) +ib_async_mode = 0 ! iceberg asynchronous mode (0=synchronous, 1=asynchronous) / diff --git a/config/bin_2p3z2d/namelist.recom b/config/bin_2p3z2d/namelist.recom index af69391f2..20e0d95be 100644 --- a/config/bin_2p3z2d/namelist.recom +++ b/config/bin_2p3z2d/namelist.recom @@ -1,361 +1,518 @@ -! 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 (meso, macro/krill, micro) +! - 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' / +! ============================================================================ +! GENERAL MODEL CONFIGURATION +! ============================================================================ &parecomsetup -enable_3zoo2det = .true. -enable_coccos = .false. +enable_3zoo2det = .true. ! Enable 3 zooplankton + 2 detritus configuration +enable_coccos = .false. ! Enable coccolithophores (currently disabled) +recom_coupled_to_atmosphere = .false. ! REcoM driven by coupled atmosphere +enable_R2OMIP = .false. ! Enable R2OMIP / +! ============================================================================ +! MAIN MODEL SWITCHES AND SETTINGS +! ============================================================================ +! --- Core Model Settings --- &pavariables -use_REcoM =.true. -REcoM_restart =.true. - -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 -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 = .true. ! O2remin Add option for O2 dependency of organic matter remineralization -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. +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. ! Turns dust input of iron off when set to.false. -UseDustClim = .true. -UseDustClimAlbani = .true. ! Use Albani dustclim field (If it is false Mahowald will be used) -use_photodamage = .true. ! use Alvarez et al (2018) for chlorophyll degradation -HetRespFlux_plus = .true. !MB More stable computation of zooplankton respiration fluxes adding a small number to HetN -REcoMDataPath = '/albedo/work/projects/MarESys/ogurses/input/mesh_CORE2_finaltopo_mean/' -restore_alkalinity = .true. -useRivers = .false. -useRivFe = .false. ! When set to true, riverine Fe source is activated -useErosion = .false. -NitrogenSS = .false. ! When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) -useAeolianN = .false. ! When set to true, aeolian nitrogen deposition is activated -firstyearoffesomcycle = 1958 ! The first year of the actual physical forcing (e.g. JRA-55) used -lastyearoffesomcycle = 2024 ! Last year of the actual physical forcing used -numofCO2cycles = 1 ! Number of cycles of the forcing planned -currentCO2cycle = 1 ! Which CO2 cycle we are currently running -DIC_PI = .true. -Nmocsy = 1 ! Length of the vector that is passed to mocsy (always one for recom) -recom_debug =.false. -ciso =.false. ! Main switch to enable/disable carbon isotopes (13|14C) -benthos_num = 4 ! number of benthic BGC tracers -> 8 if (ciso == .true.) otherwise -> 4 -use_MEDUSA = .false. ! Main switch for the sediment model MEDUSA -sedflx_num = 0 ! if 0: no file from MEDUSA is read but default sediment -bottflx_num = 4 ! if ciso&ciso_14: =8; if .not.ciso_14: =6; no ciso: =4 -use_atbox = .false. -add_loopback = .false. ! add loopback fluxes through rivers to the surface -lb_tscale = 1.0 ! /year: fraction of loopback fluxes yearly added to the surface -/ - +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 mesozooplankton nitrogen [mmol N/m³] +cZoo2N = 0.2 ! Initial macrozooplankton 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 ! 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 -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 -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 -/ - +! --- 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 -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 -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 -SiCmax = 0.8d0 -NCuptakeRatio = 0.2d0 ! [mmol N/mmol C] Maximum uptake ratio of N:C -NCUptakeRatio_d = 0.2d0 -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 -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 -res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant -res_phy_d = 0.01d0 -res_phy_c = 0.01d0 -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] / +! ============================================================================ +! MESOZOOPLANKTON (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 = 0.5d0 ! Maximum diatom preference -sDiaNsq = 0.d0 -pzPhy = 0.04d0 ! Maximum small phytoplankton preference -sPhyNsq = 0.d0 -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. -/ - +graz_max = 0.31 ! Maximum grazing rate [1/day] +epsilonr = 0.09 ! Half-saturation constant [(mmol N)²/m⁶] +res_het = 0.028 ! Respiration [1/day] +Redfield = 6.625 ! C:N Redfield ratio [mmol C/mmol N] +loss_het = 0.04 ! The quadratic mortality rate (loss to detritus) [m3/(mmolN*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) ! check, should this be moved to micro? or is this mesozooplankton graing on micro? +sMicZooNsq = 0.0 ! Microzooplankton preference slope +/ + +! ============================================================================ +! MACROZOOPLANKTON (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 -fecal_rate_c_mes = 0.32d0 -pzDia2 = 1.0d0 ! Maximum diatom preference -sDiaNsq2 = 0.d0 -pzPhy2 = 0.07d0 ! Maximum small phytoplankton preference -sPhyNsq2 = 0.d0 -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 ! Maximum microzooplankton 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 ! Macrozooplankton N fecal rate [1/day] +fecal_rate_c_mes = 0.32 ! Macrozooplankton 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 ! Macrozooplankton preference +sHetNsq = 0.0 ! Macrozooplankton preference slope +pzMicZoo2 = 1.0 ! Macrozooplankton preference on microzooplankton +sMicZooNsq2 = 0.0 ! Macrozooplankton preference slope on microzooplankton + +! --- 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 ! [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 -/ - +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 (Mesozooplankton) --- +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 (Macrozooplankton) --- +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 +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 +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.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 +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 ! [] 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 ! [] 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 -lossC_z3 = 0.05d0 +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 ! 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] +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 ! 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 ! 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 +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 = 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 ! 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/job_albedo b/config/bin_3p3z2d/job_albedo deleted file mode 100755 index f00ec4f36..000000000 --- a/config/bin_3p3z2d/job_albedo +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -#SBATCH --account=biogeo_model.biogeo_model -#SBATCH --job-name=3p3z2d -#SBATCH --partition=mpp -#SBATCH -N 9 -#SBATCH --cpus-per-task=1 -#SBATCH --time=08:00:00 -#SBATCH --qos=12h -#SBATCH --tasks-per-node 96 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O - -#SBATCH -o slurm-out.out -#SBATCH -e slurm-err.out - -# disable hyperthreading -#SBATCH --hint=nomultithread - -module purge -source ../env/albedo/shell -export OMP_NUM_THREADS=1 -ulimit -s unlimited - -# determine JOBID -JOBID=`echo $SLURM_JOB_ID |cut -d"." -f1` - -#ln -s ../bin/fesom.x . # cp -n ../bin/fesom.x -#cp -n ../config/namelist.config . -#cp -n ../config/namelist.forcing . -#cp -n ../config/namelist.oce . -#cp -n ../config/namelist.dyn . -#cp -n ../config/namelist.tra . -#cp -n ../config/namelist.ice . -#cp -n ../config/namelist.io . -#cp -n ../config/namelist.icepack . - -#___DETERMINE SLURM JOBID+OUTPUTFILE____________________________________________ -jobid=$(echo $SLURM_JOB_ID | cut -d"." -f1) -fname="fesom2.0.out" - -#___PUT JOB IN QUEUE____________________________________________________________ -date -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_albedo -#fi - -Resultpath='/albedo/work/user/...' -test -e $Resultpath/fesom.xxxxxx.oce.restart && exit - -IsInFile=$( tail -3 fesom2.0.out | grep -c timesteps) -if (( IsInFile > 0 )); then -# submit next #job \ - echo "submitting next job" - cp fesom2.0.out fesom.out.done - sbatch job_albedo -else - echo "something is wrong, last line of fesom.out reads" - echo $( tail -1 fesom2.0.out) - echo "abnormal termination of job script" -fi diff --git a/config/bin_3p3z2d/namelist.config b/config/bin_3p3z2d/namelist.config deleted file mode 100644 index ffff081c0..000000000 --- a/config/bin_3p3z2d/namelist.config +++ /dev/null @@ -1,76 +0,0 @@ -! This is the namelist file for model general configuration - -&modelname -runid='fesom' -/ - -×tep -step_per_day=32 !96 !96 !72 !72 !45 !72 !96 -run_length= 1 !62 !62 !62 !28 -run_length_unit='y' ! y, m, d, s -/ - -&clockinit ! the model starts at -timenew=0.0 -daynew=1 -yearnew=1958 -/ - -&paths -MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' -ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' -ResultPath='/albedo/work/user/...' -/ - -&restart_log -restart_length=1 ! --> do netcdf restart ( only required for d,h,s cases, y, m take 1) -restart_length_unit='y' !output period: y, d, h, s, off -raw_restart_length=1 ! --> do core dump restart -raw_restart_length_unit='off' ! e.g. y, d, h, s, off -bin_restart_length=1 ! --> do derived type binary restart -bin_restart_length_unit='off' ! e.g. y, d, h, s, off -logfile_outfreq=960 !in logfile info. output frequency, # steps -/ - -&ale_def -which_ALE='zstar' ! 'linfs','zlevel', 'zstar' -use_partial_cell=.true. -/ - -&geometry -cartesian=.false. -fplane=.false. -cyclic_length=360 ![degree] -rotated_grid=.true. !option only valid for coupled model case now -force_rotation=.true. -alphaEuler=50. ![degree] Euler angles, convention: -betaEuler=15. ![degree] first around z, then around new x, -gammaEuler=-90. ![degree] then around new z. -/ - -&calendar -include_fleapyear=.false. -/ - -&run_config -use_ice=.true. ! ocean+ice -use_cavity=.false. ! -use_cavity_partial_cell=.false. -use_floatice = .false. -use_sw_pene=.true. -flag_debug=.false. -use_transit=.false. -/ - -&machine -n_levels=2 -n_part= 12, 36 ! 432 number of partitions on each hierarchy level -/ - -&icebergs -use_icesheet_coupling=.false. -ib_num=1 -use_icebergs=.false. -steps_per_ib_step=8 -ib_async_mode=0 -/ diff --git a/config/bin_3p3z2d/namelist.dyn b/config/bin_3p3z2d/namelist.dyn deleted file mode 100644 index fb7919588..000000000 --- a/config/bin_3p3z2d/namelist.dyn +++ /dev/null @@ -1,24 +0,0 @@ -&dynamics_visc -visc_gamma0 = 0.003 ! [m/s], backgroung viscosity= gamma0*len, it should be as small a s possible (keep it < 0.01 m/s). -visc_gamma1 = 0.1 ! [nodim], for computation of the flow aware viscosity -visc_gamma2 = 0.285 ! [s/m], is only used in easy backscatter option -visc_easybsreturn= 1.5 - -opt_visc = 5 -! 5=Kinematic (easy) Backscatter -! 6=Biharmonic flow aware (viscosity depends on velocity Laplacian) -! 7=Biharmonic flow aware (viscosity depends on velocity differences) -! 8=Dynamic Backscatter - -use_ivertvisc= .true. -/ - -&dynamics_general -momadv_opt = 2 ! option for momentum advection in moment only =2 -use_freeslip = .false. ! Switch on free slip -use_wsplit = .false. ! Switch for implicite/explicte splitting of vert. velocity -wsplit_maxcfl= 1.0 ! maximum allowed CFL criteria in vertical (0.5 < w_max_cfl < 1.) - ! in older FESOM it used to be w_exp_max=1.e-3 -ldiag_KE=.false. ! activates energy diagnostics -/ - diff --git a/config/bin_3p3z2d/namelist.forcing b/config/bin_3p3z2d/namelist.forcing deleted file mode 100644 index d890c69ec..000000000 --- a/config/bin_3p3z2d/namelist.forcing +++ /dev/null @@ -1,80 +0,0 @@ -! This is the namelist file for forcing - -&forcing_exchange_coeff -Ce_atm_oce=0.00175 ! exchange coeff. of latent heat over open water -Ch_atm_oce=0.00175 ! exchange coeff. of sensible heat over open water -Cd_atm_oce=0.001 ! drag coefficient between atmosphere and water -Ce_atm_ice=0.00175 ! exchange coeff. of latent heat over ice -Ch_atm_ice=0.00175 ! exchange coeff. of sensible heat over ice -Cd_atm_ice=0.0012 ! drag coefficient between atmosphere and ice -Swind =0.0 ! parameterization for coupled current feedback -/ - -&forcing_bulk -AOMIP_drag_coeff=.false. -ncar_bulk_formulae=.true. -ncar_bulk_z_wind=10.0 ! height at which wind forcing is located (CORE, JRA-do: 10m, JRA, NCEP:2m) -ncar_bulk_z_tair=10.0 ! height at which temp forcing is located (CORE, JRA-do: 10m, JRA, NCEP:2m) -ncar_bulk_z_shum=10.0 ! height at which humi forcing is located (CORE, JRA-do: 10m, JRA, NCEP:2m) - -/ - -&land_ice -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 - nm_tair_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/tas.clim61' ! name of file with 2m air temperature - nm_prec_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/prra.clim61' ! name of file with total precipitation - nm_snow_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/prsn.clim61' ! name of file with snow precipitation - 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_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_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_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. - 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_3p3z2d/namelist.ice deleted file mode 100644 index bcd86f145..000000000 --- a/config/bin_3p3z2d/namelist.ice +++ /dev/null @@ -1,31 +0,0 @@ -! Ice namelist -&ice_dyn -whichEVP=0 ! 0=standart; 1=mEVP; 2=aEVP -Pstar=30000.0 ! [N/m^2] -ellipse=2.0 -c_pressure=20.0 ! ice concentration parameter used in ice strength computation -delta_min=1.0e-11 ! [s^(-1)] -evp_rheol_steps=120 ! number of EVP subcycles -alpha_evp=250 ! constant that control numerical stability of mEVP. Adjust with resolution. -beta_evp=250 ! constant that control numerical stability of mEVP. Adjust with resolution. -c_aevp=0.15 ! a tuning constant in aEVP. Adjust with resolution. -Cd_oce_ice=0.0055 ! drag coef. oce - ice -ice_gamma_fct=0.5 ! smoothing parameter -ice_diff=0.0 ! diffusion to stabilize -theta_io=0.0 ! rotation angle -ice_ave_steps=1 ! ice step=ice_ave_steps*oce_step -/ - -&ice_therm -Sice=4.0 ! Ice salinity 3.2--5.0 ppt. -h0=.5 ! Lead closing parameter [m] -emiss_ice=0.97 ! Emissivity of Snow/Ice, -emiss_wat=0.97 ! Emissivity of open water -albsn=0.81 ! Albedo: frozen snow -albsnm=0.77 ! melting snow -albi=0.7 ! frozen ice -albim=0.68 ! melting ice -albw=0.1 ! open water -con=2.1656 ! Thermal conductivities: ice; W/m/K -consn=0.31 ! snow -/ diff --git a/config/bin_3p3z2d/namelist.icepack b/config/bin_3p3z2d/namelist.icepack deleted file mode 100644 index ed0dd4d4c..000000000 --- a/config/bin_3p3z2d/namelist.icepack +++ /dev/null @@ -1,146 +0,0 @@ -&env_nml ! In the original release these variables are defined in the icepack.settings - nicecat = 5 ! number of ice thickness categories - nfsdcat = 1 ! number of floe size categories - nicelyr = 4 ! number of vertical layers in the ice - nsnwlyr = 4 ! number of vertical layers in the snow - ntraero = 0 ! number of aerosol tracers (up to max_aero in ice_domain_size.F90) - trzaero = 0 ! number of z aerosol tracers (up to max_aero = 6) - tralg = 0 ! number of algal tracers (up to max_algae = 3) - trdoc = 0 ! number of dissolve organic carbon (up to max_doc = 3) - trdic = 0 ! number of dissolve inorganic carbon (up to max_dic = 1) - trdon = 0 ! number of dissolve organic nitrogen (up to max_don = 1) - trfed = 0 ! number of dissolved iron tracers (up to max_fe = 2) - trfep = 0 ! number of particulate iron tracers (up to max_fe = 2) - nbgclyr = 0 ! number of zbgc layers - trbgcz = 0 ! set to 1 for zbgc tracers (needs TRBGCS = 0 and TRBRI = 1) - trzs = 0 ! set to 1 for zsalinity tracer (needs TRBRI = 1) - trbri = 0 ! set to 1 for brine height tracer - trage = 0 ! set to 1 for ice age tracer - trfy = 0 ! set to 1 for first-year ice area tracer - trlvl = 0 ! set to 1 for level and deformed ice tracers - trpnd = 0 ! set to 1 for melt pond tracers - trbgcs = 0 ! set to 1 for skeletal layer tracers (needs TRBGCZ = 0) - ndtd = 1 ! dynamic time steps per thermodynamic time step -/ - -&grid_nml - kcatbound = 1 -/ - -&tracer_nml - tr_iage = .false. - tr_FY = .false. - tr_lvl = .false. - tr_pond_cesm = .false. - tr_pond_topo = .false. - tr_pond_lvl = .false. - tr_aero = .false. - tr_fsd = .false. -/ - -&thermo_nml - kitd = 1 - ktherm = 1 - conduct = 'bubbly' - a_rapid_mode = 0.5e-3 - Rac_rapid_mode = 10.0 - aspect_rapid_mode = 1.0 - dSdt_slow_mode = -5.0e-8 - phi_c_slow_mode = 0.05 - phi_i_mushy = 0.85 - ksno = 0.3 -/ - -&shortwave_nml - shortwave = 'ccsm3' - albedo_type = 'ccsm3' - albicev = 0.78 - albicei = 0.36 - albsnowv = 0.98 - albsnowi = 0.70 - albocn = 0.1 - ahmax = 0.3 - R_ice = 0. - R_pnd = 0. - R_snw = 1.5 - dT_mlt = 1.5 - rsnw_mlt = 1500. - kalg = 0.6 -/ - -&ponds_nml - hp1 = 0.01 - hs0 = 0. - hs1 = 0.03 - dpscale = 1.e-3 - frzpnd = 'hlid' - rfracmin = 0.15 - rfracmax = 1. - pndaspect = 0.8 -/ - -&forcing_nml - formdrag = .false. - atmbndy = 'default' - calc_strair = .true. - calc_Tsfc = .true. - highfreq = .false. - natmiter = 5 - ustar_min = 0.0005 - emissivity = 0.95 - fbot_xfer_type = 'constant' - update_ocn_f = .false. - l_mpond_fresh = .false. - tfrz_option = 'linear_salt' - oceanmixed_ice = .true. - wave_spec_type = 'none' -/ - -&dynamics_nml - kstrength = 1 - krdg_partic = 1 - krdg_redist = 1 - mu_rdg = 3 - Cf = 17. - P_star = 27000. - C_star = 20. -/ - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!!!!!!!!!! Icepack output namelist !!!!!!!!!! -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -&nml_list_icepack -io_list_icepack = 'aicen ',1, 'm', 4, ! Sea ice concentration - 'vicen ',1, 'm', 4, ! Volume per unit area of ice - 'vsnon ',1, 'm', 4, ! Volume per unit area of snow - !'Tsfcn ',1, 'm', 4, ! Sea ice surf. temperature - !'iagen ',1, 'm', 4, ! Sea ice age - !'FYn ',1, 'm', 4, ! First year ice - !'lvln ',1, 'm', 4, ! Ridged sea ice area and volume - !'pond_cesmn',1, 'm', 4, ! Melt ponds area, volume and refrozen lid thickness - !'pond_topon',1, 'm', 4, ! Melt ponds area, volume and refrozen lid thickness - !'pond_lvln ',1, 'm', 4, ! Melt ponds area, volume and refrozen lid thickness - !'brinen ',1, 'm', 4, ! Volume fraction of ice with dynamic salt - !'qicen ',1, 'm', 4, ! Sea ice enthalpy - !'sicen ',1, 'm', 4, ! Sea ice salinity - !'qsnon ',1, 'm', 4, ! Snow enthalpy - ! Average over thicknes classes - !'aice ',1, 'm', 4, ! Sea ice concentration - !'vice ',1, 'm', 4, ! Volume per unit area of ice - !'vsno ',1, 'm', 4, ! Volume per unit area of snow - !'Tsfc ',1, 'm', 4, ! Sea ice surf. temperature - !'iage ',1, 'm', 4, ! Sea ice age - !'FY ',1, 'm', 4, ! First year ice - !'lvl ',1, 'm', 4, ! Ridged sea ice area and volume - !'pond_cesm ',1, 'm', 4, ! Melt ponds area, volume and refrozen lid thickness - !'pond_topo ',1, 'm', 4, ! Melt ponds area, volume and refrozen lid thickness - !'pond_lvl ',1, 'm', 4, ! Melt ponds area, volume and refrozen lid thickness - !'brine ',1, 'm', 4, ! Volume fraction of ice with dynamic salt - !'qice ',1, 'm', 4, ! Sea ice enthalpy - !'sice ',1, 'm', 4, ! Sea ice salinity - !'qsno ',1, 'm', 4, ! Snow enthalpy - ! Other variables - !'uvel ',1, 'm', 4, ! x-component of sea ice velocity - !'vvel ',1, 'm', 4, ! y-component of sea ice velocity -/ diff --git a/config/bin_3p3z2d/namelist.io b/config/bin_3p3z2d/namelist.io deleted file mode 100644 index 6da21b99b..000000000 --- a/config/bin_3p3z2d/namelist.io +++ /dev/null @@ -1,90 +0,0 @@ -&diag_list -ldiag_solver =.false. -lcurt_stress_surf=.false. -ldiag_curl_vel3 =.false. -ldiag_Ri =.false. -ldiag_turbflux =.false. -ldiag_salt3D =.false. -ldiag_dMOC =.false. -ldiag_DVD =.false. -ldiag_forc =.false. -ldiag_extflds =.false. -/ - -&nml_general -io_listsize =150 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list -vec_autorotate =.false. -/ - -! for sea ice related variables use_ice should be true, otherewise there will be no output -! for 'curl_surf' to work lcurt_stress_surf must be .true. otherwise no output -! for 'fer_C', 'bolus_u', 'bolus_v', 'bolus_w', 'fer_K' to work Fer_GM must be .true. otherwise no output -! 'otracers' - all other tracers if applicable -! for 'dMOC' to work ldiag_dMOC must be .true. otherwise no output -&nml_list -io_list = 'sst ',1, 'm', 4, - 'sss ',1, 'm', 4, - 'ssh ',1, 'm', 4, - 'uice ',1, 'm', 4, - 'vice ',1, 'm', 4, - 'a_ice ',1, 'm', 4, - 'm_ice ',1, 'm', 4, - 'm_snow ',1, 'm', 4, - 'MLD1 ',1, 'm', 4, - 'MLD2 ',1, 'm', 4, - 'MLD3 ',1, 'm', 4, - 'tx_sur ',1, 'm', 4, - 'ty_sur ',1, 'm', 4, - 'temp ',1, 'm', 4, - 'salt ',1, 'm', 8, - 'otracers ',1, 'm', 4, - 'N2 ',1, 'y', 4, - 'Kv ',1, 'y', 4, - 'u ',1, 'm', 4, - 'v ',1, 'm', 4, - 'unod ',1, 'm', 4, - 'vnod ',1, 'm', 4, - 'w ',1, 'm', 4, - 'Av ',1, 'y', 4, - 'bolus_u ',1, 'y', 4, - 'bolus_v ',1, 'y', 4, - 'bolus_w ',1, 'y', 4, - 'dpCO2s ',1, 'm', 4, - 'pCO2s ',1, 'm', 4, - 'CO2f ',1, 'm', 4, - 'Hp ',1, 'm', 4, - 'aFe ',1, 'm', 4, - 'aN ',1, 'm', 4, - 'denb ',1, 'm', 4, - 'benN ',1, 'm', 4, - 'benC ',1, 'm', 4, - 'benSi ',1, 'm', 4, - 'benCalc ',1, 'm', 4, - 'Chldegd ',1, 'm', 4, - 'Chldegn ',1, 'm', 4, - 'Chldegc ',1, 'm', 4, - 'NNAd ',1, 'm', 4, - 'NNAn ',1, 'm', 4, - 'NNAc ',1, 'm', 4, - 'GPPd ',1, 'm', 4, - 'GPPn ',1, 'm', 4, - 'GPPc ',1, 'm', 4, - 'NPPd ',1, 'm', 4, - 'NPPn ',1, 'm', 4, - 'NPPc ',1, 'm', 4, - 'PAR ',1, 'm', 4, - 'respmeso',1, 'm', 4, - 'respmacro',1, 'm', 4, - 'respmicro',1, 'm', 4, - 'calcdiss',1, 'm', 4, - 'calcif',1, 'm', 4, - 'aggn',1, 'm', 4, - 'aggd',1, 'm', 4, - 'aggc',1, 'm', 4, - 'docexn',1, 'm', 4, - 'docexd',1, 'm', 4, - 'docexc',1, 'm', 4, - 'respn',1, 'm', 4, - 'respd',1, 'm', 4, - 'respc',1, 'm', 4, -/ diff --git a/config/bin_3p3z2d/namelist.oce b/config/bin_3p3z2d/namelist.oce deleted file mode 100644 index 7af6867f7..000000000 --- a/config/bin_3p3z2d/namelist.oce +++ /dev/null @@ -1,26 +0,0 @@ -! The namelist file for the finite-volume ocean model - -&oce_dyn -C_d=0.0025 ! Bottom drag, nondimensional -A_ver= 1.e-4 ! Vertical viscosity, m^2/s -scale_area=5.8e9 ! Visc. and diffus. are for an element with scale_area -SPP=.false. ! Salt Plume Parameterization -Fer_GM=.true. ! to swith on/off GM after Ferrari et al. 2010 -K_GM_max = 2000.0 ! max. GM thickness diffusivity (m2/s) -K_GM_min = 2.0 ! max. GM thickness diffusivity (m2/s) -K_GM_bvref = 2 ! def of bvref in ferreira scaling 0=srf,1=bot mld,2=mean over mld,3=weighted mean over mld -K_GM_rampmax = -1.0 ! Resol >K_GM_rampmax[km] GM on -K_GM_rampmin = -1.0 ! Resol 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_transit=.false. +use_ice = .true. ! enable sea ice model +use_cavity = .false. ! enable ice shelf cavities +use_cavity_partial_cell = .false. ! use partial cells in ice shelf cavities (not recommended) +use_floatice = .false. ! enable floating ice (icebergs) +use_sw_pene = .true. ! enable shortwave radiation penetration into ocean +flag_debug = .false. ! enable debug output (verbose logging) +use_transit = .false. ! enable transient tracer module (CFCs, SF6, etc.) / +! ============================================================================ +! PARALLEL DECOMPOSITION (DOMAIN PARTITIONING) +! ============================================================================ &machine -n_levels=2 -n_part= 12, 36 ! 432 number of partitions on each hierarchy level +n_levels = 2 ! number of hierarchy levels for domain decomposition +n_part = 12, 36 ! number of partitions at each level (total CPUs = product of n_part) + ! example: 2 x 128 = 256 MPI tasks + ! adjust based on mesh size and available compute resources + ! maximum scaling reached at ~300 FESOM2 2D nodes per CPU (see first line in nod2d.out for number of 2D nodes) / +! ============================================================================ +! ICEBERG SETTINGS +! ============================================================================ &icebergs -use_icesheet_coupling=.false. -ib_num=1 -use_icebergs=.false. -steps_per_ib_step=8 -ib_async_mode=0 +use_icesheet_coupling = .false. ! enable ice sheet model +ib_num = 1 ! number of iceberg classes +use_icebergs = .false. ! enable iceberg module +steps_per_ib_step = 8 ! ocean time steps per iceberg time step (iceberg subcycling) +ib_async_mode = 0 ! iceberg asynchronous mode (0=synchronous, 1=asynchronous) / diff --git a/config/bin_4p3z2d/namelist.recom b/config/bin_4p3z2d/namelist.recom index 94fb26c67..c003c0060 100644 --- a/config/bin_4p3z2d/namelist.recom +++ b/config/bin_4p3z2d/namelist.recom @@ -1,404 +1,556 @@ -! 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 (meso, macro/krill, micro) +! - 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' / +! ============================================================================ +! GENERAL MODEL CONFIGURATION +! ============================================================================ &parecomsetup -enable_3zoo2det = .true. -enable_coccos = .true. +enable_3zoo2det = .true. ! Enable 3 zooplankton + 2 detritus configuration +enable_coccos = .true. ! Enable coccolithophores +recom_coupled_to_atmosphere = .false. ! REcoM driven by coupled atmosphere +enable_R2OMIP = .false. ! Enable R2OMIP / +! ============================================================================ +! MAIN MODEL SWITCHES AND SETTINGS +! ============================================================================ +! --- Core Model Settings --- &pavariables -use_REcoM =.true. -REcoM_restart =.true. - -bgc_num = 36 !33 !30 !22 !33 !24 !38 -diags3d_num = 31 ! 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 -VPhaeo = 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. -!TIRPS = .false. ! Temperature induced reduction in photosynthesis for phytoplankton -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) -CO2lim = .true. ! CO2 dependence of growth and calcification -Diags = .true. +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. ! Turns dust input of iron off when set to.false. -UseDustClim = .true. -UseDustClimAlbani = .true. ! Use Albani dustclim field (If it is false Mahowald will be used) -use_photodamage = .true. ! use Alvarez et al (2018) for chlorophyll degradation -HetRespFlux_plus = .true. !MB More stable computation of zooplankton respiration fluxes adding a small number to HetN -REcoMDataPath = '/albedo/work/projects/MarESys/ogurses/input/mesh_CORE2_finaltopo_mean/' -restore_alkalinity = .true. -useRivers = .false. -useRivFe = .false. ! When set to true, riverine Fe source is activated -useErosion = .false. -NitrogenSS = .false. ! When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) -useAeolianN = .false. ! When set to true, aeolian nitrogen deposition is activated -firstyearoffesomcycle = 1958 ! The first year of the actual physical forcing (e.g. JRA-55) used -lastyearoffesomcycle = 2024 ! Last year of the actual physical forcing used -numofCO2cycles = 1 ! Number of cycles of the forcing planned -currentCO2cycle = 1 ! Which CO2 cycle we are currently running -DIC_PI = .true. -Nmocsy = 1 ! Length of the vector that is passed to mocsy (always one for recom) -recom_debug =.false. -ciso =.false. ! Main switch to enable/disable carbon isotopes (13|14C) -benthos_num = 4 ! number of benthic BGC tracers -> 8 if (ciso == .true.) otherwise -> 4 -use_MEDUSA = .false. ! Main switch for the sediment model MEDUSA -sedflx_num = 0 ! if 0: no file from MEDUSA is read but default sediment -bottflx_num = 4 ! if ciso&ciso_14: =8; if .not.ciso_14: =6; no ciso: =4 -use_atbox = .false. -add_loopback = .false. ! add loopback fluxes through rivers to the surface -lb_tscale = 1.0 ! /year: fraction of loopback fluxes yearly added to the surface -/ - +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 mesozooplankton nitrogen [mmol N/m³] +cZoo2N = 0.2 ! Initial macrozooplankton 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 -Tmax_phaeo = 16d0 ! [°C] For Blanchard temp fxn: maximum temperature -Topt_phaeo = 6.7982d0 ! [°C] For Blanchard temp fxn: optimum temperature -uopt_phaeo = 0.6903d0 ! [1/day] For Blanchard temp fxn: optimum growth rate -beta_phaeo = 0.7114d0 ! [unitless] For Blanchard temp fxn -ord_d = -0.2216d0 ! diatom ordonnée -expon_d = 0.0406d0 ! diatom exponent -ord_phy = -0.7338d0 ! small phyto ordonnée -expon_phy = 0.06422d0 ! small phyto exponent -ord_cocco = -0.2310d0 ! coccolitho ordonnée -expon_cocco = 0.0327d0 ! coccolitho exponent -ord_phaeo = -0.2310d0 ! phaeocystis ordonnée -expon_phaeo = 0.0327d0 ! phaeocystis exponent -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 -!d1_d = 0.001d0 ! 42°C version -!d2_d = 0.2d0 ! 42°C version -!d1_phy = 0.0016d0 ! 42°C version -!d2_phy = 0.1987d0 ! 42°C version -!d1_cocco = 0.0025d0 ! 42°C version -!d2_cocco = 0.17d0 ! 42°C version +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 -NMinSlope = 50.d0 -SiMinSlope = 1000.d0 -NCmin = 0.04d0 !0.05d0 -NCmin_d = 0.04d0 !0.05d0 -NCmin_c = 0.04d0 ! NEW -NCmin_p = 0.04d0 ! NEW for Phaeocystis -SiCmin = 0.04d0 -k_Fe = 0.04d0 -k_Fe_d = 0.12d0 -k_Fe_c = 0.09d0 ! NEW -k_Fe_p = 0.09d0 ! NEW for Phaeocystis (to be tuned) -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_p = 0.75d0 ! NEW for Phaeocystis (to be tuned) -/ - +! --- 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.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.15d0 !0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] ! NEW value for Phaeocystis -alfa_d = 0.19d0 ! An initial slope of the P-I curve -alfa_c = 0.10d0 ! NEW -alfa_p = 0.17d0 ! NEW for Phaeocystis (to be tuned) -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 +alfa_p = 0.17 ! Phaeocystis initial P-I slope (to be tuned) +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 -V_cm_fact_p = 0.7d0 ! NEW for Phaeocystis -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_p = 0.15d0 ! NEW for Phaeocystis (to be tuned) -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_p = 0.2d0 ! NEW for Phaeocystis -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_p = 0.7d0 ! NEW for Phaeocystis (to be tuned) -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_p = 2.6d0 ! NEW for Phaeocystis -res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant -res_phy_d = 0.01d0 -res_phy_c = 0.01d0 ! NEW -res_phy_p = 0.01d0 ! NEW for phaeocystis -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 +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.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] / +! ============================================================================ +! MESOZOOPLANKTON (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 ! NEW value for Phaeocystis -sDiaNsq = 0.d0 -pzPhy = 0.5d0 !0.04d0 !0.25d0 !1.0d0 ! Maximum nano-phytoplankton preference (NEW: 3/12) ! NEW value for Phaeocystis -sPhyNsq = 0.d0 -pzCocco = 0.666d0 !0.4d0 ! NEW (8/12) ! NEW value for Phaeocystis -sCoccoNsq = 0.d0 ! NEW -pzPhaeo = 0.5d0 ! NEW for Phaeocystis -sPhaeoNsq = 0.d0 ! NEW for Phaeocystis -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 [1/day] +Redfield = 6.625 ! C:N Redfield ratio [mmol C/mmol N] +loss_het = 0.04 ! The quadratic mortality rate (loss to detritus) [m3/(mmolN*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 ! Mesozooplankton grazing preference on microzooplankton +sMicZooNsq = 0.0 ! Mesozooplankton preference slope +/ + +! ============================================================================ +! MACROZOOPLANKTON (SECOND ZOOPLANKTON) +! ============================================================================ &pasecondzooplankton -graz_max2 = 0.25d0 !0.1d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter ! NEW value for Phaeocystis -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.0d0 ! Maximum diatom preference ! NEW value for Phaeocystis -sDiaNsq2 = 0.d0 -pzPhy2 = 0.5d0 !0.07d0 ! Maximum diatom preference ! NEW value for Phaeocystis -sPhyNsq2 = 0.d0 -pzCocco2 = 0.5d0 !0.7d0 ! NEW ! NEW value for Phaeocystis -sCoccoNsq2 = 0.d0 ! NEW -pzPhaeo2 = 0.5d0 ! NEW for Phaeocystis -sPhaeoNsq2 = 0.d0 ! NEW for Phaeocystis -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.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 ! Macrozooplankton N fecal rate [1/day] +fecal_rate_c_mes = 0.32 ! Macrozooplankton 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 ! Preference for grazing on mesozooplankton +sHetNsq = 0.0 ! preference slope +pzMicZoo2 = 1.0 ! Preference for grazing on microzooplankton +sMicZooNsq2 = 0.0 ! 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.36d0 !0.46d0 ! NEW 3Zoo [mmol N/(m3 * day)] Maximum grazing loss parameter ! NEW value for Phaeocystis -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 !0.02d0 ! NEW 3Zoo [1/day] Respiration by heterotrophs and mortality (loss to detritus) ! NEW value for Phaeocystis -pzDia3 = 0.5d0 !0.04d0 ! NEW 3Zoo Maximum diatom preference ! NEW value for Phaeocystis -sDiaNsq3 = 0.d0 ! NEW 3Zoo -pzPhy3 = 1.0d0 !0.07d0 ! NEW 3Zoo Maximum nano-phytoplankton preference ! NEW value for Phaeocystis -sPhyNsq3 = 0.d0 ! NEW 3Zoo -pzCocco3 = 0.5d0 !0.7d0 ! NEW 3Zoo Maximum coccolithophore preference ! ATTENTION: This value needs to be tuned; I start with zero preference! ! NEW value for Phaeocystis -sCoccoNsq3 = 0.d0 ! NEW 3Zoo -pzPhaeo3 = 0.25d0 ! NEW for Phaeocystis -sPhaeoNsq3 = 0.d0 ! NEW for Phaeocystis -/ - +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 -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 (Mesozooplankton) --- +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 (Microzooplankton) --- +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_p = 0.05d0 ! NEW for Phaeocystis +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.10d0 ! [1/day] Phytoplankton loss of carbon -lossC_d = 0.10d0 -lossC_c = 0.10d0 ! NEW -lossC_p = 0.10d0 ! NEW for Phaeocystis +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.15d0 !0.25d0 !0.2d0 ! NEW value for Phaeocystis ! [1/day] -deg_Chl_d = 0.2d0 ! 0.15d0 ! NEW value for Phaeocystis -deg_Chl_c = 0.2d0 ! NEW (has been 0.5) -deg_Chl_p = 0.15d0 ! NEW for Phaeocystis - +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.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_phaeo = 1.162e+00 ! [dimensionless] Phaeocystis -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_phaeo = 4.888e+01 ! [mol/kg] Phaeocystis -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_phaeo = 2.255e-01 ! [kg/mol] Phaeocystis -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_phaeo = 1.023e+07 ! [kg/mol] Phaeocystis -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) + +! --- 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.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.5d0 !0.0d0 -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_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.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 = 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_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/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/config/namelist.oce b/config/namelist.oce index 92d42c294..0720bc9ed 100644 --- a/config/namelist.oce +++ b/config/namelist.oce @@ -18,7 +18,6 @@ C_d = 0.0025 ! bottom drag coefficient (dimensionless, typical: 0.0025) A_ver = 1.e-4 ! background vertical viscosity [m²/s] scale_area = 5.8e9 ! reference element area for viscosity/diffusivity scaling [m²] - ! --- Salt Plume Parameterization --- SPP = .false. ! enable Salt Plume Parameterization (for brine rejection under sea ice) diff --git a/env/albedo/shell b/env/albedo/shell index 004a4e0b2..e3225d145 100644 --- a/env/albedo/shell +++ b/env/albedo/shell @@ -19,3 +19,5 @@ export UCX_HANDLE_ERRORS=bt export HDF5_USE_FILE_LOCKING=FALSE export I_MPI_PMI=pmi2 export I_MPI_PMI_LIBRARY=/usr/lib64/libpmi2.so + +export ENABLE_ALBEDO_INTELMPI_WORKAROUNDS='' diff --git a/config/bin_3p3z2d/namelist.recom b/setups/test_pi_recom/namelist.recom similarity index 89% rename from config/bin_3p3z2d/namelist.recom rename to setups/test_pi_recom/namelist.recom index 36feb2ae9..7d3677575 100644 --- a/config/bin_3p3z2d/namelist.recom +++ b/setups/test_pi_recom/namelist.recom @@ -2,11 +2,11 @@ &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 @@ -16,16 +16,16 @@ enable_coccos = .false. &pavariables use_REcoM =.true. -REcoM_restart =.true. +REcoM_restart =.false. -bgc_num = 33 !24 !38 !22 +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 @@ -37,7 +37,7 @@ O2dep_remin = .true. ! O2remin Add option for O2 dependency of orga use_ballasting = .true. use_density_scaling = .true. use_viscosity_scaling = .true. -OmegaC_diss = .true. ! 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!!!! +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. @@ -46,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 @@ -98,11 +98,11 @@ NCmin_c = 0.04d0 SiCmin = 0.04d0 k_Fe = 0.04d0 k_Fe_d = 0.12d0 -k_Fe_c = 0.09d0 +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 +P_cm_c = 2.8d0 / &palight_calculations @@ -159,7 +159,7 @@ pzDia = 0.5d0 ! Maximum diatom preference sDiaNsq = 0.d0 pzPhy = 0.04d0 ! Maximum small phytoplankton preference sPhyNsq = 0.d0 -pzCocco = 0.4d0 ! Maximum coccolithophore preference +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 @@ -179,7 +179,7 @@ pzDia2 = 1.0d0 ! Maximum diatom preference sDiaNsq2 = 0.d0 pzPhy2 = 0.07d0 ! Maximum small phytoplankton preference sPhyNsq2 = 0.d0 -pzCocco2 = 0.7d0 ! Maximum coccolithophore 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 @@ -196,22 +196,22 @@ graz_max3 = 0.46d0 ! [mmol N/(m3 * day)] Maximum grazing loss p 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 +pzDia3 = 0.04d0 ! Maximum diatom preference sDiaNsq3 = 0.d0 -pzPhy3 = 0.07d0 ! Maximum small phytoplankton preference +pzPhy3 = 0.07d0 ! Maximum small phytoplankton preference sPhyNsq3 = 0.d0 -pzCocco3 = 0.7d0 ! Maximum coccolithophore preference +pzCocco3 = 0.7d0 ! Maximum coccolithophore preference ! will not be used in the 2p3z3d version sCoccoNsq3 = 0.d0 / &pagrazingdetritus -pzDet = 0.5d0 ! Maximum small detritus prefence by first zooplankton +pzDet = 0.5d0 ! Maximum small detritus prefence by first zooplankton sDetNsq = 0.d0 -pzDetZ2 = 0.5d0 ! Maximum large detritus preference by first zooplankton +pzDetZ2 = 0.5d0 ! Maximum large detritus preference by first zooplankton sDetZ2Nsq = 0.d0 -pzDet2 = 0.5d0 ! Maximum small detritus prefence by second zooplankton +pzDet2 = 0.5d0 ! Maximum small detritus prefence by second zooplankton sDetNsq2 = 0.d0 -pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton +pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton sDetZ2Nsq2 = 0.d0 / @@ -241,9 +241,9 @@ lossC_c = 0.10d0 / &paphytoplankton_ChlA -deg_Chl = 0.075 !0.2d0 !0.25d0 ! [1/day] -deg_Chl_d = 0.075 !0.2d0 !0.15d0 -deg_Chl_c = 0.075 !0.2d0 +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 @@ -303,7 +303,7 @@ RiverFeConc = 100 &pacalc calc_prod_ratio = 0.02 -calc_diss_guts = 0.5d0 ! set to zero if OmegaC_diss is set to false +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 ! Value from Aumont et al. 2015, is used with OmegaC_diss flag @@ -338,7 +338,7 @@ 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 ! 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 @@ -358,4 +358,3 @@ atbox_spinup = .false. cosmic_14_init = 2.0 / - diff --git a/config/bin_3p3z2d/namelist.tra b/setups/test_pi_recom/namelist.tra similarity index 89% rename from config/bin_3p3z2d/namelist.tra rename to setups/test_pi_recom/namelist.tra index 33be191e7..c6f24dca8 100644 --- a/config/bin_3p3z2d/namelist.tra +++ b/setups/test_pi_recom/namelist.tra @@ -36,16 +36,16 @@ nml_tracer_list = 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., +!1031, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1032, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1033, 'MFCT', 'QR4C', 'FCT ', 1., 1., !101, 'UPW1', 'UPW1', 'NON ', 0., 0. / &tracer_init3d ! initial conditions for tracers n_ic3d = 8 ! number of tracers to initialize idlist = 1019, 1022, 1018, 1003, 1002, 1001, 2, 1 ! their IDs (0 is temperature, 1 is salinity, etc.). The reading order is defined here! -filelist = 'fe_pisces_opa_eq_init_3D_changed_name.nc', 'woa18_all_o00_01_mmol_fesom2.nc', 'woa13_all_i00_01_fesom2.nc', 'GLODAPv2.2016b.TAlk_fesom2_mmol_fix_z_Fillvalue.nc', 'GLODAPv2.2016b.TCO2_fesom2_mmol_fix_z_Fillvalue.nc', 'woa13_all_n00_01_fesom2.nc', 'phc3.0_winter.nc', 'phc3.0_winter.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist +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 / diff --git a/setups/test_pi_recom/setup.yml b/setups/test_pi_recom/setup.yml index 1304b6c0c..6b9179ed8 100644 --- a/setups/test_pi_recom/setup.yml +++ b/setups/test_pi_recom/setup.yml @@ -92,8 +92,8 @@ namelist.recom: useErosion: False NitrogenSS: False useAeolianN: False - firstyearoffesomcycle: 1948 - lastyearoffesomcycle: 1948 + firstyearoffesomcycle: 1958 + lastyearoffesomcycle: 2024 numofCO2cycles: 1 currentCO2cycle: 1 DIC_PI: True @@ -135,7 +135,11 @@ namelist.io: freq: 1 unit: d prec: 8 - "otracers ": + "DIN ": + freq: 1 + unit: d + prec: 8 + "DIC ": freq: 1 unit: d prec: 8 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5747616b9..c5ecc4949 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,12 @@ else() set(FESOM_PLATFORM_STRATEGY "notset" CACHE STRING "switch to platform specific compile settings, this is usually determined via the env.sh script") endif() +if(DEFINED ENV{ENABLE_ALBEDO_INTELMPI_WORKAROUNDS}) # be able to set the initial cache value from our env settings for albedo, not only via cmake command + option(ALBEDO_INTELMPI_WORKAROUNDS "workaround for performance issues on albedo" ON) +else() + option(ALBEDO_INTELMPI_WORKAROUNDS "workaround for performance issues on albedo" OFF) +endif() + # Cray compiler specific optimizations if(CMAKE_Fortran_COMPILER_ID STREQUAL "Cray") # Make sure to also set these variables in the runtime environment: @@ -38,6 +44,11 @@ if(DEFINED DISABLE_MULTITHREADING) endif() #TODO: these machine specific block can easyly go in cmake toolchain. +if(ALBEDO_INTELMPI_WORKAROUNDS) + add_compile_options(-DENABLE_ALBEDO_INTELMPI_WORKAROUNDS) + #SH add_compile_options(-DDISABLE_PARALLEL_RESTART_READ) +endif() + if (${FESOM_PLATFORM_STRATEGY} STREQUAL levante.dkrz.de ) option(ASYNCHRONOUS_IO_THREADS "enable asynchronous I/O threads" OFF) elseif(${FESOM_PLATFORM_STRATEGY} STREQUAL leo-dcgp ) diff --git a/src/MOD_TRACER.F90 b/src/MOD_TRACER.F90 index 0fd08466b..0d0d6a913 100644 --- a/src/MOD_TRACER.F90 +++ b/src/MOD_TRACER.F90 @@ -22,7 +22,7 @@ MODULE MOD_TRACER integer :: ID !___________________________________________________________________________ ! TODO: Make it as a part of namelist.tra -logical :: ltra_diag = .true. +logical :: ltra_diag = .true. ! OG - tra_diag contains procedure WRITE_T_TRACER_DATA @@ -44,13 +44,14 @@ 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 +! 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 diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 802feb95f..5ff859d34 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -199,7 +199,7 @@ subroutine fesom_init(fesom_total_nsteps) f%npes =>f%partit%npes - + if(f%mype==0) then call plot_fesomlogo() write(*,*) @@ -222,10 +222,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 5b0f69bcc..fbebeb6d4 100644 --- a/src/gen_forcing_init.F90 +++ b/src/gen_forcing_init.F90 @@ -143,6 +143,7 @@ subroutine forcing_array_setup(partit, mesh) runoff=0.0_WP evaporation = 0.0_WP ice_sublimation = 0.0_WP + #if defined (__oasis) || defined (__ifsinterface) || defined (__yac) allocate(sublimation(n2), evap_no_ifrac(n2)) sublimation=0.0_WP diff --git a/src/gen_ic3d.F90 b/src/gen_ic3d.F90 index 445928bed..e9566cbbd 100644 --- a/src/gen_ic3d.F90 +++ b/src/gen_ic3d.F90 @@ -20,8 +20,10 @@ MODULE g_ic3d USE g_comm_auto USE g_support USE g_config, only: dummy, ClimateDataPath, use_cavity +#if defined(__recom) + use recom_config, only: enable_3zoo2det, enable_coccos +#endif USE g_clock, only: r_restart - IMPLICIT NONE include 'netcdf.inc' @@ -257,7 +259,7 @@ SUBROUTINE nc_ic3d_ini(partit, mesh) call nc_readGrid(partit) - ! prepare nearest coordinates in INfile , save to bilin_indx_i/j + ! prepare nearest coordinates in INfile, save to bilin_indx_i/j !_________________________________________________________________________ ! cavity case if (use_cavity) then @@ -531,6 +533,7 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) real(kind=WP) :: locDINmax, locDINmin, locDICmax, locDICmin, locAlkmax !OG real(kind=WP) :: locAlkmin, locDSimax, locDSimin, locDFemax, locDFemin real(kind=WP) :: locO2min, locO2max + real(kind=WP) :: locDICremax, locDICremin ! DICremin tracer (added by Sina) if (partit%mype==0) write(*,*) "Start: Initial conditions for tracers" @@ -606,6 +609,8 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) locDFemin = locDINmin locO2max = locDINmax locO2min = locDINmin + locDICremax = locDINmax ! DICremin tracer (added by Sina) + locDICremin = locDINmin #endif do n=1, partit%myDim_nod2d locTmax = max(locTmax,maxval(tracers%data(1)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) @@ -626,6 +631,20 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) locDFemin = min(locDFemin,minval(tracers%data(21)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) locO2max = max(locO2max,maxval(tracers%data(24)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) locO2min = min(locO2min,minval(tracers%data(24)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + ! DICremin tracer (added by Sina) + if (enable_3zoo2det .and. enable_coccos) then + locDICremax = max(locDICremax,maxval(tracers%data(39)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDICremin = min(locDICremin,minval(tracers%data(39)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + else if (enable_coccos .and. .not. enable_3zoo2det) then + locDICremax = max(locDICremax,maxval(tracers%data(31)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDICremin = min(locDICremin,minval(tracers%data(31)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + else if (enable_3zoo2det .and. .not. enable_coccos) then + locDICremax = max(locDICremax,maxval(tracers%data(33)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDICremin = min(locDICremin,minval(tracers%data(33)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + else + locDICremax = max(locDICremax,maxval(tracers%data(25)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDICremin = min(locDICremin,minval(tracers%data(25)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + end if #endif end do call MPI_AllREDUCE(locTmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, partit%MPI_COMM_FESOM, partit%MPIerr) @@ -664,6 +683,11 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) if (partit%mype==0) write(*,*) ' |-> gobal max init. O2. =', glo call MPI_AllREDUCE(locO2min , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, partit%MPI_COMM_FESOM, partit%MPIerr) if (partit%mype==0) write(*,*) ' `-> gobal min init. O2. =', glo + call MPI_AllREDUCE(locDICremax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, partit%MPI_COMM_FESOM, partit%MPIerr) + if (partit%mype==0) write(*,*) ' |-> gobal max init. DICremin. =', glo + call MPI_AllREDUCE(locDICremin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, partit%MPI_COMM_FESOM, partit%MPIerr) + if (partit%mype==0) write(*,*) ' |-> gobal min init. DICremin. =', glo + #endif ! Apply perturbations based on selected mode diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index b40a0d204..387e5b1f9 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -185,9 +185,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_modules_config.F90 b/src/gen_modules_config.F90 index ecc17effa..aeb795f25 100755 --- a/src/gen_modules_config.F90 +++ b/src/gen_modules_config.F90 @@ -120,8 +120,17 @@ module g_config !_____________________________________________________________________________ ! *** configuration*** logical :: use_sw_pene=.true. - logical :: use_ice=.false. + logical :: use_ice=.false. ! to be supplied + ! *** REcoM coupled to the atmosphere *** + ! True when REcoM is driven by atmospheric forcing produced by a coupled + ! atmosphere model: switches SBC input filenames to the daily + ! '01_reduced.nc' pattern and triggers daily (rather than monthly) + ! refresh of SSS restoring and river runoff in gen_surface_forcing. Read + ! from &parecomsetup in namelist.recom; default .false. keeps standard + ! yearly-file forcing. + logical :: recom_coupled_to_atmosphere = .false. + ! *** icebergs *** logical :: use_icebergs=.false. logical :: turn_off_hf=.false. diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index 99d672fbb..aa42a995a 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -33,7 +33,6 @@ MODULE g_sbf !! sbc_ini -- initialization atmpospheric forcing !! sbc_do -- provide a sbc (surface boundary conditions) each time step !! - USE iso_fortran_env, only: error_unit USE MOD_MESH USE MOD_PARTIT USE MOD_PARSUP @@ -415,17 +414,17 @@ SUBROUTINE nc_readTimeGrid(flf, partit) (trim(flf%calendar).eq.'noleap') .or. & (trim(flf%calendar).eq.'365_days')) then if (include_fleapyear .eqv. .true.) then - write(error_unit,*) achar(27)//'[33m' - write(error_unit,*) '____________________________________________________________' - write(error_unit,*) ' WARNING: It looks like you want to use CORE forcing, Right?' - write(error_unit,*) ' but setted include_fleapyear=.true.. CORE forcing ' - write(error_unit,*) ' does not contain any leap years or particular ' - write(error_unit,*) ' calender option (julian, gregorian). So if im right,' - write(error_unit,*) ' please go to namelist.config and set ' - write(error_unit,*) ' include_fleapyear=.false. otherwise comment this ' - write(error_unit,*) ' message block in gen_surface_forcing.F90.' - write(error_unit,*) '____________________________________________________________' - write(error_unit,*) achar(27)//'[0m' + print *, achar(27)//'[33m' + write(*,*) '____________________________________________________________' + write(*,*) ' WARNING: It looks like you want to use CORE forcing, Right?' + write(*,*) ' but setted include_fleapyear=.true.. CORE forcing ' + write(*,*) ' does not contain any leap years or particular ' + write(*,*) ' calender option (julian, gregorian). So if im right,' + write(*,*) ' please go to namelist.config and set ' + write(*,*) ' include_fleapyear=.false. otherwise comment this ' + write(*,*) ' message block in gen_surface_forcing.F90.' + write(*,*) '____________________________________________________________' + print *, achar(27)//'[0m' call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) end if elseif ((trim(flf%calendar).eq.'julian') .or. & @@ -433,39 +432,39 @@ SUBROUTINE nc_readTimeGrid(flf, partit) (trim(flf%calendar).eq.'proleptic_gregorian') .or. & (trim(flf%calendar).eq.'standard')) then if (include_fleapyear .eqv. .false.) then - write(error_unit,*) achar(27)//'[33m' - write(error_unit,*) '____________________________________________________________' - write(error_unit,*) ' WARNING: It looks like you want to use either JRA55, ERA,' - write(error_unit,*) ' NCEP or a similar forcing, Right?, but setted ' - write(error_unit,*) ' include_fleapyear=.false. JRA55, ERA or NCEP contain' - write(error_unit,*) ' all fleapyears and use a specific calendar option ' - write(error_unit,*) ' (julian, gregorian). So that the calendars in FESOM2.0' - write(error_unit,*) ' work properly, when using these forcings ' - write(error_unit,*) ' include_fleapyear must be true. So if im right, please go' - write(error_unit,*) ' to namelist.config and set include_fleapyear=.true. ' - write(error_unit,*) ' otherwise comment this message block in' - write(error_unit,*) ' gen_surface_forcing.F90' - write(error_unit,*) '____________________________________________________________' - write(error_unit,*) achar(27)//'[0m' + print *, achar(27)//'[33m' + write(*,*) '____________________________________________________________' + write(*,*) ' WARNING: It looks like you want to use either JRA55, ERA,' + write(*,*) ' NCEP or a similar forcing, Right?, but setted ' + write(*,*) ' include_fleapyear=.false. JRA55, ERA or NCEP contain' + write(*,*) ' all fleapyears and use a specific calendar option ' + write(*,*) ' (julian, gregorian). So that the calendars in FESOM2.0' + write(*,*) ' work properly, when using these forcings ' + write(*,*) ' include_fleapyear must be true. So if im right, please go' + write(*,*) ' to namelist.config and set include_fleapyear=.true. ' + write(*,*) ' otherwise comment this message block in' + write(*,*) ' gen_surface_forcing.F90' + write(*,*) '____________________________________________________________' + print *, achar(27)//'[0m' call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) end if else - write(error_unit,*) achar(27)//'[31m' - write(error_unit,*) '____________________________________________________________' - write(error_unit,*) ' ERROR: I am not familiar with the found calendar option,' - write(error_unit,*) ' dont know what to do. Either talk to the FESOM2 developers' - write(error_unit,*) ' or add the calendar option by your self in ...' - write(error_unit,*) ' gen_surface_forcing.F90, line:364-367' - write(error_unit,*) ' ' - write(error_unit,*) ' elseif ((trim(flf%calendar).eq."julian") .or. &' - write(error_unit,*) ' (trim(flf%calendar).eq."gregorian") .or. &' - write(error_unit,*) ' (trim(flf%calendar).eq."NEW_CALENDAR").or. &' - write(error_unit,*) ' (trim(flf%calendar).eq."standard")) then ' - write(error_unit,*) ' ' - write(error_unit,*) ' The time axis calendar attribute can be checked for ' - write(error_unit,*) ' example with ncdump -h forcing_file.nc ' - write(error_unit,*) '____________________________________________________________' - write(error_unit,*) achar(27)//'[0m' + print *, achar(27)//'[31m' + write(*,*) '____________________________________________________________' + write(*,*) ' ERROR: I am not familiar with the found calendar option,' + write(*,*) ' dont know what to do. Either talk to the FESOM2 developers' + write(*,*) ' or add the calendar option by your self in ...' + write(*,*) ' gen_surface_forcing.F90, line:364-367' + write(*,*) ' ' + write(*,*) ' elseif ((trim(flf%calendar).eq."julian") .or. &' + write(*,*) ' (trim(flf%calendar).eq."gregorian") .or. &' + write(*,*) ' (trim(flf%calendar).eq."NEW_CALENDAR").or. &' + write(*,*) ' (trim(flf%calendar).eq."standard")) then ' + write(*,*) ' ' + write(*,*) ' The time axis calendar attribute can be checked for ' + write(*,*) ' example with ncdump -h forcing_file.nc ' + write(*,*) '____________________________________________________________' + print *, achar(27)//'[0m' call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) end if ! --> if ((trim(flf%calendar).eq.'none') .or. & ... end if !--> if (partit%mype==0 .and. use_flpyrcheck) then @@ -548,6 +547,7 @@ SUBROUTINE nc_sbc_ini_fillnames(yyyy) !! ** Purpose : Fill names of sbc_flfi array (file names and variable names) !prepare proper nc file (add year and .nc to the end of the file name from namelist +if (.NOT. recom_coupled_to_atmosphere) then if (l_xwind) write(sbc_flfi(i_xwind)%file_name, *) trim(make_full_path(nm_xwind_file)),trim(yyear),'.nc' if (l_ywind) write(sbc_flfi(i_ywind)%file_name, *) trim(make_full_path(nm_ywind_file)),trim(yyear),'.nc' if (l_xstre) write(sbc_flfi(i_xstre)%file_name, *) trim(make_full_path(nm_xstre_file)),trim(yyear),'.nc' @@ -560,7 +560,21 @@ SUBROUTINE nc_sbc_ini_fillnames(yyyy) if (l_snow) write(sbc_flfi(i_snow)%file_name, *) trim(make_full_path(nm_snow_file)), trim(yyear),'.nc' if (l_mslp) write(sbc_flfi(i_mslp)%file_name, *) trim(make_full_path(nm_mslp_file)), trim(yyear),'.nc' if (l_cloud) write(sbc_flfi(i_cloud)%file_name, *) trim(make_full_path(nm_cloud_file)),trim(yyear),'.nc' - +else + ! AWICM forcing + if (l_xwind) write(sbc_flfi(i_xwind)%file_name, *) trim(make_full_path(nm_xwind_file)),trim(yyear),'01_reduced.nc' + if (l_ywind) write(sbc_flfi(i_ywind)%file_name, *) trim(make_full_path(nm_ywind_file)),trim(yyear),'01_reduced.nc' + if (l_xstre) write(sbc_flfi(i_xstre)%file_name, *) trim(make_full_path(nm_xstre_file)),trim(yyear),'01_reduced.nc' + if (l_ystre) write(sbc_flfi(i_ystre)%file_name, *) trim(make_full_path(nm_ystre_file)),trim(yyear),'01_reduced.nc' + if (l_humi) write(sbc_flfi(i_humi)%file_name, *) trim(make_full_path(nm_humi_file)), trim(yyear),'01_reduced.nc' + if (l_qsr) write(sbc_flfi(i_qsr)%file_name, *) trim(make_full_path(nm_qsr_file)), trim(yyear),'01_reduced.nc' + if (l_qlw) write(sbc_flfi(i_qlw)%file_name, *) trim(make_full_path(nm_qlw_file)), trim(yyear),'01_reduced.nc' + if (l_tair) write(sbc_flfi(i_tair)%file_name, *) trim(make_full_path(nm_tair_file)), trim(yyear),'01_reduced.nc' + if (l_prec) write(sbc_flfi(i_prec)%file_name, *) trim(make_full_path(nm_prec_file)), trim(yyear),'01_reduced.nc' + if (l_snow) write(sbc_flfi(i_snow)%file_name, *) trim(make_full_path(nm_snow_file)), trim(yyear),'01_reduced.nc' + if (l_mslp) write(sbc_flfi(i_mslp)%file_name, *) trim(make_full_path(nm_mslp_file)), trim(yyear),'01_reduced.nc' + if (l_cloud) write(sbc_flfi(i_cloud)%file_name, *) trim(make_full_path(nm_cloud_file)), trim(yyear),'01_reduced.nc' +endif if (l_xwind) sbc_flfi(i_xwind)%file_name=ADJUSTL(trim(sbc_flfi(i_xwind)%file_name)) if (l_ywind) sbc_flfi(i_ywind)%file_name=ADJUSTL(trim(sbc_flfi(i_ywind)%file_name)) if (l_xstre) sbc_flfi(i_xstre)%file_name=ADJUSTL(trim(sbc_flfi(i_xstre)%file_name)) @@ -827,20 +841,18 @@ SUBROUTINE getcoeffld(fld_idx, rdate, partit, mesh) t_indx_p1 = t_indx delta_t = 1.0_wp if (mype==0) then - write(error_unit,*) 'WARNING: no temporal extrapolation into future (nearest neighbour is used): ', trim(var_name), ' !' - write(error_unit,*) trim(file_name) - write(error_unit,*) nc_time(1), nc_time(nc_Ntime), now_date - flush(error_unit) + write(*,*) 'WARNING: no temporal extrapolation into future (nearest neighbour is used): ', trim(var_name), ' !' + write(*,*) trim(file_name) + write(*,*) nc_time(1), nc_time(nc_Ntime), now_date end if elseif (t_indx < 1) then ! NO extrapolation back in time t_indx = 1 t_indx_p1 = t_indx delta_t = 1.0_wp if (mype==0) then - write(error_unit,*) 'WARNING: no temporal extrapolation back in time (nearest neighbour is used): ', trim(var_name), ' !' - write(error_unit,*) trim(file_name) - write(error_unit,*) nc_time(1), nc_time(nc_Ntime), now_date - flush(error_unit) + write(*,*) 'WARNING: no temporal extrapolation back in time (nearest neighbour is used): ', trim(var_name), ' !' + write(*,*) trim(file_name) + write(*,*) nc_time(1), nc_time(nc_Ntime), now_date end if end if @@ -1066,7 +1078,7 @@ SUBROUTINE sbc_ini(partit, mesh) if (iost == 0) then if (mype==0) WRITE(*,*) ' file : ', 'namelist.forcing',' open ok' else - if (mype==0) WRITE(error_unit,*) 'ERROR: --> bad opening file : ', 'namelist.forcing',' ; iostat=',iost + if (mype==0) WRITE(*,*) 'ERROR: --> bad opening file : ', 'namelist.forcing',' ; iostat=',iost call par_ex(partit%MPI_COMM_FESOM, partit%mype, 1) endif READ( nm_sbc_unit, nml=nam_sbc, iostat=iost ) @@ -1224,38 +1236,38 @@ SUBROUTINE sbc_ini(partit, mesh) inquire(file=make_full_path(nm_sss_data_file), exist=file_exist) if ( .not. file_exist) then if (mype==0) then - write(error_unit,*) - write(error_unit,*) achar(27)//'[33m' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) ' ERROR: file not found: ', trim(make_full_path(nm_sss_data_file)) - write(error_unit,*) ' --> check your namelist.focing' - write(error_unit,*) ' ...' - write(error_unit,*) ' nm_sss_data_file =...' - write(error_unit,*) ' ...' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) achar(27)//'[0m' - write(error_unit,*) + write(*,*) + print *, achar(27)//'[33m' + write(*,*) '____________________________________________________________________' + write(*,*) ' ERROR: file not found: ', trim(make_full_path(nm_sss_data_file)) + write(*,*) ' --> check your namelist.focing' + write(*,*) ' ...' + write(*,*) ' nm_sss_data_file =...' + write(*,*) ' ...' + write(*,*) '____________________________________________________________________' + print *, achar(27)//'[0m' + write(*,*) end if call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) end if else if (mype==0) then - write(error_unit,*) - write(error_unit,*) achar(27)//'[33m' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) ' ERROR: you choose an unknown sss_data_source ! ' - write(error_unit,*) ' currently supported is only sss_data_soure=:' - write(error_unit,*) ' - ''CORE1'' or ''CORE2'': for monthly SSS climatology' - write(error_unit,*) '' - write(error_unit,*) ' --> please check your namelist.forcing' - write(error_unit,*) ' ...' - write(error_unit,*) ' sss_data_source=...' - write(error_unit,*) ' nm_sss_file =...' - write(error_unit,*) ' ...' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) achar(27)//'[0m' - write(error_unit,*) + write(*,*) + print *, achar(27)//'[33m' + write(*,*) '____________________________________________________________________' + write(*,*) ' ERROR: you choose an unknown sss_data_source ! ' + write(*,*) ' currently supported is only sss_data_soure=:' + write(*,*) ' - ''CORE1'' or ''CORE2'': for monthly SSS climatology' + write(*,*) '' + write(*,*) ' --> please check your namelist.forcing' + write(*,*) ' ...' + write(*,*) ' sss_data_source=...' + write(*,*) ' nm_sss_file =...' + write(*,*) ' ...' + write(*,*) '____________________________________________________________________' + print *, achar(27)//'[0m' + write(*,*) end if call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) @@ -1274,7 +1286,6 @@ SUBROUTINE sbc_ini(partit, mesh) write(*,*) ' nm_runoff_file = ', trim(make_full_path(nm_runoff_file)) write(*,*) end if - ! runoff in CORE is constant in time ! Warning: For a global mesh, conservative scheme is to be updated!! file_exist=.false. @@ -1285,22 +1296,22 @@ SUBROUTINE sbc_ini(partit, mesh) else if (mype==0) then - write(error_unit,*) - write(error_unit,*) achar(27)//'[31m' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) ' ERROR: file not found: ', trim(make_full_path(nm_runoff_file)) - write(error_unit,*) ' --> check your namelist.focing' - write(error_unit,*) ' ...' - write(error_unit,*) ' nm_runoff_file =...' - write(error_unit,*) ' ...' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) achar(27)//'[0m' - write(error_unit,*) + write(*,*) + print *, achar(27)//'[31m' + write(*,*) '____________________________________________________________________' + write(*,*) ' ERROR: file not found: ', trim(make_full_path(nm_runoff_file)) + write(*,*) ' --> check your namelist.focing' + write(*,*) ' ...' + write(*,*) ' nm_runoff_file =...' + write(*,*) ' ...' + write(*,*) '____________________________________________________________________' + print *, achar(27)//'[0m' + write(*,*) end if call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) - + end if - + elseif (runoff_data_source=='Dai09' .or. runoff_data_source=='JRA55') then if (mype==0) then write(*,*) ' --> using monthly runoff climatology (12 time slices) ' @@ -1317,46 +1328,46 @@ SUBROUTINE sbc_ini(partit, mesh) inquire(file=make_full_path(nm_runoff_file), exist=file_exist) if ( .not. file_exist .and. runoff_climatology) then if (mype==0) then - write(error_unit,*) - write(error_unit,*) achar(27)//'[31m' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) ' ERROR: file not found: ', trim(make_full_path(nm_runoff_file)) - write(error_unit,*) ' --> check your namelist.focing' - write(error_unit,*) ' ...' - write(error_unit,*) ' nm_runoff_file =...' - write(error_unit,*) ' ...' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) achar(27)//'[0m' - write(error_unit,*) + write(*,*) + print *, achar(27)//'[31m' + write(*,*) '____________________________________________________________________' + write(*,*) ' ERROR: file not found: ', trim(make_full_path(nm_runoff_file)) + write(*,*) ' --> check your namelist.focing' + write(*,*) ' ...' + write(*,*) ' nm_runoff_file =...' + write(*,*) ' ...' + write(*,*) '____________________________________________________________________' + print *, achar(27)//'[0m' + write(*,*) end if call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) - + end if - + else if (mype==0) then - write(error_unit,*) - write(error_unit,*) achar(27)//'[31m' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) ' ERROR: you choose an unknown runoff_data_source ! ' - write(error_unit,*) ' supported is only runoff_data_soure=:' - write(error_unit,*) ' - ''CORE1'' or ''CORE2'': for longterm climatology (only one timeslice for the entire simulation) ' - write(error_unit,*) ' - ''JRA55'' or ''Dai09'': for monthly climatology (each month has a different runoff timeslice, ' - write(error_unit,*) ' this can be done as a monthly climatology (runoff_climatology=.true.) or ' - write(error_unit,*) ' as a transient monthly climatology (runoff_climatology=.false.) than each' - write(error_unit,*) ' month and each year have differnt runoff' - write(error_unit,*) '' - write(error_unit,*) ' --> please check your namelist.forcing' - write(error_unit,*) ' ...' - write(error_unit,*) ' runoff_data_source=...' - write(error_unit,*) ' nm_runoff_file =...' - write(error_unit,*) ' ...' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) achar(27)//'[0m' - write(error_unit,*) + write(*,*) + print *, achar(27)//'[31m' + write(*,*) '____________________________________________________________________' + write(*,*) ' ERROR: you choose an unknown runoff_data_source ! ' + write(*,*) ' supported is only runoff_data_soure=:' + write(*,*) ' - ''CORE1'' or ''CORE2'': for longterm climatology (only one timeslice for the entire simulation) ' + write(*,*) ' - ''JRA55'' or ''Dai09'': for monthly climatology (each month has a different runoff timeslice, ' + write(*,*) ' this can be done as a monthly climatology (runoff_climatology=.true.) or ' + write(*,*) ' as a transient monthly climatology (runoff_climatology=.false.) than each' + write(*,*) ' month and each year have differnt runoff' + write(*,*) '' + write(*,*) ' --> please check your namelist.forcing' + write(*,*) ' ...' + write(*,*) ' runoff_data_source=...' + write(*,*) ' nm_runoff_file =...' + write(*,*) ' ...' + write(*,*) '____________________________________________________________________' + print *, achar(27)//'[0m' + write(*,*) end if call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) - + end if !___________________________________________________________________________ @@ -1376,51 +1387,50 @@ SUBROUTINE sbc_ini(partit, mesh) end if else if (mype==0) then - write(error_unit,*) - write(error_unit,*) achar(27)//'[31m' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) ' ERROR: file not found: ', make_full_path(nm_chl_data_file) - write(error_unit,*) ' --> check your namelist.focing' - write(error_unit,*) ' ...' - write(error_unit,*) ' chl_data_source =...' - write(error_unit,*) ' nm_chl_data_file =...' - write(error_unit,*) ' ...' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) achar(27)//'[0m' - write(error_unit,*) + write(*,*) + print *, achar(27)//'[31m' + write(*,*) '____________________________________________________________________' + write(*,*) ' ERROR: file not found: ', make_full_path(nm_chl_data_file) + write(*,*) ' --> check your namelist.focing' + write(*,*) ' ...' + write(*,*) ' chl_data_source =...' + write(*,*) ' nm_chl_data_file =...' + write(*,*) ' ...' + write(*,*) '____________________________________________________________________' + print *, achar(27)//'[0m' + write(*,*) end if call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) end if elseif (chl_data_source == 'Const.' .or. chl_data_source == 'None') then if (mype==0) then - write(error_unit,*) achar(27)//'[33m' - write(error_unit,*) ' --> you will use short-wave penetration with constant chlorophyll concentration: ', chl_const - write(error_unit,*) ' Are you sure about this??? Usually the shortwave penetration will run better with Sweeney' - write(error_unit,*) ' heterogenous chlorophyl climatology. So set chl_data_source=''Sweeney'' and nm_chl_data_file=... ' - write(error_unit,*) ' chl_data_source =', trim(chl_data_source) - write(error_unit,*) achar(27)//'[0m' - flush(error_unit) + print *, achar(27)//'[33m' + write(*,*) ' --> you will use short-wave penetration with constant chlorophyll concentration: ', chl_const + write(*,*) ' Are you sure about this??? Usually the shortwave penetration will run better with Sweeney' + write(*,*) ' heterogenous chlorophyl climatology. So set chl_data_source=''Sweeney'' and nm_chl_data_file=... ' + write(*,*) ' chl_data_source =', trim(chl_data_source) + print *, achar(27)//'[0m' end if chl=chl_const else if (mype==0) then - write(error_unit,*) - write(error_unit,*) achar(27)//'[31m' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) ' ERROR: you choose an unknown chl_data_source ! ' - write(error_unit,*) ' supported is only chl_data_source=:' - write(error_unit,*) ' - ''Sweeney'' : use Sweeney chlorophyl climatology' - write(error_unit,*) ' - ''Const.'' or ''None'' : use constant chlorophyl value of chl_const=',chl_const - write(error_unit,*) '' - write(error_unit,*) ' --> please check your namelist.forcing' - write(error_unit,*) ' ...' - write(error_unit,*) ' chl_data_source=...' - write(error_unit,*) ' ...' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) achar(27)//'[0m' - write(error_unit,*) + write(*,*) + print *, achar(27)//'[31m' + write(*,*) '____________________________________________________________________' + write(*,*) ' ERROR: you choose an unknown chl_data_source ! ' + write(*,*) ' supported is only chl_data_source=:' + write(*,*) ' - ''Sweeney'' : use Sweeney chlorophyl climatology' + write(*,*) ' - ''Const.'' or ''None'' : use constant chlorophyl value of chl_const=',chl_const + write(*,*) '' + write(*,*) ' --> please check your namelist.forcing' + write(*,*) ' ...' + write(*,*) ' chl_data_source=...' + write(*,*) ' ...' + write(*,*) '____________________________________________________________________' + print *, achar(27)//'[0m' + write(*,*) end if call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) @@ -1434,13 +1444,18 @@ SUBROUTINE sbc_ini(partit, mesh) #if defined(__recom) ! OPEN and read namelist for SBC REcoM open( unit=nm_sbc_unit+1, file='namelist.recom', form='formatted', access='sequential', status='old', iostat=iost ) - if (iost == 0) then - if (mype==0) WRITE(*,*) ' file : ', 'namelist.recom for sbc',' open ok' - else - if (mype==0) WRITE(error_unit,*) 'ERROR: --> bad opening file : ', 'namelist.recom for sbc',' ; iostat=',iost + !if (iost == 0) then + ! if (mype==0) WRITE(*,*) ' file : ', 'namelist.recom for sbc',' open ok' + !else + ! if (mype==0) WRITE(*,*) 'ERROR: --> bad opening file : ', 'namelist.recom for sbc',' ; iostat=',iost + call log_recom_namelist_open(mype, iost) + if (iost /= 0) then call par_ex(partit%MPI_COMM_FESOM, partit%mype) stop endif + + + READ( nm_sbc_unit+1, nml=nam_rsbc, iostat=iost ) close( nm_sbc_unit+1 ) #endif @@ -1468,6 +1483,7 @@ SUBROUTINE sbc_do(partit, mesh) real(wp) :: rdate ! date integer :: fld_idx, i logical :: do_rotation_wind, do_rotation_stre, force_newcoeff, update_monthly_flag + logical :: update_daily_flag = .false. ! true when recom_coupled_to_atmosphere integer :: yyyy, dd, mm, flag_flpyr=0 integer, pointer :: nc_Ntime, t_indx, t_indx_p1 real(wp), pointer :: nc_time(:) @@ -1478,13 +1494,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 - character(300) :: sedfilename - logical :: do_read=.false. - integer :: n_lb - integer, dimension(2) :: istart, icount - real(kind=8) :: total_runoff + 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 @@ -1575,7 +1587,10 @@ SUBROUTINE sbc_do(partit, mesh) !=========================================================================== ! prepare a flag which checks whether to update monthly data (SSS, river runoff) - update_monthly_flag=( (day_in_month==num_day_in_month(fleapyear,month) .AND. timenew==86400._WP) .OR. mstep==1 ) + update_monthly_flag=( (day_in_month==num_day_in_month(fleapyear,month) .AND. timenew==86400._WP) .OR. mstep==1) + if (recom_coupled_to_atmosphere) then + update_daily_flag = ( (timenew==86400._WP) .OR. mstep==1) + endif !___________________________________________________________________________ ! read in SSS for applying SSS restoring @@ -1604,7 +1619,7 @@ SUBROUTINE sbc_do(partit, mesh) end if end if end if - + !___________________________________________________________________________ ! runoff --> depends on simulated month if(runoff_data_source=='Dai09' .or. runoff_data_source=='JRA55') then @@ -1638,18 +1653,18 @@ SUBROUTINE sbc_do(partit, mesh) inquire(file=filename, exist=file_exist) if (.not. file_exist) then if (mype==0) then - write(error_unit,*) - write(error_unit,*) achar(27)//'[31m' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) ' ERROR: file not found: ',trim(filename) - write(error_unit,*) ' --> check your namelist.focing' - write(error_unit,*) ' ...' - write(error_unit,*) ' nm_runoff_file =...' - write(error_unit,*) ' ...' - write(error_unit,*) '____________________________________________________________________' - write(error_unit,*) achar(27)//'[0m' - write(error_unit,*) - end if + write(*,*) + print *, achar(27)//'[31m' + write(*,*) '____________________________________________________________________' + write(*,*) ' ERROR: file not found: ',trim(filename) + write(*,*) ' --> check your namelist.focing' + write(*,*) ' ...' + write(*,*) ' nm_runoff_file =...' + write(*,*) ' ...' + write(*,*) '____________________________________________________________________' + print *, achar(27)//'[0m' + write(*,*) + end if call par_ex(partit%MPI_COMM_FESOM, partit%mype, 0) end if @@ -1658,460 +1673,442 @@ SUBROUTINE sbc_do(partit, mesh) call read_2ddata_on_grid_NetCDF(filename,'runoff', i, runoff, partit, mesh) !kg/m2/s -> m/s runoff=runoff/1000.0_WP - + end if ! --> if(update_monthly_flag) then end if ! --> if(runoff_data_source=='Dai09' .or. ... + !river runoff AWICM + if(runoff_data_source == 'AWICM') then + if(update_daily_flag) then + !daily data already in m/s + i = daynew + filename=trim(make_full_path(nm_runoff_file))//cyearnew//'0101_redistributed.nc' + call read_2ddata_on_grid_NetCDF(filename,'runoff', i, runoff, partit, mesh) + end if + end if + #if defined (__recom) -!< read surface atmospheric deposition for Fe, N, CO2 -if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Atm_input'//achar(27)//'[0m' - -! ******** 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 (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) - totnumyear = lastyearoffesomcycle-firstyearoffesomcycle+1 - firstyearofcurrentCO2cycle = lastyearoffesomcycle-numofCO2cycles*totnumyear+(currentCO2cycle-1)*totnumyear - - currentCO2year = firstyearofcurrentCO2cycle + (yearnew-firstyearoffesomcycle)+1 - if(mype==0) write(*,*),currentCO2year, firstyearofcurrentCO2cycle, yearnew, firstyearoffesomcycle - write(currentCO2year_char,'(i4)') currentCO2year - CO2vari = 'AtmCO2_'//currentCO2year_char - - ! open file - status=nf90_open(filename, nf90_nowrite, ncid) - if (status.ne.nf90_noerr)then - write(error_unit,*) 'ERROR: CANNOT READ CO2 FILE CORRECTLY !!!!!' - write(error_unit,*) 'Error in opening netcdf file '//filename - call par_ex(MPI_COMM_FESOM, mype) - stop - endif - - ! data - allocate(ncdata(12)) - status=nf90_inq_varid(ncid, CO2vari, varid) - CO2start = 1 - CO2count = 12 - status=nf90_get_var(ncid, varid, ncdata, start=(/CO2start/), count=(/CO2count/)) - AtmCO2(:)=ncdata(:) - deallocate(ncdata) - if (mype==0) write(*,*),'Current carbon year=',currentCO2year - 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 - +! ============================================================ +! Read surface atmospheric deposition for Fe, N, CO2 +! ============================================================ + call log_recom_atm_input_entry(mype, recom_debug) + ! ---------------------------------------------------------------- + ! Atmospheric CO2 — update once per year (when mstep == 1) + ! ---------------------------------------------------------------- -! ******** Sediment input ********* -!-Checking if files need to be opened--------------------------------------------- - if(use_MEDUSA .and. (sedflx_num .ne. 0)) then - allocate(ncdata(9)) - if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Sed_input'//achar(27)//'[0m' - ! MEDUSA input needs to be renamed via jobscript - sedfilename = trim(ResultPath)//'medusa_flux2fesom.nc' - if (mype==0) write(*,*) 'Updating sedimentary input first time from', sedfilename - -!-Opening files-------------------------------------------------------------------- - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_din', 1, GloSed(:,1), partit,mesh) -! if (mype==0) write(*,*) mype, 'sediment DIN flux:', maxval(GloSed(:,1)), minval(GloSed(:,1)) - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_dic', 1, GloSed(:,2), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment DIC flux:', maxval(GloSed(:,2)), minval(GloSed(:,2)) - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_alk', 1, GloSed(:,3), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment Alk flux:', maxval(GloSed(:,3)), minval(GloSed(:,3)) - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_dsi', 1, GloSed(:,4), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment DSi flux:', maxval(GloSed(:,4)), minval(GloSed(:,4)) - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_o2', 1, GloSed(:,5), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment O2 flux:', maxval(GloSed(:,5)), minval(GloSed(:,5)) - - if(ciso) then - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_dic13', 1, GloSed(:,6), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment DIC13 flux:', maxval(GloSed(:,6)), minval(GloSed(:,6)) - if(ciso_14) then - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_dic14', 1, GloSed(:,7), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment DIC14 flux:', maxval(GloSed(:,7)), minval(GloSed(:,7)) - end if ! ciso_14 - end if ! ciso - -! unit conversion - GloSed(:,:)=GloSed(:,:)/86400 - -! read loopback fluxes from the same file - if(add_loopback) then - if (mype==0) write(*,*) 'adding loopback fluxes through runoff for the first time' !OG - - istart = (/1,1/) - icount = (/1,1/) - ncdata = 0.d0 - - total_runoff = 8.76d5*86400 - - status=nf_open(sedfilename, nf_nowrite, ncid) - if(status.ne.nf_noerr) call handle_err(status) - - status=nf_inq_varid(ncid, 'loopback_orgm_din', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(1)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_orgm_din (mmolN/day):', ncdata(1) !OG - - status=nf_inq_varid(ncid, 'loopback_orgm_dic', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(2)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_orgm_dic (mmolC/day):', ncdata(2) !OG - - status=nf_inq_varid(ncid, 'loopback_orgm_alk', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(3)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_orgm_alk (mmolAlk/day):', ncdata(3) !OG - - status=nf_inq_varid(ncid, 'loopback_opal', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(4)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_opal (mmolSi/day):', ncdata(4) !OG - - status=nf_inq_varid(ncid, 'loopback_caco3', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(5)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_caco3 (mmolC/day):', ncdata(5) !OG - - if(ciso) then - status=nf_inq_varid(ncid, 'loopback_orgm_dic13', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(6)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_dic13:', ncdata(6) !OG - - status=nf_inq_varid(ncid, 'loopback_caco313', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(7)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_caco313:', ncdata(7)!OG - - if(ciso_14 .and. ciso_organic_14) then - status=nf_inq_varid(ncid, 'loopback_orgm_dic14', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(8)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_dic14:', ncdata(8) !OG - - status=nf_inq_varid(ncid, 'loopback_caco314', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(9)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_caco314:', ncdata(9) !OG - - end if ! ciso_14 .and. ciso_organic_14 - end if ! ciso - deallocate(ncdata) - status=nf_close(ncid) - -! calculating fluxes back to ocean surface through rivers (mmol/m2/s) -! converting from fluxes out of sediment to fluxes into the ocean - do n_lb = 1,9 - lb_flux(:,n_lb) = -runoff*ncdata(n_lb)/total_runoff*lb_tscale - end do + if (mstep == 1) then - end if ! add_loopback + ! --- Source: Atmospheric box model --- + if (use_atbox) then + AtmCO2(:) = x_co2atm(1) - else + if (ciso) then + AtmCO2_13(:) = x_co2atm_13(1) + if (ciso_14) AtmCO2_14(:,1) = x_co2atm_14(1) + end if -!-Checking if files need to be opened--------------------------------------------- - call monthly_event(do_read, 1) - if(do_read) then ! file is opened and read every year - i=month - if (i > 12) i=1 - if (mype==0) write(*,*) 'Updating sedimentary input for month', i, 'from', sedfilename !OG - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_din', 1, GloSed(:,1), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment DIN flux:', maxval(GloSed(:,1)), minval(GloSed(:,1)) - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_dic', 1, GloSed(:,2), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment DIC flux:', maxval(GloSed(:,2)), minval(GloSed(:,2)) - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_alk', 1, GloSed(:,3), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment Alk flux:', maxval(GloSed(:,3)), minval(GloSed(:,3)) - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_dsi', 1, GloSed(:,4), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment DSi flux:', maxval(GloSed(:,4)), minval(GloSed(:,4)) - - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_o2', 1, GloSed(:,5), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment O2 flux:', maxval(GloSed(:,5)), minval(GloSed(:,5)) - - if(ciso) then - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_dic13', 1, GloSed(:,6), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment DIC13 flux:', maxval(GloSed(:,6)), minval(GloSed(:,6)) - if(ciso_14) then - call read_2ddata_on_grid_NetCDF(sedfilename, 'df_dic14', 1, GloSed(:,7), partit, mesh) -! if (mype==0) write(*,*) mype, 'sediment DIC14 flux:', maxval(GloSed(:,7)), minval(GloSed(:,7)) - end if ! ciso_14 - end if ! ciso - -!to mmol/m2/s - GloSed(:,:)=GloSed(:,:)/86400 - -! read loopback fluxes from the same file - if(add_loopback) then - if (mype==0) write(*,*) 'adding loopback fluxes into the ocean monthly' !OG - - istart = (/1,1/) - icount = (/1,1/) - ncdata = 0.d0 - - total_runoff = 8.76d5*86400 - - status=nf_open(sedfilename, nf_nowrite, ncid) - if(status.ne.nf_noerr) call handle_err(status) - - status=nf_inq_varid(ncid, 'loopback_orgm_din', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(1)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_orgm_din (mmolN/day):', ncdata(1) !OG - - status=nf_inq_varid(ncid, 'loopback_orgm_dic', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(2)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_orgm_dic (mmolC/day):', ncdata(2) !OG - - status=nf_inq_varid(ncid, 'loopback_orgm_alk', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(3)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_orgm_alk (mmolAlk/day):', ncdata(3) !OG - - status=nf_inq_varid(ncid, 'loopback_opal', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(4)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_opal (mmolSi/day):', ncdata(4) !OG - - status=nf_inq_varid(ncid, 'loopback_caco3', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(5)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_caco3 (mmolC/day):', ncdata(5) !OG - - if(ciso) then - status=nf_inq_varid(ncid, 'loopback_orgm_dic13', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(6)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_dic13:', ncdata(6) !OG - - status=nf_inq_varid(ncid, 'loopback_caco313', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(7)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_caco313:', ncdata(7) !OG - - if(ciso_14 .and. ciso_organic_14) then - status=nf_inq_varid(ncid, 'loopback_orgm_dic14', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(8)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_dic14:', ncdata(8) !OG - - status=nf_inq_varid(ncid, 'loopback_caco314', varid) - if(status.ne.nf_noerr) call handle_err(status) - status=nf_get_vara_double(ncid,varid,istart,icount,ncdata(9)) - if(status.ne.nf_noerr) call handle_err(status) - if (mype==0) write(*,*) mype, 'loopback_caco314:', ncdata(9) !OG - - end if ! ciso_14 .and. ciso_organic_14 - end if ! ciso - status=nf_close(ncid) - -! calculating fluxes back to ocean surface through rivers (mmol/m2/s) -! converting from fluxes out of sediment to fluxes into the ocean - do n_lb = 1,9 - lb_flux(:,n_lb) = -runoff*ncdata(n_lb)/total_runoff*lb_tscale - end do + ! --- Source: Prescribed CO2 values --- + else - end if ! add_loopback + ! Option A: Constant CO2 (spinup mode) + if (constant_CO2) then + AtmCO2(:) = CO2_for_spinup + if (mype == 0) then + write(*,*) 'Constant_CO2 = ', CO2_for_spinup + write(*,*) 'Atm CO2 = ', AtmCO2 + end if - end if ! do_read + 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 + lat_val = geo_coord_nod2D(2,i) / rad + + 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 - if (mype==0) write(*,*) 'sedimentary input from MEDUSA not used!' !OG + ! Option B: Transient CO2 from file + else + filename=trim(make_full_path(nm_co2_data_file)) + !if (mype==0) write(*,*) 'Updating CO2 climatology for month ', i,' from ', trim(filename) - end if ! use_MEDUSA and sedflx_num not 0 + ! Compute the CO2 year corresponding to the current FESOM cycle + totnumyear = lastyearoffesomcycle - firstyearoffesomcycle + 1 + firstyearofcurrentCO2cycle = lastyearoffesomcycle & + - numofCO2cycles*totnumyear & + + (currentCO2cycle-1) * totnumyear - end if + currentCO2year = firstyearofcurrentCO2cycle & + + (yearnew - firstyearoffesomcycle) + 1 + + if (mype == 0) write(*,*) currentCO2year, firstyearofcurrentCO2cycle, & + yearnew, firstyearoffesomcycle + write(currentCO2year_char, '(i4)') currentCO2year + CO2vari = 'AtmCO2_' // currentCO2year_char + + ! Open NetCDF file + status = nf90_open(filename, nf90_nowrite, ncid) + if (status /= nf90_noerr) then + if (mype == 0) then + print *, 'ERROR: Cannot open CO2 file: ', trim(filename) + end if + call par_ex(MPI_COMM_FESOM, mype) + stop + end if + + ! Read 12-month CO2 array + allocate(ncdata(12)) + status = nf90_inq_varid(ncid, CO2vari, varid) + CO2start = 1 + CO2count = 12 + status = nf90_get_var(ncid, varid, ncdata, & + start=(/CO2start/), count=(/CO2count/)) + AtmCO2(:) = ncdata(:) + deallocate(ncdata) + + !if (mype==0) write(*,*),'Current carbon year=',currentCO2year + !if (mype==0) write(*,*),'Atm CO2=', AtmCO2 + call log_co2_transient_update(mype, i, currentCO2year, filename) + status = nf90_close(ncid) + + end if ! constant_CO2 / transient CO2 + + end if ! use_atbox / prescribed CO2 + + ! --- Diagnostic output --- + call log_co2_control_output(mype, AtmCO2(1), ciso, AtmCO2_13(1), & + ciso_14, AtmCO2_14(1,1), use_atbox) + + if (mype == 0 .and. ciso) then + print *, ' AtmCO2_13 = ', AtmCO2_13(1) + if (ciso_14) print *, ' AtmCO2_14 = ', AtmCO2_14(:,1) + if (use_atbox) print *, ' use_atbox = .true.' + end if -! ******** Fe deposition ********* - if (fe_data_source=='Albani') then + end if ! mstep == 1 + + ! ---------------------------------------------------------------- + ! Iron (Fe) deposition + ! ---------------------------------------------------------------- + if (fe_data_source == 'Albani') then if (update_monthly_flag) then - i=month - if (mstep > 1) i=i+1 - if (i > 12) i=1 - filename=trim(make_full_path(nm_fe_data_file)) - if (mype==0) write(*,*) 'Updating iron climatology for month ', i,' from ', trim(filename) - call read_2ddata_on_grid_NetCDF(filename,'DustClim', i, GloFeDust, partit, mesh) + i = month + if (mstep > 1) i = i + 1 + if (i > 12) i = 1 + + filename = trim(make_full_path(nm_fe_data_file)) + !if (mype==0) write(*,*) 'Updating iron climatology for month ', i,' from ', trim(filename) + call log_fe_update(mype, i, filename) + call read_2ddata_on_grid_NetCDF(filename, 'DustClim', i, GloFeDust, partit, mesh) end if else - if (mype==0) write(*,*) 'Albani is switched off --> Check namelist.recom' + if (mype == 0) write(*,*) 'Albani is switched off --> Check namelist.recom' end if -! ******** N deposition ********* + ! ---------------------------------------------------------------- + ! Nitrogen (N) deposition + ! ---------------------------------------------------------------- if (useAeolianN) then -! todo: check below when useAeolianN is .true. - if (mstep==1) then ! The year has changed - i=month -! if (mstep > 1) i=i+1 -! if (i > 12) i=1 -! if (mype==0) write(*,*) 'Updating iron climatology for month ', i - filename=trim(make_full_path(nm_aen_data_file)) - if (mype==0) write(*,*) 'Updating nitrogen climatology for month ', i,' from ', trim(filename) - if (yearnew .gt. 2009) then + ! TODO: verify behaviour when useAeolianN is .true. + if (mstep == 1) then ! Year has changed — update annually + + i = month + filename = trim(make_full_path(nm_aen_data_file)) + + ! Select variable name based on year bounds + if (yearnew > 2009) then Nvari = 'NDep2009' - else if (yearnew .lt. 1850) then + else if (yearnew < 1850) then Nvari = 'NDep1850' else - Nvari = 'NDep'//cyearnew - endif + Nvari = 'NDep' // cyearnew + end if + call log_nitrogen_update(mype, i, filename, Nvari) call read_2ddata_on_grid_NetCDF(filename, Nvari, i, GloNDust, partit, mesh) + end if else GloNDust = 0.0_WP - if (mstep==1 .and. mype==0) write(*,*) 'useAeolianN is switched off' + if (mstep == 1) call log_nitrogen_disabled(mype) + !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 + !========================================================================= + ! RIVER INPUT + ! + ! Two mutually exclusive river input pathways: + ! + ! 1. R2OMIP pathway (enable_R2OMIP = .true.) + ! - Reads DIN, DOC_l, DOC_sl, POC from a NetCDF file. + ! - File is opened ONCE at the first model step (mstep == 1). + ! - Two sub-modes: + ! a) constant_PI_Rivers = .true. → pre-industrial climatology + ! b) constant_PI_Rivers = .false. → transient, year-specific file + ! + ! 2. Standard monthly pathway (enable_R2OMIP = .false.) + ! - Reads Alk, DIC, DIN, DOC, DON monthly. + ! - DSi is derived from DIN via a Redfield-like ratio. + ! - Updated only when update_monthly_flag is set. + ! + ! If useRivers = .false., all riverine fluxes are suppressed. + !========================================================================= + + !------------------------------------------------------------------------- + ! R2OMIP river input pathway (transient or constant pre-industrial) + !------------------------------------------------------------------------- + + if (enable_R2OMIP) then + + ! File is read once — at the very first model time step only. + if (mstep == 1) then + + !--- Rank 0: resolve filename and open the NetCDF file --- + if (mype==0) then + + if (constant_PI_Rivers) then + + ! Pre-industrial climatology (time-invariant) + !write(*,'(A)') 'INFO: Using constant pre-industrial riverine inputs' + filename = trim(REcoMDataPath) // 'Rivers_R2OMIP_PI.nc' + call log_river_r2omip_pi(mype, filename) + + else + ! Transient forcing — one file per simulation year + !write(*,'(4A)') 'INFO: Using transient riverine inputs — ', & + ! 'model year = ', trim(cyearnew), & + ! ' from ', trim(filename) + filename = trim(REcoMDataPath) // 'Rivers_R2OMIP_' // trim(cyearnew) // '.nc' + call log_river_r2omip_transient(mype, cyearnew, filename) + + endif + + write(*,*) 'Opening river file: ', trim(filename) + + status=nf90_open(filename, nf90_nowrite, ncid) + + end if ! mype == 0 + + !--- Broadcast open status to all MPI ranks --- + call MPI_BCast(status, 1, MPI_INTEGER, 0, MPI_COMM_FESOM, ierror) + + if (status /= nf90_noerr) then + if (mype == 0) then + write(*,'(A)') 'ERROR: Failed to open river input file: ' // trim(filename) + end if + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + end if + + !--- Load river nutrient fields and validate each --- + ! Each variable is read onto the 2-D unstructured grid and + ! checked for physical plausibility (river_sanity_check). + !if (mype == 0) write(*,*) 'Sanity-checking R2OMIP river variables...' + call log_river_sanity_start(mype) + + call load_river_variable(ncid, 'DIC', RiverDIC2D, partit, mesh) + locmax = maxval(RiverDIC2D) + locmin = minval(RiverDIC2D) + call river_sanity_check (locmax, locmin, 'DIC', partit, mesh) + !call river_sanity_check (RiverDIC2D, 'DIC', partit, mesh) + + call load_river_variable(ncid, 'DIN', RiverDIN2D, partit, mesh) + locmax = maxval(RiverDIN2D) + locmin = minval(RiverDIN2D) + call river_sanity_check (locmax, locmin, 'DIN', partit, mesh) + !call river_sanity_check (RiverDIN2D, 'DIN', partit, mesh) + + call load_river_variable(ncid, 'DOC_l', RiverDOCl2D, partit, mesh) + locmax = maxval(RiverDOCl2D) + locmin = minval(RiverDOCl2D) + call river_sanity_check (locmax, locmin, 'DOC_l', partit, mesh) + !call river_sanity_check (RiverDOCl2D, 'DOC_l', partit, mesh) + + call load_river_variable(ncid, 'DOC_sl', RiverDOCsl2D, partit, mesh) + locmax = maxval(RiverDOCsl2D) + locmin = minval(RiverDOCsl2D) + call river_sanity_check (locmax, locmin, 'DOC_sl', partit, mesh) + !call river_sanity_check (RiverDOCsl2D, 'DOC_sl', partit, mesh) + + call load_river_variable(ncid, 'POC', RiverPOC2D, partit, mesh) + locmax = maxval(RiverPOC2D) + locmin = minval(RiverPOC2D) + call river_sanity_check (locmax, locmin, 'POC', partit, mesh) + !call river_sanity_check (RiverPOC2D, 'POC', partit, mesh) + + !--- Close the file (rank 0 only; others never opened it) --- + if (mype == 0) status = nf90_close(ncid) + + end if ! mstep == 1 + + !--------------------------------------------------------------------- + ! PATHWAY 2: Standard monthly river inputs + !--------------------------------------------------------------------- + else + + if (update_monthly_flag) then + + !--- Compute the correct month index with year-end wrap-around --- + ! At mstep == 1 the month index is used as-is; thereafter it is + ! incremented by 1 to advance to the next calendar month. + i = month + if (mstep > 1) i = i + 1 + if (i > 12) i = 1 + + filename = trim(nm_river_data_file) + !if (mype == 0) then + ! write(*,'(A,I2,2A)') 'Updating riverine data for month ', i, & + ! ' from ', trim(filename) + !end if + call log_river_monthly_update(mype, i, filename) + + !--- Read biogeochemical tracers from the monthly climatology --- + call read_2ddata_on_grid_NetCDF(filename, 'Alkalinity', i, RiverAlk2D, partit, mesh) + 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', i, RiverDOC2D, partit, mesh) + call read_2ddata_on_grid_NetCDF(filename, 'DON', i, RiverDON2D, partit, mesh) + + ! Alkalinity in the file is given as [CaCO3]; convert to + ! total alkalinity by multiplying by 2 (each mol CaCO3 + ! releases 2 equivalents of carbonate alkalinity). + RiverAlk2D = RiverAlk2D * 2.0d0 + + ! DSi is not stored in the climatology file; estimate it + ! from DIN using a Redfield-like Si:N ratio of 16:15. + RiverDSi2D = RiverDIN2D * (16.0d0 / 15.0d0) + + end if ! update_monthly_flag + + end if ! enable_R2OMIP + + !------------------------------------------------------------------------- + ! RIVERS DISABLED: zero out all riverine fluxes + !------------------------------------------------------------------------- + else + + is_riverinput = 0.0d0 + !if (mype == 0 .and. mstep == 1) then + ! write(*,*) 'INFO: Riverine input disabled (useRivers = .false.)' + !end if + if (mstep == 1) call log_river_disabled(mype) + + end if ! useRivers + + !----------------------------------------------------------------------------- + ! Riverine iron input + !----------------------------------------------------------------------------- -! ******** Riverine input of iron ********* if (useRivFe) then - ! River runoff (m/s) is multiplied with Fe concentration * muemolFe/m3 -> muemolFe/m2/s - ! add river nutrients as surface boundary condition (surface_bc function in - ! oce_ale_tracers) + + ! River runoff (m/s) is multiplied with Fe concentration * muemolFe/m3 -> muemolFe/m2/s + ! add river nutrients as surface boundary condition (surface_bc function in + ! oce_ale_tracers) RiverFe = runoff * RiverFeConc else + RiverFe = 0.0d0 + end if -! ******** Erosion (Nutrients) ********* - if (useErosion) then -!< read erosion input - ! *** River inputs are in mmol/m2/s *** - ! add erosion nutrients as surface boundary condition (surface_bc function in oce_ale_tracers) - if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Erosion_input'//achar(27)//'[0m' + !========================================================================= + ! EROSION INPUT MODULE — REcoM Biogeochemistry + ! + ! Applies monthly erosion fluxes as a surface boundary condition. + ! Units: mmol m⁻² s⁻¹ (passed to surface_bc in oce_ale_tracers) + ! + ! Variables loaded: + ! POC → ErosionTOC2D (particulate organic carbon) + ! PON → ErosionTON2D (particulate organic nitrogen) + ! TSi → ErosionTSi2D (silicate, derived from TON via Redfield ratio) + ! + ! Note: Silicate is not stored in the erosion file; it is estimated + ! from TON using a Redfield-like Si:N ratio of 16:15. + !========================================================================= + + if (useErosion) then - is_erosioninput = 1.0d0 + is_erosioninput = 1.0d0 + + !--- Optional debug trace (ANSI cyan, rank 0 only) --- + !if (recom_debug .and. mype == 0) then + ! print *, achar(27)//'[36m'//' --> Erosion_input'//achar(27)//'[0m' + !end if + + call log_erosion_entry(mype, recom_debug) if (update_monthly_flag) then - i=month - if (mstep > 1) i=i+1 - if (i > 12) i=1 - filename=trim(nm_erosion_data_file) - if (mype==0) write(*,*) 'Updating erosion restoring data for month ', i,' from ', trim(filename) - call read_2ddata_on_grid_NetCDF(filename,'POC', i, ErosionTOC2D, partit, mesh) - ! write(*,*) mype, 'ErosionTOC2D', maxval(ErosionTOC2D(:)), minval(ErosionTOC2D(:)) - - call read_2ddata_on_grid_NetCDF(filename,'PON', i, ErosionTON2D, partit, mesh) - ! write(*,*) mype, 'ErosionTON2D', maxval(ErosionTON2D(:)), minval(ErosionTON2D(:)) + + !--- Compute current month index with year-end wrap-around --- + ! At mstep == 1 the month index is used as-is; thereafter it is + ! incremented by 1 to advance to the next calendar month. + i = month + if (mstep > 1) i = i + 1 + if (i > 12) i = 1 + + filename = trim(nm_erosion_data_file) + !if (mype == 0) then + ! write(*,'(A,I2,2A)') 'Updating erosion data for month ', i, & + ! ' from ', trim(filename) + !end if + call log_erosion_monthly_update(mype, i, filename) + + !--- Read particulate organic tracers from the monthly file --- + call read_2ddata_on_grid_NetCDF(filename, 'POC', i, ErosionTOC2D, partit, mesh) + call read_2ddata_on_grid_NetCDF(filename, 'PON', i, ErosionTON2D, partit, mesh) + + ! Silicate is absent from the erosion file; derive it from TON + ! using a Redfield-like Si:N ratio of 16:15. + ! Note: integer division (16/15 = 1) is avoided by using + ! double-precision literals. + ErosionTSi2D = ErosionTON2D * (16.0d0 / 15.0d0) - ! No silicates in erosion, we convert from nitrogen with redfieldian ratio - ErosionTSi2D=ErosionTON2D * 16/15 - end if - else - is_erosioninput = 0.0d0 - if (mype==0 .and. mstep==1) write(*,*) 'No erosion input' - end if + end if ! update_monthly_flag + + !------------------------------------------------------------------------- + ! EROSION DISABLED: zero out all erosion fluxes + !------------------------------------------------------------------------- + else + + is_erosioninput = 0.0d0 + !if (mype == 0 .and. mstep == 1) then + ! write(*,*) 'INFO: Erosion input disabled (useErosion = .false.)' + !end if + if (mstep == 1) call log_erosion_disabled(mype) + + end if ! useErosion #endif !!PS if (partit%mype==0) then @@ -2229,7 +2226,7 @@ SUBROUTINE check_nferr(iost,fname, partit) integer, intent(in) :: iost if (iost .ne. NF90_NOERR) then - write(error_unit,*) 'ERROR: I/O status= "',trim(nf90_strerror(iost)),'";',iost,' file= ',fname + write(*,*) 'ERROR: I/O status= "',trim(nf90_strerror(iost)),'";',iost,' file= ',fname call par_ex(partit%MPI_COMM_FESOM, partit%mype) stop endif @@ -2579,7 +2576,7 @@ subroutine fairall(sst,airt,u10,v10,precip,qs,qa,rhoa,evap,taux,tauy,qe,qh) end if ! ier >0 end if ! Ri < 0.25 - end if !delw != 0.0 + end if !delw != 0.0 return end subroutine fairall @@ -3153,12 +3150,12 @@ subroutine read_runoff_mapper(file, vari, R, partit, mesh) call MPI_BCast(status, 1, MPI_INTEGER, 0, MPI_COMM_FESOM, ierror) if (status.ne.nf90_noerr)then - write(error_unit,*) 'ERROR: CANNOT READ 2D netCDF FILE CORRECTLY !!!!!' - write(error_unit,*) 'Error in opening netcdf file '//file + print*,'ERROR: CANNOT READ 2D netCDF FILE CORRECTLY !!!!!' + print*,'Error in opening netcdf file '//file call par_ex(partit%MPI_COMM_FESOM, partit%mype) stop endif - + if (mype==0) then ! lat status=nf90_inq_dimid(ncid, 'lat', latid) @@ -3274,8 +3271,8 @@ subroutine read_runoff_mapper(file, vari, R, partit, mesh) if (status/=number_arrival_points) then if (mype==0) then - write(error_unit,*) 'RUNOFF MAPPER ERROR: total number of arrival points does not sum up among partitions: ', status, number_arrival_points - write(error_unit,*) 'two different grid points have same distance to a target point!' + write(*,*) 'RUNOFF MAPPER ERROR: total number of arrival points does not sum up among partitions: ', status, number_arrival_points + write(*,*) 'two different grid points have same distance to a target point!' end if call par_ex(partit%MPI_COMM_FESOM, partit%mype) STOP @@ -3304,8 +3301,8 @@ subroutine read_runoff_mapper(file, vari, R, partit, mesh) j=data_sparse(i) if ((j<0) .OR. (j>drain_num)) then if (mype==0) then - write(error_unit,*) 'RUNOFF MAPPER ERROR: arrival point has an index outside of permitted range', j, drain_num - write(error_unit,*) 'two different grid points have same distance to a target point!' + write(*,*) 'RUNOFF MAPPER ERROR: arrival point has an index outside of permitted range', j, drain_num + write(*,*) 'two different grid points have same distance to a target point!' end if call par_ex(partit%MPI_COMM_FESOM, partit%mype) STOP diff --git a/src/info_module.F90 b/src/info_module.F90 index 00488185e..bbb8b3d1b 100644 --- a/src/info_module.F90 +++ b/src/info_module.F90 @@ -86,7 +86,14 @@ subroutine print_definitions() print '(g0)', 'VERBOSE is ON' #else print '(g0)', 'VERBOSE is OFF' -#endif +#endif + +#ifdef ENABLE_ALBEDO_INTELMPI_WORKAROUNDS + print '(g0)', 'ENABLE_ALBEDO_INTELMPI_WORKAROUNDS is ON' +#else + print '(g0)', 'ENABLE_ALBEDO_INTELMPI_WORKAROUNDS is OFF' +#endif + #ifdef ENABLE_NVHPC_WORKAROUNDS print '(g0)', 'ENABLE_NVHPC_WORKAROUNDS is ON' #else diff --git a/src/int_recom/recom_atbox.F90 b/src/int_recom/recom_atbox.F90 index 4e579c51e..4474d44ee 100644 --- a/src/int_recom/recom_atbox.F90 +++ b/src/int_recom/recom_atbox.F90 @@ -89,4 +89,3 @@ subroutine recom_atbox(partit, mesh) return end subroutine recom_atbox - diff --git a/src/int_recom/recom_extra.F90 b/src/int_recom/recom_extra.F90 index 44973c167..467d0a096 100644 --- a/src/int_recom/recom_extra.F90 +++ b/src/int_recom/recom_extra.F90 @@ -203,3 +203,110 @@ subroutine krill_resp(n, partit, mesh) end if endif end subroutine krill_resp + + +! Load river biogeochemical variables from NetCDF file R2OMIP +! Variables: DIC, 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 + +!----------------------------------------------------------------------------- +! Subroutine: river_sanity_check +! +! Purpose: Compute and print global min/max of a 2D riverine input array +! across all MPI ranks as a quick plausibility check after reading. +! +! Arguments: +! river_var - local 2D array of riverine input values +! varname - short label printed in the diagnostic output +!----------------------------------------------------------------------------- +!subroutine river_sanity_check(river_var, varname, partit, mesh) +subroutine river_sanity_check(locmax, locmin, varname, partit, mesh) + + use MOD_PARTIT + use MOD_PARSUP + use MOD_MESH + !use mpi + + implicit none + + ! Input parameters + type(t_partit), intent(inout), target :: partit + type(t_mesh), intent(inout), target :: mesh + + !real(8), intent(in) :: river_var(:) + character(len=*), intent(in) :: varname + + real(8) :: locmax, locmin, glo + !integer :: MPIerr + + +#include "../associate_part_def.h" +#include "../associate_mesh_def.h" +#include "../associate_part_ass.h" +#include "../associate_mesh_ass.h" + + !locmax = maxval(river_var) + !locmin = minval(river_var) + + call MPI_AllReduce(locmax, glo, 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype == 0) write(*,'(A,A,A,ES14.6)') ' |-> global max riverine ', trim(varname), '. = ', glo + + call MPI_AllReduce(locmin, glo, 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype == 0) write(*,'(A,A,A,ES14.6)') ' |-> global min riverine ', trim(varname), '. = ', glo + +end subroutine river_sanity_check + + diff --git a/src/int_recom/recom_forcing.F90 b/src/int_recom/recom_forcing.F90 index f74022f8e..81c4588fb 100644 --- a/src/int_recom/recom_forcing.F90 +++ b/src/int_recom/recom_forcing.F90 @@ -34,7 +34,6 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali use g_forcing_arrays use g_comm_auto use g_support - use, intrinsic :: ieee_arithmetic, only: ieee_is_nan implicit none type(t_dyn) , intent(inout), target :: dynamics @@ -277,6 +276,8 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali state(1:nn,imiczoon) = max(tiny,state(1:nn,imiczoon)) state(1:nn,imiczooc) = max(tiny,state(1:nn,imiczooc)) endif + + state(1:nn,idicremin) = max(tiny,state(1:nn,idicremin)) ! for DICremin tracer (added by Sina) if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> ciso after REcoM_Forcing'//achar(27)//'[0m' @@ -359,5 +360,54 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali 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 b8a94b276..c023b479f 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -30,7 +30,6 @@ subroutine recom_init(tracers, partit, mesh) use REcoM_locVar use recom_config use REcoM_ciso - implicit none #include "netcdf.inc" !___________________________________________________________________________ @@ -41,6 +40,7 @@ subroutine recom_init(tracers, partit, mesh) real(kind=WP) :: locDINmax, locDINmin, locDICmax, locDICmin, locAlkmax, glo real(kind=WP) :: locAlkmin, locDSimax, locDSimin, locDFemax, locDFemin real(kind=WP) :: locO2max, locO2min + real(kind=WP) :: locDICremin, locDICremax ! initialization of DIC remin (added by Sina) type(t_tracer), intent(inout), target :: tracers type(t_partit), intent(inout), target :: partit @@ -67,14 +67,25 @@ 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(RiverDON2D ( node_size )) - allocate(RiverDOC2D ( node_size )) - allocate(RiverDSi2D ( node_size )) - allocate(RiverDIC2D ( node_size )) - allocate(RiverAlk2D ( node_size )) - allocate(RiverFe ( node_size )) + if (enable_R2OMIP) then + allocate(RiverDIC2D ( node_size )) + allocate(RiverDIN2D ( node_size )) + allocate(RiverDOCl2D ( node_size )) + allocate(RiverDOCsl2D ( node_size )) + allocate(RiverPOC2D ( node_size )) + else + allocate(RiverDIN2D ( node_size )) + allocate(RiverDON2D ( node_size )) + allocate(RiverDOC2D ( node_size )) + allocate(RiverDSi2D ( node_size )) + allocate(RiverDIC2D ( node_size )) + allocate(RiverAlk2D ( node_size )) + endif + allocate(RiverFe ( node_size )) !! * Erosion nutrients as surface boundary condition * allocate(ErosionTON2D ( node_size )) @@ -95,8 +106,19 @@ 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 @@ -108,16 +130,27 @@ subroutine recom_init(tracers, partit, mesh) GloNDust = 0.d0 AtmNInput = 0.d0 - RiverDIN2D = 0.d0 - RiverDON2D = 0.d0 - RiverDOC2D = 0.d0 - RiverDSi2D = 0.d0 - RiverDIC2D = 0.d0 - RiverAlk2D = 0.d0 + ! calcite dissolution at the ocean bottom !R2OMIP + OmegaC_bottom = 0.d0 + + if (enable_R2OMIP) then + RiverDIC2D = 0.d0 + RiverDIN2D = 0.d0 + RiverDOCl2D = 0.d0 + RiverDOCsl2D = 0.d0 + RiverPOC2D = 0.d0 + else + RiverDIN2D = 0.d0 + RiverDON2D = 0.d0 + RiverDOC2D = 0.d0 + RiverDSi2D = 0.d0 + RiverDIC2D = 0.d0 + RiverAlk2D = 0.d0 + end if RiverFe = 0.d0 - ErosionTON2D = 0.d0 ErosionTOC2D = 0.d0 + ErosionTON2D = 0.d0 ErosionTSi2D = 0.d0 relax_alk = 0.d0 @@ -134,6 +167,12 @@ 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 @@ -184,6 +223,70 @@ subroutine recom_init(tracers, partit, mesh) 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 )) allocate(respmacro ( nl-1, node_size )) @@ -207,6 +310,21 @@ subroutine recom_init(tracers, partit, mesh) 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 respmicro = 0.d0 @@ -229,6 +347,21 @@ subroutine recom_init(tracers, partit, mesh) 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)) @@ -327,8 +460,24 @@ subroutine recom_init(tracers, partit, mesh) 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 ! OG 16.03.23 - Sinkvel2_tr(:,:,:) = 0.0d0 ! 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)) @@ -344,6 +493,7 @@ subroutine recom_init(tracers, partit, mesh) ! After reading parecomsetup namelist call initialize_tracer_indices + call print_sinking_config(mype) ! Validation check here call validate_recom_tracers(num_tracers, mype) @@ -529,6 +679,8 @@ subroutine recom_init(tracers, partit, mesh) 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 (1032) @@ -597,6 +749,8 @@ subroutine recom_init(tracers, partit, mesh) locDFemin = locDINmin locO2max = locDINmax locO2min = locDINmin + locDICremax = locDICremax ! init DIC remin (added by Sina) + locDICremin = locDICremin ! init DIC remin (added by Sina) do n=1, myDim_nod2d locDINmax = max(locDINmax,maxval(tracers%data(3)%values(ulevels_nod2D(n):nlevels_nod2D(n)-1,n)) ) @@ -611,16 +765,54 @@ subroutine recom_init(tracers, partit, mesh) locDFemin = min(locDFemin,minval(tracers%data(21)%values(ulevels_nod2D(n):nlevels_nod2D(n)-1,n)) ) locO2max = max(locO2max,maxval(tracers%data(24)%values(ulevels_nod2D(n):nlevels_nod2D(n)-1,n)) ) locO2min = min(locO2min,minval(tracers%data(24)%values(ulevels_nod2D(n):nlevels_nod2D(n)-1,n)) ) + ! DICremin tracer (added by Sina) + if (enable_3zoo2det .and. enable_coccos) then + locDICremax = max(locDICremax,maxval(tracers%data(39)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDICremin = min(locDICremin,minval(tracers%data(39)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + else if (enable_coccos .and. .not. enable_3zoo2det) then + locDICremax = max(locDICremax,maxval(tracers%data(31)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDICremin = min(locDICremin,minval(tracers%data(31)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + else if (enable_3zoo2det .and. .not. enable_coccos) then + locDICremax = max(locDICremax,maxval(tracers%data(33)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDICremin = min(locDICremin,minval(tracers%data(33)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + else + locDICremax = max(locDICremax,maxval(tracers%data(25)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + locDICremin = min(locDICremin,minval(tracers%data(25)%values(mesh%ulevels_nod2D(n):mesh%nlevels_nod2D(n)-1,n)) ) + end if + end do if (mype==0) write(*,*) "Sanity check for REcoM variables after recom_init call" - call print_global_minmax('DIN', locDINmin, locDINmax, .true.) - call print_global_minmax('DIC', locDICmin, locDICmax, .true.) - call print_global_minmax('Alk', locAlkmin, locAlkmax, .true.) - call print_global_minmax('DSi', locDSimin, locDSimax, .true.) - call print_global_minmax('DFe', locDFemin, locDFemax, .false.) - call print_global_minmax('O2', locO2min, locO2max, .false.) - + call MPI_AllREDUCE(locDINmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal max init. DIN. =', glo + call MPI_AllREDUCE(locDINmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal min init. DIN. =', glo + + call MPI_AllREDUCE(locDICmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal max init. DIC. =', glo + call MPI_AllREDUCE(locDICmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal min init. DIC. =', glo + call MPI_AllREDUCE(locAlkmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal max init. Alk. =', glo + call MPI_AllREDUCE(locAlkmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal min init. Alk. =', glo + call MPI_AllREDUCE(locDSimax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal max init. DSi. =', glo + call MPI_AllREDUCE(locDSimin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal min init. DSi. =', glo + call MPI_AllREDUCE(locDFemax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal max init. DFe. =', glo + call MPI_AllREDUCE(locDFemin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' `-> gobal min init. DFe. =', glo + call MPI_AllREDUCE(locO2max , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal max init. O2. =', glo + call MPI_AllREDUCE(locO2min , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' `-> gobal min init. O2. =', glo + call MPI_AllREDUCE(locDICremax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal max init. DICremin =', glo + call MPI_AllREDUCE(locDICremin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) + if (mype==0) write(*,*) ' |-> gobal min init. DICremin =', glo + if (enable_3zoo2det) then is_3zoo2det=1.0_WP else @@ -633,28 +825,11 @@ subroutine recom_init(tracers, partit, mesh) is_coccos=0.0_WP endif -contains - -subroutine print_global_minmax(label, loc_min, loc_max, use_pipe) - character(len=*), intent(in) :: label - real(kind=8) , intent(in) :: loc_min, loc_max - logical , intent(in) :: use_pipe - - real(kind=8) :: glo_min, glo_max - character(len=3) :: prefix_min, prefix_max - - if (use_pipe) then - prefix_max = ' |' - prefix_min = ' |' - else - prefix_max = ' |' - prefix_min = ' `' - end if - - call MPI_AllREDUCE(loc_max , glo_max , 1, MPI_DOUBLE_PRECISION, MPI_MAX, MPI_COMM_FESOM, MPIerr) - if (mype==0) write(*,*) prefix_max//'-> gobal max init. '//trim(label)//' =', glo_max - call MPI_AllREDUCE(loc_min , glo_min , 1, MPI_DOUBLE_PRECISION, MPI_MIN, MPI_COMM_FESOM, MPIerr) - if (mype==0) write(*,*) prefix_min//'-> gobal min init. '//trim(label)//' =', glo_min -end subroutine print_global_minmax + if (enable_R2OMIP) then + is_R2OMIP=1.0_WP + else + is_R2OMIP=0.0_WP + endif end subroutine recom_init + diff --git a/src/int_recom/recom_log.F90 b/src/int_recom/recom_log.F90 new file mode 100644 index 000000000..c49772ab7 --- /dev/null +++ b/src/int_recom/recom_log.F90 @@ -0,0 +1,423 @@ +!============================================================================= +! REcoM LOGGING MODULE — centralised, colourful log statements +! +! All print / write statements that were scattered inside +! #if defined (__recom) ... #endif +! blocks of gen_surface_forcing.F90 are collected here. +! +! ANSI colour legend used throughout: +! CYAN [36m — debug / verbose trace (recom_debug only) +! GREEN [32m — success / file opened / data loaded OK +! YELLOW [33m — informational update (monthly data, year change) +! MAGENTA [35m — CO2 / carbon cycle values +! RED [31m — errors (abort follows immediately) +! RESET [0m — always appended after every coloured line +!============================================================================= + +#if defined (__recom) + + !========================================================================== + ! Helper: emit one coloured line from rank-0 only + ! Usage: call recom_log(mype, COLOR_GREEN, 'message text') + ! + ! Colour constants: + ! COLOR_CYAN = achar(27)//'[36m' + ! COLOR_GREEN = achar(27)//'[32m' + ! COLOR_YELLOW = achar(27)//'[33m' + ! COLOR_MAGENTA = achar(27)//'[35m' + ! COLOR_RED = achar(27)//'[31m' + ! COLOR_RESET = achar(27)//'[0m' + !========================================================================== + SUBROUTINE recom_log(mype, color_code, msg) + implicit none + integer, intent(in) :: mype + character(len=*), intent(in) :: color_code + character(len=*), intent(in) :: msg + if (mype == 0) then + write(*, '(3A)') trim(color_code), trim(msg), achar(27)//'[0m' + end if + END SUBROUTINE recom_log + + !========================================================================== + ! SECTION 1 — sbc_ini (called once at initialisation) + ! Original location: end of sbc_ini, inside #if defined(__recom) + !========================================================================== + SUBROUTINE log_recom_namelist_open(mype, iostat_val) + ! Replaces the open/error block for namelist.recom + implicit none + integer, intent(in) :: mype, iostat_val + if (iostat_val == 0) then + call recom_log(mype, achar(27)//'[32m', & + ' file : namelist.recom for sbc open ok') + else + call recom_log(mype, achar(27)//'[31m', & + 'ERROR: --> bad opening file : namelist.recom for sbc') + ! caller must invoke par_ex / stop after this + end if + END SUBROUTINE log_recom_namelist_open + + !========================================================================== + ! SECTION 2 — sbc_do : debug entry trace + ! Original: if (recom_debug .and. mype==0) print *, '... --> Atm_input ...' + !========================================================================== + SUBROUTINE log_recom_atm_input_entry(mype, recom_debug) + implicit none + integer, intent(in) :: mype + logical, intent(in) :: recom_debug + if (recom_debug .and. mype == 0) then + call recom_log(mype, achar(27)//'[36m', & + ' --> Atm_input (entering atmospheric forcing update)') + end if + END SUBROUTINE log_recom_atm_input_entry + + !========================================================================== + ! SECTION 3 — Atmospheric CO2 + ! Covers: constant_CO2, transient file, atbox, control output + !========================================================================== + + ! 3a Constant CO2 spinup value + SUBROUTINE log_co2_constant(mype, CO2_for_spinup) + implicit none + integer, intent(in) :: mype + real(kind=8), intent(in) :: CO2_for_spinup + if (mype == 0) then + call recom_log(mype, achar(27)//'[35m', & + ' [CO2] Mode: constant spinup value') + write(*, '(A,F10.4)') achar(27)//'[35m'// & + ' Constant_CO2 = ', CO2_for_spinup + write(*, '(A)') achar(27)//'[0m' + end if + END SUBROUTINE log_co2_constant + + ! 3b Transient CO2 file read + SUBROUTINE log_co2_transient_update(mype, month_idx, currentCO2year, filename) + implicit none + integer, intent(in) :: mype, month_idx, currentCO2year + character(len=*), intent(in) :: filename + if (mype == 0) then + write(*, '(2A,I0,A,I0,2A)') achar(27)//'[35m', & + ' [CO2] Updating climatology for month ', month_idx, & + ' | carbon year = ', currentCO2year, & + ' from ', trim(filename) + write(*, '(A)') achar(27)//'[0m' + end if + END SUBROUTINE log_co2_transient_update + + ! 3c CO2 error: cannot open file + SUBROUTINE log_co2_file_error(mype, filename) + implicit none + integer, intent(in) :: mype + character(len=*), intent(in) :: filename + if (mype == 0) then + call recom_log(mype, achar(27)//'[31m', & + 'ERROR: CANNOT READ CO2 FILE CORRECTLY !!!!!') + call recom_log(mype, achar(27)//'[31m', & + 'Error in opening netcdf file: '//trim(filename)) + end if + END SUBROUTINE log_co2_file_error + + ! 3d Control output of atmospheric CO2 values (AtmCO2, AtmCO2_13, AtmCO2_14) + SUBROUTINE log_co2_control_output(mype, AtmCO2_val, & + ciso, AtmCO2_13_val, & + ciso_14, AtmCO2_14_val, & + use_atbox) + implicit none + integer, intent(in) :: mype + real(kind=8), intent(in) :: AtmCO2_val, AtmCO2_13_val, AtmCO2_14_val + logical, intent(in) :: ciso, ciso_14, use_atbox + if (mype == 0) then + write(*, '(2A,ES12.5)') achar(27)//'[35m', & + ' [CO2] AtmCO2 = ', AtmCO2_val + if (ciso) then + write(*, '(A,ES12.5)') & + ' AtmCO2_13 = ', AtmCO2_13_val + if (ciso_14) & + write(*, '(A,ES12.5)') & + ' AtmCO2_14 = ', AtmCO2_14_val + end if + if (use_atbox) & + write(*, '(A)') ' use_atbox = .true.' + write(*, '(A)') achar(27)//'[0m' + end if + END SUBROUTINE log_co2_control_output + + !========================================================================== + ! SECTION 4 — Iron (Fe) deposition + !========================================================================== + + ! 4a Monthly Albani Fe update + SUBROUTINE log_fe_update(mype, month_idx, filename) + implicit none + integer, intent(in) :: mype, month_idx + character(len=*), intent(in) :: filename + if (mype == 0) then + write(*, '(2A,I3,2A)') achar(27)//'[33m', & + ' [Fe] Updating iron climatology for month ', month_idx, & + ' from ', trim(filename) + write(*, '(A)') achar(27)//'[0m' + end if + END SUBROUTINE log_fe_update + + ! 4b Albani switched off + SUBROUTINE log_fe_disabled(mype) + implicit none + integer, intent(in) :: mype + call recom_log(mype, achar(27)//'[33m', & + ' [Fe] Albani dust is switched off --> Check namelist.recom') + END SUBROUTINE log_fe_disabled + + !========================================================================== + ! SECTION 5 — Nitrogen deposition + !========================================================================== + + ! 5a Monthly N update + SUBROUTINE log_nitrogen_update(mype, month_idx, filename, Nvari) + implicit none + integer, intent(in) :: mype, month_idx + character(len=*), intent(in) :: filename, Nvari + if (mype == 0) then + write(*, '(2A,I3,4A)') achar(27)//'[33m', & + ' [N] Updating nitrogen climatology for month ', month_idx, & + ' variable=', trim(Nvari), & + ' from ', trim(filename) + write(*, '(A)') achar(27)//'[0m' + end if + END SUBROUTINE log_nitrogen_update + + ! 5b N deposition disabled + SUBROUTINE log_nitrogen_disabled(mype) + implicit none + integer, intent(in) :: mype + call recom_log(mype, achar(27)//'[33m', & + ' [N] useAeolianN = .false.') + END SUBROUTINE log_nitrogen_disabled + + !========================================================================== + ! SECTION 6 — River inputs + !========================================================================== + + ! 6a R2OMIP: constant pre-industrial + SUBROUTINE log_river_r2omip_pi(mype, filename) + implicit none + integer, intent(in) :: mype + character(len=*), intent(in) :: filename + if (mype == 0) then + call recom_log(mype, achar(27)//'[32m', & + ' [RIV] Mode: constant pre-industrial riverine inputs (R2OMIP PI)') + call recom_log(mype, achar(27)//'[32m', & + ' Opening: '//trim(filename)) + end if + END SUBROUTINE log_river_r2omip_pi + + ! 6b R2OMIP: transient year-specific + SUBROUTINE log_river_r2omip_transient(mype, cyearnew, filename) + implicit none + integer, intent(in) :: mype + character(len=*), intent(in) :: cyearnew, filename + if (mype == 0) then + write(*, '(4A)') achar(27)//'[32m', & + ' [RIV] Mode: transient R2OMIP year=', trim(cyearnew), & + ' from '//trim(filename) + write(*, '(A)') achar(27)//'[0m' + end if + END SUBROUTINE log_river_r2omip_transient + + ! 6c R2OMIP file open error + SUBROUTINE log_river_r2omip_error(mype, filename) + implicit none + integer, intent(in) :: mype + character(len=*), intent(in) :: filename + if (mype == 0) then + call recom_log(mype, achar(27)//'[31m', & + 'ERROR: Failed to open river input file: '//trim(filename)) + end if + END SUBROUTINE log_river_r2omip_error + + ! 6d R2OMIP sanity check start + SUBROUTINE log_river_sanity_start(mype) + implicit none + integer, intent(in) :: mype + call recom_log(mype, achar(27)//'[32m', & + ' [RIV] Sanity-checking R2OMIP river variables...') + END SUBROUTINE log_river_sanity_start + + ! 6e Standard monthly river update + SUBROUTINE log_river_monthly_update(mype, month_idx, filename) + implicit none + integer, intent(in) :: mype, month_idx + character(len=*), intent(in) :: filename + if (mype == 0) then + write(*, '(2A,I3,2A)') achar(27)//'[33m', & + ' [RIV] Updating riverine data for month ', month_idx, & + ' from ', trim(filename) + write(*, '(A)') achar(27)//'[0m' + end if + END SUBROUTINE log_river_monthly_update + + ! 6f Rivers disabled + SUBROUTINE log_river_disabled(mype) + implicit none + integer, intent(in) :: mype + call recom_log(mype, achar(27)//'[33m', & + ' [RIV] Riverine input disabled (useRivers = .false.)') + END SUBROUTINE log_river_disabled + + !========================================================================== + ! SECTION 7 — Erosion inputs + !========================================================================== + + ! 7a Debug entry trace + SUBROUTINE log_erosion_entry(mype, recom_debug) + implicit none + integer, intent(in) :: mype + logical, intent(in) :: recom_debug + if (recom_debug .and. mype == 0) then + call recom_log(mype, achar(27)//'[36m', & + ' --> Erosion_input (entering erosion update)') + end if + END SUBROUTINE log_erosion_entry + + ! 7b Monthly erosion update + SUBROUTINE log_erosion_monthly_update(mype, month_idx, filename) + implicit none + integer, intent(in) :: mype, month_idx + character(len=*), intent(in) :: filename + if (mype == 0) then + write(*, '(2A,I3,2A)') achar(27)//'[33m', & + ' [ERO] Updating erosion data for month ', month_idx, & + ' from ', trim(filename) + write(*, '(A)') achar(27)//'[0m' + end if + END SUBROUTINE log_erosion_monthly_update + + ! 7c Erosion disabled + SUBROUTINE log_erosion_disabled(mype) + implicit none + integer, intent(in) :: mype + call recom_log(mype, achar(27)//'[33m', & + ' [ERO] Erosion input disabled (useErosion = .false.)') + END SUBROUTINE log_erosion_disabled + +#endif +!============================================================================= +! +! HOW TO REPLACE CALLS IN gen_surface_forcing.F90 +! ───────────────────────────────────────────────── +! +! sbc_ini +! ─────── +! BEFORE: +! if (iost == 0) then +! if (mype==0) WRITE(*,*) ' file : ', 'namelist.recom for sbc',' open ok' +! else +! if (mype==0) WRITE(*,*) 'ERROR: --> bad opening file : namelist.recom ...' +! +! AFTER: +! call log_recom_namelist_open(mype, iost) +! if (iost /= 0) then; call par_ex(...); stop; end if +! +! ───────────────────────────────────────────────── +! sbc_do — debug entry +! ─────── +! BEFORE: +! if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Atm_input'//... +! +! AFTER: +! call log_recom_atm_input_entry(mype, recom_debug) +! +! ───────────────────────────────────────────────── +! sbc_do — CO2 +! ────────────── +! BEFORE: +! if (mype==0) write(*,*) 'Updating CO2 climatology for month ', i,' from ', trim(filename) +! ... +! if (mype==0) write(*,*),'Current carbon year=',currentCO2year +! if (mype==0) write(*,*),'Atm CO2=', AtmCO2 +! print *, "In atm_input: AtmCO2 = ", AtmCO2(1) +! ... +! +! AFTER: +! call log_co2_transient_update(mype, i, currentCO2year, filename) +! ... +! call log_co2_control_output(mype, AtmCO2(1), ciso, AtmCO2_13(1), & +! ciso_14, AtmCO2_14(1,1), use_atbox) +! +! ───────────────────────────────────────────────── +! sbc_do — Fe +! ───────────── +! BEFORE: +! if (mype==0) write(*,*) 'Updating iron climatology for month ', i,' from ', trim(filename) +! +! AFTER: +! call log_fe_update(mype, i, filename) +! +! ───────────────────────────────────────────────── +! sbc_do — N +! ──────────── +! BEFORE: +! if (mype==0) write(*,*) 'Updating nitrogen climatology for month ', i,' from ', trim(filename) +! ... +! GloNDust = 0.0_WP +! if (mstep==1 .and. mype==0) write(*,*) 'useAeolianN is switched off' +! +! AFTER: +! call log_nitrogen_update(mype, i, filename, Nvari) +! ... +! call log_nitrogen_disabled(mype) +! +! ───────────────────────────────────────────────── +! sbc_do — Rivers +! ───────────────── +! BEFORE (R2OMIP PI): +! write(*,'(A)') 'INFO: Using constant pre-industrial riverine inputs' +! +! AFTER: +! call log_river_r2omip_pi(mype, filename) +! +! BEFORE (R2OMIP transient): +! write(*,'(4A)') 'INFO: Using transient riverine inputs ...', trim(cyearnew), ... +! +! AFTER: +! call log_river_r2omip_transient(mype, cyearnew, filename) +! +! BEFORE (sanity check): +! if (mype == 0) write(*,*) 'Sanity-checking R2OMIP river variables...' +! +! AFTER: +! call log_river_sanity_start(mype) +! +! BEFORE (standard monthly): +! write(*,'(A,I2,2A)') 'Updating riverine data for month ', i, ' from ', trim(filename) +! +! AFTER: +! call log_river_monthly_update(mype, i, filename) +! +! BEFORE (disabled): +! if (mype == 0 .and. mstep == 1) write(*,*) 'INFO: Riverine input disabled ...' +! +! AFTER: +! if (mstep == 1) call log_river_disabled(mype) +! +! ───────────────────────────────────────────────── +! sbc_do — Erosion +! ────────────────── +! BEFORE: +! if (recom_debug .and. mype == 0) print *, achar(27)//'[36m'//' --> Erosion_input'//... +! +! AFTER: +! call log_erosion_entry(mype, recom_debug) +! +! BEFORE: +! write(*,'(A,I2,2A)') 'Updating erosion data for month ', i, ' from ', trim(filename) +! +! AFTER: +! call log_erosion_monthly_update(mype, i, filename) +! +! BEFORE: +! if (mype == 0 .and. mstep == 1) write(*,*) 'INFO: Erosion input disabled ...' +! +! AFTER: +! if (mstep == 1) call log_erosion_disabled(mype) +! +!============================================================================= + diff --git a/src/int_recom/recom_main.F90 b/src/int_recom/recom_main.F90 index 6b583ebb7..97c1c06ef 100755 --- a/src/int_recom/recom_main.F90 +++ b/src/int_recom/recom_main.F90 @@ -1,7 +1,10 @@ -! 24.03.2023 -! OG -!=============================================================================== -! Main REcoM +! ============================================================================== +! 24.03.2023 OG +! MODULE / SUBROUTINE: recom +! Purpose: Top-level REcoM biogeochemistry driver. Loops over all local nodes, +! sets up per-column forcing, calls REcoM_Forcing, collects diagnostics, +! and performs MPI halo exchanges. +! ============================================================================== module recom_interface interface subroutine recom(ice, dynamics, tracers, partit, mesh) @@ -64,6 +67,7 @@ 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 @@ -149,16 +153,23 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) yearold, x_co2atm(1), x_co2atm_13(1), x_co2atm_14(1), cosmic_14(1) * production_rate_to_flux_14 end if end if + +! Resetting DICremin tracer to zero when reaching surface (added by Sina) + do tr_num=1,num_tracers + if (tracers%data(tr_num)%ID==1037) then + tracers%data(tr_num)%values(1, : ) = 0 + end if +end do + ! ====================================================================================== !********************************* LOOP STARTS ***************************************** do n=1, myDim_nod2D ! needs exchange_nod in the end ! if (ulevels_nod2D(n)>1) cycle -! nzmin = ulevels_nod2D(n) + nzmin = ulevels_nod2D(n) !!---- Number of vertical layers nzmax = nlevels_nod2D(n)-1 - if (nzmax < 1) cycle !!---- This is needed for piston velocity Loc_ice_conc = a_ice(n) @@ -175,6 +186,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) @@ -249,7 +263,11 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) ttf_rhs_bak = 0.0 - call recom_diag_backup(tracers, n, nzmax, num_tracers, ttf_rhs_bak) + 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) @@ -262,115 +280,8 @@ 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)) - 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 + ! Allocate and initialize all diagnostic arrays for a water column + call allocate_and_init_diags(nl) end if if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> REcoM_Forcing'//achar(27)//'[0m' @@ -378,147 +289,49 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) ! ====================================================================================== !******************************** RECOM FORCING **************************************** 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 - , HCO3_watercolumn & ! NEW MOCSY HCO3 for the whole watercolumn - , CO3_watercolumn & ! NEW DISS CO3 for the whole watercolumn - , OmegaC_watercolumn & ! NEW DISS OmegaC for the whole watercolumn - , kspc_watercolumn & ! NEW DISS stoichiometric solubility product for calcite [mol^2/kg^2] - , rhoSW_watercolumn & ! NEW DISS in-situ density of seawater [mol/m^3] + , CO2_watercolumn & + , pH_watercolumn & + , pCO2_watercolumn & + , HCO3_watercolumn & + , CO3_watercolumn & + , OmegaC_watercolumn & + , kspc_watercolumn & + , rhoSW_watercolumn & , PAR, ice, dynamics, tracers, partit, mesh) do tr_num = num_tracers-bgc_num+1, num_tracers !bgc_num+2 tracers%data(tr_num)%values(1:nzmax, n) = C(1:nzmax, tr_num-2) end do - call recom_diag_store_delta(tracers, n, nzmax, num_tracers, ttf_rhs_bak) + ! 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 (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> ciso after REcoM_Forcing'//achar(27)//'[0m' + if (Diags) then + call update_2d_diags(n) - !! * 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 - - end if + call update_3d_diags(n, nzmax) + ! Deallocate vertical tracer array + call deallocate_diags() + 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) @@ -575,31 +388,67 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) call exchange_nod(Benthos(:,n), partit) end do - if (Diags) then - call exchange_nod(NPPn, partit) - call exchange_nod(NPPd, partit) - call exchange_nod(GPPn, partit) - call exchange_nod(GPPd, partit) - call exchange_nod(NNAn, partit) - call exchange_nod(NNAd, partit) - call exchange_nod(Chldegn, partit) - call exchange_nod(Chldegd, 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 - endif + if (Diags) call exchange_diags(partit) + +! if (Diags) then +! call exchange_nod(NPPn, partit) +! call exchange_nod(NPPd, partit) +! call exchange_nod(GPPn, partit) +! call exchange_nod(GPPd, partit) +! call exchange_nod(NNAn, partit) +! call exchange_nod(NNAd, partit) +! call exchange_nod(Chldegn, partit) +! call exchange_nod(Chldegd, 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) @@ -615,34 +464,6 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) call exchange_nod(kspc3D, partit) call exchange_nod(rhoSW3D, partit) -contains - -subroutine recom_diag_backup(tracers, n, nzmax, num_tracers, ttf_rhs_bak) - type(t_tracer), intent(in) :: tracers - integer , intent(in) :: n, nzmax, num_tracers - real(kind=WP) , intent(inout) :: ttf_rhs_bak(:,:) - integer :: tr_num - - 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 -end subroutine recom_diag_backup - -subroutine recom_diag_store_delta(tracers, n, nzmax, num_tracers, ttf_rhs_bak) - type(t_tracer), intent(inout) :: tracers - integer , intent(in) :: n, nzmax, num_tracers - real(kind=WP) , intent(in) :: ttf_rhs_bak(:,:) - integer :: tr_num - - 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) - end if - end do -end subroutine recom_diag_store_delta - end subroutine recom ! ====================================================================================== @@ -711,8 +532,10 @@ subroutine bio_fluxes(tracers, partit, mesh) ! Balance alkalinity restoring to climatology do n=1, myDim_nod2D+eDim_nod2D ! relax_alk(n)=surf_relax_Alk * (Alk_surf(n) - tracers%data(2+ialk)%values(1, n)) -! relax_alk(n)=surf_relax_Alk * (Alk_surf(n) - alkalinity(ulevels_nod2d(n),n) +! relax_alk(n)=surf_relax_Alk * (Alk_surf(n) - alkalinity(ulevels_nod2d(n),n)) +if (ulevels_nod2d(n) ==1) then relax_alk(n)=surf_relax_Alk * (Alk_surf(n) - alkalinity(1, n)) +end if end do ! 2. virtual alkalinity flux diff --git a/src/int_recom/recom_modules.F90 b/src/int_recom/recom_modules.F90 index 1d50fda51..1ef5868e3 100644 --- a/src/int_recom/recom_modules.F90 +++ b/src/int_recom/recom_modules.F90 @@ -15,6 +15,7 @@ !! 2014: original implementation (V. Schourup-Kristensen) ! module recom_config + use g_config, only: recom_coupled_to_atmosphere implicit none save @@ -33,6 +34,8 @@ module recom_config Integer :: izoo2n = 23, izoo2c = 24, idetz2n = 25, & idetz2c = 26, idetz2si = 27, idetz2calc = 28 + Integer :: idicremin = 0 ! added by Sina + ! Microzooplankton (third zooplankton group) integer :: imiczoon = 0 ! Microzooplankton Nitrogen (set below) integer :: imiczooc = 0 ! Microzooplankton Carbon (set below) @@ -50,6 +53,9 @@ module recom_config integer :: iphac = 0 ! Phaeocystis Carbon (set below) integer :: iphachl = 0 ! Phaeocystis Chlorophyll (set below) + ! Terrestrial DOC input (when enable_R2OMIP is enabled) + integer :: idoct = 0 + !============================================================================= Integer :: ivphy = 1, ivdia = 2, ivdet = 3, ivdetsc = 4, ivcoc = 5, ivpha = 6 @@ -58,8 +64,9 @@ module recom_config integer, dimension(8) :: recom_remin_tracer_id = (/1001, 1002, 1003, 1018, 1019, 1022, 1302, 1402/) -! OG -! Todo: Make recom_sinking_tracer_id case sensitive +! The static declaration integer, dimension(32) :: recom_sinking_tracer_id +! must remain size 32 (the full-model case uses all 32 slots), and the = 0 +! reset before partial fills ensures unused slots are inert. 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, & @@ -87,8 +94,9 @@ module recom_config !! *** REcoM setup *** Logical :: enable_3zoo2det = .false. ! Control extended zooplankton variables - Logical :: enable_coccos = .false. ! Control coccolithophore variables - namelist /parecomsetup/ enable_3zoo2det, enable_coccos + Logical :: enable_coccos = .false. ! Control coccolithophore variables + Logical :: enable_R2OMIP = .false. ! Control R2OMIP + namelist /parecomsetup/ enable_3zoo2det, enable_coccos, recom_coupled_to_atmosphere, enable_R2OMIP !! *** General configuration *** @@ -106,11 +114,11 @@ module recom_config 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 - Logical :: REcoM_Grazing_Variable_Preference = .true. ! Decides if grazing should have preference for phyN or DiaN + Logical :: REcoM_Geider_limiter = .false. ! Decides what routine should be used to calculate limiters in sms + Logical :: REcoM_Grazing_Variable_Preference = .true. ! Allow grazing preference to vary with food availability Logical :: Grazing_detritus = .false. ! Decides grazing on detritus Logical :: het_resp_noredfield = .true. ! Decides respiratation of copepods - Logical :: diatom_mucus = .true. ! Effect of nutrient limitation on the aggregation + Logical :: diatom_mucus = .true. ! Effect of nutrient limitation on the aggregation Logical :: O2dep_remin = .true. ! NEW O2remin Add option for O2 dependency of organic matter remineralization Logical :: use_ballasting = .true. ! NEW BALL Logical :: use_density_scaling = .true. ! NEW BALL @@ -118,16 +126,17 @@ module recom_config Logical :: OmegaC_diss = .true. ! NEW DISS Use mocsy calcite omega to compute calcite dissolution Logical :: CO2lim = .true. ! NEW Use CO2 dependence of growth and calcification !Logical :: inter_CT_CL = .true. ! NEW inter use interaction between CO2 and both, temperature and light - Logical :: Diags = .true. !!!!!!!!!!!!!!!!!!!!!!Change in recom.F90 Diagnostics -> Diags + Logical :: Diags = .true. !!!!!!!!!!!!!!!!!!!!!!Change in recom.F90 Diagnostics -> Diags Logical :: constant_CO2 = .true. Logical :: UseFeDust = .true. ! Turns dust input of iron off when set to.false. Logical :: UseDustClim = .true. - Logical :: UseDustClimAlbani = .true. ! Use Albani dustclim field (If it is false Mahowald will be used) + Logical :: UseDustClimAlbani = .true. ! Use Albani dustclim field (If it is false Mahowald will be used) Logical :: use_photodamage = .false. ! use Alvarez et al (2018) for chlorophyll degradation - logical :: HetRespFlux_plus = .true. !MB More stable computation of zooplankton respiration fluxes adding a small number to HetN + logical :: HetRespFlux_plus = .true. ! MB More stable computation of zooplankton respiration fluxes adding a small number to HetN 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) @@ -166,7 +175,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, & @@ -291,9 +301,9 @@ module recom_config !! *** Zooplankton *** Real(kind=8) :: graz_max = 2.4d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter Real(kind=8) :: epsilonr = 0.35d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss - Real(kind=8) :: res_het = 0.01d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) + Real(kind=8) :: res_het = 0.01d0 ! [1/day] Respiration by heterotrophs (loss to DIC) Real(kind=8) :: Redfield = 6.625 ! [mmol C/mmol N] Redfield ratio of C:N = 106:16 - Real(kind=8) :: loss_het = 0.05d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) + Real(kind=8) :: loss_het = 0.05d0 ! [m3/(mmolN*day)] The quadratic mortality rate (loss to detritus) Real(kind=8) :: pzDia = 0.5d0 ! Maximum diatom preference Real(kind=8) :: sDiaNsq = 0.d0 Real(kind=8) :: pzPhy = 1.0d0 ! Maximum nano-phytoplankton preference @@ -373,11 +383,13 @@ 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 @@ -518,6 +530,13 @@ module recom_config subroutine initialize_tracer_indices() implicit none + ! --------------------------------------------------------------------------- + ! Base sinking tracers (always present in all configurations): + ! Det1: DetN(1007), DetC(1008), DetSi(1017), DetCalc(1021) + ! Phy: PhyN(1004), PhyC(1005), PhyCalc(1020), PhyChl(1006) + ! Dia: DiaN(1013), DiaC(1014), DiaSi(1016), DiaChl(1015) + ! --------------------------------------------------------------------------- + if (enable_3zoo2det .and. enable_coccos) then ! ======================================================================= ! CASE: 4 phytoplankton + 3 zooplankton + 2 detritus @@ -535,14 +554,46 @@ subroutine initialize_tracer_indices() imiczoon = 35 imiczooc = 36 -! allocate(recom_cocco_tracer_id(3)) - recom_cocco_tracer_id = (/1029, 1030, 1031/) + ! Terrestrial DOC input (when enable_R2OMIP is enabled) + if (enable_R2OMIP) then + idoct = 37 + idicremin = 38 + else + idicremin = 37 + end if -! allocate(recom_phaeo_tracer_id(3)) + recom_cocco_tracer_id = (/1029, 1030, 1031/) recom_phaeo_tracer_id = (/1032, 1033, 1034/) - -! allocate(recom_det2_tracer_id(4)) - recom_det2_tracer_id = (/1025, 1026, 1027, 1028/) + recom_det2_tracer_id = (/1025, 1026, 1027, 1028/) + + ! Base(12) + Det2(4) + Zoo2Det2(4) + Cocco(3) + Phaeo(3) + CoccoCalc(2) + ! Det1 sinking: 1007,1008,1017,1021 + ! Phy sinking: 1004,1005,1020,1006 + ! Dia sinking: 1013,1014,1016,1015 + ! Det2 sinking: 1025,1026,1027,1028 (DetZ2N,DetZ2C,DetZ2Si,DetZ2Calc) + ! Zoo2 det: 1308,1321 (via zoo2 sinking tracer IDs) + ! Phy cal: 1305,1320 + ! Dia cal: 1314 + ! Cocco sinking:1029,1030,1031 -> mapped as 1308..? + ! + ! Reconstructing from original array for full model: + ! Original: 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 + + recom_sinking_tracer_id = 0 + recom_sinking_tracer_id(1:22) = & + (/1007, 1008, 1017, 1021, 1004, 1005, 1020, 1006, & + 1013, 1014, 1016, 1015, 1025, 1026, 1027, 1028, & + 1029, 1030, 1031, 1032, 1033, 1034/) + if (ciso) then + recom_sinking_tracer_id(23:32) = & + (/1308, 1321, 1305, 1320, & + 1314, 1408, 1421, 1405, 1420, 1414/) + end if else if (enable_coccos .and. .not. enable_3zoo2det) then ! ======================================================================= @@ -559,12 +610,35 @@ subroutine initialize_tracer_indices() iphac = 27 iphachl = 28 -! allocate(recom_cocco_tracer_id(3)) - recom_cocco_tracer_id = (/1023, 1024, 1025/) + ! Terrestrial DOC input (when enable_R2OMIP is enabled) + if (enable_R2OMIP) then + idoct = 29 + idicremin = 30 + else + idicremin = 29 + end if -! allocate(recom_phaeo_tracer_id(3)) + recom_cocco_tracer_id = (/1023, 1024, 1025/) recom_phaeo_tracer_id = (/1026, 1027, 1028/) + ! Det1 sinking: 1007,1008,1017,1021 + ! Phy sinking: 1004,1005,1020,1006 + ! Dia sinking: 1013,1014,1016,1015 + ! Cocco sinking:1023,1024,1025 + ! Phaeo sinking:1026,1027,1028 + ! Ciso-style: 1308,1321,1305,1320,1314,1408,1421,1405,1420,1414 + ! No Det2, no Zoo2 sinking + recom_sinking_tracer_id = 0 + recom_sinking_tracer_id(1:18) = & + (/1007, 1008, 1017, 1021, 1004, 1005, 1020, 1006, & + 1013, 1014, 1016, 1015, 1023, 1024, 1025, & + 1026, 1027, 1028/) + if (ciso) then + recom_sinking_tracer_id(19:28) = & + (/1308, 1321, 1305, 1320, & + 1314, 1408, 1421, 1405, 1420, 1414/) + end if + else if (enable_3zoo2det .and. .not. enable_coccos) then ! ======================================================================= ! CASE: 2 phytoplankton + 3 zooplankton + 2 detritus @@ -576,8 +650,32 @@ subroutine initialize_tracer_indices() imiczoon = 29 imiczooc = 30 -! allocate(recom_det2_tracer_id(4)) + ! Terrestrial DOC input (when enable_R2OMIP is enabled) + if (enable_R2OMIP) then + idoct = 31 + idicremin = 32 + else + idicremin = 31 + end if + recom_det2_tracer_id = (/1025, 1026, 1027, 1028/) + + ! Det1 sinking: 1007,1008,1017,1021 + ! Phy sinking: 1004,1005,1020,1006 + ! Dia sinking: 1013,1014,1016,1015 + ! Det2 sinking: 1025,1026,1027,1028 + ! Ciso-style: 1308,1321,1305,1320,1314,1408,1421,1405,1420,1414 + ! No Cocco/Phaeo sinking + recom_sinking_tracer_id = 0 + recom_sinking_tracer_id(1:16) = & + (/1007, 1008, 1017, 1021, 1004, 1005, 1020, 1006, & + 1013, 1014, 1016, 1015, 1025, 1026, 1027, 1028/) + if (ciso) then + recom_sinking_tracer_id(17:26) = & + (/1308, 1321, 1305, 1320, & + 1314, 1408, 1421, 1405, 1420, 1414/) + end if + else ! ======================================================================= ! CASE: 2 phytoplankton + 1 zooplankton + 1 detritus (BASE CONFIGURATION) @@ -586,6 +684,30 @@ subroutine initialize_tracer_indices() ! Zooplankton: mesozoo only ! Detritus: det1 only ! (All indices already set to default values) + + ! Terrestrial DOC input (when enable_R2OMIP is enabled) + if (enable_R2OMIP) then + idoct = 23 + idicremin = 24 + else + idicremin = 23 + end if + + ! Det1 sinking: 1007,1008,1017,1021 + ! Phy sinking: 1004,1005,1020,1006 + ! Dia sinking: 1013,1014,1016,1015 + ! Ciso-style: 1308,1321,1305,1320,1314,1408,1421,1405,1420,1414 + ! No Det2, no Cocco/Phaeo sinking + recom_sinking_tracer_id = 0 + recom_sinking_tracer_id(1:12) = & + (/1007, 1008, 1017, 1021, 1004, 1005, 1020, 1006, & + 1013, 1014, 1016, 1015/) + if (ciso) then + recom_sinking_tracer_id(13:22) = & + (/1308, 1321, 1305, 1320, & + 1314, 1408, 1421, 1405, 1420, 1414/) + end if + endif end subroutine initialize_tracer_indices @@ -596,6 +718,9 @@ end subroutine initialize_tracer_indices ! 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 @@ -607,6 +732,7 @@ subroutine validate_recom_tracers(num_tracers, mype) integer :: actual_bgc_num integer :: expected_total_tracers integer :: num_physical_tracers + integer :: doc_tracers logical :: config_error character(len=200) :: error_msg @@ -620,6 +746,13 @@ subroutine validate_recom_tracers(num_tracers, mype) ! Physical tracers (temperature, salinity, etc.) - typically first 2 num_physical_tracers = 2 + ! DOC tracers count + if (enable_R2OMIP) 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 @@ -638,7 +771,9 @@ subroutine validate_recom_tracers(num_tracers, mype) ! Additional phaeocystis: 3 tracers (1032-1034) ! Additional microzoo: 2 tracers (1035-1036) ! Total: 22 + 4 + 6 + 3 + 2 = 36 (actually 22 + 14 = 36) - expected_bgc_num = 36 + ! Additional DICremin: 1 tracer (1037) (added by Sina) + ! Plus DOC: +1 if enable_R2OMIP + expected_bgc_num = 37 + doc_tracers ! Sina: changed from 36 to 37 else if (enable_coccos .and. .not. enable_3zoo2det) then ! --------------------------------------------------------------------------- @@ -648,7 +783,9 @@ subroutine validate_recom_tracers(num_tracers, mype) ! Additional coccos: 3 tracers (1023-1025) ! Additional phaeocystis: 3 tracers (1026-1028) ! Total: 22 + 6 = 28 - expected_bgc_num = 28 + ! Additional DICremin: 1 tracer (1037) (added by Sina) + ! Plus DOC: +1 if enable_R2OMIP + expected_bgc_num = 29 + doc_tracers ! Sina: changed from 28 to 29 else if (enable_3zoo2det .and. .not. enable_coccos) then ! --------------------------------------------------------------------------- @@ -659,15 +796,23 @@ subroutine validate_recom_tracers(num_tracers, mype) ! Additional det2: 4 tracers (1025-1028) ! Additional microzoo: 2 tracers (1029-1030) ! Total: 22 + 8 = 30 - expected_bgc_num = 30 + ! Additional DICremin: 1 tracer (1037) (added by Sina) + ! Plus DOC: +1 if enable_R2OMIP + expected_bgc_num = 31 + doc_tracers ! Sina: changed from 30 to 31 else ! --------------------------------------------------------------------------- ! Configuration 1: Base model (2 phyto + 1 zoo + 1 detritus) ! --------------------------------------------------------------------------- ! Base: 22 tracers (1001-1022) - expected_bgc_num = 22 + ! Additional DICremin: 1 tracer (1037) (added by Sina) + ! Plus DOC: +1 if enable_R2OMIP + expected_bgc_num = 23 + doc_tracers ! Sina: changed from 22 to 23 + + 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 @@ -708,6 +853,10 @@ subroutine validate_recom_tracers(num_tracers, mype) expected_tracer_ids(36) = 1034 ! PhaeoChl expected_tracer_ids(37) = 1035 ! Zoo3N expected_tracer_ids(38) = 1036 ! Zoo3C + expected_tracer_ids(39) = 1037 ! DIC remin (added by Sina) + if (enable_R2OMIP) then + expected_tracer_ids(40) = 1038 ! DOCt (terrestrial DOC) ! Sina: each number increased by 1 + end if else if (enable_coccos .and. .not. enable_3zoo2det) then ! Coccos only: 1001-1022 (base) + 1023-1028 (coccos+phaeo) @@ -717,6 +866,10 @@ subroutine validate_recom_tracers(num_tracers, mype) expected_tracer_ids(28) = 1026 ! PhaeoN expected_tracer_ids(29) = 1027 ! PhaeoC expected_tracer_ids(30) = 1028 ! PhaeoChl + expected_tracer_ids(31) = 1037 ! DIC remin (added by Sina) + if (enable_R2OMIP) then + expected_tracer_ids(32) = 1029 ! DOCt (terrestrial DOC) ! Sina: changed 31 to 32 + end if else if (enable_3zoo2det .and. .not. enable_coccos) then ! 3Zoo2Det only: 1001-1022 (base) + 1023-1030 (zoo2+det2+zoo3) @@ -728,7 +881,23 @@ subroutine validate_recom_tracers(num_tracers, mype) expected_tracer_ids(30) = 1028 ! DetZ2Calc expected_tracer_ids(31) = 1029 ! Zoo3N expected_tracer_ids(32) = 1030 ! Zoo3C + expected_tracer_ids(33) = 1037 ! DIC remin (added by Sina) + if (enable_R2OMIP) then + expected_tracer_ids(34) = 1031 ! DOCt (terrestrial DOC) ! Sina: changed 33 to 34 + end if + + else + expected_tracer_ids(25) = 1037 ! add DIC remin tracer to base BGC tracers (added by Sina) + ! Base configuration: only tracers 1, 2, 1001-1022 + if (enable_R2OMIP) then + expected_tracer_ids(26) = 1023 ! DOCt (terrestrial DOC) ! Sina: changed 25 to 26 + 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 ! =========================================================================== @@ -743,9 +912,13 @@ subroutine validate_recom_tracers(num_tracers, mype) write(*,*) 'Model configuration:' write(*,*) ' enable_3zoo2det = ', enable_3zoo2det write(*,*) ' enable_coccos = ', enable_coccos + write(*,*) ' recom_coupled_to_atmosphere = ', recom_coupled_to_atmosphere + write(*,*) ' enable_R2OMIP = ', enable_R2OMIP + 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 @@ -768,17 +941,25 @@ subroutine validate_recom_tracers(num_tracers, mype) write(*,*) ' Difference: ', actual_bgc_num - expected_bgc_num write(*,*) '' write(*,*) 'Required tracer IDs for current configuration:' - write(*,*) ' Base tracers (always): 1001-1022 (22 tracers)' + write(*,*) ' Base tracers (always): 1001-1022 (22 tracers) + 1037 (DICremin)' 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' + write(*,*) ' - DICremin: 1037 ' ! added by Sina + if (enable_R2OMIP) 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' + write(*,*) ' - DICremin: 1037 ' ! added by Sina + if (enable_R2OMIP) 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)' @@ -786,12 +967,20 @@ subroutine validate_recom_tracers(num_tracers, mype) write(*,*) ' - CoccoN, C, Chl: 1029-1031' write(*,*) ' - PhaeoN, C, Chl: 1032-1034' write(*,*) ' MicroZoo extension: 1035-1036 (2 tracers)' + write(*,*) ' - DICremin: 1037 ' ! added by Sina + if (enable_R2OMIP) then + write(*,*) ' Terrestrial DOC: 1038 (1 tracer)' ! Sina: increased from 1037 to 1038 + end if + else + if (enable_R2OMIP) 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 and enable_coccos match your setup' + write(*,*) ' 2. Ensure enable_3zoo2det, enable_coccos, enable_R2OMIP, and useRivers match your setup' write(*,*) ' 3. Add/remove tracers to match the expected configuration' write(*,*) '==========================================================================' write(*,*) '' @@ -819,7 +1008,7 @@ subroutine validate_recom_tracers(num_tracers, mype) write(*,*) ' Expected value: ', expected_bgc_num write(*,*) '' write(*,*) 'This may indicate that bgc_num was not updated after changing' - write(*,*) 'enable_3zoo2det or enable_coccos flags.' + write(*,*) 'enable_3zoo2det, enable_coccos, enable_R2OMIP, or useRivers flag.' write(*,*) '==========================================================================' write(*,*) '' end if @@ -862,6 +1051,7 @@ subroutine validate_recom_tracers(num_tracers, mype) 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 enable_R2OMIP is enabled' write(*,*) '' ! Configuration-specific warnings @@ -873,27 +1063,47 @@ subroutine validate_recom_tracers(num_tracers, mype) write(*,*) ' - Coccos uses: 1029-1031' write(*,*) ' - Phaeocystis uses: 1032-1034' write(*,*) ' - Microzooplankton: 1035-1036' + write(*,*) ' - DIC remin: 1037 ' ! added by Sina + if (enable_R2OMIP) then + write(*,*) ' - Terrestrial DOC: 1038' ! Sina: increased from 1037 to 1038 + 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)' - write(*,*) ' - Tracers 1029+ are NOT used in this configuration' + write(*,*) ' - DIC remin: 1037 ' ! added by Sina + if (enable_R2OMIP) 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)' - write(*,*) ' - Tracers 1031+ are NOT used in this configuration' + write(*,*) ' - DIC remin: 1037 ' ! added by Sina + if (enable_R2OMIP) 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' - write(*,*) ' - Tracers 1023+ are NOT used in base configuration' - write(*,*) '' + write(*,*) ' - Only tracers 1-2, 1001-1022 and 1037 should be present' ! 1037 added by Sina + if (enable_R2OMIP) 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 @@ -920,6 +1130,17 @@ subroutine validate_recom_tracers(num_tracers, mype) write(*,*) 'Microzoo MUST use IDs 1029-1030 (NOT 1035-1036).' end if + if (useRivers) then + write(*,*) '' + write(*,*) 'Rivers enabled (useRivers = .true.)' + end if + + if (enable_R2OMIP) then + write(*,*) '' + write(*,*) 'enable_R2OMIP enabled (enable_R2OMIP = .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' @@ -957,6 +1178,9 @@ end subroutine validate_recom_tracers ! 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 @@ -971,11 +1195,19 @@ subroutine validate_tracer_id_sequence(tracer_ids, num_tracers, mype) 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 (enable_R2OMIP) then + doc_tracers = 1 + else + doc_tracers = 0 + end if + ! Allocate expected IDs array allocate(expected_ids(num_tracers)) @@ -992,14 +1224,37 @@ subroutine validate_tracer_id_sequence(tracer_ids, num_tracers, mype) 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/) + expected_ids(39) = 1037 ! DICremin, added by Sina + if (enable_R2OMIP) then + expected_ids(40) = 1038 ! DOCt ! Sina: each number increased by 1 + end if else if (enable_coccos .and. .not. enable_3zoo2det) then expected_ids(25:30) = (/1023, 1024, 1025, 1026, 1027, 1028/) + expected_ids(31) = 1037 ! DICremin, added by Sina + if (enable_R2OMIP) then + expected_ids(32) = 1029 ! DOCt ! Sina: increased 31 to 32 + end if else if (enable_3zoo2det .and. .not. enable_coccos) then expected_ids(25:32) = (/1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030/) + expected_ids(33) = 1037 ! DICremin, added by Sina + if (enable_R2OMIP) then + expected_ids(34) = 1031 ! DOCt ! Sina: increased 33 to 34 + end if + + else + ! Base configuration + expected_ids(25) = 1037 ! DICremin, added by Sina + if (enable_R2OMIP) then + expected_ids(26) = 1023 ! DOCt ! Sina: increased 25 to 26 + end if end if + if (use_age_tracer) then + expected_ids(num_tracers) = 100 + end if + ! =========================================================================== ! Check 1: Compare actual vs expected tracer IDs ! =========================================================================== @@ -1099,7 +1354,134 @@ subroutine validate_tracer_id_sequence(tracer_ids, num_tracers, mype) end subroutine validate_tracer_id_sequence +! ============================================================================== +! SUBROUTINE: print_sinking_config +! Purpose: Print the sinking tracer configuration for the current model setup +! ============================================================================== +subroutine print_sinking_config(mype) + implicit none + + integer, intent(in) :: mype + integer :: i, n_sinking + + if (mype /= 0) return + + ! Count active sinking tracers (non-zero entries) + n_sinking = count(recom_sinking_tracer_id /= 0) + + write(*,*) + write(*,*) '==========================================================================' + write(*,*) 'REcoM SINKING TRACER CONFIGURATION' + write(*,*) '==========================================================================' + write(*,*) 'Model flags:' + write(*,'(A,L1)') ' enable_3zoo2det : ', enable_3zoo2det + write(*,'(A,L1)') ' enable_coccos : ', enable_coccos + write(*,'(A,L1)') ' useRivers : ', useRivers + write(*,*) + write(*,'(A,I3)') ' Active sinking tracers: ', n_sinking + write(*,*) + + write(*,*) '----------------------------------------------------------' + write(*,*) ' Slot | Tracer ID | Description' + write(*,*) '----------------------------------------------------------' + do i = 1, 32 + if (recom_sinking_tracer_id(i) == 0) cycle + write(*,'(A,I4,A,I6,A,A)') ' ', i, ' | ', & + recom_sinking_tracer_id(i), ' | ', & + trim(sinking_tracer_name(recom_sinking_tracer_id(i))) + end do + write(*,*) '----------------------------------------------------------' + + write(*,*) + write(*,*) 'Sinking velocity assignments:' + write(*,'(A,F8.3,A)') ' VDet (Det1) : ', VDet, ' m/day' + write(*,'(A,F8.3,A)') ' VDet_zoo2 : ', VDet_zoo2, ' m/day' + write(*,'(A,F8.3,A)') ' VPhy : ', VPhy, ' m/day' + write(*,'(A,F8.3,A)') ' VDia : ', VDia, ' m/day' + if (enable_coccos) then + write(*,'(A,F8.3,A)') ' VCocco : ', VCocco, ' m/day' + write(*,'(A,F8.3,A)') ' VPhaeo : ', VPhaeo, ' m/day' + end if + write(*,'(A,L1)') ' allow_var_sinking : ', allow_var_sinking + write(*,*) + write(*,*) '==========================================================================' + write(*,*) +end subroutine print_sinking_config + +! ============================================================================== +! FUNCTION: sinking_tracer_name +! Purpose: Return a human-readable name for a given tracer ID +! ============================================================================== +function sinking_tracer_name(id) result(name) + implicit none + + integer, intent(in) :: id + character(len=24) :: name + + select case (id) + ! ------------------------------------------------------------------ + ! Detritus pool 1 + ! ------------------------------------------------------------------ + case (1007); name = 'DetN' + case (1008); name = 'DetC' + case (1017); name = 'DetSi' + case (1021); name = 'DetCalc' + ! ------------------------------------------------------------------ + ! Small phytoplankton + ! ------------------------------------------------------------------ + case (1004); name = 'PhyN' + case (1005); name = 'PhyC' + case (1020); name = 'PhyCalc' + case (1006); name = 'PhyChl' + ! ------------------------------------------------------------------ + ! Diatoms + ! ------------------------------------------------------------------ + case (1013); name = 'DiaN' + case (1014); name = 'DiaC' + case (1016); name = 'DiaSi' + case (1015); name = 'DiaChl' + ! ------------------------------------------------------------------ + ! Detritus pool 2 (3zoo2det) + ! ------------------------------------------------------------------ + case (1025); name = 'DetZ2N' + case (1026); name = 'DetZ2C' + case (1027); name = 'DetZ2Si' + case (1028); name = 'DetZ2Calc' + ! ------------------------------------------------------------------ + ! Coccolithophores (coccos) + ! ------------------------------------------------------------------ + case (1029); name = 'CoccoN' + case (1030); name = 'CoccoC' + case (1031); name = 'CoccoChl' + ! ------------------------------------------------------------------ + ! Phaeocystis (coccos) + ! ------------------------------------------------------------------ + case (1032); name = 'PhaeoN' + case (1033); name = 'PhaeoC' + case (1034); name = 'PhaeoChl' + ! ------------------------------------------------------------------ + ! C-isotope (13C) counterparts + ! ------------------------------------------------------------------ + case (1305); name = 'PhyCalc_13C' + case (1308); name = 'DetN_13C' + case (1314); name = 'DiaSi_13C' + case (1320); name = 'PhyChl_13C' + case (1321); name = 'DetC_13C' + ! ------------------------------------------------------------------ + ! C-isotope (14C) counterparts + ! ------------------------------------------------------------------ + case (1405); name = 'PhyCalc_14C' + case (1408); name = 'DetN_14C' + case (1414); name = 'DiaSi_14C' + case (1420); name = 'PhyChl_14C' + case (1421); name = 'DetC_14C' + ! ------------------------------------------------------------------ + case default + write(name,'(A,I6)') 'Unknown ID: ', id + end select + +end function sinking_tracer_name end module recom_config ! @@ -1285,20 +1667,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 - Real(kind=8) :: locNPPp, locGPPp, locNNAp, locChldegp ! Phaeocystis + + ! ================================================================== + ! 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(:) :: vertNPPp, vertGPPp, vertNNAp, vertChldegp ! Phaeocystis - 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, vertaggp - Real(kind=8),allocatable,dimension(:) :: vertdocexn, vertdocexd, vertdocexc, vertdocexp - Real(kind=8),allocatable,dimension(:) :: vertrespn, vertrespd, vertrespc, vertrespp + + ! ================================================================== + ! 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 @@ -1329,6 +1776,7 @@ Module REcoM_declarations real(kind=8) :: is_3zoo2det real(kind=8) :: is_coccos +real(kind=8) :: is_R2OMIP end module REcoM_declarations @@ -1345,6 +1793,7 @@ Module REcoM_GloVar 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 @@ -1373,6 +1822,11 @@ 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 ! @@ -1397,10 +1851,34 @@ Module REcoM_GloVar 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_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 @@ -1422,6 +1900,22 @@ Module REcoM_GloVar 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 @@ -1452,7 +1946,11 @@ 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 @@ -1466,7 +1964,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, RiverDOC2D, RiverDSi2D, RiverAlk2D + 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 @@ -1849,3 +2352,700 @@ end function wind_10 end module REcoM_ciso +! ============================================================================== +! MODULE: recom_diags_management +! Purpose: Allocation, initialization, update, and deallocation of all REcoM +! diagnostic arrays (per-node water column and global 2D/3D fields). +! ============================================================================== +module recom_diags_management + use recom_config + implicit none + +contains + +! ============================================================================== +! SUBROUTINE: allocate_and_init_diags +! Purpose: Allocate and initialize all local (per-column) diagnostic arrays +! ============================================================================== +subroutine allocate_and_init_diags(nl) + use recom_locvar + use REcoM_declarations + implicit none + + integer, intent(in) :: nl ! Number of vertical levels + + ! -------------------------------------------------------------------------- + ! Small Phytoplankton & Diatoms (always active) + ! -------------------------------------------------------------------------- + call alloc_init_phyto_diags(nl) + + ! -------------------------------------------------------------------------- + ! Coccolithophores and Phaeocystis (optional) + ! -------------------------------------------------------------------------- + if (enable_coccos) call alloc_init_cocco_diags(nl) + + ! Calcification arrays (always needed) + allocate(vertcalcdiss(nl-1), vertcalcif(nl-1)) + vertcalcdiss = 0.d0 + vertcalcif = 0.d0 + + ! -------------------------------------------------------------------------- + ! Zooplankton grazing (optional) + ! -------------------------------------------------------------------------- + if (Grazing_detritus) call alloc_init_zoo_diags(nl) + + ! -------------------------------------------------------------------------- + ! Dissolution, remineralization, and carbonate chemistry + ! -------------------------------------------------------------------------- + call alloc_init_bgc_diags(nl) + +end subroutine allocate_and_init_diags + +! ============================================================================== +! SUBROUTINE: alloc_init_phyto_diags +! Purpose: Allocate and initialize small phytoplankton and diatom diagnostics +! ============================================================================== +subroutine alloc_init_phyto_diags(nl) + use recom_locvar + use recom_declarations + implicit none + + integer, intent(in) :: nl + + ! -------------------------------------------------------------------------- + ! 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 + + ! -------------------------------------------------------------------------- + ! Photosynthesis and Nitrogen Assimilation + ! -------------------------------------------------------------------------- + allocate(vertphotn(nl-1), vertphotd(nl-1)) + allocate(vertNassimn(nl-1), vertNassimd(nl-1)) + vertphotn = 0.d0 + vertphotd = 0.d0 + vertNassimn = 0.d0 + vertNassimd = 0.d0 + + ! -------------------------------------------------------------------------- + ! DOM Remineralisation + ! -------------------------------------------------------------------------- + allocate(vertDONremin(nl-1), vertDOCremin(nl-1)) + vertDONremin = 0.d0 + vertDOCremin = 0.d0 + + ! -------------------------------------------------------------------------- + ! Temperature and Photosynthesis Tracking Variables + ! -------------------------------------------------------------------------- + + allocate(VTPhyCO2(nl-1), VTDiaCO2(nl-1)) + allocate(VTCphotLigLim_phyto(nl-1), VTCphotLigLim_diatoms(nl-1)) + allocate(VTCphot_phyto(nl-1), VTCphot_diatoms(nl-1)) + allocate(VTTemp_phyto(nl-1), VTTemp_diatoms(nl-1)) + allocate(VTqlimitFac_phyto(nl-1), VTqlimitFac_diatoms(nl-1)) + allocate(VTSi_assimDia(nl-1)) + + VTPhyCO2 = 0.d0 + VTDiaCO2 = 0.d0 + VTCphotLigLim_phyto = 0.d0 + VTCphotLigLim_diatoms = 0.d0 + VTCphot_phyto = 0.d0 + VTCphot_diatoms = 0.d0 + VTTemp_phyto = 0.d0 + VTTemp_diatoms = 0.d0 + VTqlimitFac_phyto = 0.d0 + VTqlimitFac_diatoms = 0.d0 + VTSi_assimDia = 0.d0 +end subroutine alloc_init_phyto_diags + +! ============================================================================== +! SUBROUTINE: alloc_init_cocco_diags +! Purpose: Allocate and initialize coccolithophore and Phaeocystis diagnostics +! ============================================================================== +subroutine alloc_init_cocco_diags(nl) + use recom_locvar + use recom_declarations + implicit none + + integer, intent(in) :: nl + + ! ---------------------------------------------------------------------- + ! Coccolithophores + ! ---------------------------------------------------------------------- + allocate(vertNPPc(nl-1), vertGPPc(nl-1), vertNNAc(nl-1), vertChldegc(nl-1)) + allocate(vertrespc(nl-1), vertdocexc(nl-1), vertaggc(nl-1)) + vertNPPc = 0.d0 + vertGPPc = 0.d0 + vertNNAc = 0.d0 + vertChldegc = 0.d0 + vertrespc = 0.d0 + vertdocexc = 0.d0 + vertaggc = 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 + + ! -------------------------------------------------------------------------- + ! Photosynthesis and Nitrogen Assimilation + ! -------------------------------------------------------------------------- + allocate(vertphotc(nl-1), vertphotp(nl-1)) + allocate(vertNassimc(nl-1), vertNassimp(nl-1)) + vertphotc = 0.d0 + vertphotp = 0.d0 + vertNassimc = 0.d0 + vertNassimp = 0.d0 + + ! -------------------------------------------------------------------------- + ! Temperature / photosynthesis tracking + ! -------------------------------------------------------------------------- + allocate(VTTemp_cocco(nl-1), VTTemp_phaeo(nl-1)) + allocate(VTCoccoCO2(nl-1), VTPhaeoCO2(nl-1)) + allocate(VTqlimitFac_cocco(nl-1), VTqlimitFac_phaeo(nl-1)) + allocate(VTCphotLigLim_cocco(nl-1),VTCphotLigLim_phaeo(nl-1)) + allocate(VTCphot_cocco(nl-1), VTCphot_phaeo(nl-1)) + VTTemp_cocco = 0.d0 + VTTemp_phaeo = 0.d0 + VTCoccoCO2 = 0.d0 + VTPhaeoCO2 = 0.d0 + VTqlimitFac_cocco = 0.d0 + VTqlimitFac_phaeo = 0.d0 + VTCphotLigLim_cocco = 0.d0 + VTCphotLigLim_phaeo = 0.d0 + VTCphot_cocco = 0.d0 + VTCphot_phaeo = 0.d0 +end subroutine alloc_init_cocco_diags + +! ============================================================================== +! SUBROUTINE: alloc_init_zoo_diags +! Purpose: Allocate and initialize zooplankton grazing diagnostics +! ============================================================================== +subroutine alloc_init_zoo_diags(nl) + use recom_locvar + use recom_declarations + implicit none + + integer, intent(in) :: nl + + ! -------------------------------------------------------------------------- + ! Mesozooplankton (always present when Grazing_detritus is on) + ! -------------------------------------------------------------------------- + allocate(vertgrazmeso_tot(nl-1), vertgrazmeso_n(nl-1), vertgrazmeso_d(nl-1)) + allocate(vertgrazmeso_det(nl-1), vertrespmeso(nl-1)) + vertgrazmeso_tot = 0.d0 + vertgrazmeso_n = 0.d0 + vertgrazmeso_d = 0.d0 + vertgrazmeso_det = 0.d0 + vertrespmeso = 0.d0 + + ! -------------------------------------------------------------------------- + ! Mesozooplankton Respiration + ! -------------------------------------------------------------------------- + allocate(vertmesocdis(nl-1)) + vertmesocdis = 0.d0 + + if (.not. enable_3zoo2det) return + + ! -------------------------------------------------------------------------- + ! 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 + + ! -------------------------------------------------------------------------- + ! Microzooplankton Dissolution + ! -------------------------------------------------------------------------- + allocate( vertmicrocdis(nl-1)) + vertmicrocdis = 0.d0 + + ! -------------------------------------------------------------------------- + ! Additional mesozooplankton arrays (3-zoo config) + ! -------------------------------------------------------------------------- + allocate(vertgrazmeso_mic(nl-1), vertgrazmeso_det2(nl-1)) + vertgrazmeso_mic = 0.d0 + vertgrazmeso_det2 = 0.d0 + + ! -------------------------------------------------------------------------- + ! 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 + + ! -------------------------------------------------------------------------- + ! Macrozooplankton Dissolution + ! -------------------------------------------------------------------------- + allocate(vertmacrocdis(nl-1)) + allocate(vertfastcdis(nl-1)) + vertmacrocdis = 0.d0 + vertfastcdis = 0.d0 + + if (.not. enable_coccos) return + + allocate(vertgrazmicro_c(nl-1), vertgrazmicro_p(nl-1)) + allocate(vertgrazmeso_c(nl-1), vertgrazmeso_p(nl-1)) + allocate(vertgrazmacro_c(nl-1), vertgrazmacro_p(nl-1)) + vertgrazmicro_c = 0.d0 + vertgrazmicro_p = 0.d0 + vertgrazmeso_c = 0.d0 + vertgrazmeso_p = 0.d0 + vertgrazmacro_c = 0.d0 + vertgrazmacro_p = 0.d0 + +end subroutine alloc_init_zoo_diags + +! ============================================================================== +! SUBROUTINE: alloc_init_bgc_diags +! Purpose: Allocate and initialize dissolution/remineralization diagnostics +! ============================================================================== +subroutine alloc_init_bgc_diags(nl) + use REcoM_declarations + implicit none + + integer, intent(in) :: nl + + allocate(vertDISSOC(nl-1), vertDISSON(nl-1), vertDISSOSi(nl-1)) + allocate(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 +end subroutine alloc_init_bgc_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 + + ! -------------------------------------------------------------------------- + ! Zooplankton Mortality / Dissolution + ! -------------------------------------------------------------------------- + mesocdis(1:nzmax,n) = vertmesocdis(1:nzmax) + + if (enable_3zoo2det) then + microcdis(1:nzmax,n) = vertmicrocdis(1:nzmax) + macrocdis(1:nzmax,n) = vertmacrocdis(1:nzmax) + fastcdis(1:nzmax,n) = vertfastcdis(1:nzmax) + endif + + ! -------------------------------------------------------------------------- + ! Photosynthesis and Nitrogen Assimilation + ! -------------------------------------------------------------------------- + photn(1:nzmax,n) = vertphotn(1:nzmax) + photd(1:nzmax,n) = vertphotd(1:nzmax) + Nassimn(1:nzmax,n) = vertNassimn(1:nzmax) + Nassimd(1:nzmax,n) = vertNassimd(1:nzmax) + + if (enable_coccos) then + photc(1:nzmax,n) = vertphotc(1:nzmax) + photp(1:nzmax,n) = vertphotp(1:nzmax) + Nassimc(1:nzmax,n) = vertNassimc(1:nzmax) + Nassimp(1:nzmax,n) = vertNassimp(1:nzmax) + endif + + ! -------------------------------------------------------------------------- + ! DOM Remineralisation + ! -------------------------------------------------------------------------- + DONremin(1:nzmax,n) = vertDONremin(1:nzmax) + DOCremin(1:nzmax,n) = vertDOCremin(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) + 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) + + ! -------------------------------------------------------------------------- + ! Zooplankton Mortality / Dissolution + ! -------------------------------------------------------------------------- + deallocate(vertmesocdis) + + if (enable_3zoo2det) then + deallocate(vertfastcdis) + deallocate(vertmicrocdis,vertmacrocdis) + endif + + ! -------------------------------------------------------------------------- + ! Photosynthesis and Nitrogen Assimilation + ! -------------------------------------------------------------------------- + deallocate(vertphotn, vertNassimn) + deallocate(vertphotd, vertNassimd) + + + ! -------------------------------------------------------------------------- + ! DOM Remineralisation + ! -------------------------------------------------------------------------- + deallocate(vertDONremin, vertDOCremin) + + 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) + + ! -------------------------------------------------------------------------- + ! Photosynthesis and Nitrogen Assimilation + ! -------------------------------------------------------------------------- + deallocate(vertphotc, vertNassimc) + deallocate(vertphotp, vertNassimp) + 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 + +! ============================================================================== +! SUBROUTINE: exchange_diags +! Purpose: MPI halo exchange for all active 2D/3D diagnostic fields +! ============================================================================== +subroutine exchange_diags(partit) + use recom_glovar + use recom_declarations + use MOD_PARTIT + use g_comm_auto + implicit none + + type(t_partit), intent(inout), target :: partit + + ! Net Primary / Gross Primary Production and N assimilation + call exchange_nod(NPPn, partit); call exchange_nod(GPPn, partit) + call exchange_nod(NNAn, partit); call exchange_nod(Chldegn, partit) + call exchange_nod(NPPd, partit); call exchange_nod(GPPd, partit) + call exchange_nod(NNAd, partit); call exchange_nod(Chldegd, 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 + + ! Mesozooplankton + call exchange_nod(grazmeso_tot, partit); call exchange_nod(grazmeso_n, partit) + call exchange_nod(grazmeso_d, partit); call exchange_nod(grazmeso_det, partit) + + if (enable_coccos) then + call exchange_nod(grazmeso_c, partit); call exchange_nod(grazmeso_p, partit) + endif + + 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); 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(grazmacro_c, partit); call exchange_nod(grazmacro_p, partit) + call exchange_nod(grazmicro_c, partit); call exchange_nod(grazmicro_p, partit) + endif + endif + +end subroutine exchange_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 fb1036fdf..654259aa3 100644 --- a/src/int_recom/recom_sinking.F90 +++ b/src/int_recom/recom_sinking.F90 @@ -140,7 +140,19 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1007 .or. & !idetn tracers%data(tr_num)%ID==1013 .or. & !idian tracers%data(tr_num)%ID==1025 ) then !idetz2n - call accum_benthos(n, tr_num, 1, 1, add_benthos_2d(n), area(1,n), dt, .true.) + 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 * @@ -148,21 +160,51 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1008 .or. & !idetc tracers%data(tr_num)%ID==1014 .or. & !idiac tracers%data(tr_num)%ID==1026 ) then !idetz2c - call accum_benthos(n, tr_num, 2, 2, add_benthos_2d(n), area(1,n), dt, .true.) + 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 * if( tracers%data(tr_num)%ID==1016 .or. & !idiasi tracers%data(tr_num)%ID==1017 .or. & !idetsi tracers%data(tr_num)%ID==1027 ) then !idetz2si - call accum_benthos(n, tr_num, 3, 3, add_benthos_2d(n), area(1,n), dt, .true.) + 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 * if( tracers%data(tr_num)%ID==1020 .or. & !iphycal tracers%data(tr_num)%ID==1021 .or. & !idetcal tracers%data(tr_num)%ID==1028 ) then !idetz2cal - call accum_benthos(n, tr_num, 4, 4, add_benthos_2d(n), area(1,n), dt, .true.) + 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 @@ -170,12 +212,30 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) 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 - call accum_benthos(n, tr_num, 0, 5, add_benthos_2d(n), area(1,n), dt, .false.) + + 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 - call accum_benthos(n, tr_num, 0, 6, add_benthos_2d(n), area(1,n), dt, .false.) + + 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 @@ -185,12 +245,28 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) 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 - call accum_benthos(n, tr_num, 0, 7, add_benthos_2d(n), area(1,n), dt, .false.) + + 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 - call accum_benthos(n, tr_num, 0, 8, add_benthos_2d(n), area(1,n), dt, .false.) + 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 @@ -208,30 +284,9 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) 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 -contains - -subroutine accum_benthos(n, tr_num, benthos_idx, flx_idx, add_val, area_surf, dt_local, do_benthos) - integer , intent(in) :: n, tr_num - integer , intent(in) :: benthos_idx, flx_idx - real(kind=WP), intent(in) :: add_val, area_surf, dt_local - logical , intent(in) :: do_benthos - - if (do_benthos) then - Benthos(n,benthos_idx)= Benthos(n,benthos_idx) + add_val - end if - - if (use_MEDUSA) then - SinkFlx_tr(n,flx_idx,tr_num) = SinkFlx_tr(n,flx_idx,tr_num) + add_val / area_surf / dt_local - endif - if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then - Benthos_tr(n,flx_idx,tr_num)= Benthos_tr(n,flx_idx,tr_num) + add_val - endif -end subroutine accum_benthos - end subroutine ver_sinking_recom_benthos ! ! @@ -326,16 +381,22 @@ subroutine diff_ver_recom_expl(tr_num, tracers, partit, mesh) 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 *** @@ -540,7 +601,7 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) ! 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 end if @@ -694,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 @@ -811,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 diff --git a/src/int_recom/recom_sms.F90 b/src/int_recom/recom_sms.F90 index 67067018a..7893f1989 100644 --- a/src/int_recom/recom_sms.F90 +++ b/src/int_recom/recom_sms.F90 @@ -31,7 +31,6 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & use mvars use mdepth2press use gsw_mod_toolbox, only: gsw_sa_from_sp,gsw_ct_from_pt,gsw_rho - use, intrinsic :: ieee_arithmetic, only: ieee_is_nan implicit none type(t_dyn) , intent(inout), target :: dynamics @@ -41,6 +40,7 @@ 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 @@ -101,6 +101,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & 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 @@ -111,7 +112,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & PhyCalc, & ! [mmol/m3] Phytoplankton calcite DetCalc, & ! [mmol/m3] Detrital calcite FreeFe, & ! [mmol/m3] Free iron - O2 ! [mmol/m3] Dissolved oxygen + O2, & ! [mmol/m3] Dissolved oxygen + DICremin ! tracer for DIC remineralization (for tracking as diagnostic (added by Sina) ! Coccolithophore variables (conditionally used based on namelist) real(kind=8) :: & @@ -411,11 +413,13 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! DIC : Dissolved inorganic carbon (CO2 + HCO3- + CO3--) [mmolC m-3] ! ALK : Total alkalinity [meq m-3] ! O2 : Dissolved oxygen [mmolO2 m-3] + ! DICremin : Tracer for DIC remineralization (added by Sina) !----------------------------------------------------------------------- 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)) + DICremin = max(tiny, state(k, idicremin) + sms(k, idicremin)) !----------------------------------------------------------------------- ! DISSOLVED ORGANIC MATTER @@ -430,6 +434,11 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & DON = max(tiny, state(k, idon) + sms(k, idon)) EOC = max(tiny, state(k, idoc) + sms(k, idoc)) + if (enable_R2OMIP) then + DOCt = max(tiny, state(k,idoct) + sms(k, idoct)) ! R2OMIP + else + DOCt = 0.0_WP + end if !----------------------------------------------------------------------- ! SMALL PHYTOPLANKTON !----------------------------------------------------------------------- @@ -987,8 +996,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & 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)) + 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 @@ -1620,6 +1629,25 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & endif + 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 !=============================================================================== @@ -1950,6 +1978,9 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! 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) @@ -1977,6 +2008,9 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & 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 @@ -1999,6 +2033,9 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & 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 @@ -2015,6 +2052,9 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & 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 @@ -3970,6 +4010,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !--------------------------------------------------------------------------- ! Microbial degradation of dissolved organic carbon + rho_C1 * arrFunc * O2Func * EOC & ! Temperature and O2 dependent + + rho_C1t * DOCt * is_R2OMIP & ! --> Remineralization of terrestrial DOC ! R2OMIP !--------------------------------------------------------------------------- ! SOURCES: Zooplankton Respiration (increases DIC) !--------------------------------------------------------------------------- @@ -4235,7 +4276,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! SOURCES: Direct Transfer from Grazing !----------------------------------------------------------------------- ! All grazed material enters detritus (no detritus grazing) - + grazingFlux_phy3 & ! Microzooplankton->small phyto + + grazingFlux_phy3 & ! Microzooplankton->small phyto !OG added + grazingFlux_dia3 & ! Microzooplankton->diatoms + grazingFlux_Cocco3 * is_coccos & ! Microzooplankton->coccoliths + grazingFlux_Phaeo3 * is_coccos & ! Microzooplankton->Phaeocystis @@ -4360,7 +4401,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! SINKS: Detritus Consumption (C-basis) !----------------------------------------------------------------------- - grazingFlux_Det * recipDet * grazEff & ! Mesozooplankton - - grazingFlux_Det2 * recipDet * grazEff2 & ! Macrozooplankton + - grazingFlux_Det2 * recipDet * grazEff2 & ! Macrozooplankton ! corrected recipDet2 -> recipDet !----------------------------------------------------------------------- ! SINKS: Remineralization !----------------------------------------------------------------------- @@ -4394,6 +4435,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! SINKS: Detritus Consumption (C-basis) !----------------------------------------------------------------------- - grazingFlux_Det * recipDet * grazEff & + ! - grazingFlux_Det2 * recipDet2 * grazEff & !!!!!! CHECK !----------------------------------------------------------------------- ! SINKS: Remineralization !----------------------------------------------------------------------- @@ -4739,7 +4781,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !----------------------------------------------------------------------- + grazingFlux_phy2 * (1.d0 - grazEff2) & ! Small phytoplankton + grazingFlux_dia2 * (1.d0 - grazEff2) & ! Diatoms - + grazingFlux_Cocco * (1.d0 - grazEff) * is_coccos & ! Coccoliths (meso) + + 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) @@ -4878,7 +4920,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & + 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 & + + 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) & @@ -5033,7 +5075,12 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !--------------------------------------------------------------------------- - rho_c1 * arrFunc * O2Func * EOC & ! Bacterial respiration ) * dt_b + sms(k,idoc) - + if (enable_R2OMIP) then + ! R2OMIP - terrestrial DOC + sms(k,idoct) = ( & + - rho_C1t * DOCt & + ) * dt_b + sms(k,idoct) + end if !=============================================================================== ! 21. DIATOM NITROGEN (DiaN) !=============================================================================== @@ -5700,6 +5747,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! SINKS: Heterotrophic Respiration and Remineralization !--------------------------------------------------------------------------- - rho_C1 * arrFunc * O2Func * EOC & ! DOC remineralization + - rho_C1t * DOCt * is_R2OMIP & - hetRespFlux & ! Mesozooplankton - Zoo2RespFlux * is_3zoo2det & ! Macrozooplankton - MicZooRespFlux * is_3zoo2det & ! Microzooplankton @@ -5707,6 +5755,14 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! Note: redO2C converts carbon-based rates to oxygen equivalents ! using the Redfield ratio (typically ~170/122 = 1.39 mol O2/mol C) + !=============================================================================== + ! 37. DIC remineralzation tracer to track remineralization as an diagnostics + !=============================================================================== + ! idicremin : Tracer for remineralization diagnostics (added by Sina) + sms(k,idicremin) = ( & + + rho_c1 * arrFunc * O2Func * EOC & + ) * dt_b + sms(k,idicremin) + if (ciso) then !=========================================================================== @@ -6225,6 +6281,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & end if ! ciso_14 end if ! ciso + !------------------------------------------------------------------------------- ! DIAGNOSTIC ACCUMULATION INITIALIZATION !------------------------------------------------------------------------------- @@ -6413,7 +6470,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ) * recipbiostep endif - !=========================================================================== + !=========================================================================== ! CHLOROPHYLL DEGRADATION RATES !=========================================================================== ! Tracks chlorophyll turnover rates (photodamage + senescence) @@ -6463,6 +6520,332 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ) * 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 + + if (Grazing_detritus) then + +!=========================================================================== +! 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 + + if (enable_3zoo2det) then + vertgrazmeso_tot(k) = vertgrazmeso_tot(k) + ( & + + GrazingFlux_DetZ2 * recipDet2 * grazEff & ! Detritus 2 + + grazingFlux_miczoo * recipQZoo3 * grazEff & ! Microzooplankton + ) * recipbiostep + endif + + ! 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 + + ! Diatom mortality + vertgrazmeso_d(k) = vertgrazmeso_d(k) + ( & + + grazingFlux_dia * recipQuota_dia & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore mortality + vertgrazmeso_c(k) = vertgrazmeso_c(k) + ( & + + grazingFlux_Cocco * recipQuota_cocco & + ) * recipbiostep + + ! Phaeocystis mortality + vertgrazmeso_p(k) = vertgrazmeso_p(k) + ( & + + grazingFlux_Phaeo * recipQuota_Phaeo & + ) * recipbiostep + endif + + ! 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 + + + +!=========================================================================== +! 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 + + ! 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 + +!=========================================================================== +! 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 * is_R2OMIP & ! Bacterial respiration / remineralization of terrestriel DOC + ) * recipbiostep + + vertREMOCt(k) = vertREMOCt(k) + ( & + + rho_C1t * DOCt * is_R2OMIP & ! Bacterial respiration / remineralization of terrestriel DOC + ) * recipbiostep + + vertREMON(k) = vertREMON(k) + ( & + + rho_N * arrFunc * O2Func * DON & ! Bacterial respiration / remineralization + ) * recipbiostep + !=========================================================================== ! ZOOPLANKTON RESPIRATION !=========================================================================== @@ -6537,6 +6920,28 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & + 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 !=========================================================================== @@ -6594,6 +6999,42 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ) * 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 !=========================================================================== @@ -6696,6 +7137,32 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & + 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 !=========================================================================== @@ -6861,6 +7328,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !=========================================================================== ! 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] @@ -6882,13 +7350,17 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !--------------------------------------------------------------------------- ! Calculate N remineralization flux [mmolN m-2 day-1] - call update_benthos_decay(decayRateBenN, 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] @@ -6909,13 +7381,17 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !--------------------------------------------------------------------------- ! Calculate C remineralization flux [mmolC m-2 day-1] - call update_benthos_decay(decayRateBenC, 2) + 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] @@ -6938,13 +7414,17 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !--------------------------------------------------------------------------- ! Calculate Si dissolution flux [mmolSi m-2 day-1] - call update_benthos_decay(decayRateBenSi, 3) + 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] @@ -6970,7 +7450,10 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !--------------------------------------------------------------------------- ! Calculate calcite dissolution flux [mmolC m-2 day-1] - call update_benthos_decay(calc_diss_ben, 4) + 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 @@ -6997,7 +7480,10 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! Calculate 13C remineralization flux ! Ignores isotopic fractionation during remineralization (alpha ≈ 1) - call update_benthos_decay(alpha_dcal_13 * decayRateBenC, 5) + decayBenthos(5) = alpha_dcal_13 * decayRateBenC * LocBenthos(5) + + ! Update benthic 13C pool + LocBenthos(5) = LocBenthos(5) - decayBenthos(5) * dt_b !======================================================================= ! Carbon-13 Calcite Dissolution @@ -7011,7 +7497,10 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !----------------------------------------------------------------------- ! Calculate 13C calcite dissolution flux - call update_benthos_decay(calc_diss_13, 6) + decayBenthos(6) = calc_diss_13 * LocBenthos(6) + + ! Update benthic 13C-calcite pool + LocBenthos(6) = LocBenthos(6) - decayBenthos(6) * dt_b if (ciso_14) then @@ -7033,7 +7522,10 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! Calculate 14C remineralization flux ! Ignores isotopic fractionation during remineralization - call update_benthos_decay(alpha_dcal_14 * decayRateBenC, 7) + 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 @@ -7047,7 +7539,10 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !--------------------------------------------------------------- ! Calculate 14C calcite dissolution flux - call update_benthos_decay(calc_diss_14, 8) + decayBenthos(8) = calc_diss_14 * LocBenthos(8) + + ! Update benthic 14C-calcite pool + LocBenthos(8) = LocBenthos(8) - decayBenthos(8) * dt_b else !--------------------------------------------------------------- @@ -7069,16 +7564,6 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & end do ! Main time loop ends -contains - -subroutine update_benthos_decay(rate, idx) - real(kind=8), intent(in) :: rate - integer , intent(in) :: idx - - decayBenthos(idx) = rate * LocBenthos(idx) - LocBenthos(idx) = LocBenthos(idx) - decayBenthos(idx) * dt_b -end subroutine update_benthos_decay - end subroutine REcoM_sms !------------------------------------------------------------------------------- diff --git a/src/io_fesom_file.F90 b/src/io_fesom_file.F90 index 1706f0cec..8eacfc2f6 100644 --- a/src/io_fesom_file.F90 +++ b/src/io_fesom_file.F90 @@ -221,6 +221,11 @@ subroutine read_and_scatter_variables(this) end if do lvl=1, nlvl + +#ifdef ENABLE_ALBEDO_INTELMPI_WORKAROUNDS + call MPI_Barrier(this%comm, mpierr) +#endif + if(this%is_iorank()) then t_start = MPI_Wtime() if(is_2d) then @@ -313,6 +318,11 @@ subroutine gather_and_write_variables(this) end if do lvl=1, nlvl + +#ifdef ENABLE_ALBEDO_INTELMPI_WORKAROUNDS + call MPI_Barrier(this%comm, mpierr) +#endif + ! the data from our pointer is not contiguous (if it is 3D data), so we can not pass the pointer directly to MPI laux = var%local_data_copy(lvl,:) ! todo: remove this buffer and pass the data directly to MPI (change order of data layout to be levelwise or do not gather levelwise but by columns) diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index e9f334745..debd526d4 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -31,13 +31,12 @@ module io_MEANDATA public :: print_per_stream_costs ! Sub-decomposition timers for FESOM `output`. Accumulated per-rank by the - ! output() routine; reduced + printed once at finalize from fesom_module. - ! Cost is one MPI_Wtime() pair per region per call — negligible. - real(WP), public, save :: rtime_om_update_means = 0.0_WP !< update_means accumulator (every step) - real(WP), public, save :: rtime_om_streamloop = 0.0_WP !< per-stream loop incl. write_mean dispatch - real(WP), public, save :: rtime_om_pack = 0.0_WP !< Fortran nested-loop pack from local_values_*_copy → tmp2/tmp3 - real(WP), public, save :: rtime_om_mask = 0.0_WP !< io_xios_apply_wet_* / apply_ice_mask_* full-array scans - real(WP), public, save :: rtime_om_xsend = 0.0_WP !< pure io_xios_send_* (xios_send_field) call + ! output() routine; reduced and printed once at finalize from fesom_module. + real(WP), public, save :: rtime_om_update_means = 0.0_WP + real(WP), public, save :: rtime_om_streamloop = 0.0_WP + real(WP), public, save :: rtime_om_pack = 0.0_WP + real(WP), public, save :: rtime_om_mask = 0.0_WP + real(WP), public, save :: rtime_om_xsend = 0.0_WP ! !-------------------------------------------------------------------------------------------- ! @@ -73,7 +72,6 @@ module io_MEANDATA integer :: dimID(2), dimvarID(2), varID integer :: freq=1 character :: freq_unit='m' - real(kind=WP) :: rtime_per_stream=0._WP !< cumulative wall in this stream's write_mean dispatch over the run; printed sorted at finalize logical :: is_in_use=.false. logical :: is_elem_based = .false. logical :: flip @@ -99,16 +97,7 @@ module io_MEANDATA ! !-------------------------------------------------------------------------------------------- ! - ! Wrapper holding a pointer to a heap-allocated Meandata. io_stream is an - ! array of these wrappers so the backing array can be grown via move_alloc - ! without moving the Meandata targets themselves: existing entry=>io_stream(i)%p - ! pointers stay valid across resizes, and the Meandata's final destructor is - ! not triggered (finalisation only runs on explicit deallocate of %p). - type :: MeandataPtr - type(Meandata), pointer :: p => null() - end type MeandataPtr - type(MeandataPtr), allocatable, save :: io_stream(:) - integer, parameter :: IO_STREAM_INITIAL_CAPACITY = 32 + type(Meandata), save, target :: io_stream(250) ! todo: find a way to increase the array withhout move_alloc to keep the derived types in Meandata intact integer, save :: io_NSTREAMS=0 real(kind=WP) :: ctime !current time in seconds from the beginning of the year ! @@ -121,7 +110,7 @@ module io_MEANDATA character(len=1), save :: filesplit_freq='y' integer, save :: compression_level=0 type io_entry - CHARACTER(len=20) :: id ='unknown ' + CHARACTER(len=15) :: id ='unknown ' INTEGER :: freq =0 CHARACTER :: unit ='' INTEGER :: precision =0 @@ -202,7 +191,6 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) use o_mixing_KPP_mod use g_backscatter use diagnostics - use cmor_variables_diag use g_forcing_arrays #if defined (__cvmix) use g_cvmix_tke @@ -241,117 +229,7 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) #include "associate_mesh_ass.h" !___________________________________________________________________________ - ! OPEN and read namelist for I/O. - ! When XIOS is driving output, ignore namelist.io entirely: register every - ! known stream id at freq=1/unit='s'/precision=4 and let XIOS's XML decide - ! which of those are actually written, at what cadence, with what averaging. - ! XIOS silently drops fields not declared in field_def_*.xml, so registering - ! a superset is safe. -#if defined(__XIOS) - if (io_xios_is_on()) then - ! Register ice-concentration pointer for sender-side masking of - ! ice-tagged XIOS fields (see io_xios_apply_ice_mask_*). - call io_xios_set_ice_conc(ice%data(1)%values, mesh%elem2D_nodes) - ! Register wet/bottom pointers for sender-side masking of ocean - ! fields (see io_xios_apply_wet_*). - call io_xios_set_wet_ptrs(mesh%ulevels_nod2D, mesh%nlevels_nod2D, & - mesh%ulevels, mesh%nlevels, mesh%nl) - block - character(len=20), parameter :: xios_ids(*) = (/ character(len=20) :: & - "aFe ", "age ", "aggc ", & - "aggd ", "aggn ", "a_ice ", & - "alb ", "alpha ", "aN ", & - "apnd ", "atmice_x ", "atmice_y ", & - "atmoce_x ", "atmoce_y ", "Av ", & - "benC ", "benCalc ", "benN ", & - "benSi ", "beta ", "bolus_u ", & - "bolus_v ", "bolus_w ", "calcdiss ", & - "calcif ", "cfl_z ", "Chldegc ", & - "Chldegd ", "Chldegn ", "CO2f ", & - "curl_surf ", "dens_flux ", "d_eta ", & - "dhe ", "dMOC ", "docexc ", & - "docexd ", "docexn ", "dpCO2s ", & - "DVD ", "dyngrarea ", "dyngrice ", & - "dyngrsnw ", "elevat_ice ", "enthalpy ", & - "eps11 ", "eps12 ", "eps22 ", & - "evap ", "fer_C ", "fer_gammax ", & - "fer_gammay ", "fer_K ", "fer_scal ", & - "fer_tapfac ", "fh ", "fh_lat ", & - "fh_lwr ", "fh_lwrout ", "fh_radtot ", & - "fh_sen ", "fh_swr ", "flice ", & - "FORC ", "fw ", "fw_ice ", & - "fw_snw ", "GPPc ", "GPPd ", & - "GPPn ", "h2o16 ", "h2o16_ice ", & - "h2o18 ", "h2o18_ice ", "hbar ", & - "hbar_old ", "hc ", "hc300m ", & - "hc700m ", "hDo16 ", "hDo16_ice ", & - "helem ", "h_ice ", "hnode ", & - "hnode_new ", "Hp ", "hpnd ", & - "h_snow ", "icb ", "iceoce_x ", & - "iceoce_y ", "ice_rejectsalt ", "IDEMIX ", & - "inv_areamass ", "ipnd ", "ist ", & - "kpp_obldepth ", "kpp_sbuoyflx ", "Kv ", & - "landice ", "lwr ", "metric_fac ", & - "m_ice ", "MLD1 ", "MLD2 ", & - "MLD3 ", "m_snow ", "N2 ", & - "NNAc ", "NNAd ", "NNAn ", & - "NPPc ", "NPPc3D ", "NPPd ", & - "NPPd3D ", "NPPn ", "O2f ", & - "opottempdiff ", "opottemprmadvect ", "opottemptend ", & - "osaltdiff ", "osaltrmadvect ", "osalttend ", & - "otracers ", "PAR ", "pbo ", & - "pCO2s ", "pgf_x ", "pgf_y ", & - "prec ", "qcon ", "qres ", & - "qsi ", "qso ", "qsr ", & - "realsalt ", "redi_K ", "relaxsalt ", & - "respc ", "respd ", "respmacro ", & - "respmeso ", "respmicro ", "respn ", & - "rhs_a ", "rhs_m ", "rsdoabsorb ", & - "runoff ", "runoff_liquid ", "runoff_solid ", & - "salt ", "sgm11 ", "sgm12 ", & - "sgm22 ", "shum ", "siarean ", & - "siareas ", "siextentn ", "siextents ", & - "sigma0 ", "sigma_x ", "sigma_y ", & - "sivoln ", "sivols ", "slopetap_x ", & - "slopetap_y ", "slopetap_z ", "slope_x ", & - "slope_y ", "slope_z ", "snow ", & - "soga ", "sos ", "SPLIT-EXPL ", & - "ssh ", "ssh_rhs ", "ssh_rhs_old ", & - "sss ", "sst ", "strength_ice ", & - "swice ", "swr ", "tair ", & - "temp ", "thdgrarea ", "thdgrice ", & - "thdgrsnw ", "thetaoga ", "TIDAL ", & - "TKE ", "tos ", "TRGRD_XYZ ", & - "t_star ", "twice ", "tx_sur ", & - "ty_sur ", "u ", "u_back_tend ", & - "u_dis_tend ", "uice ", "unod ", & - "unod_sfc ", "u_rhs_ice ", "u_total_tend ", & - "UVW_SQR ", & - "uwice ", "uwind ", "v ", & - "v_back_tend ", "v_dis_tend ", "vice ", & - "virtsalt ", "vnod ", "vnod_sfc ", & - "volo ", & - "v_rhs_ice ", "v_total_tend ", "vve_5 ", & - "vwice ", "vwind ", "w " /) - integer :: k - if (mype==0) WRITE(*,*) 'XIOS mode: skipping namelist.io; registering all ', & - size(xios_ids), ' known streams. XML decides output.' - io_listsize = size(xios_ids) - vec_autorotate = .FALSE. - lnextGEMS = .FALSE. - nlev_upper = 1 - filesplit_freq = 'y' - compression_level = 0 - allocate(io_list(io_listsize)) - do k = 1, io_listsize - io_list(k)%id = xios_ids(k) - io_list(k)%freq = 1 - io_list(k)%unit = 's' - io_list(k)%precision = 4 - end do - end block - else -#endif + ! OPEN and read namelist for I/O open( unit=nm_io_unit, file='namelist.io', form='formatted', access='sequential', status='old', iostat=iost ) if (iost == 0) then if (mype==0) WRITE(*,*) ' file : ', 'namelist.io',' open ok' @@ -370,9 +248,6 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) allocate(io_list(io_listsize)) READ(nm_io_unit, nml=nml_list, iostat=iost ) close(nm_io_unit ) -#if defined(__XIOS) - end if -#endif !___________________________________________________________________________ ! TODO: unknown variable found then write clearly in log, saves lot of frustration. @@ -401,85 +276,6 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) CASE ('qsr ') call def_stream(nod2D, myDim_nod2D,'qsr' , 'solar radiation' , 'W/s^2' , qsr_c(:) , io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) -! CMOR diagnostics for CMIP6/CMIP7 (require ldiag_cmor=.true.) -CASE ('tos ') - if (ldiag_cmor) then - call def_stream(nod2D, myDim_nod2D, 'tos', 'sea surface temperature', 'degC', tos(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh, "Sea surface temperature (CMOR)") - end if -CASE ('sos ') - if (ldiag_cmor) then - call def_stream(nod2D, myDim_nod2D, 'sos', 'sea surface salinity', 'psu', sos(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh, "Sea surface salinity (CMOR)") - end if -CASE ('pbo ') - if (ldiag_cmor) then - call def_stream(nod2D, myDim_nod2D, 'pbo', 'sea water pressure at sea floor', 'Pa', pbo(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh, "Sea water pressure at sea floor") - end if -CASE ('opottemptend') - if (ldiag_cmor) then - call def_stream(nod2D, myDim_nod2D, 'opottemptend', 'tendency of sea water potential temperature', 'W/m2', opottemptend(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh, "Tendency of sea water potential temperature expressed as heat content") - end if -CASE ('osalttend ') - if (ldiag_cmor) then - call def_stream(nod2D, myDim_nod2D, 'osalttend', 'tendency of sea water salinity', 'psu m/s', osalttend(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh, "Tendency of sea water salinity expressed as salt content") - end if -CASE ('opottemprmadvect') - if (ldiag_cmor) then - call def_stream(nod2D, myDim_nod2D, 'opottemprmadvect', 'temperature tendency due to advection', 'W/m2', opottemprmadvect(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh, "Tendency of sea water potential temperature expressed as heat content due to residual mean advection") - end if -CASE ('opottempdiff') - if (ldiag_cmor) then - call def_stream(nod2D, myDim_nod2D, 'opottempdiff', 'temperature tendency due to diffusion', 'W/m2', opottempdiff(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh, "Tendency of sea water potential temperature expressed as heat content due to parameterized dianeutral mixing") - end if -CASE ('osaltrmadvect') - if (ldiag_cmor) then - call def_stream(nod2D, myDim_nod2D, 'osaltrmadvect', 'salinity tendency due to advection', 'psu m/s', osaltrmadvect(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh, "Tendency of sea water salinity expressed as salt content due to residual mean advection") - end if -CASE ('osaltdiff ') - if (ldiag_cmor) then - call def_stream(nod2D, myDim_nod2D, 'osaltdiff', 'salinity tendency due to diffusion', 'psu m/s', osaltdiff(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh, "Tendency of sea water salinity expressed as salt content due to parameterized dianeutral mixing") - end if -CASE ('rsdoabsorb') - if (ldiag_cmor) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'rsdoabsorb', 'shortwave flux absorbed in ocean layer', 'W/m2', rsdoabsorb(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - end if - -! CMOR 0D (scalar) diagnostics for CMIP6/CMIP7 (require ldiag_cmor=.true.) -CASE ('volo ') - if (ldiag_cmor) then - call def_stream0D('volo', 'sea water volume', 'm3', volo, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, "Total volume of liquid sea water") - end if -CASE ('soga ') - if (ldiag_cmor) then - call def_stream0D('soga', 'global mean sea water salinity', 'psu', soga, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, "Global mean sea water salinity") - end if -CASE ('thetaoga ') - if (ldiag_cmor) then - call def_stream0D('thetaoga', 'global mean sea water potential temperature', 'degC', thetaoga, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, "Global mean sea water potential temperature") - end if -CASE ('siarean ') - if (ldiag_cmor) then - call def_stream0D('siarean', 'sea ice area northern hemisphere', '1e12 m2', siarean, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, "Total area of sea ice in the Northern hemisphere") - end if -CASE ('siareas ') - if (ldiag_cmor) then - call def_stream0D('siareas', 'sea ice area southern hemisphere', '1e12 m2', siareas, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, "Total area of sea ice in the Southern hemisphere") - end if -CASE ('siextentn ') - if (ldiag_cmor) then - call def_stream0D('siextentn', 'sea ice extent northern hemisphere', '1e12 m2', siextentn, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, "Total area of sea ice extent in the Northern hemisphere") - end if -CASE ('siextents ') - if (ldiag_cmor) then - call def_stream0D('siextents', 'sea ice extent southern hemisphere', '1e12 m2', siextents, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, "Total area of sea ice extent in the Southern hemisphere") - end if -CASE ('sivoln ') - if (ldiag_cmor) then - call def_stream0D('sivoln', 'sea ice volume northern hemisphere', '1e9 m3', sivoln, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, "Total volume of sea ice in the Northern hemisphere") - end if -CASE ('sivols ') - if (ldiag_cmor) then - call def_stream0D('sivols', 'sea ice volume southern hemisphere', '1e9 m3', sivols, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, "Total volume of sea ice in the Southern hemisphere") - end if ! 2d ssh diagnostic variables CASE ('ssh_rhs ') @@ -819,175 +615,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) + 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 ('benN ') +CASE ('riverDIN ') 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, '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 ('benC ') +CASE ('riverDOCsl ') 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, '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 ('benSi ') +CASE ('riverDOCl ') 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, '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 ('benCalc ') +CASE ('riverPOC ') 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, 'riverPOC','riverine POC input','mmolC/m2/s', RiverPOC2D(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -! ciso -CASE ('benC_13 ') + +CASE ('riverDFe ') if (use_REcoM) then - if (ciso) then - call def_stream(nod2D, myDim_nod2D, 'benC_13','Benthos Carbon-13','mmol/m2', Benthos(:,5), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - end if + 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 -CASE ('benC_14 ') + + +! ===================================================================== +! 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 - if (ciso) then - call def_stream(nod2D, myDim_nod2D, 'benC_14','Benthos Carbon-14','mmol/m2', Benthos(:,6), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - end if + 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 ('benCalc_13') + +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 - if (ciso) then - call def_stream(nod2D, myDim_nod2D, 'benCalc_13','Benthos calcite-13','mmol/m2', Benthos(:,7), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - end if + 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 ('benCalc_14') + +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 - if (ciso) then - call def_stream(nod2D, myDim_nod2D, 'benCalc_14','Benthos calcite-14','mmol/m2', Benthos(:,8), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - end if + 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 -!ciso + +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) + end if + +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, & + 'denb', 'Benthic denitrification rate', 'mmol/m2', DenitBen(:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +! ===================================================================== +! 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, & + '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 ('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, & + '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 ('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, & + '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 ('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, & + '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 + +! ===================================================================== +! 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, & + '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) + 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 ('NPPd ') +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, '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, & + '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 ('GPPn ') +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, '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, & + '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 ('GPPd ') +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, '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, & + 'ChlDegn', 'Chlorophyll degradation nanophytoplankton', '1/d', Chldegn, & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -CASE ('NNAn ') +! --------------------------------------------------------------------- +! 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, '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, & + '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 ('NNAd ') +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, '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, & + '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 ('Chldegn ') +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, '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, & + '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 - endif + 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 + +! --------------------------------------------------------------------- +! 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)', diags2D(:,9), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, mesh) ! NEW - 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) ! Phaeocystis + 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)', diags2D(:,10), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, mesh) ! NEW - 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) ! Phaeocystis + 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)', diags2D(:,11), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, mesh) ! NEW - 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) ! Phaeocystis + 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, 'GNAp','Gross N-assimilation phaeocystis','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, 'ChlDegp','Chlorophyll degradation phaeocystis','1/d', Chldegp, io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! Phaeocystis + 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 -#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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< !___________________________________________________________________________________________________________________________________ @@ -998,269 +1680,1041 @@ 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 + 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/), & + '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') - 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) + ! ===================================================================== + ! 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') - 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) + ! ===================================================================== + ! 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 ') - 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) ! Phaeocystis - endif + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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/), 'docexp','DOC excretion by phaeocystis', 'mmolC/(m2*d)', docexp(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! Phaeocystis + 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 ') - 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) ! Phaeocystis - endif + ! ===================================================================== + ! 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/m3/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/m3/d', NPPd3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif CASE ('NPPc3D ') - 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 + ! ===================================================================== + ! 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/m3/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/), 'NPPp3D','Net primary production of phaeocystis', 'mmolC/(m2*d)', NPPp3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! Phaeocystis + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), & + 'NPPp3D', 'Net primary production of phaeocystis', 'mmolC/m3/d', NPPp3D(:,:), & + io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif +! ===================================================================== +! TEMPERATURE EFFECTS ON PHOTOSYNTHESIS +! Description: Temperature-dependent growth rate modifiers +! ===================================================================== + CASE ('TTemp_diatoms ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'TTemp_diatoms','Temperature dependence of diatoms PS', 'per day',TTemp_diatoms(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - endif + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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 ') - 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 + ! ===================================================================== + ! 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, "(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 - 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 - else if (tracers%data(j)%ID==1002) then ! NOTE Divide tracers%work%tra_advvert(:,:,j) by dt + + + 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/s]', tracers%work%tra_advhoriz(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + 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/s]', tracers%work%tra_advvert(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + 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/s]', tracers%work%tra_diff_part_hor_redi(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + 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 (.not. tracers%data(j)%i_vert_diff) then + 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/s]', tracers%work%tra_diff_part_ver_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + 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/s]', tracers%work%tra_diff_part_ver_redi_expl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + 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/s]', tracers%work%tra_diff_part_ver_impl(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + 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/s]', tracers%work%tra_recom_sms(:,:,j), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + 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 @@ -1268,8 +2722,38 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) 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) @@ -1285,6 +2769,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) @@ -1295,6 +2782,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) @@ -1305,6 +2795,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) @@ -1315,6 +2808,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) @@ -1335,6 +2832,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) @@ -1345,6 +2846,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) @@ -1365,75 +2903,253 @@ 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/), 'PhaeoN', 'PhaeoN', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW + 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/), 'PhaeoC', 'PhaeoC', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW + 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) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoChl', 'PhaeoChl', '[mg/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW + 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) 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 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 + + else if (tracers%data(j)%ID==1037) 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) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'DICremin', 'DICremin', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! DICremin tracer (added by Sina) endif + + ! ===================================================================== + ! Tracer ID 1038: Only in FULL model configuration with rivers + ! This is Terrestrial DOC + ! ===================================================================== + else if (tracers%data(j)%ID==1038) 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 @@ -1464,10 +3180,8 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) end do -CASE ('dens_insitu') - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'dens_insitu', 'In-situ density anomaly', 'kg/m3', density_m_rho0(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) -CASE ('dens_sigma0') - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'dens_sigma0', 'Potential density anomaly with respect to srf.', 'kg/m3', density_sigma0(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) +CASE ('sigma0 ') + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'sigma0', 'potential density', 'kg/m3', density_m_rho0(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) !---wiso-code !___________________________________________________________________________________________________________________________________ @@ -1512,10 +3226,6 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/),'unod', 'zonal velocity at nodes', 'm/s', dynamics%uvnode(1,:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) CASE ('vnod ') call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/),'vnod', 'meridional velocity at nodes', 'm/s', dynamics%uvnode(2,:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) -CASE ('unod_sfc ') - call def_stream(nod2D, myDim_nod2D, 'unod_sfc', 'zonal surface velocity at nodes', 'm/s', dynamics%uvnode(1,1,1:myDim_nod2D), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) -CASE ('vnod_sfc ') - call def_stream(nod2D, myDim_nod2D, 'vnod_sfc', 'meridional surface velocity at nodes', 'm/s', dynamics%uvnode(2,1,1:myDim_nod2D), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) CASE ('w ') call def_stream((/nl, nod2D/), (/nl, myDim_nod2D/), 'w', 'vertical velocity', 'm/s', dynamics%w(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) CASE ('Av ') @@ -1617,8 +3327,8 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) if (Fer_GM) call def_stream((/std_dens_N, nod2D /), (/std_dens_N, myDim_nod2D/), 'std_dens_DIVbolus', 'm3/s', 'm3/s' ,std_dens_DIV_fer(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) call def_stream((/std_dens_N, elem2D/), (/std_dens_N, myDim_elem2D/), 'std_dens_Z', 'm', 'm' ,std_dens_Z(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) call def_stream((/std_dens_N, elem2D/), (/std_dens_N, myDim_elem2D/), 'std_dens_H' , 'density thickness' , 'm' , std_dens_H(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - call def_stream((/nl-1, nod2D /), (/nl-1, myDim_nod2D /), 'density_dMOC', 'density' , 'kg/m3', density_dmoc(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - call def_stream(elem2D, myDim_elem2D , 'density_flux_e', 'density flux at elems ', 'm/s', dens_flux_e(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream((/nl-1, nod2D /), (/nl-1, myDim_nod2D /), 'density_dMOC', 'density' , 'm', density_dmoc(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(elem2D, myDim_elem2D , 'density_flux_e', 'density flux at elems ', 'm', dens_flux_e(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if !_______________________________________________________________________________ @@ -1739,13 +3449,13 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream(nod2D , myDim_nod2D , 'cd', 'wind drag coef. ' , '', cd_atm_oce_arr(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) call def_stream(nod2D , myDim_nod2D , 'ch', 'transfer coeff. sensible heat', '', ch_atm_oce_arr(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) call def_stream(nod2D , myDim_nod2D , 'ce', 'transfer coeff. evaporation ' , '', ce_atm_oce_arr(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) -#if defined (__oasis) || defined (__yac) +#if defined (__oasis) call def_stream(nod2D, myDim_nod2D, 'subli', 'sublimation', 'm/s', sublimation(:) , io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) #endif if ((use_virt_salt) .or. ( (.not. use_virt_salt) .and. (use_cavity) )) then if (sel_forcvar(13)==0) call def_stream(nod2D , myDim_nod2D , 'virtsalt', 'virtual salt flux' , 'm/s*psu', virtual_salt(:) , io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -#if !defined (__oasis) && !defined (__yac) +#if !defined (__oasis) if (sel_forcvar(14)==0) call def_stream(nod2D , myDim_nod2D , 'relaxsalt', 'relaxation salt flux' , 'm/s*psu', relax_salt(:) , io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) #endif if (sel_forcvar(15)==0) call def_stream(nod2D , myDim_nod2D , 'realsalt' , 'real salt flux from sea ice' , 'm/s*psu', real_salt_flux(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -1842,8 +3552,8 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) !_______________________________________________________________________________ ! compute horizontal and vertical tracer gradients CASE ('TRGRD_XYZ ') + sel_trgrd_xyz=1 if (ldiag_trgrd_xyz) then - sel_trgrd_xyz = 1 call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'temp_grdx', 'zonal temperature gradient', 'K/m', trgrd_x(1,:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'temp_grdy', 'meridional temperature gradient', 'K/m', trgrd_y(1,:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D /), 'temp_grdz', 'vertical temperature gradient', 'K/m', trgrd_z(1,:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) @@ -1886,39 +3596,13 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl, nod2D/), (/nl, myDim_nod2D/), 'KvdSdz', 'KvdSdz', 'PSU m/s', KvdSdz(:,:), 1, 'm', i_real8, partit, mesh) end if !___________________________________________________________________________ - ! Tracers flux diagnostics. Default monthly output, but honor io_list - ! entries if the user requested a different frequency. + ! Tracers flux diagnostics without predefined freq, freq_unit, prec, --> + ! default monthly output if (ldiag_trflx .and. sel_trgrd_xyz==0) then - block - integer :: k, tf_freq - character :: tf_unit - character(len=5) :: tf_names(4) - character(len=6) :: tf_long(4) - character(len=8) :: tf_units(4) - tf_names = (/ 'utemp', 'vtemp', 'usalt', 'vsalt' /) - tf_long = (/ 'u*temp', 'v*temp', 'u*salt', 'v*salt' /) - tf_units = (/ 'm/s*degC', 'm/s*degC', 'm/s*psu ', 'm/s*psu ' /) - do j = 1, 4 - tf_freq = 1; tf_unit = 'm' - do k = 1, io_listsize - if (trim(io_list(k)%id) == trim(tf_names(j))) then - tf_freq = io_list(k)%freq - tf_unit = io_list(k)%unit - exit - end if - end do - select case (j) - case (1) - call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), trim(tf_names(j)), trim(tf_long(j)), trim(tf_units(j)), tuv(1,:,:), tf_freq, tf_unit, i_real8, partit, mesh) - case (2) - call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), trim(tf_names(j)), trim(tf_long(j)), trim(tf_units(j)), tuv(2,:,:), tf_freq, tf_unit, i_real8, partit, mesh) - case (3) - call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), trim(tf_names(j)), trim(tf_long(j)), trim(tf_units(j)), suv(1,:,:), tf_freq, tf_unit, i_real8, partit, mesh) - case (4) - call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), trim(tf_names(j)), trim(tf_long(j)), trim(tf_units(j)), suv(2,:,:), tf_freq, tf_unit, i_real8, partit, mesh) - end select - end do - end block + call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'utemp', 'u*temp', 'm/s*°C', tuv(1,:,:), 1, 'm', i_real8, partit, mesh) + call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'vtemp', 'v*temp', 'm/s*°C', tuv(2,:,:), 1, 'm', i_real8, partit, mesh) + call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'usalt', 'u*salt', 'm/s*psu', suv(1,:,:), 1, 'm', i_real8, partit, mesh) + call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'vsalt', 'v*salt', 'm/s*psu', suv(2,:,:), 1, 'm', i_real8, partit, mesh) end if !___________________________________________________________________________ @@ -2095,96 +3779,8 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/) , 'ke_DV', 'RHO*V', 'kg*s/m^2', dynamics%ke_DV(:,:), io_list(i)%freq, 'm', 8, partit, mesh) call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/) , 'ke_elemD', 'RHO* on elem', 'kg/m^3', dynamics%ke_elemD(:,:), io_list(i)%freq, 'm', 8, partit, mesh) call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/) , 'ke_elemD2', 'RHO*^2 on elem', 'kg2/m^6', dynamics%ke_elemD2(:,:), io_list(i)%freq, 'm', 8, partit, mesh) - end if - - !___________________________________________________________________________ - ! CMOR diagnostics: auto-register with defaults if ldiag_cmor=.true. and - ! not already defined in io_list. Default: monthly, double precision - if (ldiag_cmor) then - ! 2D fields - if (.not. stream_already_defined('tos')) then - call def_stream(nod2D, myDim_nod2D, 'tos', 'sea surface temperature', 'degC', tos(:), 1, 'm', 8, partit, mesh, "Sea surface temperature (CMOR)") - end if - if (.not. stream_already_defined('sos')) then - call def_stream(nod2D, myDim_nod2D, 'sos', 'sea surface salinity', 'psu', sos(:), 1, 'm', 8, partit, mesh, "Sea surface salinity (CMOR)") - end if - if (.not. stream_already_defined('pbo')) then - call def_stream(nod2D, myDim_nod2D, 'pbo', 'sea water pressure at sea floor', 'Pa', pbo(:), 1, 'm', 8, partit, mesh, "Sea water pressure at sea floor") - end if - if (.not. stream_already_defined('opottemptend')) then - call def_stream(nod2D, myDim_nod2D, 'opottemptend', 'tendency of sea water potential temperature', 'W/m2', opottemptend(:), 1, 'm', 8, partit, mesh, "Tendency of sea water potential temperature") - end if - - ! 0D (scalar) fields - if (.not. stream0D_already_defined('volo')) then - call def_stream0D('volo', 'sea water volume', 'm3', volo, 1, 'm', 8, partit, "Total volume of liquid sea water") - end if - if (.not. stream0D_already_defined('soga')) then - call def_stream0D('soga', 'global mean sea water salinity', 'psu', soga, 1, 'm', 8, partit, "Global mean sea water salinity") - end if - if (.not. stream0D_already_defined('thetaoga')) then - call def_stream0D('thetaoga', 'global mean sea water potential temperature', 'degC', thetaoga, 1, 'm', 8, partit, "Global mean sea water potential temperature") - end if - if (.not. stream0D_already_defined('siarean')) then - call def_stream0D('siarean', 'sea ice area northern hemisphere', '1e12 m2', siarean, 1, 'm', 8, partit, "Total area of sea ice in the Northern hemisphere") - end if - if (.not. stream0D_already_defined('siareas')) then - call def_stream0D('siareas', 'sea ice area southern hemisphere', '1e12 m2', siareas, 1, 'm', 8, partit, "Total area of sea ice in the Southern hemisphere") - end if - if (.not. stream0D_already_defined('siextentn')) then - call def_stream0D('siextentn', 'sea ice extent northern hemisphere', '1e12 m2', siextentn, 1, 'm', 8, partit, "Total area of sea ice extent in the Northern hemisphere") - end if - if (.not. stream0D_already_defined('siextents')) then - call def_stream0D('siextents', 'sea ice extent southern hemisphere', '1e12 m2', siextents, 1, 'm', 8, partit, "Total area of sea ice extent in the Southern hemisphere") - end if - if (.not. stream0D_already_defined('sivoln')) then - call def_stream0D('sivoln', 'sea ice volume northern hemisphere', '1e9 m3', sivoln, 1, 'm', 8, partit, "Total volume of sea ice in the Northern hemisphere") - end if - if (.not. stream0D_already_defined('sivols')) then - call def_stream0D('sivols', 'sea ice volume southern hemisphere', '1e9 m3', sivols, 1, 'm', 8, partit, "Total volume of sea ice in the Southern hemisphere") - end if - - if (mype == 0) then - write(*,*) ' CMOR diagnostics: all variables registered with defaults (monthly, double precision)' - write(*,*) ' Override via io_list entries in namelist.io' - end if - end if - + end if end subroutine - - -!_______________________________________________________________________________ -! Check if a 2D/3D stream is already defined -function stream_already_defined(name) result(found) - character(len=*), intent(in) :: name - logical :: found - integer :: i - - found = .false. - do i = 1, io_NSTREAMS - if (trim(io_stream(i)%p%name) == trim(name)) then - found = .true. - return - end if - end do -end function stream_already_defined - - -!_______________________________________________________________________________ -! Check if a 0D stream is already defined -function stream0D_already_defined(name) result(found) - character(len=*), intent(in) :: name - logical :: found - integer :: i - - found = .false. - do i = 1, io_NSTREAMS0D - if (trim(io_stream0D(i)%name) == trim(name)) then - found = .true. - return - end if - end do -end function stream0D_already_defined ! ! !_______________________________________________________________________________ @@ -2408,7 +4004,6 @@ subroutine assoc_ids(entry) subroutine write_mean(entry, entry_index) use mod_mesh use io_gather_module - use diagnostics, only: std_dens_N implicit none type(Meandata), intent(inout) :: entry integer, intent(in) :: entry_index @@ -2418,167 +4013,6 @@ subroutine write_mean(entry, entry_index) real(kind=8) :: t0,t1 integer mpierr -#if defined(__XIOS) - ! Route all streams (node- and element-based) to XIOS when enabled. Per - ! io_xios wrappers, fields not declared in field_def_*.xml are gated out - ! by xios_is_valid_field() so sending unconditionally is safe. For - ! element-based fields, pack via owned_elem_local to match the strictly- - ! owned element domain declared to XIOS in io_xios_init. - if (io_xios_is_on()) then - block - integer :: k, kk, nze, n_own - integer, pointer :: own(:) - real(real64), allocatable :: tmp2_r8(:), tmp3_r8(:,:) - real(real32), allocatable :: tmp2_r4(:), tmp3_r4(:,:) - real(WP) :: tp0, tp1, tm0, tm1, ts0, ts1 - if (entry%is_elem_based) then - own => io_xios_owned_elem_local() - n_own = io_xios_n_owned_elem() - if (entry%accuracy == i_real8) then - if (entry%glsize(1) == 1) then - tp0 = MPI_Wtime() - allocate(tmp2_r8(n_own)) - do k=1, n_own; tmp2_r8(k) = entry%local_values_r8_copy(1, own(k)); end do - tp1 = MPI_Wtime(); rtime_om_pack = rtime_om_pack + (tp1 - tp0) - tm0 = MPI_Wtime() - if (io_xios_is_ice_field(entry%name)) then - call io_xios_apply_ice_mask_2d_elem_r8(tmp2_r8) - else - call io_xios_apply_wet_2d_elem_r8(tmp2_r8) - end if - tm1 = MPI_Wtime(); rtime_om_mask = rtime_om_mask + (tm1 - tm0) - ts0 = MPI_Wtime() - call io_xios_send_2d_r8(entry%name, tmp2_r8) - ts1 = MPI_Wtime(); rtime_om_xsend = rtime_om_xsend + (ts1 - ts0) - deallocate(tmp2_r8) - else - tp0 = MPI_Wtime() - nze = size(entry%local_values_r8_copy, 1) - allocate(tmp3_r8(nze, n_own)) - do k=1, n_own - do kk=1, nze; tmp3_r8(kk,k) = entry%local_values_r8_copy(kk, own(k)); end do - end do - tp1 = MPI_Wtime(); rtime_om_pack = rtime_om_pack + (tp1 - tp0) - tm0 = MPI_Wtime() - if (nze /= std_dens_N) call io_xios_apply_wet_3d_elem_r8(tmp3_r8) - tm1 = MPI_Wtime(); rtime_om_mask = rtime_om_mask + (tm1 - tm0) - ts0 = MPI_Wtime() - call io_xios_send_3d_r8(entry%name, tmp3_r8) - ts1 = MPI_Wtime(); rtime_om_xsend = rtime_om_xsend + (ts1 - ts0) - deallocate(tmp3_r8) - end if - else - if (entry%glsize(1) == 1) then - tp0 = MPI_Wtime() - allocate(tmp2_r4(n_own)) - do k=1, n_own; tmp2_r4(k) = entry%local_values_r4_copy(1, own(k)); end do - tp1 = MPI_Wtime(); rtime_om_pack = rtime_om_pack + (tp1 - tp0) - tm0 = MPI_Wtime() - if (io_xios_is_ice_field(entry%name)) then - call io_xios_apply_ice_mask_2d_elem_r4(tmp2_r4) - else - call io_xios_apply_wet_2d_elem_r4(tmp2_r4) - end if - tm1 = MPI_Wtime(); rtime_om_mask = rtime_om_mask + (tm1 - tm0) - ts0 = MPI_Wtime() - call io_xios_send_2d_r4(entry%name, tmp2_r4) - ts1 = MPI_Wtime(); rtime_om_xsend = rtime_om_xsend + (ts1 - ts0) - deallocate(tmp2_r4) - else - tp0 = MPI_Wtime() - nze = size(entry%local_values_r4_copy, 1) - allocate(tmp3_r4(nze, n_own)) - do k=1, n_own - do kk=1, nze; tmp3_r4(kk,k) = entry%local_values_r4_copy(kk, own(k)); end do - end do - tp1 = MPI_Wtime(); rtime_om_pack = rtime_om_pack + (tp1 - tp0) - tm0 = MPI_Wtime() - if (nze /= std_dens_N) call io_xios_apply_wet_3d_elem_r4(tmp3_r4) - tm1 = MPI_Wtime(); rtime_om_mask = rtime_om_mask + (tm1 - tm0) - ts0 = MPI_Wtime() - call io_xios_send_3d_r4(entry%name, tmp3_r4) - ts1 = MPI_Wtime(); rtime_om_xsend = rtime_om_xsend + (ts1 - ts0) - deallocate(tmp3_r4) - end if - end if - else - if (entry%accuracy == i_real8) then - if (entry%glsize(1) == 1) then - tp0 = MPI_Wtime() - allocate(tmp2_r8(entry%p_partit%myDim_nod2D)) - do k=1, entry%p_partit%myDim_nod2D - tmp2_r8(k) = entry%local_values_r8_copy(1, k) - end do - tp1 = MPI_Wtime(); rtime_om_pack = rtime_om_pack + (tp1 - tp0) - tm0 = MPI_Wtime() - if (io_xios_is_ice_field(entry%name)) then - call io_xios_apply_ice_mask_2d_r8(tmp2_r8) - else - call io_xios_apply_wet_2d_r8(tmp2_r8) - end if - tm1 = MPI_Wtime(); rtime_om_mask = rtime_om_mask + (tm1 - tm0) - ts0 = MPI_Wtime() - call io_xios_send_2d_r8(entry%name, tmp2_r8) - ts1 = MPI_Wtime(); rtime_om_xsend = rtime_om_xsend + (ts1 - ts0) - deallocate(tmp2_r8) - else - tp0 = MPI_Wtime() - nze = size(entry%local_values_r8_copy, 1) - allocate(tmp3_r8(nze, entry%p_partit%myDim_nod2D)) - do k=1, entry%p_partit%myDim_nod2D - do kk=1, nze; tmp3_r8(kk,k) = entry%local_values_r8_copy(kk, k); end do - end do - tp1 = MPI_Wtime(); rtime_om_pack = rtime_om_pack + (tp1 - tp0) - tm0 = MPI_Wtime() - if (nze /= std_dens_N) call io_xios_apply_wet_3d_r8(tmp3_r8) - tm1 = MPI_Wtime(); rtime_om_mask = rtime_om_mask + (tm1 - tm0) - ts0 = MPI_Wtime() - call io_xios_send_3d_r8(entry%name, tmp3_r8) - ts1 = MPI_Wtime(); rtime_om_xsend = rtime_om_xsend + (ts1 - ts0) - deallocate(tmp3_r8) - end if - else - if (entry%glsize(1) == 1) then - tp0 = MPI_Wtime() - allocate(tmp2_r4(entry%p_partit%myDim_nod2D)) - do k=1, entry%p_partit%myDim_nod2D - tmp2_r4(k) = entry%local_values_r4_copy(1, k) - end do - tp1 = MPI_Wtime(); rtime_om_pack = rtime_om_pack + (tp1 - tp0) - tm0 = MPI_Wtime() - if (io_xios_is_ice_field(entry%name)) then - call io_xios_apply_ice_mask_2d_r4(tmp2_r4) - else - call io_xios_apply_wet_2d_r4(tmp2_r4) - end if - tm1 = MPI_Wtime(); rtime_om_mask = rtime_om_mask + (tm1 - tm0) - ts0 = MPI_Wtime() - call io_xios_send_2d_r4(entry%name, tmp2_r4) - ts1 = MPI_Wtime(); rtime_om_xsend = rtime_om_xsend + (ts1 - ts0) - deallocate(tmp2_r4) - else - tp0 = MPI_Wtime() - nze = size(entry%local_values_r4_copy, 1) - allocate(tmp3_r4(nze, entry%p_partit%myDim_nod2D)) - do k=1, entry%p_partit%myDim_nod2D - do kk=1, nze; tmp3_r4(kk,k) = entry%local_values_r4_copy(kk, k); end do - end do - tp1 = MPI_Wtime(); rtime_om_pack = rtime_om_pack + (tp1 - tp0) - tm0 = MPI_Wtime() - if (nze /= std_dens_N) call io_xios_apply_wet_3d_r4(tmp3_r4) - tm1 = MPI_Wtime(); rtime_om_mask = rtime_om_mask + (tm1 - tm0) - ts0 = MPI_Wtime() - call io_xios_send_3d_r4(entry%name, tmp3_r4) - ts1 = MPI_Wtime(); rtime_om_xsend = rtime_om_xsend + (ts1 - ts0) - deallocate(tmp3_r4) - end if - end if - end if - end block - return - end if -#endif - ! Serial output implemented so far !___________________________________________________________________________ ! write new time index ctime_copy to file --> expand time array in nc file @@ -2607,6 +4041,11 @@ subroutine write_mean(entry, entry_index) ! loop over vertical layers --> do gather 3d variables layerwise in 2d ! slices do lev=1, size1 + +#ifdef ENABLE_ALBEDO_INTELMPI_WORKAROUNDS + call MPI_Barrier(entry%comm, mpierr) +#endif + !___________________________________________________________________ ! local output variables are gahtered in 2d shaped entry%aux_r8 ! either for vertices or elements @@ -2643,6 +4082,11 @@ subroutine write_mean(entry, entry_index) ! loop over vertical layers --> do gather 3d variables layerwise in 2d ! slices do lev=1, size1 + +#ifdef ENABLE_ALBEDO_INTELMPI_WORKAROUNDS + call MPI_Barrier(entry%comm, mpierr) +#endif + !PS if (entry%p_partit%mype==entry%root_rank) t0=MPI_Wtime() !___________________________________________________________________ ! local output variables are gahtered in 2d shaped entry%aux_r8 @@ -2680,8 +4124,8 @@ subroutine update_means integer :: I, J DO n=1, io_NSTREAMS - entry=>io_stream(n)%p - + entry=>io_stream(n) + !_____________ compute in 8 byte accuracy ______________________________ IF (entry%accuracy == i_real8) then IF (entry%flip) then @@ -2725,12 +4169,6 @@ subroutine update_means entry%addcounter=entry%addcounter+1 END DO ! --> DO n=1, io_NSTREAMS - - ! Update 0D (scalar) means - DO n=1, io_NSTREAMS0D - io_stream0D(n)%local_value = io_stream0D(n)%local_value + real(io_stream0D(n)%ptr, real64) - io_stream0D(n)%addcounter = io_stream0D(n)%addcounter + 1 - END DO end subroutine ! ! @@ -2789,14 +4227,8 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) end if ! --> if (lfirst) then !___________________________________________________________________________ - !PS if (partit%flag_debug .and. partit%mype==0) print *, achar(27)//'[33m'//' -I/O-> call update_means'//achar(27)//'[0m' - block - real(WP) :: tum0, tum1 - tum0 = MPI_Wtime() - call update_means - tum1 = MPI_Wtime() - rtime_om_update_means = rtime_om_update_means + (tum1 - tum0) - end block + !PS if (partit%flag_debug .and. partit%mype==0) print *, achar(27)//'[33m'//' -I/O-> call update_means'//achar(27)//'[0m' + call update_means #if defined(__MULTIO) output_done = .false. @@ -2804,13 +4236,10 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) !___________________________________________________________________________ ! loop over defined streams - block - real(WP) :: tsl0, tsl1 - tsl0 = MPI_Wtime() do n=1, io_NSTREAMS !_______________________________________________________________________ ! make pointer for entry onto io_stream object - entry=>io_stream(n)%p + entry=>io_stream(n) !#if defined(__MULTIO) ! call mio_write_nod(mio, entry) ! lfirst=.false. @@ -2818,23 +4247,12 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) !#endif !_______________________________________________________________________ - ! Cadence dispatch: - ! - XIOS-driven path: ask XIOS whether this field needs a sample now. - ! Cadence is set in XML (field_def freq_op), so the per-event heavy - ! work below (mean-divide, pack, mask, write_mean dispatch) only - ! fires at the XML-declared cadence, not every model step. - ! - Native (non-XIOS) path: keep the namelist.io freq_unit-based - ! event check (unchanged behaviour for FESOM-standalone runs). + !check whether output will be written based on event frequency do_output=.false. -#if defined(__XIOS) - if (io_xios_is_on()) then - do_output = io_xios_field_is_active(trim(entry%name)) - else -#endif if (entry%freq_unit.eq.'y') then call annual_event(do_output, entry%freq) - else if (entry%freq_unit == 'm') then - call monthly_event(do_output, entry%freq) + else if (entry%freq_unit == 'm') then + call monthly_event(do_output, entry%freq) else if (entry%freq_unit == 'd') then call daily_event(do_output, entry%freq) else if (entry%freq_unit == 'h') then @@ -2847,14 +4265,11 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) call par_ex(partit%MPI_COMM_FESOM, partit%mype, 1) stop endif -#if defined(__XIOS) - end if -#endif #if defined(__MULTIO) output_done = output_done .or. do_output #endif - + !_______________________________________________________________________ ! if its time for output --> do_output==.true. if (do_output) then @@ -2862,7 +4277,7 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) #if !defined(__MULTIO) if(entry%thread_running) call entry%thread%join() entry%thread_running = .false. - + ! define filepath if (filesplit_freq=='m') then filepath = trim(ResultPath)//trim(entry%name)//'.'//trim(runid)//'.'//cyearnew//'_'//cmonth//'.nc' @@ -2872,39 +4287,35 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) !___________________________________________________________________ ! only root rank task does output -#if defined(__XIOS) - if(.not. io_xios_is_on() .and. partit%mype == entry%root_rank) then -#else if(partit%mype == entry%root_rank) then -#endif !_______________________________________________________________ ! create new output file ?! if(filepath /= trim(entry%filename)) then - if("" /= trim(entry%filename)) call assert_nf(nf90_close(entry%ncid), __LINE__) + if("" /= trim(entry%filename)) call assert_nf(nf90_close(entry%ncid), __LINE__) entry%filename = filepath !___________________________________________________________ ! use any existing file with this name or create a new one if( nf90_open(entry%filename, nf90_write, entry%ncid) /= nf90_noerr ) then - !PS if (partit%flag_debug) print *, achar(27)//'[33m'//' -I/O-> call create_new_file'//achar(27)//'[0m' + !PS if (partit%flag_debug) print *, achar(27)//'[33m'//' -I/O-> call create_new_file'//achar(27)//'[0m' call create_new_file(entry, ice, dynamics, partit, mesh) - - !PS if (partit%flag_debug) print *, achar(27)//'[33m'//' -I/O-> call assert_nf A'//achar(27)//'[0m'//', k=',k, ', rootpart=', entry%root_rank + + !PS if (partit%flag_debug) print *, achar(27)//'[33m'//' -I/O-> call assert_nf A'//achar(27)//'[0m'//', k=',k, ', rootpart=', entry%root_rank call assert_nf( nf90_open(entry%filename, nf90_write, entry%ncid), __LINE__) end if - + !___________________________________________________________ ! setup all dimension definition and attributes of the netcdf - ! file - !PS if (partit%flag_debug) print *, achar(27)//'[33m'//' -I/O-> call assoc_ids'//achar(27)//'[0m' + ! file + !PS if (partit%flag_debug) print *, achar(27)//'[33m'//' -I/O-> call assoc_ids'//achar(27)//'[0m' call assoc_ids(entry) - + end if ! --> if(filepath /= trim(entry%filename)) then - + !_______________________________________________________________ - ! if the time rtime at the rec_count is larger than ctime we + ! if the time rtime at the rec_count is larger than ctime we ! look for the closest record with the timestamp less than ctime do k=entry%rec_count, 1, -1 - !PS if (partit%flag_debug) print *, achar(27)//'[33m'//' -I/O-> call assert_nf B'//achar(27)//'[0m'//', k=',k, ', rootpart=', entry%root_rank + !PS if (partit%flag_debug) print *, achar(27)//'[33m'//' -I/O-> call assert_nf B'//achar(27)//'[0m'//', k=',k, ', rootpart=', entry%root_rank ! determine rtime from exiting file call assert_nf( nf90_get_var(entry%ncid, entry%tID, rtime), __LINE__) if (ctime > rtime) then @@ -2923,44 +4334,35 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) #endif !___________________________________________________________________ ! write double precision output - ! - ! NetCDF fill-value substitution is skipped under __MULTIO: multio - ! ships the array straight to GRIB and a 9.97e36 sentinel in the - ! data range wrecks GRIB packing precision (real ice values get - ! quantized to ~0). Multio gets the clean mean (zeros stay zeros). if (entry%accuracy == i_real8) then !$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(I,J) DO J=1, size(entry%local_values_r8,dim=2) DO I=1, size(entry%local_values_r8,dim=1) -#if defined(__MULTIO) - entry%local_values_r8_copy(I,J) = entry%local_values_r8(I,J) /real(entry%addcounter,real64) ! compute_means -#else + ! Check if point has valid data (non-zero accumulated value) + ! Use small epsilon to account for floating point precision if (abs(entry%local_values_r8(I,J)) < 1.0e-30_real64) then entry%local_values_r8_copy(I,J) = NC_FILL_DOUBLE ! No data - set to fill value else entry%local_values_r8_copy(I,J) = entry%local_values_r8(I,J) /real(entry%addcounter,real64) ! compute_means end if -#endif entry%local_values_r8(I,J) = 0._real64 ! clean_meanarrays - reset to 0 for next accumulation END DO ! --> DO I=1, size(entry%local_values_r8,dim=1) END DO ! --> DO J=1, size(entry%local_values_r8,dim=2) !$OMP END PARALLEL DO - + !___________________________________________________________________ ! write single precision output else if (entry%accuracy == i_real4) then !$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(I,J) DO J=1, size(entry%local_values_r4,dim=2) DO I=1, size(entry%local_values_r4,dim=1) -#if defined(__MULTIO) - entry%local_values_r4_copy(I,J) = entry%local_values_r4(I,J) /real(entry%addcounter,real32) ! compute_means -#else + ! Check if point has valid data (non-zero accumulated value) + ! Use small epsilon to account for floating point precision if (abs(entry%local_values_r4(I,J)) < 1.0e-30_real32) then entry%local_values_r4_copy(I,J) = NC_FILL_FLOAT ! No data - set to fill value else entry%local_values_r4_copy(I,J) = entry%local_values_r4(I,J) /real(entry%addcounter,real32) ! compute_means end if -#endif entry%local_values_r4(I,J) = 0._real32 ! clean_meanarrays - reset to 0 for next accumulation END DO ! --> DO I=1, size(entry%local_values_r4,dim=1) END DO ! --> DO J=1, size(entry%local_values_r4,dim=2) @@ -2975,30 +4377,16 @@ subroutine output(istep, ice, dynamics, tracers, partit, mesh) ! if (n==1) then entry%rec_count = istep call send_data_to_multio(entry) -! end if +! end if #else !___________________________________________________________________ ! this is where the magic happens --> here do_output_callback is ! triggered as a method of the io_stream object --> call write_mean(...) - block - real(WP) :: tps0, tps1 - tps0 = MPI_Wtime() - call entry%thread%run() - tps1 = MPI_Wtime() - entry%rtime_per_stream = entry%rtime_per_stream + (tps1 - tps0) - end block + call entry%thread%run() entry%thread_running = .true. #endif endif ! --> if (do_output) then end do ! --> do n=1, io_NSTREAMS - tsl1 = MPI_Wtime() - rtime_om_streamloop = rtime_om_streamloop + (tsl1 - tsl0) - end block - - !___________________________________________________________________________ - ! Handle 0D (scalar) output streams - call output_0D_streams(istep, partit) - lfirst=.false. #if defined(__MULTIO) @@ -3172,7 +4560,7 @@ subroutine do_output_callback(entry_index) ! EO args type(Meandata), pointer :: entry - entry=>io_stream(entry_index)%p + entry=>io_stream(entry_index) entry%p_partit%mype=entry%mype_workaround ! for the thread callback, copy back the value of our mype as a workaround for errors with the cray envinronment (at least with ftn 2.5.9 and cray-mpich 7.5.3) !___________________________________________________________________________ ! collect local mean output data (entry%local_values_r8_copy) into global 2d @@ -3186,15 +4574,10 @@ subroutine do_output_callback(entry_index) ! synchronize after writes: ! To minimize data loss in case of abnormal termination, or To make data ! available to other processes for reading immediately after it is written. - if(entry%p_partit%mype == entry%root_rank) then + if(entry%p_partit%mype == entry%root_rank) then !PS if (entry%p_partit%flag_debug) print *, achar(27)//'[31m'//' -I/O-> call nf_sync'//achar(27)//'[0m', entry%p_partit%mype -#if defined(__XIOS) - ! When XIOS drives output no legacy netCDF file was opened; entry%ncid - ! is invalid. Skip the sync. - if (.not. io_xios_is_on()) & -#endif call assert_nf( nf90_sync(entry%ncid), __LINE__ ) ! flush the file to disk after each write - end if + end if end subroutine ! @@ -3206,78 +4589,10 @@ subroutine finalize_output() integer i type(Meandata), pointer :: entry do i=1, io_NSTREAMS - entry=>io_stream(i)%p + entry=>io_stream(i) if(entry%thread_running) call entry%thread%join() - entry%thread_running = .false. - end do - - ! Close 0D stream files - do i=1, io_NSTREAMS0D - if (io_stream0D(i)%ncid >= 0) then - call assert_nf(nf90_close(io_stream0D(i)%ncid), __LINE__) - io_stream0D(i)%ncid = -1 - end if - end do -end subroutine -! -! -!_______________________________________________________________________________ -!> Print per-stream cumulative cost (entry%thread%run() wrap time, mean across -!> ranks) sorted descending. Called from fesom_module's finalize block; -!> master-rank only to keep the log readable. -subroutine print_per_stream_costs(comm, mype, npes) - use mpi - integer, intent(in) :: comm, mype, npes - integer :: i, ierr, k, top_n, idx - real(real32) :: ttime - real(real32), allocatable :: per_stream(:), per_stream_max(:), sorted(:) - integer, allocatable :: order(:) - - if (io_NSTREAMS <= 0) return - allocate(per_stream(io_NSTREAMS), per_stream_max(io_NSTREAMS)) - do i = 1, io_NSTREAMS - per_stream(i) = real(io_stream(i)%p%rtime_per_stream, real32) - end do - per_stream_max = per_stream - call MPI_AllREDUCE(MPI_IN_PLACE, per_stream, io_NSTREAMS, MPI_REAL, MPI_SUM, comm, ierr) - per_stream = per_stream / real(npes, real32) - call MPI_AllREDUCE(MPI_IN_PLACE, per_stream_max, io_NSTREAMS, MPI_REAL, MPI_MAX, comm, ierr) - - if (mype /= 0) then - deallocate(per_stream, per_stream_max) - return - end if - - ! sort by mean descending - allocate(order(io_NSTREAMS), sorted(io_NSTREAMS)) - do i = 1, io_NSTREAMS; order(i) = i; end do - sorted = per_stream - do i = 1, io_NSTREAMS-1 - do k = i+1, io_NSTREAMS - if (sorted(k) > sorted(i)) then - ttime = sorted(i); sorted(i) = sorted(k); sorted(k) = ttime - idx = order(i); order(i) = order(k); order(k) = idx - end if - end do + entry%thread_running = .false. end do - - write(*,*) '___PER-STREAM OUTPUT COST [seconds] (entry%thread%run() wrap, sorted desc)' - write(*,'(2x,a30,2a12,3x,a8,2x,a5)') 'stream', 'mean', 'max', 'freq', 'is_3D' - top_n = min(io_NSTREAMS, 30) - do i = 1, top_n - idx = order(i) - block - character(len=8) :: freq_str - write(freq_str,'(i0,a1)') io_stream(idx)%p%freq, io_stream(idx)%p%freq_unit - write(*,'(2x,a30,2f12.4,3x,a8,2x,L5)') trim(io_stream(idx)%p%name), & - per_stream(idx), per_stream_max(idx), & - adjustl(freq_str), & - (io_stream(idx)%p%glsize(1) > 1) - end block - end do - if (io_NSTREAMS > top_n) write(*,'(2x,a,i0,a)') '...', io_NSTREAMS - top_n, ' more streams below the top 30' - - deallocate(per_stream, per_stream_max, order, sorted) end subroutine ! ! @@ -3437,66 +4752,6 @@ subroutine def_stream2D(glsize, lcsize, name, description, units, data, freq, fr ! ! !_______________________________________________________________________________ -! build 0D (scalar) meandata streaming object for global values -subroutine def_stream0D(name, description, units, data, freq, freq_unit, accuracy, partit, long_description) - USE MOD_PARTIT - USE MOD_PARSUP - implicit none - character(len=*), intent(in) :: name, description, units - real(kind=WP), target, intent(in) :: data - integer, intent(in) :: freq - character, intent(in) :: freq_unit - integer, intent(in) :: accuracy - type(t_partit), intent(inout) :: partit - character(len=*), optional, intent(in) :: long_description - type(Meandata0D), pointer :: entry - integer :: i - - !___________________________________________________________________________ - if (partit%mype==0) then - write(*,*) 'adding I/O stream 0D (scalar) for ', trim(name) - end if - - !___________________________________________________________________________ - ! check if we already have this variable - do i=1, io_NSTREAMS0D - if(trim(io_stream0D(i)%name) .eq. name) then - print *,"variable '"//name//"' already exists in 0D streams" - call assert(.false., __LINE__) - end if - end do - - !___________________________________________________________________________ - ! add this instance to io_stream0D array - io_NSTREAMS0D = io_NSTREAMS0D + 1 - call assert(size(io_stream0D) >= io_NSTREAMS0D, __LINE__) - entry => io_stream0D(io_NSTREAMS0D) - - !___________________________________________________________________________ - ! fill up 0D meandata streaming object - entry%name = name - entry%description = description - entry%units = units - entry%ptr => data - entry%local_value = 0._real64 - entry%addcounter = 0 - entry%accuracy = accuracy - entry%freq = freq - entry%freq_unit = freq_unit - entry%is_in_use = .true. - entry%ncid = -1 - entry%rec_count = 0 - - if (present(long_description)) then - entry%long_description = long_description - else - entry%long_description = description - end if - -end subroutine def_stream0D -! -! -!_______________________________________________________________________________ ! initialse new meandata streaming object subroutine associate_new_stream(name, entry) type(Meandata), pointer :: entry @@ -3508,20 +4763,19 @@ subroutine associate_new_stream(name, entry) !___________________________________________________________________________ ! check if we already have this variable do i=1, io_NSTREAMS - if(trim(io_stream(i)%p%name) .eq. name) then + if(trim(io_stream(i)%name) .eq. name) then print *,"variable '"//name//"' already exists, & &check if you define it multiple times, for example in namelist.io, & &namelist.icepack, io_meandata.F90 or other place that add I/O stream." - call assert(.false., __LINE__) + call assert(.false., __LINE__) end if end do - + !___________________________________________________________________________ ! add this instance to io_stream array io_NSTREAMS = io_NSTREAMS +1 - call ensure_io_stream_capacity(io_NSTREAMS) - allocate(io_stream(io_NSTREAMS)%p) - entry=>io_stream(io_NSTREAMS)%p + call assert(size(io_stream) >= io_NSTREAMS, __LINE__) + entry=>io_stream(io_NSTREAMS) end subroutine ! ! @@ -3647,31 +4901,6 @@ subroutine assert(val, line) end if end subroutine ! -!_______________________________________________________________________________ -! Grow io_stream wrapper array as needed. Only the pointer wrappers are copied; -! the heap-allocated Meandata targets stay put, so existing pointers into -! io_stream(i)%p remain valid and no finalisation of Meandata is triggered. -subroutine ensure_io_stream_capacity(required) - integer, intent(in) :: required - type(MeandataPtr), allocatable :: tmp(:) - integer :: old_size, new_size, i - if (.not. allocated(io_stream)) then - allocate(io_stream(max(IO_STREAM_INITIAL_CAPACITY, required))) - return - end if - old_size = size(io_stream) - if (old_size >= required) return - new_size = old_size - do while (new_size < required) - new_size = new_size * 2 - end do - allocate(tmp(new_size)) - do i = 1, old_size - tmp(i)%p => io_stream(i)%p - end do - call move_alloc(tmp, io_stream) -end subroutine -! ! !_______________________________________________________________________________ ! do vector rotation on the fly @@ -3690,8 +4919,8 @@ subroutine io_r2g(n, partit, mesh) logical :: do_rotation if (n==io_NSTREAMS) RETURN - entry_x=>io_stream(n)%p - entry_y=>io_stream(n+1)%p + entry_x=>io_stream(n) + entry_y=>io_stream(n+1) IF (.NOT. (entry_x%freq_unit==entry_y%freq_unit) .and. ((entry_x%freq==entry_y%freq))) RETURN IF (entry_x%accuracy /= entry_y%accuracy) RETURN do_rotation=.FALSE. @@ -3835,4 +5064,74 @@ SUBROUTINE send_data_to_multio(entry) END DO END SUBROUTINE #endif +! +! +!_______________________________________________________________________________ +! initialse new meandata streaming object for a 0D (scalar) output +subroutine def_stream0D(name, description, units, data, freq, freq_unit, accuracy, partit, long_description) + USE MOD_PARTIT + USE MOD_PARSUP + implicit none + character(len=*), intent(in) :: name, description, units + real(kind=WP), target, intent(in) :: data + integer, intent(in) :: freq + character, intent(in) :: freq_unit + integer, intent(in) :: accuracy + type(t_partit), intent(inout) :: partit + character(len=*), optional, intent(in) :: long_description + type(Meandata0D), pointer :: entry + integer :: i + + !___________________________________________________________________________ + if (partit%mype==0) then + write(*,*) 'adding I/O stream 0D (scalar) for ', trim(name) + end if + + !___________________________________________________________________________ + ! check if we already have this variable + do i=1, io_NSTREAMS0D + if(trim(io_stream0D(i)%name) .eq. name) then + print *,"variable '"//name//"' already exists in 0D streams" + call assert(.false., __LINE__) + end if + end do + + !___________________________________________________________________________ + ! add this instance to io_stream0D array + io_NSTREAMS0D = io_NSTREAMS0D + 1 + call assert(size(io_stream0D) >= io_NSTREAMS0D, __LINE__) + entry => io_stream0D(io_NSTREAMS0D) + + !___________________________________________________________________________ + ! fill up 0D meandata streaming object + entry%name = name + entry%description = description + entry%units = units + entry%ptr => data + entry%local_value = 0._real64 + entry%addcounter = 0 + entry%accuracy = accuracy + entry%freq = freq + entry%freq_unit = freq_unit + entry%is_in_use = .true. + entry%ncid = -1 + entry%rec_count = 0 + + if (present(long_description)) then + entry%long_description = long_description + else + entry%long_description = description + end if + +end subroutine def_stream0D + +!_______________________________________________________________________________ +! Per-stream output cost report (sorted at finalize). The current Meandata type +! on this branch does not carry the per-stream wall-clock accumulator the full +! reporter on main consumes; for now this is a no-op stub so the unconditional +! call in fesom_module.F90 links cleanly. +subroutine print_per_stream_costs(comm, mype, npes) + integer, intent(in) :: comm, mype, npes +end subroutine print_per_stream_costs + end module diff --git a/src/io_restart_file_group.F90 b/src/io_restart_file_group.F90 index 27e34a5f7..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(200) + 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 fa0cd7c65..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) @@ -224,7 +227,7 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, nl1 = nlevels_nod2D(n) do nz = nu1, nl1-1 ! Horizontal advection part for LO (FCT is .TRUE.) - tracers%work%tra_advhoriz(nz,n,tr_num) = fct_LO(nz,n) * dt/areasvol(nz,n)/hnode_new(nz,n) + 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 @@ -310,7 +313,7 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, nl1 = nlevels_nod2D(n) do nz = nu1, nl1-1 ! Vertical advection part for LO (FCT is .TRUE.) - tracers%work%tra_advvert (nz,n,tr_num) = (adv_flux_ver(nz, n)-adv_flux_ver(nz+1, n))*dt/areasvol(nz,n)/hnode_new(nz,n) + 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 @@ -380,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 !___________________________________________________________________________ @@ -456,41 +459,13 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, end if !-->if ((ldiag_DVD) .and. (tr_num<=2)) then - -! O:G - tra_diag -!#if defined (__recom) - if (tracers%data(tr_num)%ltra_diag) then - !_______________________________________________________________________ - if (trim(tracers%data(tr_num)%tra_adv_lim)=='FCT') then - do n=1, myDim_nod2D+eDim_nod2D - nu1 = ulevels_nod2D(n) - nl1 = nlevels_nod2D(n) - do nz = nu1, nl1-1 - ! part for LO + antidiffusive (FCT is .TRUE.) - tracers%work%tra_advhoriz(nz,n,tr_num) = tracers%work%tra_advhoriz(nz,n,tr_num) + dttf_h(nz,n)/hnode_new(nz,n) - tracers%work%tra_advvert(nz,n,tr_num) = tracers%work%tra_advvert(nz,n,tr_num) + dttf_v(nz,n)/hnode_new(nz,n) - end do - end do - else - do n=1, myDim_nod2D+eDim_nod2D - nu1 = ulevels_nod2D(n) - nl1 = nlevels_nod2D(n) - do nz = nu1, nl1-1 - ! (FCT .FALSE.) - tracers%work%tra_advhoriz(nz,n,tr_num) = dttf_h(nz,n)/hnode_new(nz,n) - tracers%work%tra_advvert (nz,n,tr_num) = dttf_v(nz,n)/hnode_new(nz,n) - end do - end do - end if - end if -!#endif - 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 @@ -499,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) @@ -555,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 @@ -617,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 7c88a2c5c..c2b10fcbe 100644 --- a/src/oce_ale_tracer.F90 +++ b/src/oce_ale_tracer.F90 @@ -157,7 +157,6 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) use diagnostics, only: ldiag_DVD use g_forcing_param, only: use_age_tracer !---age-code use mod_transit, only: decay14, decay39 - use cmor_variables_diag, only: ldiag_cmor, save_cmor_advection implicit none type(t_ice) , intent(in) , target :: ice type(t_dyn) , intent(inout), target :: dynamics @@ -167,6 +166,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, 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 @@ -193,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: @@ -219,6 +219,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) ! 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 !___________________________________________________________________________ @@ -233,17 +234,29 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) if(use_MEDUSA) then SinkFlx = 0.0d0 endif - SinkingVel1 = 0.0d0 ! OG 16.03.23 - SinkingVel2 = 0.0d0 ! OG 16.03.23 + 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) !!& @@ -260,13 +273,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) tracers%work%del_ttf(:, node)=tracers%work%del_ttf(:, node)+tracers%work%del_ttf_advhoriz(:, node)+tracers%work%del_ttf_advvert(:, node) end do !$OMP END PARALLEL DO - - !___________________________________________________________________________ - ! Save advection snapshot for CMOR tendency decomposition - if (ldiag_cmor .and. (tr_num <= 2)) then - call save_cmor_advection(tr_num, tracers%work%del_ttf(:, 1:myDim_nod2D), myDim_nod2D, nl-1) - end if - + !___________________________________________________________________________ ! diffuse tracers if (flag_debug .and. mype==0) print *, achar(27)//'[37m'//' --> call diff_tracers_ale'//achar(27)//'[0m' @@ -276,21 +283,12 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, 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) - -!YY: C14 seems to be calculated both in fesom and recom -!YY: decay differently calculated??? -#if defined(__ciso) - ! radioactive decay of 14C - if (ciso_14 .and. any(c14_tracer_id == tracers%data(tr_num)%ID)) then - tracers%data(tr_num)%values(:,:) = tracers%data(tr_num)%values(:,:) * (1 - lambda_14 * dt) - end if ! ciso & ciso_14 -#endif - + !___________________________________________________________________________ ! 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 @@ -396,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 @@ -430,7 +429,13 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) ttf_rhs_bak = 0.0 if (tracers%data(tr_num)%ltra_diag) then - call backup_ttf_rhs(del_ttf, ttf_rhs_bak, ulevels_nod2D, nlevels_nod2D, myDim_nod2D, eDim_nod2D) + 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 diffusion @@ -440,12 +445,25 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) 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 - call store_diag_component(del_ttf, ttf_rhs_bak, hnode_new, ulevels_nod2D, nlevels_nod2D, myDim_nod2D, eDim_nod2D, & - tracers%work%tra_diff_part_hor_redi(:,:,tr_num)) + 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 - call backup_ttf_rhs(del_ttf, ttf_rhs_bak, ulevels_nod2D, nlevels_nod2D, myDim_nod2D, eDim_nod2D) + 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 @@ -454,22 +472,42 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, 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 - call store_diag_component(del_ttf, ttf_rhs_bak, hnode_new, ulevels_nod2D, nlevels_nod2D, myDim_nod2D, eDim_nod2D, & - tracers%work%tra_diff_part_ver_expl(:,:,tr_num)) + 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 - call backup_ttf_rhs(del_ttf, ttf_rhs_bak, ulevels_nod2D, nlevels_nod2D, myDim_nod2D, eDim_nod2D) + 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 - call store_diag_component(del_ttf, ttf_rhs_bak, hnode_new, ulevels_nod2D, nlevels_nod2D, myDim_nod2D, eDim_nod2D, & - tracers%work%tra_diff_part_ver_redi_expl(:,:,tr_num)) + 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 @@ -483,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 @@ -522,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) @@ -536,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) @@ -585,55 +664,13 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) 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 -contains - -subroutine backup_ttf_rhs(del_ttf, ttf_rhs_bak, ulevels_nod2D, nlevels_nod2D, myDim_nod2D, eDim_nod2D) - real(kind=WP), intent(in) :: del_ttf(:,:) - real(kind=WP), intent(inout) :: ttf_rhs_bak(:,:) - integer , intent(in) :: ulevels_nod2D(:) - integer , intent(in) :: nlevels_nod2D(:) - integer , intent(in) :: myDim_nod2D - integer , intent(in) :: eDim_nod2D - - integer :: n, nz, nu1, nl1 - - 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 subroutine backup_ttf_rhs - -subroutine store_diag_component(del_ttf, ttf_rhs_bak, hnode_new, ulevels_nod2D, nlevels_nod2D, myDim_nod2D, eDim_nod2D, target_field) - real(kind=WP), intent(in) :: del_ttf(:,:) - real(kind=WP), intent(in) :: ttf_rhs_bak(:,:) - real(kind=WP), intent(in) :: hnode_new(:,:) - integer , intent(in) :: ulevels_nod2D(:) - integer , intent(in) :: nlevels_nod2D(:) - integer , intent(in) :: myDim_nod2D - integer , intent(in) :: eDim_nod2D - real(kind=WP), intent(inout) :: target_field(:,:) - - integer :: n, nz, nu1, nl1 - - do n=1, myDim_nod2D+eDim_nod2D - nu1 = ulevels_nod2D(n) - nl1 = nlevels_nod2D(n) - do nz = nu1, nl1-1 - target_field(nz,n) = (del_ttf(nz,n) - ttf_rhs_bak(nz,n)) / hnode_new(nz,n) ! Unit [Conc] - end do - end do -end subroutine store_diag_component - end subroutine diff_tracers_ale ! ! @@ -1003,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 @@ -1028,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 @@ -1131,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 @@ -1213,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* @@ -1665,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 @@ -1756,102 +1793,321 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit, mesh, sst, sss, aice) CASE (39) ! Argon-39 (fractionationation-corrected 39Ar/Ar) ! Local isotopic 39Ar/Ar air-sea exchange flux (m / s) bc_surface = dt * (iso_flux("arg", sst, sss, wind_2, aice, press_a, xarg_a, r39ar_a, sval, arg_0) - sval * water_flux(n) * is_nonlinfs) + !--- 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 & - + 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 & - + lb_flux(n,3) + lb_flux(n,5)*2) !CaCO3:Alk burial=1:2 - else - bc_surface= dt*(virtual_alk(n) + relax_alk(n) & - + RiverAlk2D(n) * is_riverinput) - end if - CASE (1004:1010) - bc_surface=0.0_WP - CASE (1011) ! DON - bc_surface= dt*RiverDON2D(n) * is_riverinput - CASE (1012) ! DOC - bc_surface= dt*RiverDOC2D(n) * is_riverinput - CASE (1013:1017) +#if defined(__recom) +! ============================================================================= +! SURFACE BOUNDARY CONDITIONS FOR RECOM BIOGEOCHEMICAL TRACERS +! +! bc_surface is the surface flux [tracer units] applied to each tracer per +! timestep (dt). Fluxes include atmospheric deposition, river input, erosion, +! air-sea gas exchange, and (optionally) MEDUSA sediment loopback fluxes. +! +! Flags used throughout: +! is_riverinput : 1 if river input is enabled, else 0 +! is_erosioninput : 1 if erosion input is enabled, else 0 +! use_MEDUSA : true if MEDUSA sediment module is active +! add_loopback : true if sediment loopback fluxes are included +! enable_R2OMIP : true if R2OMIP river chemistry scheme is active +! ciso, ciso_14 : true if carbon isotope tracers (13C / 14C) are enabled +! +! lb_flux(n, k) : MEDUSA loopback fluxes at column n for tracer k: +! k=1 DIN k=2 DIC k=3 Alk k=4 DSi +! k=5 CaCO3 k=6 DIC13 k=7 CaCO3-13C +! k=8 DIC14 k=9 CaCO3-14C +! ============================================================================= + + ! ------------------------------------------------------------------------- + ! 1001 : DIN – Dissolved Inorganic Nitrogen + ! Sources: atmospheric N deposition + river DIN + erosion TON + ! + MEDUSA loopback (lb_flux k=1) when enabled + ! ------------------------------------------------------------------------- + + CASE (1001) + IF (use_MEDUSA .AND. add_loopback) THEN + 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 + + ! ------------------------------------------------------------------------- + ! 1002 : DIC – Dissolved Inorganic Carbon + ! Sources: air-sea CO2 flux + river DIC + erosion TOC + ! + MEDUSA loopback (lb_flux k=2 DIC, k=5 CaCO3) when enabled + ! + ! R2OMIP variant: also adds river labile DOC (RiverDOCl2D) to DIC; + ! labile DOC is assumed to remineralise rapidly. + ! ------------------------------------------------------------------------- + + CASE (1002) + 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 + IF (enable_R2OMIP) THEN + bc_surface = dt * ( GloCO2flux_seaicemask(n) & + + RiverDIC2D(n) * is_riverinput & + + RiverDOCl2D(n) * is_riverinput & ! labile DOC treated as DIC in R2OMIP + + ErosionTOC2D(n) * is_erosioninput ) + ELSE + bc_surface = dt * ( GloCO2flux_seaicemask(n) & + + RiverDIC2D(n) * is_riverinput & + + ErosionTOC2D(n) * is_erosioninput ) + END IF + END IF + + ! ------------------------------------------------------------------------- + ! 1003 : Alk – Total Alkalinity + ! Sources: virtual salt flux (virtual_alk), relaxation term (relax_alk), + ! river Alk + MEDUSA loopback (lb_flux k=3 Alk, k=5 CaCO3) + ! + ! CaCO3 dissolution releases 2 mol Alk per mol C (1:2 ratio). + ! + ! R2OMIP variant: river alkalinity prescribed via RiverDIC2D (no + ! explicit RiverAlk2D), loopback uses lb_flux k=5 only. + ! ------------------------------------------------------------------------- + + CASE (1003) + IF (use_MEDUSA .AND. add_loopback) THEN + IF (enable_R2OMIP) THEN + bc_surface = dt * ( virtual_alk(n) + relax_alk(n) & + + lb_flux(n,3) + lb_flux(n,5)*2 ) ! CaCO3:Alk = 1:2 + ELSE + bc_surface = dt * ( virtual_alk(n) + relax_alk(n) & + + RiverAlk2D(n) * is_riverinput & + + lb_flux(n,3) + lb_flux(n,5)*2 ) ! CaCO3:Alk = 1:2 + END IF + ELSE + IF (enable_R2OMIP) THEN + bc_surface = dt * ( virtual_alk(n) + relax_alk(n) & + + RiverDIC2D(n) * is_riverinput ) ! R2OMIP proxy for river Alk + ELSE + bc_surface = dt * ( virtual_alk(n) + relax_alk(n) & + + RiverAlk2D(n) * is_riverinput ) + END IF + END IF + + ! ------------------------------------------------------------------------- + ! 1004–1006 : No surface flux + ! ------------------------------------------------------------------------- + + CASE (1004:1006) bc_surface=0.0_WP - CASE (1018) ! DSi - if (use_MEDUSA .and. add_loopback) then - bc_surface=dt*(RiverDSi2D(n) * is_riverinput & - + ErosionTSi2D(n) * is_erosioninput & - + lb_flux(n,4)) - else - bc_surface=dt*(RiverDSi2D(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) - end if - CASE (1020:1021) ! Cal + ! ------------------------------------------------------------------------- + ! 1007 : PON – Particulate Organic Nitrogen (= detN in RECOM) + ! R2OMIP only: derived from river POC using Redfield-like N:C ratio (25/276) + ! ------------------------------------------------------------------------- + + CASE (1007) + IF (enable_R2OMIP) THEN + bc_surface = (25.0_WP / 276.0_WP) * dt * RiverPOC2D(n) * is_riverinput + ELSE + bc_surface = 0.0_WP + END IF + + ! ------------------------------------------------------------------------- + ! 1008 : POC – Particulate Organic Carbon (= detC in RECOM) + ! R2OMIP only: river particulate organic carbon input + ! ------------------------------------------------------------------------- + CASE (1008) + IF (enable_R2OMIP) THEN + bc_surface = dt * RiverPOC2D(n) * is_riverinput + ELSE + bc_surface = 0.0_WP + END IF + + ! ------------------------------------------------------------------------- + ! 1009–1010 : No surface flux + ! ------------------------------------------------------------------------- + CASE (1009:1010) bc_surface=0.0_WP - CASE (1022) ! OXY - bc_surface= dt*GloO2flux_seaicemask(n) -! bc_surface=0.0_WP - CASE (1023:1036) - bc_surface=0.0_WP ! OG added bc for recom fields - CASE (1302) ! Before (1037) ! DIC_13 + ! ------------------------------------------------------------------------- + ! 1011 : DON – Dissolved Organic Nitrogen + ! R2OMIP: derived from river semi-labile DOC (RiverDOCsl2D) using N:C + ! stoichiometry from Seitzinger et al. (103/2583 ≈ C/N ~25) + ! Standard: river DON directly + ! ------------------------------------------------------------------------- + + CASE (1011) + IF (enable_R2OMIP) THEN + bc_surface = (103.0_WP / 2583.0_WP) * dt * RiverDOCsl2D(n) * is_riverinput + ELSE + bc_surface = dt * RiverDON2D(n) * is_riverinput + END IF + + ! ------------------------------------------------------------------------- + ! 1012 : DOC – Dissolved Organic Carbon (refractory / bulk) + ! R2OMIP: DOC split into labile (→ DIC, see 1002) and semi-labile (→ 1031); + ! bulk DOC field receives no direct flux under R2OMIP. + ! Standard: river DOC directly + ! ------------------------------------------------------------------------- + CASE (1012) + IF (enable_R2OMIP) THEN + bc_surface = 0.0_WP + ELSE + bc_surface = dt * RiverDOC2D(n) * is_riverinput + END IF + + ! ------------------------------------------------------------------------- + ! 1013–1017 : No surface flux + ! ------------------------------------------------------------------------- + CASE (1013:1017) + bc_surface = 0.0_WP + + ! ------------------------------------------------------------------------- + ! 1018 : DSi – Dissolved Silica + ! Sources: river DSi + erosion TSi + MEDUSA loopback (lb_flux k=4) + ! + ! R2OMIP variant (no loopback): DSi estimated from river DIN using the + ! Si:N ratio from Turner et al. (2003): Si ≈ (194/16.2) × DIN + ! R2OMIP + MEDUSA loopback: currently set to zero (under review – CHECK) + ! ------------------------------------------------------------------------- + CASE (1018) + IF (use_MEDUSA .AND. add_loopback) THEN + IF (enable_R2OMIP) THEN + bc_surface = 0.0_WP ! TODO: R2OMIP + loopback path not yet implemented + ELSE + bc_surface = dt * ( RiverDSi2D(n) * is_riverinput & + + ErosionTSi2D(n) * is_erosioninput & + + lb_flux(n,4) ) + END IF + ELSE + IF (enable_R2OMIP) THEN + ! Si:N proxy ratio from Turner et al. (2003) + bc_surface = dt * ( (194.0_WP / 16.2_WP) * RiverDIN2D(n) * is_riverinput & + + ErosionTSi2D(n) * is_erosioninput ) + ELSE + bc_surface = dt * ( RiverDSi2D(n) * is_riverinput & + + ErosionTSi2D(n) * is_erosioninput ) + END IF + END IF + + ! ------------------------------------------------------------------------- + ! 1019 : Fe – Dissolved Iron + ! Sources: atmospheric dust deposition (AtmFeInput) + ! + river Fe (RiverFe) when useRivFe is enabled + ! + ! Commented alternative (Tashiro et al. 2023 R2OMIP formula) — unstable: + ! bc_surface = dt*AtmFeInput + dt*(0.002*(RiverDOCsl2D**(-1.616))) + ! ------------------------------------------------------------------------- + CASE (1019) + 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 + + ! ------------------------------------------------------------------------- + ! 1020–1021 : CaCO3 – no surface boundary flux (internal source/sink only) + ! ------------------------------------------------------------------------- + CASE (1020:1021) + bc_surface = 0.0_WP + + ! ------------------------------------------------------------------------- + ! 1022 : OXY – Dissolved Oxygen + ! Source: air-sea O2 flux (seaice-masked) + ! ------------------------------------------------------------------------- + CASE (1022) + bc_surface = dt * GloO2flux_seaicemask(n) + + ! ------------------------------------------------------------------------- + ! 1023–1030 : No surface flux (additional RECOM fields) + ! ------------------------------------------------------------------------- + CASE (1023:1030) + bc_surface = 0.0_WP + + ! ------------------------------------------------------------------------- + ! 1031 : DOC_terr – Terrigenous (semi-labile) dissolved organic carbon + ! R2OMIP only: river semi-labile DOC (RiverDOCsl2D) input + ! Labile fraction goes to DIC (case 1002); DON to case 1011. + ! ------------------------------------------------------------------------- + CASE (1031) + IF (enable_R2OMIP) THEN + bc_surface = dt * RiverDOCsl2D(n) * is_riverinput + ELSE + bc_surface = 0.0_WP + END IF + + ! ------------------------------------------------------------------------- + ! 1032–1037 : No surface flux (additional RECOM fields) + ! ------------------------------------------------------------------------- + CASE (1032:1037) + bc_surface = 0.0_WP + + ! ========================================================================= + ! CARBON ISOTOPE TRACERS (requires __ciso preprocessor flag) + ! ========================================================================= + #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 + + ! ------------------------------------------------------------------------- + ! 1302 : DIC_13 – Dissolved 13C-labelled inorganic carbon + ! Source: isotopically fractionated air-sea CO2 flux + ! + MEDUSA loopback for 13C-DIC (k=6) and 13C-CaCO3 (k=7) + ! Only active when ciso = .true. + ! ------------------------------------------------------------------------- + CASE (1302) + 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 + + ! ------------------------------------------------------------------------- + ! 1305–1321 : Organic 13C tracers – no surface flux + ! ------------------------------------------------------------------------- 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 + bc_surface = 0.0_WP + + ! ------------------------------------------------------------------------- + ! 1402 : DIC_14 – Dissolved 14C-labelled inorganic carbon (radiocarbon) + ! Source: isotopically fractionated air-sea CO2 flux + ! + MEDUSA loopback for 14C-DIC (k=8) and 14C-CaCO3 (k=9) + ! (only when ciso_organic_14 is also enabled) + ! Only active when ciso = .true. AND ciso_14 = .true. + ! ------------------------------------------------------------------------- + CASE (1402) + 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 + + ! ------------------------------------------------------------------------- + ! 1405–1421 : Organic 14C tracers – no surface flux + ! ------------------------------------------------------------------------- CASE (1405:1421) - bc_surface=0.0_WP ! organic 14C + bc_surface = 0.0_WP + #endif + +#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 c80a1d1e3..f5ddf8559 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 48a5c84a1..5b9edf3a5 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -157,7 +157,6 @@ subroutine ocean_setup(dynamics, tracers, partit, mesh) case ('cvmix_PP+cvmix_TIDAL' ) ; mix_scheme_nmb = 47 case ('cvmix_TKE+cvmix_IDEMIX') ; mix_scheme_nmb = 56 #endif - case ('TOY' ) ; mix_scheme_nmb = 8 case default stop "!not existing mixing scheme!" call par_ex(partit%MPI_COMM_FESOM, partit%mype) @@ -320,7 +319,7 @@ SUBROUTINE tracer_init(tracers, partit, mesh) integer :: AB_order = 2 namelist /tracer_listsize/ num_tracers namelist /tracer_list / nml_tracer_list - namelist /tracer_general / smooth_bh_tra, gamma0_tra, gamma1_tra, gamma2_tra, i_vert_diff, AB_order, ltra_diag + namelist /tracer_general / smooth_bh_tra, gamma0_tra, gamma1_tra, gamma2_tra, i_vert_diff, AB_order !___________________________________________________________________________ ! pointer on necessary derived types #include "associate_part_def.h" @@ -498,11 +497,15 @@ SUBROUTINE tracer_init(tracers, partit, mesh) 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 @@ -527,7 +530,6 @@ SUBROUTINE dynamics_init(dynamics, partit, mesh) ! define dynamics namelist parameter integer :: opt_visc real(kind=WP) :: visc_gamma0, visc_gamma1, visc_gamma2 - real(kind=WP) :: visc_gamma0_h, visc_gamma1_h real(kind=WP) :: visc_easybsreturn logical :: use_ivertvisc=.true. logical :: uke_scaling=.true. @@ -553,7 +555,6 @@ SUBROUTINE dynamics_init(dynamics, partit, mesh) real(kind=WP) :: se_visc_gamma0, se_visc_gamma1, se_visc_gamma2 namelist /dynamics_visc / opt_visc, check_opt_visc, visc_gamma0, visc_gamma1, visc_gamma2, & - visc_gamma0_h, visc_gamma1_h, & use_ivertvisc, visc_easybsreturn, & uke_scaling, uke_scaling_factor, uke_advection, & rosb_dis, smooth_back, smooth_dis, smooth_back_tend, K_back, c_back @@ -593,8 +594,6 @@ SUBROUTINE dynamics_init(dynamics, partit, mesh) dynamics%visc_gamma0 = visc_gamma0 dynamics%visc_gamma1 = visc_gamma1 dynamics%visc_gamma2 = visc_gamma2 - dynamics%visc_gamma0_h = visc_gamma0_h - dynamics%visc_gamma1_h = visc_gamma1_h dynamics%visc_easybsreturn = visc_easybsreturn dynamics%uke_scaling = uke_scaling dynamics%uke_scaling_factor = uke_scaling_factor @@ -893,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 @@ -1005,21 +1006,23 @@ 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 allocate(density_ref(nl-1,node_size)) density_ref = density_0 allocate(density_m_rho0(nl-1, node_size)) - allocate(density_sigma0(nl-1, node_size)) allocate(density_m_rho0_slev(nl-1, node_size)) !!PS + allocate(density_sigma0(nl-1, node_size)) !!OG if (ldiag_dMOC) then allocate(density_dMOC (nl-1, node_size)) end if allocate(pgf_x(nl-1, elem_size),pgf_y(nl-1, elem_size)) density_m_rho0=0.0_WP - density_sigma0=0.0_WP density_m_rho0_slev=0.0_WP !!PS + density_sigma0=0.0_WP !!OG if (ldiag_dMOC) then density_dMOC =0.0_WP end if @@ -1126,6 +1129,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'read Nitrate climatology from:', trim(filelist(6)) write(*,*) 'read Salt climatology from:', trim(filelist(7)) write(*,*) 'read Temperature climatology from:', trim(filelist(8)) + write(*,*) 'read DIC remineralization from:', trim(filelist(9)) ! DICremin (added by Sina) end if ! read ocean state ! this must be always done! First two tracers with IDs 0 and 1 are the temperature and salinity. @@ -1211,7 +1215,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:1036) + 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/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc b/test/input/recom/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc index f2ede08cb..3c5292ae1 100644 Binary files a/test/input/recom/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc and b/test/input/recom/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc differ diff --git a/test/input/recom/din5deg.nc b/test/input/recom/din5deg.nc index e3a0e7db5..74d678dbc 100644 Binary files a/test/input/recom/din5deg.nc and b/test/input/recom/din5deg.nc differ diff --git a/test/input/recom/oxy5deg.nc b/test/input/recom/oxy5deg.nc index 4a1d8c992..6298ec1d2 100644 Binary files a/test/input/recom/oxy5deg.nc and b/test/input/recom/oxy5deg.nc differ diff --git a/test/input/recom/si5deg.nc b/test/input/recom/si5deg.nc index ebe088dbd..a81e284b4 100644 Binary files a/test/input/recom/si5deg.nc and b/test/input/recom/si5deg.nc differ diff --git a/test/input/recom/talk5deg.nc b/test/input/recom/talk5deg.nc index c62089056..25fde4bdc 100644 Binary files a/test/input/recom/talk5deg.nc and b/test/input/recom/talk5deg.nc differ