diff --git a/.github/workflows/fesom2_recom.yml b/.github/workflows/fesom2_recom.yml new file mode 100644 index 000000000..c511a2c79 --- /dev/null +++ b/.github/workflows/fesom2_recom.yml @@ -0,0 +1,95 @@ + +name: "FESOM2: REcoM Biogeochemistry" +# Controls when the action will run. Triggers the workflow on pull request only. +on: + workflow_dispatch: {} + pull_request: + types: + - opened + - synchronize + - reopened + branches: + - main +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + general_test: + # Containers must run in Linux based operating systems + runs-on: ubuntu-latest + # Docker Hub image that `container-job` executes in + container: ghcr.io/fesom/fesom2_docker:fesom2_test_refactoring-master + + # Service containers to run with `gfortran_ubuntu` + steps: + # NK: this changes working directory to fesom2 + - uses: actions/checkout@v2 + + - 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 + 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 + sed -i "s|woa13_all_i00_01_fesom2\.nc|si5deg.nc|" namelist.tra + sed -i "s|GLODAPv2\.2016b\.TAlk_fesom2_mmol_fix_z_Fillvalue\.nc|talk5deg.nc|" namelist.tra + 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 + ln -s DustClimMonthlyAlbani_pimesh.nc DustClimMonthlyAlbani.nc + cd ../../.. + + # Copy forcing data files (from 1948) + 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 + fcheck . diff --git a/cmake/BuildLibfyaml.cmake b/cmake/BuildLibfyaml.cmake index 920482619..4785de9a0 100644 --- a/cmake/BuildLibfyaml.cmake +++ b/cmake/BuildLibfyaml.cmake @@ -46,7 +46,7 @@ ExternalProject_Add(libfyaml-external BUILD_COMMAND make -j${CMAKE_BUILD_PARALLEL_LEVEL} -C src libfyaml.la BUILD_IN_SOURCE ON BUILD_BYPRODUCTS ${LIBFYAML_INSTALL_PREFIX}/lib/libfyaml.so - INSTALL_COMMAND make -C src install-libLTLIBRARIES install-includeHEADERS && make install-pkgconfigDATA + INSTALL_COMMAND make -C src install-libLTLIBRARIES install-includeHEADERS install-libfyamlHEADERS && make install-pkgconfigDATA LOG_DOWNLOAD OFF LOG_CONFIGURE OFF LOG_BUILD OFF diff --git a/config/bin_2p1z1d/job_albedo b/config/bin_2p1z1d/job_albedo index bac3e2b3a..d735fd967 100755 --- a/config/bin_2p1z1d/job_albedo +++ b/config/bin_2p1z1d/job_albedo @@ -1,16 +1,15 @@ #!/bin/bash -#SBATCH --account=nwg_hauck.maresys # edit your account -#SBATCH --job-name=recom +#SBATCH --account=biogeo_model.biogeo_model +#SBATCH --job-name=2p1z1d #SBATCH --partition=mpp -#SBATCH --time=01:30:00 -####SBATCH --constraint="[rack1|rack3]" +#SBATCH -N 9 +#SBATCH --cpus-per-task=1 +#SBATCH --time=08:00:00 #SBATCH --qos=12h -#SBATCH --nodes=9 # Number of tasks (MPI) tasks to be launched -#SBATCH --tasks-per-node 96 #8 #4 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O -#SBATCH --cpus-per-task 1 +#SBATCH --tasks-per-node 96 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O -#SBATCH -o fesom2o.out -#SBATCH -e fesom2e.out +#SBATCH -o slurm-out.out +#SBATCH -e slurm-err.out # disable hyperthreading #SBATCH --hint=nomultithread @@ -23,35 +22,33 @@ 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 . +#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_${SLURM_JOB_NAME}_${jobid}.out" +fname="fesom2.0.out" #___PUT JOB IN QUEUE____________________________________________________________ date -####srun --mpi=pmi2 ./fesom.x >> ${fname} srun --mpi=pmi2 ./fesom.x > fesom2.0.out date #qstat -f $PBS_JOBID #export EXITSTATUS=$? #if [ ${EXITSTATUS} -eq 0 ] || [ ${EXITSTATUS} -eq 127 ] ; then -#sbatch job_ollie +#sbatch job_albedo #fi -#Resultpath='/albedo/scratch/user/ogurses/ocean_only/' -Resultpath='/albedo/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags/' -test -d $Resultpath/fesom.2019.oce.restart && exit +Resultpath='/albedo/work/user/...' +test -e $Resultpath/fesom.xxxxx.oce.restart && exit IsInFile=$( tail -3 fesom2.0.out | grep -c timesteps) if (( IsInFile > 0 )); then diff --git a/config/bin_2p1z1d/namelist.config b/config/bin_2p1z1d/namelist.config index eb9a4375d..ffff081c0 100644 --- a/config/bin_2p1z1d/namelist.config +++ b/config/bin_2p1z1d/namelist.config @@ -6,8 +6,8 @@ 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 +run_length= 1 !62 !62 !62 !28 +run_length_unit='y' ! y, m, d, s / &clockinit ! the model starts at @@ -18,8 +18,8 @@ yearnew=1958 &paths MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' -ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' -ResultPath='/albedo/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags/' +ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' +ResultPath='/albedo/work/user/...' / &restart_log @@ -29,7 +29,7 @@ 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 +logfile_outfreq=960 !in logfile info. output frequency, # steps / &ale_def @@ -59,9 +59,18 @@ 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_2p1z1d/namelist.forcing b/config/bin_2p1z1d/namelist.forcing index a17799393..d890c69ec 100644 --- a/config/bin_2p1z1d/namelist.forcing +++ b/config/bin_2p1z1d/namelist.forcing @@ -23,11 +23,23 @@ ncar_bulk_z_shum=10.0 ! height at which humi forcing is located (CORE, JRA-do: 1 use_landice_water=.false. landice_start_mon=5 landice_end_mon=10 +fwf_path='./mesh/' + +/ + +&age_tracer +use_age_tracer=.false. +use_age_mask=.false. +age_tracer_path='./mesh/' +age_start_year=2000 + / &nam_sbc nm_xwind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 nm_ywind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 + nm_xstre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 + nm_ystre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 nm_humi_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/huss.clim61' ! name of file with humidity nm_qsr_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rsds.clim61' ! name of file with solar heat nm_qlw_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rlds.clim61' ! name of file with Long wave @@ -37,24 +49,32 @@ landice_end_mon=10 nm_mslp_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/psl.clim61' ! air_pressure_at_sea_level nm_xwind_var = 'uas' ! name of variable in file with wind nm_ywind_var = 'vas' ! name of variable in file with wind - nm_humi_var = 'huss' ! name of variable in file with humidity - nm_qsr_var = 'rsds' ! name of variable in file with solar heat - nm_qlw_var = 'rlds' ! name of variable in file with Long wave + nm_xstre_var = 'uas' ! name of variable in file with wind + nm_ystre_var = 'vas' ! name of variable in file with wind + nm_humi_var = 'huss' ! name of variable in file with humidity + nm_qsr_var = 'rsds' ! name of variable in file with solar heat + nm_qlw_var = 'rlds' ! name of variable in file with Long wave nm_tair_var = 'tas' ! name of variable in file with 2m air temperature - nm_prec_var = 'prra' ! name of variable in file with total precipitation - nm_snow_var = 'prsn' ! name of variable in file with total precipitation - nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level + nm_prec_var = 'prra' ! name of variable in file with total precipitation + nm_snow_var = 'prsn' ! name of variable in file with total precipitation + nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level nm_nc_iyear = 1900 nm_nc_imm = 1 ! initial month of time axis in netCDF nm_nc_idd = 1 ! initial day of time axis in netCDF nm_nc_freq = 1 ! data points per day (i.e. 86400 if the time axis is in seconds) nm_nc_tmid = 0 ! 1 if the time stamps are given at the mid points of the netcdf file, 0 otherwise (i.e. 1 in CORE1, CORE2; 0 in JRA55) y_perpetual=.true. - l_xwind=.true. l_ywind=.true. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. + l_xwind=.true. l_ywind=.true. l_xstre=.false. l_ystre=.false. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. nm_runoff_file ='/albedo/pool/FESOM/forcing/CORE2/runoff.nc' runoff_data_source ='CORE2' !Dai09, CORE2 !runoff_data_source ='Dai09' !Dai09, CORE2, JRA55 !runoff_climatology =.true. - nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' sss_data_source ='CORE2' + nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' + chl_data_source ='None' !'Sweeney' monthly chlorophyll climatology or 'NONE' for constant chl_const (below). Make use_sw_pene=.TRUE. in namelist.config! + nm_chl_data_file ='/pool/data/AWICM/FESOM2/FORCING/JRA55-do-v1.4.0/Sweeney/Sweeney_2005.nc' + chl_const = 0.1 + use_runoff_mapper = .FALSE. + runoff_basins_file = 'runoff_maps_regular.nc' + runoff_radius = 500000. / diff --git a/config/bin_2p1z1d/namelist.icepack.cesm.ponds b/config/bin_2p1z1d/namelist.icepack.cesm.ponds new file mode 100644 index 000000000..51aa33191 --- /dev/null +++ b/config/bin_2p1z1d/namelist.icepack.cesm.ponds @@ -0,0 +1,144 @@ +&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 = 1 ! 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 = .true. + 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 +/ + +&shortwave_nml + shortwave = 'dEdd' + albedo_type = 'ccsm3' + albicev = 0.78 + albicei = 0.36 + albsnowv = 0.98 + albsnowi = 0.70 + 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_2p1z1d/namelist.io b/config/bin_2p1z1d/namelist.io index 7a6fe3cff..990c90c2f 100644 --- a/config/bin_2p1z1d/namelist.io +++ b/config/bin_2p1z1d/namelist.io @@ -12,7 +12,7 @@ ldiag_extflds =.false. / &nml_general -io_listsize =100 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list +io_listsize =150 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list vec_autorotate =.false. / @@ -40,11 +40,11 @@ io_list = 'sst ',1, 'm', 4, 'otracers ',1, 'm', 4, 'N2 ',1, 'y', 4, 'Kv ',1, 'y', 4, - 'u ',1, 'y', 4, - 'v ',1, 'y', 4, - 'unod ',1, 'y', 4, - 'vnod ',1, 'y', 4, - 'w ',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, diff --git a/config/bin_2p1z1d/namelist.recom b/config/bin_2p1z1d/namelist.recom index dd53c8538..bcdea2e79 100644 --- a/config/bin_2p1z1d/namelist.recom +++ b/config/bin_2p1z1d/namelist.recom @@ -9,11 +9,16 @@ nm_erosion_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_fina nm_co2_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/MonthlyAtmCO2_gcb2023.nc' / +&parecomsetup +enable_3zoo2det = .true. +enable_coccos = .false. +/ + &pavariables use_REcoM =.true. REcoM_restart =.true. -bgc_num = 22 !33 !24 !38 +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 @@ -28,12 +33,12 @@ REcoM_Grazing_Variable_Preference = .true. ! Decides if grazing should have pref Grazing_detritus = .true. het_resp_noredfield = .true. ! Decides respiratation of copepod group diatom_mucus = .true. ! Decides nutrient limitation effect on aggregation -O2dep_remin = .false. ! O2remin Add option for O2 dependency of organic matter remineralization -use_ballasting = .false. ! BALL -use_density_scaling = .false. ! BALL -use_viscosity_scaling = .false. ! BALL -OmegaC_diss = .false. ! DISS Use OmegaC from Mocsy to compute calcite dissolution (after Aumont et al. 2015 and Gehlen et al. 2007) -CO2lim = .false. ! CO2 dependence of growth and calcification +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. constant_CO2 = .true. UseFeDust = .true. ! Turns dust input of iron off when set to.false. @@ -49,7 +54,7 @@ useErosion = .false. NitrogenSS = .false. ! When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) useAeolianN = .false. ! When set to true, aeolian nitrogen deposition is activated firstyearoffesomcycle = 1958 ! The first year of the actual physical forcing (e.g. JRA-55) used -lastyearoffesomcycle = 2022 ! Last year of the actual physical forcing used +lastyearoffesomcycle = 2024 ! Last year of the actual physical forcing used numofCO2cycles = 1 ! Number of cycles of the forcing planned currentCO2cycle = 1 ! Which CO2 cycle we are currently running DIC_PI = .true. @@ -81,23 +86,23 @@ recom_Tref = 288.15d0 ! [K] C2K = 273.15d0 ! Conversion from degrees C to K Ae = 4500.d0 ! [K] Slope of the linear part of the Arrhenius function reminSi = 0.02d0 -k_o2_remin = 15.d0 ! NEW O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 +k_o2_remin = 15.d0 ! O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 / &palimiter_function NMinSlope = 50.d0 SiMinSlope = 1000.d0 -NCmin = 0.04d0 !0.05d0 -NCmin_d = 0.04d0 !0.05d0 -NCmin_c = 0.04d0 ! NEW +NCmin = 0.04d0 +NCmin_d = 0.04d0 +NCmin_c = 0.04d0 SiCmin = 0.04d0 k_Fe = 0.04d0 k_Fe_d = 0.12d0 -k_Fe_c = 0.09d0 ! NEW +k_Fe_c = 0.09d0 k_si = 4.d0 P_cm = 3.0d0 ! [1/day] Rate of C-specific photosynthesis P_cm_d = 3.5d0 -P_cm_c = 2.8d0 ! NEW +P_cm_c = 2.8d0 / &palight_calculations @@ -108,33 +113,33 @@ a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific at &paphotosynthesis alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] alfa_d = 0.19d0 ! An initial slope of the P-I curve -alfa_c = 0.10d0 ! NEW +alfa_c = 0.10d0 parFrac = 0.43d0 / &paassimilation V_cm_fact = 0.7d0 ! scaling factor for temperature dependent maximum of C-specific N-uptake V_cm_fact_d = 0.7d0 -V_cm_fact_c = 0.7d0 ! NEW +V_cm_fact_c = 0.7d0 NMaxSlope = 1000.d0 ! Max slope for limiting function SiMaxSlope = 1000.d0 NCmax = 0.2d0 ! [mmol N/mmol C] Maximum cell quota of nitrogen (N:C) NCmax_d = 0.2d0 -NCmax_c = 0.15d0 ! NEW +NCmax_c = 0.15d0 SiCmax = 0.8d0 NCuptakeRatio = 0.2d0 ! [mmol N/mmol C] Maximum uptake ratio of N:C NCUptakeRatio_d = 0.2d0 -NCUptakeRatio_c = 0.2d0 ! NEW +NCUptakeRatio_c = 0.2d0 SiCUptakeRatio = 0.2d0 k_din = 0.55d0 ! [mmol N/m3] Half-saturation constant for nitrate uptake k_din_d = 1.0d0 -k_din_c = 0.9d0 ! NEW +k_din_c = 0.9d0 Chl2N_max = 3.15d0 ! [mg CHL/mmol N] Maximum CHL a : N ratio = 0.3 gCHL gN^-1 Chl2N_max_d = 4.2d0 -Chl2N_max_c = 3.5d0 ! NEW +Chl2N_max_c = 3.5d0 res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant res_phy_d = 0.01d0 -res_phy_c = 0.01d0 ! NEW +res_phy_c = 0.01d0 biosynth = 2.33d0 ! [mmol C/mmol N] Cost of biosynthesis biosynthSi = 0.d0 / @@ -145,67 +150,69 @@ ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron sta / &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) +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.04d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) -pzDia = 1.0d0 !0.5d0 ! Maximum diatom preference +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 = 0.5d0 !0.25d0 !1.0d0 ! Maximum nano-phytoplankton preference (NEW: 3/12) +pzPhy = 1.0d0 ! Maximum small phytoplankton preference sPhyNsq = 0.d0 -pzCocco = 0.666d0 ! NEW (8/12) -sCoccoNsq = 0.d0 ! NEW -pzMicZoo = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference -sMicZooNsq = 0.d0 ! NEW 3Zoo +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 +&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 ! NEW 3Zoo -fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo -pzDia2 = 1.5d0 !1.d0 ! Maximum diatom preference +fecal_rate_n_mes = 0.25d0 +fecal_rate_c_mes = 0.32d0 +pzDia2 = 1.0d0 ! Maximum diatom preference sDiaNsq2 = 0.d0 -pzPhy2 = 0.5d0 ! Maximum diatom preference +pzPhy2 = 0.08d0 ! Maximum small phytoplankton preference sPhyNsq2 = 0.d0 -pzCocco2 = 0.5d0 ! NEW -sCoccoNsq2 = 0.d0 ! NEW -pzHet = 1.5d0 !0.8d0 ! Maximum diatom preference +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 -graz_max3 = 0.46d0 ! NEW 3Zoo [mmol N/(m3 * day)] Maximum grazing loss parameter -epsilon3 = 0.64d0 ! NEW 3Zoo [(mmol N)2 /m6] Half saturation constant for grazing loss -loss_miczoo = 0.01d0 ! NEW 3Zoo [1/day] Temperature dependent N degradation of extracellular organic N (EON) -res_miczoo = 0.01d0 ! NEW 3Zoo [1/day] Respiration by heterotrophs and mortality (loss to detritus) -pzDia3 = 0.5d0 ! NEW 3Zoo Maximum diatom preference -sDiaNsq3 = 0.d0 ! NEW 3Zoo -pzPhy3 = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference -sPhyNsq3 = 0.d0 ! NEW 3Zoo -pzCocco3 = 0.d0 ! NEW 3Zoo Maximum coccolithophore preference ! ATTENTION: This value needs to be tuned; I start with zero preference! -sCoccoNsq3 = 0.d0 ! NEW 3Zoo +&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 / &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 -sDetNsq2 = 0.d0 -pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton -sDetZ2Nsq2 = 0.d0 +pzDet2 = 0.5d0 ! Maximum small detritus prefence by second zooplankton +sDetNsq2 = 0.d0 +pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton +sDetZ2Nsq2 = 0.d0 / &paaggregation @@ -224,25 +231,25 @@ rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradatio &paphytoplankton_N lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds lossN_d = 0.05d0 -lossN_c = 0.05d0 ! NEW +lossN_c = 0.05d0 / &paphytoplankton_C lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon lossC_d = 0.10d0 -lossC_c = 0.10d0 ! NEW +lossC_c = 0.10d0 / &paphytoplankton_ChlA -deg_Chl = 0.25d0 !0.2d0 !0.25d0 ! [1/day] -deg_Chl_d = 0.15d0 !0.2d0 !0.15d0 -deg_Chl_c = 0.2d0 ! NEW (has been 0.5) +deg_Chl = 0.075 !0.2d0 !0.25d0 ! [1/day] +deg_Chl_d = 0.075 !0.3d0 !0.15d0 +deg_Chl_c = 0.075 !0.2d0 / &padetritus_N -gfin = 0.3d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into zooplankton pool) +gfin = 0.3d0 ! [] Grazing efficiency (fraction of grazing flux into zooplankton pool) grazEff2 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into second zooplankton pool) -grazEff3 = 0.8d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) +grazEff3 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) reminN = 0.165d0 ! [1/day] Temperature dependent remineralisation rate of detritus / @@ -252,8 +259,8 @@ rho_c2 = 0.1d0 ! [1/day] Temperature dependent C degradatio / &paheterotrophs -lossN_z = 0.1d0 -lossC_z = 0.1d0 +lossN_z = 0.15d0 +lossC_z = 0.15d0 / &paseczooloss @@ -262,11 +269,11 @@ lossC_z2 = 0.02d0 / &pathirdzooloss -lossN_z3 = 0.05d0 ! NEW 3Zoo -lossC_z3 = 0.05d0 ! NEW 3Zoo +lossN_z3 = 0.05d0 +lossC_z3 = 0.05d0 / -&paco2lim ! NEW +&paco2lim Cunits = 976.5625 ! Conversion factor between [mol/m3] (model) and [umol/kg] (function): (1000 * 1000) / 1024 a_co2_phy = 1.162e+00 ! [dimensionless] a_co2_dia = 1.040e+00 ! [dimensionless] @@ -296,11 +303,11 @@ RiverFeConc = 100 &pacalc calc_prod_ratio = 0.02 -calc_diss_guts = 0.0d0 -calc_diss_rate = 0.005714 ! 20.d0/3500.d0 +calc_diss_guts = 0.0d0 ! set to zero if OmegaC_diss is set to false +calc_diss_rate = 0.005714d0 ! 20.d0/3500.d0 calc_diss_rate2 = 0.005714d0 -calc_diss_omegac = 0.197d0 ! NEW DISS Value from Aumont et al. 2015, will be used with OmegaC_diss flag -calc_diss_exp = 1.d0 ! NEW DISS Exponent in the dissolution rate of calcite, will be used with OmegaC_diss flag +calc_diss_omegac = 0.197d0 ! Value from Aumont et al. 2015, is used with OmegaC_diss flag +calc_diss_exp = 1.d0 ! Exponent in the dissolution rate of calcite, is used with OmegaC_diss flag / &pabenthos_decay_rate @@ -331,9 +338,9 @@ rho_opal = 2090.d0 ! kg m-3; density of Opal (see Table 1 in Cram rho_ref_part = 1230.d0 ! kg m-3; reference particle density (see Cram et al., 2018) rho_ref_water = 1027.d0 ! kg m-3; reference seawater density (see Cram et al., 2018) visc_ref_water = 0.00158d0 ! kg m-1 s-1; reference seawater viscosity, at Temp=4 degC (see Cram et al., 2018) -w_ref1 = 10.d0 ! m s-1; reference sinking velocity of small detritus +w_ref1 = 5.d0 ! m s-1; reference sinking velocity of small detritus w_ref2 = 200.d0 ! m s-1; reference sinking velocity of large detritus -depth_scaling1 = 0.015d0 ! s-1; factor to increase sinking speed of det1 with depth, set to 0 if not wanted +depth_scaling1 = 0.01d0 ! s-1; factor to increase sinking speed of det1 with depth, set to 0 if not wanted depth_scaling2 = 0.d0 ! s-1; factor to increase sinking speed of det2 with depth, set to 0 if not wanted max_sinking_velocity = 250.d0 ! d-1; for numerical stability, set a maximum possible sinking velocity here (applies to both detritus classes) / @@ -351,3 +358,4 @@ atbox_spinup = .false. cosmic_14_init = 2.0 / + diff --git a/config/bin_2p3z2d/job_albedo b/config/bin_2p3z2d/job_albedo index 5f3c516e7..d6e379887 100755 --- a/config/bin_2p3z2d/job_albedo +++ b/config/bin_2p3z2d/job_albedo @@ -1,16 +1,15 @@ #!/bin/bash -#SBATCH --account=nwg_hauck.maresys # edit your account -#SBATCH --job-name=recom +#SBATCH --account=biogeo_model.biogeo_model +#SBATCH --job-name=2p3z2d #SBATCH --partition=mpp -#SBATCH --time=01:30:00 -####SBATCH --constraint="[rack1|rack3]" +#SBATCH -N 9 +#SBATCH --cpus-per-task=1 +#SBATCH --time=08:00:00 #SBATCH --qos=12h -#SBATCH --nodes=9 # Number of tasks (MPI) tasks to be launched -#SBATCH --tasks-per-node 96 #8 #4 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O -#SBATCH --cpus-per-task 1 +#SBATCH --tasks-per-node 96 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O -#SBATCH -o fesom2o.out -#SBATCH -e fesom2e.out +#SBATCH -o slurm-out.out +#SBATCH -e slurm-err.out # disable hyperthreading #SBATCH --hint=nomultithread @@ -23,35 +22,33 @@ 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 . +#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_${SLURM_JOB_NAME}_${jobid}.out" +fname="fesom2.0.out" #___PUT JOB IN QUEUE____________________________________________________________ date -####srun --mpi=pmi2 ./fesom.x >> ${fname} srun --mpi=pmi2 ./fesom.x > fesom2.0.out date #qstat -f $PBS_JOBID #export EXITSTATUS=$? #if [ ${EXITSTATUS} -eq 0 ] || [ ${EXITSTATUS} -eq 127 ] ; then -#sbatch job_ollie +#sbatch job_albedo #fi -#Resultpath='/albedo/scratch/user/ogurses/ocean_only/' -Resultpath='/albedo/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags_3Zoo2Det_v3/' -test -d $Resultpath/fesom.2019.oce.restart && exit +Resultpath='/albedo/work/user/xxx' +test -e $Resultpath/fesom.xxx.oce.restart && exit IsInFile=$( tail -3 fesom2.0.out | grep -c timesteps) if (( IsInFile > 0 )); then diff --git a/config/bin_2p3z2d/namelist.config b/config/bin_2p3z2d/namelist.config index 25c5e4a31..ffff081c0 100644 --- a/config/bin_2p3z2d/namelist.config +++ b/config/bin_2p3z2d/namelist.config @@ -6,8 +6,8 @@ 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 +run_length= 1 !62 !62 !62 !28 +run_length_unit='y' ! y, m, d, s / &clockinit ! the model starts at @@ -18,8 +18,8 @@ yearnew=1958 &paths MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' -ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' -ResultPath='/albedo/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags_3Zoo2Det_v3/' +ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' +ResultPath='/albedo/work/user/...' / &restart_log @@ -29,7 +29,7 @@ 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 +logfile_outfreq=960 !in logfile info. output frequency, # steps / &ale_def @@ -59,9 +59,18 @@ use_cavity_partial_cell=.false. use_floatice = .false. use_sw_pene=.true. flag_debug=.false. +use_transit=.false. / &machine n_levels=2 n_part= 12, 36 ! 432 number of partitions on each hierarchy level / + +&icebergs +use_icesheet_coupling=.false. +ib_num=1 +use_icebergs=.false. +steps_per_ib_step=8 +ib_async_mode=0 +/ diff --git a/config/bin_2p3z2d/namelist.forcing b/config/bin_2p3z2d/namelist.forcing index a17799393..d890c69ec 100644 --- a/config/bin_2p3z2d/namelist.forcing +++ b/config/bin_2p3z2d/namelist.forcing @@ -23,11 +23,23 @@ ncar_bulk_z_shum=10.0 ! height at which humi forcing is located (CORE, JRA-do: 1 use_landice_water=.false. landice_start_mon=5 landice_end_mon=10 +fwf_path='./mesh/' + +/ + +&age_tracer +use_age_tracer=.false. +use_age_mask=.false. +age_tracer_path='./mesh/' +age_start_year=2000 + / &nam_sbc nm_xwind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 nm_ywind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 + nm_xstre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 + nm_ystre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 nm_humi_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/huss.clim61' ! name of file with humidity nm_qsr_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rsds.clim61' ! name of file with solar heat nm_qlw_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rlds.clim61' ! name of file with Long wave @@ -37,24 +49,32 @@ landice_end_mon=10 nm_mslp_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/psl.clim61' ! air_pressure_at_sea_level nm_xwind_var = 'uas' ! name of variable in file with wind nm_ywind_var = 'vas' ! name of variable in file with wind - nm_humi_var = 'huss' ! name of variable in file with humidity - nm_qsr_var = 'rsds' ! name of variable in file with solar heat - nm_qlw_var = 'rlds' ! name of variable in file with Long wave + nm_xstre_var = 'uas' ! name of variable in file with wind + nm_ystre_var = 'vas' ! name of variable in file with wind + nm_humi_var = 'huss' ! name of variable in file with humidity + nm_qsr_var = 'rsds' ! name of variable in file with solar heat + nm_qlw_var = 'rlds' ! name of variable in file with Long wave nm_tair_var = 'tas' ! name of variable in file with 2m air temperature - nm_prec_var = 'prra' ! name of variable in file with total precipitation - nm_snow_var = 'prsn' ! name of variable in file with total precipitation - nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level + nm_prec_var = 'prra' ! name of variable in file with total precipitation + nm_snow_var = 'prsn' ! name of variable in file with total precipitation + nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level nm_nc_iyear = 1900 nm_nc_imm = 1 ! initial month of time axis in netCDF nm_nc_idd = 1 ! initial day of time axis in netCDF nm_nc_freq = 1 ! data points per day (i.e. 86400 if the time axis is in seconds) nm_nc_tmid = 0 ! 1 if the time stamps are given at the mid points of the netcdf file, 0 otherwise (i.e. 1 in CORE1, CORE2; 0 in JRA55) y_perpetual=.true. - l_xwind=.true. l_ywind=.true. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. + l_xwind=.true. l_ywind=.true. l_xstre=.false. l_ystre=.false. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. nm_runoff_file ='/albedo/pool/FESOM/forcing/CORE2/runoff.nc' runoff_data_source ='CORE2' !Dai09, CORE2 !runoff_data_source ='Dai09' !Dai09, CORE2, JRA55 !runoff_climatology =.true. - nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' sss_data_source ='CORE2' + nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' + chl_data_source ='None' !'Sweeney' monthly chlorophyll climatology or 'NONE' for constant chl_const (below). Make use_sw_pene=.TRUE. in namelist.config! + nm_chl_data_file ='/pool/data/AWICM/FESOM2/FORCING/JRA55-do-v1.4.0/Sweeney/Sweeney_2005.nc' + chl_const = 0.1 + use_runoff_mapper = .FALSE. + runoff_basins_file = 'runoff_maps_regular.nc' + runoff_radius = 500000. / diff --git a/config/bin_2p3z2d/namelist.icepack.cesm.ponds b/config/bin_2p3z2d/namelist.icepack.cesm.ponds new file mode 100644 index 000000000..51aa33191 --- /dev/null +++ b/config/bin_2p3z2d/namelist.icepack.cesm.ponds @@ -0,0 +1,144 @@ +&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 = 1 ! 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 = .true. + 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 +/ + +&shortwave_nml + shortwave = 'dEdd' + albedo_type = 'ccsm3' + albicev = 0.78 + albicei = 0.36 + albsnowv = 0.98 + albsnowi = 0.70 + 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_2p3z2d/namelist.io b/config/bin_2p3z2d/namelist.io index 01bcab49f..10bb72c1b 100644 --- a/config/bin_2p3z2d/namelist.io +++ b/config/bin_2p3z2d/namelist.io @@ -12,7 +12,7 @@ ldiag_extflds =.false. / &nml_general -io_listsize =100 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list +io_listsize =150 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list vec_autorotate =.false. / @@ -40,11 +40,11 @@ io_list = 'sst ',1, 'm', 4, 'otracers ',1, 'm', 4, 'N2 ',1, 'y', 4, 'Kv ',1, 'y', 4, - 'u ',1, 'y', 4, - 'v ',1, 'y', 4, - 'unod ',1, 'y', 4, - 'vnod ',1, 'y', 4, - 'w ',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, diff --git a/config/bin_2p3z2d/namelist.recom b/config/bin_2p3z2d/namelist.recom index 24145b956..af69391f2 100644 --- a/config/bin_2p3z2d/namelist.recom +++ b/config/bin_2p3z2d/namelist.recom @@ -9,11 +9,16 @@ nm_erosion_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_fina nm_co2_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/MonthlyAtmCO2_gcb2023.nc' / +&parecomsetup +enable_3zoo2det = .true. +enable_coccos = .false. +/ + &pavariables use_REcoM =.true. REcoM_restart =.true. -bgc_num = 30 !22 !33 !24 !38 +bgc_num = 30 !24 !38 !22 diags3d_num = 28 ! Number of diagnostic 3d tracers to be saved bgc_base_num = 22 ! standard tracers VDet = 20.d0 ! Sinking velocity, constant through the water column and positive downwards @@ -28,12 +33,12 @@ REcoM_Grazing_Variable_Preference = .true. ! Decides if grazing should have pref Grazing_detritus = .true. het_resp_noredfield = .true. ! Decides respiratation of copepod group diatom_mucus = .true. ! Decides nutrient limitation effect on aggregation -O2dep_remin = .false. ! O2remin Add option for O2 dependency of organic matter remineralization -use_ballasting = .false. ! BALL -use_density_scaling = .false. ! BALL -use_viscosity_scaling = .false. ! BALL -OmegaC_diss = .false. ! DISS Use OmegaC from Mocsy to compute calcite dissolution (after Aumont et al. 2015 and Gehlen et al. 2007) -CO2lim = .false. ! CO2 dependence of growth and calcification +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. constant_CO2 = .true. UseFeDust = .true. ! Turns dust input of iron off when set to.false. @@ -49,7 +54,7 @@ useErosion = .false. NitrogenSS = .false. ! When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) useAeolianN = .false. ! When set to true, aeolian nitrogen deposition is activated firstyearoffesomcycle = 1958 ! The first year of the actual physical forcing (e.g. JRA-55) used -lastyearoffesomcycle = 2022 ! Last year of the actual physical forcing used +lastyearoffesomcycle = 2024 ! Last year of the actual physical forcing used numofCO2cycles = 1 ! Number of cycles of the forcing planned currentCO2cycle = 1 ! Which CO2 cycle we are currently running DIC_PI = .true. @@ -81,23 +86,23 @@ recom_Tref = 288.15d0 ! [K] C2K = 273.15d0 ! Conversion from degrees C to K Ae = 4500.d0 ! [K] Slope of the linear part of the Arrhenius function reminSi = 0.02d0 -k_o2_remin = 15.d0 ! NEW O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 +k_o2_remin = 15.d0 ! O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 / &palimiter_function NMinSlope = 50.d0 SiMinSlope = 1000.d0 -NCmin = 0.04d0 !0.05d0 -NCmin_d = 0.04d0 !0.05d0 -NCmin_c = 0.04d0 ! NEW +NCmin = 0.04d0 +NCmin_d = 0.04d0 +NCmin_c = 0.04d0 SiCmin = 0.04d0 k_Fe = 0.04d0 k_Fe_d = 0.12d0 -k_Fe_c = 0.09d0 ! NEW +k_Fe_c = 0.09d0 k_si = 4.d0 P_cm = 3.0d0 ! [1/day] Rate of C-specific photosynthesis P_cm_d = 3.5d0 -P_cm_c = 2.8d0 ! NEW +P_cm_c = 2.8d0 / &palight_calculations @@ -108,33 +113,33 @@ a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific at &paphotosynthesis alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] alfa_d = 0.19d0 ! An initial slope of the P-I curve -alfa_c = 0.10d0 ! NEW +alfa_c = 0.10d0 parFrac = 0.43d0 / &paassimilation V_cm_fact = 0.7d0 ! scaling factor for temperature dependent maximum of C-specific N-uptake V_cm_fact_d = 0.7d0 -V_cm_fact_c = 0.7d0 ! NEW +V_cm_fact_c = 0.7d0 NMaxSlope = 1000.d0 ! Max slope for limiting function SiMaxSlope = 1000.d0 NCmax = 0.2d0 ! [mmol N/mmol C] Maximum cell quota of nitrogen (N:C) NCmax_d = 0.2d0 -NCmax_c = 0.15d0 ! NEW +NCmax_c = 0.15d0 SiCmax = 0.8d0 NCuptakeRatio = 0.2d0 ! [mmol N/mmol C] Maximum uptake ratio of N:C NCUptakeRatio_d = 0.2d0 -NCUptakeRatio_c = 0.2d0 ! NEW +NCUptakeRatio_c = 0.2d0 SiCUptakeRatio = 0.2d0 k_din = 0.55d0 ! [mmol N/m3] Half-saturation constant for nitrate uptake k_din_d = 1.0d0 -k_din_c = 0.9d0 ! NEW +k_din_c = 0.9d0 Chl2N_max = 3.15d0 ! [mg CHL/mmol N] Maximum CHL a : N ratio = 0.3 gCHL gN^-1 Chl2N_max_d = 4.2d0 -Chl2N_max_c = 3.5d0 ! NEW +Chl2N_max_c = 3.5d0 res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant res_phy_d = 0.01d0 -res_phy_c = 0.01d0 ! NEW +res_phy_c = 0.01d0 biosynth = 2.33d0 ! [mmol C/mmol N] Cost of biosynthesis biosynthSi = 0.d0 / @@ -145,19 +150,19 @@ ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron sta / &pazooplankton -graz_max = 0.31d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +graz_max = 0.31d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter epsilonr = 0.09d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss -res_het = 0.028d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +res_het = 0.028d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) Redfield = 6.625 ! [mmol C/mmol N] Redfield ratio of C:N = 106:16 loss_het = 0.04d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) -pzDia = 1.0d0 !0.5d0 ! Maximum diatom preference +pzDia = 0.5d0 ! Maximum diatom preference sDiaNsq = 0.d0 -pzPhy = 0.5d0 !0.25d0 !1.0d0 ! Maximum nano-phytoplankton preference (NEW: 3/12) +pzPhy = 0.04d0 ! Maximum small phytoplankton preference sPhyNsq = 0.d0 -pzCocco = 0.666d0 ! NEW (8/12) -sCoccoNsq = 0.d0 ! NEW -pzMicZoo = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference -sMicZooNsq = 0.d0 ! NEW 3Zoo +pzCocco = 0.4d0 ! Maximum coccolithophore preference ! will not be used in the 2p3z3d version +sCoccoNsq = 0.d0 +pzMicZoo = 1.0d0 ! Maximum microzooplankton preference +sMicZooNsq = 0.d0 tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. / @@ -168,17 +173,17 @@ res_zoo2 = 0.0107d0 ! [1/day] Respiration by heterotrophs and mo loss_zoo2 = 0.003d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) fecal_rate_n = 0.104d0 ! [1/day] Temperature dependent N degradation of \ fecal_rate_c = 0.236d0 -fecal_rate_n_mes = 0.25d0 ! NEW 3Zoo -fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo -pzDia2 = 1.5d0 !1.d0 ! Maximum diatom preference +fecal_rate_n_mes = 0.25d0 +fecal_rate_c_mes = 0.32d0 +pzDia2 = 1.0d0 ! Maximum diatom preference sDiaNsq2 = 0.d0 -pzPhy2 = 0.5d0 ! Maximum diatom preference +pzPhy2 = 0.07d0 ! Maximum small phytoplankton preference sPhyNsq2 = 0.d0 -pzCocco2 = 0.5d0 ! NEW -sCoccoNsq2 = 0.d0 ! NEW -pzHet = 1.5d0 !0.8d0 ! Maximum diatom preference +pzCocco2 = 0.7d0 ! Maximum coccolithophore preference ! will not be used in the 2p3z3d version +sCoccoNsq2 = 0.d0 +pzHet = 1.5d0 ! Maximum mesozooplankton preference sHetNsq = 0.d0 -pzMicZoo2 = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference +pzMicZoo2 = 1.0d0 ! Maximum microzooplankton preference sMicZooNsq2 = 0.d0 t1_zoo2 = 28145.d0 ! Krill temp. function constant1 t2_zoo2 = 272.5d0 ! Krill temp. function constant2 @@ -187,27 +192,27 @@ t4_zoo2 = 274.15d0 ! Krill temp. function constant3 / &pathirdzooplankton -graz_max3 = 0.46d0 ! NEW 3Zoo [mmol N/(m3 * day)] Maximum grazing loss parameter -epsilon3 = 0.64d0 ! NEW 3Zoo [(mmol N)2 /m6] Half saturation constant for grazing loss -loss_miczoo = 0.01d0 ! NEW 3Zoo [1/day] Temperature dependent N degradation of extracellular organic N (EON) -res_miczoo = 0.01d0 ! NEW 3Zoo [1/day] Respiration by heterotrophs and mortality (loss to detritus) -pzDia3 = 0.5d0 ! NEW 3Zoo Maximum diatom preference -sDiaNsq3 = 0.d0 ! NEW 3Zoo -pzPhy3 = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference -sPhyNsq3 = 0.d0 ! NEW 3Zoo -pzCocco3 = 0.d0 ! NEW 3Zoo Maximum coccolithophore preference ! ATTENTION: This value needs to be tuned; I start with zero preference! -sCoccoNsq3 = 0.d0 ! NEW 3Zoo +graz_max3 = 0.46d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilon3 = 0.64d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss +loss_miczoo = 0.01d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) +res_miczoo = 0.02d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +pzDia3 = 0.04d0 ! Maximum diatom preference +sDiaNsq3 = 0.d0 +pzPhy3 = 0.07d0 ! Maximum small phytoplankton preference +sPhyNsq3 = 0.d0 +pzCocco3 = 0.7d0 ! Maximum coccolithophore preference ! will not be used in the 2p3z3d version +sCoccoNsq3 = 0.d0 / &pagrazingdetritus -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 -sDetNsq2 = 0.d0 -pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton -sDetZ2Nsq2 = 0.d0 +pzDet2 = 0.5d0 ! Maximum small detritus prefence by second zooplankton +sDetNsq2 = 0.d0 +pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton +sDetZ2Nsq2 = 0.d0 / &paaggregation @@ -226,25 +231,25 @@ rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradatio &paphytoplankton_N lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds lossN_d = 0.05d0 -lossN_c = 0.05d0 ! NEW +lossN_c = 0.05d0 / &paphytoplankton_C lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon lossC_d = 0.10d0 -lossC_c = 0.10d0 ! NEW +lossC_c = 0.10d0 / &paphytoplankton_ChlA -deg_Chl = 0.25d0 !0.2d0 !0.25d0 ! [1/day] -deg_Chl_d = 0.15d0 !0.2d0 !0.15d0 -deg_Chl_c = 0.2d0 ! NEW (has been 0.5) +deg_Chl = 0.25d0 !0.075 !0.2d0 !0.25d0 ! [1/day] +deg_Chl_d = 0.15d0 !0.075 !0.2d0 !0.15d0 +deg_Chl_c = 0.2d0 !0.075 !0.2d0 / &padetritus_N -gfin = 0.3d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into zooplankton pool) +gfin = 0.3d0 ! [] Grazing efficiency (fraction of grazing flux into zooplankton pool) grazEff2 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into second zooplankton pool) -grazEff3 = 0.8d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) +grazEff3 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) reminN = 0.165d0 ! [1/day] Temperature dependent remineralisation rate of detritus / @@ -264,11 +269,11 @@ lossC_z2 = 0.02d0 / &pathirdzooloss -lossN_z3 = 0.05d0 ! NEW 3Zoo -lossC_z3 = 0.05d0 ! NEW 3Zoo +lossN_z3 = 0.05d0 +lossC_z3 = 0.05d0 / -&paco2lim ! NEW +&paco2lim Cunits = 976.5625 ! Conversion factor between [mol/m3] (model) and [umol/kg] (function): (1000 * 1000) / 1024 a_co2_phy = 1.162e+00 ! [dimensionless] a_co2_dia = 1.040e+00 ! [dimensionless] @@ -298,11 +303,11 @@ RiverFeConc = 100 &pacalc calc_prod_ratio = 0.02 -calc_diss_guts = 0.0d0 -calc_diss_rate = 0.005714 ! 20.d0/3500.d0 +calc_diss_guts = 0.0d0 ! set to zero if OmegaC_diss is set to false +calc_diss_rate = 0.005714d0 ! 20.d0/3500.d0 calc_diss_rate2 = 0.005714d0 -calc_diss_omegac = 0.197d0 ! NEW DISS Value from Aumont et al. 2015, will be used with OmegaC_diss flag -calc_diss_exp = 1.d0 ! NEW DISS Exponent in the dissolution rate of calcite, will be used with OmegaC_diss flag +calc_diss_omegac = 0.197d0 ! Value from Aumont et al. 2015, is used with OmegaC_diss flag +calc_diss_exp = 1.d0 ! Exponent in the dissolution rate of calcite, is used with OmegaC_diss flag / &pabenthos_decay_rate @@ -333,9 +338,9 @@ rho_opal = 2090.d0 ! kg m-3; density of Opal (see Table 1 in Cram rho_ref_part = 1230.d0 ! kg m-3; reference particle density (see Cram et al., 2018) rho_ref_water = 1027.d0 ! kg m-3; reference seawater density (see Cram et al., 2018) visc_ref_water = 0.00158d0 ! kg m-1 s-1; reference seawater viscosity, at Temp=4 degC (see Cram et al., 2018) -w_ref1 = 10.d0 ! m s-1; reference sinking velocity of small detritus +w_ref1 = 5.d0 ! m s-1; reference sinking velocity of small detritus w_ref2 = 200.d0 ! m s-1; reference sinking velocity of large detritus -depth_scaling1 = 0.015d0 ! s-1; factor to increase sinking speed of det1 with depth, set to 0 if not wanted +depth_scaling1 = 0.01d0 ! s-1; factor to increase sinking speed of det1 with depth, set to 0 if not wanted depth_scaling2 = 0.d0 ! s-1; factor to increase sinking speed of det2 with depth, set to 0 if not wanted max_sinking_velocity = 250.d0 ! d-1; for numerical stability, set a maximum possible sinking velocity here (applies to both detritus classes) / @@ -353,3 +358,4 @@ atbox_spinup = .false. cosmic_14_init = 2.0 / + diff --git a/config/bin_3p3z2d/job_albedo b/config/bin_3p3z2d/job_albedo index 9eff795cb..f00ec4f36 100755 --- a/config/bin_3p3z2d/job_albedo +++ b/config/bin_3p3z2d/job_albedo @@ -1,16 +1,15 @@ #!/bin/bash -#SBATCH --account=nwg_hauck.maresys # edit your account -#SBATCH --job-name=recom +#SBATCH --account=biogeo_model.biogeo_model +#SBATCH --job-name=3p3z2d #SBATCH --partition=mpp -#SBATCH --time=01:30:00 -####SBATCH --constraint="[rack1|rack3]" +#SBATCH -N 9 +#SBATCH --cpus-per-task=1 +#SBATCH --time=08:00:00 #SBATCH --qos=12h -#SBATCH --nodes=9 # Number of tasks (MPI) tasks to be launched -#SBATCH --tasks-per-node 96 #8 #4 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O -#SBATCH --cpus-per-task 1 +#SBATCH --tasks-per-node 96 # using all 128CPus we exceed the maxload limit (>130) of many used nodes when us parallel I/O -#SBATCH -o fesom2o.out -#SBATCH -e fesom2e.out +#SBATCH -o slurm-out.out +#SBATCH -e slurm-err.out # disable hyperthreading #SBATCH --hint=nomultithread @@ -23,35 +22,33 @@ 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 . +#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_${SLURM_JOB_NAME}_${jobid}.out" +fname="fesom2.0.out" #___PUT JOB IN QUEUE____________________________________________________________ date -####srun --mpi=pmi2 ./fesom.x >> ${fname} srun --mpi=pmi2 ./fesom.x > fesom2.0.out date #qstat -f $PBS_JOBID #export EXITSTATUS=$? #if [ ${EXITSTATUS} -eq 0 ] || [ ${EXITSTATUS} -eq 127 ] ; then -#sbatch job_ollie +#sbatch job_albedo #fi -#Resultpath='/albedo/scratch/user/ogurses/ocean_only/' -Resultpath='/albedo/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags_3Zoo2Det_coccos/' -test -d $Resultpath/fesom.2019.oce.restart && exit +Resultpath='/albedo/work/user/...' +test -e $Resultpath/fesom.xxxxxx.oce.restart && exit IsInFile=$( tail -3 fesom2.0.out | grep -c timesteps) if (( IsInFile > 0 )); then diff --git a/config/bin_3p3z2d/namelist.config b/config/bin_3p3z2d/namelist.config index 9a048d633..ffff081c0 100644 --- a/config/bin_3p3z2d/namelist.config +++ b/config/bin_3p3z2d/namelist.config @@ -6,8 +6,8 @@ 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 +run_length= 1 !62 !62 !62 !28 +run_length_unit='y' ! y, m, d, s / &clockinit ! the model starts at @@ -18,8 +18,8 @@ yearnew=1958 &paths MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' -ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' -ResultPath='/albedo/scratch/user/ogurses/fesom2.5_recom_st1_vsink_vben_diags_3Zoo2Det_coccos/' +ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' +ResultPath='/albedo/work/user/...' / &restart_log @@ -29,7 +29,7 @@ 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 +logfile_outfreq=960 !in logfile info. output frequency, # steps / &ale_def @@ -59,9 +59,18 @@ 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.forcing b/config/bin_3p3z2d/namelist.forcing index a17799393..d890c69ec 100644 --- a/config/bin_3p3z2d/namelist.forcing +++ b/config/bin_3p3z2d/namelist.forcing @@ -23,11 +23,23 @@ ncar_bulk_z_shum=10.0 ! height at which humi forcing is located (CORE, JRA-do: 1 use_landice_water=.false. landice_start_mon=5 landice_end_mon=10 +fwf_path='./mesh/' + +/ + +&age_tracer +use_age_tracer=.false. +use_age_mask=.false. +age_tracer_path='./mesh/' +age_start_year=2000 + / &nam_sbc nm_xwind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 nm_ywind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 + nm_xstre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with winds, if nm_sbc=2 + nm_ystre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with winds, if nm_sbc=2 nm_humi_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/huss.clim61' ! name of file with humidity nm_qsr_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rsds.clim61' ! name of file with solar heat nm_qlw_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/rlds.clim61' ! name of file with Long wave @@ -37,24 +49,32 @@ landice_end_mon=10 nm_mslp_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/psl.clim61' ! air_pressure_at_sea_level nm_xwind_var = 'uas' ! name of variable in file with wind nm_ywind_var = 'vas' ! name of variable in file with wind - nm_humi_var = 'huss' ! name of variable in file with humidity - nm_qsr_var = 'rsds' ! name of variable in file with solar heat - nm_qlw_var = 'rlds' ! name of variable in file with Long wave + nm_xstre_var = 'uas' ! name of variable in file with wind + nm_ystre_var = 'vas' ! name of variable in file with wind + nm_humi_var = 'huss' ! name of variable in file with humidity + nm_qsr_var = 'rsds' ! name of variable in file with solar heat + nm_qlw_var = 'rlds' ! name of variable in file with Long wave nm_tair_var = 'tas' ! name of variable in file with 2m air temperature - nm_prec_var = 'prra' ! name of variable in file with total precipitation - nm_snow_var = 'prsn' ! name of variable in file with total precipitation - nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level + nm_prec_var = 'prra' ! name of variable in file with total precipitation + nm_snow_var = 'prsn' ! name of variable in file with total precipitation + nm_mslp_var = 'psl' ! name of variable in file with air_pressure_at_sea_level nm_nc_iyear = 1900 nm_nc_imm = 1 ! initial month of time axis in netCDF nm_nc_idd = 1 ! initial day of time axis in netCDF nm_nc_freq = 1 ! data points per day (i.e. 86400 if the time axis is in seconds) nm_nc_tmid = 0 ! 1 if the time stamps are given at the mid points of the netcdf file, 0 otherwise (i.e. 1 in CORE1, CORE2; 0 in JRA55) y_perpetual=.true. - l_xwind=.true. l_ywind=.true. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. + l_xwind=.true. l_ywind=.true. l_xstre=.false. l_ystre=.false. l_humi=.true. l_qsr=.true. l_qlw=.true. l_tair=.true. l_prec=.true. l_mslp=.true. l_cloud=.false. l_snow=.true. nm_runoff_file ='/albedo/pool/FESOM/forcing/CORE2/runoff.nc' runoff_data_source ='CORE2' !Dai09, CORE2 !runoff_data_source ='Dai09' !Dai09, CORE2, JRA55 !runoff_climatology =.true. - nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' sss_data_source ='CORE2' + nm_sss_data_file ='/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' + chl_data_source ='None' !'Sweeney' monthly chlorophyll climatology or 'NONE' for constant chl_const (below). Make use_sw_pene=.TRUE. in namelist.config! + nm_chl_data_file ='/pool/data/AWICM/FESOM2/FORCING/JRA55-do-v1.4.0/Sweeney/Sweeney_2005.nc' + chl_const = 0.1 + use_runoff_mapper = .FALSE. + runoff_basins_file = 'runoff_maps_regular.nc' + runoff_radius = 500000. / diff --git a/config/bin_3p3z2d/namelist.icepack.cesm.ponds b/config/bin_3p3z2d/namelist.icepack.cesm.ponds new file mode 100644 index 000000000..51aa33191 --- /dev/null +++ b/config/bin_3p3z2d/namelist.icepack.cesm.ponds @@ -0,0 +1,144 @@ +&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 = 1 ! 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 = .true. + 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 +/ + +&shortwave_nml + shortwave = 'dEdd' + albedo_type = 'ccsm3' + albicev = 0.78 + albicei = 0.36 + albsnowv = 0.98 + albsnowi = 0.70 + 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 index b1d4c18e6..6da21b99b 100644 --- a/config/bin_3p3z2d/namelist.io +++ b/config/bin_3p3z2d/namelist.io @@ -12,7 +12,7 @@ ldiag_extflds =.false. / &nml_general -io_listsize =100 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list +io_listsize =150 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list vec_autorotate =.false. / @@ -55,6 +55,7 @@ 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_3p3z2d/namelist.recom b/config/bin_3p3z2d/namelist.recom index 3679e244f..36feb2ae9 100644 --- a/config/bin_3p3z2d/namelist.recom +++ b/config/bin_3p3z2d/namelist.recom @@ -9,11 +9,16 @@ nm_erosion_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_fina nm_co2_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/MonthlyAtmCO2_gcb2023.nc' / +&parecomsetup +enable_3zoo2det = .true. +enable_coccos = .false. +/ + &pavariables use_REcoM =.true. REcoM_restart =.true. -bgc_num = 33 !30 !22 !33 !24 !38 +bgc_num = 33 !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 @@ -29,10 +34,10 @@ Grazing_detritus = .true. het_resp_noredfield = .true. ! Decides respiratation of copepod group diatom_mucus = .true. ! Decides nutrient limitation effect on aggregation O2dep_remin = .true. ! O2remin Add option for O2 dependency of organic matter remineralization -use_ballasting = .true. ! BALL -use_density_scaling = .true. ! BALL -use_viscosity_scaling = .true. ! BALL -OmegaC_diss = .true. ! DISS Use OmegaC from Mocsy to compute calcite dissolution (after Aumont et al. 2015 and Gehlen et al. 2007) +use_ballasting = .true. +use_density_scaling = .true. +use_viscosity_scaling = .true. +OmegaC_diss = .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!!!! CO2lim = .true. ! CO2 dependence of growth and calcification Diags = .true. constant_CO2 = .true. @@ -49,7 +54,7 @@ useErosion = .false. NitrogenSS = .false. ! When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) useAeolianN = .false. ! When set to true, aeolian nitrogen deposition is activated firstyearoffesomcycle = 1958 ! The first year of the actual physical forcing (e.g. JRA-55) used -lastyearoffesomcycle = 2023 ! Last year of the actual physical forcing used +lastyearoffesomcycle = 2024 ! Last year of the actual physical forcing used numofCO2cycles = 1 ! Number of cycles of the forcing planned currentCO2cycle = 1 ! Which CO2 cycle we are currently running DIC_PI = .true. @@ -81,23 +86,23 @@ recom_Tref = 288.15d0 ! [K] C2K = 273.15d0 ! Conversion from degrees C to K Ae = 4500.d0 ! [K] Slope of the linear part of the Arrhenius function reminSi = 0.02d0 -k_o2_remin = 15.d0 ! NEW O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 +k_o2_remin = 15.d0 ! O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 / &palimiter_function NMinSlope = 50.d0 SiMinSlope = 1000.d0 -NCmin = 0.04d0 !0.05d0 -NCmin_d = 0.04d0 !0.05d0 -NCmin_c = 0.04d0 ! NEW +NCmin = 0.04d0 +NCmin_d = 0.04d0 +NCmin_c = 0.04d0 SiCmin = 0.04d0 k_Fe = 0.04d0 k_Fe_d = 0.12d0 -k_Fe_c = 0.09d0 ! NEW +k_Fe_c = 0.09d0 k_si = 4.d0 P_cm = 3.0d0 ! [1/day] Rate of C-specific photosynthesis P_cm_d = 3.5d0 -P_cm_c = 2.8d0 ! NEW +P_cm_c = 2.8d0 / &palight_calculations @@ -108,33 +113,33 @@ a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific at &paphotosynthesis alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] alfa_d = 0.19d0 ! An initial slope of the P-I curve -alfa_c = 0.10d0 ! NEW +alfa_c = 0.10d0 parFrac = 0.43d0 / &paassimilation V_cm_fact = 0.7d0 ! scaling factor for temperature dependent maximum of C-specific N-uptake V_cm_fact_d = 0.7d0 -V_cm_fact_c = 0.7d0 ! NEW +V_cm_fact_c = 0.7d0 NMaxSlope = 1000.d0 ! Max slope for limiting function SiMaxSlope = 1000.d0 NCmax = 0.2d0 ! [mmol N/mmol C] Maximum cell quota of nitrogen (N:C) NCmax_d = 0.2d0 -NCmax_c = 0.15d0 ! NEW +NCmax_c = 0.15d0 SiCmax = 0.8d0 NCuptakeRatio = 0.2d0 ! [mmol N/mmol C] Maximum uptake ratio of N:C NCUptakeRatio_d = 0.2d0 -NCUptakeRatio_c = 0.2d0 ! NEW +NCUptakeRatio_c = 0.2d0 SiCUptakeRatio = 0.2d0 k_din = 0.55d0 ! [mmol N/m3] Half-saturation constant for nitrate uptake k_din_d = 1.0d0 -k_din_c = 0.9d0 ! NEW +k_din_c = 0.9d0 Chl2N_max = 3.15d0 ! [mg CHL/mmol N] Maximum CHL a : N ratio = 0.3 gCHL gN^-1 Chl2N_max_d = 4.2d0 -Chl2N_max_c = 3.5d0 ! NEW +Chl2N_max_c = 3.5d0 res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant res_phy_d = 0.01d0 -res_phy_c = 0.01d0 ! NEW +res_phy_c = 0.01d0 biosynth = 2.33d0 ! [mmol C/mmol N] Cost of biosynthesis biosynthSi = 0.d0 / @@ -145,19 +150,19 @@ ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron sta / &pazooplankton -graz_max = 0.31d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +graz_max = 0.31d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter epsilonr = 0.09d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss -res_het = 0.028d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +res_het = 0.028d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) Redfield = 6.625 ! [mmol C/mmol N] Redfield ratio of C:N = 106:16 loss_het = 0.04d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) -pzDia = 0.5d0 !1.0d0 !0.5d0 ! Maximum diatom preference +pzDia = 0.5d0 ! Maximum diatom preference sDiaNsq = 0.d0 -pzPhy = 0.04d0 !0.5d0 !0.25d0 !1.0d0 ! Maximum nano-phytoplankton preference (NEW: 3/12) +pzPhy = 0.04d0 ! Maximum small phytoplankton preference sPhyNsq = 0.d0 -pzCocco = 0.4d0 !0.666d0 ! NEW (8/12) -sCoccoNsq = 0.d0 ! NEW -pzMicZoo = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference -sMicZooNsq = 0.d0 ! NEW 3Zoo +pzCocco = 0.4d0 ! Maximum coccolithophore preference +sCoccoNsq = 0.d0 +pzMicZoo = 1.0d0 ! Maximum microzooplankton preference +sMicZooNsq = 0.d0 tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. / @@ -168,17 +173,17 @@ res_zoo2 = 0.0107d0 ! [1/day] Respiration by heterotrophs and mo loss_zoo2 = 0.003d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) fecal_rate_n = 0.104d0 ! [1/day] Temperature dependent N degradation of \ fecal_rate_c = 0.236d0 -fecal_rate_n_mes = 0.25d0 ! NEW 3Zoo -fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo -pzDia2 = 1.0d0 !1.5d0 !1.d0 ! Maximum diatom preference +fecal_rate_n_mes = 0.25d0 +fecal_rate_c_mes = 0.32d0 +pzDia2 = 1.0d0 ! Maximum diatom preference sDiaNsq2 = 0.d0 -pzPhy2 = 0.07d0 !0.5d0 ! Maximum diatom preference +pzPhy2 = 0.07d0 ! Maximum small phytoplankton preference sPhyNsq2 = 0.d0 -pzCocco2 = 0.7 !0.5d0 ! NEW -sCoccoNsq2 = 0.d0 ! NEW -pzHet = 1.5d0 !0.8d0 ! Maximum diatom preference +pzCocco2 = 0.7d0 ! Maximum coccolithophore preference +sCoccoNsq2 = 0.d0 +pzHet = 1.5d0 ! Maximum mesozooplankton preference sHetNsq = 0.d0 -pzMicZoo2 = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference +pzMicZoo2 = 1.0d0 ! Maximum microzooplankton preference sMicZooNsq2 = 0.d0 t1_zoo2 = 28145.d0 ! Krill temp. function constant1 t2_zoo2 = 272.5d0 ! Krill temp. function constant2 @@ -187,27 +192,27 @@ t4_zoo2 = 274.15d0 ! Krill temp. function constant3 / &pathirdzooplankton -graz_max3 = 0.46d0 ! NEW 3Zoo [mmol N/(m3 * day)] Maximum grazing loss parameter -epsilon3 = 0.64d0 ! NEW 3Zoo [(mmol N)2 /m6] Half saturation constant for grazing loss -loss_miczoo = 0.01d0 ! NEW 3Zoo [1/day] Temperature dependent N degradation of extracellular organic N (EON) -res_miczoo = 0.02d0 !0.01d0 ! NEW 3Zoo [1/day] Respiration by heterotrophs and mortality (loss to detritus) -pzDia3 = 0.04d0 !0.5d0 ! NEW 3Zoo Maximum diatom preference -sDiaNsq3 = 0.d0 ! NEW 3Zoo -pzPhy3 = 0.07 !1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference -sPhyNsq3 = 0.d0 ! NEW 3Zoo -pzCocco3 = 0.7d0 !0.d0 ! NEW 3Zoo Maximum coccolithophore preference ! ATTENTION: This value needs to be tuned; I start with zero preference! -sCoccoNsq3 = 0.d0 ! NEW 3Zoo +graz_max3 = 0.46d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilon3 = 0.64d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss +loss_miczoo = 0.01d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) +res_miczoo = 0.02d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +pzDia3 = 0.04d0 ! Maximum diatom preference +sDiaNsq3 = 0.d0 +pzPhy3 = 0.07d0 ! Maximum small phytoplankton preference +sPhyNsq3 = 0.d0 +pzCocco3 = 0.7d0 ! Maximum coccolithophore preference +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 -sDetNsq2 = 0.d0 -pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton -sDetZ2Nsq2 = 0.d0 +pzDet2 = 0.5d0 ! Maximum small detritus prefence by second zooplankton +sDetNsq2 = 0.d0 +pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton +sDetZ2Nsq2 = 0.d0 / &paaggregation @@ -226,25 +231,25 @@ rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradatio &paphytoplankton_N lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds lossN_d = 0.05d0 -lossN_c = 0.05d0 ! NEW +lossN_c = 0.05d0 / &paphytoplankton_C lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon lossC_d = 0.10d0 -lossC_c = 0.10d0 ! NEW +lossC_c = 0.10d0 / &paphytoplankton_ChlA -deg_Chl = 0.25d0 !0.2d0 !0.25d0 ! [1/day] -deg_Chl_d = 0.15d0 !0.2d0 !0.15d0 -deg_Chl_c = 0.2d0 ! NEW (has been 0.5) +deg_Chl = 0.075 !0.2d0 !0.25d0 ! [1/day] +deg_Chl_d = 0.075 !0.2d0 !0.15d0 +deg_Chl_c = 0.075 !0.2d0 / &padetritus_N -gfin = 0.3d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into zooplankton pool) +gfin = 0.3d0 ! [] Grazing efficiency (fraction of grazing flux into zooplankton pool) grazEff2 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into second zooplankton pool) -grazEff3 = 0.8d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) +grazEff3 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) reminN = 0.165d0 ! [1/day] Temperature dependent remineralisation rate of detritus / @@ -264,11 +269,11 @@ lossC_z2 = 0.02d0 / &pathirdzooloss -lossN_z3 = 0.05d0 ! NEW 3Zoo -lossC_z3 = 0.05d0 ! NEW 3Zoo +lossN_z3 = 0.05d0 +lossC_z3 = 0.05d0 / -&paco2lim ! NEW +&paco2lim Cunits = 976.5625 ! Conversion factor between [mol/m3] (model) and [umol/kg] (function): (1000 * 1000) / 1024 a_co2_phy = 1.162e+00 ! [dimensionless] a_co2_dia = 1.040e+00 ! [dimensionless] @@ -298,11 +303,11 @@ RiverFeConc = 100 &pacalc calc_prod_ratio = 0.02 -calc_diss_guts = 0.5d0 !0.0d0 -calc_diss_rate = 0.005714d0 ! 20.d0/3500.d0 +calc_diss_guts = 0.5d0 ! set to zero if OmegaC_diss is set to false +calc_diss_rate = 0.005714d0 ! 20.d0/3500.d0 calc_diss_rate2 = 0.005714d0 -calc_diss_omegac = 0.197d0 ! NEW DISS Value from Aumont et al. 2015, will be used with OmegaC_diss flag -calc_diss_exp = 1.d0 ! NEW DISS Exponent in the dissolution rate of calcite, will be used with OmegaC_diss flag +calc_diss_omegac = 0.197d0 ! Value from Aumont et al. 2015, is used with OmegaC_diss flag +calc_diss_exp = 1.d0 ! Exponent in the dissolution rate of calcite, is used with OmegaC_diss flag / &pabenthos_decay_rate @@ -335,7 +340,7 @@ rho_ref_water = 1027.d0 ! kg m-3; reference seawater density (see Cram visc_ref_water = 0.00158d0 ! kg m-1 s-1; reference seawater viscosity, at Temp=4 degC (see Cram et al., 2018) w_ref1 = 10.d0 ! m s-1; reference sinking velocity of small detritus w_ref2 = 200.d0 ! m s-1; reference sinking velocity of large detritus -depth_scaling1 = 0.01d0 !5d0 ! s-1; factor to increase sinking speed of det1 with depth, set to 0 if not wanted +depth_scaling1 = 0.01d0 ! s-1; factor to increase sinking speed of det1 with depth, set to 0 if not wanted depth_scaling2 = 0.d0 ! s-1; factor to increase sinking speed of det2 with depth, set to 0 if not wanted max_sinking_velocity = 250.d0 ! d-1; for numerical stability, set a maximum possible sinking velocity here (applies to both detritus classes) / @@ -353,3 +358,4 @@ atbox_spinup = .false. cosmic_14_init = 2.0 / + diff --git a/config/bin_4p3z2d/job_albedo b/config/bin_4p3z2d/job_albedo new file mode 100755 index 000000000..e31795168 --- /dev/null +++ b/config/bin_4p3z2d/job_albedo @@ -0,0 +1,63 @@ +#!/bin/bash +#SBATCH --account=biogeo_model.biogeo_model +#SBATCH --job-name=4p3z2d +#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/xxx' +test -e $Resultpath/fesom.xxxx.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_4p3z2d/namelist.config b/config/bin_4p3z2d/namelist.config new file mode 100644 index 000000000..ffff081c0 --- /dev/null +++ b/config/bin_4p3z2d/namelist.config @@ -0,0 +1,76 @@ +! This is the namelist file for model general configuration + +&modelname +runid='fesom' +/ + +×tep +step_per_day=32 !96 !96 !72 !72 !45 !72 !96 +run_length= 1 !62 !62 !62 !28 +run_length_unit='y' ! y, m, d, s +/ + +&clockinit ! the model starts at +timenew=0.0 +daynew=1 +yearnew=1958 +/ + +&paths +MeshPath='/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' +ClimateDataPath='/albedo/work/projects/MarESys/ogurses/input/corrected_input/' +ResultPath='/albedo/work/user/...' +/ + +&restart_log +restart_length=1 ! --> do netcdf restart ( only required for d,h,s cases, y, m take 1) +restart_length_unit='y' !output period: y, d, h, s, off +raw_restart_length=1 ! --> do core dump restart +raw_restart_length_unit='off' ! e.g. y, d, h, s, off +bin_restart_length=1 ! --> do derived type binary restart +bin_restart_length_unit='off' ! e.g. y, d, h, s, off +logfile_outfreq=960 !in logfile info. output frequency, # steps +/ + +&ale_def +which_ALE='zstar' ! 'linfs','zlevel', 'zstar' +use_partial_cell=.true. +/ + +&geometry +cartesian=.false. +fplane=.false. +cyclic_length=360 ![degree] +rotated_grid=.true. !option only valid for coupled model case now +force_rotation=.true. +alphaEuler=50. ![degree] Euler angles, convention: +betaEuler=15. ![degree] first around z, then around new x, +gammaEuler=-90. ![degree] then around new z. +/ + +&calendar +include_fleapyear=.false. +/ + +&run_config +use_ice=.true. ! ocean+ice +use_cavity=.false. ! +use_cavity_partial_cell=.false. +use_floatice = .false. +use_sw_pene=.true. +flag_debug=.false. +use_transit=.false. +/ + +&machine +n_levels=2 +n_part= 12, 36 ! 432 number of partitions on each hierarchy level +/ + +&icebergs +use_icesheet_coupling=.false. +ib_num=1 +use_icebergs=.false. +steps_per_ib_step=8 +ib_async_mode=0 +/ diff --git a/config/bin_4p3z2d/namelist.dyn b/config/bin_4p3z2d/namelist.dyn new file mode 100644 index 000000000..fb7919588 --- /dev/null +++ b/config/bin_4p3z2d/namelist.dyn @@ -0,0 +1,24 @@ +&dynamics_visc +visc_gamma0 = 0.003 ! [m/s], backgroung viscosity= gamma0*len, it should be as small a s possible (keep it < 0.01 m/s). +visc_gamma1 = 0.1 ! [nodim], for computation of the flow aware viscosity +visc_gamma2 = 0.285 ! [s/m], is only used in easy backscatter option +visc_easybsreturn= 1.5 + +opt_visc = 5 +! 5=Kinematic (easy) Backscatter +! 6=Biharmonic flow aware (viscosity depends on velocity Laplacian) +! 7=Biharmonic flow aware (viscosity depends on velocity differences) +! 8=Dynamic Backscatter + +use_ivertvisc= .true. +/ + +&dynamics_general +momadv_opt = 2 ! option for momentum advection in moment only =2 +use_freeslip = .false. ! Switch on free slip +use_wsplit = .false. ! Switch for implicite/explicte splitting of vert. velocity +wsplit_maxcfl= 1.0 ! maximum allowed CFL criteria in vertical (0.5 < w_max_cfl < 1.) + ! in older FESOM it used to be w_exp_max=1.e-3 +ldiag_KE=.false. ! activates energy diagnostics +/ + diff --git a/config/bin_4p3z2d/namelist.forcing b/config/bin_4p3z2d/namelist.forcing new file mode 100644 index 000000000..d890c69ec --- /dev/null +++ b/config/bin_4p3z2d/namelist.forcing @@ -0,0 +1,80 @@ +! 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_4p3z2d/namelist.ice b/config/bin_4p3z2d/namelist.ice new file mode 100644 index 000000000..bcd86f145 --- /dev/null +++ b/config/bin_4p3z2d/namelist.ice @@ -0,0 +1,31 @@ +! 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_4p3z2d/namelist.icepack b/config/bin_4p3z2d/namelist.icepack new file mode 100644 index 000000000..ed0dd4d4c --- /dev/null +++ b/config/bin_4p3z2d/namelist.icepack @@ -0,0 +1,146 @@ +&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_4p3z2d/namelist.icepack.cesm.ponds b/config/bin_4p3z2d/namelist.icepack.cesm.ponds new file mode 100644 index 000000000..51aa33191 --- /dev/null +++ b/config/bin_4p3z2d/namelist.icepack.cesm.ponds @@ -0,0 +1,144 @@ +&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 = 1 ! 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 = .true. + 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 +/ + +&shortwave_nml + shortwave = 'dEdd' + albedo_type = 'ccsm3' + albicev = 0.78 + albicei = 0.36 + albsnowv = 0.98 + albsnowi = 0.70 + 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_4p3z2d/namelist.io b/config/bin_4p3z2d/namelist.io new file mode 100644 index 000000000..aef0697d9 --- /dev/null +++ b/config/bin_4p3z2d/namelist.io @@ -0,0 +1,138 @@ +&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, + 'CO2 ',1, 'm', 4, + 'pH ',1, 'm', 4, + 'pCO2 ',1, 'm', 4, + 'HCO3 ',1, 'm', 4, + 'CO3 ',1, 'm', 4, + 'OmegaC ',1, 'm', 4, + 'kspc ',1, 'm', 4, + 'rhoSW ',1, 'm', 4, + 'wsink_det1',1, 'm', 8, + 'wsink_det2',1, 'm', 8, + 'rho_det1',1, 'm', 8, + 'rho_det2',1, 'm', 8, + 'scaling_rho_1',1, 'm', 8, + 'scaling_rho_2',1, 'm', 8, + 'scaling_visc',1, 'm', 8, + 'grazmeso_tot',1, 'm', 4, + 'grazmeso_n',1, 'm', 4, + 'grazmeso_d',1, 'm', 4, + 'grazmeso_c',1, 'm', 4, + 'respmeso',1, 'm', 4, + 'respmacro',1, 'm', 4, + 'respmicro',1, 'm', 4, + '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, + 'NPPp ',1, 'm', 4, + 'GPPp ',1, 'm', 4, + 'NNAp ',1, 'm', 4, + 'Chldegp ',1, 'm', 4, + 'grazmeso_p',1, 'm', 4, + 'aggp ',1, 'm', 4, + 'respp ',1, 'm', 4, + 'docexp ',1, 'm', 4, + 'TTemp_diatoms',1, 'm', 4, + 'TTemp_phyto',1, 'm', 4, + 'TTemp_cocco',1, 'm', 4, + 'TTemp_phaeo',1, 'm', 4, + 'TPhyCO2 ',1, 'm', 4, + 'TDiaCO2 ',1, 'm', 4, + 'TCoccoCO2 ',1, 'm', 4, + 'TPhaeoCO2 ',1, 'm', 4, + 'TqLF_phyto ',1, 'm', 4, + 'TqLF_diatoms',1, 'm', 4, + 'TqLF_cocco ',1, 'm', 4, + 'TqLF_phaeo ',1, 'm', 4, + 'TCphotLL_phyto ',1, 'm', 4, + 'TCphotLL_dia ',1, 'm', 4, + 'TCphotLL_cocco ',1, 'm', 4, + 'TCphotLL_phaeo ',1, 'm', 4, + 'TCphot_phyto',1, 'm', 4, + 'TCphot_diatoms',1, 'm', 4, + 'TCphot_cocco',1, 'm', 4, + 'TCphot_phaeo',1, 'm', 4, + 'TSi_assimDia',1, 'm', 4, +/ diff --git a/config/bin_4p3z2d/namelist.oce b/config/bin_4p3z2d/namelist.oce new file mode 100644 index 000000000..7af6867f7 --- /dev/null +++ b/config/bin_4p3z2d/namelist.oce @@ -0,0 +1,26 @@ +! 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 8 if (ciso == .true.) otherwise -> 4 +use_MEDUSA = .false. ! Main switch for the sediment model MEDUSA +sedflx_num = 0 ! if 0: no file from MEDUSA is read but default sediment +bottflx_num = 4 ! if ciso&ciso_14: =8; if .not.ciso_14: =6; no ciso: =4 +use_atbox = .false. +add_loopback = .false. ! add loopback fluxes through rivers to the surface +lb_tscale = 1.0 ! /year: fraction of loopback fluxes yearly added to the surface +/ + +&pasinking +Vdet_a = 0.0288 ! [1/day] +Vcalc = 0.0144 ! [1/day] +/ + +&painitialization_N +cPhyN = 0.2d0 +cHetN = 0.2d0 +cZoo2N = 0.2d0 +/ + +&paArrhenius +recom_Tref = 288.15d0 ! [K] +C2K = 273.15d0 ! Conversion from degrees C to K +Ae = 4500.d0 ! [K] Slope of the linear part of the Arrhenius function +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 +/ + +&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) +/ + +&palight_calculations +k_w = 0.04d0 ! [1/m] Light attenuation coefficient +a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific attenuation coefficients +/ + +&paphotosynthesis +alfa = 0.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 +/ + +&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 +/ + +&pairon_chem +totalligand = 1.d0 ! [mumol/m3] order 1. Total free ligand +ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron stability constant +/ + +&pazooplankton +graz_max = 0.31d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilonr = 0.09d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss +res_het = 0.028d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +Redfield = 6.625 ! [mmol C/mmol N] Redfield ratio of C:N = 106:16 +loss_het = 0.04d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) +pzDia = 1.0d0 !0.5d0 ! Maximum diatom preference ! 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. +/ + +&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 +/ + +&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 +/ + +&pagrazingdetritus +pzDet = 0.5d0 ! Maximum small detritus prefence by first zooplankton +sDetNsq = 0.d0 +pzDetZ2 = 0.5d0 ! Maximum large detritus preference by first zooplankton +sDetZ2Nsq = 0.d0 +pzDet2 = 0.5d0 ! Maximum small detritus prefence by second zooplankton +sDetNsq2 = 0.d0 +pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton +sDetZ2Nsq2 = 0.d0 +/ + +&paaggregation +agg_PD = 0.165d0 ! [m3/(mmol N * day)] Maximum aggregation loss parameter for DetN +agg_PP = 0.015d0 ! [m3/(mmol N * day)] Maximum aggregation loss parameter for PhyN and DiaN (plankton) +/ + +&padin_rho_N +rho_N = 0.11d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) (Remineralization of DON) +/ + +&padic_rho_C1 +rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradation of extracellular organic C (EOC) +/ + +&paphytoplankton_N +lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds +lossN_d = 0.05d0 +lossN_c = 0.05d0 ! NEW +lossN_p = 0.05d0 ! 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 +/ + +&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 + +/ + +&padetritus_N +gfin = 0.3d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into zooplankton pool) +grazEff2 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into second zooplankton pool) +grazEff3 = 0.8d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) +reminN = 0.165d0 ! [1/day] Temperature dependent remineralisation rate of detritus +/ + +&padetritus_C +reminC = 0.15d0 ! [1/day] Temperature dependent remineralisation rate of detritus +rho_c2 = 0.1d0 ! [1/day] Temperature dependent C degradation of TEP-C +/ + +&paheterotrophs +lossN_z = 0.1d0 +lossC_z = 0.1d0 +/ + +&paseczooloss +lossN_z2 = 0.02d0 +lossC_z2 = 0.02d0 +/ + +&pathirdzooloss +lossN_z3 = 0.05d0 ! NEW 3Zoo +lossC_z3 = 0.05d0 ! NEW 3Zoo +/ + +&paco2lim ! NEW +Cunits = 976.5625 ! Conversion factor between [mol/m3] (model) and [umol/kg] (function): (1000 * 1000) / 1024 +a_co2_phy = 1.162e+00 ! [dimensionless] +a_co2_dia = 1.040e+00 ! [dimensionless] +a_co2_cocco = 1.109e+00 ! [dimensionless] +a_co2_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] +/ + +&pairon +Fe2N = 0.033d0 ! Fe2C * 6.625 +Fe2N_benthos = 0.15d0 ! test, default was 0.14 Fe2C_benthos * 6.625 - will have to be tuned. [umol/m2/day] +kScavFe = 0.07d0 +dust_sol = 0.02d0 ! Dissolution of Dust for bioavaliable +RiverFeConc = 100 +/ + +&pacalc +calc_prod_ratio = 0.02 +calc_diss_guts = 0.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 +/ + +&pabenthos_decay_rate +decayRateBenN = 0.005d0 +decayRateBenC = 0.005d0 +decayRateBenSi = 0.005d0 +q_NC_Denit = 0.86d0 ! N:C quota of the denitrification process +/ + +&paco2_flux_param +permil = 0.000000976 ! 1.e-3/1024.5d0 ! Converting DIC from [mmol/m3] to [mol/kg] +permeg = 1.e-6 ! [atm/uatm] Changes units from uatm to atm +!X1 = exp(-5.d0*log(10.d0)) ! Lowest ph-value = 7.7 (phlo) +!X2 = exp(-9.d0*log(10.d0)) ! Highest ph-value = 9.5 (phhi) +Xacc = 1.e-12 ! Accuracy for ph-iteration (phacc) +CO2_for_spinup = 278.d0 ! [uatm] Atmospheric partial pressure of CO2 +/ + +&paalkalinity_restoring +surf_relax_Alk = 3.2e-07 !10.d0/31536000.d0 +/ + +&paballasting +rho_POC = 1033.d0 ! kg m-3; density of POC (see Table 1 in Cram et al., 2018) +rho_PON = 1033.d0 ! kg m-3; density of PON (see Table 1 in Cram et al., 2018) +rho_CaCO3 = 2830.d0 ! kg m-3; density of CaCO3 (see Table 1 in Cram et al., 2018) +rho_opal = 2090.d0 ! kg m-3; density of Opal (see Table 1 in Cram et al., 2018) +rho_ref_part = 1230.d0 ! kg m-3; reference particle density (see Cram et al., 2018) +rho_ref_water = 1027.d0 ! kg m-3; reference seawater density (see Cram et al., 2018) +visc_ref_water = 0.00158d0 ! kg m-1 s-1; reference seawater viscosity, at Temp=4 degC (see Cram et al., 2018) +w_ref1 = 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) +/ + +&paciso +ciso_init = .false. ! initial fractionation of bulk organic matter +ciso_14 = .false. ! include inorganic radiocarbon +ciso_organic_14 = .false. ! include organic radiocarbon +lambda_14 = 3.8561e-12 ! corresponding to 1 year = 365.00 days +delta_CO2_13 = -6.61 ! atmospheric d13C (permil), global-mean value +big_delta_CO2_14(1) = 0. ! atmospheric D14C (permil), northern hemisphere polewards of 30°N +big_delta_CO2_14(2) = 0. ! atmospheric D14C (permil), (sub) tropical zone 30°N - 30°S +big_delta_CO2_14(3) = 0. ! atmospheric D14C (permil), southern hemisphere polewards of 30°S +atbox_spinup = .false. +cosmic_14_init = 2.0 +/ + diff --git a/config/bin_4p3z2d/namelist.tra b/config/bin_4p3z2d/namelist.tra new file mode 100644 index 000000000..7fd6837a2 --- /dev/null +++ b/config/bin_4p3z2d/namelist.tra @@ -0,0 +1,93 @@ +&tracer_listsize +num_tracers=100 !number of tracers to allocate. shallbe large or equal to the number of streams in &nml_list +/ + +&tracer_list +nml_tracer_list = +1 , 'MFCT', 'QR4C', 'FCT ', 1., 1., +2 , 'MFCT', 'QR4C', 'FCT ', 1., 1., +1001, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1002, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1003, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1004, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1005, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1006, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1007, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1008, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1009, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1010, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1011, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1012, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1013, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1014, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1015, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1016, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1017, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1018, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1019, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1020, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1021, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1022, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1023, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1024, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1025, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1026, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1027, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1028, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1029, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1030, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1031, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1032, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1033, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1034, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1035, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1036, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!101, 'UPW1', 'UPW1', 'NON ', 0., 0. +/ + +&tracer_init3d ! initial conditions for tracers +n_ic3d = 8 ! number of tracers to initialize +idlist = 1019, 1022, 1018, 1003, 1002, 1001, 2, 1 ! their IDs (0 is temperature, 1 is salinity, etc.). The reading order is defined here! +filelist = 'fe_pisces_opa_eq_init_3D_changed_name.nc', 'woa18_all_o00_01_mmol_fesom2.nc', 'woa13_all_i00_01_fesom2.nc', 'GLODAPv2.2016b.TAlk_fesom2_mmol_fix_z_Fillvalue.nc', 'GLODAPv2.2016b.TCO2_fesom2_mmol_fix_z_Fillvalue.nc', 'woa13_all_n00_01_fesom2.nc', 'phc3.0_winter.nc', 'phc3.0_winter.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist +varlist = 'Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp' ! variables to read from specified files +t_insitu = .true. ! if T is insitu it will be converted to potential after reading it +/ + +&tracer_init2d ! initial conditions for 2D tracers (sea ice) +n_ic2d = 3 ! number of tracers to initialize +idlist = 1, 2, 3 ! their IDs (0 is a_ice, 1 is m_ice, 3 m_snow). The reading order is defined here! +filelist = 'a_ice.nc', 'm_ice.nc', 'm_snow.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist +varlist = 'a_ice', 'm_ice', 'm_snow' ! variables to read from specified files +ini_ice_from_file=.false. +/ + +&tracer_general +! bharmonic diffusion for tracers. We recommend to use this option in very high resolution runs (Redi is generally off there). +smooth_bh_tra =.false. ! use biharmonic diffusion (filter implementation) for tracers +gamma0_tra = 0.0005 ! gammaX_tra are analogous to those in the dynamical part +gamma1_tra = 0.0125 +gamma2_tra = 0. +i_vert_diff =.true. +/ + +&tracer_phys +use_momix = .true. ! switch on/off !Monin-Obukhov -> TB04 mixing +momix_lat = -50.0 ! latitidinal treshhold for TB04, =90 --> global +momix_kv = 0.01 ! PP/KPP, mixing coefficient within MO length +use_instabmix = .true. ! enhance convection in case of instable stratification +instabmix_kv = 0.1 +use_windmix = .false. ! enhance mixing trough wind only for PP mixing (for stability) +windmix_kv = 1.e-3 +windmix_nl = 2 +diff_sh_limit=5.0e-3 ! for KPP, max diff due to shear instability +Kv0_const=.true. +double_diffusion=.false. ! for KPP,dd switch +K_ver=1.0e-5 +K_hor=3000. +surf_relax_T=0.0 +surf_relax_S=1.929e-06 ! 50m/300days 6.43e-07! m/s 10./(180.*86400.) +balance_salt_water =.true. ! balance virtual-salt or freshwater flux or not +clim_relax=0.0 ! 1/s, geometrical information has to be supplied +ref_sss_local=.true. +ref_sss=34. +/ diff --git a/setups/forcings.yml b/setups/forcings.yml index 5e71d53dd..64357e760 100644 --- a/setups/forcings.yml +++ b/setups/forcings.yml @@ -254,4 +254,67 @@ test_global: calendar: include_fleapyear: False +test_recom: + forcing_exchange_coeff: + Ce_atm_oce: 1.75e-3 + Ch_atm_oce: 1.75e-3 + Cd_atm_oce: 1.0e-3 + Ce_atm_ice: 1.75e-3 + Ch_atm_ice: 1.75e-3 + Cd_atm_ice: 1.2e-3 + forcing_bulk: + AOMIP_drag_coeff: False + ncar_bulk_formulae: True + ncar_bulk_z_wind: 10.0 + ncar_bulk_z_tair: 10.0 + ncar_bulk_z_shum: 10.0 + land_ice: + use_landice_water: False + landice_start_mon: 5 + landice_end_mon: 10 + nam_sbc: + nm_xwind_file: u_10. + nm_ywind_file: v_10. + nm_humi_file: q_10. + nm_qsr_file: ncar_rad. + nm_qlw_file: ncar_rad. + nm_tair_file: t_10. + nm_prec_file: ncar_precip. + nm_snow_file: ncar_precip. + nm_mslp_file: slp. + nm_xwind_var: U_10_MOD + nm_ywind_var: V_10_MOD + nm_humi_var: Q_10_MOD + nm_qsr_var: SWDN_MOD + nm_qlw_var: LWDN_MOD + nm_tair_var: T_10_MOD + nm_prec_var: RAIN + nm_snow_var: SNOW + nm_mslp_var: SLP + nm_nc_iyear: 1948 + nm_nc_imm: 1 + nm_nc_idd: 1 + nm_nc_freq: 1 + nm_nc_tmid: 1 + l_xwind: True + l_ywind: True + l_humi: True + l_qsr: True + l_qlw: True + l_tair: True + l_prec: True + l_mslp: False + l_cloud: False + l_snow: True + nm_runoff_file: runoff.nc + runoff_data_source: CORE2 + nm_sss_data_file: PHC2_salx.nc + sss_data_source: CORE2 + chl_data_source: None + namelist.config: + clockinit: + yearnew: 1958 + calendar: + include_fleapyear: True + diff --git a/setups/paths.yml b/setups/paths.yml index 435cd6a86..09d5db735 100644 --- a/setups/paths.yml +++ b/setups/paths.yml @@ -62,9 +62,11 @@ docker: forcing: test_global: ./test/input/global/ test_icebergs: ./test/input/icebergs/ + test_recom: ./test/input/global/ clim: test_global: ./test/input/global/ test_icebergs: ./test/input/icebergs/ + test_recom: ./test/input/recom/ opath: opath: ./test/ diff --git a/setups/test_pi_recom/README.md b/setups/test_pi_recom/README.md new file mode 100644 index 000000000..3443b29fe --- /dev/null +++ b/setups/test_pi_recom/README.md @@ -0,0 +1,74 @@ +# REcoM Biogeochemistry CI Test + +This test validates FESOM2 with REcoM (Regulated Ecosystem Model) biogeochemistry module. + +## Test Configuration + +- **Mesh**: PI mesh (test_global) - ~3k nodes +- **Duration**: 1 day +- **Time steps**: 32 per day +- **Processes**: 2 MPI tasks +- **Features**: + - REcoM biogeochemistry (30 tracers) + - 3 zooplankton, 2 detritus groups + - Iron chemistry with dust input + - CO2 system (without calcification for this test) + +## Required Input Files + +All files are located in `test/input/recom/`: + +### REcoM-specific files: +- `DustClimMonthlyAlbani_pimesh.nc` - Dust deposition climatology +- `MonthlyAtmCO2_gcb2024.nc` - Atmospheric CO2 concentration +- `GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc` - Pre-industrial DIC (optional) + +### Initial conditions for biogeochemical tracers: +- `fe5deg.nc` - Iron (Fe) +- `oxy5deg.nc` - Oxygen +- `si5deg.nc` - Silicate +- `talk5deg.nc` - Total alkalinity +- `tco2_5deg.nc` - Total dissolved inorganic carbon +- `din5deg.nc` - Dissolved inorganic nitrogen +- `woa18_netcdf_5deg.nc` - Temperature and salinity + +## Build Instructions + +Compile FESOM2 with REcoM support: + +```bash +./configure.sh ubuntu -DRECOM_COUPLED=ON +``` + +## Running the Test + +### Local Docker Test: +```bash +mkrun recom test_pi_recom -m docker +cd work_recom +./job_docker_new +``` + +### CI Test (GitHub Actions): +The test runs automatically via `.github/workflows/fesom2_recom.yml` on pull requests to main branch. + +## Expected Outputs + +The test outputs daily averages for: +- Physical variables: SST, temperature, salinity, velocities, sea ice +- Biogeochemical variables: DIN (nitrogen), DIC (carbon) + +## Validation + +The `fcheck` values in `setup.yml` validate that: +1. Physical fields match baseline test_pi values +2. Biogeochemical tracers are within expected ranges: + - DIN: ~15 mmol/m³ (global mean) + - DIC: ~2100 mmol/m³ (global mean) + +## Notes + +- This test uses `REcoM_restart=False` for initialization from climatology +- Cavity is disabled (`use_cavity=False`) +- Uses standard PI mesh without cavity features +- Test follows the same pattern as icebergs and cavity tests diff --git a/setups/test_pi_recom/setup.yml b/setups/test_pi_recom/setup.yml new file mode 100644 index 000000000..1304b6c0c --- /dev/null +++ b/setups/test_pi_recom/setup.yml @@ -0,0 +1,151 @@ +mesh: test_global +forcing: test_recom +clim: + type: test_recom + filelist: + - 'fe5deg.nc' + - 'oxy5deg.nc' + - 'si5deg.nc' + - 'talk5deg.nc' + - 'tco2_5deg.nc' + - 'din5deg.nc' + - 'woa18_netcdf_5deg.nc' + - 'woa18_netcdf_5deg.nc' + varlist: ['Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp'] +ntasks: 2 +time: "00:15:00" + +namelist.config: + run_config: + use_cavity: False + use_cavity_partial_cell: False + timestep: + step_per_day: 32 + run_length: 1 + run_length_unit: "d" + clockinit: + yearnew: 1948 + calendar: + include_fleapyear: False + geometry: + force_rotation: True + restart_log: + restart_length: 1 + restart_length_unit: "d" + logfile_outfreq: 10 + +namelist.dyn: + dynamics_general: + use_wsplit: True + +namelist.ice: + ice_dyn: + whichEVP: 1 + evp_rheol_steps: 120 + +namelist.tra: + tracer_listsize: + num_tracers: 100 + tracer_init3d: + n_ic3d: 8 + idlist: [1019, 1022, 1018, 1003, 1002, 1001, 2, 1] + filelist: ['fe5deg.nc', 'oxy5deg.nc', 'si5deg.nc', 'talk5deg.nc', 'tco2_5deg.nc', 'din5deg.nc', 'woa18_netcdf_5deg.nc', 'woa18_netcdf_5deg.nc'] + varlist: ['Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp'] + t_insitu: True + +namelist.recom: + nam_rsbc: + fe_data_source: 'Albani' + nm_fe_data_file: 'DustClimMonthlyAlbani_pimesh.nc' + nm_co2_data_file: 'MonthlyAtmCO2_gcb2024.nc' + parecomsetup: + enable_3zoo2det: True + enable_coccos: False + pavariables: + use_REcoM: True + REcoM_restart: False + bgc_num: 30 + diags3d_num: 28 + bgc_base_num: 22 + biostep: 1 + REcoM_Geider_limiter: False + REcoM_Grazing_Variable_Preference: True + Grazing_detritus: True + het_resp_noredfield: True + diatom_mucus: True + O2dep_remin: True + use_ballasting: True + use_density_scaling: True + use_viscosity_scaling: True + OmegaC_diss: False + CO2lim: True + Diags: True + constant_CO2: True + UseFeDust: True + UseDustClim: True + UseDustClimAlbani: True + use_photodamage: True + HetRespFlux_plus: True + restore_alkalinity: True + useRivers: False + useRivFe: False + useErosion: False + NitrogenSS: False + useAeolianN: False + firstyearoffesomcycle: 1948 + lastyearoffesomcycle: 1948 + numofCO2cycles: 1 + currentCO2cycle: 1 + DIC_PI: True + Nmocsy: 1 + recom_debug: False + ciso: False + benthos_num: 4 + use_MEDUSA: False + sedflx_num: 0 + bottflx_num: 4 + use_atbox: False + add_loopback: False + lb_tscale: 1.0 + +namelist.io: + nml_list: + io_list: + "sst ": + freq: 1 + unit: d + prec: 8 + "a_ice ": + freq: 1 + unit: d + prec: 8 + "temp ": + freq: 1 + unit: d + prec: 8 + "salt ": + freq: 1 + unit: d + prec: 8 + "u ": + freq: 1 + unit: d + prec: 8 + "v ": + freq: 1 + unit: d + prec: 8 + "otracers ": + freq: 1 + unit: d + prec: 8 + +fcheck: + a_ice: 0.8819344996872085 + salt: 34.73157304881824 + sst: 8.586927880016397 + temp: 2.470427869759253 + u: -0.0016324243978025638 + v: -5.3040445705995874e-05 + DIN: 20.250062071295385 + DIC: 2197.053774584202 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7b0c28486..50b449211 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -71,6 +71,9 @@ if(${ENABLE_OPENMP}) find_package(OpenMP REQUIRED COMPONENTS Fortran) endif() +option(RECOM_COUPLED "Use RECOM" OFF) +message(STATUS "RECOM_COUPLED: ${RECOM_COUPLED}") + option(USE_ICEPACK "Use ICEPACK" OFF) message(STATUS "USE_ICEPACK: ${USE_ICEPACK}") @@ -317,7 +320,7 @@ if(OPENMP_REPRODUCIBLE) endif() if(${RECOM_COUPLED}) - target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __3Zoo2Det __coccos)# __usetp) + target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2) # __3Zoo2Det __coccos)# __usetp) endif() if(${CISO_COUPLED}) diff --git a/src/MOD_TRACER.F90 b/src/MOD_TRACER.F90 index efeeed623..0fd08466b 100644 --- a/src/MOD_TRACER.F90 +++ b/src/MOD_TRACER.F90 @@ -20,6 +20,9 @@ MODULE MOD_TRACER real(kind=WP) :: tra_adv_pv = 1. ! a parameter to be used in horizontal advection (for QR4C it is the fraction of fourth-order contribution in the solution) integer :: AB_order=2 integer :: ID +!___________________________________________________________________________ +! TODO: Make it as a part of namelist.tra +logical :: ltra_diag = .true. contains procedure WRITE_T_TRACER_DATA @@ -41,7 +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 +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(:,:,:) + ! The fct part real(kind=WP),allocatable,dimension(:,:) :: fct_LO ! Low-order solution real(kind=WP),allocatable,dimension(:,:) :: adv_flux_hor ! Antidif. horiz. contrib. from edges / backup for iterafive fct scheme diff --git a/src/gen_ic3d.F90 b/src/gen_ic3d.F90 index 4af214cd6..825c07cf0 100644 --- a/src/gen_ic3d.F90 +++ b/src/gen_ic3d.F90 @@ -351,11 +351,20 @@ SUBROUTINE getcoeffld(tracers, partit, mesh) iost = nf_inq_varid(ncid, varname, id_data) iost = nf_inq_var_fill(ncid, id_data, NO_FILL, FILL_VALUE) ! FillValue defined? if (NO_FILL==1) then - print *, 'No _FillValue is set in ', trim(filename), ', trying dummy =', dummy, FILL_VALUE + ! No _FillValue attribute found, try missing_value attribute + iost = nf_get_att_double(ncid, id_data, 'missing_value', FILL_VALUE) + if (iost /= NF_NOERR) then + ! Neither _FillValue nor missing_value found, use NetCDF default fill value + FILL_VALUE = NF_FILL_DOUBLE ! 9.9692099683868690e+36 + print *, 'No _FillValue or missing_value in ', trim(filename), ', using NetCDF default:', FILL_VALUE + else + print *, 'Using missing_value from ', trim(filename), ':', FILL_VALUE + end if else - print *, 'The FillValue in ', trim(filename), ' is set to ', FILL_VALUE ! should set dummy accordingly + print *, 'Using _FillValue from ', trim(filename), ':', FILL_VALUE end if end if + call MPI_BCast(FILL_VALUE, 1, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM, ierror) call MPI_BCast(iost, 1, MPI_INTEGER, 0, MPI_COMM_FESOM, ierror) call check_nferr(iost,filename,partit) !read data from file @@ -497,6 +506,7 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) !! ** Purpose : read 3D initial conditions for tracers from netcdf and interpolate on model grid !!---------------------------------------------------------------------- USE insitu2pot_interface + USE ieee_arithmetic IMPLICIT NONE type(t_mesh), intent(in), target :: mesh type(t_partit), intent(inout), target :: partit @@ -535,15 +545,14 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) do current_tracer=1, tracers%num_tracers !_________________________________________________________________________ - ! set remaining dummy values from bottom topography to 0.0_WP - where (tracers%data(current_tracer)%values > 0.9_WP*dummy) - tracers%data(current_tracer)%values=0.0_WP - end where - - !_________________________________________________________________________ - ! eliminate values within cavity that result from the extrapolation of - ! initialisation + ! set remaining dummy values and NaN from interpolation to 0.0_WP do n=1,partit%myDim_nod2d + partit%eDim_nod2D + do i=1, mesh%nl-1 + if (tracers%data(current_tracer)%values(i,n) > 0.9_WP*dummy .or. & + ieee_is_nan(tracers%data(current_tracer)%values(i,n))) then + tracers%data(current_tracer)%values(i,n) = 0.0_WP + end if + end do ! ensure cavity is zero if (use_cavity) tracers%data(current_tracer)%values(1:mesh%ulevels_nod2D(n)-1,n)=0.0_WP ! ensure bottom is zero @@ -561,7 +570,7 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) if (partit%mype==0) write(*,*) "converting insitu temperature to potential..." call insitu2pot(tracers, partit, mesh) end if - if (partit%mype==0) write(*,*) "DONE: Initial conditions for tracers" + if (partit%mype==0) write(*,*) "DONE: Initial conditions for tracers" !_________________________________________________________________________ ! check initial fields locTmax = -6666 diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index 869b00a52..ff4e4cad4 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -175,6 +175,9 @@ subroutine setup_model(partit) endif call par_ex(partit%MPI_COMM_FESOM, partit%mype, 1) endif + read (fileunit, NML=parecomsetup, iostat=istat) + if (istat /= 0) call check_namelist_read(fileunit, 'parecomsetup', nmlfile, partit) + read (fileunit, NML=pavariables, iostat=istat) if (istat /= 0) call check_namelist_read(fileunit, 'pavariables', nmlfile, partit) diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index b95a99af7..bff8bbd4b 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -1457,6 +1457,7 @@ SUBROUTINE sbc_do(partit, mesh) #if defined (__recom) use recom_config use recom_glovar + use REcoM_ciso #endif IMPLICIT NONE @@ -1475,6 +1476,11 @@ SUBROUTINE sbc_do(partit, mesh) 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 #endif type(t_partit), intent(inout), target :: partit type(t_mesh), intent(in), target :: mesh @@ -1659,10 +1665,40 @@ SUBROUTINE sbc_do(partit, mesh) ! ******** Atmospheric CO2 ********* if (mstep == 1) then ! The year has changed + if (use_atbox) then +! Atmospheric box model CO2 values + AtmCO2(:) = x_co2atm(1) + if (ciso) then + AtmCO2_13(:) = x_co2atm_13(1) + if (ciso_14) AtmCO2_14(:,1) = x_co2atm_14(1) + end if + else +! Prescribed atmospheric CO2 values + if (constant_CO2) then AtmCO2(:) = CO2_for_spinup if (mype==0) write(*,*) 'Constant_CO2 = ', CO2_for_spinup - if (mype==0) write(*,*),'Atm CO2=', AtmCO2 + if (mype==0) write(*,*),'Atm CO2=', AtmCO2 + if (ciso) then + AtmCO2_13 = CO2_for_spinup * (1. + 0.001 * delta_co2_13) + if (ciso_14) then +! Atmospheric 14C varies with latitude + do i=1, myDim_nod2D +! Latitude of atmospheric input data + lat_val = geo_coord_nod2D(2,i) / rad +! Binning to latitude zones + if (ciso_organic_14) then +! Convert Delta_14C to delta_14C + delta_co2_14 = (big_delta_co2_14(lat_zone(lat_val)) + 2. * delta_co2_13 + 50.) / & + (0.95 - 0.002 * delta_co2_13) + else +! "Inorganic" 14C approximation: delta_14C := Delta_14C + delta_co2_14 = big_delta_co2_14(lat_zone(lat_val)) + end if + AtmCO2_14(lat_zone(lat_val),:) = CO2_for_spinup * (1. + 0.001 * delta_co2_14) + end do + end if + end if else filename=trim(make_full_path(nm_co2_data_file)) if (mype==0) write(*,*) 'Updating CO2 climatology for month ', i,' from ', trim(filename) @@ -1696,8 +1732,266 @@ SUBROUTINE sbc_do(partit, mesh) if (mype==0) write(*,*),'Atm CO2=', AtmCO2 status=nf90_close(ncid) end if + end if ! atmospheric box model or prescribed CO2 values + +! Control output of atmospheric CO2 values + if (mype==0) then !OG + print *, "In atm_input: AtmCO2 = ", AtmCO2(1) + if (ciso) then + print *, " AtmCO2_13 = ", AtmCO2_13(1) + if (ciso_14) print *, " AtmCO2_14 = ", AtmCO2_14(:,1) + end if + if (use_atbox) print *, " use_atbox = .true." + end if + + + +! ******** 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 + + end if ! add_loopback + + else + +!-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 + + end if ! add_loopback + + end if ! do_read + + if (mype==0) write(*,*) 'sedimentary input from MEDUSA not used!' !OG + + end if ! use_MEDUSA and sedflx_num not 0 + end if + ! ******** Fe deposition ********* if (fe_data_source=='Albani') then if (update_monthly_flag) then diff --git a/src/int_recom/recom/gasx.F90 b/src/int_recom/recom/gasx.F90 index bd5473527..c4d2d8b01 100755 --- a/src/int_recom/recom/gasx.F90 +++ b/src/int_recom/recom/gasx.F90 @@ -6,7 +6,7 @@ MODULE gasx !> Computes air-sea CO2 flux & surface-ocean carbonate system vars (pH, CO2*, HCO3- and CO32-, OmegaA, OmegaC, R) !! from T, S, P, ALK, DIC, total inorganic silicon, total inorganic phosphorus, all as 1-D arrays SUBROUTINE flxco2(co2flux, co2ex, dpco2, & - ph, pco2, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, & + ph, pco2, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, K0, & temp, sal, alk, dic, sil, phos, kw660, xco2, Patm, dz1, N, lon, lat, & optCON, optT, optP, optB, optK1K2, optKf, optGAS, optS ) ! Purpose: @@ -127,6 +127,8 @@ SUBROUTINE flxco2(co2flux, co2ex, dpco2, ! rhoSW = in-situ density of seawater; rhoSW = f(s, t, p) ! p = pressure [decibars]; p = f(depth, latitude) if computed from depth [m] OR p = depth if [db] ! tempis = in-situ temperature [degrees C] + ! K0 = CO2 solubility [(mol/kg) / atm] + #if USE_PRECISION == 2 # define SGLE(x) (x) @@ -237,10 +239,12 @@ SUBROUTINE flxco2(co2flux, co2ex, dpco2, REAL(kind=rx), INTENT(out), DIMENSION(N) :: p !> in-situ temperature \b [degrees C] REAL(kind=rx), INTENT(out), DIMENSION(N) :: tempis + !> K0, solubility of CO2 \b [(mol/kg) / atm] + REAL(kind=rx), INTENT(out), DIMENSION(N) :: K0 ! Local variables REAL(kind=r8) :: tk, invtk, dtemp - REAL(kind=r8) :: tmp, K0, co2star, co2starair, kwco2 + REAL(kind=r8) :: tmp, co2star, co2starair, kwco2 ! K0 REAL(kind=rx), DIMENSION(N) :: pCO2atm, fCO2atm REAL(kind=rx), DIMENSION(N) :: depth0, lat0 @@ -361,7 +365,7 @@ SUBROUTINE flxco2(co2flux, co2ex, dpco2, K0 = EXP( tmp + DBLE(salprac(i))*(0.023517d0 - 0.00023656d0*tk + 0.0047036e-4_r8*tk*tk) ) ! "Atmospheric" [CO2*], air-sea CO2 flux, sfc DIC rate of change, & Delta pCO2 - co2starair = K0 * DBLE(fco2atm(i)) * 1.0e-6_r8 * DBLE(rhoSW(i)) !Equil. [CO2*] for atm CO2 at Patm & sfc-water T,S [mol/m3] + co2starair = K0(i) * DBLE(fco2atm(i)) * 1.0e-6_r8 * DBLE(rhoSW(i)) !Equil. [CO2*] for atm CO2 at Patm & sfc-water T,S [mol/m3] co2star = DBLE(co2(i)) !Oceanic [CO2*] in [mol/m3] from vars.f90 co2flux(i) = SGLE(kwco2 * (co2starair - co2star)) !Air-sea CO2 flux [mol/(m2 * s)] ! the conversion from co2flux to impact on dic is done in recom_forcing/recom_sms diff --git a/src/int_recom/recom/vars.F90 b/src/int_recom/recom/vars.F90 index 2ef70defa..d20069a10 100755 --- a/src/int_recom/recom/vars.F90 +++ b/src/int_recom/recom/vars.F90 @@ -570,7 +570,7 @@ SUBROUTINE vars_sprac (ph, pco2, fco2, co2, hco3, co3, OmegaA, OmegaC, kspc_out, ! If Absolute salinity is given IF (trim(opS) == 'Sabs') THEN ! If in-situ or potential temperature is given - IF (trim(optT) /= 'Scsv') THEN + IF (trim(optT) /= 'Scsv') THEN !!!!!!!!! Is it a bug? OG 20.03.2025 Scsv -> Tcsv .OR. tcsv ! First compute conservative temperature tempcsv = gsw_ct_from_t (DBLE(ssal), tempis90, DBLE(p(i))) ELSE diff --git a/src/int_recom/recom_atbox.F90 b/src/int_recom/recom_atbox.F90 new file mode 100644 index 000000000..4e579c51e --- /dev/null +++ b/src/int_recom/recom_atbox.F90 @@ -0,0 +1,92 @@ + subroutine recom_atbox(partit, mesh) +! Simple 0-d box model to calculate the temporal evolution of atmospheric CO2. +! Initially the box model was part of module recom_ciso. Now it can be run also +! without carbon isotopes (ciso==.false.) +! mbutzin, 2021-07-08 + +! Settings are copied from subroutine bio_fluxes, +! some of the following modules may be unnecessary here +! use REcoM_declarations +! use REcoM_LocVar + use REcoM_GloVar + use recom_config + use recom_ciso + + use mod_mesh + USE MOD_PARTIT + USE MOD_PARSUP + + use g_config + use o_arrays + use g_comm_auto + use g_forcing_arrays + use g_support + + + implicit none + integer :: n, elem, elnodes(3),n1 + real(kind=WP) :: total_co2flux, & ! (mol / s) + total_co2flux_13, & ! (mol / s) carbon-13 + total_co2flux_14 ! (mol / s) radiocarbon + real(kind=WP), parameter :: mol_allatm = 1.7726e20 ! atmospheric inventory of all compounds (mol) + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + +#include "../associate_part_def.h" +#include "../associate_mesh_def.h" +#include "../associate_part_ass.h" +#include "../associate_mesh_ass.h" + +! Globally integrated air-sea CO2 flux (mol / s) + total_co2flux = 0. + call integrate_nod(0.001 * GloCO2flux_seaicemask , total_CO2flux, partit, mesh) + +! Atmospheric carbon budget (mol) +! mass of the dry atmosphere = 5.1352e18 kg (Trenberth & Smith 2005, doi:10.1175/JCLI-3299.1) +! mean density of air = 0.02897 kg / mol (https://nssdc.gsfc.nasa.gov/planetary/factsheet/earthfact.html) +! => total molecular inventory of the dry atmosphere: moles_atm = 1.7726e20 mol == constant. +! mol_co2atm = mol_co2atm - total_co2flux * dt +! Atmospheric mixing ratios in ppm +! x_co2atm(1) = mol_co2atm / mol_allatm * 1.e6 ! ppm + x_co2atm(1) = x_co2atm(1) - total_co2flux / mol_allatm * dt * 1.e6 + x_co2atm = x_co2atm(1) + + if (ciso) then +! Consider 13CO2 (and maybe also 14CO2) + +! Globally integrated air-sea 13CO2 flux (mol / s) + total_co2flux_13 = 0. + call integrate_nod(0.001 * GloCO2flux_seaicemask_13, total_co2flux_13, partit, mesh) + +! Atmospheric carbon-13 budget (mol) +! mol_co2atm_13 = mol_co2atm_13 - total_co2flux_13 * dt +! Budget in terms of the 13C / 12C volume mixing ratio +! x_co2atm_13(1) = mol_co2atm_13 / mol_allatm * 1.e6 + x_co2atm_13(1) = x_co2atm_13(1) - total_co2flux_13 / mol_allatm * dt * 1.e6 + x_co2atm_13 = x_co2atm_13(1) + + if (ciso_14) then + total_co2flux_14 = 0. ! globally integrated air-sea 14CO2 flux (mol / s) + call integrate_nod(0.001 * GloCO2flux_seaicemask_14, total_co2flux_14, partit, mesh) +! Atmospheric radiocarbon budget in mol: +! mol_co2atm_14 = mol_co2atm_14 + dt * (cosmic_14(1) - mol_co2atm_14 * lambda_14 - total_co2flux_14) +! = (mol_co2atm_14 + dt * (cosmic_14(1) - total_co2flux_14)) / (1 + lambda_14 * dt) +! Budget in terms of the 14C / 12C volume mixing ratio + x_co2atm_14(1) = (x_co2atm_14(1) + dt * (cosmic_14(1) - total_co2flux_14) / mol_allatm * 1.e6) / & + (1 + lambda_14 * dt) + x_co2atm_14 = x_co2atm_14(1) + +! Adjust cosmogenic 14C production (mol / s) in spinup runs, + r_atm_14 = x_co2atm_14(1) / x_co2atm(1) +! r_atm_spinup_14 is calculated once-only in subroutine recom_init + if (atbox_spinup .and. abs(r_atm_14 - r_atm_spinup_14) > 0.001) then + cosmic_14(1) = cosmic_14(1) * (r_atm_spinup_14 / r_atm_14) +! cosmic_14(1) = cosmic_14(1) * (1 + 0.01 * (r_atm_14_spinup / r_atm_14)) + end if + cosmic_14 = cosmic_14(1) + endif + end if + + return + end subroutine recom_atbox + diff --git a/src/int_recom/recom_extra.F90 b/src/int_recom/recom_extra.F90 index 5495e0c8f..44973c167 100644 --- a/src/int_recom/recom_extra.F90 +++ b/src/int_recom/recom_extra.F90 @@ -1,34 +1,35 @@ !=============================================================================== ! Subroutine for calculating flux-depth and thickness of control volumes !=============================================================================== -subroutine Depth_calculations(n,Nn,wF,zF,thick,recipthick, partit, mesh) - use recom_config +subroutine Depth_calculations(n, nn, wf, zf, thick, recipthick, partit, mesh) + use recom_config use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP - USE o_PARAM - USE o_ARRAYS - USE g_CONFIG - use g_forcing_arrays - use g_comm_auto - - use g_clock - use g_rotate_grid - - implicit none -! Input - type(t_partit), intent(inout), target :: partit - type(t_mesh) , intent(inout), target :: mesh - - Integer, intent(in) :: Nn ! Total number of nodes -! Output - real(kind=8),dimension(mesh%nl), intent(out) :: zF ! [m] Depth of vertical fluxes + use MOD_PARTIT + use MOD_PARSUP + use o_PARAM + use o_ARRAYS + use g_CONFIG + use g_forcing_arrays + use g_comm_auto + use g_clock + use g_rotate_grid + + implicit none + + ! Input parameters + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + integer , intent(in) :: n ! Current node + integer , intent(in) :: nn ! Total number of vertical nodes - real(kind=8),dimension(mesh%nl-1), intent(out) :: thick ! [m] Distance between two nodes = thickness - real(kind=8),dimension(mesh%nl-1), intent(out) :: recipthick ! [1/m] reciprocal of thickness + ! Output arrays + real(kind=8), dimension(mesh%nl,6), intent(out) :: wf ! [m/day] Flux velocities at the border of the control volumes + real(kind=8), dimension(mesh%nl), intent(out) :: zf ! [m] Depth of vertical fluxes + real(kind=8), dimension(mesh%nl-1), intent(out) :: thick ! [m] Distance between two nodes = layer thickness + real(kind=8), dimension(mesh%nl-1), intent(out) :: recipthick ! [1/m] Reciprocal thickness - real(kind=8),dimension(mesh%nl,5), intent(out) :: wF ! [m/day] Velocities of fluxes at the border of the control volumes - Integer :: k, n ! Index for depth + ! Local variables + integer :: k ! Layer index #include "../associate_part_def.h" #include "../associate_mesh_def.h" @@ -48,16 +49,17 @@ subroutine Depth_calculations(n,Nn,wF,zF,thick,recipthick, partit, mesh) ! allocate(Z_3d_n(nl-1,myDim_nod2D+eDim_nod2D)) ! ============================================================================== modular -!! Background sinking speed + !! Background sinking speed + wF(2:Nn, ivphy) = VPhy ! Phytoplankton sinking velocity + wF(2:Nn, ivdia) = VDia ! Diatoms sinking velocity + wF(2:Nn, ivdet) = VDet ! Detritus sinking velocity + wF(2:Nn, ivdetsc) = VDet_zoo2 ! Second detritus sinking velocity + wF(2:Nn, ivcoc) = VCocco ! Coccolithophores sinking velocity + wF(2:Nn, ivpha) = VPhaeo ! Phaeocystis sinking velocity - wF(2:Nn,ivphy) = VPhy - wF(2:Nn,ivdia) = VDia - wF(2:Nn,ivdet) = VDet - wF(2:Nn,ivdetsc) = VDet_zoo2 - wF(2:Nn,ivcoc) = VCocco - - wF(1,:) = 0.d0 - wF(Nn+1,:) = 0.d0 + !! Boundary conditions (surface and bottom) + wF(1,:) = 0.d0 + wF(Nn+1,:) = 0.d0 !if (allow_var_sinking) then !! wF(2:Nn+1,ivdet) = Vdet_a * abs(zbar_n(2:Nn+1)) + VDet @@ -65,31 +67,25 @@ subroutine Depth_calculations(n,Nn,wF,zF,thick,recipthick, partit, mesh) ! wF(2:Nn+1,ivdet) = Vcalc * abs(zbar_3d_n(2:Nn+1, n)) + VDet !end if -!---------------------------------------------------- -! Vertical layers thickness - - thick =0.0_WP - recipthick=0.0_WP - zF=0.0_WP - -!do n=1,myDim_nod2D+eDim_nod2D - do k=1, Nn !nlevels_nod2D(n)-1 - thick(k)=hnode(k,n) - if (hnode(k,n) > 0._WP) then - recipthick(k)=1./hnode(k,n) - else - recipthick(k)=0._WP - end if - end do -!end do - -! layer depth (negative) - -!do n=1,myDim_nod2D+eDim_nod2D - do k=1, Nn+1 !nlevels_nod2D(n) - zF(k)=zbar_3d_n(k,n) - end do -!end do + !! Calculate layer thickness and reciprocal of it + thick = 0.0_WP + recipthick = 0.0_WP + zf = 0.0_WP + + do k=1, nn + thick(k) = hnode(k,n) + if (hnode(k,n) > 0.0_WP) then +! if thick(k) > 0.0_WP) then ! alternative + recipthick(k) = 1.0/hnode(k,n) + else + recipthick(k) = 0.0_WP + end if + end do + + !! set layer depth (negative) + do k=1, nn+1 + zf(k)=zbar_3d_n(k,n) + end do end subroutine Depth_calculations @@ -100,24 +96,26 @@ subroutine Cobeta(partit, mesh) use REcoM_GloVar use g_clock use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use o_PARAM use g_comm_auto - Implicit none + + implicit none -! Declarations - real(kind=8) :: yearfrac ! The fraction of the year that has passed [0 1] - real(kind=8) :: yDay ! yearfrac in radians [0 2*pi] - real(kind=8) :: declination = 0.d0 ! Declination of the sun at present lat and time - real(kind=8) :: CosAngleNoon = 0.d0 ! Cos(Angle of Incidence) at Noon ? - integer :: n + ! Input parameters + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh -! Constants - real(kind=8) :: nWater = 1.33 + ! Local variables + real(kind=8) :: yearfrac ! Fraction of year [0 1] + real(kind=8) :: yDay ! Year fraction in radians [0 2*pi] + real(kind=8) :: declination = 0.d0 ! Declination of the sun at present lat and time + real(kind=8) :: CosAngleNoon = 0.d0 ! Cosine of Angle of Incidence at noon + integer :: n - type(t_partit), intent(inout), target :: partit - type(t_mesh) , intent(inout), target :: mesh + ! Constants + real(kind=8), parameter :: nWater = 1.33 ! Refractive indices of water #include "../associate_part_def.h" #include "../associate_mesh_def.h" @@ -131,9 +129,11 @@ subroutine Cobeta(partit, mesh) !! Publishing Company, Amsterdam, Oxford, !! New York, 1976, ISBN 0-444-41444-4. - yearfrac = mod(real(daynew),real(ndpyr))/real(ndpyr) - yDay = 2 * pi * yearfrac - declination = 0.006918 & + !! Calculate solar declination using Paltridge & Platt (1976) formula + yearfrac = mod(real(daynew), real(ndpyr)) / real(ndpyr) + yDay = 2.0d0 * pi * yearfrac + + declination = 0.006918 & - 0.399912 * cos( yDay) & + 0.070257 * sin( yDay) & - 0.006758 * cos(2 * yDay) & @@ -141,33 +141,35 @@ subroutine Cobeta(partit, mesh) - 0.002697 * cos(3 * yDay) & + 0.001480 * sin(3 * yDay) - do n=1, myDim_nod2D!+eDim_nod2D - - cosAngleNoon = sin(geo_coord_nod2D(2,n)) * sin(declination) & - + cos(geo_coord_nod2D(2,n)) * cos(declination) - cosAI(n) = sqrt(1-(1-cosAngleNoon**2)/nWater**2) + !! Calculate cosine of angle of incidence for each node + do n = 1, myDim_nod2D + cosAngleNoon = sin(geo_coord_nod2D(2, n)) * sin(declination) & + + cos(geo_coord_nod2D(2, n)) * cos(declination) - end do + cosAI(n) = sqrt(1.0d0 - (1.0d0 - cosAngleNoon**2) / nWater**2) + end do end subroutine Cobeta !================================================================================ ! Calculating second zooplankton respiration rates !================================================================================ subroutine krill_resp(n, partit, mesh) - use REcoM_declarations - use REcoM_LocVar - use REcoM_GloVar - use g_clock - use o_PARAM -! use g_PARSUP + use REcoM_declarations + use REcoM_LocVar + use REcoM_GloVar + use g_clock + use o_PARAM use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP - use g_comm_auto - implicit none - integer :: n - - type(t_partit), intent(inout), target :: partit - type(t_mesh) , intent(inout), target :: mesh + use MOD_PARTIT + use MOD_PARSUP + use g_comm_auto + + implicit none + + ! Input parameters + integer :: n + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + #include "../associate_part_def.h" #include "../associate_mesh_def.h" #include "../associate_part_ass.h" @@ -201,4 +203,3 @@ subroutine krill_resp(n, partit, mesh) end if endif end subroutine krill_resp - diff --git a/src/int_recom/recom_forcing.F90 b/src/int_recom/recom_forcing.F90 index 81650779d..f74022f8e 100644 --- a/src/int_recom/recom_forcing.F90 +++ b/src/int_recom/recom_forcing.F90 @@ -1,7 +1,7 @@ !=============================================================================== ! REcoM_Forcing !=============================================================================== -subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sali_depth & +subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali_depth & , CO2_watercolumn & , pH_watercolumn & , pCO2_watercolumn & @@ -34,6 +34,7 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal 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 @@ -66,7 +67,7 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal !!---- Subroutine Depth real(kind=8),dimension(mesh%nl) :: zF ! [m] Depth of fluxes - real(kind=8),dimension(mesh%nl,5) :: SinkVel ! [m/day] + real(kind=8),dimension(mesh%nl,6) :: SinkVel ! [m/day] real(kind=8),dimension(mesh%nl-1) :: thick ! [m] Vertical distance between two nodes = Thickness real(kind=8),dimension(mesh%nl-1) :: recipthick ! [1/m] reciprocal of thick @@ -110,10 +111,13 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal tiny_Si = tiny_C_d/SiCmax ! SiCmax = 0.8d0 -#if defined (__coccos) - tiny_N_c = tiny_chl/chl2N_max_c ! 0.00001/ 3.5d0 +if (enable_coccos) then + tiny_N_c = tiny_chl/chl2N_max_c ! 0.00001/ 3.5d0 tiny_C_c = tiny_N_c/NCmax_c ! NCmax_c = 0.15d0 -#endif + + tiny_N_p = tiny_chl/chl2N_max_p ! 0.00001/ 3.5d0 + tiny_C_p = tiny_N_p/NCmax_p ! NCmax_c = 0.15d0 +endif call Cobeta(partit, mesh) call Depth_calculations(n, Nn,SinkVel,zF,thick,recipthick, partit, mesh) @@ -134,7 +138,7 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal REcoM_T = min(REcoM_T, 40.d0) !!---- minimum set to 21: K1/K2 Lueker valid between 2degC-35degC and 19-43psu, else causes trouble in regions with S between 19 and 21 and ice conc above 97% - REcoM_S = max(21.d0, Sali(1)) + REcoM_S = max(21.d0, Sali(1)) !!---- maximum set to 43: K1/K2 Lueker valid between 2degC-35degC and 19-43psu, else causes trouble REcoM_S = min(REcoM_S, 43.d0) !!!!!!!! !!---- convert from Pa to atm. @@ -183,7 +187,7 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal endif call flxco2(co2flux, co2ex, dpco2surf, & - ph, pco2surf, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, & + ph, pco2surf, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, K0, & REcoM_T, REcoM_S, REcoM_Alk, REcoM_DIC, REcoM_Si, REcoM_Phos, kw660, LocAtmCO2, Patm, thick(One), Nmocsy, Lond,Latd, & optCON='mol/m3',optT='Tpot ',optP='m ',optB='u74',optK1K2='l ',optKf='dg',optGAS='Pinsitu',optS='Sprc') @@ -259,19 +263,71 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal state(1:nn,idiac) = max(tiny_C_d,state(1:nn,idiac)) state(1:nn,idiasi) = max(tiny_Si, state(1:nn,idiasi)) -#if defined (__coccos) +if (enable_coccos) then state(1:nn,icchl) = max(tiny_chl,state(1:nn,icchl)) state(1:nn,icocn) = max(tiny_N_c,state(1:nn,icocn)) state(1:nn,icocc) = max(tiny_C_c,state(1:nn,icocc)) -#endif -#if defined (__3Zoo2Det) + state(1:nn,iphachl) = max(tiny_chl,state(1:nn,iphachl)) + state(1:nn,iphan) = max(tiny_N_p,state(1:nn,iphan)) + state(1:nn,iphac) = max(tiny_C_p,state(1:nn,iphac)) +endif + +if (enable_3zoo2det) then state(1:nn,imiczoon) = max(tiny,state(1:nn,imiczoon)) state(1:nn,imiczooc) = max(tiny,state(1:nn,imiczooc)) -#endif +endif if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> ciso after REcoM_Forcing'//achar(27)//'[0m' + if (ciso) then +! Calculate carbon-isotopic fractionation, radioactive decay is calculated in oce_ale_tracer.F90 + +! Fractionation due to air-sea exchange and chemical speciation of CO2 + call recom_ciso_airsea(recom_t(1), co3(1), recom_dic(1)) ! -> alpha_aq, alpha_dic. CO3 is taken from mocsy + +! Isotopic ratios of dissolved CO2, also needed to calculate biogenic fractionation + r_dic_13 = max(tiny*1e-3,state(1,idic_13)*1e-3) / recom_dic(1) + r_co2s_13 = alpha_aq_13 / alpha_dic_13 * r_dic_13 +! Calculate air-sea fluxes of 13|14CO2 in mmol / m**2 / s + kwco2 = kw660(1) * (660/scco2(REcoM_T(1)))**0.5 ! Piston velocity (via mocsy) + co2sat = co2flux(1) / (kwco2 + tiny) + co2(1) ! Saturation concentration of CO2 (via mocsy) +! co2flux_13 = kwco2 * alpha_k_13 * (alpha_aq_13 * r_atm_13 * co2sat - r_co2s_13 * co2(1)) +! co2flux_13 = alpha_k_13 * alpha_aq_13 * kwco2 * (r_atm_13 * co2sat - r_dic_13 * co2(1) / alpha_dic_13) +! Fractionation factors were determined for freshwater, include a correction for enhanced fractionation in seawater + co2flux_13 = (alpha_k_13 * alpha_aq_13 - 0.0002) * kwco2 * (r_atm_13 * co2sat - r_dic_13 * co2(1) / alpha_dic_13) + co2flux_seaicemask_13 = co2flux_13 * 1.e3 + +! Biogenic fractionation due to photosynthesis of plankton +! phyc_13|14 and diac_13|14 are only used in REcoM_sms to calculate DIC_13|14, DOC_13|14 and DetC_13|14 + + call recom_ciso_photo(co2(1)) ! -> alpha_p + r_phyc_13 = r_co2s_13 / alpha_p_13 + r_diac_13 = r_co2s_13 / alpha_p_dia_13 + state(1:nn,iphyc_13) = max((tiny_C * r_phyc_13), (state(1:nn,iphyc) * r_phyc_13)) + state(1:nn,idiac_13) = max((tiny_C_d * r_diac_13), (state(1:nn,idiac) * r_diac_13)) + +! The same for radiocarbon, fractionation factors have been already derived above + if (ciso_14) then +! Air-sea exchange + r_dic_14 = max(tiny*1e-3,state(1,idic_14)*1e-3) / recom_dic(1) + r_co2s_14 = alpha_aq_14 / alpha_dic_14 * r_dic_14 +! co2flux_14 = kwco2 * alpha_k_14 * (alpha_aq_14 * r_atm_14 * co2sat - r_co2s_14 * co2(1)) +! Fractionation factors were determined for freshwater, include a correction for enhanced fractionation seawater + co2flux_14 = (alpha_k_14 * alpha_aq_14 - 0.0004) * kwco2 * (r_atm_14 * co2sat - r_dic_14 * co2(1) / alpha_dic_14) + co2flux_seaicemask_14 = co2flux_14 * 1.e3 +! Biogenic fractionation + if (ciso_organic_14) then + r_phyc_14 = r_co2s_14 / alpha_p_14 + r_diac_14 = r_co2s_14 / alpha_p_dia_14 + state(1:nn,iphyc_14) = max((tiny_C * r_phyc_14), (state(1:nn,iphyc) * r_phyc_14)) + state(1:nn,idiac_14) = max((tiny_C_d * r_diac_14), (state(1:nn,idiac) * r_diac_14)) + end if + end if +! Radiocarbon + end if +! ciso + !------------------------------------------------------------------------------- ! Diagnostics if (Diags) then @@ -291,10 +347,17 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp , Temp, Sali, Sal locNNAd = sum(vertNNAd(1:nn) * thick(1:nn)) locChldegd = sum(vertChldegd(1:nn) * thick(1:nn)) +if (enable_coccos) then locNPPc = sum(vertNPPc(1:nn) * thick(1:nn)) locGPPc = sum(vertGPPc(1:nn) * thick(1:nn)) locNNAc = sum(vertNNAc(1:nn) * thick(1:nn)) locChldegc = sum(vertChldegc(1:nn) * thick(1:nn)) + locNPPp = sum(vertNPPp(1:nn) * thick(1:nn)) + locGPPp = sum(vertGPPp(1:nn) * thick(1:nn)) + locNNAp = sum(vertNNAp(1:nn) * thick(1:nn)) + locChldegp = sum(vertChldegp(1:nn) * thick(1:nn)) +endif + end if end subroutine REcoM_Forcing diff --git a/src/int_recom/recom_init.F90 b/src/int_recom/recom_init.F90 index e9b5aebbf..b8a94b276 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -30,6 +30,7 @@ subroutine recom_init(tracers, partit, mesh) use REcoM_locVar use recom_config use REcoM_ciso + implicit none #include "netcdf.inc" !___________________________________________________________________________ @@ -45,6 +46,9 @@ subroutine recom_init(tracers, partit, mesh) type(t_partit), intent(inout), target :: partit type(t_mesh), intent(in) , target :: mesh + ! After reading tracer namelist - validate actual IDs + integer, dimension(tracers%num_tracers) :: tracer_id_array + #include "../associate_part_def.h" #include "../associate_mesh_def.h" #include "../associate_part_ass.h" @@ -70,6 +74,7 @@ subroutine recom_init(tracers, partit, mesh) allocate(RiverDSi2D ( node_size )) allocate(RiverDIC2D ( node_size )) allocate(RiverAlk2D ( node_size )) + allocate(RiverFe ( node_size )) !! * Erosion nutrients as surface boundary condition * allocate(ErosionTON2D ( node_size )) @@ -97,6 +102,7 @@ subroutine recom_init(tracers, partit, mesh) allocate(decayBenthos ( benthos_num )) ! [1/day] Decay rate of detritus in the benthic layer allocate(PAR3D ( nl-1, node_size )) + GloFeDust = 0.d0 AtmFeInput = 0.d0 GloNDust = 0.d0 @@ -108,9 +114,10 @@ subroutine recom_init(tracers, partit, mesh) RiverDSi2D = 0.d0 RiverDIC2D = 0.d0 RiverAlk2D = 0.d0 + RiverFe = 0.d0 ErosionTON2D = 0.d0 - ErosionTON2D = 0.d0 + ErosionTOC2D = 0.d0 ErosionTSi2D = 0.d0 relax_alk = 0.d0 @@ -130,8 +137,6 @@ subroutine recom_init(tracers, partit, mesh) LocBenthos = 0.d0 decayBenthos = 0.d0 - wFluxPhy = 0.d0 - wFluxDia = 0.d0 PAR3D = 0.d0 ! pco2surf = 0.d0 @@ -148,28 +153,36 @@ subroutine recom_init(tracers, partit, mesh) allocate(NPPn ( node_size )) allocate(NPPd ( node_size )) allocate(NPPc ( node_size )) + allocate(NPPp ( node_size )) allocate(GPPn ( node_size )) allocate(GPPd ( node_size )) allocate(GPPc ( node_size )) + allocate(GPPp ( node_size )) allocate(NNAn ( node_size )) allocate(NNAd ( node_size )) allocate(NNAc ( node_size )) + allocate(NNAp ( node_size )) allocate(Chldegn ( node_size )) allocate(Chldegd ( node_size )) allocate(Chldegc ( node_size )) + allocate(Chldegp ( node_size )) NPPn = 0.d0 NPPd = 0.d0 NPPc = 0.d0 + NPPp = 0.d0 GPPn = 0.d0 GPPd = 0.d0 GPPc = 0.d0 + GPPp = 0.d0 NNAn = 0.d0 NNAd = 0.d0 NNAc = 0.d0 + NNAp = 0.d0 Chldegn = 0.d0 Chldegd = 0.d0 Chldegc = 0.d0 + Chldegp = 0.d0 !! *** Allocate 3D diagnostics *** allocate(respmeso ( nl-1, node_size )) @@ -180,15 +193,19 @@ subroutine recom_init(tracers, partit, mesh) allocate(aggn ( nl-1, node_size )) allocate(aggd ( nl-1, node_size )) allocate(aggc ( nl-1, node_size )) + allocate(aggp ( nl-1, node_size )) allocate(docexn ( nl-1, node_size )) allocate(docexd ( nl-1, node_size )) allocate(docexc ( nl-1, node_size )) + allocate(docexp ( nl-1, node_size )) allocate(respn ( nl-1, node_size )) allocate(respd ( nl-1, node_size )) allocate(respc ( nl-1, node_size )) + allocate(respp ( nl-1, node_size )) allocate(NPPn3D ( nl-1, node_size )) allocate(NPPd3D ( nl-1, node_size )) allocate(NPPc3D ( nl-1, node_size )) + allocate(NPPp3D ( nl-1, node_size )) respmeso = 0.d0 respmacro = 0.d0 @@ -198,15 +215,78 @@ subroutine recom_init(tracers, partit, mesh) aggn = 0.d0 aggd = 0.d0 aggc = 0.d0 + aggp = 0.d0 docexn = 0.d0 docexd = 0.d0 docexc = 0.d0 + docexp = 0.d0 respn = 0.d0 respd = 0.d0 respc = 0.d0 + respp = 0.d0 NPPn3D = 0.d0 NPPd3D = 0.d0 NPPc3D = 0.d0 + NPPp3D = 0.d0 + +!! From Hannahs new temperature function (not sure if needed as diagnostic): + + allocate(TTemp_diatoms (nl-1,node_size)) + allocate(TTemp_phyto (nl-1,node_size)) + allocate(TTemp_cocco (nl-1,node_size)) + allocate(TTemp_phaeo (nl-1,node_size)) + + TTemp_diatoms (:,:) = 0.d0 + TTemp_phyto (:,:) = 0.d0 + TTemp_cocco (:,:) = 0.d0 + TTemp_phaeo (:,:) = 0.d0 + + allocate(TPhyCO2 (nl-1,node_size)) + allocate(TDiaCO2 (nl-1,node_size)) + allocate(TCoccoCO2 (nl-1,node_size)) + allocate(TPhaeoCO2 (nl-1,node_size)) + + TPhyCO2 (:,:) = 0.d0 + TDiaCO2 (:,:) = 0.d0 + TCoccoCO2 (:,:) = 0.d0 + TPhaeoCO2 (:,:) = 0.d0 + + allocate(TqlimitFac_phyto (nl-1,node_size)) + allocate(TqlimitFac_diatoms (nl-1,node_size)) + allocate(TqlimitFac_cocco (nl-1,node_size)) + allocate(TqlimitFac_phaeo (nl-1,node_size)) + + TqlimitFac_phyto (:,:) = 0.d0 + TqlimitFac_diatoms (:,:) = 0.d0 + TqlimitFac_cocco (:,:) = 0.d0 + TqlimitFac_phaeo (:,:) = 0.d0 + + + allocate(TCphotLigLim_diatoms (nl-1,node_size)) + allocate(TCphotLigLim_phyto (nl-1,node_size)) + allocate(TCphotLigLim_cocco (nl-1,node_size)) + allocate(TCphotLigLim_phaeo (nl-1,node_size)) + + + TCphotLigLim_diatoms (:,:) = 0.d0 + TCphotLigLim_phyto (:,:) = 0.d0 + TCphotLigLim_cocco (:,:) = 0.d0 + TCphotLigLim_phaeo (:,:) = 0.d0 + + allocate(TCphot_diatoms (nl-1,node_size)) + allocate(TCphot_phyto (nl-1,node_size)) + allocate(TCphot_cocco (nl-1,node_size)) + allocate(TCphot_phaeo (nl-1,node_size)) + + TCphot_diatoms (:,:) = 0.d0 + TCphot_phyto (:,:) = 0.d0 + TCphot_cocco (:,:) = 0.d0 + TCphot_phaeo (:,:) = 0.d0 + + allocate(TSi_assimDia (nl-1,node_size)) + + TSi_assimDia (:,:) = 0.d0 + end if !! *** Allocate 3D mocsy *** @@ -246,125 +326,240 @@ subroutine recom_init(tracers, partit, mesh) Sinkingvel1(:,:) = 0.d0 Sinkingvel2(:,:) = 0.d0 + allocate(Sinkvel1_tr(nl,node_size,num_tracers), Sinkvel2_tr(nl,node_size,num_tracers)) ! OG 16.03.23 + Sinkvel1_tr(:,:,:) = 0.0d0 ! OG 16.03.23 + Sinkvel2_tr(:,:,:) = 0.0d0 ! OG 16.03.23 + + if (use_MEDUSA) then + allocate(GloSed(node_size,sedflx_num)) + allocate(SinkFlx(node_size,bottflx_num)) + allocate(SinkFlx_tr(node_size,bottflx_num,num_tracers)) ! kh 25.03.22 buffer sums per tracer index + + SinkFlx(:,:) = 0.d0 + SinkFlx_tr(:,:,:) = 0.0d0 ! kh 25.03.22 + GloSed(:,:) = 0.d0 + allocate(lb_flux(node_size,9)) + lb_flux(:,:) = 0.d0 + end if + + ! After reading parecomsetup namelist + call initialize_tracer_indices + + ! Validation check here + call validate_recom_tracers(num_tracers, mype) + + ! ... populate tracer_id_array from namelist ... + tracer_id_array = tracers%data(1:tracers%num_tracers)%ID + call validate_tracer_id_sequence(tracer_id_array, num_tracers, mype) + + !=============================================================================== + ! Model Configuration Summary + !=============================================================================== + ! Configuration 1: Base model (enable_3zoo2det=F, enable_coccos=F) + ! - 2 Phytoplankton: General Phy, Diatoms + ! - 1 Zooplankton: Heterotrophs + ! - 1 Detritus pool + ! + ! Configuration 2: 3Zoo2Det (enable_3zoo2det=T, enable_coccos=F) + ! - 2 Phytoplankton: General Phy, Diatoms + ! - 3 Zooplankton: Het, Zoo2, Zoo3 + ! - 2 Detritus pools + ! + ! Configuration 3: Coccos (enable_3zoo2det=F, enable_coccos=T) + ! - 4 Phytoplankton: General Phy, Diatoms, Coccos, Phaeo + ! - 1 Zooplankton: Heterotrophs + ! - 1 Detritus pool + ! + ! Configuration 4: Full model (enable_3zoo2det=T, enable_coccos=T) + ! - 4 Phytoplankton: General Phy, Diatoms, Coccos, Phaeo + ! - 3 Zooplankton: Het, Zoo2, Zoo3 + ! - 2 Detritus pools + !=============================================================================== + DO i=num_tracers-bgc_num+1, num_tracers id=tracers%data(i)%ID SELECT CASE (id) -! ******************* -! CASE 2phy 1zoo 1det -! ******************* -! Skip: DIN, DIC, Alk, DSi and O2 are read from files -! Fe [mol/L] => [umol/m3] Check the units again! + !--------------------------------------------------------------------------- + ! Base Model: 2 Phytoplankton + 1 Zooplankton + 1 Detritus + !--------------------------------------------------------------------------- + ! Skip: DIN, DIC, Alk, DSi and O2 are read from files + ! Fe [mol/L] => [umol/m3] Check the units again! + + ! --- Small Phytoplankton + CASE (1004) ! PhyN - Phytoplankton Nitrogen + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max - CASE (1004) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max ! PhyN + CASE (1005) ! PhyC - Phytoplankton Carbon + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax - CASE (1005) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax ! PhyC + CASE (1006) ! PhyChl - Phytoplankton Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl - CASE (1006) - tracers%data(i)%values(:,:) = tiny_chl ! PhyChl + ! --- Detritus (Non-living organic matter) --- + CASE (1007) ! DetN - Detrital Nitrogen + tracers%data(i)%values(:,:) = tiny - CASE (1007) - tracers%data(i)%values(:,:) = tiny ! DetN + CASE (1008) ! DetC - Detrital Carbon + tracers%data(i)%values(:,:) = tiny - CASE (1008) - tracers%data(i)%values(:,:) = tiny ! DetC + ! --- Mesozooplankton (Heterotrophs) --- + CASE (1009) ! HetN - Heterotroph Nitrogen + tracers%data(i)%values(:,:) = tiny - CASE (1009) - tracers%data(i)%values(:,:) = tiny ! HetN + CASE (1010) ! HetC - Heterotroph Carbon (using Redfield ratio) + tracers%data(i)%values(:,:) = tiny * Redfield - CASE (1010) - tracers%data(i)%values(:,:) = tiny * Redfield ! HetC + ! --- Dissolved Organic Matter --- + CASE (1011) ! DON - Dissolved Organic Nitrogen + tracers%data(i)%values(:,:) = tiny - CASE (1011) - tracers%data(i)%values(:,:) = tiny ! DON + CASE (1012) ! DOC - Dissolved Organic Carbon + tracers%data(i)%values(:,:) = tiny - CASE (1012) - tracers%data(i)%values(:,:) = tiny ! DOC + ! --- Diatoms --- + CASE (1013) ! DiaN - Diatom Nitrogen + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max - CASE (1013) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max ! DiaN + CASE (1014) ! DiaC - Diatom Carbon + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax - CASE (1014) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax ! DiaC + CASE (1015) ! DiaChl - Diatom Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl - CASE (1015) - tracers%data(i)%values(:,:) = tiny_chl ! DiaChl + CASE (1016) ! DiaSi - Diatom Silica + tracers%data(i)%values(:,:) = tiny_chl/chl2N_max_d/NCmax_d/SiCmax - CASE (1016) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max_d/NCmax_d/SiCmax ! DiaSi + CASE (1017) ! DetSi - Detrital Silica + tracers%data(i)%values(:,:) = tiny - CASE (1017) - tracers%data(i)%values(:,:) = tiny ! DetSi + ! --- Iron (micronutrient) --- + CASE (1019) ! Fe - Iron (unit conversion: mol/L => umol/m3) + tracers%data(i)%values(:,:) = tracers%data(i)%values(:,:)* 1.e9 - CASE (1019) - tracers%data(i)%values(:,:) = tracers%data(i)%values(:,:)* 1.e9 ! Fe [mol/L] => [umol/m3] Check the units again! + ! --- Calcium Carbonate (Calcite) --- + CASE (1020) ! PhyCalc - Phytoplankton Calcite + tracers%data(i)%values(:,:) = tiny * Redfield - CASE (1020) - tracers%data(i)%values(:,:) = tiny * Redfield ! PhyCalc + CASE (1021) ! DetCalc - Detrital Calcite + tracers%data(i)%values(:,:) = tiny - CASE (1021) - tracers%data(i)%values(:,:) = tiny ! DetCalc + !--------------------------------------------------------------------------- + ! Extended Model: Additional Zooplankton and Detritus (enable_3zoo2det) + !--------------------------------------------------------------------------- -! ******************* -! CASE 2phy 2zoo 2det -! ******************* -#if defined (__3Zoo2Det) CASE (1023) - tracers%data(i)%values(:,:) = tiny ! Zoo2N + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! Zoo2N - Macrozooplankton Nitrogen + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! CoccoN - Coccolithophore Nitrogen + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max + END IF + CASE (1024) - tracers%data(i)%values(:,:) = tiny * Redfield ! Zoo2C + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! Zoo2C - Macrozooplankton Carbon + tracers%data(i)%values(:,:) = tiny * Redfield + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! CoccoC - Coccolithophore Carbon + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max / NCmax + END IF + CASE (1025) - tracers%data(i)%values(:,:) = tiny ! DetZ2N + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! DetZ2N - Macrozooplankton Detrital Nitrogen + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! CoccoChl - Coccolithophore Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl + END IF + CASE (1026) - tracers%data(i)%values(:,:) = tiny ! DetZ2C + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! DetZ2C - Macrozooplankton Detrital Carbon + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! PhaeoN - Phaeocystis Nitrogen + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max + END IF + CASE (1027) - tracers%data(i)%values(:,:) = tiny ! DetZ2Si + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! DetZ2Si - Zooplankton 2 Detrital Silica + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! PhaeoC - Phaeocystis Carbon + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max / NCmax + END IF + CASE (1028) - tracers%data(i)%values(:,:) = tiny ! DetZ2Calc -#endif + IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! DetZ2Calc - Macrozooplankton Detrital Calcite + tracers%data(i)%values(:,:) = tiny + ELSE IF (enable_coccos .AND. .NOT. enable_3zoo2det) THEN + ! PhaeoChl - Phaeocystis Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl + END IF + + !--------------------------------------------------------------------------- + ! Extended Model: Coccolithophores with 3Zoo2Det + !--------------------------------------------------------------------------- -! ******************* -! CASE 3phy 2zoo 2det -! ******************* -#if defined (__coccos) & defined (__3Zoo2Det) CASE (1029) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max ! CoccoN + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! CoccoN - Coccolithophore Nitrogen + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max + ELSE IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! Zoo3N - Microzooplankton Nitrogen + tracers%data(i)%values(:,:) = tiny + END IF + CASE (1030) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax ! CoccoC + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! CoccoC - Coccolithophore Carbon + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max / NCmax + ELSE IF (enable_3zoo2det .AND. .NOT. enable_coccos) THEN + ! Zoo3C - Microzooplankton Carbon + tracers%data(i)%values(:,:) = tiny * Redfield + END IF + CASE (1031) - tracers%data(i)%values(:,:) = tiny_chl ! CoccoChl -! ******************* -! CASE 3phy 1zoo 1det -! ******************* -#elif defined (__coccos) & !defined (__3Zoo2Det) - CASE (1023) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max ! CoccoN - CASE (1024) - tracers%data(i)%values(:,:) = tiny_chl/chl2N_max/NCmax ! CoccoC - CASE (1025) - tracers%data(i)%values(:,:) = tiny_chl ! CoccoChl -#endif + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! CoccoChl - Coccolithophore Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl + END IF -! ******************* -! CASE 3phy 3zoo 2det -! ******************* -#if defined (__coccos) & defined (__3Zoo2Det) CASE (1032) - tracers%data(i)%values(:,:) = tiny ! Zoo3N + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! PhaeoN - Phaeocystis Nitrogen + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max + END IF + CASE (1033) - tracers%data(i)%values(:,:) = tiny * Redfield ! Zoo3C -#elif !defined (__coccos) & defined (__3Zoo2Det) -! ******************* -! CASE 2phy 3zoo 2det -! ******************* - CASE (1029) - tracers%data(i)%values(:,:) = tiny ! Zoo3N - CASE (1030) - tracers%data(i)%values(:,:) = tiny * Redfield ! Zoo3C -#endif + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! PhaeoC - Phaeocystis Carbon + tracers%data(i)%values(:,:) = tiny_chl / chl2N_max / NCmax + END IF + + CASE (1034) + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! PhaeoChl - Phaeocystis Chlorophyll + tracers%data(i)%values(:,:) = tiny_chl + END IF + + CASE (1035) + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! Zoo3N - Zooplankton 3 Nitrogen + tracers%data(i)%values(:,:) = tiny + END IF + + CASE (1036) + IF (enable_coccos .AND. enable_3zoo2det) THEN + ! Zoo3C - Zooplankton 3 Carbon + tracers%data(i)%values(:,:) = tiny * Redfield + END IF END SELECT END DO @@ -419,31 +614,47 @@ subroutine recom_init(tracers, partit, mesh) end do if (mype==0) write(*,*) "Sanity check for REcoM variables after recom_init call" - 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 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.) + + if (enable_3zoo2det) then + is_3zoo2det=1.0_WP + else + is_3zoo2det=0.0_WP + endif + + if (enable_coccos) then + is_coccos=1.0_WP + else + is_coccos=0.0_WP + endif + +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 - end subroutine recom_init + 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 + end subroutine recom_init diff --git a/src/int_recom/recom_main.F90 b/src/int_recom/recom_main.F90 index c9c5575e5..6b583ebb7 100755 --- a/src/int_recom/recom_main.F90 +++ b/src/int_recom/recom_main.F90 @@ -6,8 +6,8 @@ module recom_interface interface subroutine recom(ice, dynamics, tracers, partit, mesh) use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use mod_tracer use MOD_DYN use MOD_ICE @@ -29,8 +29,8 @@ subroutine bio_fluxes(tracers, partit, mesh) use recom_config use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use mod_tracer use g_config @@ -52,11 +52,11 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) use MOD_MESH use MOD_TRACER use MOD_DYN - USE MOD_ICE + use MOD_ICE use o_ARRAYS use o_PARAM - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use recom_declarations use bio_fluxes_interface @@ -67,7 +67,8 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) use g_clock use g_forcing_arrays, only: press_air, u_wind, v_wind, shortwave use g_comm_auto - IMPLICIT NONE + + implicit none type(t_dyn) , intent(inout), target :: dynamics type(t_tracer), intent(inout), target :: tracers @@ -98,6 +99,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) integer :: idiags real(kind=8) :: Sali + logical :: do_update = .false. real(kind=8), allocatable :: Temp(:), Sali_depth(:), zr(:), PAR(:) real(kind=8), allocatable :: C(:,:) @@ -113,6 +115,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) real(kind=8), allocatable :: OmegaC_watercolumn(:) real(kind=8), allocatable :: kspc_watercolumn(:) real(kind=8), allocatable :: rhoSW_watercolumn(:) + real(kind=WP) :: ttf_rhs_bak (mesh%nl-1, tracers%num_tracers) ! local variable #include "../associate_part_def.h" #include "../associate_mesh_def.h" @@ -135,6 +138,17 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) if (restore_alkalinity) call bio_fluxes(tracers, partit, mesh) if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> bio_fluxes'//achar(27)//'[0m' + if (use_atbox) then ! MERGE +! Prognostic atmospheric isoCO2 + call recom_atbox(partit,mesh) +! optional I/O of isoCO2 and inferred cosmogenic 14C production; this may cost some CPU time + if (ciso .and. ciso_14) then + call annual_event(do_update) + if (do_update .and. mype==0) write (*, fmt = '(a50,2x,i6,4(2x,f6.2))') & + 'Year, xCO2 (ppm), cosmic 14C flux (at / cm² / s):', & + yearold, x_co2atm(1), x_co2atm_13(1), x_co2atm_14(1), cosmic_14(1) * production_rate_to_flux_14 + end if + end if ! ====================================================================================== !********************************* LOOP STARTS ***************************************** @@ -144,6 +158,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) !!---- 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) @@ -176,6 +191,31 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) !!---- Atmospheric CO2 in LocVar LocAtmCO2 = AtmCO2(month) +! Update of prognostic atmospheric CO2 values + if (use_atbox) then + LocAtmCO2 = x_co2atm(1) + if (ciso) then + LocAtmCO2_13 = x_co2atm_13(1) + if (ciso_14) LocAtmCO2_14 = x_co2atm_14(1) + end if + else +! Consider prescribed atmospheric CO2 values + if (ciso) then + LocAtmCO2_13 = AtmCO2_13(month) + if (ciso_14) then +! Latitude of nodal point n + lat_val = geo_coord_nod2D(2,n) / rad +! Zonally binned NH / SH / TZ 14CO2 input values + LocAtmCO2_14 = AtmCO2_14(lat_zone(lat_val), month) + end if + end if + end if ! use_atbox + + if (ciso) then + r_atm_13 = LocAtmCO2_13(1) / LocAtmCO2(1) + if (ciso_14) r_atm_14 = LocAtmCO2_14(1) / LocAtmCO2(1) + end if + !!---- Shortwave penetration SW = parFrac * shortwave(n) SW = SW * (1.d0 - a_ice(n)) @@ -206,6 +246,11 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) C(1:nzmax, tr_num-2) = tracers%data(tr_num)%values(1:nzmax, n) end do + ttf_rhs_bak = 0.0 + + + call recom_diag_backup(tracers, n, nzmax, num_tracers, ttf_rhs_bak) + !!---- Depth of the nodes in the water column zr(1:nzmax) = Z_3d_n(1:nzmax, n) @@ -219,30 +264,87 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) if (Diags) then !! * Allocate 3D diagnostics * - allocate(vertrespmeso(nl-1), vertrespmacro(nl-1), vertrespmicro(nl-1)) + 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), vertaggc(nl-1)) + allocate(vertaggn(nl-1), vertaggd(nl-1)) vertaggn = 0.d0 vertaggd = 0.d0 - vertaggc = 0.d0 - allocate(vertdocexn(nl-1), vertdocexd(nl-1), vertdocexc(nl-1)) + allocate(vertdocexn(nl-1), vertdocexd(nl-1)) vertdocexn = 0.d0 vertdocexd = 0.d0 - vertdocexc = 0.d0 - allocate(vertrespn(nl-1), vertrespd(nl-1), vertrespc(nl-1)) + 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 @@ -256,18 +358,26 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) 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 + 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 end if if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> REcoM_Forcing'//achar(27)//'[0m' ! ====================================================================================== !******************************** RECOM FORCING **************************************** - call REcoM_Forcing(zr, n, nzmax, C, SW, Loc_slp , Temp, Sali, Sali_depth & + call REcoM_Forcing(zr, n, nzmax, C, SW, Loc_slp, Temp, Sali, Sali_depth & , CO2_watercolumn & ! NEW MOCSY CO2 for the whole watercolumn , pH_watercolumn & ! NEW MOCSY pH for the whole watercolumn , pCO2_watercolumn & ! NEW MOCSY pCO2 for the whole watercolumn @@ -282,6 +392,8 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) 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) + !!---- 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] @@ -291,48 +403,116 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) !! * Update 2D diagnostics * NPPn(n) = locNPPn NPPd(n) = locNPPd - NPPc(n) = locNPPc GPPn(n) = locGPPn GPPd(n) = locGPPd - GPPc(n) = locGPPc NNAn(n) = locNNAn NNAd(n) = locNNAd - NNAc(n) = locNNAc Chldegn(n) = locChldegn Chldegd(n) = locChldegd + +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) - aggd (1:nzmax,n) = vertaggd (1:nzmax) - aggc (1:nzmax,n) = vertaggc (1:nzmax) docexn (1:nzmax,n) = vertdocexn (1:nzmax) - docexd (1:nzmax,n) = vertdocexd (1:nzmax) - docexc (1:nzmax,n) = vertdocexc (1:nzmax) respn (1:nzmax,n) = vertrespn (1:nzmax) - respd (1:nzmax,n) = vertrespd (1:nzmax) - respc (1:nzmax,n) = vertrespc (1:nzmax) NPPn3D (1:nzmax,n) = vertNPPn (1:nzmax) + + 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) - deallocate(vertNPPc, vertGPPc, vertNNAc, vertChldegc) +if (enable_coccos) then + deallocate(vertNPPc, vertGPPc, vertNNAc, vertChldegc) + deallocate(vertNPPp, vertGPPp, vertNNAp, vertChldegp) +endif !! * Deallocating 3D Diagnostics * - deallocate(vertrespmeso, vertrespmacro, vertrespmicro ) - deallocate(vertcalcdiss, vertcalcif ) - deallocate(vertaggn, vertaggd, vertaggc ) - deallocate(vertdocexn, vertdocexd, vertdocexc ) - deallocate(vertrespn, vertrespd, vertrespc ) + 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 @@ -345,6 +525,12 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) GloCO2flux(n) = dflux(1) ! [mmol/m2/d] GloCO2flux_seaicemask(n) = co2flux_seaicemask(1) ! [mmol/m2/s] GloO2flux_seaicemask(n) = o2flux_seaicemask(1) ! [mmol/m2/s] + if (ciso) then + GloCO2flux_seaicemask_13(n) = co2flux_seaicemask_13(1) ! [mmol/m2/s] + if (ciso_14) then + GloCO2flux_seaicemask_14(n) = co2flux_seaicemask_14(1) ! [mmol/m2/s] + end if + end if GloO2flux(n) = oflux(1) ! [mmol/m2/d] PAR3D(1:nzmax,n) = PAR(1:nzmax) @@ -375,6 +561,16 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) call exchange_nod(GloCO2flux_seaicemask, partit) call exchange_nod(GloO2flux_seaicemask, partit) + if (ciso) then + call exchange_nod(GloPCO2surf_13, partit) + call exchange_nod(GloCO2flux_13, partit) + call exchange_nod(GloCO2flux_seaicemask_13, partit) + if (ciso_14) then + call exchange_nod(GloPCO2surf_14, partit) + call exchange_nod(GloCO2flux_14, partit) + call exchange_nod(GloCO2flux_seaicemask_14, partit) + end if + end if do n=1, benthos_num call exchange_nod(Benthos(:,n), partit) end do @@ -388,10 +584,16 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) 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 do n=1, benthos_num @@ -412,6 +614,35 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) call exchange_nod(OmegaC3D, partit) 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 ! ====================================================================================== @@ -425,8 +656,8 @@ subroutine bio_fluxes(tracers, partit, mesh) use recom_config use mod_mesh - USE MOD_PARTIT - USE MOD_PARSUP + use MOD_PARTIT + use MOD_PARSUP use mod_tracer use g_config @@ -496,4 +727,4 @@ subroutine bio_fluxes(tracers, partit, mesh) relax_alk=relax_alk-net/ocean_area ! at ocean surface layer -end subroutine bio_fluxes \ No newline at end of file +end subroutine bio_fluxes diff --git a/src/int_recom/recom_modules.F90 b/src/int_recom/recom_modules.F90 index c4113377c..1d50fda51 100644 --- a/src/int_recom/recom_modules.F90 +++ b/src/int_recom/recom_modules.F90 @@ -30,69 +30,50 @@ module recom_config isi = 18, ife = 19, iphycal = 20, idetcal = 21, & ioxy = 22 -#if defined (__3Zoo2Det) -! ******************* -! CASE 2phy 2zoo 2det -! ******************* Integer :: izoo2n = 23, izoo2c = 24, idetz2n = 25, & idetz2c = 26, idetz2si = 27, idetz2calc = 28 -#endif -#if defined (__coccos) & defined (__3Zoo2Det) -! ******************* -! CASE 3phy 2zoo 2det -! ******************* - Integer :: icocn = 29, icocc = 30, icchl = 31 + ! Microzooplankton (third zooplankton group) + integer :: imiczoon = 0 ! Microzooplankton Nitrogen (set below) + integer :: imiczooc = 0 ! Microzooplankton Carbon (set below) -#elif defined (__coccos) & !defined (__3Zoo2Det) -! ******************* -! CASE 3phy 1zoo 1det -! ******************* - Integer :: icocn = 23, icocc = 24, icchl = 25 -#endif + ! --------------------------------------------------------------------------- + ! PHYTOPLANKTON GROUPS (coccos configuration) + ! --------------------------------------------------------------------------- + ! Coccolithophores and Phaeocystis when enable_coccos = .true. -#if defined (__coccos) & defined (__3Zoo2Det) -! ******************* -! CASE 3phy 3zoo 2det -! ******************* - Integer :: imiczoon = 32, imiczooc = 33 + integer :: icocn = 0 ! Coccolithophore Nitrogen (set below) + integer :: icocc = 0 ! Coccolithophore Carbon (set below) + integer :: icchl = 0 ! Coccolithophore Chlorophyll (set below) -#elif !defined (__coccos) & defined (__3Zoo2Det) -! ******************* -! CASE 2phy 3zoo 2det -! ******************* - Integer :: imiczoon = 29, imiczooc = 30 -#endif + integer :: iphan = 0 ! Phaeocystis Nitrogen (set below) + integer :: iphac = 0 ! Phaeocystis Carbon (set below) + integer :: iphachl = 0 ! Phaeocystis Chlorophyll (set below) !============================================================================= - Integer :: ivphy = 1, ivdia = 2, ivdet = 3, ivdetsc = 4, ivcoc = 5 - + Integer :: ivphy = 1, ivdia = 2, ivdet = 3, ivdetsc = 4, ivcoc = 5, ivpha = 6 + !============================================================================= integer, dimension(8) :: recom_remin_tracer_id = (/1001, 1002, 1003, 1018, 1019, 1022, 1302, 1402/) ! OG ! Todo: Make recom_sinking_tracer_id case sensitive - integer, dimension(29) :: recom_sinking_tracer_id = (/1007, 1008, 1017, 1021, 1004, 1005, 1020, 1006, & + integer, dimension(32) :: recom_sinking_tracer_id = (/1007, 1008, 1017, 1021, 1004, 1005, 1020, 1006, & 1013, 1014, 1016, 1015, 1025, 1026, 1027, 1028, & 1029, 1030, 1031, & + 1032, 1033, 1034, & 1308, 1321, 1305, 1320, & 1314, 1408, 1421, 1405, 1420, 1414/) integer, dimension(8) :: recom_det_tracer_id = (/1007, 1008, 1017, 1021, 1308, 1321, 1408, 1421/) integer, dimension(8) :: recom_phy_tracer_id = (/1004, 1005, 1020, 1305, 1320, 1405, 1420, 1006/) integer, dimension(6) :: recom_dia_tracer_id = (/1013, 1014, 1314, 1414, 1016, 1015/) -#if defined (__coccos) & defined (__3Zoo2Det) - integer, dimension(3) :: recom_cocco_tracer_id = (/1029, 1030, 1031/) - -#elif defined (__coccos) & !defined (__3Zoo2Det) - integer, dimension(3) :: recom_cocco_tracer_id = (/1023, 1024, 1025/) -#endif - -#if defined (__3Zoo2Det) - integer, dimension(4) :: recom_det2_tracer_id = (/1025, 1026, 1027, 1028/) -#endif + ! Configuration-dependent tracer arrays (allocated during initialization) + integer, dimension(3) :: recom_cocco_tracer_id + integer, dimension(3) :: recom_phaeo_tracer_id + integer, dimension(4) :: recom_det2_tracer_id !============================================================================= @@ -104,19 +85,25 @@ module recom_config Real(kind=8) :: Pa2atm = 101325.d0 ! [Pa/atm] Real(kind=8) :: redO2C = 1.453 ! O2:C ratio Anderson and Sarmiento, 1994 +!! *** REcoM setup *** + Logical :: enable_3zoo2det = .false. ! Control extended zooplankton variables + Logical :: enable_coccos = .false. ! Control coccolithophore variables + namelist /parecomsetup/ enable_3zoo2det, enable_coccos + !! *** General configuration *** Logical :: use_REcoM = .true. Logical :: REcoM_restart = .false. - Integer :: bgc_num = 33 ! NEW increased the number from 28 to 34 (added coccos and respiration) ! NEW 3Zoo changed from 31 to 33 + Integer :: bgc_num = 36 ! NEW increased the number from 28 to 34 (added coccos and respiration) ! NEW 3Zoo changed from 31 to 33 ! added phaeocystis: changed from 33 to 36 integer :: bgc_base_num = 22 ! standard tracers - Integer :: diags3d_num = 28 ! Number of diagnostic 3d tracers to be saved + Integer :: diags3d_num = 31 ! Number of diagnostic 3d tracers to be saved Real(kind=8) :: VDet = 20.d0 ! Sinking velocity, constant through the water column and positive downwards Real(kind=8) :: VDet_zoo2 = 200.d0 ! Sinking velocity, constant through the water column Real(kind=8) :: VPhy = 0.d0 !!! If the number of sinking velocities are different from 3, code needs to be changed !!! Real(kind=8) :: VDia = 0.d0 Real(kind=8) :: VCocco = 0.d0 ! NEW + Real(kind=8) :: VPhaeo = 0.d0 ! Phaeocystis Logical :: allow_var_sinking = .true. Integer :: biostep = 1 ! Number of times biology should be stepped forward for each time step Logical :: REcoM_Geider_limiter = .false. ! Decides what routine should be used to calculate limiters in sms @@ -168,6 +155,7 @@ module recom_config bgc_num, diags3d_num, bgc_base_num, & VDet, VDet_zoo2, & VPhy, VDia, VCocco, & + VPhaeo, & allow_var_sinking, biostep, REcoM_Geider_limiter, & REcoM_Grazing_Variable_Preference, & Grazing_detritus, & @@ -201,13 +189,31 @@ module recom_config namelist /painitialization_N/ cPhyN, cHetN, cZoo2N !!------------------------------------------------------------------------------ -!! *** Arrhenius function *** +!! *** Temperature and Arrhenius functions *** Real(kind=8) :: recom_Tref = 288.15d0 ! [K] Real(kind=8) :: C2K = 273.15d0 ! Conversion from degrees C to K Real(kind=8) :: Ae = 4500.d0 ! [K] Slope of the linear part of the Arrhenius function + +!! *** Temperature variables for Blanchard function *** + Real(kind=8) :: Tmax_phaeo = 16d0 ! [degC] For Blanchard temp fxn: maximum temperature + Real(kind=8) :: Topt_phaeo = 7.5272d0 ! [degC] For Blanchard temp fxn: optimum temperature + Real(kind=8) :: uopt_phaeo = 0.7328d0 ! [1/day] For Blanchard function: optimum growth date + Real(kind=8) :: beta_phaeo = 0.7829d0 ! [unitless] For Blanchard function + +! NEW MODIFIED parameters + Real(kind=8) :: ord_d = -0.2216d0 ! parameters for diatom temperature function + Real(kind=8) :: expon_d = 0.0406d0 ! diatom exponent + Real(kind=8) :: ord_phy = -1.2154d0 ! small phyto ordonnee + Real(kind=8) :: expon_phy = 0.0599d0 ! small phyto exponent + Real(kind=8) :: ord_cocco = -0.2310d0 ! coccolith ordonnee + Real(kind=8) :: expon_cocco = 0.0327d0 ! small phyto ordonnee + Real(kind=8) :: ord_phaeo = -0.2310d0 ! phaeocystis ordonnee + Real(kind=8) :: expon_phaeo = 0.0327d0 ! phaeocystis ordonnee + Real(kind=8) :: reminSi = 0.02d0 Real(kind=8) :: k_o2_remin = 15.d0 ! NEW O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 - namelist /paArrhenius/ recom_Tref, C2K, Ae, reminSi, k_o2_remin + namelist /paArrhenius/ recom_Tref, C2K, Ae, Tmax_phaeo, Topt_phaeo, uopt_phaeo, beta_phaeo, ord_d, expon_d, ord_phy, expon_phy, ord_cocco, expon_cocco, ord_phaeo, expon_phaeo, reminSi, k_o2_remin + !!------------------------------------------------------------------------------ !! *** For limiter function *** Real(kind=8) :: NMinSlope = 50.d0 @@ -215,15 +221,19 @@ module recom_config Real(kind=8) :: NCmin = 0.04d0 Real(kind=8) :: NCmin_d = 0.04d0 Real(kind=8) :: NCmin_c = 0.04d0 ! NEW + Real(kind=8) :: NCmin_p = 0.04d0 ! Phaeocystis Real(kind=8) :: SiCmin = 0.04d0 Real(kind=8) :: k_Fe = 0.04d0 Real(kind=8) :: k_Fe_d = 0.12d0 Real(kind=8) :: k_Fe_c = 0.04 ! NEW + Real(kind=8) :: k_Fe_p = 0.09 ! Phaeocystis (to be tuned) Real(kind=8) :: k_si = 4.d0 Real(kind=8) :: P_cm = 3.0d0 ! [1/day] the rate of C-specific photosynthesis Real(kind=8) :: P_cm_d = 3.5d0 Real(kind=8) :: P_cm_c = 3.3d0 ! NEW - namelist /palimiter_function/ NMinSlope, SiMinSlope, NCmin, NCmin_d, NCmin_c, SiCmin, k_Fe, k_Fe_d, k_Fe_c, k_si, P_cm, P_cm_d, P_cm_c + Real(kind=8) :: P_cm_p = 3.4d0 ! NEW for Phaeocystis ( to be tuned) + namelist /palimiter_function/ NMinSlope, SiMinSlope, NCmin, NCmin_d, NCmin_c, NCmin_p, SiCmin, k_Fe, k_Fe_d, k_Fe_c, k_Fe_p, k_si, P_cm, P_cm_d, P_cm_c, P_cm_p + !!------------------------------------------------------------------------------ !! *** For light calculations *** Real(kind=8) :: k_w = 0.04d0 ! [1/m] Light attenuation coefficient @@ -231,40 +241,47 @@ module recom_config namelist /palight_calculations/ k_w, a_chl !!------------------------------------------------------------------------------ !! *** Photosynthesis *** - Real(kind=8) :: alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] + Real(kind=8) :: alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] Real(kind=8) :: alfa_d = 0.19d0 ! An initial slope of the P-I curve Real(kind=8) :: alfa_c = 0.10d0 ! NEW + Real(kind=8) :: alfa_p = 0.10d0 ! Phaeocystis (to be tuned) Real(kind=8) :: parFrac = 0.43d0 - namelist /paphotosynthesis/ alfa, alfa_d, alfa_c, parFrac + namelist /paphotosynthesis/ alfa, alfa_d, alfa_c, alfa_p, parFrac !!------------------------------------------------------------------------------ !! *** Assimilation *** Real(kind=8) :: V_cm_fact = 0.7d0 ! scaling factor for temperature dependent maximum of C-specific N-uptake Real(kind=8) :: V_cm_fact_d = 0.7d0 - Real(kind=8) :: V_cm_fact_c = 0.7d0 ! NEW + Real(kind=8) :: V_cm_fact_c = 0.7d0 ! NEW + Real(kind=8) :: V_cm_fact_p = 0.7d0 ! Phaeocystis Real(kind=8) :: NMaxSlope = 1000.d0 ! Max slope for limiting function Real(kind=8) :: SiMaxSlope = 1000.d0 Real(kind=8) :: NCmax = 0.2d0 ! [mmol N/mmol C] Maximum cell quota of nitrogen (N:C) Real(kind=8) :: NCmax_d = 0.2d0 Real(kind=8) :: NCmax_c = 0.15d0 ! NEW + Real(kind=8) :: NCmax_p = 0.1d0 ! Phaeocystis (to be tuned) Real(kind=8) :: SiCmax = 0.8d0 Real(kind=8) :: NCuptakeRatio = 0.2d0 ! [mmol N/mmol C] Maximum uptake ratio of N:C Real(kind=8) :: NCUptakeRatio_d = 0.2d0 Real(kind=8) :: NCUptakeRatio_c = 0.2d0 ! NEW + Real(kind=8) :: NCUptakeRatio_p = 0.2d0 ! Phaeocystis Real(kind=8) :: SiCUptakeRatio = 0.2d0 Real(kind=8) :: k_din = 0.55d0 ! [mmol N/m3] Half-saturation constant for nitrate uptake Real(kind=8) :: k_din_d = 1.0d0 Real(kind=8) :: k_din_c = 0.55d0 ! NEW + Real(kind=8) :: k_din_p = 0.55d0 ! Phaeocystis (to be tuned) Real(kind=8) :: Chl2N_max = 3.15d0 ! [mg CHL/mmol N] Maximum CHL a : N ratio = 0.3 gCHL gN^-1 Real(kind=8) :: Chl2N_max_d = 4.2d0 Real(kind=8) :: Chl2N_max_c = 3.5d0 ! NEW + Real(kind=8) :: Chl2N_max_p = 3.5d0 ! Phaeocystis (to be tuned (?)) Real(kind=8) :: res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant Real(kind=8) :: res_phy_d = 0.01d0 Real(kind=8) :: res_phy_c = 0.0075d0 ! NEW + Real(kind=8) :: res_phy_p = 0.008d0 ! Phaeocystis (to be tuned (?)) Real(kind=8) :: biosynth = 2.33d0 ! [mmol C/mmol N] Cost of biosynthesis Real(kind=8) :: biosynthSi = 0.d0 - namelist /paassimilation/ V_cm_fact, V_cm_fact_d, V_cm_fact_c, NMaxSlope, SiMaxSlope, NCmax, NCmax_d, NCmax_c, SiCmax, & - NCuptakeRatio, NCUptakeRatio_d, NCUptakeRatio_c, SiCUptakeRatio, k_din, k_din_d, k_din_c, & - Chl2N_max, Chl2N_max_d, Chl2N_max_c, res_phy, res_phy_d, res_phy_c, biosynth, biosynthSi + namelist /paassimilation/ V_cm_fact, V_cm_fact_d, V_cm_fact_c, V_cm_fact_p, NMaxSlope, SiMaxSlope, NCmax, NCmax_d, NCmax_c, NCmax_p, SiCmax, & + NCuptakeRatio, NCUptakeRatio_d, NCUptakeRatio_c, NCUptakeRatio_p, SiCUptakeRatio, k_din, k_din_d, k_din_c, k_din_p, & + Chl2N_max, Chl2N_max_d, Chl2N_max_c, Chl2N_max_p, res_phy, res_phy_d, res_phy_c, res_phy_p, biosynth, biosynthSi !!------------------------------------------------------------------------------ !! *** Iron chemistry *** Real(kind=8) :: totalligand = 1.d0 ! [mumol/m3] order 1. Total free ligand @@ -283,26 +300,30 @@ module recom_config Real(kind=8) :: sPhyNsq = 0.d0 Real(kind=8) :: pzCocco = 0.5d0 ! NEW (value is just a guess) Real(kind=8) :: sCoccoNsq = 0.d0 ! NEW + Real(kind=8) :: pzPhaeo = 1.0d0 ! Phaeocystis (to be tuned) + Real(kind=8) :: sPhaeoNsq = 0.d0 ! Phaeocystis Real(kind=8) :: pzMicZoo = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference Real(kind=8) :: sMicZooNsq = 0.d0 ! NEW 3Zoo real(kind=8) :: tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. - namelist /pazooplankton/ graz_max, epsilonr, res_het, Redfield, loss_het, pzDia, sDiaNsq, pzPhy, sPhyNsq, pzCocco, sCoccoNsq, pzMicZoo, sMicZooNsq, tiny_het + namelist /pazooplankton/ graz_max, epsilonr, res_het, Redfield, loss_het, pzDia, sDiaNsq, pzPhy, sPhyNsq, pzCocco, sCoccoNsq, pzPhaeo, sPhaeoNsq, pzMicZoo, sMicZooNsq, tiny_het !!------------------------------------------------------------------------------- -!! *** SecondZooplankton *** +!! *** SecondZooplankton (Macrozooplankton) *** Real(kind=8) :: graz_max2 = 0.1d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter Real(kind=8) :: epsilon2 = 0.0144d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss Real(kind=8) :: res_zoo2 = 0.0107d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) Real(kind=8) :: loss_zoo2 = 0.003d0 ! [1/day] Temperature dependent N degradation of extracellular organic N - Real(kind=8) :: fecal_rate_n = 0.13d0 + Real(kind=8) :: fecal_rate_n = 0.13d0 Real(kind=8) :: fecal_rate_c = 0.295d0 Real(kind=8) :: fecal_rate_n_mes = 0.25d0 ! NEW 3Zoo - Real(kind=8) :: fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo + Real(kind=8) :: fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo Real(kind=8) :: pzDia2 = 1.d0 ! Maximum diatom preference Real(kind=8) :: sDiaNsq2 = 0.d0 Real(kind=8) :: pzPhy2 = 0.5d0 ! Maximum diatom preference Real(kind=8) :: sPhyNsq2 = 0.d0 Real(kind=8) :: pzCocco2 = 0.2d0 ! NEW (value is just a guess) Real(kind=8) :: sCoccoNsq2 = 0.d0 ! NEW + Real(kind=8) :: pzPhaeo2 = 0.5d0 ! Phaeocystis (to be tuned) + Real(kind=8) :: sPhaeoNsq2 = 0.d0 ! Phaeocystis Real(kind=8) :: pzHet = 0.8d0 ! Maximum diatom preference Real(kind=8) :: sHetNsq = 0.d0 Real(kind=8) :: pzMicZoo2 = 0.8d0 ! NEW Zoo3 Maximum microzooplankton preference @@ -313,7 +334,7 @@ module recom_config Real(kind=8) :: t4_zoo2 = 274.15d0 ! Krill temp. function constant3 namelist /pasecondzooplankton/ graz_max2, epsilon2, res_zoo2, & loss_zoo2, fecal_rate_n, fecal_rate_c, fecal_rate_n_mes, fecal_rate_c_mes, & ! NEW 3Zoo - pzDia2, sDiaNsq2, pzPhy2, sPhyNsq2, pzCocco2, sCoccoNsq2, pzHet, sHetNsq, & + pzDia2, sDiaNsq2, pzPhy2, sPhyNsq2, pzCocco2, sCoccoNsq2, pzPhaeo2, sPhaeoNsq2, pzHet, sHetNsq, & pzMicZoo2, sMicZooNsq2, & t1_zoo2, t2_zoo2, t3_zoo2, t4_zoo2 !------------------------------------------------------------------------------- @@ -328,7 +349,9 @@ module recom_config Real(kind=8) :: sPhyNsq3 = 0.d0 ! NEW 3Zoo Real(kind=8) :: pzCocco3 = 0.d0 ! NEW 3Zoo Maximum coccolithophore preference ! ATTENTION: This value needs to be tuned; I start with zero preference! Real(kind=8) :: sCoccoNsq3 = 0.d0 ! NEW 3Zoo - namelist /pathirdzooplankton/ graz_max3, epsilon3, loss_miczoo, res_miczoo, pzDia3, sDiaNsq3, pzPhy3, sPhyNsq3, pzCocco3, sCoccoNsq3 + Real(kind=8) :: pzPhaeo3 = 1.0d0 ! Phaeocystis 3Zoo Maximum phaeocystis preference (to be tuned (?)) + Real(kind=8) :: sPhaeoNsq3 = 0.d0 ! Phaeocystis 3Zoo + namelist /pathirdzooplankton/ graz_max3, epsilon3, loss_miczoo, res_miczoo, pzDia3, sDiaNsq3, pzPhy3, sPhyNsq3, pzCocco3, sCoccoNsq3, pzPhaeo3, sPhaeoNsq3 !------------------------------------------------------------------------------- !! *** Detritus Grazing Params *** @@ -359,20 +382,23 @@ module recom_config !! *** Phytoplankton N *** Real(kind=8) :: lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds Real(kind=8) :: lossN_d = 0.05d0 - Real(kind=8) :: lossN_c = 0.05d0 - namelist /paphytoplankton_N/ lossN, lossN_d, lossN_c + Real(kind=8) :: lossN_c = 0.05d0 + Real(kind=8) :: lossN_p = 0.05d0 ! Phaeocystis + namelist /paphytoplankton_N/ lossN, lossN_d, lossN_c, lossN_p !!------------------------------------------------------------------------------ !! *** Phytoplankton C *** Real(kind=8) :: lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon Real(kind=8) :: lossC_d = 0.10d0 - Real(kind=8) :: lossC_c = 0.10d0 - namelist /paphytoplankton_C/ lossC, lossC_d, lossC_c + Real(kind=8) :: lossC_c = 0.10d0 + Real(kind=8) :: lossC_p = 0.10d0 ! Phaeocystis + namelist /paphytoplankton_C/ lossC, lossC_d, lossC_c, lossC_p !!------------------------------------------------------------------------------ !! *** Phytoplankton ChlA *** Real(8) :: deg_Chl = 0.25d0 ! [1/day] Real(kind=8) :: deg_Chl_d = 0.25d0 Real(kind=8) :: deg_Chl_c = 0.20d0 ! (value is just a guess) - namelist /paphytoplankton_ChlA/ deg_Chl, deg_Chl_d, deg_Chl_c + Real(kind=8) :: deg_Chl_p = 0.25d0 ! Phaeocystis + namelist /paphytoplankton_ChlA/ deg_Chl, deg_Chl_d, deg_Chl_c, deg_Chl_p !!------------------------------------------------------------------------------ !! *** Detritus N *** Real(kind=8) :: gfin = 0.3d0 ! 3Zoo [] Grazing efficiency (fraction of grazing flux into zooplankton pool) @@ -405,32 +431,36 @@ module recom_config Real(kind=8) :: Cunits = 976.5625 ! Conversion factor between [mol/m3] (model) and [umol/kg] (function): (1000 * 1000) / 1024 Real(kind=8) :: a_co2_phy = 1.162e+00 ! [unitless] - Real(kind=8) :: a_co2_dia = 1.040e+00 ! [unitless] - Real(kind=8) :: a_co2_cocco = 1.109e+00 ! [unitless] - Real(kind=8) :: a_co2_calc = 1.102e+00 ! [unitless] - Real(kind=8) :: b_co2_phy = 4.888e+01 ! [mol/kg] + Real(kind=8) :: a_co2_dia = 1.040e+00 ! [unitless] + Real(kind=8) :: a_co2_cocco = 1.109e+00 ! [unitless] + Real(kind=8) :: a_co2_phaeo = 1.162e+00 ! [unitless] + Real(kind=8) :: a_co2_calc = 1.102e+00 ! [unitless] + Real(kind=8) :: b_co2_phy = 4.888e+01 ! [mol/kg] Real(kind=8) :: b_co2_dia = 2.890e+01 ! [mol/kg] Real(kind=8) :: b_co2_cocco = 3.767e+01 ! [mol/kg] + Real(kind=8) :: b_co2_phaeo = 4.888e+01 ! [mol/kg] Real(kind=8) :: b_co2_calc = 4.238e+01 ! [mol/kg] Real(kind=8) :: c_co2_phy = 2.255e-01 ! [kg/mol] - Real(kind=8) :: c_co2_dia = 8.778e-01 ! [kg/mol] - Real(kind=8) :: c_co2_cocco = 3.912e-01 ! [kg/mol] - Real(kind=8) :: c_co2_calc = 7.079e-01 ! [kg/mol] - Real(kind=8) :: d_co2_phy = 1.023e+07 ! [kg/mol] - Real(kind=8) :: d_co2_dia = 2.640e+06 ! [kg/mol] - Real(kind=8) :: d_co2_cocco = 9.450e+06 ! [kg/mol] - Real(kind=8) :: d_co2_calc = 1.343e+07 ! [kg/mol] - namelist /paco2lim/ Cunits, a_co2_phy, a_co2_dia, a_co2_cocco, a_co2_calc, & - b_co2_phy, b_co2_dia, b_co2_cocco, b_co2_calc, & - c_co2_phy, c_co2_dia, c_co2_cocco, c_co2_calc, & - d_co2_phy, d_co2_dia, d_co2_cocco, d_co2_calc + Real(kind=8) :: c_co2_dia = 8.778e-01 ! [kg/mol] + Real(kind=8) :: c_co2_cocco = 3.912e-01 ! [kg/mol] + Real(kind=8) :: c_co2_phaeo = 2.255e-01 ! [kg/mol] + Real(kind=8) :: c_co2_calc = 7.079e-01 ! [kg/mol] + Real(kind=8) :: d_co2_phy = 1.023e+07 ! [kg/mol] + Real(kind=8) :: d_co2_dia = 2.640e+06 ! [kg/mol] + Real(kind=8) :: d_co2_cocco = 9.450e+06 ! [kg/mol] + Real(kind=8) :: d_co2_phaeo = 1.023e+07 ! [kg/mol] + Real(kind=8) :: d_co2_calc = 1.343e+07 ! [kg/mol] + namelist /paco2lim/ Cunits, a_co2_phy, a_co2_dia, a_co2_cocco, a_co2_phaeo, a_co2_calc, & + b_co2_phy, b_co2_dia, b_co2_cocco, b_co2_phaeo, b_co2_calc, & + c_co2_phy, c_co2_dia, c_co2_cocco, c_co2_phaeo, c_co2_calc, & + d_co2_phy, d_co2_dia, d_co2_cocco, d_co2_phaeo, d_co2_calc !!------------------------------------------------------------------------------ !! *** Iron *** Real(kind=8) :: Fe2N = 0.033d0 ! Fe2C * 6.625 (Fe2C = 0.005d0) Real(kind=8) :: Fe2N_benthos = 0.15d0 ! default was 0.14 Fe2C_benthos (=0.02125=0.68d0/32.d0) * 6.625 - will have to be tuned. [umol/m2/day] Real(kind=8) :: kScavFe = 0.07d0 Real(kind=8) :: dust_sol = 0.02d0 !Dissolution of Dust for bioavaliable - Real(kind=8) :: RiverFeConc = 100d0 ! mean DFe concentration in rivers + Real(kind=8) :: RiverFeConc = 100d0 ! mean DFe concentration in rivers namelist /pairon/ Fe2N, Fe2N_benthos, kScavFe, dust_sol, RiverFeConc !!------------------------------------------------------------------------------ !! *** Calcification *** @@ -477,6 +507,600 @@ module recom_config namelist /paballasting/ rho_POC, rho_PON, rho_CaCO3, rho_opal, rho_ref_part, & rho_ref_water, visc_ref_water, w_ref1, w_ref2, depth_scaling1, & depth_scaling2, max_sinking_velocity + +contains + + ! --------------------------------------------------------------------------- + ! SUBROUTINE: initialize_tracer_indices + ! --------------------------------------------------------------------------- + ! Purpose: Set up tracer indices based on model configuration + ! --------------------------------------------------------------------------- + subroutine initialize_tracer_indices() + implicit none + + if (enable_3zoo2det .and. enable_coccos) then + ! ======================================================================= + ! CASE: 4 phytoplankton + 3 zooplankton + 2 detritus + ! ======================================================================= + ! Phytoplankton: small phyto, diatoms, coccolithophores, phaeocystis + ! Zooplankton: mesozoo, macrozoo, microzoo + ! Detritus: det1, det2 + + icocn = 29 + icocc = 30 + icchl = 31 + iphan = 32 + iphac = 33 + iphachl = 34 + imiczoon = 35 + imiczooc = 36 + +! allocate(recom_cocco_tracer_id(3)) + recom_cocco_tracer_id = (/1029, 1030, 1031/) + +! allocate(recom_phaeo_tracer_id(3)) + recom_phaeo_tracer_id = (/1032, 1033, 1034/) + +! allocate(recom_det2_tracer_id(4)) + recom_det2_tracer_id = (/1025, 1026, 1027, 1028/) + + else if (enable_coccos .and. .not. enable_3zoo2det) then + ! ======================================================================= + ! CASE: 4 phytoplankton + 1 zooplankton + 1 detritus + ! ======================================================================= + ! Phytoplankton: small phyto, diatoms, coccolithophores, phaeocystis + ! Zooplankton: mesozoo only + ! Detritus: det1 only + + icocn = 23 + icocc = 24 + icchl = 25 + iphan = 26 + iphac = 27 + iphachl = 28 + +! allocate(recom_cocco_tracer_id(3)) + recom_cocco_tracer_id = (/1023, 1024, 1025/) + +! allocate(recom_phaeo_tracer_id(3)) + recom_phaeo_tracer_id = (/1026, 1027, 1028/) + + else if (enable_3zoo2det .and. .not. enable_coccos) then + ! ======================================================================= + ! CASE: 2 phytoplankton + 3 zooplankton + 2 detritus + ! ======================================================================= + ! Phytoplankton: small phyto, diatoms only + ! Zooplankton: mesozoo, macrozoo, microzoo + ! Detritus: det1, det2 + + imiczoon = 29 + imiczooc = 30 + +! allocate(recom_det2_tracer_id(4)) + recom_det2_tracer_id = (/1025, 1026, 1027, 1028/) + else + ! ======================================================================= + ! CASE: 2 phytoplankton + 1 zooplankton + 1 detritus (BASE CONFIGURATION) + ! ======================================================================= + ! Phytoplankton: small phyto, diatoms only + ! Zooplankton: mesozoo only + ! Detritus: det1 only + ! (All indices already set to default values) + endif + end subroutine initialize_tracer_indices + +! ============================================================================== +! SUBROUTINE: validate_recom_tracers +! ============================================================================== +! Purpose: Validate consistency between namelist tracer configuration and +! biogeochemical model setup (enable_3zoo2det, enable_coccos) +! ============================================================================== +subroutine validate_recom_tracers(num_tracers, mype) + implicit none + + ! Arguments + integer, intent(in) :: num_tracers ! Total number of tracers from namelist + integer, intent(in) :: mype ! MPI rank + + ! Local variables + integer :: expected_bgc_num + integer :: actual_bgc_num + integer :: expected_total_tracers + integer :: num_physical_tracers + logical :: config_error + character(len=200) :: error_msg + + ! For tracer ID validation + integer :: i, tracer_id + integer, dimension(:), allocatable :: expected_tracer_ids + logical, dimension(:), allocatable :: tracer_found + integer :: num_expected_tracers + logical :: id_error + + ! Physical tracers (temperature, salinity, etc.) - typically first 2 + num_physical_tracers = 2 + + ! Calculate actual BGC tracer count from namelist + actual_bgc_num = num_tracers - num_physical_tracers + + ! =========================================================================== + ! Determine expected BGC tracer count based on configuration + ! =========================================================================== + config_error = .false. + + if (enable_3zoo2det .and. enable_coccos) then + ! --------------------------------------------------------------------------- + ! Configuration 4: Full model (4 phyto + 3 zoo + 2 detritus) + ! --------------------------------------------------------------------------- + ! Base: 22 tracers (1001-1022) + ! Additional 3zoo2det: 4 tracers for det2 (1025-1028) + ! Additional coccos: 6 tracers for coccos (1029-1031) + ! Additional phaeocystis: 3 tracers (1032-1034) + ! Additional microzoo: 2 tracers (1035-1036) + ! Total: 22 + 4 + 6 + 3 + 2 = 36 (actually 22 + 14 = 36) + expected_bgc_num = 36 + + else if (enable_coccos .and. .not. enable_3zoo2det) then + ! --------------------------------------------------------------------------- + ! Configuration 3: Coccos only (4 phyto + 1 zoo + 1 detritus) + ! --------------------------------------------------------------------------- + ! Base: 22 tracers (1001-1022) + ! Additional coccos: 3 tracers (1023-1025) + ! Additional phaeocystis: 3 tracers (1026-1028) + ! Total: 22 + 6 = 28 + expected_bgc_num = 28 + + else if (enable_3zoo2det .and. .not. enable_coccos) then + ! --------------------------------------------------------------------------- + ! Configuration 2: 3Zoo2Det only (2 phyto + 3 zoo + 2 detritus) + ! --------------------------------------------------------------------------- + ! Base: 22 tracers (1001-1022) + ! Additional zoo2: 2 tracers (1023-1024) + ! Additional det2: 4 tracers (1025-1028) + ! Additional microzoo: 2 tracers (1029-1030) + ! Total: 22 + 8 = 30 + expected_bgc_num = 30 + + else + ! --------------------------------------------------------------------------- + ! Configuration 1: Base model (2 phyto + 1 zoo + 1 detritus) + ! --------------------------------------------------------------------------- + ! Base: 22 tracers (1001-1022) + expected_bgc_num = 22 + + end if + + expected_total_tracers = num_physical_tracers + expected_bgc_num + + ! =========================================================================== + ! Build expected tracer ID list for current configuration + ! =========================================================================== + + ! Determine total expected tracers + num_expected_tracers = expected_total_tracers + allocate(expected_tracer_ids(num_expected_tracers)) + allocate(tracer_found(num_expected_tracers)) + tracer_found = .false. + + ! Physical tracers (always present) + expected_tracer_ids(1) = 1 ! Temperature + expected_tracer_ids(2) = 2 ! Salinity + + ! Base BGC tracers (always present for all configurations) + do i = 1, 22 + expected_tracer_ids(num_physical_tracers + i) = 1000 + i + end do + + ! Configuration-specific tracers + if (enable_3zoo2det .and. enable_coccos) then + ! Full model: 1001-1022 (base) + 1023-1024 (zoo2) + 1025-1028 (det2) + 1029-1036 (coccos+phaeo+zoo3) + expected_tracer_ids(25) = 1023 ! Zoo2N + expected_tracer_ids(26) = 1024 ! Zoo2C + expected_tracer_ids(27) = 1025 ! DetZ2N + expected_tracer_ids(28) = 1026 ! DetZ2C + expected_tracer_ids(29) = 1027 ! DetZ2Si + expected_tracer_ids(30) = 1028 ! DetZ2Calc + expected_tracer_ids(31) = 1029 ! CoccoN + expected_tracer_ids(32) = 1030 ! CoccoC + expected_tracer_ids(33) = 1031 ! CoccoChl + expected_tracer_ids(34) = 1032 ! PhaeoN + expected_tracer_ids(35) = 1033 ! PhaeoC + expected_tracer_ids(36) = 1034 ! PhaeoChl + expected_tracer_ids(37) = 1035 ! Zoo3N + expected_tracer_ids(38) = 1036 ! Zoo3C + + else if (enable_coccos .and. .not. enable_3zoo2det) then + ! Coccos only: 1001-1022 (base) + 1023-1028 (coccos+phaeo) + expected_tracer_ids(25) = 1023 ! CoccoN + expected_tracer_ids(26) = 1024 ! CoccoC + expected_tracer_ids(27) = 1025 ! CoccoChl + expected_tracer_ids(28) = 1026 ! PhaeoN + expected_tracer_ids(29) = 1027 ! PhaeoC + expected_tracer_ids(30) = 1028 ! PhaeoChl + + else if (enable_3zoo2det .and. .not. enable_coccos) then + ! 3Zoo2Det only: 1001-1022 (base) + 1023-1030 (zoo2+det2+zoo3) + expected_tracer_ids(25) = 1023 ! Zoo2N + expected_tracer_ids(26) = 1024 ! Zoo2C + expected_tracer_ids(27) = 1025 ! DetZ2N + expected_tracer_ids(28) = 1026 ! DetZ2C + expected_tracer_ids(29) = 1027 ! DetZ2Si + expected_tracer_ids(30) = 1028 ! DetZ2Calc + expected_tracer_ids(31) = 1029 ! Zoo3N + expected_tracer_ids(32) = 1030 ! Zoo3C + end if + ! else: base configuration only needs tracers 1, 2, 1001-1022 + + ! =========================================================================== + ! Perform validation checks + ! =========================================================================== + + if (mype == 0) then + write(*,*) '' + write(*,*) '==========================================================================' + write(*,*) 'REcoM TRACER CONFIGURATION VALIDATION' + write(*,*) '==========================================================================' + write(*,*) 'Model configuration:' + write(*,*) ' enable_3zoo2det = ', enable_3zoo2det + write(*,*) ' enable_coccos = ', enable_coccos + write(*,*) '' + write(*,*) 'Tracer counts:' + write(*,*) ' Physical tracers (T, S, ...) = ', num_physical_tracers + write(*,*) ' Expected BGC tracers = ', expected_bgc_num + write(*,*) ' Expected TOTAL tracers = ', expected_total_tracers + write(*,*) ' Actual tracers from namelist = ', num_tracers + write(*,*) ' Actual BGC tracers from namelist = ', actual_bgc_num + write(*,*) '' + end if + + ! Check for inconsistencies + if (actual_bgc_num /= expected_bgc_num) then + config_error = .true. + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'ERROR: TRACER COUNT MISMATCH!' + write(*,*) '==========================================================================' + write(*,*) 'The number of BGC tracers in the namelist does not match' + write(*,*) 'the expected count for the current configuration.' + write(*,*) '' + write(*,*) ' Expected BGC tracers: ', expected_bgc_num + write(*,*) ' Actual BGC tracers: ', actual_bgc_num + write(*,*) ' Difference: ', actual_bgc_num - expected_bgc_num + write(*,*) '' + write(*,*) 'Required tracer IDs for current configuration:' + write(*,*) ' Base tracers (always): 1001-1022 (22 tracers)' + + if (enable_3zoo2det .and. .not. enable_coccos) then + write(*,*) ' 3Zoo2Det extension: 1023-1030 (8 tracers)' + write(*,*) ' - Zoo2N, Zoo2C: 1023-1024' + write(*,*) ' - DetZ2 pool: 1025-1028' + write(*,*) ' - MicZooN, MicZooC: 1029-1030' + 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' + else if (enable_3zoo2det .and. enable_coccos) then + write(*,*) ' - Zoo2N, Zoo2C: 1023-1024' + write(*,*) ' 3Zoo2Det extension: 1025-1028 (4 tracers for det2)' + write(*,*) ' Coccos extension: 1029-1034 (6 tracers)' + write(*,*) ' - CoccoN, C, Chl: 1029-1031' + write(*,*) ' - PhaeoN, C, Chl: 1032-1034' + write(*,*) ' MicroZoo extension: 1035-1036 (2 tracers)' + 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(*,*) ' 3. Add/remove tracers to match the expected configuration' + write(*,*) '==========================================================================' + write(*,*) '' + end if + else + ! Validation passed + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'VALIDATION PASSED: Tracer configuration is consistent!' + write(*,*) '==========================================================================' + write(*,*) '' + end if + end if + + ! =========================================================================== + ! Additional sanity check: verify bgc_num variable matches + ! =========================================================================== + if (bgc_num /= expected_bgc_num) then + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'WARNING: bgc_num variable inconsistency!' + write(*,*) '==========================================================================' + write(*,*) 'The bgc_num parameter does not match the expected value.' + write(*,*) ' Current bgc_num value: ', bgc_num + write(*,*) ' Expected value: ', expected_bgc_num + write(*,*) '' + write(*,*) 'This may indicate that bgc_num was not updated after changing' + write(*,*) 'enable_3zoo2det or enable_coccos flags.' + write(*,*) '==========================================================================' + write(*,*) '' + end if + config_error = .true. + end if + + ! =========================================================================== + ! Validate tracer IDs: Check for correct IDs and detect clashes + ! =========================================================================== + id_error = .false. + + ! This check requires access to the actual tracer IDs from the namelist + ! We'll validate against the expected list + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'VALIDATING TRACER IDs' + write(*,*) '==========================================================================' + write(*,*) 'Expected tracer ID sequence:' + write(*,*) '' + + ! Display expected IDs in a readable format + write(*,*) 'Physical tracers:' + write(*,*) ' ', expected_tracer_ids(1:num_physical_tracers) + write(*,*) '' + write(*,*) 'Base BGC tracers (1001-1022):' + write(*,*) ' ', expected_tracer_ids(3:24) + write(*,*) '' + + if (expected_bgc_num > 22) then + write(*,*) 'Extended configuration tracers:' + write(*,*) ' ', expected_tracer_ids(25:num_expected_tracers) + write(*,*) '' + end if + + write(*,*) 'CRITICAL: The tracer IDs in your namelist MUST match this sequence' + write(*,*) ' exactly, in the same order!' + write(*,*) '' + write(*,*) 'Common errors to avoid:' + write(*,*) ' - Using wrong tracer ID numbers (e.g., 1023 instead of 1025)' + write(*,*) ' - Tracer ID clashes between configurations' + write(*,*) ' - Incorrect order of tracer IDs in namelist' + write(*,*) ' - Missing or duplicate tracer IDs' + write(*,*) '' + + ! Configuration-specific warnings + if (enable_3zoo2det .and. enable_coccos) then + write(*,*) 'IMPORTANT for FULL MODEL (3zoo2det + coccos):' + ! write(*,*) ' - Tracers 1023-1024 are NOT used (reserved for other configs)' + write(*,*) ' - Zoo2 uses: 1023-1024' + write(*,*) ' - Det2 pool uses: 1025-1028' + write(*,*) ' - Coccos uses: 1029-1031' + write(*,*) ' - Phaeocystis uses: 1032-1034' + write(*,*) ' - Microzooplankton: 1035-1036' + 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(*,*) '' + 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(*,*) '' + 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(*,*) '' + end if + + write(*,*) '==========================================================================' + write(*,*) '' + end if + + ! =========================================================================== + ! Check for tracer ID clashes based on configuration + ! =========================================================================== + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'CHECKING FOR TRACER ID CONFLICTS' + write(*,*) '==========================================================================' + + ! Warn about potential clashes between configurations + if (enable_3zoo2det .and. enable_coccos) then + write(*,*) 'Full model configuration active.' + ! write(*,*) 'Ensure you are NOT using tracer IDs 1023-1024 in your namelist!' + ! write(*,*) 'These are reserved for configurations WITHOUT full model.' + else if (enable_coccos) then + write(*,*) 'Coccos-only configuration active.' + write(*,*) 'Coccos MUST use IDs 1023-1025 (NOT 1029-1031).' + write(*,*) 'Phaeocystis MUST use IDs 1026-1028 (NOT 1032-1034).' + else if (enable_3zoo2det) then + write(*,*) '3Zoo2Det-only configuration active.' + write(*,*) 'Microzoo MUST use IDs 1029-1030 (NOT 1035-1036).' + end if + + write(*,*) '' + ! write(*,*) 'No automated clash detection available without tracer array access.' + write(*,*) 'Please manually verify your namelist tracer_list against the' + write(*,*) 'expected sequence shown above.' + write(*,*) '==========================================================================' + write(*,*) '' + end if + + ! =========================================================================== + ! Stop execution if configuration error detected + ! =========================================================================== + if (config_error) then + if (mype == 0) then + write(*,*) '' + write(*,*) '******************************************************************' + write(*,*) '*** FATAL ERROR: MODEL CONFIGURATION INCONSISTENCY DETECTED ***' + write(*,*) '*** MODEL EXECUTION STOPPED ***' + write(*,*) '******************************************************************' + write(*,*) '' + end if + deallocate(expected_tracer_ids, tracer_found) + call par_ex(0) ! Stop execution (use appropriate stop routine for your model) + stop + end if + + ! Clean up + deallocate(expected_tracer_ids, tracer_found) + +end subroutine validate_recom_tracers + +! ============================================================================== +! SUBROUTINE: validate_tracer_id_sequence +! ============================================================================== +! Purpose: Validate that actual tracer IDs from namelist match expected sequence +! Call this after reading the tracer namelist +! ============================================================================== +subroutine validate_tracer_id_sequence(tracer_ids, num_tracers, mype) + implicit none + + ! Arguments + integer, dimension(:), intent(in) :: tracer_ids ! Actual IDs from namelist + integer, intent(in) :: num_tracers ! Number of tracers + integer, intent(in) :: mype ! MPI rank + + ! Local variables + integer :: i, j + integer, dimension(:), allocatable :: expected_ids + integer :: num_expected + logical :: error_found + logical :: duplicate_found + integer :: num_physical_tracers + + error_found = .false. + duplicate_found = .false. + num_physical_tracers = 2 + + ! Allocate expected IDs array + allocate(expected_ids(num_tracers)) + + ! Build expected ID sequence + expected_ids(1) = 1 + expected_ids(2) = 2 + + do i = 1, 22 + expected_ids(num_physical_tracers + i) = 1000 + i + end do + + if (enable_3zoo2det .and. enable_coccos) then + ! Full model configuration + expected_ids(25:30) = (/1023, 1024, 1025, 1026, 1027, 1028/) + expected_ids(31:36) = (/1029, 1030, 1031, 1032, 1033, 1034/) + expected_ids(37:38) = (/1035, 1036/) + + else if (enable_coccos .and. .not. enable_3zoo2det) then + expected_ids(25:30) = (/1023, 1024, 1025, 1026, 1027, 1028/) + + else if (enable_3zoo2det .and. .not. enable_coccos) then + expected_ids(25:32) = (/1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030/) + end if + + ! =========================================================================== + ! Check 1: Compare actual vs expected tracer IDs + ! =========================================================================== + if (mype == 0) then + write(*,*) '' + write(*,*) '==========================================================================' + write(*,*) 'VALIDATING TRACER ID SEQUENCE FROM NAMELIST' + write(*,*) '==========================================================================' + end if + + do i = 1, num_tracers + if (tracer_ids(i) /= expected_ids(i)) then + error_found = .true. + if (mype == 0) then + write(*,*) 'ERROR at position ', i, ':' + write(*,*) ' Expected tracer ID: ', expected_ids(i) + write(*,*) ' Found tracer ID: ', tracer_ids(i) + write(*,*) '' + end if + end if + end do + + ! =========================================================================== + ! Check 2: Detect duplicate tracer IDs + ! =========================================================================== + do i = 1, num_tracers - 1 + do j = i + 1, num_tracers + if (tracer_ids(i) == tracer_ids(j)) then + duplicate_found = .true. + if (mype == 0) then + write(*,*) 'ERROR: Duplicate tracer ID detected!' + write(*,*) ' Tracer ID ', tracer_ids(i), ' appears at positions ', i, ' and ', j + write(*,*) '' + end if + end if + end do + end do + + ! =========================================================================== + ! Check 3: Detect forbidden tracer IDs for current configuration + ! =========================================================================== + !if (enable_3zoo2det .and. enable_coccos) then + ! Check for forbidden IDs 1023-1024 in full model + !do i = 1, num_tracers + !if (tracer_ids(i) == 1023 .or. tracer_ids(i) == 1024) then + !error_found = .true. + !if (mype == 0) then + !write(*,*) 'ERROR: Forbidden tracer ID in full model configuration!' + !write(*,*) ' Tracer ID ', tracer_ids(i), ' at position ', i + !write(*,*) ' IDs 1023-1024 are NOT used when both flags are enabled' + !write(*,*) '' + !end if + !end if + !end do + !end if + + ! =========================================================================== + ! Report results + ! =========================================================================== + if (error_found .or. duplicate_found) then + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'TRACER ID VALIDATION FAILED!' + write(*,*) '==========================================================================' + write(*,*) '' + write(*,*) 'Expected tracer ID sequence for current configuration:' + write(*,*) expected_ids + write(*,*) '' + write(*,*) 'Actual tracer ID sequence from namelist:' + write(*,*) tracer_ids + write(*,*) '' + write(*,*) 'ACTION REQUIRED:' + write(*,*) ' Correct the tracer IDs in your namelist.config file' + write(*,*) ' Ensure the sequence matches exactly as expected' + write(*,*) '==========================================================================' + write(*,*) '' + write(*,*) '******************************************************************' + write(*,*) '*** FATAL ERROR: INVALID TRACER ID SEQUENCE ***' + write(*,*) '*** MODEL EXECUTION STOPPED ***' + write(*,*) '******************************************************************' + write(*,*) '' + end if + deallocate(expected_ids) + call par_ex(0) + stop + else + if (mype == 0) then + write(*,*) '==========================================================================' + write(*,*) 'TRACER ID VALIDATION PASSED!' + write(*,*) 'All tracer IDs match expected sequence - no clashes detected.' + write(*,*) '==========================================================================' + write(*,*) '' + end if + end if + + deallocate(expected_ids) + +end subroutine validate_tracer_id_sequence + + + end module recom_config ! !=============================================================================== @@ -489,16 +1113,22 @@ Module REcoM_declarations Real(kind=8) :: tiny_N ! Min PhyN Real(kind=8) :: tiny_N_d ! Min DiaN Real(kind=8) :: tiny_N_c ! Min CocN ! NEW + Real(kind=8) :: tiny_N_p ! Min PhaN ! Phaeocystis Real(kind=8) :: tiny_C ! Min PhyC Real(kind=8) :: tiny_C_d ! Min DiaC Real(kind=8) :: tiny_C_c ! Min CocC ! NEW + Real(kind=8) :: tiny_C_p ! Min PhaC ! Phaeocystis Real(kind=8) :: tiny_Si ! Min DiaSi !!------------------------------------------------------------------------------ !! *** Temperature dependence of rates *** Real(kind=8) :: rTref ! [1/K] Reciproque value of reference temp for Arrhenius function Real(kind=8) :: rTloc ! [1/K] Reciproque of local ocean temp - Real(kind=8) :: arrFunc ! [] Temp dependence of rates + Real(kind=8) :: arrFunc ! [] Temp dependence of rates (also for Phaeocystis) Real(kind=8) :: CoccoTFunc ! [] Temp dependence of coccolithophores + Real(kind=8) :: Temp_diatoms ! [] Temp dependence of diatoms + Real(kind=8) :: Temp_phyto ! [] Temp dependence of small phyto + Real(kind=8) :: Temp_cocco ! [] Temp dependence of coccolithophores + Real(kind=8) :: Temp_phaeo ! [] Temp dependence of phaeocystis Real(kind=8) :: arrFuncZoo2 ! [] Temperature function for krill Real(kind=8) :: q10_mic ! 3Zoo Real(kind=8) :: q10_mic_res ! 3Zoo @@ -515,13 +1145,15 @@ Module REcoM_declarations Real(kind=8) :: CoccoCO2 Real(kind=8) :: DiaCO2 Real(kind=8) :: PhyCO2 + Real(kind=8) :: PhaeoCO2 + !!------------------------------------------------------------------------------ !! *** Quotas *** - Real(kind=8) :: quota, quota_dia, quota_cocco ! [mmol N/mmol C] Quota between phytoplankton N and C (NEW changed term) - Real(kind=8) :: recipQuota, recipQuota_dia, recipQuota_cocco ! [mmol C/mmol N] Reciproque of 'quota' (NEW changed term) - Real(kind=8) :: Chl2C, Chl2C_dia, Chl2C_cocco ! [mg ChlA/mmol C] Quota between phytoplankton ChlA and C (NEW changed term) - Real(kind=8) :: Chl2C_plast, Chl2C_plast_dia, CHL2C_plast_cocco ! [mg ChlA/mmol C] needed for photodamage (NEW changed term) - Real(kind=8) :: Chl2N, Chl2N_dia, Chl2N_cocco ! [mg ChlA/mmol N] Quota between phytoplankton ChlA and N (NEW changed term) + Real(kind=8) :: quota, quota_dia, quota_cocco, quota_phaeo ! [mmol N/mmol C] Quota between phytoplankton N and C (NEW changed term) + Real(kind=8) :: recipQuota, recipQuota_dia, recipQuota_cocco, recipQuota_phaeo ! [mmol C/mmol N] Reciproque of 'quota' (NEW changed term) + Real(kind=8) :: Chl2C, Chl2C_dia, Chl2C_cocco, Chl2C_phaeo ! [mg ChlA/mmol C] Quota between phytoplankton ChlA and C (NEW changed term) + Real(kind=8) :: Chl2C_plast, Chl2C_plast_dia, CHL2C_plast_cocco, CHL2C_plast_phaeo ! [mg ChlA/mmol C] needed for photodamage (NEW changed term) + Real(kind=8) :: Chl2N, Chl2N_dia, Chl2N_cocco, Chl2N_phaeo ! [mg ChlA/mmol N] Quota between phytoplankton ChlA and N (NEW changed term) Real(kind=8) :: qSiC Real(kind=8) :: qSiN Real(kind=8) :: recipQZoo ! [mmol C/mmol N] Quota between heterotrophic C and N @@ -535,8 +1167,8 @@ Module REcoM_declarations !! *** For limiter function *** Real(kind=8) :: qlimitFac, qlimitFacTmp ! Factor that regulates photosynthesis Real(kind=8),external :: recom_limiter ! Function calculating qlimitFac - Real(kind=8) :: FeLimitFac ! [Mumol/m3] Half sat constant for iron - Real(kind=8) :: pMax, pMax_dia, pMax_cocco ! [1/day] Maximum rate of C-specific photosynthesis + Real(kind=8) :: FeLimitFac ! [Mumol/m3] Half sat constant for iron + Real(kind=8) :: pMax, pMax_dia, pMax_cocco, pMax_phaeo ! [1/day] Maximum rate of C-specific photosynthesis !!------------------------------------------------------------------------------ !! *** Light *** Real(kind=8) :: kappar ! [1/m] Light attenuation coefficient modified by chla @@ -548,48 +1180,59 @@ Module REcoM_declarations Real(kind=8) :: PARave ! [?] Average light in the control volumes !!------------------------------------------------------------------------------ !! *** Photosynthesis *** - Real(kind=8) :: Cphot, Cphot_dia, Cphot_cocco ! [1/day] C-specific rate of photosynthesis + Real(kind=8) :: Cphot, Cphot_dia, Cphot_cocco, Cphot_phaeo ! [1/day] C-specific rate of photosynthesis !!------------------------------------------------------------------------------ !! *** Assimilation *** Real(kind=8) :: V_cm ! scaling factor for temperature dependent maximum of C-specific N-uptake - Real(kind=8) :: limitFacN,limitFacN_dia,limitFacN_cocco ! Factor that regulates N-assimilation. Calc from function recom_limiter + Real(kind=8) :: limitFacN,limitFacN_dia,limitFacN_cocco, limitFacN_phaeo ! Factor that regulates N-assimilation. Calc from function recom_limiter Real(kind=8) :: limitFacSi - Real(kind=8) :: N_assim, N_assim_dia, N_assim_Cocco ! [mmol N/(mmol C * day)] C specific N utilization rate + Real(kind=8) :: N_assim, N_assim_dia, N_assim_Cocco, N_assim_phaeo ! [mmol N/(mmol C * day)] C specific N utilization rate Real(kind=8) :: Si_assim !!------------------------------------------------------------------------------ !! *** Chlorophyll *** - Real(kind=8) :: ChlSynth, ChlSynth_dia, ChlSynth_cocco ! [mg CHL/ mmol N] CHL a synthesis regulation term - Real(kind=8) :: phyRespRate, phyRespRate_dia, phyRespRate_cocco ! [1/day] Phytoplankton respiration rate - Real(kind=8) :: KOchl, KOchl_dia, KOchl_cocco ! coefficient for damage to the photosynthetic apparatus + Real(kind=8) :: ChlSynth, ChlSynth_dia, ChlSynth_cocco, ChlSynth_phaeo ! [mg CHL/ mmol N] CHL a synthesis regulation term + Real(kind=8) :: phyRespRate, phyRespRate_dia, phyRespRate_cocco, phyRespRate_phaeo ! [1/day] Phytoplankton respiration rate + Real(kind=8) :: KOchl, KOchl_dia, KOchl_cocco, KOchl_phaeo ! coefficient for damage to the photosynthetic apparatus +!!------------------------------------------------------------------------------ +!! *** Vertical only Decomposition of phytoplankton growth components *** + Real(kind=8),allocatable,dimension(:) :: VTTemp_diatoms, VTTemp_phyto, VTTemp_cocco, VTTemp_phaeo ! Vertical 1D temperature effect on phytoplankton photosynthesis + Real(kind=8),allocatable,dimension(:) :: VTPhyCO2, VTDiaCO2, VTCoccoCO2, VTPhaeoCO2 ! CO2 effect + Real(kind=8),allocatable,dimension(:) :: VTqlimitFac_phyto, VTqlimitFac_diatoms, VTqlimitFac_cocco, VTqlimitFac_phaeo ! nutrient effect + Real(kind=8),allocatable,dimension(:) :: VTCphotLigLim_phyto, VTCphotLigLim_diatoms, VTCphotLigLim_cocco, VTCphotLigLim_phaeo ! light limitation + Real(kind=8),allocatable,dimension(:) :: VTCphot_phyto, VTCphot_diatoms, VTCphot_cocco, VTCphot_phaeo + Real(kind=8),allocatable,dimension(:) :: VTSi_assimDia + !!------------------------------------------------------------------------------ !! *** Iron chemistry *** Real(kind=8),external :: iron_chemistry, iron_chemistry_2ligands - Real(kind=8) :: logK1, logK2, Klig1, Klig2 + Real(kind=8) :: logK1, logK2, Klig1, Klig2 !!------------------------------------------------------------------------------ !! *** Zooplankton *** Real(kind=8) :: DiaNsq - Real(kind=8) :: varpzdia, fDiaN ! Part of Diatoms available for food - Real(kind=8) :: PhyNsq - Real(kind=8) :: varpzPhy, fPhyN ! Part of Nano available for food - Real(kind=8) :: CoccoNsq ! NEW - Real(kind=8) :: varpzCocco,fCoccoN ! NEW - Real(kind=8) :: MicZooNsq ! NEW 3Zoo - Real(kind=8) :: varpzMicZoo, fMicZooN ! NEW 3Zoo Part of microzooplankton available for food - Real(kind=8) :: food, foodsq ! [(mmol N)2/m6] - Real(kind=8) :: grazingFlux_phy, grazingFlux_Dia, grazingFlux_Cocco ! [mmol N / (m3 * day)] (NEW changed term) - Real(kind=8) :: grazingFlux_miczoo ! NEW 3Zoo + Real(kind=8) :: varpzdia, fDiaN ! Part of Diatoms available for food + Real(kind=8) :: PhyNsq + Real(kind=8) :: varpzPhy, fPhyN ! Part of Nano available for food + Real(kind=8) :: CoccoNsq + Real(kind=8) :: varpzCocco,fCoccoN + Real(kind=8) :: PhaeoNsq + Real(kind=8) :: varpzPhaeo,fPhaeoN + Real(kind=8) :: MicZooNsq ! NEW 3Zoo + Real(kind=8) :: varpzMicZoo, fMicZooN ! NEW 3Zoo Part of microzooplankton available for food + Real(kind=8) :: food, foodsq ! [(mmol N)2/m6] + Real(kind=8) :: grazingFlux_phy, grazingFlux_Dia, grazingFlux_Cocco, grazingFlux_Phaeo ! [mmol N / (m3 * day)] (NEW changed term) + Real(kind=8) :: grazingFlux_miczoo ! NEW 3Zoo Real(kind=8) :: grazingFlux - Real(kind=8) :: grazEff ! NEW 3Zoo + Real(kind=8) :: grazEff ! NEW 3Zoo Real(kind=8) :: HetRespFlux ! Zooplankton respiration Real(kind=8) :: HetLossFlux ! [(mmol N)2/(m6 * day)] Zooplankton mortality (quadratic loss) !!------------------------------------------------------------------------------ !! *** Second Zooplankton *** - Real(kind=8) :: DiaNsq2, PhyNsq2, CoccoNsq2, HetNsq ! NEW (changed term) - Real(kind=8) :: varpzDia2, fDiaN2, varpzPhy2, fPhyN2, varpzCocco2, fCoccoN2, varpzHet, fHetN ! Part of Diatoms available for food + Real(kind=8) :: DiaNsq2, PhyNsq2, CoccoNsq2, PhaeoNsq2, HetNsq ! NEW (changed term) + Real(kind=8) :: varpzDia2, fDiaN2, varpzPhy2, fPhyN2, varpzCocco2, fCoccoN2, varpzPhaeo2, fPhaeoN2, varpzHet, fHetN ! Part of Diatoms available for food Real(kind=8) :: MicZooNsq2 ! NEW Zoo3 Real(kind=8) :: varpzMicZoo2, fMicZooN2 ! NEW Zoo3 - Real(kind=8) :: food2, foodsq2 ! [(mmol N)2/m6] - Real(kind=8) :: grazingFlux_phy2, grazingFlux_Dia2, grazingFlux_Cocco2, grazingFlux_het2 ! [mmol N / (m3 * day) (NEW changed term) + Real(kind=8) :: food2, foodsq2 ! [(mmol N)2/m6] + Real(kind=8) :: grazingFlux_phy2, grazingFlux_Dia2, grazingFlux_Cocco2, grazingFlux_Phaeo2, grazingFlux_het2 ! [mmol N / (m3 * day) (NEW changed term) Real(kind=8) :: grazingFlux_miczoo2 ! NEW Zoo3 Real(kind=8) :: grazingFlux2 Real(kind=8) :: Zoo2RespFlux ! Zooplankton respiration @@ -615,8 +1258,10 @@ Module REcoM_declarations Real(kind=8) :: varpzPhy3, fPhyN3 ! Part of small phytoplankton available for food Real(kind=8) :: CoccoNsq3 Real(kind=8) :: varpzCocco3, fCoccoN3 ! Part of coccolithophores available for food + Real(kind=8) :: PhaeoNsq3 + Real(kind=8) :: varpzPhaeo3, fPhaeoN3 ! Part of phaeocystis available for food Real(kind=8) :: food3, foodsq3 ! [(mmol N)2/m6] - Real(kind=8) :: grazingFlux_phy3, grazingFlux_Dia3, grazingFlux_Cocco3 ! [mmol N / (m3 * day)] + Real(kind=8) :: grazingFlux_phy3, grazingFlux_Dia3, grazingFlux_Cocco3, grazingFlux_Phaeo3 ! [mmol N / (m3 * day)] Real(kind=8) :: grazingFlux3 Real(kind=8) :: MicZooRespFlux ! Zooplankton respiration Real(kind=8) :: MicZooLossFlux ! [(mmol N)2/(m6 * day)] Zooplankton mortality (quadratic loss) @@ -643,15 +1288,17 @@ Module REcoM_declarations 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 Real(kind=8),allocatable,dimension(:) :: vertNPPn, vertGPPn, vertNNAn, vertChldegn Real(kind=8),allocatable,dimension(:) :: vertNPPd, vertGPPd, vertNNAd, vertChldegd 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(:) :: vertcalcdiss, vertcalcif - Real(kind=8),allocatable,dimension(:) :: vertaggn, vertaggd, vertaggc - Real(kind=8),allocatable,dimension(:) :: vertdocexn, vertdocexd, vertdocexc - Real(kind=8),allocatable,dimension(:) :: vertrespn, vertrespd, vertrespc + 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 !!------------------------------------------------------------------------------ !! *** Benthos *** Real(kind=8),allocatable,dimension(:) :: decayBenthos ! [1/day] Decay rate of detritus in the benthic layer @@ -659,11 +1306,13 @@ Module REcoM_declarations Real(kind=8),allocatable,dimension(:) :: wFluxPhy ! [mmol/(m2 * day)] Flux of N,C, calc and chl through sinking of phytoplankton Real(kind=8),allocatable,dimension(:) :: wFluxDia ! [mmol/(m2 * day)] Flux of N,C, Si and chl through sinking of diatoms Real(kind=8),allocatable,dimension(:) :: wFluxCocco ! NEW [mmol/(m2 * day)] Flux of N,C, calc and chl through sinking of coccos + Real(kind=8),allocatable,dimension(:) :: wFluxPhaeo ! NEW [mmol/(m2 * day)] Flux of N,C, calc and chl through sinking of Phaeocystis Real(kind=8) :: Vben_det ! [m/day] speed of sinking into benthos from water column Real(kind=8) :: Vben_det_seczoo !second zooplankton sinking benthos Real(kind=8) :: Vben_phy Real(kind=8) :: Vben_dia Real(kind=8) :: Vben_coc + Real(kind=8) :: Vben_pha ! Phaeocystis Real(kind=8) :: Ironflux ! [umol Fe/(m2*day)] Flux of Fe from sediment to water !_______________________________________________________________________________ ! Arrays added for RECOM implementation: @@ -678,6 +1327,9 @@ Module REcoM_declarations real(kind=8) :: is_riverinput real(kind=8) :: is_erosioninput +real(kind=8) :: is_3zoo2det +real(kind=8) :: is_coccos + end module REcoM_declarations !=============================================================================== @@ -686,7 +1338,7 @@ end module REcoM_declarations Module REcoM_GloVar implicit none save - + Real(kind=8),allocatable,dimension(:,:) :: Benthos ! 4 types of benthos-tracers with size [4 n2d] Real(kind=8),allocatable,dimension(:,:,:) :: Benthos_tr ! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel @@ -725,7 +1377,8 @@ Module REcoM_GloVar Real(kind=8),allocatable,dimension(:,:) :: GlowFluxDet ! Real(kind=8),allocatable,dimension(:,:) :: GlowFluxPhy ! Real(kind=8),allocatable,dimension(:,:) :: GlowFluxDia ! - Real(kind=8),allocatable,dimension(:,:) :: GlowFluxCocco ! + Real(kind=8),allocatable,dimension(:,:) :: GlowFluxCocco ! + Real(kind=8),allocatable,dimension(:,:) :: GlowFluxPhaeo ! Real(kind=8),allocatable,dimension(:,:) :: diags2D ! Diagnostics in 2D [8 n2d] Real(kind=8),allocatable,dimension(:) :: NPPn @@ -740,6 +1393,10 @@ Module REcoM_GloVar Real(kind=8),allocatable,dimension(:) :: GPPc Real(kind=8),allocatable,dimension(:) :: NNAc Real(kind=8),allocatable,dimension(:) :: Chldegc + Real(kind=8),allocatable,dimension(:) :: NPPp ! Phaeocystis + Real(kind=8),allocatable,dimension(:) :: GPPp + Real(kind=8),allocatable,dimension(:) :: NNAp + Real(kind=8),allocatable,dimension(:) :: Chldegp Real(kind=8),allocatable,dimension(:,:) :: grazmeso_tot Real(kind=8),allocatable,dimension(:,:) :: grazmeso_n Real(kind=8),allocatable,dimension(:,:) :: grazmeso_d @@ -752,15 +1409,40 @@ Module REcoM_GloVar Real(kind=8),allocatable,dimension(:,:) :: aggn Real(kind=8),allocatable,dimension(:,:) :: aggd Real(kind=8),allocatable,dimension(:,:) :: aggc + Real(kind=8),allocatable,dimension(:,:) :: aggp ! Phaeocystis Real(kind=8),allocatable,dimension(:,:) :: docexn Real(kind=8),allocatable,dimension(:,:) :: docexd Real(kind=8),allocatable,dimension(:,:) :: docexc + Real(kind=8),allocatable,dimension(:,:) :: docexp ! Phaeocystis Real(kind=8),allocatable,dimension(:,:) :: respn Real(kind=8),allocatable,dimension(:,:) :: respd Real(kind=8),allocatable,dimension(:,:) :: respc + Real(kind=8),allocatable,dimension(:,:) :: respp ! Phaeocystis Real(kind=8),allocatable,dimension(:,:) :: NPPn3D Real(kind=8),allocatable,dimension(:,:) :: NPPd3D Real(kind=8),allocatable,dimension(:,:) :: NPPc3D + Real(kind=8),allocatable,dimension(:,:) :: NPPp3D ! Phaeocystis + Real(kind=8),allocatable,dimension(:,:) :: TTemp_diatoms ! my new variables to track + Real(kind=8),allocatable,dimension(:,:) :: TTemp_phyto ! new Temperature effect + Real(kind=8),allocatable,dimension(:,:) :: TTemp_cocco ! new + Real(kind=8),allocatable,dimension(:,:) :: TTemp_phaeo ! new + Real(kind=8),allocatable,dimension(:,:) :: TPhyCO2 ! new CO2 effect + Real(kind=8),allocatable,dimension(:,:) :: TDiaCO2 + Real(kind=8),allocatable,dimension(:,:) :: TCoccoCO2 + Real(kind=8),allocatable,dimension(:,:) :: TPhaeoCO2 + Real(kind=8),allocatable,dimension(:,:) :: TqlimitFac_phyto ! new nutrient limitation + Real(kind=8),allocatable,dimension(:,:) :: TqlimitFac_diatoms + Real(kind=8),allocatable,dimension(:,:) :: TqlimitFac_cocco + Real(kind=8),allocatable,dimension(:,:) :: TqlimitFac_phaeo + Real(kind=8),allocatable,dimension(:,:) :: TCphotLigLim_phyto ! new light limitation + Real(kind=8),allocatable,dimension(:,:) :: TCphot_phyto ! new + Real(kind=8),allocatable,dimension(:,:) :: TCphotLigLim_diatoms ! new light limitation + Real(kind=8),allocatable,dimension(:,:) :: TCphot_diatoms + Real(kind=8),allocatable,dimension(:,:) :: TCphotLigLim_cocco ! new light limitation + Real(kind=8),allocatable,dimension(:,:) :: TCphot_cocco + Real(kind=8),allocatable,dimension(:,:) :: TCphotLigLim_phaeo ! new light limitation + Real(kind=8),allocatable,dimension(:,:) :: TCphot_phaeo + Real(kind=8),allocatable,dimension(:,:) :: TSi_assimDia ! tracking the assimilation of Si by Diatoms Real(kind=8),allocatable,dimension(:) :: DenitBen ! Benthic denitrification Field in 2D [n2d 1] @@ -776,7 +1458,7 @@ Module REcoM_GloVar Real(kind=8),allocatable,dimension(:,:) :: lb_flux ! Yearly burial from medusa: [n2d 5] or [n2d 9] with ciso_14 ! atmospheric box model: - real(kind=8),allocatable,dimension(:) :: x_co2atm ! atmospheric CO2 mixing ratio (mole fraction) + Real(kind=8),allocatable,dimension(:) :: x_co2atm ! atmospheric CO2 mixing ratio (mole fraction) Real(kind=8), allocatable,dimension(:) :: Alk_surf ! Surface alkalinity field used for restoring Real(kind=8), allocatable,dimension(:) :: relax_alk @@ -865,7 +1547,7 @@ Module REcoM_locVar Real(kind=8) :: PICPOCN ! (to make calcification dependent on N-limitation) Real(kind=8) :: calc_prod_final ! (added to make the calcification dependent on nutrients (N, Fe), after Krumhardt et al. 2017/2019) Integer :: currentCO2year - + end module REcoM_LocVar !=============================================================================== ! Specific declarations related to carbon isotope simulations diff --git a/src/int_recom/recom_sinking.F90 b/src/int_recom/recom_sinking.F90 index 0971e5bd0..fb1036fdf 100644 --- a/src/int_recom/recom_sinking.F90 +++ b/src/int_recom/recom_sinking.F90 @@ -109,14 +109,14 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) ! Constant vertical sinking for the second detritus class ! ******************************************************* -#if defined(__3Zoo2Det) + if (enable_3zoo2det) then if(tracers%data(tr_num)%ID==1025 .or. & !idetz2n tracers%data(tr_num)%ID==1026 .or. & !idetz2c tracers%data(tr_num)%ID==1027 .or. & !idetz2si tracers%data(tr_num)%ID==1028 ) then !idetz2calc Vben = VDet_zoo2 endif -#endif + endif Vben= Vben/SecondsPerDay ! conversion [m/d] --> [m/s] (vertical velocity, note that it is positive here) @@ -140,7 +140,7 @@ 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 - Benthos(n,1)= Benthos(n,1) + add_benthos_2d(n) ![mmol] + call accum_benthos(n, tr_num, 1, 1, add_benthos_2d(n), area(1,n), dt, .true.) endif !! * Particulate Organic Carbon * @@ -148,27 +148,90 @@ 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 - Benthos(n,2)= Benthos(n,2) + add_benthos_2d(n) + call accum_benthos(n, tr_num, 2, 2, add_benthos_2d(n), area(1,n), dt, .true.) 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 - Benthos(n,3)= Benthos(n,3) + add_benthos_2d(n) + call accum_benthos(n, tr_num, 3, 3, add_benthos_2d(n), area(1,n), dt, .true.) 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 - Benthos(n,4)= Benthos(n,4) + add_benthos_2d(n) + call accum_benthos(n, tr_num, 4, 4, add_benthos_2d(n), area(1,n), dt, .true.) + endif + + ! flux of 13C into the sediment + if (ciso) then + if( tracers%data(tr_num)%ID==1305 .or. & !iphyc_13 + tracers%data(tr_num)%ID==1308 .or. & !idetc_13 + tracers%data(tr_num)%ID==1314 ) then !idiac_14 + call accum_benthos(n, tr_num, 0, 5, add_benthos_2d(n), area(1,n), dt, .false.) + 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.) + endif + + endif + + ! flux of 14C into the sediment + if (ciso .and. ciso_organic_14) then + if( tracers%data(tr_num)%ID==1405 .or. & !iphyc_13 + tracers%data(tr_num)%ID==1408 .or. & !idetc_13 + tracers%data(tr_num)%ID==1414 ) then !idiac_14 + call accum_benthos(n, tr_num, 0, 7, add_benthos_2d(n), area(1,n), dt, .false.) + 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.) + endif + endif + end do + + if(use_MEDUSA) then + do n=1, bottflx_num +! SinkFlx(:,n) = Sinkflx(:,n)/dt +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + call exchange_nod(SinkFlx_tr(:,n,tr_num), partit) + end do + end if ! use_MEDUSA + do n=1, benthos_num +! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + call exchange_nod(Benthos_tr(:,n,tr_num), partit) + call exchange_nod(Benthos(:,n), partit) end do +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 ! ! @@ -223,6 +286,43 @@ subroutine diff_ver_recom_expl(tr_num, tracers, partit, mesh) bottom_flux = 0._WP id = tracers%data(tr_num)%ID +#if defined(__recom) +if (use_MEDUSA .and. (sedflx_num .ne. 0)) then + !CV update: the calculation later has been changed by Ozgur in such + !a way that now the variable bottom_flux is in (mol/time) units, + !rather than a flux in (mol/time/area). I therefore multiply the + !Medusa fluxes by the area to get the same unit. + + SELECT CASE (id) + CASE (1001) + bottom_flux = GloSed(:,1) * area(1,:) ! DIN + CASE (1002) + bottom_flux = GloSed(:,2) * area(1,:) ! DIC + CASE (1003) + bottom_flux = GloSed(:,3) * area(1,:) ! Alk + CASE (1018) + bottom_flux = GloSed(:,4) * area(1,:) ! Si + CASE (1019) + bottom_flux = GloSed(:,1) * Fe2N_benthos * area(1,:) + CASE (1022) + bottom_flux = GloSed(:,5) * area(1,:) ! Oxy + CASE (1302) + if (ciso) then + bottom_flux = GloSed(:,6) * area(1,:) ! DIC_13 and Calc: DIC_13 + end if + CASE (1402) + if (ciso) then + bottom_flux = GloSed(:,7) * area(1,:) ! DIC_14 and Calc: DIC_14 + end if + CASE DEFAULT + if (partit%mype==0) then + write(*,*) 'check specified in boundary conditions' + write(*,*) 'the model will stop!' + end if + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + END SELECT +else SELECT CASE (id) CASE (1001) bottom_flux = GlodecayBenthos(:,1) !*** DIN [mmolN/m^2/s] *** @@ -236,6 +336,14 @@ subroutine diff_ver_recom_expl(tr_num, tracers, partit, mesh) bottom_flux = GlodecayBenthos(:,1) * Fe2N_benthos !*** DFe *** CASE (1022) bottom_flux = -GlodecayBenthos(:,2) * redO2C !*** O2 *** + CASE (1302) + if (ciso) then + bottom_flux = GlodecayBenthos(:,5) + GlodecayBenthos(:,6) !*** DIC_13 and Calc: DIC_13 *** + end if + CASE (1402) + if (ciso) then + bottom_flux = GlodecayBenthos(:,7) + GlodecayBenthos(:,8) !*** DIC_14 and Calc: DIC_14 *** + end if CASE DEFAULT if (partit%mype==0) then write(*,*) 'check specified in boundary conditions' @@ -244,6 +352,8 @@ subroutine diff_ver_recom_expl(tr_num, tracers, partit, mesh) call par_ex(partit%MPI_COMM_FESOM, partit%mype) stop END SELECT +endif ! (use_MEDUSA .and. (sedflux_num .gt. 0)) +#endif do n=1, myDim_nod2D @@ -309,7 +419,7 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) real(kind=8) :: Rjp,Rj,Rjm real(kind=8) :: cfl, d0, d1, thetaP, thetaM, psiP, psiM - real(kind=8) :: onesixth = 1.d0/6.d0 + real(kind=8) :: onesixth = 1.d0/6.d0 real(kind=8) :: dt_sink, c1, c2 real(kind=8) :: Vsink, tv real(kind=8),dimension(mesh%nl) :: Wvel_flux @@ -334,54 +444,65 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) Vsink=0.0_WP - if (tracers%data(tr_num)%ID ==1007 .or. & !idetn - tracers%data(tr_num)%ID ==1008 .or. & !idetc - tracers%data(tr_num)%ID ==1017 .or. & !idetsi - tracers%data(tr_num)%ID ==1021 ) then !idetcal +!< Assign sinking velocities based on tracer ID +!< Groups tracers by functional type and assigns corresponding velocity +! Detritus tracers (nitrogen, carbon, silicate, calcite) + if (tracers%data(tr_num)%ID == 1007 .or. & ! idetn + tracers%data(tr_num)%ID == 1008 .or. & ! idetc + tracers%data(tr_num)%ID == 1017 .or. & ! idetsi + tracers%data(tr_num)%ID == 1021) then ! idetcal Vsink = VDet - elseif(tracers%data(tr_num)%ID ==1004 .or. & !iphyn - tracers%data(tr_num)%ID ==1005 .or. & !iphyc - tracers%data(tr_num)%ID==1006 ) then !ipchl - +! Phytoplankton tracers (nitrogen, carbon, chlorophyll) + elseif (tracers%data(tr_num)%ID == 1004 .or. & ! iphyn + tracers%data(tr_num)%ID == 1005 .or. & ! iphyc + tracers%data(tr_num)%ID == 1006) then ! ipchl Vsink = VPhy - elseif(tracers%data(tr_num)%ID==1013 .or. & !idian - tracers%data(tr_num)%ID==1014 .or. & !idiac - tracers%data(tr_num)%ID==1016 .or. & !idiasi - tracers%data(tr_num)%ID==1015 ) then !idchl - +! Diatom tracers (nitrogen, carbon, silicate, chlorophyll) + elseif (tracers%data(tr_num)%ID == 1013 .or. & ! idian + tracers%data(tr_num)%ID == 1014 .or. & ! idiac + tracers%data(tr_num)%ID == 1016 .or. & ! idiasi + tracers%data(tr_num)%ID == 1015) then ! idchl Vsink = VDia -#if defined (__coccos) - elseif(tracers%data(tr_num)%ID == 1029 .or. & !icocn - tracers%data(tr_num)%ID == 1030 .or. & !icocc - tracers%data(tr_num)%ID == 1031 ) then !icchl - +! Coccolithophore tracers (nitrogen, carbon, chlorophyll) + elseif (enable_coccos .and. & + (tracers%data(tr_num)%ID == 1029 .or. & ! icocn + tracers%data(tr_num)%ID == 1030 .or. & ! icocc + tracers%data(tr_num)%ID == 1031)) then ! icchl Vsink = VCocco -#endif - elseif(tracers%data(tr_num)%ID == 1020) then !iphycal - -#if defined (__coccos) - Vsink = VCocco -#else - Vsink = VPhy -#endif - -#if defined (__3Zoo2Det) - elseif(tracers%data(tr_num)%ID==1025 .or. & !idetz2n - tracers%data(tr_num)%ID==1026 .or. & !idetz2c - tracers%data(tr_num)%ID==1027 .or. & !idetz2si - tracers%data(tr_num)%ID==1028 ) then !idetz2calc - - Vsink = VDet_zoo2 -#endif +! Phaeocystis tracers (nitrogen, carbon, chlorophyll) + elseif (enable_coccos .and. & + (tracers%data(tr_num)%ID == 1032 .or. & ! iphan + tracers%data(tr_num)%ID == 1033 .or. & ! iphac + tracers%data(tr_num)%ID == 1034)) then ! iphachl + Vsink = VPhaeo + + +! Phytoplankton calcite tracer (special case) + elseif (tracers%data(tr_num)%ID == 1020) then ! iphycal + if (enable_coccos) then + Vsink = VCocco + else + Vsink = VPhy end if +! Zooplankton-2 detritus tracers (nitrogen, carbon, silicate, calcite) + elseif (enable_3zoo2det .and. & + (tracers%data(tr_num)%ID == 1025 .or. & ! idetz2n + tracers%data(tr_num)%ID == 1026 .or. & ! idetz2c + tracers%data(tr_num)%ID == 1027 .or. & ! idetz2si + tracers%data(tr_num)%ID == 1028)) then ! idetz2calc + Vsink = VDet_zoo2 + + end if + + !! ---- No sinking if Vsink < 0.1 m/day -if (Vsink .gt. 0.1) then +if (Vsink .gt. 0.1) then do n = 1,myDim_nod2D if (ulevels_nod2D(n)>1) cycle @@ -404,21 +525,28 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) if (allow_var_sinking) then Wvel_flux(nz) = -((Vdet_a * abs(zbar_3d_n(nz,n))/SecondsPerDay) + Vsink/SecondsPerDay) if (use_ballasting) then +! Apply ballasting on slow sinking detritus +!if (any(recom_sinking_tracer_id == tracer_id(tr_num))) then + + if (tracers%data(tr_num)%ID ==1007 .or. & !idetn + tracers%data(tr_num)%ID ==1008 .or. & !idetc + tracers%data(tr_num)%ID ==1017 .or. & !idetsi + tracers%data(tr_num)%ID ==1021 ) then !idetcal Wvel_flux(nz) = w_ref1 * scaling_density1_3D(nz,n) * scaling_visc_3D(nz,n) if (depth_scaling1.gt.0.0) Wvel_flux(nz) = Wvel_flux(nz) + (depth_scaling1 * abs(zbar_3d_n(nz,n))) if (abs(Wvel_flux(nz)) .gt. max_sinking_velocity) Wvel_flux(nz) = max_sinking_velocity - !! * sinking velocity [m d-1] surface --> bottom (negative)* + ! sinking velocity [m d-1] surface --> bottom (negative) Wvel_flux(nz) = -1.0d0 * Wvel_flux(nz)/SecondsPerDay ! now in [m s-1] + end if endif end if -#if defined (__3Zoo2Det) - - !! ---- We assume *constant* sinking for second detritus - if(tracers%data(tr_num)%ID ==1025 .or. & !idetz2n + !! ---- We assume constant sinking for second detritus + if(enable_3zoo2det .and. & + tracers%data(tr_num)%ID ==1025 .or. & !idetz2n tracers%data(tr_num)%ID ==1026 .or. & !idetz2c tracers%data(tr_num)%ID ==1027 .or. & !idetz2si tracers%data(tr_num)%ID ==1028 ) then !idetz2calc @@ -432,12 +560,17 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) if (abs(Wvel_flux(nz)) .gt. max_sinking_velocity) Wvel_flux(nz) = max_sinking_velocity - !! * sinking velocity [m d-1] surface --> bottom (negative) * + ! sinking velocity [m d-1] surface --> bottom (negative) Wvel_flux(nz) = -1.0d0 * Wvel_flux(nz)/SecondsPerDay ! now in [m s-1] end if endif -#endif + + if (tracers%data(tr_num)%ID == 1021) Sinkvel1_tr(nz,n,tr_num) = Wvel_flux(nz) !-1.0d0/SecondsPerDay !idetcal + if (enable_3zoo2det .and. & + tracers%data(tr_num)%ID == 1028) Sinkvel2_tr(nz,n,tr_num) = Wvel_flux(nz) !idetz2calc + + end do dt_sink = dt @@ -477,7 +610,7 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) (1.d0-cfl)/(1.d-20-cfl)*thetaM)) tv= (0.5 * wPs * (trarr(nz,n) + psiM * Rj)+ & - 0.5 * wM * (trarr(max(nzmin,nz-1),n) + psiP * Rj)) + 0.5 * wM * (trarr(max(nzmin,nz-1),n) + psiP * Rj)) vd_flux(nz)= - tv*area(nz,n) end do end if ! 3rd Order DST Sceheme with flux limiting @@ -496,7 +629,7 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) do nz=nzmin+1,nzmax !nlevels_nod2D_minimum-1 ! tv = trarr(nz,n) ! simple scheme - test1 -! tv = 0.5_WP*(trarr(nz-1,n)+trarr(nz,n)) ! consider both layers - test2 +! tv = 0.5_WP*(trarr(nz-1,n)+trarr(nz,n)) ! consider both layers - test2 ! tv = tv*Wvel_flux(nz) ! Wvel_flux is negative tv = - 0.5* & ! - test3 (trarr(nz-1,n)*(Wvel_flux(nz)-abs(Wvel_flux(nz))) + & @@ -525,9 +658,9 @@ subroutine ballast(tr_num, tracers, partit, mesh) use recom_config use recom_glovar - USE o_PARAM - USE o_ARRAYS - USE g_CONFIG + use o_PARAM + use o_ARRAYS + use g_CONFIG use g_forcing_arrays use g_comm_auto use g_clock @@ -588,21 +721,19 @@ subroutine ballast(tr_num, tracers, partit, mesh) scaling_density1_3D(k,row)=1.0 scaling_density2_3D(k,row)=1.0 - if (use_density_scaling) then - if (tracers%data(tr_num)%ID ==1008)then !idetc - if (tracers%data(tr_num)%values(k,row)>0.001) then ! only apply ballasting above a certain biomass (OG Todo: remove) - scaling_density1_3D(k,row) = (rho_particle1(k,row)-rho_seawater(1))/(rho_ref_part-rho_ref_water) - endif - endif -#if defined (__3Zoo2Det) - - if (tracers%data(tr_num)%ID ==1026)then ! idetz2c - if (tracers%data(tr_num)%values(k,row)>0.001) then ! only apply ballasting above a certain biomass (OG Todo: remove) - scaling_density2_3D(k,row) = (rho_particle2(k,row)-rho_seawater(1))/(rho_ref_part-rho_ref_water) - endif - endif -#endif - endif + if (use_density_scaling) then + !if (tracers%data(tr_num)%ID ==1008)then !idetc + !if (tracers%data(tr_num)%values(k,row)>0.001) then ! only apply ballasting above a certain biomass (OG Todo: remove) + scaling_density1_3D(k,row) = (rho_particle1(k,row)-rho_seawater(1))/(rho_ref_part-rho_ref_water) + !endif + !endif + !if (enable_3zoo2det .and. & + !tracers%data(tr_num)%ID ==1026)then ! idetz2c + !if (tracers%data(tr_num)%values(k,row)>0.001) then ! only apply ballasting above a certain biomass (OG Todo: remove) + scaling_density2_3D(k,row) = (rho_particle2(k,row)-rho_seawater(1))/(rho_ref_part-rho_ref_water) + !endif + !endif + endif scaling_visc_3D(k,row)=1.0 @@ -622,9 +753,11 @@ subroutine ballast(tr_num, tracers, partit, mesh) ! in the unlikely (if possible at all...) case that rho_particle(k)-rho_seawater(1)<0, prevent the scaling factor from being negative if (any(scaling_density1_3D(:,:) <= tiny)) scaling_density1_3D(:,:) = 1.0_WP ! tiny = 2.23D-16 -#if defined (__3Zoo2Det) - if (any(scaling_density2_3D(:,:) <= tiny)) scaling_density2_3D(:,:) = 1.0_WP ! tiny = 2.23D-16 -#endif + + if (enable_3zoo2det) then + if (any(scaling_density2_3D(:,:) <= tiny)) scaling_density2_3D(:,:) = 1.0_WP ! tiny = 2.23D-16 + endif + end subroutine ballast !------------------------------------------------------------------------------- ! Subroutine calculate density of particle @@ -696,7 +829,7 @@ subroutine get_particle_density(tracers, partit, mesh) rho_particle1(nzmin:nzmax,row) = rho_CaCO3*a4(nzmin:nzmax,row) + rho_opal*a3(nzmin:nzmax,row) + rho_POC*a1(nzmin:nzmax,row) + rho_PON*a2(nzmin:nzmax,row) end do -#if defined (__3Zoo2Det) + if (enable_3zoo2det) then rho_particle2 = 0.0 b1 = 0.0 b2 = 0.0 @@ -721,7 +854,7 @@ subroutine get_particle_density(tracers, partit, mesh) a4(nzmin:nzmax,row) = b4(nzmin:nzmax,row)/aux(nzmin:nzmax,row) rho_particle2(nzmin:nzmax,row) = rho_CaCO3*a4(nzmin:nzmax,row) + rho_opal*a3(nzmin:nzmax,row) + rho_POC*a1(nzmin:nzmax,row) + rho_PON*a2(nzmin:nzmax,row) end do -#endif + endif end subroutine get_particle_density !------------------------------------------------------------------------------- @@ -734,16 +867,15 @@ end subroutine get_particle_density subroutine get_seawater_viscosity(tr_num, tracers, partit, mesh) + use recom_config + use recom_glovar use MOD_MESH use MOD_PARTIT use MOD_PARSUP use MOD_TRACER - - use recom_config - use recom_glovar - USE o_PARAM - USE o_ARRAYS - USE g_CONFIG + use o_PARAM + use o_ARRAYS + use g_CONFIG use g_forcing_arrays use g_comm_auto use g_clock diff --git a/src/int_recom/recom_sms.F90 b/src/int_recom/recom_sms.F90 index 044d59c1e..67067018a 100644 --- a/src/int_recom/recom_sms.F90 +++ b/src/int_recom/recom_sms.F90 @@ -31,6 +31,7 @@ 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,7 +42,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & integer, intent(in) :: Nn !< Total number of nodes in the vertical real(kind=8),dimension(mesh%nl-1,bgc_num),intent(inout) :: state !< ChlA conc in phytoplankton [mg/m3] - !! should be in instead of inout + !! should be in instead of inout real(kind=8),dimension(mesh%nl-1) :: thick !< [m] Vertical distance between two nodes = Thickness real(kind=8),dimension(mesh%nl-1) :: recipthick !< [1/m] reciprocal of thick @@ -85,261 +86,1413 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & real(kind=8), intent(in) :: Latd(1) ! latitude in degree real(kind=8), intent(in) :: Lond(1) ! longitude in degree real(kind=8) :: mocsy_step_per_day - real(kind=8) :: & - DIN, & !< Dissolved Inorganic Nitrogen [mmol/m3] - DIC, & !< Dissolved Inorganic Carbon [mmol/m3] - Alk, & !< Total Alkalinity [mmol/m3] - PhyN, & !< Intracellular conc of Nitrogen in small phytoplankton [mmol/m3] - PhyC, & !< Intracellular conc of Carbon in small phytoplankton [mmol/m3] - PhyChl, & !< Current intracellular ChlA conc. [mg/m3] - DetN, & !< Conc of N in Detritus [mmol/m3] - DetC, & !< Conc of C in Detritus [mmol/m3] - HetN, & !< Conc of N in heterotrophs [mmol/m3] - HetC, & !< Conc of C in heterotrophs [mmol/m3] - DON, & !< Dissolved organic N in the water [mmol/m3] - EOC, & !< Extracellular Organic C conc [mmol/m3] - DiaN, & - DiaC, & - DiaChl, & - DiaSi, & - DetSi, & -#if defined (__coccos) - CoccoN, & - CoccoC, & - CoccoChl,& -#endif - Si, & - Fe, & - PhyCalc, & - DetCalc, & -#if defined (__3Zoo2Det) - Zoo2N, & - Zoo2C, & - DetZ2N, & - DetZ2C, & - DetZ2Si, & - DetZ2Calc,& - MicZooN, & ! 3Zoo - MicZooC, & ! 3Zoo -#endif - FreeFe, & - O2 + +! --- Biogeochemical state variables --- + real(kind=8) :: & + DIN, & ! [mmol/m3] Dissolved inorganic nitrogen + DIC, & ! [mmol/m3] Dissolved inorganic carbon + Alk, & ! [mmol/m3] Total alkalinity + PhyN, & ! [mmol/m3] Phytoplankton nitrogen (small) + PhyC, & ! [mmol/m3] Phytoplankton carbon (small) + PhyChl, & ! [mg/m3] Phytoplankton chlorophyll + DetN, & ! [mmol/m3] Detrital nitrogen + DetC, & ! [mmol/m3] Detrital carbon + HetN, & ! [mmol/m3] Heterotroph nitrogen + HetC, & ! [mmol/m3] Heterotroph carbon + DON, & ! [mmol/m3] Dissolved organic nitrogen + EOC, & ! [mmol/m3] Extracellular organic carbon + DiaN, & ! [mmol/m3] Diatom nitrogen + DiaC, & ! [mmol/m3] Diatom carbon + DiaChl, & ! [mg/m3] Diatom chlorophyll + DiaSi, & ! [mmol/m3] Diatom silicate + DetSi, & ! [mmol/m3] Detrital silicate + Si, & ! [mmol/m3] Dissolved silicate + Fe, & ! [mmol/m3] Dissolved iron + PhyCalc, & ! [mmol/m3] Phytoplankton calcite + DetCalc, & ! [mmol/m3] Detrital calcite + FreeFe, & ! [mmol/m3] Free iron + O2 ! [mmol/m3] Dissolved oxygen + +! Coccolithophore variables (conditionally used based on namelist) +real(kind=8) :: & + CoccoN, & ! [mmol/m3] Coccolithophore nitrogen + CoccoC, & ! [mmol/m3] Coccolithophore carbon + CoccoChl, & ! [mg/m3] Coccolithophore chlorophyll + PhaeoN, & ! [mmol/m3] Phaeocystis nitrogen + PhaeoC, & ! [mmol/m3] Phaeocystis carbon + PhaeoChl ! [mg/m3] Phaeocystis chlorophyll + +! Extended zooplankton variables (conditionally used based on namelist) +real(kind=8) :: & + Zoo2N, & ! [mmol/m3] Zooplankton type 2 nitrogen + Zoo2C, & ! [mmol/m3] Zooplankton type 2 carbon + DetZ2N, & ! [mmol/m3] Zooplankton detritus nitrogen + DetZ2C, & ! [mmol/m3] Zooplankton detritus carbon + DetZ2Si, & ! [mmol/m3] Zooplankton detritus silicate + DetZ2Calc, & ! [mmol/m3] Zooplankton detritus calcite + MicZooN, & ! [mmol/m3] Microzooplankton nitrogen + MicZooC ! [mmol/m3] Microzooplankton carbon #include "../associate_part_def.h" #include "../associate_mesh_def.h" #include "../associate_part_ass.h" #include "../associate_mesh_ass.h" - sms = zero ! double precision - tiny_N = tiny_chl/chl2N_max !< 0.00001/ 3.15d0 Chl2N_max [mg CHL/mmol N] Maximum CHL a : N ratio = 0.3 gCHL gN^-1 - tiny_N_d = tiny_chl/chl2N_max_d !< 0.00001/ 4.2d0 + ! =========================================================================== + ! VARIABLE DECLARATIONS AND INITIALIZATION + ! =========================================================================== + + !=============================================================================== + ! INITIALIZATION AND SETUP + !=============================================================================== + ! Initializes arrays, calculates minimum thresholds, and sets up time stepping. + ! + ! Variables: + ! sms : Source-minus-sink array for tracer updates [mmol m-3 day-1] + ! zero : Double precision zero (0.0d0) + ! tiny : Very small positive number (numerical stability) + ! tiny_chl : Minimum chlorophyll concentration [mgChl m-3] + ! + ! Source-Minus-Sink (SMS) Array: + ! - Accumulates all biogeochemical fluxes + ! - Dimension: (vertical_levels, number_of_tracers) + ! - Updated throughout biological calculations + ! - Applied to state variables at end of time step + ! - Units: concentration per day [mmol m-3 day-1] + !------------------------------------------------------------------------------- + + ! Initialize source-minus-sink array + ! Sets all biogeochemical fluxes to zero at start of time step + sms = zero + + !=============================================================================== + ! MINIMUM THRESHOLD VALUES + !=============================================================================== + ! Calculates minimum allowable concentrations for all biological state variables. + ! Prevents division by zero and ensures numerical stability. + ! + ! Threshold Calculation Strategy: + ! - Based on physiological maximum ratios + ! - Works backward from minimum chlorophyll + ! - Ensures stoichiometric consistency + ! - Species-specific values + ! + ! Rationale for Minimum Thresholds: + ! - Division by zero prevention in quota calculations + ! - Numerical stability in resource limitation terms + ! - Prevents spurious negative values + ! - Represents detection limits or "ghost populations" + ! + ! Typical Minimum Values: + ! - Chlorophyll: ~0.001-0.01 mgChl m-3 + ! - Nitrogen: ~0.001-0.01 mmolN m-3 + ! - Carbon: ~0.01-0.1 mmolC m-3 + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Small Phytoplankton Thresholds + !------------------------------------------------------------------------------- + ! Variables: + ! tiny_N : Minimum small phyto nitrogen [mmolN m-3] + ! tiny_C : Minimum small phyto carbon [mmolC m-3] + ! tiny_chl : Minimum chlorophyll (set externally) [mgChl m-3] + ! chl2N_max : Maximum Chlorophyll:Nitrogen ratio [mgChl mmolN-1] + ! NCmax : Maximum Nitrogen:Carbon quota [mmolN mmolC-1] + ! + ! Calculation Logic: + ! 1. Start with minimum observable Chl (tiny_chl) + ! 2. Calculate minimum N using maximum Chl:N ratio + ! 3. Calculate minimum C using maximum N:C quota + ! + ! Typical Values: + ! chl2N_max = 3.15 mgChl/mmolN (high Chl per N, low light acclimation) + ! NCmax = 0.2 mmolN/mmolC (luxury N consumption maximum) + + ! Minimum nitrogen based on minimum chlorophyll and maximum Chl:N ratio + tiny_N = tiny_chl / chl2N_max + + ! Minimum carbon based on minimum nitrogen and maximum N:C quota + tiny_C = tiny_N / NCmax + + !------------------------------------------------------------------------------- + ! Diatom Thresholds + !------------------------------------------------------------------------------- + ! Variables: + ! tiny_N_d : Minimum diatom nitrogen [mmolN m-3] + ! tiny_C_d : Minimum diatom carbon [mmolC m-3] + ! tiny_Si : Minimum diatom silicate [mmolSi m-3] + ! chl2N_max_d : Maximum diatom Chl:N ratio [mgChl mmolN-1] + ! NCmax_d : Maximum diatom N:C quota [mmolN mmolC-1] + ! SiCmax : Maximum diatom Si:C quota [mmolSi mmolC-1] + ! + ! Typical Values: + ! chl2N_max_d = 4.2 mgChl/mmolN (diatoms can have higher Chl:N) + ! NCmax_d = 0.2 mmolN/mmolC + ! SiCmax = 0.8 mmolSi/mmolC (heavily silicified frustules) + ! + ! Silicon Requirement: + ! - Unique to diatoms (frustule formation) + ! - Calculated from minimum carbon and maximum Si:C ratio + + ! Minimum diatom nitrogen + tiny_N_d = tiny_chl / chl2N_max_d + + ! Minimum diatom carbon + tiny_C_d = tiny_N_d / NCmax_d + + ! Minimum silicate (based on diatom carbon and maximum Si:C quota) + tiny_Si = tiny_C_d / SiCmax + + !------------------------------------------------------------------------------- + ! Coccolithophore and Phaeocystis Thresholds (Optional) + !------------------------------------------------------------------------------- + ! Only calculated when 4-plankton functional type model is enabled + + if (enable_coccos) then + + ! Coccolithophore thresholds + ! Variables: + ! tiny_N_c : Minimum cocco nitrogen [mmolN m-3] + ! tiny_C_c : Minimum cocco carbon [mmolC m-3] + ! chl2N_max_c : Maximum cocco Chl:N ratio [mgChl mmolN-1] + ! NCmax_c : Maximum cocco N:C quota [mmolN mmolC-1] + + tiny_N_c = tiny_chl / chl2N_max_c + tiny_C_c = tiny_N_c / NCmax_c + + ! Phaeocystis thresholds + ! Variables: + ! tiny_N_p : Minimum Phaeo nitrogen [mmolN m-3] + ! tiny_C_p : Minimum Phaeo carbon [mmolC m-3] + ! chl2N_max_p : Maximum Phaeo Chl:N ratio [mgChl mmolN-1] + ! NCmax_p : Maximum Phaeo N:C quota [mmolN mmolC-1] + + tiny_N_p = tiny_chl / chl2N_max_p + tiny_C_p = tiny_N_p / NCmax_p - tiny_C = tiny_N /NCmax !< NCmax = 0.2d0 [mmol N/mmol C] Maximum cell quota of nitrogen (N:C) - tiny_C_d = tiny_N_d/NCmax_d !< NCmax_d = 0.2d0 + endif - tiny_Si = tiny_C_d/SiCmax !< SiCmax = 0.8d0 + ! Reciprocal of heterotroph respiration rate + ! Used in Redfield-based respiration calculations + ! Variable: + ! recip_res_het : Reciprocal respiration parameter [day] + ! res_het : Heterotroph respiration rate [day-1] + ! Typical value: res_het = 0.01 day-1 (combined respiration + mortality) + recip_res_het = 1.d0 / res_het + + ! Atmospheric pressure conversion for carbonate chemistry + ! MOCSY requires pressure in atmospheres + ! Variables: + ! Patm_depth : Atmospheric pressure [atm] + ! Loc_slp : Local sea level pressure [Pa] + ! Pa2atm : Pascal to atmosphere conversion factor [Pa atm-1] + Patm_depth = Loc_slp / Pa2atm + + !=============================================================================== + ! TIME STEPPING SETUP + !=============================================================================== + ! Converts time steps and sets up sub-cycling for biogeochemistry. + ! + ! Time Step Hierarchy: + ! 1. FESOM physics time step (dt) [seconds] + ! 2. Daily time step (dt_d) [days] + ! 3. REcoM biogeochemistry sub-step (dt_b) [days] + ! + ! Sub-Cycling Rationale: + ! - Physics: Slow (hours to days) + ! - Fast biology: Minutes to hours (phytoplankton growth, grazing) + ! - Allows finer temporal resolution for biological processes + ! - Improves numerical stability for stiff biological systems + ! + ! Variables: + ! rTref : Reciprocal reference temperature [K-1] + ! recom_Tref : Reference temperature (typically 288.15 K = 15degC) [K] + ! dt : FESOM physics time step [seconds] + ! dt_d : Physics time step in days [days] + ! dt_b : REcoM biogeochemistry sub-time step [days] + ! SecondsPerDay : Conversion factor (86400) [s day-1] + ! biostep : Number of biogeochemistry steps per physics step [-] + ! + ! Typical Configuration: + ! dt = 3600 s (1 hour physics step) + ! biostep = 4 (15-minute biogeochemistry steps) + ! dt_b = 0.25/24 = 0.0104 days + !------------------------------------------------------------------------------- + + ! Convert FESOM physics time step to days + dt_d = dt / SecondsPerDay + + ! Calculate biogeochemistry sub-time step + ! Divides physics step into smaller biogeochemical steps + dt_b = dt_d / real(biostep) + + ! Reciprocal reference temperature for Arrhenius calculations + ! Reference: 288.15 K (15degC) used in temperature dependence functions + rTref = real(one) / recom_Tref + + !=============================================================================== + ! MAIN TIME INTEGRATION LOOP + !=============================================================================== + ! Iterates through biogeochemical sub-time steps within each physics time step. + ! Allows fine temporal resolution for fast biological processes. + ! + ! Loop Structure: + ! - Outer loop: Biogeochemistry sub-steps (biostep iterations) + ! - Inner loop: Vertical layers (surface to bottom) + ! + ! Variables: + ! step : Current biogeochemistry sub-step counter [-] + ! biostep : Total number of sub-steps per physics step [-] + ! kdzUpper : Cumulative light attenuation from surface [dimensionless] + ! sms : Source-minus-sink flux array [mmol m-3 day-1] + ! tiny : Threshold for negligible fluxes [mmol m-3 day-1] + ! + ! Numerical Cleanup: + ! - Removes negligible SMS values before applying + ! - Prevents accumulation of numerical noise + ! - Improves computational efficiency + !------------------------------------------------------------------------------- + + do step = one, biostep + + ! Reset upper light attenuation (top of the cell) at start of each sub-step + ! Light attenuation integrates downward through water column + kdzUpper = 0.d0 + + ! Clean up negligible SMS values to prevent numerical issues + ! Sets very small fluxes to exactly zero + if (any(abs(sms(:, :)) <= tiny)) sms(:, :) = zero + + !=========================================================================== + ! VERTICAL LOOP THROUGH WATER COLUMN + !=========================================================================== + ! Processes each vertical layer from surface to bottom. + ! Updates state variables and enforces constraints. + ! + ! Variables: + ! k : Current vertical level index [-] + ! nn : Number of vertical levels in water column [-] + ! + ! Note: Alternative loop configurations commented out: + ! - nzmin, nzmax: Min/max active levels (for dry cells) + ! - myDim_nod2D: Horizontal dimension (for 3D unstructured grids) + !--------------------------------------------------------------------------- + + do k = one, nn + ! Alternative loop structures (commented out): + ! do n = 1, myDim_nod2D + ! Nn = nlevels_nod2D(n) - 1 + ! nzmin = ulevels_nod2D(row) + ! nzmax = nlevels_nod2D(row) + + !----------------------------------------------------------------------- + ! DISSOLVED INORGANIC NUTRIENTS + !----------------------------------------------------------------------- + ! Update nutrient concentrations: state(previous) + SMS(fluxes) + ! Enforce minimum values for numerical stability + ! + ! Variables: + ! DIN : Dissolved inorganic nitrogen (NO3- + NH4+) [mmolN m-3] + ! Si : Dissolved silicate (Si(OH)4) [mmolSi m-3] + ! Fe : Dissolved iron (bioavailable Fe) [mmolFe m-3] + ! + ! max() function ensures non-negative concentrations + !----------------------------------------------------------------------- + + DIN = max(tiny, state(k, idin) + sms(k, idin)) + Si = max(tiny, state(k, isi) + sms(k, isi)) + Fe = max(tiny, state(k, ife) + sms(k, ife)) + + !----------------------------------------------------------------------- + ! CARBON SYSTEM VARIABLES + !----------------------------------------------------------------------- + ! Variables: + ! DIC : Dissolved inorganic carbon (CO2 + HCO3- + CO3--) [mmolC m-3] + ! ALK : Total alkalinity [meq m-3] + ! O2 : Dissolved oxygen [mmolO2 m-3] + !----------------------------------------------------------------------- + + DIC = max(tiny, state(k, idic) + sms(k, idic)) + ALK = max(tiny, state(k, ialk) + sms(k, ialk)) + O2 = max(tiny, state(k, ioxy) + sms(k, ioxy)) + + !----------------------------------------------------------------------- + ! DISSOLVED ORGANIC MATTER + !----------------------------------------------------------------------- + ! Variables: + ! DON : Dissolved organic nitrogen (labile + semi-labile) [mmolN m-3] + ! EOC : Dissolved organic carbon (labile + semi-labile) [mmolC m-3] + ! + ! Note: EOC naming convention (Enhanced Organic Carbon) is historical + !----------------------------------------------------------------------- + + DON = max(tiny, state(k, idon) + sms(k, idon)) + EOC = max(tiny, state(k, idoc) + sms(k, idoc)) + + !----------------------------------------------------------------------- + ! SMALL PHYTOPLANKTON + !----------------------------------------------------------------------- + ! General phytoplankton functional type + ! Variables: + ! PhyN : Small phyto nitrogen [mmolN m-3] + ! PhyC : Small phyto carbon [mmolC m-3] + ! PhyChl : Small phyto chlorophyll [mgChl m-3] + ! PhyCalc : Small phyto calcite (if calcifying) [mmolC m-3] + !----------------------------------------------------------------------- + + PhyN = max(tiny_N, state(k, iphyn) + sms(k, iphyn)) + PhyC = max(tiny_C, state(k, iphyc) + sms(k, iphyc)) + PhyChl = max(tiny_chl, state(k, ipchl) + sms(k, ipchl)) + PhyCalc = max(tiny, state(k, iphycal) + sms(k, iphycal)) + + !----------------------------------------------------------------------- + ! DIATOMS (SILICIFYING PHYTOPLANKTON) + !----------------------------------------------------------------------- + ! Large phytoplankton with silica frustules + ! Variables: + ! DiaN : Diatom nitrogen [mmolN m-3] + ! DiaC : Diatom carbon [mmolC m-3] + ! DiaChl : Diatom chlorophyll [mgChl m-3] + ! DiaSi : Diatom silicate (frustule) [mmolSi m-3] + !----------------------------------------------------------------------- + + DiaN = max(tiny_N_d, state(k, idian) + sms(k, idian)) + DiaC = max(tiny_C_d, state(k, idiac) + sms(k, idiac)) + DiaChl = max(tiny_chl, state(k, idchl) + sms(k, idchl)) + DiaSi = max(tiny_si, state(k, idiasi) + sms(k, idiasi)) + + if (enable_coccos) then + + !------------------------------------------------------------------- + ! COCCOLITHOPHORES (CALCIFYING PHYTOPLANKTON) + !------------------------------------------------------------------- + ! Variables: + ! CoccoN : Cocco nitrogen [mmolN m-3] + ! CoccoC : Cocco carbon [mmolC m-3] + ! CoccoChl : Cocco chlorophyll [mgChl m-3] + !------------------------------------------------------------------- + + CoccoN = max(tiny_N_c, state(k, icocn) + sms(k, icocn)) + CoccoC = max(tiny_C_c, state(k, icocc) + sms(k, icocc)) + CoccoChl = max(tiny_chl, state(k, icchl) + sms(k, icchl)) + + !------------------------------------------------------------------- + ! PHAEOCYSTIS (COLONIAL PHYTOPLANKTON) + !------------------------------------------------------------------- + ! Variables: + ! PhaeoN : Phaeo nitrogen [mmolN m-3] + ! PhaeoC : Phaeo carbon [mmolC m-3] + ! PhaeoChl : Phaeo chlorophyll [mgChl m-3] + !------------------------------------------------------------------- + + PhaeoN = max(tiny_N_p, state(k, iphan) + sms(k, iphan)) + PhaeoC = max(tiny_C_p, state(k, iphac) + sms(k, iphac)) + PhaeoChl = max(tiny_chl, state(k, iphachl) + sms(k, iphachl)) -#if defined (__coccos) - tiny_N_c = tiny_chl/chl2N_max_c - tiny_C_c = tiny_N_c/NCmax_c -#endif + end if - recip_res_het = 1.d0/res_het !< res_het = 0.01d0 [1/day] Respiration by heterotrophs and mortality (loss to detritus) + !----------------------------------------------------------------------- + ! HETEROTROPHS (ZOOPLANKTON) + !----------------------------------------------------------------------- + ! Primary grazers (mesozooplankton) + ! Variables: + ! HetN : Mesozooplankton nitrogen [mmolN m-3] + ! HetC : Mesozooplankton carbon [mmolC m-3] + !----------------------------------------------------------------------- + + HetN = max(tiny, state(k, ihetn) + sms(k, ihetn)) + HetC = max(tiny, state(k, ihetc) + sms(k, ihetc)) + + if (enable_3zoo2det) then + + !------------------------------------------------------------------- + ! ADDITIONAL ZOOPLANKTON (3-ZOOPLANKTON MODEL) + !------------------------------------------------------------------- + ! Macrozooplankton (e.g., krill) + ! Variables: + ! Zoo2N : Macrozooplankton nitrogen [mmolN m-3] + ! Zoo2C : Macrozooplankton carbon [mmolC m-3] + Zoo2N = max(tiny, state(k, izoo2n) + sms(k, izoo2n)) + Zoo2C = max(tiny, state(k, izoo2c) + sms(k, izoo2c)) + + ! Microzooplankton (e.g., ciliates, heterotrophic dinoflagellates) + ! Variables: + ! MicZooN : Microzooplankton nitrogen [mmolN m-3] + ! MicZooC : Microzooplankton carbon [mmolC m-3] + MicZooN = max(tiny, state(k, imiczoon) + sms(k, imiczoon)) + MicZooC = max(tiny, state(k, imiczooc) + sms(k, imiczooc)) - Patm_depth = Loc_slp/Pa2atm ! MOCSY convert from Pa to atm. + end if -!------------------------------------------------------------------------------- -!> REcoM time steps [day] -!------------------------------------------------------------------------------- + !----------------------------------------------------------------------- + ! DETRITUS (DEAD ORGANIC MATTER) + !----------------------------------------------------------------------- + ! Slow-sinking detritus pools + ! Variables: + ! DetN : Detrital nitrogen [mmolN m-3] + ! DetC : Detrital carbon [mmolC m-3] + ! DetSi : Detrital silicate [mmolSi m-3] + ! DetCalc : Detrital calcite [mmolC m-3] + !----------------------------------------------------------------------- + + DetN = max(tiny, state(k, idetn) + sms(k, idetn)) + DetC = max(tiny, state(k, idetc) + sms(k, idetc)) + DetSi = max(tiny, state(k, idetsi) + sms(k, idetsi)) + DetCalc = max(tiny, state(k, idetcal) + sms(k, idetcal)) + + if (enable_3zoo2det) then + + !------------------------------------------------------------------- + ! FAST-SINKING DETRITUS (FECAL PELLETS) + !------------------------------------------------------------------- + ! Large, rapidly sinking particles + ! Variables: + ! DetZ2N : Fast detritus nitrogen [mmolN m-3] + ! DetZ2C : Fast detritus carbon [mmolC m-3] + ! DetZ2Si : Fast detritus silicate [mmolSi m-3] + ! DetZ2Calc : Fast detritus calcite [mmolC m-3] + !------------------------------------------------------------------- + + DetZ2N = max(tiny, state(k, idetz2n) + sms(k, idetz2n)) + DetZ2C = max(tiny, state(k, idetz2c) + sms(k, idetz2c)) + DetZ2Si = max(tiny, state(k, idetz2si) + sms(k, idetz2si)) + DetZ2Calc = max(tiny, state(k, idetz2calc) + sms(k, idetz2calc)) - rTref = real(one)/recom_Tref - - dt_d = dt/SecondsPerDay !< Size of FESOM time step [day] - dt_b = dt_d/real(biostep) !< Size of REcoM time step [day] + end if -!------------------------------------------------------------------------------- -!Main time loop starts - do step = one,biostep + !----------------------------------------------------------------------- + ! FREE IRON INITIALIZATION + !----------------------------------------------------------------------- + ! Free iron will be calculated later from total iron budget + ! Accounts for scavenging, complexation, and biological uptake + !----------------------------------------------------------------------- - kdzUpper = 0.d0 !< Upper light attenuation of top cell is set to zero + FreeFe = zero - if (any(abs(sms(:,:)) <= tiny)) sms(:,:) = zero ! tiny = 2.23D-16 + !======================================================================= + ! PHYSICAL ENVIRONMENT CONSTRAINTS FOR CARBONATE CHEMISTRY + !======================================================================= + ! Validates and constrains physical parameters for MOCSY carbonate + ! system calculations. Ensures inputs are within valid ranges. + ! + ! MOCSY Valid Ranges (Lueker K1/K2 formulation): + ! Temperature: 2-35degC + ! Salinity: 19-43 psu + ! + ! Rationale for Constraints: + ! - Equilibrium constants are empirical fits + ! - Extrapolation outside valid range introduces errors + ! - Numerical instability at extreme values + ! - Ice formation creates low-salinity issues + !----------------------------------------------------------------------- + + !----------------------------------------------------------------------- + ! Temperature Constraints + !----------------------------------------------------------------------- + ! Variables: + ! REcoM_T_depth : Constrained temperature for MOCSY [degC] + ! Temp(k) : Actual temperature at depth k [degC] + ! + ! Constraints: + ! Minimum: 2degC (prevents extrapolation below calibration range) + ! Maximum: 40degC (safety limit, ocean rarely exceeds 35degC) + ! + ! Note: K1/K2 Lueker formulation valid for 2-35degC + !----------------------------------------------------------------------- + + REcoM_T_depth = max(2.d0, Temp(k)) ! Apply minimum + REcoM_T_depth = min(REcoM_T_depth, 40.d0) ! Apply maximum + + !----------------------------------------------------------------------- + ! Salinity Constraints + !----------------------------------------------------------------------- + ! Variables: + ! REcoM_S_depth : Constrained salinity for MOCSY [psu] + ! Sali_depth(k) : Actual salinity at depth k [psu] + ! + ! Constraints: + ! Minimum: 21 psu (increased from 19 to avoid numerical issues) + ! Maximum: 43 psu (upper limit of calibration range) + ! + ! Problematic Conditions: + ! - Salinity 19-21 psu with ice concentration > 97% + ! - Causes numerical instability in MOCSY + ! - Conservative constraint (21 psu minimum) prevents issues + ! + ! Note: Brackish water and ice-covered regions require special care + !----------------------------------------------------------------------- + + REcoM_S_depth = max(21.d0, Sali_depth(k)) ! Apply minimum + REcoM_S_depth = min(REcoM_S_depth, 43.d0) ! Apply maximum + + !----------------------------------------------------------------------- + ! Unit Conversions for MOCSY + !----------------------------------------------------------------------- + ! MOCSY requires concentrations in mol/m3 (not mmol/m3) + ! Conversion factor: 1e-3 (mmol -> mol) + ! + ! Variables (output): + ! REcoM_DIC_depth : DIC for MOCSY [mol m-3] + ! REcoM_Alk_depth : Alkalinity for MOCSY [mol m-3] + ! REcoM_Si_depth : Silicate for MOCSY [mol m-3] + ! REcoM_Phos_depth : Phosphate for MOCSY [mol m-3] + ! + ! Sources: + ! state(k, idic) + sms(k, idic) : DIC [mmol m-3] + ! state(k, ialk) + sms(k, ialk) : Alkalinity [mmol m-3] + ! state(k, isi) + sms(k, isi) : Silicate [mmol m-3] + ! state(k, idin) + sms(k, idin) : DIN -> Phosphate via Redfield + !----------------------------------------------------------------------- + + ! Dissolved inorganic carbon [mol m-3] + REcoM_DIC_depth = max(tiny * 1e-3, state(k, idic) * 1e-3 + sms(k, idic) * 1e-3) + + ! Total alkalinity [mol m-3] + REcoM_Alk_depth = max(tiny * 1e-3, state(k, ialk) * 1e-3 + sms(k, ialk) * 1e-3) + + ! Silicate [mol m-3] + REcoM_Si_depth = max(tiny * 1e-3, state(k, isi) * 1e-3 + sms(k, isi) * 1e-3) + + ! Phosphate [mol m-3] + ! Calculated from nitrogen using Redfield ratio (N:P = 16:1) + ! Model tracks nitrogen but MOCSY needs phosphate + REcoM_Phos_depth = max(tiny * 1e-3, state(k, idin) * 1e-3 + sms(k, idin) * 1e-3) / 16.d0 + + ! =================================================================== + ! CELLULAR QUOTAS AND RATIOS CALCULATIONS + ! =================================================================== + + !=============================================================================== + ! Small Phytoplankton Quotas + !=============================================================================== + ! Calculates stoichiometric ratios for the small phytoplankton functional type. + ! Represents diverse group of small flagellates and picophytoplankton. + ! + ! Variables: + ! quota : Nitrogen:Carbon quota [mmolN mmolC-1] + ! recipquota : Carbon:Nitrogen ratio [mmolC mmolN-1] + ! Chl2C : Chlorophyll:Carbon ratio [mgChl mmolC-1] + ! Chl2N : Chlorophyll:Nitrogen ratio [mgChl mmolN-1] + ! CHL2C_plast : Plastidic Chlorophyll:Carbon ratio [mgChl mmolC-1] + ! PhyN : Small phytoplankton nitrogen [mmolN m-3] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! PhyChl : Small phytoplankton chlorophyll [mgChl m-3] + ! NCmin : Minimum N:C quota (subsistence quota) [mmolN mmolC-1] + ! + ! Quota Interpretation: + ! - High quota (N:C > 0.15): Nutrient replete, luxury consumption + ! - Medium quota (N:C ≈ 0.10): Balanced growth + ! - Low quota (N:C < 0.06): Severely N-limited, near subsistence + ! - Minimum quota (NCmin ≈ 0.04): Zero growth threshold + ! + ! Plastidic Chlorophyll Concept: + ! - Total Chl includes storage and structural chlorophyll + ! - Plastidic Chl represents functional photosynthetic apparatus + ! - Correction factor: quota/(quota - NCmin) + ! - Higher correction when quota approaches minimum (more Chl in chloroplasts) + !------------------------------------------------------------------------------- + + ! Nitrogen:Carbon quota (cellular N:C ratio) + ! Controls growth rate via Droop limitation + quota = PhyN / PhyC + + ! Carbon:Nitrogen ratio (reciprocal) + ! Used for converting N-based fluxes to carbon + recipquota = real(one) / quota + + ! Chlorophyll:Carbon ratio + ! Reflects photoacclimation state (higher in low light) + Chl2C = PhyChl / PhyC + + ! Chlorophyll:Nitrogen ratio + ! Links photosynthetic machinery to nitrogen investment + Chl2N = PhyChl / PhyN + + ! Plastidic Chlorophyll:Carbon ratio + ! Estimates chlorophyll in active photosynthetic apparatus + ! Correction accounts for non-photosynthetic N (structural proteins, storage) + ! Formula: Chl2C x (quota / (quota - NCmin)) + ! As quota -> NCmin, more N is in photosynthetic machinery + CHL2C_plast = Chl2C * (quota / (quota - NCmin)) + + !=============================================================================== + ! Diatom Quotas + !=============================================================================== + ! Calculates stoichiometric ratios for diatoms (large phytoplankton with + ! silica frustules). Includes unique silicon quotas. + ! + ! Variables: + ! quota_dia : Diatom N:C quota [mmolN mmolC-1] + ! recipQuota_dia : Diatom C:N ratio [mmolC mmolN-1] + ! Chl2C_dia : Diatom Chl:C ratio [mgChl mmolC-1] + ! Chl2N_dia : Diatom Chl:N ratio [mgChl mmolN-1] + ! CHL2C_plast_dia : Diatom plastidic Chl:C ratio [mgChl mmolC-1] + ! qSiC : Diatom Si:C quota [mmolSi mmolC-1] + ! qSiN : Diatom Si:N quota [mmolSi mmolN-1] + ! DiaN : Diatom nitrogen [mmolN m-3] + ! DiaC : Diatom carbon [mmolC m-3] + ! DiaChl : Diatom chlorophyll [mgChl m-3] + ! DiaSi : Diatom silicon [mmolSi m-3] + ! NCmin_d : Minimum diatom N:C quota [mmolN mmolC-1] + ! + ! Silicon Quota Significance: + ! - Required for frustule (shell) formation + ! - Typical Si:C ≈ 0.13 (Brzezinski 1985) + ! - Low Si:C -> thin frustules, increased sinking mortality + ! - High Si:C -> thick frustules, enhanced sinking + ! - Si limitation can occur even when N is abundant + ! + ! Diatom-Specific Features: + ! - Generally lower Chl:C than small phytoplankton (package effect) + ! - Higher maximum growth rates when nutrient replete + ! - Bloom-forming under high-nutrient conditions + !------------------------------------------------------------------------------- + + ! Nitrogen:Carbon quota + quota_dia = DiaN / DiaC + + ! Carbon:Nitrogen ratio (reciprocal) + recipQuota_dia = real(one) / quota_dia + + ! Chlorophyll:Carbon ratio + ! Generally lower than small phytoplankton due to large cell size (package effect) + Chl2C_dia = DiaChl / DiaC + + ! Chlorophyll:Nitrogen ratio + Chl2N_dia = DiaChl / DiaN + + ! Plastidic Chlorophyll:Carbon ratio + ! Corrected for non-photosynthetic nitrogen allocation + CHL2C_plast_dia = Chl2C_dia * (quota_dia / (quota_dia - NCmin_d)) + + ! Silicon:Carbon quota + ! Critical for frustule formation and diatom physiology + ! Low Si:C indicates silicon limitation + qSiC = DiaSi / DiaC + + ! Silicon:Nitrogen quota + ! Alternative measure of silicon status relative to cellular nitrogen + qSiN = DiaSi / DiaN + + !=============================================================================== + ! Additional Phytoplankton Quotas (OPTIONAL) + !=============================================================================== + ! Calculates quotas for coccolithophores and Phaeocystis when enabled. + ! These groups have distinct biogeochemical roles. + ! + ! Coccolithophores: + ! - Calcifying phytoplankton (produce CaCO3 plates) + ! - Warm-water adapted + ! - Important for carbonate counter-pump + ! + ! Phaeocystis: + ! - Colonial phytoplankton (can form large blooms) + ! - Produces mucilaginous matrix + ! - Cold-water species (polar and temperate) + ! - High aggregation potential + !------------------------------------------------------------------------------- + + if (enable_coccos) then + + !=========================================================================== + ! Coccolithophore Quotas + !=========================================================================== + ! Calcifying phytoplankton with calcium carbonate plates (coccoliths) + ! + ! Variables: + ! quota_cocco : Cocco N:C quota [mmolN mmolC-1] + ! recipQuota_cocco : Cocco C:N ratio [mmolC mmolN-1] + ! Chl2C_cocco : Cocco Chl:C ratio [mgChl mmolC-1] + ! Chl2N_cocco : Cocco Chl:N ratio [mgChl mmolN-1] + ! CHL2C_plast_cocco : Cocco plastidic Chl:C ratio [mgChl mmolC-1] + ! CoccoN : Coccolithophore nitrogen [mmolN m-3] + ! CoccoC : Coccolithophore carbon [mmolC m-3] + ! CoccoChl : Coccolithophore chlorophyll [mgChl m-3] + ! NCmin_c : Minimum cocco N:C quota [mmolN mmolC-1] + ! + ! Note: Additional calcite quotas (CaCO3:C) calculated in calcification module + !--------------------------------------------------------------------------- + + ! Nitrogen:Carbon quota + quota_cocco = CoccoN / CoccoC + + ! Carbon:Nitrogen ratio + recipQuota_cocco = real(one) / quota_cocco + + ! Chlorophyll:Carbon ratio + Chl2C_cocco = CoccoChl / CoccoC + + ! Chlorophyll:Nitrogen ratio + Chl2N_cocco = CoccoChl / CoccoN + + ! Plastidic Chlorophyll:Carbon ratio + CHL2C_plast_cocco = Chl2C_cocco * (quota_cocco / (quota_cocco - NCmin_c)) + + !=========================================================================== + ! Phaeocystis Quotas + !=========================================================================== + ! Colonial phytoplankton that forms large blooms in cold waters + ! + ! Variables: + ! quota_phaeo : Phaeo N:C quota [mmolN mmolC-1] + ! recipQuota_phaeo : Phaeo C:N ratio [mmolC mmolN-1] + ! Chl2C_phaeo : Phaeo Chl:C ratio [mgChl mmolC-1] + ! Chl2N_phaeo : Phaeo Chl:N ratio [mgChl mmolN-1] + ! CHL2C_plast_phaeo : Phaeo plastidic Chl:C ratio [mgChl mmolC-1] + ! PhaeoN : Phaeocystis nitrogen [mmolN m-3] + ! PhaeoC : Phaeocystis carbon [mmolC m-3] + ! PhaeoChl : Phaeocystis chlorophyll [mgChl m-3] + ! NCmin_p : Minimum Phaeo N:C quota [mmolN mmolC-1] + ! + ! Ecological Notes: + ! - Forms colonial mucilaginous matrix (contributes to DOM) + ! - Can dominate Arctic/Antarctic spring blooms + ! - Enhanced aggregation and export potential + !--------------------------------------------------------------------------- + + ! Nitrogen:Carbon quota + quota_phaeo = PhaeoN / PhaeoC + + ! Carbon:Nitrogen ratio + recipQuota_phaeo = real(one) / quota_phaeo + + ! Chlorophyll:Carbon ratio + Chl2C_phaeo = PhaeoChl / PhaeoC + + ! Chlorophyll:Nitrogen ratio + Chl2N_phaeo = PhaeoChl / PhaeoN + + ! Plastidic Chlorophyll:Carbon ratio + CHL2C_plast_phaeo = Chl2C_phaeo * (quota_phaeo / (quota_phaeo - NCmin_p)) -!------------------------------------------------------------------------------- -! Main vertical loop starts - do k = one,Nn ! nzmin, nzmax -! do n=1, myDim_nod2D!+eDim_nod2D -! Nn=nlevels_nod2D(n)-1 !nzmax -! nzmin = ulevels_nod2D(row) -! nzmax = nlevels_nod2D(row) - DIN = max(tiny,state(k,idin) + sms(k,idin )) !< Avoids division by zero - DIC = max(tiny,state(k,idic) + sms(k,idic )) !! and updates Conc between - ALK = max(tiny,state(k,ialk) + sms(k,ialk )) !! local steps in REcoM when - PhyN = max(tiny_N,state(k,iphyn) + sms(k,iphyn )) !! biostep > 1 - PhyC = max(tiny_C,state(k,iphyc) + sms(k,iphyc )) - PhyChl = max(tiny_chl,state(k,ipchl) + sms(k,ipchl )) - DetN = max(tiny,state(k,idetn) + sms(k,idetn )) - DetC = max(tiny,state(k,idetc) + sms(k,idetc )) - HetN = max(tiny,state(k,ihetn) + sms(k,ihetn )) - HetC = max(tiny,state(k,ihetc) + sms(k,ihetc )) -#if defined (__3Zoo2Det) - Zoo2N = max(tiny,state(k,izoo2n) + sms(k,izoo2n)) - Zoo2C = max(tiny,state(k,izoo2c) + sms(k,izoo2c)) - DetZ2N = max(tiny,state(k,idetz2n) + sms(k,idetz2n)) - DetZ2C = max(tiny,state(k,idetz2c) + sms(k,idetz2c)) - DetZ2Si = max(tiny,state(k,idetz2si) + sms(k,idetz2si)) - DetZ2Calc = max(tiny,state(k,idetz2calc) + sms(k,idetz2calc)) - MicZooN = max(tiny,state(k,imiczoon) + sms(k,imiczoon)) - MicZooC = max(tiny,state(k,imiczooc) + sms(k,imiczooc)) -#endif - DON = max(tiny,state(k,idon) + sms(k,idon )) - EOC = max(tiny,state(k,idoc) + sms(k,idoc )) - DiaN = max(tiny_N_d,state(k,idian) + sms(k,idian )) - DiaC = max(tiny_C_d,state(k,idiac) + sms(k,idiac )) - DiaChl = max(tiny_chl,state(k,idchl) + sms(k,idchl )) - DiaSi = max(tiny_si,state(k,idiasi) + sms(k,idiasi)) - DetSi = max(tiny,state(k,idetsi) + sms(k,idetsi)) - Si = max(tiny,state(k,isi) + sms(k,isi )) -#if defined (__coccos) - CoccoN = max(tiny_N_c,state(k,icocn) + sms(k,icocn )) - CoccoC = max(tiny_C_c,state(k,icocc) + sms(k,icocc )) - CoccoChl = max(tiny_chl,state(k,icchl) + sms(k,icchl )) -#endif - Fe = max(tiny,state(k,ife) + sms(k,ife )) - O2 = max(tiny,state(k,ioxy) + sms(k,ioxy)) - FreeFe = zero + end if -! For Mocsy - REcoM_T_depth = max(2.d0, Temp(k)) ! minimum set to 2 degC: K1/K2 Lueker valid between 2degC-35degC and 19-43psu - REcoM_T_depth = min(REcoM_T_depth, 40.d0) ! maximum set to 40 degC: K1/K2 Lueker valid between 2degC-35degC and 19-43psu - REcoM_S_depth = max(21.d0, Sali_depth(k)) ! minimum set to 21: K1/K2 Lueker valid between 2degC-35degC and 19-43psu, else causes trouble in regions with S between 19 and 21 and ice conc above 97% - REcoM_S_depth = min(REcoM_S_depth, 43.d0) ! maximum set to 43: K1/K2 Lueker valid between 2degC-35degC and 19-43psu, else causes trouble - REcoM_DIC_depth = max(tiny*1e-3,state(k,idic)*1e-3 + sms(k,idic )*1e-3) - REcoM_Alk_depth = max(tiny*1e-3,state(k,ialk)*1e-3 + sms(k,ialk )*1e-3) - REcoM_Si_depth = max(tiny*1e-3,state(k,isi)*1e-3 + sms(k,isi )*1e-3) - - REcoM_Phos_depth = max(tiny*1e-3,state(k,idin)*1e-3 + sms(k,idin )*1e-3) /16 ! convert N to P with Redfield [mol/m3] - - PhyCalc = max(tiny,state(k,iphycal) + sms(k,iphycal)) - DetCalc = max(tiny,state(k,idetcal) + sms(k,idetcal)) - -!!------------------------------------------------------------------------------ -!< Quotas - ! *** Small phytoplankton - quota = PhyN / PhyC ! include variability of the N: C ratio, cellular chemical composition - recipquota = real(one) / quota - Chl2C = PhyChl / PhyC ! Chl a:phytoplankton carbon ratio, cellular chemical composition [gCHL gC^-1] - Chl2N = PhyChl / PhyN ! Chl a:phytoplankton nitrogen ratio, cellular chemical composition [gCHL gN^-1] - CHL2C_plast = Chl2C * (quota/(quota - NCmin)) - - ! *** Diatoms - quota_dia = DiaN / DiaC - recipQuota_dia = real(one)/quota_dia - Chl2C_dia = DiaChl / DiaC - Chl2N_dia = DiaChl / DiaN - CHL2C_plast_dia = Chl2C_dia * (quota_dia/(quota_dia - NCmin_d)) - qSiC = DiaSi / DiaC - qSiN = DiaSi / DiaN - -#if defined (__coccos) - quota_cocco = CoccoN / CoccoC - recipQuota_cocco = real(one)/quota_cocco - Chl2C_cocco = CoccoChl / CoccoC - Chl2N_cocco = CoccoChl / CoccoN - CHL2C_plast_cocco = Chl2C_cocco * (quota_cocco/(quota_cocco - NCmin_c)) -#endif - recipQZoo = HetC / HetN - recip_hetN_plus = 1.d0 / (HetN + tiny_het) ! MB's addition for more stable zoo respiration - if (Grazing_detritus) recipDet = DetC / DetN -#if defined (__3Zoo2Det) - recipQZoo2 = Zoo2C / Zoo2N - recipQZoo3 = MicZooC / MicZooN - if (Grazing_detritus) recipDet2 = DetZ2C / DetZ2N -#endif + !=============================================================================== + ! Zooplankton and Detritus Quotas + !=============================================================================== + ! Calculates carbon:nitrogen ratios for consumers and detrital pools. + ! These ratios are more constrained than phytoplankton (less variable). + ! + ! Zooplankton C:N ratios: + ! - Typically near Redfield ratio (C:N ≈ 6.6) + ! - Less variable than phytoplankton (homeostatic regulation) + ! - Important for grazer nutrition and trophic transfer efficiency + ! + ! Detritus C:N ratios: + ! - Reflects source material composition + ! - Can increase with depth (preferential N remineralization) + ! - Affects remineralization stoichiometry + ! + ! Variables: + ! recipQZoo : Mesozooplankton C:N ratio [mmolC mmolN-1] + ! recipQZoo2 : Macrozooplankton C:N ratio [mmolC mmolN-1] + ! recipQZoo3 : Microzooplankton C:N ratio [mmolC mmolN-1] + ! recipDet : Slow-sinking detritus C:N ratio [mmolC mmolN-1] + ! recipDet2 : Fast-sinking detritus C:N ratio [mmolC mmolN-1] + ! recip_hetN_plus : Stable divisor for respiration calculations [mmolN-1 m3] + ! HetC, HetN : Mesozooplankton carbon and nitrogen [mmol m-3] + ! Zoo2C, Zoo2N : Macrozooplankton carbon and nitrogen [mmol m-3] + ! MicZooC, MicZooN: Microzooplankton carbon and nitrogen [mmol m-3] + ! DetC, DetN : Detritus carbon and nitrogen [mmol m-3] + ! DetZ2C, DetZ2N : Fast-sinking detritus carbon and nitrogen [mmol m-3] + ! tiny_het : Small number to prevent division by zero [mmolN m-3] + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Mesozooplankton (Primary Heterotroph) Quotas + !------------------------------------------------------------------------------- + ! Primary grazer consuming phytoplankton and microzooplankton + + ! Carbon:Nitrogen ratio + ! Used for converting nitrogen-based grazing to carbon fluxes + recipQZoo = HetC / HetN + + ! Stable reciprocal for respiration calculations + ! Prevents division by zero when zooplankton biomass is very low + ! Used in Redfield-based respiration formulation + recip_hetN_plus = 1.d0 / (HetN + tiny_het) + + !------------------------------------------------------------------------------- + ! Detritus Quotas + !------------------------------------------------------------------------------- + ! Organic matter pools with variable C:N ratios -!------------------------------------------------------------------------------- -!> Temperature dependence of rates -!------------------------------------------------------------------------------- -!< Schourup 2013 Eq. A54 -!< Temperature dependence of metabolic rate, fT, dimensionless -!< Ae: Slope of the linear region of the Arrhenius plot -!< rTloc: Inverse of local temperature in [1/Kelvin] -!< rTref=288.15 (15 degC): Reference temperature for Arrhenius equation [1/Kelvin] -!< See Figure A1 -!< Other functions can be used for temperature dependency (Eppley 1972; Li 1980; Ahlgren 1987) - - rTloc = real(one)/(Temp(k) + C2K) - arrFunc = exp(-Ae * ( rTloc - rTref)) -#if defined (__coccos) - CoccoTFunc = max(0.1419d0 * Temp(k)**0.8151d0,tiny) ! Function from Fielding 2013; is based on observational GR, but range fits best to ours -#endif - -#if defined (__3Zoo2Det) - arrFuncZoo2 = exp(t1_zoo2/t2_zoo2 - t1_zoo2*rTloc)/(1 + exp(t3_zoo2/t4_zoo2 - t3_zoo2*rTloc)) ! 2Zoo - q10_mes = 1.0242**(Temp(k)) ! 3Zoo - q10_mic = 1.04**(Temp(k)) ! 3Zoo - q10_mes_res = 1.0887**(Temp(k)) ! 3Zoo - q10_mic_res = 1.0897**(Temp(k)) ! 3Zoo -#endif - -!< Silicate temperature dependence -! reminSiT = min(1.32e16 * exp(-11200.d0 * rTloc),reminSi) !! arrFunc control, reminSi=0.02d0 ! Kamatani (1982) -! reminSiT = reminSi - reminSiT = max(0.023d0 * 2.6d0**((Temp(k)-10.)/10.),reminSi) + if (Grazing_detritus) then + ! Slow-sinking detritus C:N ratio + ! Source: Unassimilated food, mortality, aggregation + ! Generally close to Redfield but can be elevated + recipDet = DetC / DetN + endif -!------------------------------------------------------------------------------- -!> O2 dependence of rates -!------------------------------------------------------------------------------- -!! O2 dependency of organic matter remineralization -!! O2Func [0.0, 1.0] -!! k_o2_remin = 15.d0 mmol m-3; Table 1 in Cram 2018 cites -!! DeVries & Weber 2017 for a range of 0-30 mmol m-3 - - O2Func = 1.d0 ! in this case, remin. rates only depend on temperature - if (O2dep_remin) O2Func = O2/(k_o2_remin + O2) ! O2remin - -!< *** Light *** -!< ************* -!! Has to be calculated here already to use the 1%PAR depth. - if (k==1) then - PARave = max(tiny,SurfSR) - PAR(k) = PARave - - chl_upper = (PhyChl + DiaChl) -#if defined (__coccos) - chl_upper = chl_upper + CoccoChl -#endif - else - chl_lower = PhyChl + DiaChl -#if defined (__coccos) - chl_lower = chl_lower + CoccoChl -#endif - Chlave = (chl_upper+chl_lower)*0.5 - - kappa = k_w + a_chl * (Chlave) - kappastar = kappa / cosAI(n) - kdzLower = kdzUpper + kappastar * thick(k-1) - Lowerlight = SurfSR * exp(-kdzLower) - Lowerlight = max(tiny,Lowerlight) - PARave = Lowerlight - PAR(k) = PARave - chl_upper = chl_lower - kdzUpper = kdzLower - end if + if (enable_3zoo2det) then -!------------------------------------------------------------------------------- -! Depth component of Mocsy (see http://ocmip5.ipsl.jussieu.fr/mocsy/pyth.html) -!------------------------------------------------------------------------------- + !--------------------------------------------------------------------------- + ! Additional Zooplankton Quotas (3-Zooplankton Model) + !--------------------------------------------------------------------------- + + ! Macrozooplankton (e.g., krill) C:N ratio + ! Larger organisms with potentially different stoichiometry + recipQZoo2 = Zoo2C / Zoo2N + + ! Microzooplankton (e.g., ciliates, heterotrophic dinoflagellates) C:N ratio + ! Smallest heterotrophs, link to microbial loop + recipQZoo3 = MicZooC / MicZooN -! Calculate the carbonate system for the very first time step of the first year of the run - !if (mocsy_restart==.false. .and. recom_istep==1) then ! r_restart is defined in gen_modules_clock in fesom_cpl. + if (Grazing_detritus) then + !----------------------------------------------------------------------- + ! Fast-Sinking Detritus (Fecal Pellets) + !----------------------------------------------------------------------- + ! Large, rapidly sinking particles + ! Source: Zooplankton fecal pellets, large aggregates + ! Important for biological pump and carbon export + + recipDet2 = DetZ2C / DetZ2N + endif + + endif + + ! =================================================================== + ! CARBON ISOTOPE TRACERS (if enabled) + ! =================================================================== + + if (ciso) then + ! 13C isotope tracers + DIC_13 = max(tiny, state(k, idic_13) + sms(k, idic_13)) + PhyC_13 = max(tiny_C, state(k, iphyc_13) + sms(k, iphyc_13)) + DetC_13 = max(tiny, state(k, idetc_13) + sms(k, idetc_13)) + HetC_13 = max(tiny, state(k, ihetc_13) + sms(k, ihetc_13)) + EOC_13 = max(tiny, state(k, idoc_13) + sms(k, idoc_13)) + DiaC_13 = max(tiny_C, state(k, idiac_13) + sms(k, idiac_13)) + PhyCalc_13 = max(tiny, state(k, iphycal_13) + sms(k, iphycal_13)) + DetCalc_13 = max(tiny, state(k, idetcal_13) + sms(k, idetcal_13)) + + ! 13C calcite dissolution with fractionation + calc_diss_13 = alpha_dcal_13 * calc_diss + + ! 13C quotas + quota_13 = PhyN / PhyC_13 + recipQuota_13 = real(one) / quota_13 + quota_dia_13 = DiaN / DiaC_13 + recipQuota_dia_13 = real(one) / quota_dia_13 + recipQZoo_13 = HetC_13 / HetN + + ! 14C radiocarbon tracers (if enabled) + if (ciso_14) then + DIC_14 = max(tiny, state(k,idic_14) + sms(k, idic_14)) + + if (ciso_organic_14) then + PhyC_14 = max(tiny_C, state(k,iphyc_14) + sms(k, iphyc_14)) + DetC_14 = max(tiny, state(k,idetc_14) + sms(k, idetc_14)) + HetC_14 = max(tiny, state(k,ihetc_14) + sms(k, ihetc_14)) + EOC_14 = max(tiny, state(k,idoc_14) + sms(k, idoc_14)) + DiaC_14 = max(tiny_C, state(k,idiac_14) + sms(k, idiac_14)) + PhyCalc_14 = max(tiny, state(k,iphycal_14) + sms(k,iphycal_14)) + DetCalc_14 = max(tiny, state(k,idetcal_14) + sms(k,idetcal_14)) + + calc_diss_14 = alpha_dcal_14 * calc_diss + + quota_14 = PhyN / PhyC_14 + recipQuota_14 = real(one) / quota_14 + quota_dia_14 = DiaN / DiaC_14 + recipQuota_dia_14 = real(one) / quota_dia_14 + recipQZoo_14 = HetC_14 / HetN + end if ! ciso_organic_14 + end if ! ciso_14 + end if ! ciso + + !=============================================================================== + ! TEMPERATURE DEPENDENCE OF METABOLIC RATES + !=============================================================================== + ! Calculates how temperature affects biological rates using multiple + ! formulations appropriate for different organism groups. + ! + ! General Principle: + ! - Metabolic rates increase exponentially with temperature (Q10 rule) + ! - Different organisms have different thermal optima and tolerances + ! - Cold-adapted vs warm-adapted species + ! + ! Variables (Arrhenius): + ! rTloc : Inverse of local absolute temperature [K-1] + ! arrFunc : Arrhenius temperature function [-] + ! Temp(k) : Temperature at depth k [degC] + ! C2K : Celsius to Kelvin conversion (273.15) [K] + ! Ae : Activation energy parameter [K] + ! rTref : Inverse reference temperature (1/288.15 K at 15degC) [K-1] + ! + ! Alternative Formulations (commented in code): + ! - Eppley (1972): Log-linear for phytoplankton + ! - Li (1980): Parabolic curve + ! - Ahlgren (1987): Optimum curve + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Standard Arrhenius Function + !------------------------------------------------------------------------------- + ! General metabolic rate temperature dependence (Schourup 2013, Eq. A54) + ! Exponential increase with temperature (no upper thermal limit) + ! + ! Equation: + ! f(T) = exp(-Ae × (1/T - 1/Tref)) + ! + ! Where: + ! - Ae: Slope of Arrhenius plot (activation energy/gas constant) + ! - Tref: Reference temperature (typically 15degC = 288.15 K) + ! - T: Absolute temperature [K] + ! + ! Used for: Most metabolic processes without strong thermal limits + ! (e.g., remineralization, basal metabolism) + + ! Calculate inverse absolute temperature + rTloc = real(one) / (Temp(k) + C2K) + + ! Calculate Arrhenius function + arrFunc = exp(-Ae * (rTloc - rTref)) + + !------------------------------------------------------------------------------- + ! Phytoplankton-Specific Temperature Functions + !------------------------------------------------------------------------------- + ! Species-specific exponential and optimum-curve temperature responses + ! Tuned for 4-plankton functional type version (small phyto, diatoms, coccos, Phaeocystis) + ! + ! Note: New functions require calibration if adapted to 2-plankton version + !------------------------------------------------------------------------------- + + ! Old coccolithophore temperature function (commented out): + ! Power law form from Fielding (2013) based on observational growth rates + ! if (enable_coccos) then + ! CoccoTFunc = max(0.1419d0 * Temp(k)**0.8151d0, tiny) + ! endif + + if (enable_coccos) then + + !--------------------------------------------------------------------------- + ! Small Phytoplankton + !--------------------------------------------------------------------------- + ! Exponential temperature response: f(T) = exp(a + b×T) + ! Represents diverse group with broad thermal tolerance + ! Monotonic increase with temperature (no upper limit in this formulation) + + Temp_phyto = exp(ord_phy + expon_phy * Temp(k)) + VTTemp_phyto(k) = Temp_phyto ! Store for diagnostics + + !--------------------------------------------------------------------------- + ! Diatoms + !--------------------------------------------------------------------------- + ! Large phytoplankton with silica frustules + ! Exponential form with different parameters than small phyto + ! Generally favored by cooler, nutrient-rich conditions + + Temp_diatoms = exp(ord_d + expon_d * Temp(k)) + VTTemp_diatoms(k) = Temp_diatoms ! Store for diagnostics + + !--------------------------------------------------------------------------- + ! Coccolithophores + !--------------------------------------------------------------------------- + ! Calcifying phytoplankton with minimum temperature threshold + ! Cold-intolerant: minimal growth below 5degC + ! Exponential increase above threshold temperature + ! + ! Ecological rationale: Coccos typically dominate in warm, stratified waters + + if (Temp(k) < 5.0) then + ! Below threshold: minimal metabolic activity + Temp_cocco = tiny + else + ! Above threshold: exponential response + Temp_cocco = exp(ord_cocco + expon_cocco * Temp(k)) + Temp_cocco = max(Temp_cocco, tiny) ! Ensure positive values + end if + VTTemp_cocco(k) = Temp_cocco ! Store for diagnostics + + !--------------------------------------------------------------------------- + ! Phaeocystis + !--------------------------------------------------------------------------- + ! Colonial phytoplankton with bell-shaped temperature response + ! Blanchard function from Grimaud et al. (2017) + ! Has optimal temperature with decline at high and low temperatures + ! + ! Equation: f(T) = uopt × ((Tmax-T)/(Tmax-Topt))^β × exp(-β×(Topt-T)/(Tmax-Topt)) + ! + ! Where: + ! - uopt: Maximum growth rate at optimal temperature [day-1] + ! - Topt: Optimal temperature [degC] + ! - Tmax: Maximum temperature (growth = 0) [degC] + ! - β: Shape parameter (steepness of curve) [-] + ! + ! Ecological rationale: Phaeocystis blooms occur at specific temperature ranges + ! (typically cold-temperate waters, 0-10degC) + + Temp_phaeo = uopt_phaeo * ((Tmax_phaeo - Temp(k)) / (Tmax_phaeo - Topt_phaeo))**beta_phaeo & + * exp(-beta_phaeo * (Topt_phaeo - Temp(k)) / (Tmax_phaeo - Topt_phaeo)) + Temp_phaeo = max(Temp_phaeo, tiny) ! Ensure positive values + VTTemp_phaeo(k) = Temp_phaeo ! Store for diagnostics + + endif + + !------------------------------------------------------------------------------- + ! Zooplankton Temperature Dependencies + !------------------------------------------------------------------------------- + ! Temperature functions for different zooplankton types with thermal limits + ! Q10 formulations: exponential increase with ~doubling per 10degC + + if (enable_3zoo2det) then + + !--------------------------------------------------------------------------- + ! Macrozooplankton (Krill) Temperature Function + !--------------------------------------------------------------------------- + ! Sigmoid function with upper thermal limit + ! Accounts for thermal stress at high temperatures + ! + ! Equation: f(T) = exp(t1/t2 - t1/T) / (1 + exp(t3/t4 - t3/T)) + ! + ! Numerator: Exponential increase with temperature + ! Denominator: Sigmoid decline at high temperatures (thermal stress) + ! + ! Ecological rationale: Macrozooplankton have defined thermal niches + ! (e.g., Antarctic krill prefer cold water, decline above ~4degC) + + arrFuncZoo2 = exp(t1_zoo2 / t2_zoo2 - t1_zoo2 * rTloc) / & + (1.0 + exp(t3_zoo2 / t4_zoo2 - t3_zoo2 * rTloc)) + + !--------------------------------------------------------------------------- + ! Q10 Temperature Coefficients + !--------------------------------------------------------------------------- + ! Q10 formulation: rate = Q10^(T/10) + ! Simple exponential increase with temperature + ! + ! Q10 values: + ! - ~1.02-1.04: Moderate temperature sensitivity (typical for metabolism) + ! - ~1.09: Higher sensitivity (respiration processes) + ! + ! Ecological interpretation: + ! - Smaller organisms (microzooplankton) often have higher Q10 + ! - Respiration Q10 > growth Q10 (maintenance costs increase faster) + + q10_mes = 1.0242**(Temp(k)) ! Mesozooplankton metabolism + q10_mic = 1.04**(Temp(k)) ! Microzooplankton metabolism + q10_mes_res = 1.0887**(Temp(k)) ! Mesozooplankton respiration + q10_mic_res = 1.0897**(Temp(k)) ! Microzooplankton respiration + + endif + + !------------------------------------------------------------------------------- + ! Silicate Dissolution Temperature Dependence + !------------------------------------------------------------------------------- + ! Temperature effect on biogenic silica (diatom frustule) dissolution + ! Higher temperatures accelerate chemical dissolution kinetics + ! + ! Variables: + ! reminSiT : Temperature-dependent Si dissolution rate [day-1] + ! reminSi : Minimum dissolution rate [day-1] + ! + ! Exponential formulation: 2.6× increase per 10degC + ! Reference temperature: 10degC + ! + + reminSiT = max(0.023d0 * 2.6d0**((Temp(k) - 10.0) / 10.0), reminSi) + + ! Alternative Kamatani (1982) function (commented out): + ! reminSiT = min(1.32e16 * exp(-11200.d0 * rTloc), reminSi) + + !=============================================================================== + ! 2. OXYGEN DEPENDENCE OF REMINERALIZATION + !=============================================================================== + ! Calculates oxygen limitation effects on aerobic organic matter decomposition. + ! Important for oxygen minimum zones (OMZs) and suboxic/anoxic environments. + ! + ! Variables: + ! O2Func : Oxygen limitation factor [0-1, 0=anoxic, 1=oxic] + ! O2 : Dissolved oxygen concentration [mmolO2 m-3] + ! k_o2_remin : Half-saturation for O2-limited remineralization [mmolO2 m-3] + ! O2dep_remin : Flag to enable O2-dependent remineralization [logical] + ! + ! Michaelis-Menten Formulation: + ! f(O2) = O2 / (k_O2 + O2) + ! + ! Parameter Value: + ! k_o2_remin = 15 mmolO2 m-3 (half-saturation constant) + ! Range: 0-30 mmolO2 m-3 based on DeVries & Weber (2017), cited in Cram (2018) + ! + ! Ecological/Biogeochemical Significance: + ! - Aerobic respiration dominates in oxic waters (O2 > 30 mmol m-3) + ! - Suboxic/anoxic metabolism (denitrification, sulfate reduction) in OMZs + ! - Reduced remineralization efficiency in low-O2 environments + ! - Important for nutrient cycling and carbon export in OMZs + ! + ! Note: When O2 < 0.1 mmol m-3, consider switching to anaerobic pathways + ! (not implemented in this version) + !------------------------------------------------------------------------------- + + ! Default: no oxygen limitation (fully oxic conditions) + O2Func = 1.d0 + + if (O2dep_remin) then + ! Enable oxygen-dependent remineralization + ! Michaelis-Menten type limitation + ! Becomes significant when O2 < ~30 mmol m-3 + O2Func = O2 / (k_o2_remin + O2) + endif + + !=============================================================================== + ! LIGHT AVAILABILITY CALCULATION + !=============================================================================== + ! Calculates photosynthetically available radiation (PAR) through the water + ! column using Beer-Lambert law with chlorophyll-based attenuation. + ! + ! Light Attenuation Components: + ! 1. Water attenuation (k_w): Clear water absorption and scattering + ! 2. Chlorophyll attenuation (a_chl): Phytoplankton self-shading + ! + ! Variables: + ! PARave : Average PAR at depth k [W m-2] + ! PAR(k) : Stored PAR for layer k [W m-2] + ! SurfSR : Surface solar radiation [W m-2] + ! chl_upper : Chlorophyll at upper layer boundary [mgChl m-3] + ! chl_lower : Chlorophyll at lower layer boundary [mgChl m-3] + ! Chlave : Average chlorophyll in layer [mgChl m-3] + ! kappa : Total attenuation coefficient [m-1] + ! kappastar : Angle-corrected attenuation coefficient [m-1] + ! k_w : Water attenuation coefficient [m-1] + ! a_chl : Chlorophyll-specific attenuation [(m2 mgChl-1)] + ! cosAI(n) : Cosine of solar zenith angle [-] + ! thick(k) : Layer thickness [m] + ! kdzLower : Cumulative optical depth [dimensionless] + ! kdzUpper : Cumulative optical depth at upper boundary [dimensionless] + ! + ! Beer-Lambert Law: + ! I(z) = I0 × exp(-κ×z) + ! where κ = k_w + a_chl×[Chl] + ! + ! Self-Shading Effect: + ! - High chlorophyll reduces light penetration + ! - Limits bloom depth and total biomass + ! - Creates trade-off between cell density and light availability + ! + ! Ecological Significance: + ! - Defines euphotic zone depth (1% surface light) + ! - Controls vertical distribution of primary production + ! - Self-shading is key negative feedback on bloom magnitude + !------------------------------------------------------------------------------- + + if (k == 1) then + + !=========================================================================== + ! SURFACE LAYER INITIALIZATION + !=========================================================================== + ! Surface layer receives full incident solar radiation + ! Initialize chlorophyll and optical depth for subsurface calculations + !--------------------------------------------------------------------------- + + ! Surface PAR equals incident solar radiation + PARave = max(tiny, SurfSR) + PAR(k) = PARave + + ! Initialize surface chlorophyll for attenuation calculation + ! Sum all phytoplankton functional types + chl_upper = (PhyChl + DiaChl) ! Base groups (always present) + + if (enable_coccos) then + ! Add coccolithophores and Phaeocystis if enabled + chl_upper = chl_upper + CoccoChl + PhaeoChl + endif + else + + !=========================================================================== + ! SUBSURFACE LIGHT ATTENUATION + !=========================================================================== + ! Calculate light penetration through water column using Beer-Lambert law + ! with chlorophyll-based self-shading + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Calculate Current Layer Chlorophyll + !--------------------------------------------------------------------------- + + chl_lower = PhyChl + DiaChl + + if (enable_coccos) then + chl_lower = chl_lower + CoccoChl + PhaeoChl + endif + + ! Average chlorophyll between layer boundaries + ! Assumes linear interpolation within layer + Chlave = (chl_upper + chl_lower) * 0.5 + + !--------------------------------------------------------------------------- + ! Calculate Attenuation Coefficient + !--------------------------------------------------------------------------- + + ! Total attenuation coefficient + ! k_w: Clear water absorption (~0.04 m-1 in ocean) + ! a_chl: Chlorophyll-specific attenuation (~0.03-0.05 m2 mgChl-1) + kappa = k_w + a_chl * Chlave + + ! Correct for solar zenith angle (path length through water) + ! Lower sun angle -> longer path -> more attenuation + kappastar = kappa / cosAI(n) + + ! Cumulative optical depth (dimensionless) + ! Integrates attenuation over depth + kdzLower = kdzUpper + kappastar * thick(k - 1) + + !--------------------------------------------------------------------------- + ! Calculate Light at Layer + !--------------------------------------------------------------------------- + + ! Beer-Lambert law: exponential decay with optical depth + Lowerlight = SurfSR * exp(-kdzLower) + Lowerlight = max(tiny, Lowerlight) ! Ensure positive value + + ! Store PAR for this layer + PARave = Lowerlight + PAR(k) = PARave + + ! Update variables for next layer + chl_upper = chl_lower ! Current lower becomes next upper + kdzUpper = kdzLower ! Current cumulative depth for next layer + + end if + + !=============================================================================== + ! MARINE CARBONATE SYSTEM CALCULATIONS (MOCSY) + !=============================================================================== + ! Calculates complete marine carbonate chemistry using the MOCSY package + ! (Marine Ocean Carbon System Solver). + ! + ! This module calculates: + ! 1. Carbonate system speciation (CO2, HCO3-, CO3--) + ! 2. pH and partial pressure of CO2 (pCO2) + ! 3. Carbonate saturation states (Omega for calcite and aragonite) + ! 4. Solubility products and seawater properties + ! + ! Key Features: + ! - Adaptive update frequency (depth-dependent) + ! - Euphotic zone: Weekly updates (high biological activity) + ! - Deep waters: Monthly updates (slower changes) + ! - Complete thermodynamic consistency + ! - Pressure correction for depth + ! + ! MOCSY Package: + ! - Developed for OCMIP5 project + ! - Solves carbonate system from two known parameters + ! - Accounts for temperature, salinity, pressure effects + ! - Multiple equilibrium constant formulations available + ! + ! Update Strategy: + ! - Initialize on first time step (mstep = 1) + ! - Euphotic zone (PAR > 1% surface): 7-day updates + ! - Deep waters (PAR < 1% surface): 30-day updates + ! - Rationale: Biological activity drives rapid changes near surface + ! + ! Input Parameters: + ! - Temperature, Salinity (from physical model) + ! - DIC, Alkalinity (from biogeochemical tracers) + ! - Silicate, Phosphate (affects equilibrium constants) + ! - Atmospheric pressure, Latitude (for gas exchange) + ! + ! Output Variables: + ! - pH, pCO2, fCO2 (CO2 partial and fugacity) + ! - CO2, HCO3-, CO3-- (carbonate species concentrations) + ! - OmegaC, OmegaA (calcite and aragonite saturation) + ! - Solubility products, seawater density + ! + ! Ecological/Biogeochemical Significance: + ! - Controls CO2 uptake/release (air-sea exchange) + ! - Regulates calcification and dissolution rates + ! - Affects phytoplankton carbon acquisition + ! - Critical for ocean acidification studies + ! + ! References: + ! - MOCSY: http://ocmip5.ipsl.jussieu.fr/mocsy/ + ! - Orr & Epitalon (2015) - MOCSY 2.0 user guide + !=============================================================================== + + !=============================================================================== + ! PREPARATION AND INITIALIZATION + !=============================================================================== + ! Prepares input data and initializes carbonate system on first time step. + ! + ! Variables: + ! dpos(1) : Depth for pressure calculations [m, positive down] + ! zF(k) : Model depth coordinate [m, negative down] + ! mstep : Model time step counter [-] + ! k : Vertical layer index [-] + ! + ! Input Arrays for MOCSY: + ! REcoM_T_depth : Temperature [degC, potential temperature] + ! REcoM_S_depth : Salinity [psu, practical salinity] + ! REcoM_Alk_depth : Total alkalinity [mol m-3] + ! REcoM_DIC_depth : Dissolved inorganic carbon [mol m-3] + ! REcoM_Si_depth : Silicate concentration [mol m-3] + ! REcoM_Phos_depth : Phosphate concentration [mol m-3] + ! Patm_depth : Atmospheric pressure [atm] + ! Latd : Latitude [degrees] + ! Nmocsy : Number of points (1 for single depth) + ! + ! Note: Depth convention conversion required (model uses negative depths) + !------------------------------------------------------------------------------- + + ! Convert model depth coordinate to positive depth for MOCSY + ! Model convention: zF(k) is negative (e.g., -100 m) + ! MOCSY convention: depth is positive (e.g., 100 m) dpos(1) = -zF(k) - if (mstep==1) then - call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & - rhoSW_depth, p_depth, tempis_depth, & - REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & - optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + !=============================================================================== + ! INITIAL CARBONATE SYSTEM CALCULATION + !=============================================================================== + ! Calculates complete carbonate system on first model time step. + ! Provides initial conditions for all carbonate chemistry variables. + ! + ! Output Variables (from MOCSY): + ! ph_depth(1) : pH on total scale [-] + ! pco2_depth(1) : Partial pressure of CO2 [μatm] + ! fco2_depth(1) : Fugacity of CO2 [μatm] + ! co2_depth(1) : Dissolved CO2 concentration [mol m-3] + ! hco3_depth(1) : Bicarbonate concentration [mol m-3] + ! co3_depth(1) : Carbonate ion concentration [mol m-3] + ! OmegaA_depth(1) : Aragonite saturation state [-] + ! OmegaC_depth(1) : Calcite saturation state [-] + ! kspc_depth(1) : Calcite solubility product [mol2 kg-2] + ! BetaD_depth(1) : Revelle factor (buffer capacity) [-] + ! rhoSW_depth(1) : Seawater density [kg m-3] + ! p_depth(1) : Pressure [bar] + ! tempis_depth(1) : In situ temperature [degC] + ! + ! Water Column Storage: + ! CO2_watercolumn(k) : Stored CO2 for biological calculations [mol m-3] + ! pH_watercolumn(k) : Stored pH [-] + ! pCO2_watercolumn(k) : Stored pCO2 [μatm] + ! HCO3_watercolumn(k) : Stored bicarbonate [mol m-3] + ! CO3_watercolumn(k) : Stored carbonate [mol m-3] + ! OmegaC_watercolumn(k) : Stored calcite saturation [-] + ! kspc_watercolumn(k) : Stored solubility product [mol2 kg-2] + ! rhoSW_watercolumn(k) : Stored seawater density [kg m-3] + ! + ! MOCSY Options: + ! optCON='mol/m3' : Concentration units (mol/m3) + ! optT='Tpot ' : Temperature is potential temperature + ! optP='m ' : Pressure given as depth in meters + ! optB='u74' : Boron:Salinity ratio from Uppström (1974) + ! optK1K2='l ' : Carbonic acid constants from Lueker et al. (2000) + ! optKf='dg' : HF constant from Dickson & Goyet (1994) + ! optGAS='Pinsitu' : Pressure is in situ (accounts for depth) + ! optS='Sprc' : Salinity on practical scale + !------------------------------------------------------------------------------- + + if (mstep == 1) then + + ! Call MOCSY to solve carbonate system + ! Uses DIC and Alkalinity as input pair (most common in ocean models) + call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, & + OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & + rhoSW_depth, p_depth, tempis_depth, & + REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, & + REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & + optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', & + optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + ! Store results in water column arrays for use in biogeochemical calculations CO2_watercolumn(k) = co2_depth(1) pH_watercolumn(k) = ph_depth(1) pCO2_watercolumn(k) = pco2_depth(1) @@ -348,18 +1501,72 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & OmegaC_watercolumn(k) = OmegaC_depth(1) kspc_watercolumn(k) = kspc_depth(1) rhoSW_watercolumn(k) = rhoSW_depth(1) - endif - -!! Calculate carbonate system every 7 days for depths < 1%PAR, and every 30 days for the depths below. - mocsy_step_per_day = 1/dt_b ! NEW ms: time steps per day in recom -> is that correct? Not necessary to define in namelist? - logfile_outfreq_7 = mocsy_step_per_day*7 - logfile_outfreq_30 = mocsy_step_per_day*30 - - if (PARave > 0.01*SurfSR .and. mod(mstep,logfile_outfreq_7)==0) then - call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & - rhoSW_depth, p_depth, tempis_depth, & - REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & - optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + endif + + !=============================================================================== + ! ADAPTIVE CARBONATE SYSTEM UPDATE FREQUENCY + !=============================================================================== + ! Determines how often to recalculate carbonate system based on depth. + ! More frequent updates where biological activity drives rapid changes. + ! + ! Variables: + ! mocsy_step_per_day : Number of model time steps per day [-] + ! dt_b : Model time step [days] + ! logfile_outfreq_7 : Number of steps in 7 days [-] + ! logfile_outfreq_30 : Number of steps in 30 days [-] + ! PARave : Average photosynthetically active radiation [W m-2] + ! SurfSR : Surface solar radiation [W m-2] + ! + ! Update Strategy: + ! - Euphotic zone (PAR > 1% surface): 7-day updates + ! * High photosynthesis rates alter DIC and pH rapidly + ! * Important for accurate phytoplankton CO2 responses + ! - Deep waters (PAR < 1% surface): 30-day updates + ! * Slower changes dominated by remineralization and mixing + ! * Reduces computational cost while maintaining accuracy + ! + ! Computational Cost Considerations: + ! - Carbonate system solving is computationally expensive + ! - Adaptive frequency balances accuracy and performance + ! - Typical speedup: 4× faster than daily updates everywhere + !------------------------------------------------------------------------------- + + ! Calculate update frequencies based on model time step + mocsy_step_per_day = 1.0 / dt_b + logfile_outfreq_7 = mocsy_step_per_day * 7.0 ! Steps in 7 days + logfile_outfreq_30 = mocsy_step_per_day * 30.0 ! Steps in 30 days + + !=============================================================================== + ! EUPHOTIC ZONE UPDATES (WEEKLY) + !=============================================================================== + ! Frequent updates in sunlit surface waters where biological activity is high. + ! Euphotic zone defined as PAR > 1% of surface irradiance. + ! + ! Biological Drivers: + ! - Photosynthesis removes DIC, increases pH + ! - Respiration/remineralization adds DIC, decreases pH + ! - Calcification removes alkalinity + ! - Rapid daily and seasonal cycles + ! + ! Why 7-day updates? + ! - Captures weekly-scale biological dynamics + ! - Adequate for phytoplankton bloom progression + ! - Reasonable computational cost + !------------------------------------------------------------------------------- + + if (PARave > 0.01 * SurfSR .and. mod(mstep, logfile_outfreq_7) == 0) then + + ! Weekly updates in euphotic zone (high biological activity) + call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, & + OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & + rhoSW_depth, p_depth, tempis_depth, & + REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, & + REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & + optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', & + optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + ! Update water column arrays with new carbonate chemistry CO2_watercolumn(k) = co2_depth(1) pH_watercolumn(k) = ph_depth(1) pCO2_watercolumn(k) = pco2_depth(1) @@ -369,11 +1576,39 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & kspc_watercolumn(k) = kspc_depth(1) rhoSW_watercolumn(k) = rhoSW_depth(1) - elseif (PARave < 0.01*SurfSR .and. mod(mstep,logfile_outfreq_30)==0) then - call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & - rhoSW_depth, p_depth, tempis_depth, & - REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & - optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + !=============================================================================== + ! DEEP WATER UPDATES (MONTHLY) + !=============================================================================== + ! Less frequent updates in dark deep waters where changes are slower. + ! Deep waters defined as PAR < 1% of surface irradiance. + ! + ! Physical/Chemical Drivers: + ! - Slow remineralization of sinking organic matter + ! - Calcite dissolution (below saturation horizon) + ! - Mixing and advection + ! - No photosynthesis to drive rapid changes + ! + ! Why 30-day updates? + ! - Changes occur on monthly to seasonal timescales + ! - Dominated by physical transport and slow remineralization + ! - Significant computational savings with minimal accuracy loss + ! + ! Note: Below permanent pycnocline, even longer update intervals + ! could be justified (e.g., seasonal) + !------------------------------------------------------------------------------- + + elseif (PARave < 0.01 * SurfSR .and. mod(mstep, logfile_outfreq_30) == 0) then + + ! Monthly updates in deep waters (low biological activity) + call vars_sprac(ph_depth, pco2_depth, fco2_depth, co2_depth, hco3_depth, co3_depth, & + OmegaA_depth, OmegaC_depth, kspc_depth, BetaD_depth, & + rhoSW_depth, p_depth, tempis_depth, & + REcoM_T_depth, REcoM_S_depth, REcoM_Alk_depth, REcoM_DIC_depth, & + REcoM_Si_depth, REcoM_Phos_depth, Patm_depth, dpos, Latd, Nmocsy, & + optCON='mol/m3', optT='Tpot ', optP='m ', optB='u74', & + optK1K2='l ', optKf='dg', optGAS='Pinsitu', optS='Sprc') + + ! Update water column arrays with new carbonate chemistry CO2_watercolumn(k) = co2_depth(1) pH_watercolumn(k) = ph_depth(1) pCO2_watercolumn(k) = pco2_depth(1) @@ -382,741 +1617,2376 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & OmegaC_watercolumn(k) = OmegaC_depth(1) kspc_watercolumn(k) = kspc_depth(1) rhoSW_watercolumn(k) = rhoSW_depth(1) + endif -!------------------------------------------------------------------------------- -! CO2 dependence of rates ! NEW CO2 -!------------------------------------------------------------------------------- -! Convert pH to proton concentration - h_depth(1) = 10.**(-ph_depth(1)) -! Conversion factor Cunits not needed for [H], because in model and function derived from pH and therefore in [mol/L] + !=============================================================================== + ! CO2 EFFECTS AND CALCITE DISSOLUTION + !=============================================================================== + ! Simulates ocean acidification impacts on phytoplankton growth and calcium + ! carbonate dissolution in the water column. + ! + ! This module calculates: + ! 1. CO2/pH effects on phytoplankton photosynthesis (species-specific) + ! 2. Calcite dissolution rates (saturation-state or depth-dependent) + ! + ! Key Features: + ! - Multi-component CO2 response (HCO3- benefit, CO2 toxicity, pH stress) + ! - Species-specific sensitivities to ocean acidification + ! - Two dissolution mechanisms (thermodynamic vs empirical) + ! - Velocity-dependent dissolution for sinking particles + ! + ! CO2 Response Function: + ! f(CO2) = a×[HCO3-]/(b+[HCO3-]) - exp(-c×[CO2]) - d×[H+] + ! + ! Three competing effects: + ! 1. HCO3- availability (substrate for carbon fixation) - POSITIVE + ! 2. High CO2 concentration (toxicity/stress) - NEGATIVE + ! 3. Low pH (proton stress on enzymes) - NEGATIVE + ! + ! Phytoplankton Groups: + ! - Small phytoplankton: Moderate sensitivity + ! - Diatoms: Generally tolerant + ! - Coccolithophores: High sensitivity (calcifying organisms) + ! - Phaeocystis: Variable sensitivity + ! + ! Dissolution Mechanisms: + ! A) Saturation-state dependent (OmegaC_diss = TRUE) + ! - Thermodynamically based on carbonate saturation + ! - Aumont et al. (2015) parameterization + ! B) Depth-dependent (OmegaC_diss = FALSE) + ! - Empirical dissolution rates scaled by sinking velocity + ! + ! Ecological/Biogeochemical Significance: + ! - Ocean acidification reduces calcification and alters competitive balance + ! - Dissolution releases CO2 and alkalinity back to seawater + ! - Critical for understanding climate change impacts on marine ecosystems + ! + ! References: + ! - Aumont et al. (2015) - Saturation-state dependent dissolution + ! - Schourup-Kristensen et al. (2013) - REcoM model description + !=============================================================================== + + !=============================================================================== + ! CO2 EFFECTS ON PHYTOPLANKTON GROWTH + !=============================================================================== + ! Calculates how ocean acidification (elevated CO2, reduced pH) affects + ! phytoplankton photosynthesis rates through a complex response function. + ! + ! Response Function Components: + ! 1. Michaelis-Menten HCO3- uptake (carbonate benefit) + ! 2. Exponential CO2 inhibition (high CO2 toxicity) + ! 3. Linear H+ inhibition (pH stress on cellular processes) + ! + ! Variables (Small Phytoplankton): + ! PhyCO2 : CO2 effect modifier for small phyto [0-3] + ! a_co2_phy : HCO3- uptake parameter [-] + ! b_co2_phy : HCO3- half-saturation [mmolC m-3] + ! c_co2_phy : CO2 inhibition coefficient [m3 mmolC-1] + ! d_co2_phy : H+ stress coefficient [L mol-1] + ! HCO3_watercolumn(k) : Bicarbonate concentration [mmolC m-3] + ! CO2_watercolumn(k) : Dissolved CO2 concentration [mmolC m-3] + ! pH_watercolumn(k) : Water column pH [-] + ! Cunits : Concentration units conversion factor [-] + ! h_depth(1) : Proton concentration at surface [mol L-1] + ! VTPhyCO2(k) : Diagnostic output for CO2 effect [-] + ! + ! Constraints: + ! - Upper limit: 3× enhancement (April 2022 modification) + ! - Lower limit: 0 (no negative values, July 2022 modification) + ! + ! Note: Similar calculations for diatoms, coccolithophores, and Phaeocystis + ! with species-specific parameters reflecting different sensitivities + !------------------------------------------------------------------------------- + + ! Convert pH to proton concentration for calculations + ! pH = -log10[H+], therefore [H+] = 10^(-pH) + h_depth(1) = 10.d0**(-ph_depth(1)) + + ! Note: Cunits conversion not needed for [H+] because pH is already in mol/L + + !------------------------------------------------------------------------------- + ! Small Phytoplankton CO2 Response + !------------------------------------------------------------------------------- + ! Moderate sensitivity to ocean acidification + ! Represents diverse group with varied carbon acquisition strategies -! Small phytoplankton PhyCO2 = a_co2_phy * HCO3_watercolumn(k) * Cunits / (b_co2_phy + HCO3_watercolumn(k) * Cunits) & - - exp(-c_co2_phy * CO2_watercolumn(k) * Cunits) - d_co2_phy * 10.**(-pH_watercolumn(k)) - PhyCO2 = min(PhyCO2,3.d0) ! April 2022: limitation to 3 - PhyCO2 = max(0.d0,PhyCO2) ! July 2022: limitation to zero + - exp(-c_co2_phy * CO2_watercolumn(k) * Cunits) & + - d_co2_phy * 10.d0**(-pH_watercolumn(k)) + + ! Apply empirical constraints based on observations + PhyCO2 = min(PhyCO2, 3.d0) ! Upper limit: maximum 3x enhancement + PhyCO2 = max(0.d0, PhyCO2) ! Lower limit: prevent negative growth response + + ! Store for diagnostics and output + VTPhyCO2(k) = PhyCO2 + + !------------------------------------------------------------------------------- + ! Diatoms CO2 Response + !------------------------------------------------------------------------------- + ! Generally tolerant to elevated CO2 + ! Efficient carbon concentrating mechanisms (CCMs) -! Diatoms DiaCO2 = a_co2_dia * HCO3_watercolumn(k) * Cunits / (b_co2_dia + HCO3_watercolumn(k) * Cunits) & - - exp(-c_co2_dia * CO2_watercolumn(k) * Cunits) - d_co2_dia * 10.**(-pH_watercolumn(k)) - DiaCO2 = min(DiaCO2,3.d0) ! April 2022: limitation to 3 - DiaCO2 = max(0.d0,DiaCO2) ! July 2022: limitation to zero - -#if defined (__coccos) -! Coccolithophores - CoccoCO2 = a_co2_cocco * HCO3_watercolumn(k) * Cunits / (b_co2_cocco + HCO3_watercolumn(k) * Cunits) & - - exp(-c_co2_cocco * CO2_watercolumn(k) * Cunits) - d_co2_cocco * 10.**(-pH_watercolumn(k)) - CoccoCO2 = min(CoccoCO2,3.d0) ! April 2022: limitation to 3 - CoccoCO2 = max(0.d0,CoccoCO2) ! July 2022: limitation to zero -#endif - - -!------------------------------------------------------------------------------ -! Calcite dissolution dependent on OmegaC ! DISS -!------------------------------------------------------------------------------ - Sink_Vel = Vdet_a* abs(zF(k)) + Vdet - - if (OmegaC_diss) then ! Calcdiss dependent on carbonate saturation - Ca = (0.02128d0/40.078d0) * Sali_depth(k)/1.80655d0 ! Calcium ion concentration [mol/kg], function from varsolver.f90 - CO3_sat = (kspc_watercolumn(k) / Ca) * rhoSW_watercolumn(k) ! Saturated carbonate ion concentration, converted to [mol/m3] - calc_diss = calc_diss_omegac * max(zero,(1-(CO3_watercolumn(k)/CO3_sat)))**(calc_diss_exp) ! Dissolution rate scaled by carbonate ratio, after Aumont et al. 2015 -#if defined (__3Zoo2Det) - calc_diss2 = calc_diss -#endif - calc_diss_ben = calc_diss - else ! Calcdiss dependent on depth - - calc_diss = calc_diss_rate * Sink_Vel/20.d0 ! Dissolution rate of CaCO3 scaled by the sinking velocity at the current depth -#if defined (__3Zoo2Det) -! calc_diss2 = calc_diss_rate2 ! Dissolution rate of CaCO3 scaled by the sinking velocity at the current depth seczoo - calc_diss2 = calc_diss_rate2* Sink_Vel/20.d0 -#endif - calc_diss_ben = calc_diss_rate * Sink_Vel/20.d0 ! DISS added the variable calc_diss_ben to keep the calcite dissolution in the benthos with the old formulation + - exp(-c_co2_dia * CO2_watercolumn(k) * Cunits) & + - d_co2_dia * 10.d0**(-pH_watercolumn(k)) + + ! Apply constraints + DiaCO2 = min(DiaCO2, 3.d0) ! Upper limit: 3x enhancement + DiaCO2 = max(0.d0, DiaCO2) ! Lower limit: no negative effect + + ! Store for diagnostics + VTDiaCO2(k) = DiaCO2 + + if (enable_coccos) then + + !--------------------------------------------------------------------------- + ! Coccolithophores CO2 Response + !--------------------------------------------------------------------------- + ! Calcifying phytoplankton - highly sensitive to ocean acidification + ! Both photosynthesis and calcification affected by carbonate chemistry + ! May be disadvantaged under future high-CO2 conditions + + CoccoCO2 = a_co2_cocco * HCO3_watercolumn(k) * Cunits / (b_co2_cocco + HCO3_watercolumn(k) * Cunits) & + - exp(-c_co2_cocco * CO2_watercolumn(k) * Cunits) & + - d_co2_cocco * 10.d0**(-pH_watercolumn(k)) + + ! Apply constraints + CoccoCO2 = min(CoccoCO2, 3.d0) ! Upper limit: 3x enhancement + CoccoCO2 = max(0.d0, CoccoCO2) ! Lower limit: no negative effect + + ! Store for diagnostics + VTCoccoCO2(k) = CoccoCO2 + + !--------------------------------------------------------------------------- + ! Phaeocystis CO2 Response + !--------------------------------------------------------------------------- + ! Colonial phytoplankton with variable CO2 sensitivity + ! Response may depend on bloom stage and environmental conditions + + PhaeoCO2 = a_co2_phaeo * HCO3_watercolumn(k) * Cunits / (b_co2_phaeo + HCO3_watercolumn(k) * Cunits) & + - exp(-c_co2_phaeo * CO2_watercolumn(k) * Cunits) & + - d_co2_phaeo * 10.d0**(-pH_watercolumn(k)) + + ! Apply constraints + PhaeoCO2 = min(PhaeoCO2, 3.d0) ! Upper limit: 3× enhancement + PhaeoCO2 = max(0.d0, PhaeoCO2) ! Lower limit: no negative effect + + ! Store for diagnostics + VTPhaeoCO2(k) = PhaeoCO2 + endif -!------------------------------------------------------------------------------- -!> Photosynthesis section, light parameters and rates -!------------------------------------------------------------------------------- -!< Schourup 2013 Appendix A6.2 -!< Intracellular regulation of C uptake -!< qlimitFac, qlimitFacTmp: Factor that regulates photosynthesis -!< NMinSlope: 50.d0 -!< NCmin: 0.04d0 -!< quota: PhyN/PhyC -!< qlimitFac [0.0, 1.0] -!< if quota < NCmin qlimitFac=0 -!< if quota > ≈ 9 * NCmin qlimitFac=1 -!< P_cm: 3.0d0 [1/day], Rate of C-specific photosynthesis - -!< pMax = The carbon-specific, light-saturated rate of photosynthesis [day^-1] -!< Nutrient limited environment -!< Small pyhtoplankton is limited by iron and nitrogen -!< Diatoms are additionally limited by silicon - -!< *** Small phytoplankton *** -!< *************************** - qlimitFac = recom_limiter(NMinSlope, NCmin, quota) ! Eqn A55 - feLimitFac = Fe/(k_Fe + Fe) ! Use Michaelis–Menten kinetics - qlimitFac = min(qlimitFac, feLimitFac) ! Liebig law of the minimum - pMax = P_cm * qlimitFac * arrFunc ! Maximum value of C-specific rate of photosynthesis - -!< *** Diatoms *** -!< *************** - qlimitFac = recom_limiter(NMinSlope, NCmin_d, quota_dia) + + !=============================================================================== + ! CALCITE DISSOLUTION + !=============================================================================== + ! Calculates dissolution rates of calcium carbonate (CaCO3) in seawater. + ! Dissolution depends on carbonate saturation state or depth (two modes). + ! + ! Carbonate Saturation State (Omega): + ! Ω = [CO3²⁻] / [CO3²⁻]sat + ! - Ω > 1: Supersaturated (favors precipitation, slow dissolution) + ! - Ω < 1: Undersaturated (favors dissolution) + ! + ! Variables (Saturation-dependent mode): + ! calc_diss : Primary detritus dissolution rate [day-1] + ! calc_diss2 : Secondary detritus dissolution rate [day-1] + ! calc_diss_ben : Benthic dissolution rate [day-1] + ! calc_diss_omegac : Base dissolution rate coefficient [day-1] + ! calc_diss_exp : Dissolution order exponent [-] + ! Ca : Calcium ion concentration [mol kg-1] + ! CO3_sat : Saturated carbonate concentration [mol m-3] + ! CO3_watercolumn(k) : Actual carbonate concentration [mol m-3] + ! kspc_watercolumn(k) : Solubility product for calcite [mol2 kg-2] + ! rhoSW_watercolumn(k): Seawater density [kg m-3] + ! Sali_depth(k) : Salinity [psu] + ! + ! Variables (Depth-dependent mode): + ! calc_diss_rate : Primary dissolution rate constant [day-1] + ! calc_diss_rate2 : Secondary dissolution rate constant [day-1] + ! Sink_Vel : Particle sinking velocity [m day-1] + ! Vdet_a : Depth-dependent sinking coefficient [day-1] + ! Vdet : Base sinking velocity [m day-1] + ! zF(k) : Depth at layer k [m] + ! + ! Note: Dissolution releases CO2 and alkalinity, affecting carbonate chemistry + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Calculate Sinking Velocity + !------------------------------------------------------------------------------- + ! Sinking velocity increases with depth (particle compaction, reduced drag) + + Sink_Vel = Vdet_a * abs(zF(k)) + Vdet + + if (OmegaC_diss) then + + !=========================================================================== + ! SATURATION-STATE DEPENDENT DISSOLUTION + !=========================================================================== + ! Thermodynamically-based dissolution using carbonate saturation state + ! Based on Aumont et al. (2015) parameterization + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Calculate Calcium Ion Concentration + !--------------------------------------------------------------------------- + ! Conservative element: scales linearly with salinity + ! Reference: 0.02128 mol/kg at salinity 35 psu + + Ca = (0.02128d0 / 40.078d0) * Sali_depth(k) / 1.80655d0 + + !--------------------------------------------------------------------------- + ! Calculate Saturated Carbonate Ion Concentration + !--------------------------------------------------------------------------- + ! [CO3²⁻]sat = Ksp / [Ca²+] + ! Where Ksp is the solubility product for calcite + ! Convert from mol/kg to mol/m3 using seawater density + + CO3_sat = (kspc_watercolumn(k) / Ca) * rhoSW_watercolumn(k) + + !--------------------------------------------------------------------------- + ! Calculate Dissolution Rate + !--------------------------------------------------------------------------- + ! Dissolution increases with undersaturation (Ω < 1) + ! Power law relationship: rate ∝ (1 - Ω)^n + ! Exponent (n) typically 1-4 depending on calcite form + + calc_diss = calc_diss_omegac * max(zero, (1.0 - (CO3_watercolumn(k) / CO3_sat)))**(calc_diss_exp) + + ! Apply same dissolution rate to all detritus types + ! Assumes similar calcite characteristics regardless of source + if (enable_3zoo2det) then + calc_diss2 = calc_diss ! Fast-sinking detritus + endif + calc_diss_ben = calc_diss ! Benthic detritus + + else + + !=========================================================================== + ! DEPTH-DEPENDENT DISSOLUTION + !=========================================================================== + ! Empirical dissolution rates scaled by sinking velocity + ! Simpler approach when carbonate chemistry is not fully resolved + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Primary Detritus Dissolution + !--------------------------------------------------------------------------- + ! Dissolution rate scales with sinking velocity + ! Faster sinking -> less time for dissolution per unit depth + ! Reference velocity: 20 m/day + + calc_diss = calc_diss_rate * Sink_Vel / 20.d0 + + if (enable_3zoo2det) then + !----------------------------------------------------------------------- + ! Secondary Detritus Dissolution (Fast-sinking) + !----------------------------------------------------------------------- + ! May have different dissolution characteristics than primary detritus + ! (e.g., more compact, different organic coating) + + calc_diss2 = calc_diss_rate2 * Sink_Vel / 20.d0 + endif + + !--------------------------------------------------------------------------- + ! Benthic Dissolution + !--------------------------------------------------------------------------- + ! Calcite reaching the sediment interface + ! Uses same rate as primary detritus + + calc_diss_ben = calc_diss_rate * Sink_Vel / 20.d0 + + endif + + !=============================================================================== + ! PHOTOSYNTHESIS LIMITATION FACTORS + !=============================================================================== + ! Calculates how nutrients, iron, and temperature limit maximum photosynthesis + ! rates using intracellular quota-based regulation (Droop model). + ! + ! Limitation Approach: + ! - Intracellular regulation through N:C, Si:C quotas + ! - Michaelis-Menten iron limitation + ! - Liebig's law: most limiting factor controls growth + ! + ! Variables (Small Phytoplankton): + ! qlimitFac : Combined nutrient limitation factor [0-1, 0=limited, 1=replete] + ! feLimitFac : Iron limitation factor [0-1] + ! quota : Phytoplankton N:C ratio [mmolN mmolC-1] + ! NCmin : Minimum N:C ratio (subsistence quota) [mmolN mmolC-1] + ! NMinSlope : Steepness of limitation curve [-] + ! Fe : Dissolved iron concentration [mmolFe m-3] + ! k_Fe : Half-saturation for Fe uptake [mmolFe m-3] + ! pMax : Maximum photosynthesis rate [day-1] + ! P_cm : Maximum rate constant [day-1] + ! Temp_phyto : Temperature function for small phyto [-] + ! arrFunc : Arrhenius temperature function [-] + ! + ! recom_limiter Function: + ! Returns limitation factor based on quota: + ! - Returns ~0 when quota near minimum (severely limited) + ! - Returns ~1 when quota is high (nutrient replete) + ! - Smooth transition controlled by slope parameter + ! + ! Note: Similar calculations for diatoms, coccolithophores, and Phaeocystis + ! with species-specific parameters and additional Si limitation for diatoms + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Small Phytoplankton + !------------------------------------------------------------------------------- + ! Limited by nitrogen and iron + ! Represents small flagellates, small cyanobacteria, etc. + + ! Nitrogen limitation based on intracellular N:C quota + qlimitFac = recom_limiter(NMinSlope, NCmin, quota) + + ! Iron limitation using Michaelis-Menten kinetics + ! Iron is often the limiting micronutrient in HNLC regions + feLimitFac = Fe / (k_Fe + Fe) + + ! Apply Liebig's law: most limiting nutrient controls photosynthesis + qlimitFac = min(qlimitFac, feLimitFac) + + ! Calculate maximum photosynthesis rate with temperature correction + if (enable_coccos) then + ! Use species-specific temperature function (when cocco module active) + pMax = qlimitFac * Temp_phyto + else + ! Use standard Arrhenius temperature function + pMax = P_cm * qlimitFac * arrFunc + endif + + !------------------------------------------------------------------------------- + ! Diatoms + !------------------------------------------------------------------------------- + ! Limited by nitrogen, silicon, and iron + ! Large phytoplankton with silica frustules (shells) + + ! Nitrogen limitation + qlimitFac = recom_limiter(NMinSlope, NCmin_d, quota_dia) + + ! Silicon limitation (unique to diatoms) + ! Required for frustule formation - critical for diatom growth qlimitFacTmp = recom_limiter(SiMinSlope, SiCmin, qSiC) - qlimitFac = min(qLimitFac, qlimitFacTmp) - feLimitFac = Fe/(k_Fe_d + Fe) - qlimitFac = min(qlimitFac, feLimitFac) - pMax_dia = P_cm_d * qlimitFac * arrFunc - -!< *** Coccolithophores *** -!< ************************ -#if defined (__coccos) - qlimitFac = recom_limiter(NMinSlope, NCmin_c, quota_cocco) - feLimitFac = Fe/(k_Fe_c + Fe) - qlimitFac = min(qlimitFac, feLimitFac) - pMax_cocco = P_cm_c * qlimitFac * CoccoTFunc ! Here the T dependency is changed -#endif -!------------------------------------------------------------------------------- -!< *** Small phytoplankton photosynthesis rate *** -!< *********************************************** - if (pMax .lt. tiny .OR. PARave /= PARave .OR. CHL2C /= CHL2C) then ! OG in case of only respiration, i.e. darkness?? + qlimitFac = min(qlimitFac, qlimitFacTmp) + + ! Iron limitation + feLimitFac = Fe / (k_Fe_d + Fe) + qlimitFac = min(qlimitFac, feLimitFac) + + ! Calculate maximum photosynthesis rate + if (enable_coccos) then + pMax_dia = qlimitFac * Temp_diatoms + else + pMax_dia = P_cm_d * qlimitFac * arrFunc + endif + + !------------------------------------------------------------------------------- + ! Coccolithophores (Optional) + !------------------------------------------------------------------------------- + ! Limited by nitrogen and iron + ! Calcifying phytoplankton that produce calcite plates + + if (enable_coccos) then + + ! Nitrogen limitation + qlimitFac = recom_limiter(NMinSlope, NCmin_c, quota_cocco) + + ! Iron limitation + feLimitFac = Fe / (k_Fe_c + Fe) + qlimitFac = min(qlimitFac, feLimitFac) + + ! Calculate maximum photosynthesis rate + pMax_cocco = qlimitFac * Temp_cocco + + !--------------------------------------------------------------------------- + ! Phaeocystis (Optional) + !--------------------------------------------------------------------------- + ! Limited by nitrogen and iron + ! Colonial phytoplankton that can form large blooms + + ! Nitrogen limitation + qlimitFac = recom_limiter(NMinSlope, NCmin_p, quota_phaeo) + + ! Iron limitation + feLimitFac = Fe / (k_Fe_p + Fe) + qlimitFac = min(qlimitFac, feLimitFac) + + ! Calculate maximum photosynthesis rate + pMax_phaeo = qlimitFac * Temp_phaeo + + endif + + !=============================================================================== + ! LIGHT-DEPENDENT PHOTOSYNTHESIS RATE CALCULATIONS + !=============================================================================== + ! Calculates actual photosynthesis rates using photosynthesis-irradiance (P-I) + ! curves. Uses exponential saturation model (no photoinhibition). + ! + ! P-I Curve Model: + ! P = Pmax × (1 - exp(-α × Chl:C × PAR / Pmax)) + ! + ! Where: + ! P : Actual photosynthesis rate [day-1] + ! Pmax : Maximum rate (nutrient and temperature limited) [day-1] + ! α : Initial slope of P-I curve (photosynthetic efficiency) [-] + ! Chl:C : Chlorophyll to carbon ratio [mgChl mmolC-1] + ! PAR : Photosynthetically active radiation [W m-2] + ! + ! Variables (Small Phytoplankton): + ! Cphot : Carbon-specific photosynthesis rate [day-1] + ! PARave : Average PAR in mixed layer [W m-2] + ! alfa : Initial slope parameter [-] + ! Chl2C : Chlorophyll:Carbon ratio [mgChl mmolC-1] + ! PhyCO2 : CO2 limitation factor [0-1] + ! VTCphotLigLim_phyto : Light limitation factor for diagnostics [0-1] + ! VTCphot_phyto : Final photosynthesis rate for diagnostics [day-1] + ! + ! Safety Checks: + ! - Check for darkness (pMax < tiny) + ! - Check for NaN values (PARave /= PARave) + ! - Check for valid Chl:C ratios + ! + ! Note: Similar calculations for all phytoplankton types + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Small Phytoplankton Photosynthesis + !------------------------------------------------------------------------------- + + if (pMax < tiny .OR. PARave /= PARave .OR. CHL2C /= CHL2C) then + ! No photosynthesis in darkness or under invalid conditions Cphot = zero else - Cphot = pMax*(real(one) - exp(-alfa * Chl2C * PARave / pMax)) - if (CO2lim) Cphot = Cphot * PhyCO2 ! Added the CO2 dependence - end if - if (Cphot .lt. tiny) Cphot = zero + ! Calculate photosynthesis using exponential P-I curve + ! Model saturates at high light (no photoinhibition) + Cphot = pMax * (1.0d0 - exp(-alfa * Chl2C * PARave / pMax)) + + ! Store light limitation factor for diagnostics + ! Ratio of actual to maximum rate indicates light limitation severity + VTCphotLigLim_phyto(k) = Cphot / pMax + + ! Apply CO2 limitation if ocean acidification sensitivity is enabled + if (CO2lim) Cphot = Cphot * PhyCO2 + endif + + ! Ensure non-negative values (numerical safety) + if (Cphot < tiny) Cphot = zero -!< *** Diatom photosynthesis rate *** -!< ********************************** - if ( pMax_dia .lt. tiny .OR. PARave /= PARave .OR. CHL2C_dia /= CHL2C_dia) then + ! Store final photosynthesis rate for diagnostics and output + VTCphot_phyto(k) = Cphot + + !------------------------------------------------------------------------------- + ! Diatom Photosynthesis + !------------------------------------------------------------------------------- + + if (pMax_dia < tiny .OR. PARave /= PARave .OR. CHL2C_dia /= CHL2C_dia) then Cphot_dia = zero else - Cphot_dia = pMax_dia * (real(one) - exp(-alfa_d * Chl2C_dia * PARave / pMax_dia)) - if (CO2lim) Cphot_dia = Cphot_dia * DiaCO2 ! Added the CO2 dependence - end if - if (Cphot_dia .lt. tiny) Cphot_dia = zero - -!< *** Coccolithophore photosynthesis rate *** -!< ******************************************* -#if defined (__coccos) - if ( pMax_cocco .lt. tiny .OR. Parave /= Parave .OR. CHL2C_cocco /= CHL2C_cocco) then - Cphot_cocco = zero - else - Cphot_cocco = pMax_cocco * (real(one) - exp( -alfa_c * Chl2C_cocco * PARave / pMax_cocco)) - if (CO2lim) Cphot_cocco = Cphot_cocco * CoccoCO2 ! Added the CO2 dependence - end if - if (Cphot_cocco .lt. tiny) Cphot_cocco = zero -#endif -!------------------------------------------------------------------------------- -!< chlorophyll degradation -!------------------------------------------------------------------------------- - KOchl = deg_Chl - KOchl_dia = deg_Chl_d -#if defined (__coccos) - KOchl_cocco = deg_Chl_c -#endif - + ! Diatom P-I curve with species-specific parameters + Cphot_dia = pMax_dia * (1.0 - exp(-alfa_d * Chl2C_dia * PARave / pMax_dia)) + + ! Store light limitation diagnostic + VTCphotLigLim_diatoms(k) = Cphot_dia / pMax_dia + + ! Apply CO2 limitation + if (CO2lim) Cphot_dia = Cphot_dia * DiaCO2 + endif + + if (Cphot_dia < tiny) Cphot_dia = zero + VTCphot_diatoms(k) = Cphot_dia + + !------------------------------------------------------------------------------- + ! Coccolithophore Photosynthesis (Optional) + !------------------------------------------------------------------------------- + + if (enable_coccos) then + + if (pMax_cocco < tiny .OR. PARave /= PARave .OR. CHL2C_cocco /= CHL2C_cocco) then + Cphot_cocco = zero + else + ! Coccolithophore P-I curve + Cphot_cocco = pMax_cocco * (1.0 - exp(-alfa_c * Chl2C_cocco * PARave / pMax_cocco)) + + ! Store light limitation diagnostic + VTCphotLigLim_cocco(k) = Cphot_cocco / pMax_cocco + + ! Apply CO2 limitation + if (CO2lim) Cphot_cocco = Cphot_cocco * CoccoCO2 + endif + + if (Cphot_cocco < tiny) Cphot_cocco = zero + VTCphot_cocco(k) = Cphot_cocco + + !--------------------------------------------------------------------------- + ! Phaeocystis Photosynthesis (Optional) + !--------------------------------------------------------------------------- + + if (pMax_phaeo < tiny .OR. PARave /= PARave .OR. CHL2C_phaeo /= CHL2C_phaeo) then + Cphot_phaeo = zero + else + ! Phaeocystis P-I curve + Cphot_phaeo = pMax_phaeo * (1.0 - exp(-alfa_p * Chl2C_phaeo * PARave / pMax_phaeo)) + + ! Store light limitation diagnostic + VTCphotLigLim_phaeo(k) = Cphot_phaeo / pMax_phaeo + + ! Apply CO2 limitation + if (CO2lim) Cphot_phaeo = Cphot_phaeo * PhaeoCO2 + endif + + if (Cphot_phaeo < tiny) Cphot_phaeo = zero + VTCphot_phaeo(k) = Cphot_phaeo + + endif + + !=============================================================================== + ! CHLOROPHYLL DEGRADATION + !=============================================================================== + ! Calculates chlorophyll degradation rates with optional photodamage effects. + ! Chlorophyll degrades due to senescence and light-induced damage. + ! + ! Two Modes: + ! A) Base degradation: Constant rate (use_photodamage = FALSE) + ! B) Photodamage-dependent: Light-dependent rate (use_photodamage = TRUE) + ! + ! Variables: + ! KOchl : Chlorophyll degradation rate for small phyto [day-1] + ! KOchl_dia : Chlorophyll degradation rate for diatoms [day-1] + ! KOchl_cocco : Chlorophyll degradation rate for coccos [day-1] + ! KOchl_phaeo : Chlorophyll degradation rate for Phaeocystis [day-1] + ! deg_Chl : Base degradation rate constant [day-1] + ! CHL2C_plast : Chlorophyll:Carbon ratio in plastids [mgChl mmolC-1] + ! alfa : P-I curve initial slope [-] + ! PARave : Average PAR [W m-2] + ! pMax : Maximum photosynthesis rate [day-1] + ! + ! Photodamage Model: + ! - High light damages photosystem II and degrades chlorophyll + ! - Uses same exponential form as P-I curve (saturating damage) + ! - Minimum degradation rate (10% of base) in darkness + ! - No upper cap (commented out safety constraint) + ! + ! Note: Photodamage increases chlorophyll turnover at high light + ! This helps prevent photoinhibition and photooxidative stress + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Set Base Chlorophyll Degradation Rates + !------------------------------------------------------------------------------- + ! Constant degradation rates independent of light (senescence) + + KOchl = deg_Chl ! Small phytoplankton + KOchl_dia = deg_Chl_d ! Diatoms + + if (enable_coccos) then + KOchl_cocco = deg_Chl_c ! Coccolithophores + KOchl_phaeo = deg_Chl_p ! Phaeocystis + endif + if (use_photodamage) then -!< add a minimum value for photodamage -!< *** Phytoplankton Chla loss *** -!< ******************************* - if (pMax .lt. tiny .OR. PARave /= PARave .OR. CHL2C_plast /= CHL2C_plast) then - KOchl = deg_Chl*0.1d0 + + !=========================================================================== + ! PHOTODAMAGE-DEPENDENT DEGRADATION + !=========================================================================== + ! Light-dependent chlorophyll degradation using saturation model + ! Higher light intensity increases chlorophyll turnover + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Small Phytoplankton Chlorophyll Loss + !--------------------------------------------------------------------------- + + if (pMax < tiny .OR. PARave /= PARave .OR. CHL2C_plast /= CHL2C_plast) then + ! Minimum degradation in darkness (10% of base rate) + KOchl = deg_Chl * 0.1d0 else - KOchl = deg_Chl*(real(one) - exp(-alfa * CHL2C_plast * PARave / pMax)) - KOchl = max((deg_Chl*0.1d0), KOchl) + ! Saturation model: degradation increases with light + ! Uses same exponential form as P-I curve + KOchl = deg_Chl * (real(one) - exp(-alfa * CHL2C_plast * PARave / pMax)) + + !< Alternative linear model (commented out): + !< Degradation directly proportional to light intensity + !KOchl = deg_Chl * CHL2C_plast * PARave + + ! Ensure minimum degradation rate (10% of base) + KOchl = max((deg_Chl * 0.1d0), KOchl) + + !< Safety constraint (commented out): + !< Caps maximum degradation at 0.3 day-1 + !KOchl = min(KOchl, 0.3d0) end if -!< *** Diatoms Chla loss *** -!< ************************* - if (pMax_dia .lt. tiny .OR. PARave /= PARave .OR. CHL2C_plast_dia /= CHL2C_plast_dia) then - KOchl_dia = deg_Chl_d*0.1d0 + + !--------------------------------------------------------------------------- + ! Diatom Chlorophyll Loss + !--------------------------------------------------------------------------- + + if (pMax_dia < tiny .OR. PARave /= PARave .OR. CHL2C_plast_dia /= CHL2C_plast_dia) then + KOchl_dia = deg_Chl_d * 0.1d0 else - KOchl_dia = deg_Chl_d * (real(one) - exp(-alfa_d * CHL2C_plast_dia * PARave / pMax_dia )) - KOchl_dia = max((deg_Chl_d*0.1d0), KOchl_dia) - end if -!< *** Coccolithophores chla loss *** -!< ********************************** -#if defined (__coccos) - if (pMax_cocco .lt. tiny .OR. PARave /= Parave .OR. CHL2C_plast_cocco /= CHL2C_plast_cocco) then - KOchl_cocco = deg_Chl_c*0.1d0 - else - KOchl_cocco = deg_Chl_c * (real(one) - exp( -alfa_c * CHL2C_plast_cocco * PARave / pMax_cocco )) - KOchl_cocco = max((deg_Chl_c*0.1d0), KOchl_cocco) - end if -#endif - if (KOchl /= KOchl) then - print*,' KOchl is ', KOchl - print*,' deg_Chl is ', deg_Chl - print*,' alfa is ', alfa - print*,' CHL2C is ', CHL2C_plast - print*,' PARave is ', PARave - print*,' pMax is ', pMax - stop + ! Diatom-specific photodamage model + KOchl_dia = deg_Chl_d * (real(one) - exp(-alfa_d * CHL2C_plast_dia * PARave / pMax_dia)) + + !KOchl_dia = deg_Chl_d * CHL2C_plast_dia * PARave + + KOchl_dia = max((deg_Chl_d * 0.1d0), KOchl_dia) + !KOchl_dia = min(KOchl_dia, 0.3d0) end if - if (KOchl_dia /= KOchl_dia) then - print*,' KOchl_dia is ', KOchl_dia - print*,' deg_Chl_d is ', deg_Chl_d - print*,' alfa_d is ', alfa_d - print*,' CHL2C_d is ', CHL2C_plast_dia - print*,' PARave is ', PARave - print*,' pMax_d is ', pMax_dia + + if (enable_coccos) then + + !----------------------------------------------------------------------- + ! Coccolithophore Chlorophyll Loss + !----------------------------------------------------------------------- + + if (pMax_cocco < tiny .OR. PARave /= PARave .OR. CHL2C_plast_cocco /= CHL2C_plast_cocco) then + KOchl_cocco = deg_Chl_c * 0.1d0 + else + ! Coccolithophore-specific photodamage model + KOchl_cocco = deg_Chl_c * (real(one) - exp(-alfa_c * CHL2C_plast_cocco * PARave / pMax_cocco)) + + !KOchl_cocco = deg_Chl_c * CHL2C_plast_cocco * PARave + + KOchl_cocco = max((deg_Chl_c * 0.1d0), KOchl_cocco) + !KOchl_cocco = min(KOchl_cocco, 0.3d0) + end if + + !----------------------------------------------------------------------- + ! Phaeocystis Chlorophyll Loss + !----------------------------------------------------------------------- + + if (pMax_phaeo < tiny .OR. PARave /= PARave .OR. CHL2C_plast_phaeo /= CHL2C_plast_phaeo) then + KOchl_phaeo = deg_Chl_p * 0.1d0 + else + ! Phaeocystis-specific photodamage model + KOchl_phaeo = deg_Chl_p * (real(one) - exp(-alfa_p * CHL2C_plast_phaeo * PARave / pMax_phaeo)) + + !KOchl_phaeo = deg_Chl_p * CHL2C_plast_phaeo * PARave + + KOchl_phaeo = max((deg_Chl_p * 0.1d0), KOchl_phaeo) + !KOchl_phaeo = min(KOchl_phaeo, 0.3d0) + end if + + endif ! enable_coccos + + endif ! use_photodamage + + !--------------------------------------------------------------------------- + ! ERROR CHECKING AND DEBUGGING + ! Check for NaN values in chlorophyll degradation rates + !--------------------------------------------------------------------------- + + ! Small phytoplankton + if (KOchl /= KOchl) then + print*, 'ERROR: KOchl is NaN' + print*, ' deg_Chl =', deg_Chl + print*, ' alfa =', alfa + print*, ' CHL2C_plast =', CHL2C_plast + print*, ' PARave =', PARave + print*, ' pMax =', pMax + stop + end if + + ! Diatoms + if (KOchl_dia /= KOchl_dia) then + print*, 'ERROR: KOchl_dia is NaN' + print*, ' deg_Chl_d =', deg_Chl_d + print*, ' alfa_d =', alfa_d + print*, ' CHL2C_plast_dia =', CHL2C_plast_dia + print*, ' PARave =', PARave + print*, ' pMax_dia =', pMax_dia + stop + end if + + ! Additional species (if enabled) + if (enable_coccos) then + if (KOchl_cocco /= KOchl_cocco) then + print*, 'ERROR: KOchl_cocco is NaN' + print*, ' deg_Chl_c =', deg_Chl_c + print*, ' alfa_c =', alfa_c + print*, ' CHL2C_plast_cocco =', CHL2C_plast_cocco + print*, ' PARave =', PARave + print*, ' pMax_cocco =', pMax_cocco stop end if -#if defined (__coccos) - if (KOchl_cocco /= KOchl_cocco) then - print*,' KOchl_cocco is ', KOchl_cocco - print*,' deg_Chl_c is ', deg_Chl_c - print*,' alfa_c is ', alfa_c - print*,' CHL2C_c is ', CHL2C_plast_cocco - print*,' PARave is ', PARave - print*,' pMax_c is ', pMax_cocco + + if (KOchl_phaeo /= KOchl_phaeo) then + print*, 'ERROR: KOchl_phaeo is NaN' + print*, ' deg_Chl_p =', deg_Chl_p + print*, ' alfa_p =', alfa_p + print*, ' CHL2C_plast_phaeo =', CHL2C_plast_phaeo + print*, ' PARave =', PARave + print*, ' pMax_phaeo =', pMax_phaeo stop - end if -#endif - end if ! photodamage - -!------------------------------------------------------------------------------- -!> Assimilation section -!------------------------------------------------------------------------------- + end if + endif -!< Nitrogen and silicon part -!< Compute assimilation from Geider et al 1998 -!< V_cm: Scaling factor for C-specific N uptake, dimensionless -!< NCmax: Maximum cell quota of nitrogen (N:C) [mmol N/mmol C] -!< NMaxSlope: Max slope for limiting function -!< NCuptakeRatio: Maximum uptake ratio N:C [mmol N mmol C−1] -!< SiCUptakeRatio: Maximum uptake ratio Si : C [mmol Si mmol C−1 ] -!< The N:C ratio is taken into account, as a -!! too high ratio indicates that the intracellular -!! concentration of energy rich carbon molecules becomes too low to -!! use energy on silicon uptake. - - V_cm = V_cm_fact - limitFacN = recom_limiter(NMaxSlope, quota, NCmax) - N_assim = V_cm * pMax * NCuptakeRatio & ! [mmol N / (mmol C * day)] - * limitFacN * (DIN/(DIN + k_din)) ! Michaelis–Menten kinetics - - V_cm = V_cm_fact_d - limitFacN_dia = recom_limiter(NMaxSlope, quota_dia, NCmax_d) - N_assim_dia = V_cm * pMax_dia * NCUptakeRatio_d & - * limitFacN_dia * DIN/(DIN + k_din_d) - -#if defined (__coccos) - V_cm = V_cm_fact_c + !=============================================================================== + ! PHYTOPLANKTON ASSIMILATION SECTION + !=============================================================================== + ! Computes nutrient uptake, chlorophyll synthesis, and respiration rates + ! for multiple phytoplankton functional types following Geider et al. 1998 + !=============================================================================== + + !=============================================================================== + ! NITROGEN ASSIMILATION + !=============================================================================== + ! Calculates nitrogen uptake rates for all phytoplankton groups based on + ! nutrient availability, cell quota status, and maximum uptake capacity + ! + ! Key Parameters: + ! V_cm_fact : Scaling factor for C-specific N uptake [-] + ! NCmax : Maximum cell quota of nitrogen (N:C) [mmolN mmolC-1] + ! NMaxSlope : Maximum slope for quota limiting function [-] + ! NCuptakeRatio : Maximum uptake ratio N:C [mmolN mmolC-1] + ! k_din : Half-saturation constant for DIN uptake [mmolN m-3] + ! pMax : Maximum photosynthesis rate [day-1] + ! + ! Note: Cell quota limiting function prevents luxury N uptake when internal + ! N:C ratio approaches maximum capacity + !------------------------------------------------------------------------------- + + ! --- Small phytoplankton Nitrogen Uptake --- + V_cm = V_cm_fact + limitFacN = recom_limiter(NMaxSlope, quota, NCmax) + N_assim = V_cm * pMax * NCuptakeRatio * limitFacN * (DIN/(DIN + k_din)) + + ! --- Diatom Nitrogen Uptake --- + V_cm = V_cm_fact_d + limitFacN_dia = recom_limiter(NMaxSlope, quota_dia, NCmax_d) + N_assim_dia = V_cm * pMax_dia * NCUptakeRatio_d * limitFacN_dia * DIN/(DIN + k_din_d) + + ! --- Optional Coccolithophore and Phaeocystis Groups --- + if (enable_coccos) then + ! Coccolithophore nitrogen uptake + V_cm = V_cm_fact_c limitFacN_cocco = recom_limiter(NMaxSlope, quota_cocco, NCmax_c) - N_assim_cocco = V_cm * pMax_cocco * NCUptakeRatio_c & - * limitFacN_cocco * DIN/(DIN + k_din_c) -#endif + N_assim_cocco = V_cm * pMax_cocco * NCUptakeRatio_c * limitFacN_cocco * & + DIN/(DIN + k_din_c) + + ! Phaeocystis nitrogen uptake + V_cm = V_cm_fact_p + limitFacN_phaeo = recom_limiter(NMaxSlope, quota_phaeo, NCmax_p) + N_assim_phaeo = V_cm * pMax_phaeo * NCUptakeRatio_p * limitFacN_phaeo * & + DIN/(DIN + k_din_p) + endif - limitFacSi = recom_limiter(SiMaxSlope, qSiC, SiCmax) & - * limitFacN_dia - Si_assim = V_cm_fact_d * P_cm_d * arrFunc * SiCUptakeRatio & - * limitFacSi * Si/(Si + k_si) + !=============================================================================== + ! SILICON ASSIMILATION (DIATOMS ONLY) + !=============================================================================== + ! Calculates silicate uptake for diatom frustule formation + ! + ! Key Parameters: + ! SiCUptakeRatio : Maximum uptake ratio Si:C [mmolSi mmolC-1] + ! SiCmax : Maximum cell quota of silicon (Si:C) [mmolSi mmolC-1] + ! SiMaxSlope : Maximum slope for Si quota limiting function [-] + ! k_si : Half-saturation constant for Si uptake [mmolSi m-3] + ! P_cm_d : Maximum photosynthesis rate for diatoms [day-1] + ! + ! Note: Silicon uptake is coupled to nitrogen status - high N:C ratios indicate + ! low intracellular energy reserves, limiting energy-intensive Si uptake + !------------------------------------------------------------------------------- + + limitFacSi = recom_limiter(SiMaxSlope, qSiC, SiCmax) * limitFacN_dia + + if (.NOT. enable_coccos) then + ! Standard silicon assimilation formulation + Si_assim = V_cm_fact_d * P_cm_d * arrFunc * SiCUptakeRatio * limitFacSi * & + Si/(Si + k_si) + else + ! Alternative formulation with temperature dependence + Si_assim = V_cm_fact_d * Temp_diatoms * SiCUptakeRatio * limitFacSi * & + Si/(Si + k_si) + VTSi_assimDia(k) = Si_assim + endif -!------------------------------------------------------------------------------- -!< *** Iron chemistry *** -!< ********************** -! select the method to calculate freeFe - freeFe = iron_chemistry(Fe,totalligand,ligandStabConst) -!------------------------------------------------------------------------------- -!< *** Chlorophyll synthesis *** -!< ***************************** + !=============================================================================== + ! 3. IRON CHEMISTRY + !=============================================================================== + ! Computes free (bioavailable) iron concentration from total dissolved iron + ! accounting for complexation with organic ligands + ! + ! Variables: + ! Fe : Total dissolved iron [µmol m-3] + ! totalligand : Total organic ligand concentration [µmol m-3] + ! ligandStabConst : Conditional stability constant [M-1] + ! freeFe : Free (inorganic) iron concentration [µmol m-3] + !------------------------------------------------------------------------------- + + freeFe = iron_chemistry(Fe, totalligand, ligandStabConst) + + !=============================================================================== + ! 4. CHLOROPHYLL SYNTHESIS + !=============================================================================== + ! Calculates chlorophyll production coupled to nitrogen assimilation + ! following photoacclimation theory (Geider et al. 1998) + ! + ! Key Parameters: + ! Chl2N_max : Maximum Chl:N ratio [mg Chl mmolN-1] + ! Chl2C : Chlorophyll to carbon ratio [mg Chl mmolC-1] + ! alfa : Initial slope of P-I curve [mmolC (mg Chl)-1 m2 µmol-1 day-1] + ! Cphot : Carbon-specific photosynthesis rate [day-1] + ! PARave : Depth-averaged photosynthetically available radiation [µmol m-2 s-1] + ! + ! Note: Chlorophyll synthesis is down-regulated when light is sufficient, + ! preventing over-investment in light-harvesting machinery + !------------------------------------------------------------------------------- + + ! --- Small phytoplankton Chlorophyll Synthesis --- + chlSynth = zero + if (PARave >= tiny .AND. PARave == PARave) then + chlSynth = N_assim * Chl2N_max * & + min(real(one), Cphot/(alfa * Chl2C * PARave)) + endif -!< Coupled to N uptake -!< Converted to chlorophyll units with a maximum Chl:N ratio, Chl2N_max -!< Chl2N_max: Maximum Chl:N ratio for phytoplankton [mg Chl mmol N−1 ] + ! --- Diatom Chlorophyll Synthesis --- + ChlSynth_dia = zero + if (PARave >= tiny .AND. PARave == PARave) then + ChlSynth_dia = N_assim_dia * Chl2N_max_d * & + min(real(one), Cphot_dia / (alfa_d * Chl2C_dia * PARave)) + end if - chlSynth = zero - if (PARave .ge. tiny .AND. PARave .eq. PARave) then - chlSynth = N_assim * Chl2N_max & - * min(real(one),Cphot/(alfa * Chl2C * PARave)) - end if - ChlSynth_dia = zero - if (PARave .ge. tiny .AND. PARave .eq. PARave) then - ChlSynth_dia = N_assim_dia * Chl2N_max_d & - * min(real(one),Cphot_dia /(alfa_d * Chl2C_dia * PARave)) - end if + ! --- Optional Coccolithophore and Phaeocystis Chlorophyll Synthesis --- + if (enable_coccos) then + ! Coccolithophore chlorophyll synthesis ChlSynth_cocco = zero -#if defined (__coccos) - if (PARave .ge. tiny .AND. PARave .eq. PARave) then - ChlSynth_cocco = N_assim_cocco * Chl2N_max_c & - * min(real(one),Cphot_cocco /(alfa_c * Chl2C_cocco * PARave)) - end if -#endif -!------------------------------------------------------------------------------- -!< *** Phytoplankton respiraion rate *** -!< ************************************* + if (PARave >= tiny .AND. PARave == PARave) then + ChlSynth_cocco = N_assim_cocco * Chl2N_max_c * & + min(real(one), Cphot_cocco / (alfa_c * Chl2C_cocco * PARave)) + end if -!< res_phy: Maintenance respiration rate constant [day−1 ] -!< biosynth: The cost of biosynthesis of N [mmol C mmol N−1 ] + ! Phaeocystis chlorophyll synthesis + ChlSynth_phaeo = zero + if (PARave >= tiny .AND. PARave == PARave) then + ChlSynth_phaeo = N_assim_phaeo * Chl2N_max_p * & + min(real(one), Cphot_phaeo/(alfa_p * Chl2C_phaeo * PARave)) + end if + endif - phyRespRate = res_phy * limitFacN + biosynth * N_assim - phyRespRate_dia = res_phy_d * limitFacN_dia + biosynth * N_assim_dia + biosynthSi * Si_assim -#if defined (__coccos) + !=============================================================================== + ! 5. PHYTOPLANKTON RESPIRATION RATES + !=============================================================================== + ! Computes carbon loss through maintenance respiration and biosynthetic costs + ! + ! Key Parameters: + ! res_phy : Maintenance respiration rate constant [day-1] + ! biosynth : Biosynthetic cost of nitrogen assimilation [mmolC mmolN-1] + ! biosynthSi : Biosynthetic cost of silicon assimilation [mmolC mmolSi-1] + ! + ! Components: + ! 1. Maintenance respiration: Quota-dependent baseline metabolic cost + ! 2. Biosynthetic costs: Additional respiration for nutrient assimilation + ! + ! Equation: R = res_phy * limitFacN + biosynth * N_assim + biosynthSi * Si_assim + !------------------------------------------------------------------------------- + + ! --- Small phytoplankton Respiration --- + phyRespRate = res_phy * limitFacN + biosynth * N_assim + + ! --- Diatom Respiration (includes silicon biosynthesis cost) --- + phyRespRate_dia = res_phy_d * limitFacN_dia + biosynth * N_assim_dia + & + biosynthSi * Si_assim + + ! --- Optional Coccolithophore and Phaeocystis Respiration --- + if (enable_coccos) then phyRespRate_cocco = res_phy_c * limitFacN_cocco + biosynth * N_assim_cocco -#endif + phyRespRate_phaeo = res_phy_p * limitFacN_phaeo + biosynth * N_assim_phaeo + endif -!------------------------------------------------------------------------------- -! Mesozooplankton -!------------------------------------------------------------------------------- -!< Grazing on small phytoplankton, diatoms, coccolithophore (optional), -!< microzooplankton (optional), slow- and fast-sinking detritus - -!< *** Food availability *** -!< ************************* -!< pzPhy: Maximum nanophytoplankton preference -!< pzDia: Maximum diatom preference -!< pzCocco: Maximum coccolithophore preference -!< pzDet: Maximum slow-sinking detritus prefence by first zooplankton -!< pzDetZ2: Maximum fast-sinking detritus preference by first zooplankton -!< pzMicZoo: Maximum microzooplankton preference by first zooplankton - - if (REcoM_Grazing_Variable_Preference) then ! CHECK ONUR - aux = pzPhy*PhyN + pzDia*DiaN - if (Grazing_detritus) aux = aux + PzDet*DetN -#if defined (__3Zoo2Det) - if (Grazing_detritus) aux = aux + pzDetZ2*DetZ2N ! 2Det - aux = aux + pzMicZoo*MicZooN ! 3Zoo -#endif -#if defined (__coccos) - aux = aux + pzCocco*CoccoN -#endif -! ****************************************************************************** - varpzPhy = (pzPhy*PhyN)/aux - varpzDia = (pzDia*DiaN)/aux - if (Grazing_detritus) varpzDet = (pzDet*DetN)/aux -#if defined (__3Zoo2Det) - if (Grazing_detritus) varpzDetZ2 = (pzDetZ2*DetZ2N)/aux ! 2Det - varpzMicZoo = (pzMicZoo*MicZooN)/aux ! 3Zoo -#endif -#if defined (__coccos) - varpzCocco = (pzCocco*CoccoN)/aux -#endif -! ****************************************************************************** - fDiaN = varpzDia * DiaN - fPhyN = varpzPhy * PhyN - if (Grazing_detritus) fDetN = varpzDet * DetN -#if defined (__3Zoo2Det) - if (Grazing_detritus) fDetZ2N = varpzDetZ2 * DetZ2N ! 2Det - fMicZooN = varpzMicZoo * MicZooN ! 3Zoo -#endif -#if defined (__coccos) - fCoccoN = varpzCocco * CoccoN -#endif - else ! REcoM_Grazing_Variable_Preference = .false. - fPhyN = pzPhy * PhyN - fDiaN = pzDia * DiaN - if (Grazing_detritus) fDetN = pzDet * DetN -#if defined (__3Zoo2Det) - if (Grazing_detritus) fDetZ2N = pzDetZ2 * DetZ2N ! 2Det - fMicZooN = pzMicZoo * MicZooN ! 3Zoo -#endif -#if defined (__coccos) - fCoccoN = pzCocco * CoccoN -#endif - end if ! REcoM_Grazing_Variable_Preference + !=============================================================================== + ! MESOZOOPLANKTON GRAZING + !=============================================================================== + ! Simulates mesozooplankton grazing on multiple prey types using a Holling + ! Type III functional response with food-dependent preferences and efficiency. + ! + ! This module calculates: + ! 1. Food availability and grazing preferences (fixed or variable) + ! 2. Total grazing flux with Holling Type III response + ! 3. Distribution of grazing among prey types + ! 4. Food-dependent grazing efficiency + ! 5. Carbon flux from grazed prey to mesozooplankton + ! + ! Key Features: + ! - Variable or fixed prey preferences + ! - Optional prey types (coccolithophores, microzooplankton, detritus) + ! - Temperature-dependent grazing rate (Q10 or Arrhenius) + ! - Food-dependent assimilation efficiency + ! + ! References: + ! - Schourup-Kristensen et al. (2013) - REcoM model description + !=============================================================================== + + !=============================================================================== + ! 1. FOOD AVAILABILITY AND GRAZING PREFERENCES + !=============================================================================== + ! Calculates which prey types are available and their relative preferences. + ! Two modes: + ! - Variable preferences: Adjust based on relative prey abundance + ! - Fixed preferences: Use constant maximum preference values + ! + ! Variables: + ! pzPhy, pzDia : Max preference for small phyto and diatoms [-] + ! pzCocco, pzPhaeo: Max preference for coccoliths and Phaeocystis [-] + ! pzDet, pzDetZ2 : Max preference for slow/fast sinking detritus [-] + ! pzMicZoo : Max preference for microzooplankton [-] + ! PhyN, DiaN : Small phytoplankton and diatom nitrogen [mmolN m-3] + ! CoccoN, PhaeoN : Coccolithophore and Phaeocystis nitrogen [mmolN m-3] + ! DetN, DetZ2N : Slow and fast sinking detritus nitrogen [mmolN m-3] + ! MicZooN : Microzooplankton nitrogen [mmolN m-3] + ! varpz* : Variable preferences (calculated from availability) [-] + ! f*N : Available food pools (preference × concentration) [mmolN m-3] + ! aux : Total weighted food availability [mmolN m-3] + ! + ! Logic: + ! IF variable preferences: varpz_i = (pz_i × prey_i) / Σ(pz_j × prey_j) + ! ELSE: Use fixed maximum preferences (pz_i) + ! Food pools: f_i = preference_i × prey_i + !------------------------------------------------------------------------------- + + if (REcoM_Grazing_Variable_Preference) then + !--------------------------------------------------------------------------- + ! VARIABLE PREFERENCE MODE + ! Preferences scale with relative abundance of each prey type + !--------------------------------------------------------------------------- + + ! Calculate total weighted food availability (denominator) + aux = pzPhy * PhyN + pzDia * DiaN -!< *** Grazing fluxes *** -!< ********************** - food = fPhyN + fDiaN - if (Grazing_detritus) food = food + fDetN -#if defined (__3Zoo2Det) - if (Grazing_detritus) food = food + fDetZ2N - food = food + fMicZooN ! 3Zoo -#endif -#if defined (__coccos) - food = food + fCoccoN -#endif -! ****************************************************************************** - foodsq = food**2 - grazingFlux = (Graz_max * foodsq)/(epsilonr + foodsq) * HetN * arrFunc -#if defined (__3Zoo2Det) - grazingFlux = (Graz_max * foodsq)/(epsilonr + foodsq) * HetN * q10_mes -#endif - grazingFlux_phy = grazingFlux * fphyN / food - grazingFlux_Dia = grazingFlux * fDiaN / food - if (Grazing_detritus) grazingFlux_Det = grazingFlux * fDetN / food -#if defined (__3Zoo2Det) - if (Grazing_detritus) grazingFlux_DetZ2 = grazingFlux * fDetZ2N / food - grazingFlux_miczoo = grazingFlux * fMicZooN / food ! 3Zoo -#endif -#if defined (__coccos) - grazingFlux_Cocco = grazingFlux * fCoccoN / food -#endif - -!< *** Grazing efficiency *** -!< ************************** - grazEff = gfin + 1/(0.2*food + 2) - - grazingFluxcarbon_mes = (grazingFlux_phy * recipQuota * grazEff) & - + (grazingFlux_Dia * recipQuota_Dia * grazEff) - - if (Grazing_detritus) grazingFluxcarbon_mes = grazingFluxcarbon_mes & - + (grazingFlux_Det * recipDet * grazEff) -#if defined (__3Zoo2Det) - if (Grazing_detritus) grazingFluxcarbon_mes = grazingFluxcarbon_mes & - + (grazingFlux_DetZ2 * recipDet2 * grazEff) - grazingFluxcarbon_mes = grazingFluxcarbon_mes & - + (grazingFlux_miczoo * recipQZoo3 * grazEff) ! 3Zoo -#endif -#if defined (__coccos) - grazingFluxcarbon_mes = grazingFluxcarbon_mes & - + (grazingFlux_Cocco * recipQuota_Cocco * grazEff) -#endif + if (Grazing_detritus) then + aux = aux + pzDet * DetN + endif -!------------------------------------------------------------------------------- -! Second Zooplankton -!------------------------------------------------------------------------------- -!< Grazing on small phytoplankton, diatoms, coccolithophore (optional), -!< heterotrophs, slow- and fast-sinking detritus - -!< *** Food availability *** -!< ************************* -!< pzPhy2: Maximum nanophytoplankton preference -!< pzDia2: Maximum diatom preference -!< pzCocco2: Maximum coccolithophore preference -!< pzDet2: Maximum slow-sinking detritus prefence -!< pzDetZ22: Maximum fast-sinking detritus preference -!< pzHet: Maximum mesozooplankton preference -!< pzMicZoo2: Maximum microzooplankton preference - -#if defined (__3Zoo2Det) - if (REcoM_Grazing_Variable_Preference) then - aux = pzPhy2 * PhyN + PzDia2 * DiaN + pzHet * HetN - if (Grazing_detritus) aux = aux + pzDet2 * DetN + pzDetZ22 * DetZ2N - aux = aux + pzMicZoo2 * MicZooN ! 3Zoo -#if defined (__coccos) - aux = aux + pzCocco2 * CoccoN -#endif -! ****************************************************************************** - varpzPhy2 = (pzPhy2 * PhyN)/aux - varpzDia2 = (pzDia2 * DiaN)/aux - varpzMicZoo2 = (pzMicZoo2 * MicZooN)/aux ! 3Zoo - -#if defined (__coccos) - varpzCocco2 = (pzCocco2 * CoccoN)/aux -#endif - varpzHet = (pzHet * HetN)/aux - if (Grazing_detritus) then - varpzDet2 = (pzDet2 * DetN)/aux - varpzDetZ22 = (pzDetZ22 * DetZ2N)/aux - end if -! ****************************************************************************** - fDiaN2 = varpzDia2 * DiaN - fPhyN2 = varpzPhy2 * PhyN - fMicZooN2 = varpzMicZoo2 * MicZooN ! 3Zoo -#if defined (__coccos) - fCoccoN2 = varpzCocco2 * CoccoN -#endif - fHetN = varpzHet * HetN - if (Grazing_detritus) then - fDetN2 = varpzDet2 * DetN - fDetZ2N2 = varpzDetZ22 * DetZ2N - end if - else ! REcoM_Grazing_Variable_Preference = .false. - - fDiaN2 = pzDia2 * DiaN - fPhyN2 = pzPhy2 * PhyN - fMicZooN2 = pzMicZoo2 * MicZooN ! 3Zoo -#if defined (__coccos) - fCoccoN2 = pzCocco2 * CoccoN -#endif - fHetN = pzHet * HetN - if (Grazing_detritus) then - fDetN2 = pzDet2 * DetN - fDetZ2N2 = pzDetZ22 * DetZ2N - end if - end if ! REcoM_Grazing_Variable_Preference + if (enable_3zoo2det) then + if (Grazing_detritus) aux = aux + pzDetZ2 * DetZ2N ! Fast-sinking detritus + aux = aux + pzMicZoo * MicZooN ! Microzooplankton + endif -!< *** Grazing fluxes *** -!< ********************** - food2 = fPhyN2 + fDiaN2 + fHetN - if (Grazing_detritus) food2 = food2 + fDetN2 + fDetZ2N2 - food2 = food2 + fMicZooN2 ! 3Zoo -#if defined (__coccos) - food2 = food2 + fCoccoN2 -#endif -! ****************************************************************************** - foodsq2 = food2**2 - grazingFlux2 = (Graz_max2 * foodsq2)/(epsilon2 + foodsq2) * Zoo2N * arrFuncZoo2 + if (enable_coccos) then + aux = aux + pzCocco * CoccoN + pzPhaeo * PhaeoN + endif - grazingFlux_phy2 = (grazingFlux2 * fphyN2)/food2 - grazingFlux_Dia2 = (grazingFlux2 * fDiaN2)/food2 - grazingFlux_miczoo2 = (grazingFlux2 * fMicZooN2)/food2 ! 3Zoo + ! Calculate variable preferences (normalized by total availability) + varpzPhy = (pzPhy * PhyN) / aux + varpzDia = (pzDia * DiaN) / aux -#if defined (__coccos) - grazingFlux_Cocco2 = (grazingFlux2 * fCoccoN2)/food2 -#endif - grazingFlux_het2 = (grazingFlux2 * fHetN)/food2 if (Grazing_detritus) then - grazingFlux_Det2 = (grazingFlux2 * fDetN2)/food2 - grazingFlux_DetZ22 = (grazingFlux2 * fDetZ2N2)/food2 - end if + varpzDet = (pzDet * DetN) / aux + endif + + if (enable_3zoo2det) then + if (Grazing_detritus) varpzDetZ2 = (pzDetZ2 * DetZ2N) / aux + varpzMicZoo = (pzMicZoo * MicZooN) / aux + endif + + if (enable_coccos) then + varpzCocco = (pzCocco * CoccoN) / aux + varpzPhaeo = (pzPhaeo * PhaeoN) / aux + endif + + ! Calculate available food pools (preference × concentration) + fPhyN = varpzPhy * PhyN + fDiaN = varpzDia * DiaN - grazingFluxcarbonzoo2 = (grazingFlux_phy2 * recipQuota * grazEff2) & - + (grazingFlux_Dia2 * recipQuota_Dia * grazEff2) & - + (grazingFlux_het2 * recipQZoo * grazEff2) if (Grazing_detritus) then - grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & - + (grazingFlux_Det2 * recipDet * grazEff2) & - + (grazingFlux_DetZ22 * recipDet2 * grazEff2) - end if - grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & - + (grazingFlux_miczoo2 * recipQZoo3 * grazEff2) ! 3Zoo -#if defined (__coccos) - grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & - + (grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2) -#endif + fDetN = varpzDet * DetN + endif -!------------------------------------------------------------------------------- -! Third Zooplankton (Microzooplankton) -!------------------------------------------------------------------------------- -!< Grazing on small phytoplankton, diatoms and coccolithophore (optional) + if (enable_3zoo2det) then + if (Grazing_detritus) fDetZ2N = varpzDetZ2 * DetZ2N + fMicZooN = varpzMicZoo * MicZooN + endif -!< *** Food availability *** -!< ************************* -!< pzPhy3: Maximum nanophytoplankton preference -!< pzDia3: Maximum diatom preference -!< pzCocco3: Maximum coccolithophore preference + if (enable_coccos) then + fCoccoN = varpzCocco * CoccoN + fPhaeoN = varpzPhaeo * PhaeoN + endif - if (REcoM_Grazing_Variable_Preference) then - aux = pzPhy3 * PhyN + pzDia3 * DiaN -#if defined (__coccos) - aux = aux + pzCocco3 * CoccoN -#endif -! ****************************************************************************** - varpzPhy3 = (pzPhy3 * PhyN)/aux - varpzDia3 = (pzDia3 * DiaN)/aux -#if defined (__coccos) - varpzCocco3 = (pzCocco3 * CoccoN)/aux -#endif -! ****************************************************************************** - fPhyN3 = varpzPhy3 * PhyN - fDiaN3 = varpzDia3 * DiaN -#if defined (__coccos) - fCoccoN3 = varpzCocco3 * CoccoN -#endif - else ! REcoM_Grazing_Variable_Preference = .false. - - fPhyN3 = pzPhy3 * PhyN - fDiaN3 = pzDia3 * DiaN -#if defined (__coccos) - fCoccoN3 = pzCocco3 * CoccoN -#endif - endif !REcoM_Grazing_Variable_Preference - -!< *** Grazing fluxes *** -!< ********************** - food3 = fPhyN3 + fDiaN3 -#if defined (__coccos) - food3 = food3 + fCoccoN3 -#endif -! ****************************************************************************** - foodsq3 = food3**2 - grazingFlux3 = (Graz_max3 * foodsq3)/(epsilon3 + foodsq3) * MicZooN * q10_mic - grazingFlux_phy3 = (grazingFlux3 * fphyN3)/food3 - grazingFlux_Dia3 = (grazingFlux3 * fDiaN3)/food3 -#if defined (__coccos) - grazingFlux_Cocco3 = (grazingFlux3 * fCoccoN3)/food3 -#endif -#endif + else + !--------------------------------------------------------------------------- + ! FIXED PREFERENCE MODE + ! Use constant maximum preference values + !--------------------------------------------------------------------------- -!------------------------------------------------------------------------------- -!< Heterotrophic respiration is assumed to drive zooplankton back to -!< Redfield C:N if their C:N becomes higher than Redfield -!< res_het: Timescale for zooplankton respiration [day−1 ] - - if (het_resp_noredfield) then -#if defined (__3Zoo2Det) - HetRespFlux = res_het * q10_mes_res * HetC ! 3Zoo -#else - HetRespFlux = res_het * arrFunc * HetC ! tau * f_T [HetC] -#endif - else - HetRespFlux = recip_res_het * arrFunc * (hetC * recip_hetN_plus - redfield) * HetC - HetRespFlux = max(zero, HetRespFlux) !!!!!!!! CHECK Judith Valid for het_resp_noredfield case as well ???????? Then move it below + fPhyN = pzPhy * PhyN + fDiaN = pzDia * DiaN + + if (Grazing_detritus) then + fDetN = pzDet * DetN endif + if (enable_3zoo2det) then + if (Grazing_detritus) fDetZ2N = pzDetZ2 * DetZ2N + fMicZooN = pzMicZoo * MicZooN + endif -!------------------------------------------------------------------------------- -!< Zooplanton mortality (Quadratic) + if (enable_coccos) then + fCoccoN = pzCocco * CoccoN + fPhaeoN = pzPhaeo * PhaeoN + endif - hetLossFlux = loss_het * HetN * HetN + endif ! REcoM_Grazing_Variable_Preference + + !=============================================================================== + ! 2. TOTAL GRAZING FLUX (HOLLING TYPE III) + !=============================================================================== + ! Calculates total grazing rate using a sigmoidal (Type III) functional response. + ! This creates a threshold effect where grazing accelerates at higher food levels. + ! + ! Variables: + ! food : Total available food [mmolN m-3] + ! foodsq : Squared food concentration [mmolN2 m-6] + ! grazingFlux : Total N grazing rate [mmolN m-3 day-1] + ! Graz_max : Maximum specific grazing rate [day-1] + ! epsilonr : Half-saturation constant squared [mmolN2 m-6] + ! HetN : Mesozooplankton nitrogen concentration [mmolN m-3] + ! q10_mes : Q10 temperature function for mesozooplankton [-] + ! arrFunc : Arrhenius temperature function [-] + ! + ! Equation: Holling Type III + ! grazingFlux = (Graz_max × food²) / (epsilonr + food²) × HetN × T_func + ! + ! Note: Uses Q10 when 3-zoo/2-detritus enabled, otherwise uses Arrhenius + !------------------------------------------------------------------------------- + + ! Sum all available food pools + food = fPhyN + fDiaN -#if defined (__3Zoo2Det) -!------------------------------------------------------------------------------- -!< Second zooplankton respiration + if (Grazing_detritus) then + food = food + fDetN + endif - call krill_resp(n, partit, mesh) + if (enable_3zoo2det) then + if (Grazing_detritus) food = food + fDetZ2N + food = food + fMicZooN + endif - if((grazingFluxcarbonzoo2/Zoo2C) <= 0.1)then - res_zoo2_f = 0.1*(grazingFluxcarbonzoo2/Zoo2C*100) - else - res_zoo2_f = 1. - end if - recip_res_zoo22 = res_zoo2*(1.+ res_zoo2_f + res_zoo2_a) - Zoo2RespFlux = recip_res_zoo22 * Zoo2C -!------------------------------------------------------------------------------- -!< Second zooplankton mortality (Quadratic) + if (enable_coccos) then + food = food + fCoccoN + fPhaeoN + endif - Zoo2LossFlux = loss_zoo2 * zoo2N * zoo2N + ! Calculate grazing flux with Holling Type III functional response + foodsq = food**2 -!------------------------------------------------------------------------------- -!< Second zooplankton fecal pellets + if (enable_3zoo2det) then + grazingFlux = (Graz_max * foodsq) / (epsilonr + foodsq) * HetN * q10_mes + else + grazingFlux = (Graz_max * foodsq) / (epsilonr + foodsq) * HetN * arrFunc + endif - Zoo2fecalloss_n = fecal_rate_n * grazingFlux2 - Zoo2fecalloss_c = fecal_rate_c * grazingFluxcarbonzoo2 + !=============================================================================== + ! 3. GRAZING FLUX DISTRIBUTION + !=============================================================================== + ! Partitions total grazing among prey types proportional to their availability. + ! + ! Variables: + ! grazingFlux_phy : Grazing on small phytoplankton [mmolN m-3 day-1] + ! grazingFlux_Dia : Grazing on diatoms [mmolN m-3 day-1] + ! grazingFlux_Det : Grazing on slow-sinking detritus [mmolN m-3 day-1] + ! grazingFlux_DetZ2 : Grazing on fast-sinking detritus [mmolN m-3 day-1] + ! grazingFlux_miczoo : Grazing on microzooplankton [mmolN m-3 day-1] + ! grazingFlux_Cocco : Grazing on coccolithophores [mmolN m-3 day-1] + ! grazingFlux_Phaeo : Grazing on Phaeocystis [mmolN m-3 day-1] + ! + ! Equation for each prey type i: + ! grazingFlux_i = grazingFlux × (f_i / total_food) + !------------------------------------------------------------------------------- + + grazingFlux_phy = grazingFlux * fPhyN / food + grazingFlux_Dia = grazingFlux * fDiaN / food -!------------------------------------------------------------------------------- -!< Mesozooplankton fecal pellets + if (Grazing_detritus) then + grazingFlux_Det = grazingFlux * fDetN / food + endif - mesfecalloss_n = fecal_rate_n_mes * grazingFlux - mesfecalloss_c = fecal_rate_c_mes * grazingFluxcarbon_mes + if (enable_3zoo2det) then + if (Grazing_detritus) grazingFlux_DetZ2 = grazingFlux * fDetZ2N / food + grazingFlux_miczoo = grazingFlux * fMicZooN / food + endif -!------------------------------------------------------------------------------- -! Third zooplankton, microzooplankton, respiration ! 3Zoo + if (enable_coccos) then + grazingFlux_Cocco = grazingFlux * fCoccoN / food + grazingFlux_Phaeo = grazingFlux * fPhaeoN / food + endif - MicZooRespFlux = res_miczoo * q10_mic_res * MicZooC -!------------------------------------------------------------------------------- -! Third zooplankton, microzooplankton, mortality (Quadratic) ! 3Zoo + !=============================================================================== + ! 4. GRAZING EFFICIENCY AND CARBON FLUX + !=============================================================================== + ! Calculates food-dependent assimilation efficiency and converts grazed nitrogen + ! to carbon flux using prey-specific C:N ratios. + ! + ! Variables: + ! grazEff : Grazing/assimilation efficiency [-] + ! gfin : Baseline grazing efficiency [-] + ! grazingFluxcarbon_mes : Total carbon flux to mesozooplankton [mmolC m-3 day-1] + ! recipQuota : Small phytoplankton C:N ratio [mmolC mmolN-1] + ! recipQuota_Dia : Diatom C:N ratio [mmolC mmolN-1] + ! recipQuota_Cocco : Coccolithophore C:N ratio [mmolC mmolN-1] + ! recipQuota_phaeo : Phaeocystis C:N ratio [mmolC mmolN-1] + ! recipDet, recipDet2 : Detritus C:N ratios [mmolC mmolN-1] + ! recipQZoo3 : Microzooplankton C:N ratio [mmolC mmolN-1] + ! + ! Grazing Efficiency Equation: + ! grazEff = gfin + 1/(0.2×food + 2) + ! Higher food -> higher efficiency (asymptotes to gfin + 0.5) + ! + ! Carbon Flux Equation: + ! C_flux = Σ(grazingFlux_i × C:N_ratio_i × grazEff) + !------------------------------------------------------------------------------- + + ! Calculate food-dependent grazing efficiency + ! Increases with food availability, representing improved assimilation at higher rations + grazEff = gfin + 1.0 / (0.2 * food + 2.0) + + ! Convert grazed nitrogen to carbon flux using prey C:N ratios + grazingFluxcarbon_mes = (grazingFlux_phy * recipQuota * grazEff) + & + (grazingFlux_Dia * recipQuota_Dia * grazEff) - MicZooLossFlux = loss_miczoo * MicZooN * MicZooN -#endif + if (Grazing_detritus) then + grazingFluxcarbon_mes = grazingFluxcarbon_mes + & + (grazingFlux_Det * recipDet * grazEff) + endif -!------------------------------------------------------------------------------- -! Phytoplankton and detritus aggregation -!------------------------------------------------------------------------------- - if (diatom_mucus) then - qlimitFac = recom_limiter(NMinSlope, NCmin_d, quota_dia) - qlimitFacTmp = recom_limiter(SiMinSlope, SiCmin, qSiC) - qlimitFac = min(qLimitFac, qlimitFacTmp) - feLimitFac= Fe/(k_Fe_d + Fe) - qlimitFac = min(qlimitFac, feLimitFac) - aggregationrate = agg_PP * (1 - qlimitFac) * DiaN - else - aggregationrate = agg_PP * DiaN + if (enable_3zoo2det) then + if (Grazing_detritus) then + grazingFluxcarbon_mes = grazingFluxcarbon_mes + & + (grazingFlux_DetZ2 * recipDet2 * grazEff) endif - - aggregationrate = aggregationrate + agg_PD * DetN + agg_PP * PhyN - -#if defined (__3Zoo2Det) - aggregationrate = aggregationrate + agg_PD * DetZ2N ! 2Det -#endif -#if defined (__coccos) - aggregationrate = aggregationrate + agg_PP * CoccoN -#endif - -!------------------------------------------------------------------------------- -! Calcification -!------------------------------------------------------------------------------- -! Terms required for the formation and dissolution of CaCO3 -! Without this, calcification is performed by a fraction of small phytoplankton + grazingFluxcarbon_mes = grazingFluxcarbon_mes + & + (grazingFlux_miczoo * recipQZoo3 * grazEff) + endif + + if (enable_coccos) then + grazingFluxcarbon_mes = grazingFluxcarbon_mes + & + (grazingFlux_Cocco * recipQuota_Cocco * grazEff) + & + (grazingFlux_Phaeo * recipQuota_phaeo * grazEff) + endif + + !=============================================================================== + ! MACROZOOPLANKTON GRAZING + !=============================================================================== + ! Simulates macrozooplankton (second zooplankton) grazing on multiple prey types + ! using a Holling Type II functional response with food-dependent preferences. + ! + ! This module calculates: + ! 1. Food availability and grazing preferences (fixed or variable) + ! 2. Total grazing flux with Holling Type II response + ! 3. Distribution of grazing among prey types + ! 4. Carbon assimilation from grazed prey using C:N ratios + ! + ! Key Features: + ! - Carnivorous feeding: grazes on mesozooplankton and microzooplankton + ! - Herbivorous feeding: grazes on phytoplankton, diatoms, coccolithophores + ! - Detritivorous feeding: optional grazing on slow/fast-sinking detritus + ! - Variable or fixed prey preferences + ! - Temperature-dependent grazing rate (Arrhenius) + ! - Constant assimilation efficiency (grazEff2) + ! + ! Prey Types: + ! - Primary: Mesozooplankton, microzooplankton, small phyto, diatoms + ! - Optional: Coccolithophores, Phaeocystis, slow/fast-sinking detritus + ! + ! References: + ! - Schourup-Kristensen et al. (2013) - REcoM model description + !=============================================================================== + + if (enable_3zoo2det) then + + !=========================================================================== + ! 1. FOOD AVAILABILITY AND GRAZING PREFERENCES + !=========================================================================== + ! Calculates which prey types are available and their relative preferences. + ! Two modes: + ! - Variable preferences: Adjust based on relative prey abundance + ! - Fixed preferences: Use constant maximum preference values + ! + ! Variables: + ! pzPhy2, pzDia2 : Max preference for small phyto and diatoms [-] + ! pzCocco2, pzPhaeo2: Max preference for coccoliths and Phaeocystis [-] + ! pzHet : Max preference for mesozooplankton [-] + ! pzMicZoo2 : Max preference for microzooplankton [-] + ! pzDet2, pzDetZ22 : Max preference for slow/fast sinking detritus [-] + ! PhyN, DiaN : Small phytoplankton and diatom nitrogen [mmolN m-3] + ! CoccoN, PhaeoN : Coccolithophore and Phaeocystis nitrogen [mmolN m-3] + ! HetN : Mesozooplankton nitrogen [mmolN m-3] + ! MicZooN : Microzooplankton nitrogen [mmolN m-3] + ! DetN, DetZ2N : Slow and fast sinking detritus nitrogen [mmolN m-3] + ! varpz*2, varpzHet: Variable preferences (calculated from availability) [-] + ! f*N2, fHetN : Available food pools (preference × concentration) [mmolN m-3] + ! aux : Total weighted food availability [mmolN m-3] + ! + ! Logic: + ! IF variable preferences: varpz_i = (pz_i × prey_i) / Σ(pz_j × prey_j) + ! ELSE: Use fixed maximum preferences (pz_i) + ! Food pools: f_i = preference_i × prey_i + !--------------------------------------------------------------------------- + + if (REcoM_Grazing_Variable_Preference) then + !----------------------------------------------------------------------- + ! VARIABLE PREFERENCE MODE + ! Preferences scale with relative abundance of each prey type + !----------------------------------------------------------------------- + + ! Calculate total weighted food availability (denominator) + ! Core prey: phytoplankton, diatoms, meso- and microzooplankton + aux = pzPhy2 * PhyN + pzDia2 * DiaN + pzHet * HetN + pzMicZoo2 * MicZooN + + ! Add detritus pools if detrital grazing is enabled + if (Grazing_detritus) then + aux = aux + pzDet2 * DetN + pzDetZ22 * DetZ2N + endif + + ! Add coccolithophores and Phaeocystis if enabled + if (enable_coccos) then + aux = aux + pzCocco2 * CoccoN + pzPhaeo2 * PhaeoN + endif + + ! Calculate variable preferences (normalized by total availability) + ! Each preference = (max_pref × prey_conc) / total_weighted_food + varpzPhy2 = (pzPhy2 * PhyN) / aux + varpzDia2 = (pzDia2 * DiaN) / aux + varpzMicZoo2 = (pzMicZoo2 * MicZooN) / aux + varpzHet = (pzHet * HetN) / aux + + if (enable_coccos) then + varpzCocco2 = (pzCocco2 * CoccoN) / aux + varpzPhaeo2 = (pzPhaeo2 * PhaeoN) / aux + endif + + if (Grazing_detritus) then + varpzDet2 = (pzDet2 * DetN) / aux + varpzDetZ22 = (pzDetZ22 * DetZ2N) / aux + end if + + ! Calculate available food pools (preference × concentration) + fPhyN2 = varpzPhy2 * PhyN + fDiaN2 = varpzDia2 * DiaN + fMicZooN2 = varpzMicZoo2 * MicZooN + fHetN = varpzHet * HetN + + if (enable_coccos) then + fCoccoN2 = varpzCocco2 * CoccoN + fPhaeoN2 = varpzPhaeo2 * PhaeoN + endif + + if (Grazing_detritus) then + fDetN2 = varpzDet2 * DetN + fDetZ2N2 = varpzDetZ22 * DetZ2N + end if -#if defined (__coccos) - if (Temp(k) < 10.6) then ! (PICPOC definition after Krumhardt et al. 2017, 2019; Temp(k) because we need degC here) - PICPOCtemp = 0.104d0 * Temp(k) - 0.108d0 else - PICPOCtemp = 1.0d0 - end if - PICPOCtemp = max(tiny,PICPOCtemp) - - PICPOCCO2 = a_co2_calc * HCO3_watercolumn(k) * Cunits / (b_co2_calc + HCO3_watercolumn(k) * Cunits) - exp(-c_co2_calc * CO2_watercolumn(k) * Cunits) - d_co2_calc * 10.**(-pH_watercolumn(k)) - PICPOCCO2 = min(PICPOCCO2,3.d0) ! April 2022: limitation to 3 - PICPOCCO2 = max(0.d0,PICPOCCO2) ! July 2022: limitation to zero - - PICPOCN = -0.31 * (DIN/(DIN + k_din_c)) + 1.31 - PICPOCN = max(tiny,PICPOCN) - - calcification = 1.d0 * Cphot_cocco * CoccoC * PICPOCtemp * PICPOCN - if (CO2lim) calcification = calcification * PICPOCCO2 - -#else -!< calc_prod_ratio: Calcite production ratio, dimensionless - calcification = calc_prod_ratio * Cphot * PhyC ! Z in equations -#endif - - calc_loss_agg = aggregationrate * PhyCalc - -#if defined (__coccos) -!< *** Coccolithophores *** -!< ************************ - aux = recipQuota_Cocco/(CoccoC + tiny) * PhyCalc - calc_loss_gra = grazingFlux_Cocco * aux -#if defined (__3Zoo2Det) - calc_loss_gra2 = grazingFlux_Cocco2 * aux - calc_loss_gra3 = grazingFlux_Cocco3 * aux ! 3Zoo -#endif - -#else -!< *** Small phytoplankton *** -!< *************************** - aux = recipQuota/(PhyC + tiny) * PhyCalc - calc_loss_gra = grazingFlux_phy * aux -#if defined (__3Zoo2Det) - calc_loss_gra2 = grazingFlux_phy2 * aux - calc_loss_gra3 = grazingFlux_phy3 * aux ! 3Zoo -#endif -#endif -!------------------------------------------------------------------------------- -! Sources minus sinks (SMS) -!------------------------------------------------------------------------------- + !----------------------------------------------------------------------- + ! FIXED PREFERENCE MODE + ! Use constant maximum preference values + !----------------------------------------------------------------------- + + fPhyN2 = pzPhy2 * PhyN + fDiaN2 = pzDia2 * DiaN + fMicZooN2 = pzMicZoo2 * MicZooN + fHetN = pzHet * HetN + + if (enable_coccos) then + fCoccoN2 = pzCocco2 * CoccoN + fPhaeoN2 = pzPhaeo2 * PhaeoN + endif -!< *** DIN *** -!< *********** - -!< N_assim: N assimilation rate for nanophytoplankton [mmolN mmolC-1 day-1] -!< PhyC: Intracellular carbon concentration in nanophytoplankton [mmolC m-3] -!< N_assim_Dia: N assimilation rate for diatoms [mmolN mmolC-1 day-1] -!< DiaC: Intracellular carbon concentration in diatoms [mmolC m-3] -!< N_assim_Cocco: N assimilation rate for coccolithophore [mmolN mmolC-1 day-1] -!< CoccoC: Intracellular carbon concentration in coccolithophore [mmolC m-3] -!< rho_N*arrFunc: Remineralization rate and temperature dependency which is calculated with arrFunc [day^-1] -!< O2Func: O2 dependency of organic matter remineralization -!< DON: Extracellular dissolved organic nitrogen [mmolN m-3] -!< dt_b: REcoM time step [day] - -!! Schourup 2013 Eq. A2 - - sms(k,idin) = ( & - - N_assim * PhyC & ! --> N assimilation Nanophytoplankton, [mmol N/(mmol C * day)] C specific N utilization rate - - N_assim_Dia * DiaC & ! --> N assimilation Diatoms -#if defined (__coccos) - - N_assim_Cocco * CoccoC & ! --> N assimilation Coccolithophore -#endif - + rho_N * arrFunc * O2Func * DON & ! --> DON remineralization, temperature dependent [day^-1 * mmol/m3] ! O2remin - ) * dt_b + sms(k,idin) - -!< *** DIC *** -!< *********** - -!< rho_C1: Temperature dependent C degradation of extracellular organic C (EOC) [day^-1] - - sms(k,idic) = ( & - - Cphot * PhyC & ! --> Small pyhtoplankton photosynthesis - + phyRespRate * PhyC & ! --> Small pyhtoplankton respiration - - Cphot_Dia * DiaC & ! --> Diatom photosynthesis - + phyRespRate_Dia * DiaC & ! --> Diatom respiration -#if defined (__coccos) - - Cphot_Cocco * CoccoC & ! --> Coccolithophore photosynthesis - + phyRespRate_Cocco * CoccoC & ! --> Coccolithophore respiration -#endif - + rho_C1 * arrFunc * O2Func * EOC & ! --> Remineralization of DOC ! NEW O2remin - + HetRespFlux & ! --> Mesozooplankton respiration -#if defined (__3Zoo2Det) - + Zoo2RespFlux & ! --> Macrozooplankton respiration - + MicZooRespFlux & ! --> Microzooplankton respiration -#endif - + calc_diss * DetCalc & ! --> Calcite dissolution from slow-sinking detritus - + calc_loss_gra * calc_diss_guts & ! --> Additional dissolution in mesozooplankton guts -#if defined (__3Zoo2Det) - + calc_loss_gra2 * calc_diss_guts & ! --> Additional dissolution in macrozooplankton guts - + calc_loss_gra3 * calc_diss_guts & ! --> Additional dissolution in microzooplankton guts - + calc_diss2 * DetZ2Calc & ! --> Calcite dissolution from fast-sinking detritus -#endif - - calcification & ! --> Calcification - ) * dt_b + sms(k,idic) + if (Grazing_detritus) then + fDetN2 = pzDet2 * DetN + fDetZ2N2 = pzDetZ22 * DetZ2N + end if + + end if ! REcoM_Grazing_Variable_Preference + + !=========================================================================== + ! 2. TOTAL GRAZING FLUX (HOLLING TYPE II) + !=========================================================================== + ! Calculates total grazing rate using a hyperbolic (Type II) functional + ! response. This creates saturating grazing at high food concentrations. + ! + ! Variables: + ! food2 : Total available food [mmolN m-3] + ! foodsq2 : Squared food concentration [mmolN2 m-6] + ! grazingFlux2 : Total N grazing rate [mmolN m-3 day-1] + ! Graz_max2 : Maximum specific grazing rate [day-1] + ! epsilon2 : Half-saturation constant squared [mmolN2 m-6] + ! Zoo2N : Macrozooplankton nitrogen concentration [mmolN m-3] + ! arrFuncZoo2 : Arrhenius temperature function for macrozooplankton [-] + ! + ! Equation: Holling Type II + ! grazingFlux2 = (Graz_max2 × food²) / (epsilon2 + food²) × Zoo2N × T_func + ! + ! Note: Uses Arrhenius temperature dependency (arrFuncZoo2) + !--------------------------------------------------------------------------- + + ! Sum all available food pools + food2 = fPhyN2 + fDiaN2 + fHetN + fMicZooN2 + + if (Grazing_detritus) then + food2 = food2 + fDetN2 + fDetZ2N2 + endif + + if (enable_coccos) then + food2 = food2 + fCoccoN2 + fPhaeoN2 + endif + + ! Calculate grazing flux with Holling Type II functional response + ! Type II uses squared food (similar to Type III but with different parameters) + foodsq2 = food2**2 + grazingFlux2 = (Graz_max2 * foodsq2) / (epsilon2 + foodsq2) * Zoo2N * arrFuncZoo2 + + !=========================================================================== + ! 3. GRAZING FLUX DISTRIBUTION + !=========================================================================== + ! Partitions total grazing among prey types proportional to their availability. + ! + ! Variables: + ! grazingFlux_phy2 : Grazing on small phytoplankton [mmolN m-3 day-1] + ! grazingFlux_Dia2 : Grazing on diatoms [mmolN m-3 day-1] + ! grazingFlux_miczoo2 : Grazing on microzooplankton [mmolN m-3 day-1] + ! grazingFlux_het2 : Grazing on mesozooplankton [mmolN m-3 day-1] + ! grazingFlux_Cocco2 : Grazing on coccolithophores [mmolN m-3 day-1] + ! grazingFlux_Phaeo2 : Grazing on Phaeocystis [mmolN m-3 day-1] + ! grazingFlux_Det2 : Grazing on slow-sinking detritus [mmolN m-3 day-1] + ! grazingFlux_DetZ22 : Grazing on fast-sinking detritus [mmolN m-3 day-1] + ! + ! Equation for each prey type i: + ! grazingFlux_i = grazingFlux2 × (f_i / total_food) + !--------------------------------------------------------------------------- + + ! Distribute total grazing among prey types proportionally + grazingFlux_phy2 = (grazingFlux2 * fPhyN2) / food2 + grazingFlux_Dia2 = (grazingFlux2 * fDiaN2) / food2 + grazingFlux_miczoo2 = (grazingFlux2 * fMicZooN2) / food2 + grazingFlux_het2 = (grazingFlux2 * fHetN) / food2 + + if (enable_coccos) then + grazingFlux_Cocco2 = (grazingFlux2 * fCoccoN2) / food2 + grazingFlux_Phaeo2 = (grazingFlux2 * fPhaeoN2) / food2 + endif + + if (Grazing_detritus) then + grazingFlux_Det2 = (grazingFlux2 * fDetN2) / food2 + grazingFlux_DetZ22 = (grazingFlux2 * fDetZ2N2) / food2 + end if + + !=========================================================================== + ! 4. CARBON ASSIMILATION + !=========================================================================== + ! Converts grazed nitrogen to assimilated carbon flux using prey-specific + ! C:N ratios and constant grazing efficiency. + ! + ! Variables: + ! grazingFluxcarbonzoo2 : Total carbon flux to macrozooplankton [mmolC m-3 day-1] + ! grazEff2 : Macrozooplankton grazing efficiency (constant) [-] + ! recipQuota : Small phytoplankton C:N ratio [mmolC mmolN-1] + ! recipQuota_Dia : Diatom C:N ratio [mmolC mmolN-1] + ! recipQuota_Cocco : Coccolithophore C:N ratio [mmolC mmolN-1] + ! recipQuota_Phaeo : Phaeocystis C:N ratio [mmolC mmolN-1] + ! recipQZoo : Mesozooplankton C:N ratio [mmolC mmolN-1] + ! recipQZoo3 : Microzooplankton C:N ratio [mmolC mmolN-1] + ! recipDet, recipDet2 : Detritus C:N ratios [mmolC mmolN-1] + ! + ! Carbon Flux Equation: + ! C_flux = Σ(grazingFlux_i × C:N_ratio_i × grazEff2) + ! + ! Note: Unlike mesozooplankton, macrozooplankton uses constant efficiency + ! (grazEff2) rather than food-dependent efficiency + !--------------------------------------------------------------------------- + + ! Convert grazed nitrogen to carbon flux using prey C:N ratios + ! Start with core prey types (always present) + grazingFluxcarbonzoo2 = (grazingFlux_phy2 * recipQuota * grazEff2) + & + (grazingFlux_Dia2 * recipQuota_Dia * grazEff2) + & + (grazingFlux_het2 * recipQZoo * grazEff2) + & + (grazingFlux_miczoo2 * recipQZoo3 * grazEff2) + + ! Add detritus contribution if detrital grazing is enabled + if (Grazing_detritus) then + grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & + (grazingFlux_Det2 * recipDet * grazEff2) + & + (grazingFlux_DetZ22 * recipDet2 * grazEff2) + end if + + ! Add coccolithophore and Phaeocystis contribution if enabled + if (enable_coccos) then + grazingFluxcarbonzoo2 = grazingFluxcarbonzoo2 + & + (grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2) + & + (grazingFlux_Phaeo2 * recipQuota_Phaeo * grazEff2) + endif + + endif ! enable_3zoo2det + + !=============================================================================== + ! MICROZOOPLANKTON GRAZING + !=============================================================================== + ! Simulates microzooplankton (third zooplankton) grazing on phytoplankton prey + ! using a Holling Type II functional response with food-dependent preferences. + ! + ! This module calculates: + ! 1. Food availability and grazing preferences (fixed or variable) + ! 2. Total grazing flux with Holling Type II response + ! 3. Distribution of grazing among prey types + ! 4. Carbon assimilation from grazed prey (calculated elsewhere) + ! + ! Key Features: + ! - Strictly herbivorous: only grazes on phytoplankton groups + ! - No carnivory: does not graze on other zooplankton + ! - No detritivory: does not graze on detritus + ! - Variable or fixed prey preferences + ! - Temperature-dependent grazing rate (Q10) + ! - Smallest zooplankton size class (fastest response to phytoplankton) + ! + ! Prey Types: + ! - Primary: Small phytoplankton, diatoms + ! - Optional: Coccolithophores, Phaeocystis + ! + ! Ecological Role: + ! - Links small phytoplankton to higher trophic levels + ! - Prey for mesozooplankton and macrozooplankton + ! - Rapid response to phytoplankton blooms + ! + ! References: + ! - Schourup-Kristensen et al. (2013) - REcoM model description + !=============================================================================== + + if (enable_3zoo2det) then + + !=========================================================================== + ! 1. FOOD AVAILABILITY AND GRAZING PREFERENCES + !=========================================================================== + ! Calculates which phytoplankton prey types are available and their + ! relative preferences. + ! Two modes: + ! - Variable preferences: Adjust based on relative prey abundance + ! - Fixed preferences: Use constant maximum preference values + ! + ! Variables: + ! pzPhy3, pzDia3 : Max preference for small phyto and diatoms [-] + ! pzCocco3, pzPhaeo3 : Max preference for coccoliths and Phaeocystis [-] + ! PhyN, DiaN : Small phytoplankton and diatom nitrogen [mmolN m-3] + ! CoccoN, PhaeoN : Coccolithophore and Phaeocystis nitrogen [mmolN m-3] + ! varpzPhy3, varpzDia3: Variable preferences (calculated from availability) [-] + ! varpzCocco3, varpzPhaeo3: Variable preferences for coccos/phaeo [-] + ! fPhyN3, fDiaN3 : Available food pools (preference × concentration) [mmolN m-3] + ! fCoccoN3, fPhaeoN3 : Available coccolithophore/Phaeocystis pools [mmolN m-3] + ! aux : Total weighted food availability [mmolN m-3] + ! + ! Logic: + ! IF variable preferences: varpz_i = (pz_i × prey_i) / Σ(pz_j × prey_j) + ! ELSE: Use fixed maximum preferences (pz_i) + ! Food pools: f_i = preference_i × prey_i + ! + ! Note: Microzooplankton have simpler feeding than meso/macrozooplankton + ! - No carnivory (no zooplankton prey) + ! - No detritivory (no detritus grazing) + !--------------------------------------------------------------------------- + + if (REcoM_Grazing_Variable_Preference) then + !----------------------------------------------------------------------- + ! VARIABLE PREFERENCE MODE + ! Preferences scale with relative abundance of each phytoplankton type + !----------------------------------------------------------------------- + + ! Calculate total weighted food availability (denominator) + ! Core phytoplankton prey: small phytoplankton and diatoms + aux = pzPhy3 * PhyN + pzDia3 * DiaN + + ! Add coccolithophores and Phaeocystis if enabled + if (enable_coccos) then + aux = aux + pzCocco3 * CoccoN + pzPhaeo3 * PhaeoN + endif + + ! Calculate variable preferences (normalized by total availability) + ! Each preference = (max_pref × prey_conc) / total_weighted_food + varpzPhy3 = (pzPhy3 * PhyN) / aux + varpzDia3 = (pzDia3 * DiaN) / aux + + if (enable_coccos) then + varpzCocco3 = (pzCocco3 * CoccoN) / aux + varpzPhaeo3 = (pzPhaeo3 * PhaeoN) / aux + endif + + ! Calculate available food pools (preference × concentration) + fPhyN3 = varpzPhy3 * PhyN + fDiaN3 = varpzDia3 * DiaN + + if (enable_coccos) then + fCoccoN3 = varpzCocco3 * CoccoN + fPhaeoN3 = varpzPhaeo3 * PhaeoN + endif + + else + !----------------------------------------------------------------------- + ! FIXED PREFERENCE MODE + ! Use constant maximum preference values + !----------------------------------------------------------------------- + + fPhyN3 = pzPhy3 * PhyN + fDiaN3 = pzDia3 * DiaN + + if (enable_coccos) then + fCoccoN3 = pzCocco3 * CoccoN + fPhaeoN3 = pzPhaeo3 * PhaeoN + endif + + endif ! REcoM_Grazing_Variable_Preference + + !=========================================================================== + ! 2. TOTAL GRAZING FLUX (HOLLING TYPE II) + !=========================================================================== + ! Calculates total grazing rate using a hyperbolic (Type II) functional + ! response. This creates saturating grazing at high phytoplankton + ! concentrations. + ! + ! Variables: + ! food3 : Total available phytoplankton food [mmolN m-3] + ! foodsq3 : Squared food concentration [mmolN2 m-6] + ! grazingFlux3 : Total N grazing rate [mmolN m-3 day-1] + ! Graz_max3 : Maximum specific grazing rate [day-1] + ! epsilon3 : Half-saturation constant squared [mmolN2 m-6] + ! MicZooN : Microzooplankton nitrogen concentration [mmolN m-3] + ! q10_mic : Q10 temperature function for microzooplankton [-] + ! + ! Equation: Holling Type II + ! grazingFlux3 = (Graz_max3 × food³) / (epsilon3 + food²) × MicZooN × T_func + ! + ! Note: Uses Q10 temperature dependency (q10_mic) for rapid metabolic response + ! Smaller organisms typically have higher Q10 sensitivity + !--------------------------------------------------------------------------- + + ! Sum all available phytoplankton food pools + food3 = fPhyN3 + fDiaN3 + + if (enable_coccos) then + food3 = food3 + fCoccoN3 + fPhaeoN3 + endif + + ! Calculate grazing flux with Holling Type II functional response + ! Type II creates hyperbolic saturation: grazing rate increases rapidly + ! at low food, then saturates at high food concentrations + foodsq3 = food3**2 + grazingFlux3 = (Graz_max3 * foodsq3) / (epsilon3 + foodsq3) * MicZooN * q10_mic + + !=========================================================================== + ! 3. GRAZING FLUX DISTRIBUTION + !=========================================================================== + ! Partitions total grazing among phytoplankton prey types proportional + ! to their availability. + ! + ! Variables: + ! grazingFlux_phy3 : Grazing on small phytoplankton [mmolN m-3 day-1] + ! grazingFlux_Dia3 : Grazing on diatoms [mmolN m-3 day-1] + ! grazingFlux_Cocco3 : Grazing on coccolithophores [mmolN m-3 day-1] + ! grazingFlux_Phaeo3 : Grazing on Phaeocystis [mmolN m-3 day-1] + ! + ! Equation for each prey type i: + ! grazingFlux_i = grazingFlux3 × (f_i / total_food) + ! + ! Note: This proportional distribution ensures conservation of mass + ! The sum of all distributed fluxes equals the total grazing flux + !--------------------------------------------------------------------------- + + ! Distribute total grazing among phytoplankton prey types proportionally + grazingFlux_phy3 = (grazingFlux3 * fPhyN3) / food3 + grazingFlux_Dia3 = (grazingFlux3 * fDiaN3) / food3 + + if (enable_coccos) then + grazingFlux_Cocco3 = (grazingFlux3 * fCoccoN3) / food3 + grazingFlux_Phaeo3 = (grazingFlux3 * fPhaeoN3) / food3 + endif + + !=========================================================================== + ! 4. CARBON ASSIMILATION + !=========================================================================== + ! Carbon flux calculation for microzooplankton is handled elsewhere in the + ! model code using the nitrogen grazing fluxes calculated above and + ! prey-specific C:N ratios. + ! + ! The carbon assimilation follows the general pattern: + ! C_flux = Σ(grazingFlux_i × C:N_ratio_i × grazEff3) + ! + ! Where: + ! grazEff3 = Microzooplankton grazing efficiency (constant) [-] + ! C:N ratios for each phytoplankton prey type [mmolC mmolN-1] + ! + ! This calculation is performed in the carbon balance section of the model + ! to maintain consistency with other carbon flux calculations. + !=========================================================================== + + endif ! enable_3zoo2det + + !=============================================================================== + ! MESOZOOPLANKTON RESPIRATION + !=============================================================================== + ! Calculates mesozooplankton carbon respiration using either simple temperature- + ! dependent respiration or Redfield-based respiration that accounts for C:N + ! stoichiometry deviations. + ! + ! Two respiration modes: + ! A) Simple mode: Constant specific rate with temperature correction + ! B) Redfield mode: Respirate excess carbon above Redfield C:N ratio + ! + ! Variables: + ! HetRespFlux : Mesozooplankton respiration rate [mmolC m-3 day-1] + ! res_het : Baseline respiration rate constant [day-1] + ! HetC : Mesozooplankton carbon concentration [mmolC m-3] + ! HetN : Mesozooplankton nitrogen concentration [mmolN m-3] + ! q10_mes_res : Q10 temperature function for meso respiration [-] + ! arrFunc : Arrhenius temperature function [-] + ! recip_hetN_plus : Reciprocal of (HetN + small number) [mmolN-1 m3] + ! redfield : Redfield C:N ratio (106:16 ≈ 6.625) [mmolC mmolN-1] + ! recip_res_het : Reciprocal respiration parameter [day-1] + ! + ! Logic: + ! IF simple mode: RespFlux = res_het × T_func × HetC + ! ELSE Redfield mode: RespFlux = recip_res_het × T_func × (C:N - Redfield) × HetC + ! Redfield mode respirates excess carbon when C:N > Redfield ratio + ! + ! Note: Redfield-based respiration maintains stoichiometric homeostasis + !------------------------------------------------------------------------------- + + if (het_resp_noredfield) then + !--------------------------------------------------------------------------- + ! SIMPLE RESPIRATION MODE + ! Constant specific rate with temperature dependency + !--------------------------------------------------------------------------- + + if (enable_3zoo2det) then + ! Use Q10 temperature function (exponential temperature sensitivity) + HetRespFlux = res_het * q10_mes_res * HetC + else + ! Use Arrhenius temperature function + HetRespFlux = res_het * arrFunc * HetC + endif + + else + !--------------------------------------------------------------------------- + ! REDFIELD-BASED RESPIRATION MODE + ! Respirate excess carbon above Redfield C:N ratio + !--------------------------------------------------------------------------- + + ! Calculate respiration based on deviation from Redfield ratio + ! When C:N > Redfield, organism has excess carbon that must be respired + ! This maintains stoichiometric balance in the organism + HetRespFlux = recip_res_het * arrFunc * (HetC * recip_hetN_plus - redfield) * HetC + + ! Ensure non-negative flux (no respiration when C:N ≤ Redfield) + HetRespFlux = max(zero, HetRespFlux) + + endif + + !=============================================================================== + ! CARBON ISOTOPE TRACKING (OPTIONAL) + !=============================================================================== + ! Tracks respiration fluxes of carbon isotopes (13C and 14C) for paleoclimate + ! and carbon cycle studies. + ! + ! Variables: + ! HetRespFlux_13 : 13C respiration flux [mmol13C m-3 day-1] + ! HetRespFlux_14 : 14C respiration flux [mmol14C m-3 day-1] + ! HetC_13 : Mesozooplankton 13C concentration [mmol13C m-3] + ! HetC_14 : Mesozooplankton 14C concentration [mmol14C m-3] + ! HetC : Total mesozooplankton carbon [mmolC m-3] + ! ciso : Flag for 13C isotope tracking [logical] + ! ciso_14 : Flag for 14C isotope tracking [logical] + ! ciso_organic_14 : Flag for 14C in organic matter [logical] + ! + ! Equation: + ! IsotopeFlux = TotalFlux × (Isotope_C / Total_C) + ! Assumes isotope ratios are conserved during respiration + !------------------------------------------------------------------------------- + + if (ciso) then + ! Track 13C respiration proportional to 13C:12C ratio in biomass + HetRespFlux_13 = HetRespFlux * HetC_13 / HetC + + if (ciso_14 .and. ciso_organic_14) then + ! Track 14C respiration (for radiocarbon dating applications) + ! Used to study carbon residence times and ocean circulation + HetRespFlux_14 = HetRespFlux * HetC_14 / HetC + end if + end if + + !=============================================================================== + ! MESOZOOPLANKTON MORTALITY + !=============================================================================== + ! Calculates density-dependent mortality using quadratic formulation. + ! Higher densities lead to disproportionately higher mortality. + ! + ! Variables: + ! hetLossFlux : Mesozooplankton mortality flux [mmolN m-3 day-1] + ! loss_het : Mortality rate constant [day-1 (mmolN m-3)-1] + ! HetN : Mesozooplankton nitrogen concentration [mmolN m-3] + ! + ! Equation: Quadratic Mortality + ! Mortality = loss_het × HetN² + ! + ! Ecological Rationale: + ! - Linear term represents background mortality (disease, senescence) + ! - Quadratic term represents density-dependent processes: + ! * Increased predation pressure at high densities + ! * Disease transmission (increases with encounter rate) + ! * Intraspecific competition for resources + ! + ! Note: Mortality products go to detritus pool (recycling pathway) + !------------------------------------------------------------------------------- + + hetLossFlux = loss_het * HetN * HetN + + if (enable_3zoo2det) then + + !=========================================================================== + ! MACROZOOPLANKTON RESPIRATION (KRILL) + !=========================================================================== + ! Calculates macrozooplankton respiration with feeding-dependent stress + ! response. Poor feeding conditions increase metabolic costs. + ! + ! Variables: + ! Zoo2RespFlux : Macrozooplankton respiration [mmolC m-3 day-1] + ! res_zoo2 : Baseline respiration rate [day-1] + ! res_zoo2_f : Feeding success modifier [-] + ! res_zoo2_a : Additional respiration factor [-] + ! recip_res_zoo22 : Combined respiration coefficient [day-1] + ! Zoo2C : Macrozooplankton carbon concentration [mmolC m-3] + ! grazingFluxcarbonzoo2: Carbon ingestion rate [mmolC m-3 day-1] + ! + ! Feeding Success Response: + ! - IF specific ingestion < 0.1 day-1: Stress response activated + ! * Increases metabolic costs (searching, maintenance) + ! * res_zoo2_f scales linearly with feeding rate + ! - ELSE: Normal feeding conditions (res_zoo2_f = 1.0) + ! + ! Total Respiration: + ! RespFlux = res_zoo2 × (1 + res_zoo2_f + res_zoo2_a) × Zoo2C + ! + ! Note: Calls external subroutine krill_resp() for detailed metabolism + !--------------------------------------------------------------------------- + + ! Call detailed krill respiration subroutine + ! Handles additional physiological processes (e.g., molting, reproduction) + call krill_resp(n, partit, mesh) + + ! Calculate feeding success modifier + ! Low feeding rates trigger stress response with elevated respiration + if ((grazingFluxcarbonzoo2 / Zoo2C) <= 0.1) then + ! Stress response: metabolic costs increase linearly with feeding deficit + ! Factor of 0.1 converts to percentage basis + res_zoo2_f = 0.1 * (grazingFluxcarbonzoo2 / Zoo2C * 100.0) + else + ! Normal feeding: no additional metabolic stress + res_zoo2_f = 1.0 + end if + + ! Calculate combined respiration coefficient + ! Includes baseline + feeding stress + additional factors + recip_res_zoo22 = res_zoo2 * (1.0 + res_zoo2_f + res_zoo2_a) + + ! Calculate total respiration flux + Zoo2RespFlux = recip_res_zoo22 * Zoo2C + + !=========================================================================== + ! MACROZOOPLANKTON MORTALITY + !=========================================================================== + ! Quadratic density-dependent mortality for macrozooplankton. + ! + ! Variables: + ! Zoo2LossFlux : Macrozooplankton mortality flux [mmolN m-3 day-1] + ! loss_zoo2 : Mortality rate constant [day-1 (mmolN m-3)-1] + ! zoo2N : Macrozooplankton nitrogen concentration [mmolN m-3] + ! + ! Equation: Quadratic Mortality + ! Mortality = loss_zoo2 × zoo2N² + !--------------------------------------------------------------------------- + + Zoo2LossFlux = loss_zoo2 * zoo2N * zoo2N + + !=========================================================================== + ! MICROZOOPLANKTON RESPIRATION AND MORTALITY + !=========================================================================== + ! Calculates microzooplankton respiration and mortality. + ! Simpler than macro/mesozooplankton (no feeding-dependent stress). + ! + ! Variables: + ! MicZooRespFlux : Microzooplankton respiration [mmolC m-3 day-1] + ! MicZooLossFlux : Microzooplankton mortality [mmolN m-3 day-1] + ! res_miczoo : Respiration rate constant [day-1] + ! loss_miczoo : Mortality rate constant [day-1 (mmolN m-3)-1] + ! q10_mic_res : Q10 temperature function for micro respiration [-] + ! MicZooC : Microzooplankton carbon concentration [mmolC m-3] + ! MicZooN : Microzooplankton nitrogen concentration [mmolN m-3] + ! + ! Respiration Equation: + ! RespFlux = res_miczoo × q10_mic_res × MicZooC + ! + ! Mortality Equation: + ! Mortality = loss_miczoo × MicZooN² + !--------------------------------------------------------------------------- + + ! Temperature-dependent respiration (Q10 formulation) + ! Smaller organisms typically have higher temperature sensitivity + MicZooRespFlux = res_miczoo * q10_mic_res * MicZooC + + ! Quadratic density-dependent mortality + MicZooLossFlux = loss_miczoo * MicZooN * MicZooN + + endif ! enable_3zoo2det + + !=============================================================================== + ! FECAL PELLET PRODUCTION + !=============================================================================== + ! Calculates fecal pellet production from mesozooplankton and macrozooplankton. + ! Fecal pellets are key to the biological carbon pump due to fast sinking. + ! + ! Fecal pellets represent: + ! - Undigested/unassimilated food material + ! - Packaged waste with high sinking velocity (100-1000 m/day) + ! - Major pathway for carbon export to deep ocean + ! - Important food source for deep-sea organisms + ! + ! Variables: + ! Zoo2fecalloss_n : Macrozooplankton fecal N [mmolN m-3 day-1] + ! Zoo2fecalloss_c : Macrozooplankton fecal C [mmolC m-3 day-1] + ! mesfecalloss_n : Mesozooplankton fecal N [mmolN m-3 day-1] + ! mesfecalloss_c : Mesozooplankton fecal C [mmolC m-3 day-1] + ! fecal_rate_n : Fecal production rate for N [fraction of ingestion] + ! fecal_rate_c : Fecal production rate for C [fraction of ingestion] + ! fecal_rate_n_mes : Mesozooplankton N fecal rate [-] + ! fecal_rate_c_mes : Mesozooplankton C fecal rate [-] + ! grazingFlux2 : Macrozooplankton N ingestion [mmolN m-3 day-1] + ! grazingFlux : Mesozooplankton N ingestion [mmolN m-3 day-1] + ! grazingFluxcarbonzoo2 : Macro C ingestion [mmolC m-3 day-1] + ! grazingFluxcarbon_mes : Meso C ingestion [mmolC m-3 day-1] + ! + ! Equation: + ! Fecal_flux = fecal_rate × ingestion_flux + ! Fecal rate typically 10-30% of ingestion (remainder is assimilated) + ! + ! Note: Fecal C:N ratio may differ from prey due to selective digestion + !------------------------------------------------------------------------------- + + if (enable_3zoo2det) then + + !--------------------------------------------------------------------------- + ! Macrozooplankton Fecal Pellet Production + !--------------------------------------------------------------------------- + ! Larger zooplankton produce larger, faster-sinking fecal pellets + + Zoo2fecalloss_n = fecal_rate_n * grazingFlux2 ! Nitrogen + Zoo2fecalloss_c = fecal_rate_c * grazingFluxcarbonzoo2 ! Carbon + + !--------------------------------------------------------------------------- + ! Mesozooplankton Fecal Pellet Production + !--------------------------------------------------------------------------- + ! Smaller fecal pellets than macrozooplankton but still fast-sinking + + mesfecalloss_n = fecal_rate_n_mes * grazingFlux ! Nitrogen + mesfecalloss_c = fecal_rate_c_mes * grazingFluxcarbon_mes ! Carbon + + endif ! enable_3zoo2det + + !=============================================================================== + ! PHYTOPLANKTON AND DETRITUS AGGREGATION + !=============================================================================== + ! Calculates particle aggregation that forms larger, faster-sinking particles. + ! Critical process for biological carbon pump and export production. + ! + ! Aggregation mechanisms: + ! - Particle collision and sticking (Brownian motion, shear, settling) + ! - Diatom mucus production enhances aggregation (nutrient stress response) + ! - Transparent exopolymer particles (TEP) glue particles together + ! + ! Variables: + ! aggregationrate : Total particle aggregation rate [mmolN m-3 day-1] + ! agg_PP : Phytoplankton-phytoplankton aggregation rate [day-1] + ! agg_PD : Phytoplankton-detritus aggregation rate [day-1] + ! PhyN, DiaN : Phytoplankton nitrogen concentrations [mmolN m-3] + ! CoccoN, PhaeoN : Coccolithophore and Phaeocystis N [mmolN m-3] + ! DetN, DetZ2N : Slow and fast-sinking detritus N [mmolN m-3] + ! qlimitFac : Nutrient limitation factor (0=replete, 1=limited) [-] + ! feLimitFac : Iron limitation factor [-] + ! quota_dia : Diatom N:C quota [mmolN mmolC-1] + ! qSiC : Diatom Si:C quota [mmolSi mmolC-1] + ! + ! Note: Aggregation products enter fast-sinking detritus pool (DetZ2N) + !------------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Diatom Mucus-Enhanced Aggregation (Optional) + !--------------------------------------------------------------------------- + ! Nutrient limitation triggers diatom mucus production, enhancing aggregation + ! and forming large, rapidly-sinking marine snow aggregates. + + if (diatom_mucus) then + + !----------------------------------------------------------------------- + ! Calculate nutrient limitation factors + !----------------------------------------------------------------------- + + ! Nitrogen limitation factor + ! Uses limiter function: returns 0 when quota is high (replete) + ! returns 1 when quota is low (limited) + qlimitFac = recom_limiter(NMinSlope, NCmin_d, quota_dia) + + ! Silicon limitation factor + ! Diatoms require silica for frustule (shell) formation + qlimitFacTmp = recom_limiter(SiMinSlope, SiCmin, qSiC) + qlimitFac = min(qlimitFac, qlimitFacTmp) ! Most limiting nutrient + + ! Iron limitation factor + ! Iron is essential for photosynthesis and often limiting in ocean + feLimitFac = Fe / (k_Fe_d + Fe) + qlimitFac = min(qlimitFac, feLimitFac) ! Most limiting of all nutrients + + ! Calculate mucus-enhanced aggregation rate + ! Aggregation increases with nutrient stress (high limitation factor) + ! Factor (1 - qlimitFac): 0 when replete, 1 when severely limited + aggregationrate = agg_PP * (1.0 - qlimitFac) * DiaN + + else + + !----------------------------------------------------------------------- + ! Simple aggregation without nutrient limitation effect + !----------------------------------------------------------------------- + aggregationrate = agg_PP * DiaN + + endif + + !--------------------------------------------------------------------------- + ! Total Aggregation Rate + !--------------------------------------------------------------------------- + ! Sum contributions from all particle types + ! Each particle type can aggregate with itself and other particles + + ! Add small phytoplankton and detritus aggregation + aggregationrate = aggregationrate + agg_PD * DetN + agg_PP * PhyN + + if (enable_3zoo2det) then + ! Add fast-sinking detritus aggregation + aggregationrate = aggregationrate + agg_PD * DetZ2N + endif + + if (enable_coccos) then + ! Add coccolithophore and Phaeocystis aggregation + ! These can form large blooms with high aggregation potential + aggregationrate = aggregationrate + agg_PP * CoccoN + agg_PP * PhaeoN + endif + + !=============================================================================== + ! MARINE CALCIFICATION + !=============================================================================== + ! Simulates the formation and dissolution of calcium carbonate (CaCO3) in + ! marine environments, primarily through phytoplankton calcification. + ! + ! This module calculates: + ! 1. Calcification rates (organism-specific or general) + ! 2. Environmental controls on calcification (temperature, CO2, nutrients) + ! 3. Loss processes (grazing, aggregation) + ! 4. Carbon isotope fractionation (13C, 14C - optional) + ! + ! Key Features: + ! - Explicit coccolithophore calcification (temperature, CO2, nutrient effects) + ! - General small phytoplankton calcification (simplified) + ! - Ocean acidification sensitivity (CO2/carbonate chemistry effects) + ! - PIC:POC ratio variability (environmental controls on calcite production) + ! - Isotope fractionation during calcification + ! + ! Calcification Scenarios: + ! A) enable_coccos = TRUE: Explicit coccolithophore model + ! - Temperature-dependent PIC:POC ratios (Krumhardt et al. 2017, 2019) + ! - CO2/carbonate chemistry effects (ocean acidification) + ! - Nitrogen limitation effects + ! B) enable_coccos = FALSE: General small phytoplankton + ! - Fixed fraction of photosynthesis goes to calcification + ! + ! Ecological/Biogeochemical Significance: + ! - Produces ballast that increases particle sinking (biological pump) + ! - Releases CO2 during calcification (carbonate counter-pump) + ! - Major component of ocean alkalinity cycle + ! - Sensitive to ocean acidification (climate change impact) + ! + ! References: + ! - Krumhardt et al. (2017, 2019) - Coccolithophore parameterization + ! - Gürses et al. (2023) - REcoM2 model description + !=============================================================================== + + !=============================================================================== + ! CALCIFICATION RATE CALCULATION + !=============================================================================== + ! Calculates the rate at which calcium carbonate (CaCO3) is formed by marine + ! organisms, with environmental modulation of the PIC:POC ratio. + ! + ! PIC = Particulate Inorganic Carbon (CaCO3) + ! POC = Particulate Organic Carbon (photosynthetic biomass) + ! + ! Variables (Coccolithophore mode): + ! calcification : CaCO3 formation rate [mmolC m-3 day-1] + ! Cphot_cocco : Coccolithophore C-specific photosynthesis [day-1] + ! CoccoC : Coccolithophore carbon concentration [mmolC m-3] + ! PICPOCtemp : Temperature modifier for PIC:POC ratio [-] + ! PICPOCCO2 : CO2/carbonate chemistry modifier for PIC:POC [-] + ! PICPOCN : Nitrogen limitation modifier for PIC:POC [-] + ! Temp(k) : Temperature at depth k [degC] + ! HCO3_watercolumn: Bicarbonate concentration [mmolC m-3] + ! CO2_watercolumn : Dissolved CO2 concentration [mmolC m-3] + ! pH_watercolumn : Water column pH [-] + ! DIN : Dissolved inorganic nitrogen [mmolN m-3] + ! k_din_c : Half-saturation for DIN effect on calcification [mmolN m-3] + ! a,b,c,d_co2_calc: CO2 effect parameters [-] + ! Cunits : Conversion factor for units [-] + ! + ! Variables (General phytoplankton mode): + ! calc_prod_ratio : Fixed calcification:photosynthesis ratio [-] + ! Cphot : Small phytoplankton photosynthesis rate [day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + !------------------------------------------------------------------------------- + + if (enable_coccos) then + + !=========================================================================== + ! COCCOLITHOPHORE-SPECIFIC CALCIFICATION + !=========================================================================== + ! Coccolithophores are marine phytoplankton that produce calcite plates + ! (coccoliths) as an external protective covering. + ! + ! Environmental Controls: + ! - Temperature: Optimum calcification at warm temperatures (>10.6degC) + ! - CO2: Ocean acidification reduces calcification efficiency + ! - Nitrogen: High nutrient availability reduces PIC:POC ratio + !--------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Temperature Effect on PIC:POC Ratio + !--------------------------------------------------------------------------- + ! Based on Krumhardt et al. (2017, 2019) parameterization + ! Warmer temperatures favor higher calcification efficiency + + if (Temp(k) < 10.6) then + ! Linear relationship for temperatures below 10.6degC + ! Calcification efficiency increases with temperature + PICPOCtemp = 0.104d0 * Temp(k) - 0.108d0 + else + ! Maximum efficiency at temperatures ≥ 10.6degC + ! Represents optimal conditions for coccolith formation + PICPOCtemp = 1.0d0 + end if + + ! Prevent negative values (can occur at very low temperatures) + PICPOCtemp = max(tiny, PICPOCtemp) + + !--------------------------------------------------------------------------- + ! CO2/Carbonate Chemistry Effect on PIC:POC Ratio + !--------------------------------------------------------------------------- + ! Complex function representing ocean acidification impacts + ! Three components: + ! 1. HCO3- availability (substrate for calcification) + ! 2. High CO2 inhibition (ocean acidification stress) + ! 3. Low pH inhibition (direct pH stress on calcification) + + PICPOCCO2 = a_co2_calc * HCO3_watercolumn(k) * Cunits / (b_co2_calc + HCO3_watercolumn(k) * Cunits) & + - exp(-c_co2_calc * CO2_watercolumn(k) * Cunits) & + - d_co2_calc * 10.d0**(-pH_watercolumn(k)) + + ! Apply empirical constraints to CO2 effect + PICPOCCO2 = min(PICPOCCO2, 3.d0) ! Upper limit (April 2022 modification) + PICPOCCO2 = max(0.d0, PICPOCCO2) ! Lower limit (July 2022 modification) + + !--------------------------------------------------------------------------- + ! Nitrogen Limitation Effect on PIC:POC Ratio + !--------------------------------------------------------------------------- + ! Higher DIN availability reduces calcification efficiency + ! Ecological rationale: Under nutrient replete conditions, organisms + ! allocate resources preferentially to organic carbon (growth) rather + ! than calcite plates (protection) + + PICPOCN = -0.31 * (DIN / (DIN + k_din_c)) + 1.31 + PICPOCN = max(tiny, PICPOCN) ! Prevent negative values + + !--------------------------------------------------------------------------- + ! Calculate Final Coccolithophore Calcification Rate + !--------------------------------------------------------------------------- + ! Combine photosynthesis rate with all environmental modifiers + ! Base rate × Temperature effect × Nutrient effect + + calcification = 1.d0 * Cphot_cocco * CoccoC * PICPOCtemp * PICPOCN + + ! Apply CO2 limitation if ocean acidification sensitivity is enabled + if (CO2lim) then + calcification = calcification * PICPOCCO2 + end if + + else + + !=========================================================================== + ! GENERAL SMALL PHYTOPLANKTON CALCIFICATION + !=========================================================================== + ! Simplified approach: calcification as a fixed fraction of photosynthesis + ! Used when coccolithophores are not explicitly represented + ! Represents calcification by other small calcifying organisms + !--------------------------------------------------------------------------- + + calcification = calc_prod_ratio * Cphot * PhyC + + endif + + !=============================================================================== + ! CALCIFICATION LOSS PROCESSES + !=============================================================================== + ! Calculates removal of calcified material through grazing and aggregation. + ! These processes transfer CaCO3 to zooplankton or sinking particles. + ! + ! Variables: + ! calc_loss_agg : CaCO3 loss through aggregation [mmolC m-3 day-1] + ! calc_loss_gra : CaCO3 loss to primary grazer [mmolC m-3 day-1] + ! calc_loss_gra2 : CaCO3 loss to secondary grazer [mmolC m-3 day-1] + ! calc_loss_gra3 : CaCO3 loss to tertiary grazer [mmolC m-3 day-1] + ! PhyCalc : Phytoplankton calcite content [mmolC m-3] + ! aggregationrate : Particle aggregation rate [mmolN m-3 day-1] + ! recipQuota : Small phytoplankton C:N ratio [mmolC mmolN-1] + ! recipQuota_Cocco: Coccolithophore C:N ratio [mmolC mmolN-1] + ! grazingFlux_* : Grazing rates on different prey [mmolN m-3 day-1] + ! aux : Auxiliary conversion factor [mmolC mmolN-1] + ! + ! Note: CaCO3 in grazed material can dissolve in zooplankton guts or + ! provide ballast for fecal pellets (enhancing sinking) + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Aggregation Loss + !------------------------------------------------------------------------------- + ! CaCO3 is incorporated into aggregates (marine snow) that sink rapidly + ! Provides ballast effect: increases particle density and sinking velocity + + calc_loss_agg = aggregationrate * PhyCalc + + if (enable_coccos) then + + !--------------------------------------------------------------------------- + ! Coccolithophore Grazing Losses + !--------------------------------------------------------------------------- + ! Calculate CaCO3 consumed by grazers feeding on coccolithophores + ! Requires conversion from nitrogen-based grazing to carbon flux + + ! Calculate auxiliary conversion factor (CaCO3:N ratio in coccolithophores) + aux = recipQuota_Cocco / (CoccoC + tiny) * PhyCalc + + ! Primary grazer (mesozooplankton) consumption + calc_loss_gra = grazingFlux_Cocco * aux + + if (enable_3zoo2det) then + ! Secondary grazer (macrozooplankton) consumption + calc_loss_gra2 = grazingFlux_Cocco2 * aux + + ! Tertiary grazer (microzooplankton) consumption + calc_loss_gra3 = grazingFlux_Cocco3 * aux + endif + + else + + !--------------------------------------------------------------------------- + ! Small Phytoplankton Grazing Losses + !--------------------------------------------------------------------------- + ! Calculate CaCO3 consumed by grazers feeding on calcifying small phytoplankton + + ! Calculate auxiliary conversion factor (CaCO3:N ratio in small phytoplankton) + aux = recipQuota / (PhyC + tiny) * PhyCalc + + ! Primary grazer (mesozooplankton) consumption + calc_loss_gra = grazingFlux_phy * aux + + if (enable_3zoo2det) then + ! Secondary grazer (macrozooplankton) consumption + calc_loss_gra2 = grazingFlux_phy2 * aux + + ! Tertiary grazer (microzooplankton) consumption + calc_loss_gra3 = grazingFlux_phy3 * aux + endif + + endif + + !=============================================================================== + ! CARBON ISOTOPE FRACTIONATION + !=============================================================================== + ! Handles carbon-13 and carbon-14 isotope fractionation during calcification + ! and loss processes. Used for paleoclimate reconstructions and carbon cycle + ! studies. + ! + ! Isotope Fractionation: + ! - Light isotopes (12C) are preferentially incorporated during calcification + ! - Fractionation factors (alpha) quantify this discrimination + ! - Different fractionation for 13C and 14C + ! + ! Variables: + ! calcification_13 : 13C calcification rate [mmol13C m-3 day-1] + ! calcification_14 : 14C calcification rate [mmol14C m-3 day-1] + ! alpha_calc_13 : 13C fractionation factor during calcification [-] + ! alpha_calc_14 : 14C fractionation factor during calcification [-] + ! calc_loss_agg_13/14 : Isotope losses through aggregation [mmol m-3 day-1] + ! calc_loss_gra_13/14 : Isotope losses through grazing [mmol m-3 day-1] + ! PhyCalc_13/14 : Phytoplankton calcite isotope content [mmol m-3] + ! PhyC_13/14 : Phytoplankton organic carbon isotopes [mmol m-3] + ! recipQuota_13/14 : Isotope-specific C:N ratios [mmol mmol-1] + ! + ! Applications: + ! - 13C: Paleoclimate proxies, carbon source tracing + ! - 14C: Radiocarbon dating, carbon residence times + ! + ! Note: Only executed if carbon isotope tracking is enabled (ciso = TRUE) + !------------------------------------------------------------------------------- + + if (ciso) then + + !=========================================================================== + ! Carbon-13 Isotope Calculations + !=========================================================================== + ! Track 13C through calcification and loss processes + !--------------------------------------------------------------------------- + + ! Calcification with isotopic fractionation + ! Alpha factor < 1 means light isotope (12C) is preferentially incorporated + calcification_13 = calcification * alpha_calc_13 + + ! Isotopic losses through aggregation + ! Assumes no fractionation during physical aggregation process + calc_loss_agg_13 = aggregationRate * PhyCalc_13 + + ! Isotopic losses through grazing + ! Requires isotope-specific conversion factor + calc_loss_gra_13 = grazingFlux_phy * recipQuota_13 / (PhyC_13 + tiny) * PhyCalc_13 + + if (ciso_14 .and. ciso_organic_14) then + + !======================================================================= + ! Carbon-14 Isotope Calculations + !======================================================================= + ! Track radiocarbon (14C) through calcification and loss processes + ! Used for determining carbon residence times and age dating + !----------------------------------------------------------------------- + + ! Calcification with 14C fractionation + ! 14C fractionation is approximately twice that of 13C + calcification_14 = calc_prod_ratio * Cphot * PhyC_14 * alpha_calc_14 + + ! 14C losses through aggregation + calc_loss_agg_14 = aggregationRate * PhyCalc_14 + + ! 14C losses through grazing + calc_loss_gra_14 = grazingFlux_phy * recipQuota_14 / (PhyC_14 + tiny) * PhyCalc_14 + + end if ! ciso_14 .and. ciso_organic_14 + + end if ! ciso + + !=============================================================================== + ! 1. DISSOLVED INORGANIC NITROGEN (DIN) + !=============================================================================== + ! Represents the pool of bioavailable nitrogen (nitrate + ammonium) + ! + ! Variables: + ! N_assim : N assimilation rate for small phytoplankton [mmolN mmolC-1 day-1] + ! N_assim_Dia : N assimilation rate for diatoms [mmolN mmolC-1 day-1] + ! N_assim_Cocco : N assimilation rate for coccolithophore [mmolN mmolC-1 day-1] + ! N_assim_Phaeo : N assimilation rate for Phaeocystis [mmolN mmolC-1 day-1] + ! PhyC, DiaC : Intracellular carbon concentration [mmolC m-3] + ! CoccoC, PhaeoC : Intracellular carbon concentration [mmolC m-3] + ! rho_N : Remineralization rate constant [day-1] + ! arrFunc : Arrhenius temperature dependency function [-] + ! O2Func : O2 dependency of organic matter remineralization [-] + ! DON : Dissolved organic nitrogen [mmolN m-3] + ! dt_b : REcoM time step [day] + ! + ! Equation Reference: Schourup-Kristensen 2013, Eq. A2 + + sms(k,idin) = ( & + !--------------------------------------------------------------------------- + ! SINKS: Nitrogen Uptake (decreases DIN) + !--------------------------------------------------------------------------- + ! Phytoplankton assimilation of NO3- and NH4+ + - N_assim * PhyC & ! Small phytoplankton + - N_assim_Dia * DiaC & ! Diatoms + - N_assim_Cocco * CoccoC * is_coccos & ! Coccolithophores + - N_assim_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SOURCES: Remineralization (increases DIN) + !--------------------------------------------------------------------------- + ! DON remineralization releases bioavailable nitrogen + + rho_N * arrFunc * O2Func * DON & ! Temperature and O2 dependent + ) * dt_b + sms(k,idin) + + !=============================================================================== + ! 2. DISSOLVED INORGANIC CARBON (DIC) + !=============================================================================== + ! Represents the pool of inorganic carbon (CO2 + HCO3- + CO3-2) + ! + ! Variables: + ! Cphot : Small phytoplankton photosynthesis rate [day-1] + ! Cphot_Dia : Diatom photosynthesis rate [day-1] + ! Cphot_Cocco : Coccolithophore photosynthesis rate [day-1] + ! Cphot_Phaeo : Phaeocystis photosynthesis rate [day-1] + ! phyRespRate : Small phytoplankton respiration rate [day-1] + ! phyRespRate_Dia : Diatom respiration rate [day-1] + ! phyRespRate_Cocco : Coccolithophore respiration rate [day-1] + ! phyRespRate_Phaeo : Phaeocystis respiration rate [day-1] + ! rho_C1 : Temperature-dependent DOC degradation rate [day-1] + ! EOC : Extracellular organic carbon [mmolC m-3] + ! HetRespFlux : Mesozooplankton respiration flux [mmolC m-3 day-1] + ! Zoo2RespFlux : Macrozooplankton respiration flux [mmolC m-3 day-1] + ! MicZooRespFlux : Microzooplankton respiration flux [mmolC m-3 day-1] + ! calc_diss : Slow-sinking calcite dissolution rate [day-1] + ! calc_diss2 : Fast-sinking calcite dissolution rate [day-1] + ! DetCalc : Slow-sinking calcite detritus pool [mmolC m-3] + ! DetZ2Calc : Fast-sinking calcite detritus pool [mmolC m-3] + ! calc_loss_gra : Calcite loss via mesozooplankton grazing [mmolC m-3 day-1] + ! calc_loss_gra2 : Calcite loss via macrozooplankton grazing [mmolC m-3 day-1] + ! calc_loss_gra3 : Calcite loss via microzooplankton grazing [mmolC m-3 day-1] + ! calc_diss_guts : Calcite dissolution rate in zooplankton guts [-] + ! calcification : Rate of CaCO3 formation [mmolC m-3 day-1] + + sms(k,idic) = ( & + !--------------------------------------------------------------------------- + ! SINKS: Carbon Fixation (decreases DIC) + !--------------------------------------------------------------------------- + ! Photosynthetic uptake of CO2 by phytoplankton + - Cphot * PhyC & ! Small phytoplankton + - Cphot_Dia * DiaC & ! Diatoms + - Cphot_Cocco * CoccoC * is_coccos & ! Coccolithophores + - Cphot_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SINKS: Calcification (decreases DIC) + !--------------------------------------------------------------------------- + ! CaCO3 formation: Ca2+ + CO3-2 -> CaCO3 + - calcification & + !--------------------------------------------------------------------------- + ! SOURCES: Phytoplankton Respiration (increases DIC) + !--------------------------------------------------------------------------- + ! Release of CO2 through autotrophic respiration + + phyRespRate * PhyC & ! Small phytoplankton + + phyRespRate_Dia * DiaC & ! Diatoms + + phyRespRate_Cocco * CoccoC * is_coccos & ! Coccolithophores + + phyRespRate_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SOURCES: DOC Remineralization (increases DIC) + !--------------------------------------------------------------------------- + ! Microbial degradation of dissolved organic carbon + + rho_C1 * arrFunc * O2Func * EOC & ! Temperature and O2 dependent + !--------------------------------------------------------------------------- + ! SOURCES: Zooplankton Respiration (increases DIC) + !--------------------------------------------------------------------------- + ! Release of CO2 through heterotrophic respiration + + HetRespFlux & ! Mesozooplankton + + Zoo2RespFlux * is_3zoo2det & ! Macrozooplankton + + MicZooRespFlux * is_3zoo2det & ! Microzooplankton + !--------------------------------------------------------------------------- + ! SOURCES: Calcite Dissolution (increases DIC) + !--------------------------------------------------------------------------- + ! Reaction: CaCO3 + CO2 + H2O -> Ca2+ + 2HCO3- + + calc_diss * DetCalc & ! Slow-sinking calcite + + calc_loss_gra * calc_diss_guts & ! Mesozooplankton gut + + calc_loss_gra2 * calc_diss_guts * is_3zoo2det & ! Macrozooplankton gut + + calc_loss_gra3 * calc_diss_guts * is_3zoo2det & ! Microzooplankton gut + + calc_diss2 * DetZ2Calc * is_3zoo2det & ! Fast-sinking calcite + ) * dt_b + sms(k,idic) ! if((Latd(1)<-45.0) .and. ((state(k,idic)+sms(k,idic))>2500)) then ! !co2flux(1)=0.0 @@ -1135,1048 +4005,3079 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & ! stop ! endif -!< *** Alk *** -!< *********** - -!< Alkalinity (Assumes that N:P follows a constant Redfield ratio -!< N_assimC: 1.0625 = 1/16 + 1 - - sms(k,ialk) = ( & - + 1.0625 * N_assim * PhyC & - + 1.0625 * N_assim_Dia * DiaC & -#if defined (__coccos) - + 1.0625 * N_assim_Cocco * CoccoC & -#endif - - 1.0625 * rho_N * arrFunc * O2Func * DON & ! O2remin - + 2.d0 * calc_diss * DetCalc & - + 2.d0 * calc_loss_gra * calc_diss_guts & -#if defined (__3Zoo2Det) - + 2.d0 * calc_loss_gra2 * calc_diss_guts & - + 2.d0 * calc_loss_gra3 * calc_diss_guts & ! 3Zoo - + 2.d0 * calc_diss2 * DetZ2Calc & -#endif - - 2.d0 * calcification & - ) * dt_b + sms(k,ialk) -!< *** Small Phytoplankton *** -!< *************************** - -!____________________________________________________________ -!< Small phytoplankton N - -!< lossN: Phytoplankton loss of organic N compounds [day^-1] - - sms(k,iphyn) = ( & - + N_assim * PhyC & ! --> N assimilation - - lossN * limitFacN * PhyN & ! --> DON excretion - - aggregationRate * PhyN & ! --> Aggregation loss - - grazingFlux_phy & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_phy2 & - - grazingFlux_phy3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphyn) -!____________________________________________________________ -!< Small phytoplankton C - -!< lossC: Phytoplankton loss of carbon [day^-1] -!< When N : C ratio becomes too high, excretion of DOC is downregulated -!< by the limiter function limitFacN -!< aggregationRate transfers C to the detritus pool - - sms(k,iphyc) = ( & - + Cphot * PhyC & ! --> Photosynthesis ---->/ - - lossC * limitFacN * PhyC & ! --> Excretion of DOC / Net photosynthesis - - phyRespRate * PhyC & ! --> Respiration ----->/ - - aggregationRate * PhyC & ! --> Aggregation loss - - grazingFlux_phy * recipQuota & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_phy2 * recipQuota & - - grazingFlux_phy3 * recipQuota & ! 3Zoo -#endif - ) * dt_b + sms(k,iphyc) -!____________________________________________________________ -! Phytoplankton ChlA - -!< Chl2N: Conversion factor from mmolN to mgChla -!< Chl2N = PhyChl/PhyN - - sms(k,ipchl) = ( & - + chlSynth * PhyC & ! --> Chl-a synthesis - - KOchl * PhyChl & ! --> Degradation loss - - aggregationRate * PhyChl & ! --> Aggregation loss - - grazingFlux_phy * Chl2N & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_phy2 * Chl2N & - - grazingFlux_phy3 * Chl2N & ! 3Zoo -#endif - ) * dt_b + sms(k,ipchl) - -!< *** Slow-sinking Detritus *** -!< ***************************** - -!____________________________________________________________ -! Detritus N - if (Grazing_detritus) then -#if defined (__3Zoo2Det) - sms(k,idetn) = ( & - + grazingFlux_phy3 & - - grazingFlux_phy3 * grazEff3 & - + grazingFlux_dia3 & - - grazingFlux_dia3 * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 & - - grazingFlux_Cocco3 * grazEff3 & - + aggregationRate * CoccoN & -#endif - - grazingFlux_Det * grazEff & - - grazingFlux_Det2 * grazEff2 & ! --> okay, grazing of second zoo on first detritus - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + miczooLossFlux & - - reminN * arrFunc * O2Func * DetN & ! O2remin - ) * dt_b + sms(k,idetn) -#else - sms(k,idetn) = ( & - + grazingFlux_phy & - - grazingFlux_phy * grazEff & - + grazingFlux_dia & - - grazingFlux_dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco & - - grazingFlux_Cocco * grazEff & - + aggregationRate * CoccoN & -#endif - - grazingFlux_Det * grazEff & ! Sloppy feeding is thought because of grazing flux multiplied with grazeff - - grazingFlux_Det2 * grazEff2 & !!!!!!!!!!CHECK - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + hetLossFlux & - - reminN * arrFunc * O2Func * DetN & ! O2remin - ) * dt_b + sms(k,idetn) -#endif - else -#if defined (__3Zoo2Det) - sms(k,idetn) = ( & - + grazingFlux_phy3 & - + grazingFlux_dia3 & -#if defined (__coccos) - + grazingFlux_Cocco3 & - + aggregationRate * CoccoN & -#endif - - grazingFlux * grazEff3 & - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + miczooLossFlux & - - reminN * arrFunc * O2Func * DetN & ! O2remin - ) * dt_b + sms(k,idetn) -#else - sms(k,idetn) = ( & - + grazingFlux_phy & - + grazingFlux_dia & -#if defined (__coccos) - + grazingFlux_Cocco & - + aggregationRate * CoccoN & -#endif - - grazingFlux * grazEff & - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + hetLossFlux & - - reminN * arrFunc * O2Func * DetN & ! O2remin - ) * dt_b + sms(k,idetn) -#endif - end if - -!____________________________________________________________ -! Detritus C - if (Grazing_detritus) then -#if defined (__3Zoo2Det) - sms(k,idetc) = ( & - + grazingFlux_phy3 * recipQuota & - - grazingFlux_phy3 * recipQuota * grazEff3 & - + grazingFlux_Dia3 * recipQuota_Dia & - - grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 * recipQuota_Cocco & - - grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & - + aggregationRate * CoccoC & -#endif - - grazingFlux_Det * recipDet * grazEff & - - grazingFlux_Det2 * recipDet2 * grazEff2 & - + aggregationRate * PhyC & - + aggregationRate * DiaC & - + miczooLossFlux * recipQZoo3 & - - reminC * arrFunc * O2Func * DetC & ! O2remin - ) * dt_b + sms(k,idetc) -#else - sms(k,idetc) = ( & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + aggregationRate * CoccoC & -#endif - - grazingFlux_Det * recipDet * grazEff & - - grazingFlux_Det2 * recipDet2 * grazEff & !!!!!! CHECK - + aggregationRate * phyC & - + aggregationRate * DiaC & - + hetLossFlux * recipQZoo & - - reminC * arrFunc * O2Func * DetC & ! O2remin - ) * dt_b + sms(k,idetc) -#endif - else -#if defined (__3Zoo2Det) - sms(k,idetc) = ( & - + grazingFlux_phy3 * recipQuota & - - grazingFlux_phy3 * recipQuota * grazEff3 & - + grazingFlux_Dia3 * recipQuota_Dia & - - grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 * recipQuota_Cocco & - - grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & - + aggregationRate * CoccoC & -#endif - + aggregationRate * PhyC & - + aggregationRate * DiaC & - + miczooLossFlux * recipQZoo3 & - - reminC * arrFunc * O2Func * DetC & ! O2remin - ) * dt_b + sms(k,idetc) -#else - sms(k,idetc) = ( & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + aggregationRate * CoccoC & -#endif - + aggregationRate * phyC & - + aggregationRate * DiaC & - + hetLossFlux * recipQZoo & - - reminC * arrFunc * O2Func * DetC & ! O2remin - ) * dt_b + sms(k,idetc) -#endif - end if - -!< *** Mesozooplankton *** -!< *********************** - -!____________________________________________________________ -!< Heterotrophic N - sms(k,ihetn) = ( & - + grazingFlux * grazEff & ! --> Grazing on phytoplankton -> okay, because of recipQuota -#if defined (__3Zoo2Det) - - grazingFlux_het2 & - - Mesfecalloss_n & ! 3Zoo -#endif - - hetLossFlux & ! --> Mortality - - lossN_z * HetN & ! --> Excretion of DON - ) * dt_b + sms(k,ihetn) -!____________________________________________________________ -!< Heterotrophic C + !=============================================================================== + ! 3. ALKALINITY (Alk) + !=============================================================================== + ! Total alkalinity affects ocean pH and CO2 uptake capacity + ! Assumes constant Redfield N:P ratio + ! + ! Key coefficient: 1.0625 = (1/16) + 1 + ! - Represents the change in alkalinity per mole of nitrogen + ! - Includes both nitrate reduction (+ charge) and phosphate uptake + + sms(k,ialk) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Nutrient Uptake (increases alkalinity) + !--------------------------------------------------------------------------- + ! Phytoplankton uptake of NO3- increases alkalinity + + 1.0625 * N_assim * PhyC & ! Small phytoplankton + + 1.0625 * N_assim_Dia * DiaC & ! Diatoms + + 1.0625 * N_assim_Cocco * CoccoC * is_coccos & ! Coccolithophores + + 1.0625 * N_assim_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + + !--------------------------------------------------------------------------- + ! SINKS: Remineralization (decreases alkalinity) + !--------------------------------------------------------------------------- + ! DON remineralization releases H+ and decreases alkalinity + - 1.0625 * rho_N * arrFunc * O2Func * DON & + !--------------------------------------------------------------------------- + ! SOURCES: Calcite Dissolution (increases alkalinity) + !--------------------------------------------------------------------------- + ! Reaction: CaCO3 + CO2 + H2O -> Ca2+ + 2HCO3- + ! Increases alkalinity by 2 equivalents per mole CaCO3 + + 2.d0 * calc_diss * DetCalc & ! Slow-sinking calcite + + 2.d0 * calc_loss_gra * calc_diss_guts & ! Mesozooplankton gut + + 2.d0 * calc_loss_gra2 * calc_diss_guts * is_3zoo2det & ! Macrozooplankton gut + + 2.d0 * calc_loss_gra3 * calc_diss_guts * is_3zoo2det & ! Microzooplankton gut + + 2.d0 * calc_diss2 * DetZ2Calc * is_3zoo2det & ! Fast-sinking calcite + + !--------------------------------------------------------------------------- + ! SINKS: Calcification (decreases alkalinity) + !--------------------------------------------------------------------------- + ! CaCO3 formation removes 2 equivalents of alkalinity + - 2.d0 * calcification & + ) * dt_b + sms(k,ialk) + + !=============================================================================== + ! SMALL PHYTOPLANKTON NITROGEN (PhyN) + !=============================================================================== + ! Tracks the nitrogen content of small phytoplankton + ! + ! Variables: + ! N_assim : N assimilation rate [day-1] + ! lossN : N loss rate [day-1] + ! limitFacN : Limiter function for N:C ratio regulation [-] + ! aggregationRate : Aggregation to detritus [day-1] + ! grazingFlux_phy : Mesozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_phy2 : Macrozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_phy3 : Microzooplankton grazing [mmolN m-3 day-1] + + sms(k,iphyn) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Nitrogen Assimilation + !--------------------------------------------------------------------------- + + N_assim * PhyC & + !--------------------------------------------------------------------------- + ! SINKS: Losses + !--------------------------------------------------------------------------- + - lossN * limitFacN * PhyN & ! DON excretion (N:C regulated) + - aggregationRate * PhyN & ! Aggregation to detritus + - grazingFlux_phy & ! Mesozooplankton + - grazingFlux_phy2 * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phy3 * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphyn) + + !=============================================================================== + ! 5. SMALL PHYTOPLANKTON CARBON (PhyC) + !=============================================================================== + ! Tracks the carbon content of small phytoplankton. + ! + ! Variables: + ! Cphot : Gross photosynthesis rate [day-1] + ! phyRespRate : Autotrophic respiration rate [day-1] + ! lossC : C loss rate [day-1] + ! recipQuota : Reciprocal of N:C quota (for N->C conversion) [-] + ! + ! Note: DOC excretion is downregulated by limitFacN when N:C ratio is too high + + sms(k,iphyc) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Net Photosynthesis + !--------------------------------------------------------------------------- + + Cphot * PhyC & ! Gross photosynthesis + - phyRespRate * PhyC & ! Autotrophic respiration + !--------------------------------------------------------------------------- + ! SINKS: Losses + !--------------------------------------------------------------------------- + - lossC * limitFacN * PhyC & ! DOC excretion (regulated) + - aggregationRate * PhyC & ! Aggregation to detritus + - grazingFlux_phy * recipQuota & ! Mesozooplankton (N->C) + - grazingFlux_phy2 * recipQuota * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phy3 * recipQuota * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphyc) + + !=============================================================================== + ! 6. PHYTOPLANKTON CHLOROPHYLL-A (PhyChl) + !=============================================================================== + ! Tracks chlorophyll-a content for light harvesting and photoacclimation + ! + ! Variables: + ! chlSynth : Chlorophyll synthesis rate [mgChl mmolC-1 day-1] + ! KOchl : Chlorophyll degradation rate constant [day-1] + ! Chl2N : Chl:N ratio = PhyChl/PhyN [mgChl mmolN-1] + + sms(k,ipchl) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Chlorophyll Synthesis + !--------------------------------------------------------------------------- + + chlSynth * PhyC & ! Photoacclimation + !--------------------------------------------------------------------------- + ! SINKS: Degradation and Losses + !--------------------------------------------------------------------------- + + - KOchl * PhyChl & ! Natural degradation + - aggregationRate * PhyChl & ! Aggregation to detritus + - grazingFlux_phy * Chl2N & ! Mesozooplankton + - grazingFlux_phy2 * Chl2N * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phy3 * Chl2N * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,ipchl) + + !=============================================================================== + ! 7. DETRITUS NITROGEN (DetN) + !=============================================================================== + ! Tracks nitrogen content in slow-sinking organic particles. + ! + ! Key Concepts: + ! - Sloppy Feeding: Not all grazed material is assimilated + ! Net detritus = Total grazing × (1 - grazing efficiency) + ! - Four Configurations: Based on Grazing_detritus and enable_3zoo2det flags + ! + ! Variables: + ! grazEff, grazEff2, grazEff3 : Grazing efficiency (assimilation) [-] + ! aggregationRate : Aggregation rate [day-1] + ! hetLossFlux, miczooLossFlux : Zooplankton mortality [mmolN m-3 day-1] + ! reminN : Remineralization rate [day-1] + ! arrFunc : Arrhenius temperature function [-] + ! O2Func : Oxygen limitation function [-] + ! grazingFlux_phy3, grazingFlux_dia3 : Grazing by microzooplankton [mmolN m-3 day-1] + ! grazingFlux_phy, grazingFlux_dia : Grazing by mesozooplankton [mmolN m-3 day-1] + ! DetN : Detrital nitrogen concentration [mmolN m-3] + ! dt_b : Time step [day] + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Configuration 1: WITH Detritus Grazing + 3 Zooplankton Types + !------------------------------------------------------------------------------- + + if (Grazing_detritus) then + if (enable_3zoo2det) then + sms(k,idetn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Microzooplankton + !----------------------------------------------------------------------- + ! Net flux = Total grazing - Assimilated portion + + grazingFlux_phy3 - grazingFlux_phy3 * grazEff3 & ! Small phytoplankton + + grazingFlux_dia3 - grazingFlux_dia3 * grazEff3 & ! Diatoms + + (grazingFlux_Cocco3 - grazingFlux_Cocco3 * grazEff3) * is_coccos & ! Coccolithophores + + (grazingFlux_Phaeo3 - grazingFlux_Phaeo3 * grazEff3) * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation + !----------------------------------------------------------------------- + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + aggregationRate * CoccoN * is_coccos & + + aggregationRate * PhaeoN * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + miczooLossFlux & + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption + !----------------------------------------------------------------------- + - grazingFlux_Det * grazEff & ! Mesozooplankton + - grazingFlux_Det2 * grazEff2 & ! Macrozooplankton + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetN & ! Bacterial decomposition + ) * dt_b + sms(k,idetn) + !------------------------------------------------------------------------------- + ! Configuration 2: WITH Detritus Grazing + 2 Zooplankton Types (Standard) + !------------------------------------------------------------------------------- + else + sms(k,idetn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy - grazingFlux_phy * grazEff & ! Small phytoplankton + + grazingFlux_dia - grazingFlux_dia * grazEff & ! Diatoms + + (grazingFlux_Cocco - grazingFlux_Cocco * grazEff) * is_coccos & ! Coccolithophores + + (grazingFlux_Phaeo - grazingFlux_Phaeo * grazEff) * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation + !----------------------------------------------------------------------- + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + aggregationRate * CoccoN * is_coccos & + + aggregationRate * PhaeoN * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + hetLossFlux & + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption + !----------------------------------------------------------------------- + - grazingFlux_Det * grazEff & ! Mesozooplankton + - grazingFlux_Det2 * grazEff2 & ! Macrozooplankton + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetN & + ) * dt_b + sms(k,idetn) + endif + !------------------------------------------------------------------------------- + ! Configuration 3: WITHOUT Detritus Grazing + 3 Zooplankton Types + !------------------------------------------------------------------------------- + else + if (enable_3zoo2det) then + sms(k,idetn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Direct Transfer from Grazing + !----------------------------------------------------------------------- + ! All grazed material enters detritus (no detritus grazing) + + grazingFlux_phy3 & ! Microzooplankton->small phyto + + grazingFlux_dia3 & ! Microzooplankton->diatoms + + grazingFlux_Cocco3 * is_coccos & ! Microzooplankton->coccoliths + + grazingFlux_Phaeo3 * is_coccos & ! Microzooplankton->Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation + !----------------------------------------------------------------------- + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + aggregationRate * CoccoN * is_coccos & + + aggregationRate * PhaeoN * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + miczooLossFlux & + !----------------------------------------------------------------------- + ! SINKS: Generic Zooplankton Consumption + !----------------------------------------------------------------------- + - grazingFlux * grazEff3 & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetN & + ) * dt_b + sms(k,idetn) + + !------------------------------------------------------------------------------- + ! Configuration 4: WITHOUT Detritus Grazing + 2 Zooplankton Types + !------------------------------------------------------------------------------- + else + sms(k,idetn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Direct Transfer from Grazing + !----------------------------------------------------------------------- + + grazingFlux_phy & ! Mesozooplankton->small phyto + + grazingFlux_dia & ! Mesozooplankton->diatoms + + grazingFlux_Cocco * is_coccos & ! Mesozooplankton->coccoliths + + grazingFlux_Phaeo * is_coccos & ! Mesozooplankton->Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation + !----------------------------------------------------------------------- + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + aggregationRate * CoccoN * is_coccos & + + aggregationRate * PhaeoN * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + hetLossFlux & + !----------------------------------------------------------------------- + ! SINKS: Generic Zooplankton Consumption + !----------------------------------------------------------------------- + - grazingFlux * grazEff & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetN & + ) * dt_b + sms(k,idetn) + endif + end if + + !=============================================================================== + ! 8. DETRITUS CARBON (DetC) + !=============================================================================== + ! Tracks carbon content in slow-sinking organic particles + ! + ! Key Concepts: + ! - Stoichiometric Conversion: N-based fluxes -> C-based fluxes + ! Uses reciprocal quotas (recipQuota = C:N ratio) for conversion + ! - Sloppy Feeding: Net detritus = Total grazing × (1 - efficiency) + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N quotas for phytoplankton [-] + ! recipDet, recipDet2 : C:N ratios in detritus [-] + ! recipQZoo, recipQZoo2, recipQZoo3: C:N ratios in zooplankton [-] + ! reminC : C remineralization rate [day-1] + ! +!=============================================================================== +! KEY CONCEPTS: +!=============================================================================== +! 1. SLOPPY FEEDING: Not all grazed material is assimilated +! - Net detritus production = Total grazing × (1 - grazing efficiency) +! - Represents fecal pellets and inefficient consumption +! +! 2. STOICHIOMETRIC CONVERSION: N-based fluxes -> C-based fluxes +! - recipQuota = C:N ratio of phytoplankton +! - recipDet = C:N ratio of detritus +! - recipQZoo = C:N ratio of zooplankton +! +! 3. FOOD WEB CONFIGURATIONS: +! - Grazing_detritus ON: Zooplankton can feed on detritus (coprophagy) +! - Grazing_detritus OFF: Detritus only forms from grazing/mortality +! - enable_3zoo2det: Adds microzooplankton + fast-sinking detritus +! +! 4. REMINERALIZATION: Temperature and oxygen dependent +! - arrFunc: Increases with temperature (Arrhenius kinetics) +! - O2Func: Decreases under low oxygen (anaerobic conditions) +!=============================================================================== + !------------------------------------------------------------------------------- + ! Configuration 1: WITH Detritus Grazing + 3 Zooplankton Types + !------------------------------------------------------------------------------- + if (Grazing_detritus) then + if (enable_3zoo2det) then + sms(k,idetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Microzooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy3 * recipQuota * (1.d0 - grazEff3) & ! Small phyto + + grazingFlux_Dia3 * recipQuota_Dia * (1.d0 - grazEff3) & ! Diatoms + + grazingFlux_Cocco3 * recipQuota_Cocco * (1.d0 - grazEff3) * is_coccos & ! Coccoliths + + grazingFlux_Phaeo3 * recipQuota_Phaeo * (1.d0 - grazEff3) * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation (C-basis) + !----------------------------------------------------------------------- + + aggregationRate * PhyC & + + aggregationRate * DiaC & + + aggregationRate * CoccoC * is_coccos & + + aggregationRate * PhaeoC * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + miczooLossFlux * recipQZoo3 & ! N->C conversion + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_Det * recipDet * grazEff & ! Mesozooplankton + - grazingFlux_Det2 * recipDet * grazEff2 & ! Macrozooplankton + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetC & ! Bacterial respiration + ) * dt_b + sms(k,idetc) + + !------------------------------------------------------------------------------- + ! Configuration 2: WITH Detritus Grazing + 2 Zooplankton Types (Standard) + !------------------------------------------------------------------------------- + else + sms(k,idetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * (1.d0 - grazEff) & + + grazingFlux_Dia * recipQuota_Dia * (1.d0 - grazEff) & + + grazingFlux_Cocco * recipQuota_Cocco * (1.d0 - grazEff) * is_coccos & + + grazingFlux_Phaeo * recipQuota_Phaeo * (1.d0 - grazEff) * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation (C-basis) + !----------------------------------------------------------------------- + + aggregationRate * phyC & + + aggregationRate * DiaC & + + aggregationRate * CoccoC * is_coccos & + + aggregationRate * PhaeoC * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + hetLossFlux * recipQZoo & + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_Det * recipDet * grazEff & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetC & + ) * dt_b + sms(k,idetc) + + endif + + !------------------------------------------------------------------------------- + ! Configuration 3: WITHOUT Detritus Grazing + 3 Zooplankton Types + !------------------------------------------------------------------------------- + else + if (enable_3zoo2det) then + sms(k,idetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Microzooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy3 * recipQuota * (1.d0 - grazEff3) & + + grazingFlux_Dia3 * recipQuota_Dia * (1.d0 - grazEff3) & + + grazingFlux_Cocco3 * recipQuota_Cocco * (1.d0 - grazEff3) * is_coccos & + + grazingFlux_Phaeo3 * recipQuota_Phaeo * (1.d0 - grazEff3) * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation (C-basis) + !----------------------------------------------------------------------- + + aggregationRate * PhyC & + + aggregationRate * DiaC & + + aggregationRate * CoccoC * is_coccos & + + aggregationRate * PhaeoC * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + miczooLossFlux * recipQZoo3 & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetC & + ) * dt_b + sms(k,idetc) + + !------------------------------------------------------------------------------- + ! Configuration 4: WITHOUT Detritus Grazing + 2 Zooplankton Types + !------------------------------------------------------------------------------- + else + sms(k,idetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * (1.d0 - grazEff) & + + grazingFlux_Dia * recipQuota_Dia * (1.d0 - grazEff) & + + grazingFlux_Cocco * recipQuota_Cocco * (1.d0 - grazEff) * is_coccos & + + grazingFlux_Phaeo * recipQuota_Phaeo * (1.d0 - grazEff) * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Aggregation (C-basis) + !----------------------------------------------------------------------- + + aggregationRate * phyC & + + aggregationRate * DiaC & + + aggregationRate * CoccoC * is_coccos & + + aggregationRate * PhaeoC * is_coccos & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + hetLossFlux * recipQZoo & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetC & + ) * dt_b + sms(k,idetc) + + endif + end if + + !=============================================================================== + ! 9. MESOZOOPLANKTON NITROGEN (HetN) + !=============================================================================== + ! Primary herbivorous/omnivorous grazers that feed on phytoplankton and + ! smaller prey items. + ! + ! Variables: + ! grazingFlux : Total N grazing rate [mmolN m-3 day-1] + ! grazEff : Grazing/assimilation efficiency [-] + ! grazingFlux_het2 : Predation by macrozooplankton [mmolN m-3 day-1] + ! Mesfecalloss_n : Fecal pellet production [mmolN m-3 day-1] + ! hetLossFlux : Mortality flux [mmolN m-3 day-1] + ! lossN_z : DON excretion rate [day-1] + !------------------------------------------------------------------------------- + + sms(k,ihetn) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Grazing + !--------------------------------------------------------------------------- + + grazingFlux * grazEff & ! Assimilated N + !--------------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Excretion + !--------------------------------------------------------------------------- + - grazingFlux_het2 * is_3zoo2det & ! Predation by macrozooplankton + - Mesfecalloss_n * is_3zoo2det & ! Fecal pellets + - hetLossFlux & ! Mortality + - lossN_z * HetN & ! DON excretion + ) * dt_b + sms(k,ihetn) + + !=============================================================================== + ! 10. MESOZOOPLANKTON CARBON (HetC) + !=============================================================================== + ! Carbon budget uses reciprocal quotas (C:N ratios) to convert N-based + ! grazing rates to carbon equivalents. + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N ratios of prey items [-] + ! recipDet, recipDet2 : C:N ratios of detritus [-] + ! recipQZoo, recipQZoo3 : C:N ratios of zooplankton [-] + ! hetRespFlux : Respiration to CO2 [mmolC m-3 day-1] + ! lossC_z : DOC excretion rate [day-1] + !------------------------------------------------------------------------------- + + !------------------------------------------------------------------------------- + ! Configuration: Mesozooplankton CAN Graze on Detritus + !------------------------------------------------------------------------------- if (Grazing_detritus) then - sms(k,ihetc) = ( & - + grazingFlux_phy * recipQuota * grazEff & ! --> Grazing on small phytoplankton - + grazingFlux_Dia * recipQuota_Dia * grazEff & ! --> Grazing on diatom -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco * grazEff & -#endif -#if defined (__3Zoo2Det) - + grazingFlux_miczoo * recipQZoo3 * grazEff & ! 3Zoo - + grazingFlux_DetZ2 * recipDet2 * grazEff & - - grazingFlux_het2 * recipQZoo & - - Mesfecalloss_c & ! 3Zoo -#endif - + grazingFlux_Det * recipDet * grazEff & ! --> Grazing on detritus - - hetLossFlux * recipQZoo & ! --> Mortality loss - - lossC_z * HetC & ! --> Excretion loss - - hetRespFlux & ! --> REspiration loss - ) * dt_b + sms(k,ihetc) + sms(k,ihetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * grazEff & ! Small phytoplankton + + grazingFlux_Dia * recipQuota_Dia * grazEff & ! Diatoms + + grazingFlux_Cocco * recipQuota_Cocco * grazEff * is_coccos & ! Coccolithophores + + grazingFlux_Phaeo * recipQuota_Phaeo * grazEff * is_coccos & ! Phaeocystis + + grazingFlux_miczoo * recipQZoo3 * grazEff * is_3zoo2det & ! Microzooplankton + + grazingFlux_DetZ2 * recipDet2 * grazEff * is_3zoo2det & ! Fast-sinking detritus + + grazingFlux_Det * recipDet * grazEff & ! Slow-sinking detritus + !----------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Respiration, Excretion + !----------------------------------------------------------------------- + - grazingFlux_het2 * recipQZoo * is_3zoo2det & ! Predation + - Mesfecalloss_c * is_3zoo2det & ! Fecal pellets + - hetLossFlux * recipQZoo & ! Mortality + - lossC_z * HetC & ! DOC excretion + - hetRespFlux & ! Respiration to CO2 + ) * dt_b + sms(k,ihetc) + + !------------------------------------------------------------------------------- + ! Configuration: Mesozooplankton CANNOT Graze on Detritus + !------------------------------------------------------------------------------- else - sms(k,ihetc) = ( & - + grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco * grazEff & -#endif -#if defined (__3Zoo2Det) - + grazingFlux_miczoo * recipQZoo3 * grazEff & ! 3Zoo - - grazingFlux_het2 * recipQZoo & - - Mesfecalloss_c & ! 3Zoo -#endif - - hetLossFlux * recipQZoo & - - lossC_z * HetC & - - hetRespFlux & - ) * dt_b + sms(k,ihetc) + sms(k,ihetc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis, herbivorous diet only) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia * grazEff & + + grazingFlux_Cocco * recipQuota_Cocco * grazEff * is_coccos & + + grazingFlux_Phaeo * recipQuota_Phaeo * grazEff * is_coccos & + + grazingFlux_miczoo * recipQZoo3 * grazEff * is_3zoo2det & + !----------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Respiration, Excretion + !----------------------------------------------------------------------- + - grazingFlux_het2 * recipQZoo * is_3zoo2det & + - Mesfecalloss_c * is_3zoo2det & + - hetLossFlux * recipQZoo & + - lossC_z * HetC & + - hetRespFlux & + ) * dt_b + sms(k,ihetc) endif -!< *** Macrozooplankton *** -!< ************************ - -#if defined (__3Zoo2Det) -!____________________________________________________________ -!< Second Zooplankton N - sms(k,izoo2n) = ( & - + grazingFlux2 * grazEff2 & - - Zoo2LossFlux & - - lossN_z2 * Zoo2N & - - Zoo2fecalloss_n & - ) * dt_b + sms(k,izoo2n) - -!____________________________________________________________ -!< Second Zooplankton C - if (Grazing_detritus) then - - sms(k,izoo2c) = ( & - + grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo - + grazingFlux_Det2 * recipDet * grazEff2 & - + grazingFlux_DetZ22 * recipDet2 * grazEff2 & - - zoo2LossFlux * recipQZoo2 & - - lossC_z2 * Zoo2C & - - Zoo2RespFlux & - - Zoo2fecalloss_c & - ) * dt_b + sms(k,izoo2c) - else - sms(k,izoo2c) = ( & - + grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo - - zoo2LossFlux * recipQZoo2 & - - lossC_z2 * Zoo2C & - - Zoo2RespFlux & - - Zoo2fecalloss_c & - ) * dt_b + sms(k,izoo2c) - end if - -!< *** Microzooplankton *** -!< ************************ - -!____________________________________________________________ -!< Third Zooplankton N - sms(k,imiczoon) = ( & - + grazingFlux3 * grazEff3 & - - grazingFlux_miczoo & - - grazingFlux_miczoo2 & - - MicZooLossFlux & - - lossN_z3 * MicZooN & - ) * dt_b + sms(k,imiczoon) - -!____________________________________________________________ -!< Third Zooplankton C - sms(k,imiczooc) = ( & - + grazingFlux_phy3 * recipQuota * grazEff3 & - + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & -#endif - - MicZooLossFlux * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 & - - lossC_z3 * MicZooC & - - MicZooRespFlux & - ) * dt_b + sms(k,imiczooc) - -!< *** Fast-sinking Detritus *** -!< ***************************** - -!____________________________________________________________ -!< Second Zooplankton Detritus N - if (Grazing_detritus) then - sms(k,idetz2n) = ( & - + grazingFlux_phy2 & - - grazingFlux_phy2 * grazEff2 & - + grazingFlux_dia2 & - - grazingFlux_dia2 * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco & - - grazingFlux_Cocco * grazEff & - + grazingFlux_Cocco2 & - - grazingFlux_Cocco2 * grazEff2 & -#endif - + grazingFlux_het2 & - - grazingFlux_het2 * grazEff2 & - + grazingFlux_miczoo2 & - - grazingFlux_miczoo2 * grazEff2 & - + grazingFlux_phy & - - grazingFlux_phy * grazEff & - + grazingFlux_dia & - - grazingFlux_dia * grazEff & - + grazingFlux_miczoo & - - grazingFlux_miczoo * grazEff & - - grazingFlux_DetZ2 * grazEff & - - grazingFlux_DetZ22 * grazEff2 & - + Zoo2LossFlux & - + hetLossFlux & - + Zoo2fecalloss_n & - + Mesfecalloss_n & - - reminN * arrFunc * O2Func * DetZ2N & ! O2remin - ) * dt_b + sms(k,idetz2n) - else - sms(k,idetz2n) = ( & - + grazingFlux_phy2 & - + grazingFlux_dia2 & -#if defined (__coccos) - + grazingFlux_Cocco & - + grazingFlux_Cocco2 & -#endif - + grazingFlux_het2 & - + grazingFlux_miczoo2 & - - grazingFlux2 * grazEff2 & - + grazingFlux_phy & - + grazingFlux_dia & - + grazingFlux_miczoo & - - grazingFlux * grazEff & - + Zoo2LossFlux & - + hetLossFlux & - + Zoo2fecalloss_n & - + Mesfecalloss_n & - - reminN * arrFunc * O2Func * DetZ2N & ! O2remin - ) * dt_b + sms(k,idetz2n) - end if - -!____________________________________________________________ -!< Second Zooplankton Detritus C - if (Grazing_detritus) then - sms(k,idetz2c) = ( & - + grazingFlux_phy2 * recipQuota & - - grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia & - - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + grazingFlux_Cocco2 * recipQuota_Cocco & - - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo & - - grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2 * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & - + grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 * grazEff & - - grazingFlux_DetZ2 * recipDet2 * grazEff & - - grazingFlux_DetZ22 * recipDet2 * grazEff2 & - + Zoo2LossFlux * recipQZoo2 & - + hetLossFlux * recipQZoo & - + Zoo2fecalloss_c & - + Mesfecalloss_c & - - reminC * arrFunc * O2Func * DetZ2C & ! O2remin - ) * dt_b + sms(k,idetz2c) - else - sms(k,idetz2c) = ( & - + grazingFlux_phy2 * recipQuota & - - grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia & - - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + grazingFlux_Cocco2 * recipQuota_Cocco & - - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo & - - grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2 * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & - + grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 * grazEff & - + Zoo2LossFlux * recipQZoo2 & - + hetLossFlux * recipQZoo & - + Zoo2fecalloss_c & - + Mesfecalloss_c & - - reminC * arrFunc * O2Func * DetZ2C & ! O2remin - ) * dt_b + sms(k,idetz2c) - end if - -!____________________________________________________________ -!< Second Zooplankton Detritus Si - sms(k,idetz2si) = ( & - + grazingFlux_dia2 * qSiN & ! --> qSin convert N to Si - + grazingFlux_dia * qSiN & - - reminSiT * DetZ2Si & - ) * dt_b + sms(k,idetz2si) - -!____________________________________________________________ -!< Second Zooplankton Detritus calcite - sms(k,idetz2calc) = ( & - + calc_loss_gra2 & - - calc_loss_gra2 * calc_diss_guts & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss2 * DetZ2Calc & - ) * dt_b + sms(k,idetz2calc) -#endif - -!< *** DOM *** -!< *********** - -!____________________________________________________________ -!< DON (Extracellular organic N) - - sms(k,idon) = ( & - + lossN * limitFacN * phyN & - + lossN_d * limitFacN_Dia * DiaN & -#if defined (__coccos) - + lossN_c * limitFacN_Cocco * CoccoN & -#endif - + reminN * arrFunc * O2Func * DetN & - + lossN_z * HetN & -#if defined (__3Zoo2Det) - + reminN * arrFunc * O2Func * DetZ2N & - + lossN_z2 * Zoo2N & - + lossN_z3 * MicZooN & ! 3Zoo -#endif - - rho_N * arrFunc * O2Func * DON & ! O2remin - ) * dt_b + sms(k,idon) - -!____________________________________________________________ -!< EOC - - sms(k,idoc) = ( & - + lossC * limitFacN * phyC & - + lossC_d * limitFacN_dia * DiaC & -#if defined (__coccos) - + lossC_c * limitFacN_cocco * CoccoC & -#endif - + reminC * arrFunc * O2Func * DetC & - + lossC_z * HetC & -#if defined (__3Zoo2Det) - + reminC * arrFunc * O2Func * DetZ2C & - + lossC_z2 * Zoo2C & - + lossC_z3 * MicZooC & ! 3Zoo -#endif - - rho_c1 * arrFunc * O2Func * EOC & ! O2remin - ) * dt_b + sms(k,idoc) - -!< *** Diatoms *** -!< *************** - -!____________________________________________________________ -!< Diatom N - -!< lossN: Diatom loss of organic N compounds [day^-1] -!< When N : C ratio becomes too high, excretion of DON is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers N to the detritus pool - - sms(k,idian) = ( & - + N_assim_dia * DiaC & ! --> N assimilation - - lossN_d * limitFacN_dia * DiaN & ! --> DON excretion - - aggregationRate * DiaN & ! --> Aggregation loss - - grazingFlux_Dia & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_Dia2 & - - grazingFlux_Dia3 & ! 3Zoo -#endif - ) * dt_b + sms(k,idian) - -!____________________________________________________________ -!< Diatom C - -!< lossC_d: Diatom loss of carbon [day^-1] -!< When N : C ratio becomes too high, excretion of DOC is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers C to the detritus pool - - sms(k,idiac) = ( & - + Cphot_dia * DiaC & ! -- Photosynthesis ---->/ - - lossC_d * limitFacN_dia * DiaC & ! -- Excretion of DOC --/ Net Photosynthesis - - phyRespRate_dia * DiaC & ! -- Respiration ----->/ - - aggregationRate * DiaC & - - grazingFlux_dia * recipQuota_dia & -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * recipQuota_dia & - - grazingFlux_dia3 * recipQuota_dia & ! 3Zoo -#endif - ) * dt_b + sms(k,idiac) - -!____________________________________________________________ -!< Diatom Chl - - sms(k,idchl) = ( & - + chlSynth_dia * DiaC & ! --> Chl a synthesis - - KOchl_dia * DiaChl & ! --> Degradation loss - - aggregationRate * DiaChl & ! --> Aggregation loss - - grazingFlux_dia * Chl2N_dia & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * Chl2N_dia & - - grazingFlux_dia3 * Chl2N_dia & ! 3Zoo -#endif - ) * dt_b + sms(k,idchl) - -!____________________________________________________________ -!< Diatom Si - -!< lossN_d: Diatom loss of organic nitrogen compunds [day^-1] -!< When N : C ratio becomes too high, excretion is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers Si to the detritus pool - - sms(k,idiasi) = ( & - + Si_assim * DiaC & ! -- Diatom silicon assimilation - - lossN_d * limitFacN_dia * DiaSi & ! -- Excretion to detritus - - aggregationRate * DiaSi & ! -- Aggregation loss - - grazingFlux_dia * qSiN & ! -- Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * qSiN & - - grazingFlux_dia3 * qSiN & ! 3Zoo -#endif - ) * dt_b + sms(k,idiasi) - -!< *** Coccolithophore *** -!< *********************** - -#if defined (__coccos) -!____________________________________________________________ -!< Coccolithophore N - sms(k,icocn) = ( & - + N_assim_cocco * CoccoC & - - lossN_c * limitFacN_cocco * CoccoN & - - aggregationRate * CoccoN & - - grazingFlux_Cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 & - - grazingFlux_Cocco3 & ! 3Zoo -#endif - ) * dt_b + sms(k,icocn) - -!____________________________________________________________ -!< Coccolithophore C - - sms(k,icocc) = ( & - + Cphot_cocco * CoccoC & - - lossC_c * limitFacN_cocco * CoccoC & - - phyRespRate_cocco * CoccoC & - - aggregationRate * CoccoC & - - grazingFlux_cocco * recipQuota_cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 * recipQuota_cocco & - - grazingFlux_Cocco3 * recipQuota_cocco & ! 3Zoo -#endif - ) * dt_b + sms(k,icocc) - - if(sms(k,icocc)>100) then - print*,'ERROR: strange CoccoC !' - print*,'k= ', k - print*,'dt= ', dt - print*,'dt_b= ', dt_b - print*,'state(k,icocc): ', state(k,icocc) - print*,'sms CoccoC: ', CoccoC - print*,'sms CoccoN: ', CoccoN - print*,'sms Cphot cocco: ', Cphot_cocco*CoccoC - print*,'sms lossC_c: ', lossC_c - print*,'sms limitFacN_cocco: ', limitFacN_cocco - print*,'sms phyRespRate_cocco: ', phyRespRate_cocco - print*,'sms grazingFlux_cocco: ', grazingFlux_cocco - print*,'sms grazingFlux_cocco2: ', grazingFlux_Cocco2 - print*,'sms grazingFlux_cocco3: ', grazingFlux_Cocco3 - print*,'sms recipQuota_cocco: ', recipQuota_cocco - - print*,'sms recipQuota_cocco: ', recipQuota_cocco - call par_ex(partit%MPI_COMM_FESOM, partit%mype) - stop - endif + !=============================================================================== + ! 11. MACROZOOPLANKTON NITROGEN (Zoo2N) + !=============================================================================== + ! Larger predatory zooplankton that feed on mesozooplankton, microzooplankton, + ! and phytoplankton. Only active when enable_3zoo2det = .true. + ! + ! Variables: + ! grazingFlux2 : Total N grazing rate [mmolN m-3 day-1] + ! grazEff2 : Grazing/assimilation efficiency [-] + ! Zoo2LossFlux : Mortality flux [mmolN m-3 day-1] + ! lossN_z2 : DON excretion rate [day-1] + ! Zoo2fecalloss_n : Fecal pellet production [mmolN m-3 day-1] + !------------------------------------------------------------------------------- + + if (enable_3zoo2det) then + sms(k,izoo2n) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing + !----------------------------------------------------------------------- + + grazingFlux2 * grazEff2 & ! Assimilated N + !----------------------------------------------------------------------- + ! SINKS: Mortality, Excretion, Fecal Pellets + !----------------------------------------------------------------------- + - Zoo2LossFlux & ! Mortality + - lossN_z2 * Zoo2N & ! DON excretion + - Zoo2fecalloss_n & ! Fecal pellets + ) * dt_b + sms(k,izoo2n) + + !=============================================================================== + ! 12. MACROZOOPLANKTON CARBON (Zoo2C) + !=============================================================================== + ! Carbon budget for macrozooplankton with stoichiometric conversions. + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N ratios of prey [-] + ! recipDet, recipDet2 : C:N ratios of detritus [-] + ! recipQZoo, recipQZoo2, recipQZoo3: C:N ratios of zooplankton [-] + ! Zoo2RespFlux : Respiration to CO2 [mmolC m-3 day-1] + ! lossC_z2 : DOC excretion rate [day-1] + !------------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Configuration: Macrozooplankton CAN Graze on Detritus + !--------------------------------------------------------------------------- -!____________________________________________________________ -!< Coccolithophore Chl - - sms(k,icchl) = ( & - + ChlSynth_cocco * CoccoC & - - KOchl_cocco * CoccoChl & - - aggregationRate * CoccoChl & - - grazingFlux_cocco * Chl2N_cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 * Chl2N_cocco & - - grazingFlux_Cocco3 * Chl2N_cocco & ! 3Zoo -#endif - ) * dt_b + sms(k,icchl) -#endif - -!< *** Silicate *** -!< **************** - -!____________________________________________________________ -!< Detritus Si -#if defined (__3Zoo2Det) - sms(k,idetsi) = ( & - + aggregationRate * DiaSi & - + lossN_d * limitFacN_dia * DiaSi & - + grazingFlux_dia3 * qSiN & - - reminSiT * DetSi & - ) * dt_b + sms(k,idetsi) -#else - sms(k,idetsi) = ( & - + aggregationRate * DiaSi & - + lossN_d * limitFacN_dia * DiaSi & - + grazingFlux_dia * qSiN & - - reminSiT * DetSi & - ) * dt_b + sms(k,idetsi) -#endif -!____________________________________________________________ -!< DSi, Silicate - -!< DiaC: Intracellular carbon concentration in diatoms [mmolC m-3] -!< DetSi: Detritus silicon concentration [mmolSi m-3] -!< Si_assim: Si assimilation rate for diatoms [mmolSi mmolC-1 day-1] -!< reminSiT: Remineralization rate of silicon, temperature dependency [day-1] -!< dt_b: REcoM time step [day] - -!! Schourup 2013 Eq. A3 - - sms(k,isi) = ( & - - Si_assim * DiaC & ! --> Si assimilation of diatoms - + reminSiT * DetSi & ! --> Remineralization of detritus, temperature dependent -#if defined (__3Zoo2Det) - + reminSiT * DetZ2Si & -#endif - ) * dt_b + sms(k,isi) -!< *** Iron *** -!< ************ - -!____________________________________________________________ -!< Fe - -!< Fe2N: Intracellular Fe : N ratio [μmol Fe mmol N^-1] Fe2N = Fe2C * 6.625 -!< PhyC: Intracellular carbon concentration in nanophytoplankton [mmolCm^-3] -!< Cphot: C-specific actual rate of photosynthesis for nanopyhtoplankton [day^-1] -!< DiaC: Intracellular carbon concentration in diatoms [mmol C m^-3 ] -!< Cphot_dia: C-specific actual rate of photosynthesis for diatom [day^-1] -!< phyRespRate: Nanopyhtoplankton respiration rate [day^-1] -!< phyRespRate_dia: Diatom respiration rate [day^-1] -!< lossC: Nanopyhtoplankton excretion of organic C [day^-1] -!< limitFacN: limiting factor -!< lossC_d: Diatom excretion of organic C [day^-1] -!< limitFacN_dia: limiting factor -!< detC: Detritus carbon concentration [mmol C m^-3] -!< reminC: Temperature dependent remineralisation rate of detritus [day^-1] -!< arrFunc: Arrhenius function -!< hetC: Zooplankton carbon concentration [mmol C m^-3 ] -!< lossC_z: Zooplankton excretion of organic C [day^-1 ] -!< hetRespFlux: Zooplankton respiration rate [day^-1] -!< kScavFe: Scavenging rate of iron [m3 mmol C^-1 day^-1] - - sms(k,ife) = ( Fe2N * ( & - - N_assim * PhyC & ! --> N assimilation Nanophytoplankton, [mmol N/(mmol C * day)] C specific N utilization rate - - N_assim_dia * DiaC & ! --> N assimilation Diatom -#if defined (__coccos) - - N_assim_cocco * CoccoC & - + lossN_c * limitFacN_cocco * CoccoN & -#endif - + lossN * limitFacN * PhyN & ! --> Excretion from small pythoplankton - + lossN_d * limitFacN_dia * DiaN & ! --> Excretion from diatom - + reminN * arrFunc * O2Func * DetN & ! --> Remineralization of detritus ! NEW O2remin - + lossN_z * HetN & ! --> Excretion from zooplankton -#if defined (__3Zoo2Det) - + reminN * arrFunc * O2Func * DetZ2N & ! O2remin - + lossN_z2 * Zoo2N & - + lossN_z3 * MicZooN & ! 3Zoo -#endif - ) & - - kScavFe * DetC * FreeFe & -#if defined (__3Zoo2Det) - - kScavFe * DetZ2C * FreeFe & -#endif - ) * dt_b + sms(k,ife) - -!< *** Calcification *** -!< ********************* - -!____________________________________________________________ -!< Small phytoplankton calcite - -#if defined (__coccos) - sms(k,iphycal) = ( & - + calcification & ! --> Calcification - - lossC_c * limitFacN_cocco * PhyCalc & ! --> Excretion loss - - phyRespRate_cocco * PhyCalc & ! --> Respiration - - calc_loss_agg & ! --> Aggregation loss - - calc_loss_gra & ! --> Grazing loss -#if defined (__3Zoo2Det) - - calc_loss_gra2 & - - calc_loss_gra3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphycal) -#else - sms(k,iphycal) = ( & - + calcification & ! --> Calcification - - lossC * limitFacN * PhyCalc & ! --> Excretion loss - - phyRespRate * PhyCalc & ! --> Respiration - - calc_loss_agg & ! --> Aggregation loss - - calc_loss_gra & ! --> Grazing loss -#if defined (__3Zoo2Det) - - calc_loss_gra2 & - - calc_loss_gra3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphycal) -#endif - -!____________________________________________________________ -! Detritus calcite -#if defined (__coccos) - -#if defined (__3Zoo2Det) - sms(k,idetcal) = ( & - + lossC_c * limitFacN_cocco * PhyCalc & - + phyRespRate_cocco * PhyCalc & - + calc_loss_agg & - + calc_loss_gra3 & - - calc_loss_gra3 * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) - -#else - sms(k,idetcal) = ( & - + lossC_c * limitFacN_cocco * PhyCalc & - + phyRespRate_cocco * PhyCalc & - + calc_loss_agg & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) - -#endif - -#else - -#if defined (__3Zoo2Det) - sms(k,idetcal) = ( & - + lossC * limitFacN * PhyCalc & - + phyRespRate * PhyCalc & - + calc_loss_agg & - + calc_loss_gra3 & - - calc_loss_gra3 * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) -#else - sms(k,idetcal) = ( & - + lossC * limitFacN * PhyCalc & - + phyRespRate * PhyCalc & - + calc_loss_agg & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) -#endif -#endif - -!____________________________________________________________ -! Oxygen - - sms(k,ioxy) = ( & - + Cphot * phyC & - - phyRespRate * phyC & - + Cphot_dia * diaC & - - phyRespRate_dia * diaC & -#if defined (__coccos) - + Cphot_cocco * CoccoC & - - phyRespRate_cocco * CoccoC & -#endif - - rho_C1 * arrFunc * O2Func * EOC & ! O2remin - - hetRespFlux & -#if defined (__3Zoo2Det) - - Zoo2RespFlux & - - MicZooRespFlux & ! 3Zoo -#endif - ) * redO2C * dt_b + sms(k,ioxy) -! -!------------------------------------------------------------------------------- -! Diagnostics: Averaged rates - - recipbiostep = 1.d0/real(biostep) -if (Diags) then -!*** Net primary production [mmol C /(m3 * day)] - vertNPPn(k) = vertNPPn(k) + ( & - + Cphot * PhyC & - - PhyRespRate * PhyC & - ) * recipbiostep - - vertNPPd(k) = vertNPPd(k) + ( & - + Cphot_dia * DiaC & - - PhyRespRate_dia * DiaC & - ) * recipbiostep - -#if defined (__coccos) - vertNPPc(k) = vertNPPc(k) + ( & - + Cphot_cocco * CoccoC & - - PhyRespRate_cocco * CoccoC & - ) * recipbiostep -#endif - -!*** Gross primary production [mmol C /(m3 * day)] - vertGPPn(k) = vertGPPn(k) + ( & - + Cphot * PhyC & - ) * recipbiostep - - vertGPPd(k) = vertGPPd(k) + ( & - + Cphot_dia * DiaC & - ) * recipbiostep - -#if defined (__coccos) - vertGPPc(k) = vertGPPc(k) + ( & - + Cphot_cocco * CoccoC & - ) * recipbiostep -#endif - -!*** Net N-assimilation [mmol N/(m3 * day)] - vertNNAn(k) = vertNNAn(k) + ( & - + N_assim * PhyC & - - lossN * limitFacN * PhyN & - ) * recipbiostep - - vertNNAd(k) = vertNNAd(k) + ( & - + N_assim_dia * DiaC & - - lossN * limitFacN_dia * DiaN & - ) * recipbiostep - -#if defined (__coccos) - vertNNAc(k) = vertNNAc(k) + ( & - + N_assim_cocco * CoccoC & - - lossN * limitFacN_cocco * CoccoN & - ) * recipbiostep -#endif - -!*** Changed to chlorophyll degradation (commented out gross N-assimilation below) - vertChldegn(k) = vertChldegn(k) + ( & - + KOchl & - ) * recipbiostep - - vertChldegd(k) = vertChldegd(k) + ( & - + KOchl_dia & - ) * recipbiostep - -#if defined (__coccos) - vertChldegc(k) = vertChldegc(k) + ( & - + KOchl_cocco & - ) * recipbiostep -#endif - -!*** zooplankton1 respiration - vertrespmeso(k) = vertrespmeso(k) + ( & - + HetRespFlux & - ) * recipbiostep -#if defined (__3Zoo2Det) -!*** zooplankton2 respiration - vertrespmacro(k) = vertrespmacro(k) + ( & - + Zoo2RespFlux & - ) * recipbiostep - -!*** zooplankton3 respiration - vertrespmicro(k) = vertrespmicro(k) + ( & - + MicZooRespFlux & - ) * recipbiostep -#endif -!*** calc_diss - vertcalcdiss(k) = vertcalcdiss(k) + ( & - + calc_diss * DetCalc & - ) * recipbiostep - -!*** aggregation by small phytoplankton - vertaggn(k) = vertaggn(k) + ( & - + aggregationrate * PhyC & - ) * recipbiostep - -!*** aggregation by diatoms - vertaggd(k) = vertaggd(k) + ( & - + aggregationrate * DiaC & - ) * recipbiostep - -#if defined (__coccos) -!*** aggregation by coccolithophores - vertaggc(k) = vertaggc(k) + ( & - + aggregationrate * CoccoC & - ) * recipbiostep -#endif - -!*** excrection of DOC by phytoplankton - vertdocexn(k) = vertdocexn(k) + ( & - + lossC * limitFacN * phyC & - ) * recipbiostep - -!*** excrection of DOC by diatoms - vertdocexd(k) = vertdocexd(k) + ( & - + lossC_d * limitFacN_dia * DiaC & - ) * recipbiostep - -#if defined (__coccos) -!*** excretion of DOC by coccolithophores - vertdocexc(k) = vertdocexc(k) + ( & - + lossC_c * limitFacN_cocco * CoccoC & - ) * recipbiostep -#endif - -!*** calcification - vertcalcif(k) = vertcalcif(k) + ( & - + calcification & - ) * recipbiostep - -! phy respiration - vertrespn(k) = vertrespn(k) + ( & - + PhyRespRate * PhyC & - ) * recipbiostep - -! dia respiration - vertrespd(k) = vertrespd(k) + ( & - + PhyRespRate_dia * DiaC & - ) * recipbiostep - -#if defined (__coccos) -! cocco resipration - vertrespc(k) = vertrespc(k) + ( & - + PhyRespRate_cocco * CoccoC & - ) * recipbiostep - -#endif -endif - end do ! Main vertikal loop ends + if (Grazing_detritus) then + sms(k,izoo2c) = ( & + !------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis) + !------------------------------------------------------------------- + + grazingFlux_phy2 * recipQuota * grazEff2 & ! Small phytoplankton + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & ! Diatoms + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 * is_coccos & ! Coccolithophores + + grazingFlux_Phaeo2 * recipQuota_Phaeo * grazEff2 * is_coccos & ! Phaeocystis + + grazingFlux_het2 * recipQZoo * grazEff2 & ! Mesozooplankton (predation) + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! Microzooplankton + + grazingFlux_Det2 * recipDet * grazEff2 & ! Slow-sinking detritus + + grazingFlux_DetZ22 * recipDet2 * grazEff2 & ! Fast-sinking detritus + !------------------------------------------------------------------- + ! SINKS: Mortality, Respiration, Excretion, Fecal Pellets + !------------------------------------------------------------------- + - zoo2LossFlux * recipQZoo2 & ! Mortality + - lossC_z2 * Zoo2C & ! DOC excretion + - Zoo2RespFlux & ! Respiration to CO2 + - Zoo2fecalloss_c & ! Fecal pellets + ) * dt_b + sms(k,izoo2c) + + !--------------------------------------------------------------------------- + ! Configuration: Macrozooplankton CANNOT Graze on Detritus + !--------------------------------------------------------------------------- + else + sms(k,izoo2c) = ( & + !------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis, no detritus feeding) + !------------------------------------------------------------------- + + grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 * is_coccos & + + grazingFlux_Phaeo2 * recipQuota_Phaeo * grazEff2 * is_coccos & + + grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & + !------------------------------------------------------------------- + ! SINKS: Mortality, Respiration, Excretion, Fecal Pellets + !------------------------------------------------------------------- + - zoo2LossFlux * recipQZoo2 & + - lossC_z2 * Zoo2C & + - Zoo2RespFlux & + - Zoo2fecalloss_c & + ) * dt_b + sms(k,izoo2c) -!------------------------------------------------------------------------------- -! Remineralization from the sediments into the bottom layer -!*** DIN *** -!< decayRateBenN: Remineralization rate for benthic N [day^-1] -!< LocBenthos(1): Vertically integrated N concentration in benthos (1 layer) [mmolN/m^2] - decayBenthos(1) = decayRateBenN * LocBenthos(1) - LocBenthos(1) = LocBenthos(1) - decaybenthos(1) * dt_b ! remove from benthos (flux) + end if + + !=============================================================================== + ! 13. MICROZOOPLANKTON NITROGEN (MicZooN) + !=============================================================================== + ! Small heterotrophic protists that graze on phytoplankton and are prey for + ! meso- and macrozooplankton. + ! + ! Variables: + ! grazingFlux3 : Total N grazing rate [mmolN m-3 day-1] + ! grazEff3 : Grazing/assimilation efficiency [-] + ! grazingFlux_miczoo : Predation by mesozooplankton [mmolN m-3 day-1] + ! grazingFlux_miczoo2: Predation by macrozooplankton [mmolN m-3 day-1] + ! MicZooLossFlux : Mortality flux [mmolN m-3 day-1] + ! lossN_z3 : DON excretion rate [day-1] + !------------------------------------------------------------------------------- + + sms(k,imiczoon) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing + !----------------------------------------------------------------------- + + grazingFlux3 * grazEff3 & ! Assimilated N + !----------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Excretion + !----------------------------------------------------------------------- + - grazingFlux_miczoo & ! Predation by mesozooplankton + - grazingFlux_miczoo2 & ! Predation by macrozooplankton + - MicZooLossFlux & ! Mortality + - lossN_z3 * MicZooN & ! DON excretion + ) * dt_b + sms(k,imiczoon) + + !=============================================================================== + ! 14. MICROZOOPLANKTON CARBON (MicZooC) + !=============================================================================== + ! Carbon budget for microzooplankton with stoichiometric conversions. + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N ratios of prey [-] + ! recipQZoo3 : C:N ratio of microzooplankton [-] + ! MicZooRespFlux : Respiration to CO2 [mmolC m-3 day-1] + ! lossC_z3 : DOC excretion rate [day-1] + !------------------------------------------------------------------------------- + + sms(k,imiczooc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy3 * recipQuota * grazEff3 & ! Small phytoplankton + + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & ! Diatoms + + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 * is_coccos & ! Coccolithophores + + grazingFlux_Phaeo3 * recipQuota_Phaeo * grazEff3 * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SINKS: Predation, Mortality, Respiration, Excretion + !----------------------------------------------------------------------- + - MicZooLossFlux * recipQZoo3 & ! Mortality + - grazingFlux_miczoo * recipQZoo3 & ! Predation by mesozooplankton + - grazingFlux_miczoo2 * recipQZoo3 & ! Predation by macrozooplankton + - lossC_z3 * MicZooC & ! DOC excretion + - MicZooRespFlux & ! Respiration to CO2 + ) * dt_b + sms(k,imiczooc) + + end if + + !=============================================================================== + ! 15. FAST-SINKING DETRITUS NITROGEN (DetZ2N) + !=============================================================================== + ! Particulate organic matter produced from zooplankton mortality, fecal pellets, + ! and unassimilated grazing. Sinks faster than regular detritus. + ! Only active when enable_3zoo2det = .true. + ! + ! Variables: + ! grazingFlux_phy, grazingFlux_phy2 : Grazing on small phyto [mmolN m-3 day-1] + ! grazingFlux_dia, grazingFlux_dia2 : Grazing on diatoms [mmolN m-3 day-1] + ! grazingFlux_het2 : Predation on mesozooplankton [mmolN m-3 day-1] + ! grazingFlux_miczoo, grazingFlux_miczoo2 : Grazing on microzooplankton [mmolN m-3 day-1] + ! grazingFlux_DetZ2, grazingFlux_DetZ22 : Grazing on fast detritus [mmolN m-3 day-1] + ! Zoo2LossFlux, hetLossFlux : Zooplankton mortality [mmolN m-3 day-1] + ! Zoo2fecalloss_n, Mesfecalloss_n : Fecal pellet production [mmolN m-3 day-1] + ! reminN : Remineralization rate [day-1] + !------------------------------------------------------------------------------- + + if (enable_3zoo2det) then + + !--------------------------------------------------------------------------- + ! Configuration: Zooplankton CAN Graze on Fast-Sinking Detritus + !--------------------------------------------------------------------------- + if (Grazing_detritus) then + sms(k,idetz2n) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Macrozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy2 * (1.d0 - grazEff2) & ! Small phytoplankton + + grazingFlux_dia2 * (1.d0 - grazEff2) & ! Diatoms + + grazingFlux_Cocco * (1.d0 - grazEff) * is_coccos & ! Coccoliths (meso) + + grazingFlux_Cocco2 * (1.d0 - grazEff2) * is_coccos & ! Coccoliths (macro) + + grazingFlux_Phaeo * (1.d0 - grazEff) * is_coccos & ! Phaeocystis (meso) + + grazingFlux_Phaeo2 * (1.d0 - grazEff2) * is_coccos & ! Phaeocystis (macro) + + grazingFlux_het2 * (1.d0 - grazEff2) & ! Mesozooplankton (predation) + + grazingFlux_miczoo2 * (1.d0 - grazEff2) & ! Microzooplankton + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy * (1.d0 - grazEff) & ! Small phytoplankton + + grazingFlux_dia * (1.d0 - grazEff) & ! Diatoms + + grazingFlux_miczoo * (1.d0 - grazEff) & ! Microzooplankton + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + Zoo2LossFlux & ! Macrozooplankton + + hetLossFlux & ! Mesozooplankton + !----------------------------------------------------------------------- + ! SOURCES: Fecal Pellet Production + !----------------------------------------------------------------------- + + Zoo2fecalloss_n & ! Macrozooplankton + + Mesfecalloss_n & ! Mesozooplankton + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption (Coprophagy) + !----------------------------------------------------------------------- + - grazingFlux_DetZ2 * grazEff & ! Mesozooplankton + - grazingFlux_DetZ22 * grazEff2 & ! Macrozooplankton + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetZ2N & ! Bacterial decomposition + ) * dt_b + sms(k,idetz2n) + + !--------------------------------------------------------------------------- + ! Configuration: Zooplankton CANNOT Graze on Fast-Sinking Detritus + !--------------------------------------------------------------------------- + else + sms(k,idetz2n) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Macrozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy2 & ! All grazing enters detritus + + grazingFlux_dia2 & + + grazingFlux_Cocco * is_coccos & + + grazingFlux_Cocco2 * is_coccos & + + grazingFlux_Phaeo * is_coccos & + + grazingFlux_Phaeo2 * is_coccos & + + grazingFlux_het2 & + + grazingFlux_miczoo2 & + - grazingFlux2 * grazEff2 & ! Minus assimilated portion + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton + !----------------------------------------------------------------------- + + grazingFlux_phy & + + grazingFlux_dia & + + grazingFlux_miczoo & + - grazingFlux * grazEff & ! Minus assimilated portion + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality + !----------------------------------------------------------------------- + + Zoo2LossFlux & + + hetLossFlux & + !----------------------------------------------------------------------- + ! SOURCES: Fecal Pellet Production + !----------------------------------------------------------------------- + + Zoo2fecalloss_n & + + Mesfecalloss_n & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminN * arrFunc * O2Func * DetZ2N & + ) * dt_b + sms(k,idetz2n) + end if + !=============================================================================== + ! 16. FAST-SINKING DETRITUS CARBON (DetZ2C) + !=============================================================================== + ! Carbon budget for fast-sinking detritus with stoichiometric conversions. + ! + ! Variables: + ! recipQuota, recipQuota_Dia, etc. : C:N ratios of phytoplankton [-] + ! recipQZoo, recipQZoo2, recipQZoo3: C:N ratios of zooplankton [-] + ! recipDet2 : C:N ratio of fast-sinking detritus [-] + ! reminC : C remineralization rate [day-1] + !------------------------------------------------------------------------------- + + !--------------------------------------------------------------------------- + ! Configuration: Zooplankton CAN Graze on Fast-Sinking Detritus + !--------------------------------------------------------------------------- + if (Grazing_detritus) then + sms(k,idetz2c) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Macrozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy2 * recipQuota * (1.d0 - grazEff2) & ! Small phyto + + grazingFlux_Dia2 * recipQuota_Dia * (1.d0 - grazEff2) & ! Diatoms + + grazingFlux_Cocco * recipQuota_Cocco * (1.d0 - grazEff) * is_coccos & ! Coccoliths (meso) + + grazingFlux_Cocco2 * recipQuota_Cocco * (1.d0 - grazEff2) * is_coccos & ! Coccoliths (macro) + + grazingFlux_Phaeo * recipQuota_Phaeo * (1.d0 - grazEff) * is_coccos & ! Phaeocystis (meso) + + grazingFlux_Phaeo2 * recipQuota_Phaeo * (1.d0 - grazEff2) * is_coccos & ! Phaeocystis (macro) + + grazingFlux_het2 * recipQZoo * (1.d0 - grazEff2) & ! Mesozooplankton + + grazingFlux_miczoo2 * recipQZoo3 * (1.d0 - grazEff2) & ! Microzooplankton + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * (1.d0 - grazEff) & ! Small phyto + + grazingFlux_Dia * recipQuota_Dia * (1.d0 - grazEff) & ! Diatoms + + grazingFlux_miczoo * recipQZoo3 * (1.d0 - grazEff) & ! Microzooplankton + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + Zoo2LossFlux * recipQZoo2 & ! Macrozooplankton (N->C) + + hetLossFlux * recipQZoo & ! Mesozooplankton (N->C) + !----------------------------------------------------------------------- + ! SOURCES: Fecal Pellet Production (C-basis) + !----------------------------------------------------------------------- + + Zoo2fecalloss_c & ! Macrozooplankton + + Mesfecalloss_c & ! Mesozooplankton + !----------------------------------------------------------------------- + ! SINKS: Detritus Consumption (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_DetZ2 * recipDet2 * grazEff & ! Mesozooplankton + - grazingFlux_DetZ22 * recipDet2 * grazEff2 & ! Macrozooplankton + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetZ2C & ! Bacterial respiration + ) * dt_b + sms(k,idetz2c) + + !--------------------------------------------------------------------------- + ! Configuration: Zooplankton CANNOT Graze on Fast-Sinking Detritus + !--------------------------------------------------------------------------- + else + sms(k,idetz2c) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Macrozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy2 * recipQuota * (1.d0 - grazEff2) & + + grazingFlux_Dia2 * recipQuota_Dia * (1.d0 - grazEff2) & + + grazingFlux_Cocco * recipQuota_Cocco * (1.d0 - grazEff) * is_coccos & + + grazingFlux_Cocco2 * recipQuota_Cocco * (1.d0 - grazEff2) * is_coccos & + + grazingFlux_Phaeo * recipQuota_Phaeo * (1.d0 - grazEff) * is_coccos & + + grazingFlux_Phaeo2 * recipQuota_Phaeo * (1.d0 - grazEff2) * is_coccos & + + grazingFlux_het2 * recipQZoo * (1.d0 - grazEff2) & + + grazingFlux_miczoo2 * recipQZoo3 * (1.d0 - grazEff2) & + !----------------------------------------------------------------------- + ! SOURCES: Sloppy Feeding by Mesozooplankton (C-basis) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota * (1.d0 - grazEff) & + + grazingFlux_Dia * recipQuota_Dia * (1.d0 - grazEff) & + + grazingFlux_miczoo * recipQZoo3 * (1.d0 - grazEff) & + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Mortality (C-basis) + !----------------------------------------------------------------------- + + Zoo2LossFlux * recipQZoo2 & + + hetLossFlux * recipQZoo & + !----------------------------------------------------------------------- + ! SOURCES: Fecal Pellet Production (C-basis) + !----------------------------------------------------------------------- + + Zoo2fecalloss_c & + + Mesfecalloss_c & + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * O2Func * DetZ2C & + ) * dt_b + sms(k,idetz2c) + end if -!*** DIC *** -!< decayRateBenC: Remineralization rate for benthic C [day^-1] -!< LocBenthos(2): Vertically integrated C concentration in benthos (1 layer) [mmolC/m^2] - decayBenthos(2) = decayRateBenC * LocBenthos(2) - LocBenthos(2) = LocBenthos(2) - decaybenthos(2) * dt_b + !=============================================================================== + ! 17. FAST-SINKING DETRITUS SILICA (DetZ2Si) + !=============================================================================== + ! Biogenic silica from diatom frustules in fast-sinking detritus. + ! + ! Variables: + ! grazingFlux_dia, grazingFlux_dia2 : Grazing on diatoms [mmolN m-3 day-1] + ! qSiN : Si:N ratio in diatoms [mmolSi mmolN-1] + ! reminSiT : Temperature-dependent dissolution [day-1] + !------------------------------------------------------------------------------- + + sms(k,idetz2si) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing on Diatoms + !----------------------------------------------------------------------- + + grazingFlux_dia2 * qSiN & ! Macrozooplankton grazing + + grazingFlux_dia * qSiN & ! Mesozooplankton grazing + !----------------------------------------------------------------------- + ! SINKS: Dissolution + !----------------------------------------------------------------------- + - reminSiT * DetZ2Si & ! Temperature-dependent + ) * dt_b + sms(k,idetz2si) + + !=============================================================================== + ! 18. FAST-SINKING DETRITUS CALCITE (DetZ2Calc) + !=============================================================================== + ! Calcite particles from coccolithophore shells in fast-sinking detritus. + ! + ! Variables: + ! calc_loss_gra, calc_loss_gra2 : Calcite from grazing [mmolCaCO3 m-3 day-1] + ! calc_diss_guts : Gut dissolution fraction [-] + ! calc_diss2 : Water column dissolution rate [day-1] + !------------------------------------------------------------------------------- + + sms(k,idetz2calc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Grazing on Calcifying Phytoplankton + !----------------------------------------------------------------------- + + calc_loss_gra2 * (1.d0 - calc_diss_guts) & ! Macrozooplankton (net) + + calc_loss_gra * (1.d0 - calc_diss_guts) & ! Mesozooplankton (net) + !----------------------------------------------------------------------- + ! SINKS: Dissolution in Water Column + !----------------------------------------------------------------------- + - calc_diss2 * DetZ2Calc & ! CaCO3 dissolution + ) * dt_b + sms(k,idetz2calc) + + endif ! enable_3zoo2det + + !=============================================================================== + ! 19. DISSOLVED ORGANIC NITROGEN (DON) + !=============================================================================== + ! Dissolved organic nitrogen pool from phytoplankton excretion, zooplankton + ! metabolism, and detrital remineralization. + ! + ! Variables: + ! lossN, lossN_d, lossN_c, lossN_p : Phytoplankton DON excretion rates [day-1] + ! limitFacN, limitFacN_Dia, etc. : N:C ratio limiters (regulate excretion) [-] + ! reminN : Detrital N remineralization rate [day-1] + ! rho_N : DON remineralization rate [day-1] + ! lossN_z, lossN_z2, lossN_z3 : Zooplankton DON excretion rates [day-1] + ! arrFunc : Arrhenius temperature function [-] + ! O2Func : Oxygen limitation function [-] + !------------------------------------------------------------------------------- + + sms(k,idon) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Phytoplankton Excretion + !--------------------------------------------------------------------------- + + lossN * limitFacN * phyN & ! Small phytoplankton + + lossN_d * limitFacN_Dia * DiaN & ! Diatoms + + lossN_c * limitFacN_Cocco * CoccoN * is_coccos & ! Coccolithophores + + lossN_p * limitFacN_Phaeo * PhaeoN * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SOURCES: Detrital Remineralization + !--------------------------------------------------------------------------- + + reminN * arrFunc * O2Func * DetN & ! Slow-sinking detritus + + reminN * arrFunc * O2Func * DetZ2N * is_3zoo2det & ! Fast-sinking detritus + !--------------------------------------------------------------------------- + ! SOURCES: Zooplankton Excretion + !--------------------------------------------------------------------------- + + lossN_z * HetN & ! Mesozooplankton + + lossN_z2 * Zoo2N * is_3zoo2det & ! Macrozooplankton + + lossN_z3 * MicZooN * is_3zoo2det & ! Microzooplankton + !--------------------------------------------------------------------------- + ! SINKS: Remineralization to NH4 + !--------------------------------------------------------------------------- + - rho_N * arrFunc * O2Func * DON & ! Bacterial remineralization + ) * dt_b + sms(k,idon) + + !=============================================================================== + ! 20. EXTRACELLULAR ORGANIC CARBON (EOC / DOC) + !=============================================================================== + ! Dissolved organic carbon pool from phytoplankton excretion, zooplankton + ! metabolism, and detrital remineralization. + ! + ! Variables: + ! lossC, lossC_d, lossC_c, lossC_p : Phytoplankton DOC excretion rates [day-1] + ! limitFacN, limitFacN_dia, etc. : N:C ratio limiters (regulate excretion) [-] + ! reminC : Detrital C remineralization rate [day-1] + ! rho_c1 : DOC remineralization rate [day-1] + ! lossC_z, lossC_z2, lossC_z3 : Zooplankton DOC excretion rates [day-1] + !------------------------------------------------------------------------------- + + sms(k,idoc) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Phytoplankton Excretion + !--------------------------------------------------------------------------- + + lossC * limitFacN * phyC & ! Small phytoplankton + + lossC_d * limitFacN_dia * DiaC & ! Diatoms + + lossC_c * limitFacN_cocco * CoccoC * is_coccos & ! Coccolithophores + + lossC_p * limitFacN_Phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SOURCES: Detrital Remineralization + !--------------------------------------------------------------------------- + + reminC * arrFunc * O2Func * DetC & ! Slow-sinking detritus + + reminC * arrFunc * O2Func * DetZ2C * is_3zoo2det & ! Fast-sinking detritus + !--------------------------------------------------------------------------- + ! SOURCES: Zooplankton Excretion + !--------------------------------------------------------------------------- + + lossC_z * HetC & ! Mesozooplankton + + lossC_z2 * Zoo2C * is_3zoo2det & ! Macrozooplankton + + lossC_z3 * MicZooC * is_3zoo2det & ! Microzooplankton + !--------------------------------------------------------------------------- + ! SINKS: Remineralization to CO2 + !--------------------------------------------------------------------------- + - rho_c1 * arrFunc * O2Func * EOC & ! Bacterial respiration + ) * dt_b + sms(k,idoc) + + !=============================================================================== + ! 21. DIATOM NITROGEN (DiaN) + !=============================================================================== + ! Tracks nitrogen content of diatoms (large phytoplankton with silica frustules). + ! + ! Variables: + ! N_assim_dia : N assimilation rate [day-1] + ! lossN_d : N loss rate [day-1] + ! limitFacN_dia : Limiter function for N:C ratio regulation [-] + ! aggregationRate : Aggregation to detritus [day-1] + ! grazingFlux_Dia : Mesozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_Dia2 : Macrozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_Dia3 : Microzooplankton grazing [mmolN m-3 day-1] + !------------------------------------------------------------------------------- + + sms(k,idian) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Nitrogen Assimilation + !--------------------------------------------------------------------------- + + N_assim_dia * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: DON Excretion + !--------------------------------------------------------------------------- + - lossN_d * limitFacN_dia * DiaN & + !--------------------------------------------------------------------------- + ! SINKS: Aggregation + !--------------------------------------------------------------------------- + - aggregationRate * DiaN & + !--------------------------------------------------------------------------- + ! SINKS: Grazing + !--------------------------------------------------------------------------- + - grazingFlux_Dia & ! Mesozooplankton + - grazingFlux_Dia2 * is_3zoo2det & ! Macrozooplankton + - grazingFlux_Dia3 * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,idian) + + !=============================================================================== + ! 22. DIATOM CARBON (DiaC) + !=============================================================================== + ! Tracks carbon content of diatoms. + ! + ! Variables: + ! Cphot_dia : Gross photosynthesis rate [day-1] + ! phyRespRate_dia : Autotrophic respiration rate [day-1] + ! lossC_d : C loss rate [day-1] + ! recipQuota_dia : Reciprocal of N:C quota (for N->C conversion) [-] + !------------------------------------------------------------------------------- + + sms(k,idiac) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Net Photosynthesis + !--------------------------------------------------------------------------- + + Cphot_dia * DiaC & ! Gross photosynthesis + !--------------------------------------------------------------------------- + ! SINKS: DOC Excretion + !--------------------------------------------------------------------------- + - lossC_d * limitFacN_dia * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: Respiration + !--------------------------------------------------------------------------- + - phyRespRate_dia * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: Aggregation + !--------------------------------------------------------------------------- + - aggregationRate * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: Grazing (C-basis) + !--------------------------------------------------------------------------- + - grazingFlux_dia * recipQuota_dia & ! Mesozooplankton (N->C) + - grazingFlux_dia2 * recipQuota_dia * is_3zoo2det & ! Macrozooplankton + - grazingFlux_dia3 * recipQuota_dia * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,idiac) + + !=============================================================================== + ! 23. DIATOM CHLOROPHYLL-A (DiaChl) + !=============================================================================== + ! Tracks chlorophyll-a content for light harvesting and photoacclimation. + ! + ! Variables: + ! chlSynth_dia : Chlorophyll synthesis rate [mgChl mmolC-1 day-1] + ! KOchl_dia : Chlorophyll degradation rate [day-1] + ! Chl2N_dia : Chl:N ratio = DiaChl/DiaN [mgChl mmolN-1] + !------------------------------------------------------------------------------- + + sms(k,idchl) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Chlorophyll Synthesis + !--------------------------------------------------------------------------- + + chlSynth_dia * DiaC & ! Photoacclimation + !--------------------------------------------------------------------------- + ! SINKS: Photo-oxidation + !--------------------------------------------------------------------------- + - KOchl_dia * DiaChl & + !--------------------------------------------------------------------------- + ! SINKS: Aggregation + !--------------------------------------------------------------------------- + - aggregationRate * DiaChl & + !--------------------------------------------------------------------------- + ! SINKS: Grazing (Chl-basis) + !--------------------------------------------------------------------------- + - grazingFlux_dia * Chl2N_dia & ! Mesozooplankton (N->Chl) + - grazingFlux_dia2 * Chl2N_dia * is_3zoo2det & ! Macrozooplankton + - grazingFlux_dia3 * Chl2N_dia * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,idchl) + + !=============================================================================== + ! 24. DIATOM SILICA (DiaSi) + !=============================================================================== + ! Tracks biogenic silica content in diatom frustules. + ! + ! Variables: + ! Si_assim : Silicic acid assimilation rate [day-1] + ! qSiN : Si:N ratio in diatoms [mmolSi mmolN-1] + !------------------------------------------------------------------------------- + + sms(k,idiasi) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Silicon Assimilation + !--------------------------------------------------------------------------- + + Si_assim * DiaC & + !--------------------------------------------------------------------------- + ! SINKS: Silicon Excretion + !--------------------------------------------------------------------------- + - lossN_d * limitFacN_dia * DiaSi & + !--------------------------------------------------------------------------- + ! SINKS: Aggregation + !--------------------------------------------------------------------------- + - aggregationRate * DiaSi & + !--------------------------------------------------------------------------- + ! SINKS: Grazing (Si-basis) + !--------------------------------------------------------------------------- + - grazingFlux_dia * qSiN & ! Mesozooplankton (N->Si) + - grazingFlux_dia2 * qSiN * is_3zoo2det & ! Macrozooplankton + - grazingFlux_dia3 * qSiN * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,idiasi) + + !=============================================================================== + ! 25. COCCOLITHOPHORE NITROGEN (CoccoN) + !=============================================================================== + ! Tracks nitrogen content of coccolithophores (calcifying small phytoplankton). + ! Only active when enable_coccos = .true. + ! + ! Variables: + ! N_assim_cocco : N assimilation rate [day-1] + ! lossN_c : N loss rate [day-1] + ! limitFacN_cocco : Limiter function for N:C ratio regulation [-] + ! aggregationRate : Aggregation to detritus [day-1] + ! grazingFlux_Cocco : Mesozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_Cocco2 : Macrozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_Cocco3 : Microzooplankton grazing [mmolN m-3 day-1] + !------------------------------------------------------------------------------- + + if (enable_coccos) then + sms(k,icocn) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Nitrogen Assimilation + !----------------------------------------------------------------------- + + N_assim_cocco * CoccoC & + !----------------------------------------------------------------------- + ! SINKS: DON Excretion + !----------------------------------------------------------------------- + - lossN_c * limitFacN_cocco * CoccoN & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * CoccoN & + !----------------------------------------------------------------------- + ! SINKS: Grazing + !----------------------------------------------------------------------- + - grazingFlux_Cocco & ! Mesozooplankton + - grazingFlux_Cocco2 * is_3zoo2det & ! Macrozooplankton + - grazingFlux_Cocco3 * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,icocn) + + !=============================================================================== + ! 26. COCCOLITHOPHORE CARBON (CoccoC) + !=============================================================================== + ! Tracks carbon content of coccolithophores. + ! + ! Variables: + ! Cphot_cocco : Gross photosynthesis rate [day-1] + ! phyRespRate_cocco : Autotrophic respiration rate [day-1] + ! lossC_c : C loss rate [day-1] + ! recipQuota_cocco : Reciprocal of N:C quota (for N->C conversion) [-] + !------------------------------------------------------------------------------- + + sms(k,icocc) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Net Photosynthesis + !----------------------------------------------------------------------- + + Cphot_cocco * CoccoC & ! Gross photosynthesis + !----------------------------------------------------------------------- + ! SINKS: DOC Excretion + !----------------------------------------------------------------------- + - lossC_c * limitFacN_cocco * CoccoC & + !----------------------------------------------------------------------- + ! SINKS: Respiration + !----------------------------------------------------------------------- + - phyRespRate_cocco * CoccoC & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * CoccoC & + !----------------------------------------------------------------------- + ! SINKS: Grazing (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_cocco * recipQuota_cocco & ! Mesozooplankton (N->C) + - grazingFlux_Cocco2 * recipQuota_cocco * is_3zoo2det & ! Macrozooplankton + - grazingFlux_Cocco3 * recipQuota_cocco * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,icocc) + + !--------------------------------------------------------------------------- + ! Error Check: Unrealistic CoccoC Growth + !--------------------------------------------------------------------------- + if(sms(k,icocc) > 100) then + print*,'ERROR: Unrealistic CoccoC growth detected!' + print*,'k= ', k + print*,'dt= ', dt + print*,'dt_b= ', dt_b + print*,'state(k,icocc): ', state(k,icocc) + print*,'CoccoC: ', CoccoC + print*,'CoccoN: ', CoccoN + print*,'Cphot_cocco: ', Cphot_cocco*CoccoC + print*,'lossC_c: ', lossC_c + print*,'limitFacN_cocco: ', limitFacN_cocco + print*,'phyRespRate_cocco: ', phyRespRate_cocco + print*,'grazingFlux_cocco: ', grazingFlux_cocco + print*,'grazingFlux_Cocco2: ', grazingFlux_Cocco2 + print*,'grazingFlux_Cocco3: ', grazingFlux_Cocco3 + print*,'recipQuota_cocco: ', recipQuota_cocco + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + endif -!*** Si *** -!< decayRateBenSi: Remineralization rate for benthic Si [day^-1] -!< LocBenthos(3) : Vertically integrated N concentration in benthos (1 layer) [mmolSi/m^2] - decayBenthos(3) = decayRateBenSi * LocBenthos(3) ! [1/day] * [mmolSi/m2] -> [mmolSi/m2/day] - LocBenthos(3) = LocBenthos(3) - decaybenthos(3) * dt_b + !=============================================================================== + ! 27. COCCOLITHOPHORE CHLOROPHYLL-A (CoccoChl) + !=============================================================================== + ! Tracks chlorophyll-a content for light harvesting and photoacclimation. + ! + ! Variables: + ! ChlSynth_cocco : Chlorophyll synthesis rate [mgChl mmolC-1 day-1] + ! KOchl_cocco : Chlorophyll degradation rate [day-1] + ! Chl2N_cocco : Chl:N ratio = CoccoChl/CoccoN [mgChl mmolN-1] + !------------------------------------------------------------------------------- + + sms(k,icchl) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Chlorophyll Synthesis + !----------------------------------------------------------------------- + + ChlSynth_cocco * CoccoC & ! Photoacclimation + !----------------------------------------------------------------------- + ! SINKS: Photo-oxidation + !----------------------------------------------------------------------- + - KOchl_cocco * CoccoChl & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * CoccoChl & + !----------------------------------------------------------------------- + ! SINKS: Grazing (Chl-basis) + !----------------------------------------------------------------------- + - grazingFlux_cocco * Chl2N_cocco & ! Mesozooplankton (N->Chl) + - grazingFlux_Cocco2 * Chl2N_cocco * is_3zoo2det & ! Macrozooplankton + - grazingFlux_Cocco3 * Chl2N_cocco * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,icchl) + + !=============================================================================== + ! 28. PHAEOCYSTIS NITROGEN (PhaeoN) + !=============================================================================== + ! Tracks nitrogen content of Phaeocystis (colony-forming phytoplankton). + ! Only active when enable_coccos = .true. + ! + ! Variables: + ! N_assim_phaeo : N assimilation rate [day-1] + ! lossN_p : N loss rate [day-1] + ! limitFacN_phaeo : Limiter function for N:C ratio regulation [-] + ! aggregationRate : Aggregation to detritus [day-1] + ! grazingFlux_phaeo : Mesozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_phaeo2 : Macrozooplankton grazing [mmolN m-3 day-1] + ! grazingFlux_phaeo3 : Microzooplankton grazing [mmolN m-3 day-1] + !------------------------------------------------------------------------------- + + sms(k,iphan) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Nitrogen Assimilation + !----------------------------------------------------------------------- + + N_assim_phaeo * PhaeoC & + !----------------------------------------------------------------------- + ! SINKS: DON Excretion + !----------------------------------------------------------------------- + - lossN_p * limitFacN_phaeo * PhaeoN & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * PhaeoN & + !----------------------------------------------------------------------- + ! SINKS: Grazing + !----------------------------------------------------------------------- + - grazingFlux_phaeo & ! Mesozooplankton + - grazingFlux_phaeo2 * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phaeo3 * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphan) + + !=============================================================================== + ! 29. PHAEOCYSTIS CARBON (PhaeoC) + !=============================================================================== + ! Tracks carbon content of Phaeocystis. + ! + ! Variables: + ! Cphot_phaeo : Gross photosynthesis rate [day-1] + ! phyRespRate_phaeo : Autotrophic respiration rate [day-1] + ! lossC_p : C loss rate [day-1] + ! recipQuota_phaeo : Reciprocal of N:C quota (for N->C conversion) [-] + !------------------------------------------------------------------------------- + + sms(k,iphac) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Net Photosynthesis + !----------------------------------------------------------------------- + + Cphot_phaeo * PhaeoC & ! Gross photosynthesis + !----------------------------------------------------------------------- + ! SINKS: DOC Excretion + !----------------------------------------------------------------------- + - lossC_p * limitFacN_phaeo * PhaeoC & + !----------------------------------------------------------------------- + ! SINKS: Respiration + !----------------------------------------------------------------------- + - phyRespRate_phaeo * PhaeoC & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * PhaeoC & + !----------------------------------------------------------------------- + ! SINKS: Grazing (C-basis) + !----------------------------------------------------------------------- + - grazingFlux_phaeo * recipQuota_phaeo & ! Mesozooplankton (N->C) + - grazingFlux_phaeo2 * recipQuota_phaeo * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phaeo3 * recipQuota_phaeo * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphac) + + !=============================================================================== + ! 30. PHAEOCYSTIS CHLOROPHYLL-A (PhaeoChl) + !=============================================================================== + ! Tracks chlorophyll-a content for light harvesting and photoacclimation. + ! + ! Variables: + ! chlSynth_phaeo : Chlorophyll synthesis rate [mgChl mmolC-1 day-1] + ! KOchl_phaeo : Chlorophyll degradation rate [day-1] + ! Chl2N_phaeo : Chl:N ratio = PhaeoChl/PhaeoN [mgChl mmolN-1] + !------------------------------------------------------------------------------- + + sms(k,iphachl) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Chlorophyll Synthesis + !----------------------------------------------------------------------- + + chlSynth_phaeo * PhaeoC & ! Photoacclimation + !----------------------------------------------------------------------- + ! SINKS: Photo-oxidation + !----------------------------------------------------------------------- + - KOchl_phaeo * PhaeoChl & + !----------------------------------------------------------------------- + ! SINKS: Aggregation + !----------------------------------------------------------------------- + - aggregationRate * PhaeoChl & + !----------------------------------------------------------------------- + ! SINKS: Grazing (Chl-basis) + !----------------------------------------------------------------------- + - grazingFlux_phaeo * Chl2N_phaeo & ! Mesozooplankton (N->Chl) + - grazingFlux_phaeo2 * Chl2N_phaeo * is_3zoo2det & ! Macrozooplankton + - grazingFlux_phaeo3 * Chl2N_phaeo * is_3zoo2det & ! Microzooplankton + ) * dt_b + sms(k,iphachl) + + endif ! enable_coccos + + !=============================================================================== + ! 31. DETRITAL SILICA (DetSi) + !=============================================================================== + ! Biogenic silica from diatom frustules in slow-sinking detritus. + ! + ! Variables: + ! aggregationRate : Diatom aggregation rate [day-1] + ! lossN_d : Diatom mortality/excretion rate [day-1] + ! grazingFlux_dia, grazingFlux_dia3 : Grazing on diatoms [mmolN m-3 day-1] + ! qSiN : Si:N ratio in diatoms [mmolSi mmolN-1] + ! reminSiT : Temperature-dependent dissolution [day-1] + !------------------------------------------------------------------------------- + + sms(k,idetsi) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Diatom Aggregation + !--------------------------------------------------------------------------- + + aggregationRate * DiaSi & + !--------------------------------------------------------------------------- + ! SOURCES: Diatom Excretion/Mortality + !--------------------------------------------------------------------------- + + lossN_d * limitFacN_dia * DiaSi & + !--------------------------------------------------------------------------- + ! SOURCES: Grazing on Diatoms (Si-basis) + !--------------------------------------------------------------------------- + + grazingFlux_dia3 * qSiN * is_3zoo2det & ! Microzooplankton + + grazingFlux_dia * qSiN * (1.0 - is_3zoo2det) & ! Mesozooplankton (when 3zoo disabled) + !--------------------------------------------------------------------------- + ! SINKS: Dissolution + !--------------------------------------------------------------------------- + - reminSiT * DetSi & ! Temperature-dependent + ) * dt_b + sms(k,idetsi) + + !=============================================================================== + ! 32. DISSOLVED SILICATE (DSi) + !=============================================================================== + ! Dissolved silicate available for diatom uptake. + ! Based on Schourup 2013 Eq. A3 + ! + ! Variables: + ! Si_assim : Silicic acid assimilation by diatoms [day-1] + ! reminSiT : Temperature-dependent dissolution [day-1] + ! DetSi, DetZ2Si : Detrital silica pools [mmolSi m-3] + !------------------------------------------------------------------------------- + + sms(k,isi) = ( & + !--------------------------------------------------------------------------- + ! SINKS: Biological Uptake + !--------------------------------------------------------------------------- + - Si_assim * DiaC & + !--------------------------------------------------------------------------- + ! SOURCES: Remineralization + !--------------------------------------------------------------------------- + + reminSiT * DetSi & ! Slow-sinking detritus + + reminSiT * DetZ2Si * is_3zoo2det & ! Fast-sinking detritus + ) * dt_b + sms(k,isi) + + !=============================================================================== + ! 33. DISSOLVED IRON (Fe) + !=============================================================================== + ! Tracks dissolved iron, a limiting micronutrient for phytoplankton growth. + ! + ! Key Concept: Iron cycling is coupled to nitrogen via the Fe:N ratio (Fe2N) + ! All N-based fluxes are converted to Fe equivalents + ! + ! Variables: + ! Fe2N : Intracellular Fe:N ratio [μmol Fe mmol N-1] + ! Note: Fe2N = Fe2C × 6.625 (Redfield conversion) + ! N_assim, N_assim_dia, etc. : N assimilation rates [mmol N mmol C-1 day-1] + ! lossN, lossN_d, etc. : N excretion rates [day-1] + ! limitFacN, etc. : Nutrient limitation factors [-] + ! reminN : Temperature-dependent remineralization [day-1] + ! kScavFe : Iron scavenging rate [m3 mmol C-1 day-1] + ! FreeFe : Free dissolved iron [μmol Fe m-3] + !------------------------------------------------------------------------------- + + sms(k,ife) = ( & + !--------------------------------------------------------------------------- + ! Iron Uptake/Release Coupled to Nitrogen Cycling (via Fe:N ratio) + !--------------------------------------------------------------------------- + Fe2N * ( & + !----------------------------------------------------------------------- + ! SINKS: Phytoplankton Assimilation + !----------------------------------------------------------------------- + - N_assim * PhyC & ! Small phytoplankton + - N_assim_dia * DiaC & ! Diatoms + - N_assim_cocco * CoccoC * is_coccos & ! Coccolithophores + - N_assim_phaeo * PhaeoC * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Phytoplankton Excretion + !----------------------------------------------------------------------- + + lossN * limitFacN * PhyN & ! Small phytoplankton + + lossN_d * limitFacN_dia * DiaN & ! Diatoms + + lossN_c * limitFacN_cocco * CoccoN * is_coccos & ! Coccolithophores + + lossN_p * limitFacN_phaeo * PhaeoN * is_coccos & ! Phaeocystis + !----------------------------------------------------------------------- + ! SOURCES: Detrital Remineralization + !----------------------------------------------------------------------- + + reminN * arrFunc * O2Func * DetN & ! Slow-sinking detritus + + reminN * arrFunc * O2Func * DetZ2N * is_3zoo2det & ! Fast-sinking detritus + !----------------------------------------------------------------------- + ! SOURCES: Zooplankton Excretion + !----------------------------------------------------------------------- + + lossN_z * HetN & ! Mesozooplankton + + lossN_z2 * Zoo2N * is_3zoo2det & ! Macrozooplankton + + lossN_z3 * MicZooN * is_3zoo2det & ! Microzooplankton + ) & + !--------------------------------------------------------------------------- + ! SINKS: Abiotic Iron Scavenging onto Particles + !--------------------------------------------------------------------------- + - kScavFe * DetC * FreeFe & ! Slow-sinking detritus + - kScavFe * DetZ2C * FreeFe * is_3zoo2det & ! Fast-sinking detritus + ) * dt_b + sms(k,ife) + + !=============================================================================== + ! 34. PHYTOPLANKTON CALCITE (PhyCalc) + !=============================================================================== + ! Tracks calcium carbonate in living phytoplankton (coccoliths). + ! + ! Variables: + ! calcification : CaCO3 production rate [mmolCaCO3 m-3 day-1] + ! calc_loss_agg : Calcite loss to aggregation [mmolCaCO3 m-3 day-1] + ! calc_loss_gra, calc_loss_gra2, calc_loss_gra3 : Calcite loss to grazing [mmolCaCO3 m-3 day-1] + ! lossC, lossC_c : C excretion rates [day-1] + ! phyRespRate, phyRespRate_cocco : Respiration rates [day-1] + ! limitFacN, limitFacN_cocco : N:C ratio limiters [-] + !------------------------------------------------------------------------------- + + if (enable_coccos) then + !--------------------------------------------------------------------------- + ! Configuration: Coccolithophore-Specific Calcite Dynamics + !--------------------------------------------------------------------------- + sms(k,iphycal) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Calcification + !----------------------------------------------------------------------- + + calcification & ! New CaCO3 production + !----------------------------------------------------------------------- + ! SINKS: Losses from Living Cells + !----------------------------------------------------------------------- + - lossC_c * limitFacN_cocco * PhyCalc & ! Excretion/exudation + - phyRespRate_cocco * PhyCalc & ! Respiration-associated loss + - calc_loss_agg & ! Aggregation/sinking + - calc_loss_gra & ! Mesozooplankton grazing + - calc_loss_gra2 * is_3zoo2det & ! Macrozooplankton grazing + - calc_loss_gra3 * is_3zoo2det & ! Microzooplankton grazing + ) * dt_b + sms(k,iphycal) + else + !--------------------------------------------------------------------------- + ! Configuration: Generic Phytoplankton Calcite (Small Calcifiers) + !--------------------------------------------------------------------------- + sms(k,iphycal) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Calcification + !----------------------------------------------------------------------- + + calcification & + !----------------------------------------------------------------------- + ! SINKS: Losses from Living Cells + !----------------------------------------------------------------------- + - lossC * limitFacN * PhyCalc & + - phyRespRate * PhyCalc & + - calc_loss_agg & + - calc_loss_gra & + - calc_loss_gra2 * is_3zoo2det & + - calc_loss_gra3 * is_3zoo2det & + ) * dt_b + sms(k,iphycal) + endif -!*** Calc: DIC, Alk *** ! OG calc_diss_ben is taken from the deepest level - decayBenthos(4) = calc_diss_ben * LocBenthos(4) ! NEW DISS changed calc_diss to calc_diss_ben to not make the dissolution omega dependent when using the switch OmegaC_diss - LocBenthos(4) = LocBenthos(4) - decayBenthos(4) * dt_b + !=============================================================================== + ! 35. DETRITAL CALCITE (DetCalc) + !=============================================================================== + ! Tracks calcium carbonate in slow-sinking organic particles. + ! + ! Variables: + ! calc_loss_agg : Calcite from aggregation [mmolCaCO3 m-3 day-1] + ! calc_loss_gra, calc_loss_gra3 : Calcite from grazing [mmolCaCO3 m-3 day-1] + ! calc_diss_guts : Gut dissolution fraction [-] + ! calc_diss : Water column dissolution rate [day-1] + !------------------------------------------------------------------------------- + + if (enable_coccos) then + if (enable_3zoo2det) then + !----------------------------------------------------------------------- + ! Configuration: Coccolithophore Calcite with 3-Zooplankton Model + !----------------------------------------------------------------------- + sms(k,idetcal) = ( & + !------------------------------------------------------------------- + ! SOURCES: Transfer from Living Cells + !------------------------------------------------------------------- + + lossC_c * limitFacN_cocco * PhyCalc & ! Excretion + + phyRespRate_cocco * PhyCalc & ! Respiration products + + calc_loss_agg & ! Aggregation products + + calc_loss_gra3 & ! Microzooplankton grazing + !------------------------------------------------------------------- + ! SINKS: Dissolution + !------------------------------------------------------------------- + - calc_loss_gra3 * calc_diss_guts & ! Gut dissolution + - calc_diss * DetCalc & ! Water column dissolution + ) * dt_b + sms(k,idetcal) + else + !----------------------------------------------------------------------- + ! Configuration: Coccolithophore Calcite with Standard Zooplankton + !----------------------------------------------------------------------- + sms(k,idetcal) = ( & + !------------------------------------------------------------------- + ! SOURCES: Transfer from Living Cells + !------------------------------------------------------------------- + + lossC_c * limitFacN_cocco * PhyCalc & + + phyRespRate_cocco * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + !------------------------------------------------------------------- + ! SINKS: Dissolution + !------------------------------------------------------------------- + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + endif + else + if (enable_3zoo2det) then + !----------------------------------------------------------------------- + ! Configuration: Generic Phytoplankton Calcite with 3-Zooplankton + !----------------------------------------------------------------------- + sms(k,idetcal) = ( & + !------------------------------------------------------------------- + ! SOURCES: Transfer from Living Cells + !------------------------------------------------------------------- + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra3 & + !------------------------------------------------------------------- + ! SINKS: Dissolution + !------------------------------------------------------------------- + - calc_loss_gra3 * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + else + !----------------------------------------------------------------------- + ! Configuration: Generic Phytoplankton Calcite with Standard Zooplankton + !----------------------------------------------------------------------- + sms(k,idetcal) = ( & + !------------------------------------------------------------------- + ! SOURCES: Transfer from Living Cells + !------------------------------------------------------------------- + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + !------------------------------------------------------------------- + ! SINKS: Dissolution + !------------------------------------------------------------------- + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + endif + endif + + !=============================================================================== + ! 36. DISSOLVED OXYGEN (O2) + !=============================================================================== + ! Tracks oxygen production (photosynthesis) and consumption (respiration, + ! remineralization). + ! + ! Variables: + ! Cphot, Cphot_dia, etc. : Gross photosynthesis rates [day-1] + ! phyRespRate, phyRespRate_dia, etc. : Autotrophic respiration rates [day-1] + ! rho_C1 : DOC remineralization rate [day-1] + ! hetRespFlux, Zoo2RespFlux, MicZooRespFlux : Zooplankton respiration [mmolC m-3 day-1] + ! redO2C : O2:C stoichiometric ratio (Redfield) [-] + ! Typically ~170/122 = 1.39 mol O2/mol C + !------------------------------------------------------------------------------- + + sms(k,ioxy) = ( & + !--------------------------------------------------------------------------- + ! SOURCES: Photosynthetic Oxygen Production + !--------------------------------------------------------------------------- + + Cphot * phyC & ! Small phytoplankton + + Cphot_dia * diaC & ! Diatoms + + Cphot_cocco * CoccoC * is_coccos & ! Coccolithophores + + Cphot_phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SINKS: Autotrophic Respiration + !--------------------------------------------------------------------------- + - phyRespRate * phyC & ! Small phytoplankton + - phyRespRate_dia * diaC & ! Diatoms + - phyRespRate_cocco * CoccoC * is_coccos & ! Coccolithophores + - phyRespRate_phaeo * PhaeoC * is_coccos & ! Phaeocystis + !--------------------------------------------------------------------------- + ! SINKS: Heterotrophic Respiration and Remineralization + !--------------------------------------------------------------------------- + - rho_C1 * arrFunc * O2Func * EOC & ! DOC remineralization + - hetRespFlux & ! Mesozooplankton + - Zoo2RespFlux * is_3zoo2det & ! Macrozooplankton + - MicZooRespFlux * is_3zoo2det & ! Microzooplankton + ) * redO2C * dt_b + sms(k,ioxy) + ! Note: redO2C converts carbon-based rates to oxygen equivalents + ! using the Redfield ratio (typically ~170/122 = 1.39 mol O2/mol C) + + if (ciso) then + + !=========================================================================== + ! 1. CARBON-13 (13C) BUDGETS + !=========================================================================== + ! Calculates 13C budgets for all carbon pools with isotope fractionation. + ! Parallel structure to total carbon budgets. + !--------------------------------------------------------------------------- + + !=========================================================================== + ! DISSOLVED INORGANIC CARBON (DIC_13) + !=========================================================================== + ! Source-minus-sink budget for 13C in dissolved inorganic carbon pool. + ! + ! SOURCES (+): + ! - Phytoplankton respiration (returns 13C to DIC) + ! - Diatom respiration + ! - DOC remineralization (aerobic respiration) + ! - Heterotroph respiration + ! - Calcite dissolution (releases 13C from CaCO3) + ! - Calcite dissolution in grazer guts + ! + ! SINKS (-): + ! - Phytoplankton photosynthesis (fixes 13C into organic matter) + ! - Diatom photosynthesis + ! - Calcification (removes 13C for CaCO3 formation) + ! + ! Variables: + ! Cphot, Cphot_Dia : Photosynthesis rates [day-1] + ! PhyC_13, DiaC_13 : Phytoplankton 13C pools [mmol13C m-3] + ! phyRespRate : Phytoplankton respiration rates [day-1] + ! rho_C1 : DOC remineralization rate [day-1] + ! arrFunc : Temperature function [-] + ! EOC_13 : Dissolved organic 13C [mmol13C m-3] + ! HetRespFlux_13 : Heterotroph respiration flux [mmol13C m-3 day-1] + ! calc_diss_13 : Calcite dissolution rate [day-1] + ! DetCalc_13 : Detrital calcite 13C [mmol13C m-3] + ! calc_loss_gra_13 : Calcite grazing flux [mmol13C m-3 day-1] + ! calc_diss_guts : Gut dissolution fraction [-] + ! calcification_13 : Calcification flux [mmol13C m-3 day-1] + ! dt_b : Biogeochemistry time step [day] + ! + ! Note: Photosynthesis preferentially takes up 12C, leaving DIC enriched in 13C + ! Respiration returns carbon with original isotopic composition + !--------------------------------------------------------------------------- + + sms(k, idic_13) = ( & + !----------------------------------------------------------------------- + ! SINKS: Carbon fixation (removes 13C-DIC) + !----------------------------------------------------------------------- + - Cphot * PhyC_13 & ! Small phyto photosynthesis + - Cphot_Dia * DiaC_13 & ! Diatom photosynthesis + ! + !----------------------------------------------------------------------- + ! SOURCES: Respiration and remineralization (returns 13C to DIC) + !----------------------------------------------------------------------- + + phyRespRate * PhyC_13 & ! Small phyto respiration + + phyRespRate_Dia * DiaC_13 & ! Diatom respiration + + rho_C1 * arrFunc * EOC_13 & ! DOC remineralization + + HetRespFlux_13 & ! Heterotroph respiration + ! + !----------------------------------------------------------------------- + ! SOURCES: Calcite dissolution (releases 13C from CaCO3) + !----------------------------------------------------------------------- + + calc_diss_13 * DetCalc_13 & ! Water column dissolution + + calc_loss_gra_13 * calc_diss_guts & ! Gut dissolution + ! + !----------------------------------------------------------------------- + ! SINKS: Calcification (removes 13C for CaCO3 formation) + !----------------------------------------------------------------------- + - calcification_13 & ! CaCO3 precipitation + ! + ) * dt_b + sms(k, idic_13) + + !=========================================================================== + ! SMALL PHYTOPLANKTON ORGANIC CARBON (PhyC_13) + !=========================================================================== + ! 13C budget for small phytoplankton biomass. + ! + ! SOURCES (+): + ! - Photosynthesis (fixes 13C-DIC into biomass) + ! + ! SINKS (-): + ! - Nutrient-stress mortality (lysis) + ! - Respiration (maintenance costs) + ! - Aggregation (particle formation) + ! - Grazing by zooplankton + ! + ! Variables: + ! lossC : Mortality rate constant [day-1] + ! limitFacN : Nutrient limitation factor [0-1] + ! aggregationRate : Aggregation rate [day-1] + ! grazingFlux_phy : Grazing flux on small phyto [mmolN m-3 day-1] + ! recipQuota_13 : 13C:N ratio [mmol13C mmolN-1] + ! + ! Note: Grazing uses recipQuota_13 to convert N-based flux to 13C flux + !--------------------------------------------------------------------------- + + sms(k, iphyc_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Photosynthetic production + !----------------------------------------------------------------------- + + Cphot * PhyC_13 & ! 13C fixation + ! + !----------------------------------------------------------------------- + ! SINKS: Mortality, respiration, and losses + !----------------------------------------------------------------------- + - lossC * limitFacN * PhyC_13 & ! Nutrient-stress mortality + - phyRespRate * PhyC_13 & ! Respiration + - aggregationRate * PhyC_13 & ! Aggregation loss + - grazingFlux_phy * recipQuota_13 & ! Grazing loss (N->C conversion) + ! + ) * dt_b + sms(k, iphyc_13) + + !=========================================================================== + ! DETRITAL ORGANIC CARBON (DetC_13) + !=========================================================================== + ! 13C budget for dead organic matter (detritus pool). + ! + ! SOURCES (+): + ! - Unassimilated grazing (sloppy feeding + egestion) + ! - Phytoplankton aggregation + ! - Diatom aggregation + ! - Heterotroph mortality + ! + ! SINKS (-): + ! - Remineralization (aerobic respiration) + ! - Assimilated grazing (efficient consumption) + ! + ! Variables: + ! grazEff : Grazing efficiency (fraction assimilated) [-] + ! hetLossFlux : Heterotroph mortality flux [mmolN m-3 day-1] + ! recipQZoo_13 : Heterotroph 13C:N ratio [mmol13C mmolN-1] + ! reminC : Detritus remineralization rate [day-1] + ! + ! Grazing Partitioning: + ! Total ingestion = Assimilated + Unassimilated + ! Assimilated: Goes to heterotroph biomass (grazEff × flux) + ! Unassimilated: Goes to detritus ((1-grazEff) × flux) + !--------------------------------------------------------------------------- + + sms(k, idetc_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Unassimilated grazing (sloppy feeding) + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota_13 & ! Total small phyto grazing + - grazingFlux_phy * recipQuota_13 * grazEff & ! Minus assimilated portion + + grazingFlux_Dia * recipQuota_dia_13 & ! Total diatom grazing + - grazingFlux_Dia * recipQuota_dia_13 * grazEff & ! Minus assimilated portion + ! + !----------------------------------------------------------------------- + ! SOURCES: Aggregation and mortality + !----------------------------------------------------------------------- + + aggregationRate * phyC_13 & ! Small phyto aggregation + + aggregationRate * DiaC_13 & ! Diatom aggregation + + hetLossFlux * recipQZoo_13 & ! Heterotroph mortality + ! + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - reminC * arrFunc * DetC_13 & ! Aerobic respiration + ! + ) * dt_b + sms(k, idetc_13) + + !=========================================================================== + ! HETEROTROPH ORGANIC CARBON (HetC_13) + !=========================================================================== + ! 13C budget for zooplankton biomass. + ! + ! SOURCES (+): + ! - Assimilated grazing on phytoplankton + ! - Assimilated grazing on diatoms + ! + ! SINKS (-): + ! - Mortality (density-dependent) + ! - Non-predatory losses (diseases, senescence) + ! - Respiration (metabolic costs) + ! + ! Variables: + ! lossC_z : Non-predatory loss rate [day-1] + ! hetRespFlux_13: Heterotroph respiration flux [mmol13C m-3 day-1] + ! + ! Note: Grazing efficiency (grazEff) determines assimilation fraction + ! Typical values: 0.6-0.8 (60-80% assimilated) + !--------------------------------------------------------------------------- + + sms(k, ihetc_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Assimilated food + !----------------------------------------------------------------------- + + grazingFlux_phy * recipQuota_13 * grazEff & ! Small phyto consumption + + grazingFlux_Dia * recipQuota_dia_13 * grazEff & ! Diatom consumption + ! + !----------------------------------------------------------------------- + ! SINKS: Mortality and respiration + !----------------------------------------------------------------------- + - hetLossFlux * recipQZoo_13 & ! Mortality flux + - lossC_z * HetC_13 & ! Non-predatory losses + - hetRespFlux_13 & ! Respiration + ! + ) * dt_b + sms(k, ihetc_13) + + !=========================================================================== + ! DISSOLVED ORGANIC CARBON (EOC_13) + !=========================================================================== + ! 13C budget for dissolved organic carbon pool. + ! + ! SOURCES (+): + ! - Phytoplankton exudation (nutrient-stress losses) + ! - Diatom exudation + ! - Detritus remineralization (solubilization) + ! - Heterotroph exudation (sloppy feeding, excretion) + ! - River input (terrestrial DOC) + ! + ! SINKS (-): + ! - Remineralization (microbial respiration) + ! + ! Variables: + ! lossC, lossC_d : Exudation rate constants [day-1] + ! limitFacN : Nutrient limitation factors [0-1] + ! LocRiverDOC : River DOC input flux [mmolC m-3 day-1] + ! r_iorg_13 : River 13C:12C ratio (isotopic signature) [-] + ! + ! DOC Pool Characteristics: + ! - Labile fraction: Days to weeks turnover + ! - Semi-labile fraction: Months to years turnover + ! - Model uses bulk DOC with single remineralization rate + ! + ! River Isotope Signature: + ! - Terrestrial organic matter typically depleted in 13C + ! - δ13C ≈ -27‰ for C3 plants, -13‰ for C4 plants + ! - Marine phytoplankton: δ13C ≈ -20 to -22‰ + !--------------------------------------------------------------------------- + + sms(k, idoc_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Exudation and solubilization + !----------------------------------------------------------------------- + + lossC * limitFacN * phyC_13 & ! Small phyto exudation + + lossC_d * limitFacN_dia * DiaC_13 & ! Diatom exudation + + reminC * arrFunc * DetC_13 & ! Detritus solubilization + + lossC_z * HetC_13 & ! Heterotroph exudation + ! + !----------------------------------------------------------------------- + ! SOURCES: River input (terrestrial DOC) + !----------------------------------------------------------------------- + + LocRiverDOC * r_iorg_13 & ! River 13C input + ! + !----------------------------------------------------------------------- + ! SINKS: Remineralization + !----------------------------------------------------------------------- + - rho_c1 * arrFunc * EOC_13 & ! Microbial respiration + ! + ) * dt_b + sms(k, idoc_13) + + !=========================================================================== + ! DIATOM ORGANIC CARBON (DiaC_13) + !=========================================================================== + ! 13C budget for diatom biomass (large phytoplankton). + ! + ! Structure identical to small phytoplankton (section 1.2) + ! with diatom-specific parameters and fluxes. + !--------------------------------------------------------------------------- + + sms(k, idiac_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Photosynthetic production + !----------------------------------------------------------------------- + + Cphot_dia * DiaC_13 & ! 13C fixation + ! + !----------------------------------------------------------------------- + ! SINKS: Mortality, respiration, and losses + !----------------------------------------------------------------------- + - lossC_d * limitFacN_dia * DiaC_13 & ! Nutrient-stress mortality + - phyRespRate_dia * DiaC_13 & ! Respiration + - aggregationRate * DiaC_13 & ! Aggregation loss + - grazingFlux_dia * recipQuota_dia_13 & ! Grazing loss + ! + ) * dt_b + sms(k, idiac_13) + + !=========================================================================== + ! PHYTOPLANKTON CALCITE (PhyCalc_13) + !=========================================================================== + ! 13C budget for calcium carbonate associated with living phytoplankton. + ! + ! SOURCES (+): + ! - Calcification (CaCO3 precipitation on cells) + ! + ! SINKS (-): + ! - Nutrient-stress mortality (CaCO3 to detritus) + ! - Cell death respiration (CaCO3 to detritus) + ! - Aggregation (CaCO3 incorporated in aggregates) + ! - Grazing (CaCO3 consumed with cells) + ! + ! Variables: + ! calcification_13 : 13C calcification flux [mmol13C m-3 day-1] + ! phyCalc_13 : Phytoplankton calcite 13C [mmol13C m-3] + ! calc_loss_agg_13 : Aggregation loss flux [mmol13C m-3 day-1] + ! calc_loss_gra_13 : Grazing loss flux [mmol13C m-3 day-1] + ! + ! Calcite Isotope Fractionation: + ! - Small enrichment in 13C relative to DIC (~+1‰) + ! - Temperature-dependent fractionation + ! - Important for paleoclimate proxies (foraminifera, coccoliths) + !--------------------------------------------------------------------------- + + sms(k, iphycal_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Calcification + !----------------------------------------------------------------------- + + calcification_13 & ! CaCO3 precipitation + ! + !----------------------------------------------------------------------- + ! SINKS: Mortality and losses + !----------------------------------------------------------------------- + - lossC * limitFacN * phyCalc_13 & ! Mortality to detritus + - phyRespRate * phyCalc_13 & ! Death to detritus + - calc_loss_agg_13 & ! Aggregation + - calc_loss_gra_13 & ! Grazing + ! + ) * dt_b + sms(k, iphycal_13) + + !=========================================================================== + ! DETRITAL CALCITE (DetCalc_13) + !=========================================================================== + ! 13C budget for calcium carbonate in detritus/particles. + ! + ! SOURCES (+): + ! - Phytoplankton mortality (CaCO3 from dead cells) + ! - Cell death (respiratory loss to detritus) + ! - Aggregation (CaCO3 in aggregates) + ! - Grazing (CaCO3 in fecal pellets) + ! + ! SINKS (-): + ! - Dissolution in water column + ! - Dissolution in grazer guts + ! + ! Variables: + ! calc_diss_guts : Fraction dissolved in guts (typically 0.1-0.5) [-] + ! + ! Calcite Dissolution: + ! - Thermodynamically driven (saturation state dependent) + ! - Faster in undersaturated waters (deep ocean, high CO2) + ! - Gut dissolution: Acidic environment accelerates dissolution + ! - Returns 13C to DIC pool (source for DIC_13 budget) + !--------------------------------------------------------------------------- + + sms(k, idetcal_13) = ( & + !----------------------------------------------------------------------- + ! SOURCES: Mortality and transfer from living cells + !----------------------------------------------------------------------- + + lossC * limitFacN * phyCalc_13 & ! Mortality + + phyRespRate * phyCalc_13 & ! Death + + calc_loss_agg_13 & ! Aggregation + + calc_loss_gra_13 & ! Grazing (to fecal pellets) + ! + !----------------------------------------------------------------------- + ! SINKS: Dissolution + !----------------------------------------------------------------------- + - calc_loss_gra_13 * calc_diss_guts & ! Gut dissolution + - calc_diss_13 * DetCalc_13 & ! Water column dissolution + ! + ) * dt_b + sms(k, idetcal_13) + + if (ciso_14) then + + if (ciso_organic_14) then + + !=================================================================== + ! CARBON-14 (14C) BUDGETS + !=================================================================== + ! Calculates 14C budgets for radiocarbon applications. + ! Structure identical to 13C budgets (sections 1.1-1.8). + ! + ! Additional Consideration: + ! - Radioactive decay (half-life 5,730 years) + ! - Decay term handled separately in forcing module + ! - Bomb radiocarbon (anthropogenic 14C pulse) + ! + ! Applications: + ! - Ocean ventilation age (Δ14C) + ! - Carbon residence time + ! - Mixing timescales + ! - Model validation (WOCE/CLIVAR 14C data) + ! + ! Notation: + ! All variables end in _14 (e.g., PhyC_14, DiaC_14) + ! Structure parallels 13C budgets exactly + !------------------------------------------------------------------- + + !=================================================================== + ! DIC_14 + !=================================================================== + sms(k, idic_14) = ( & + - Cphot * PhyC_14 & + + phyRespRate * PhyC_14 & + - Cphot_Dia * DiaC_14 & + + phyRespRate_Dia * DiaC_14 & + + rho_C1 * arrFunc * EOC_14 & + + HetRespFlux_14 & + + calc_diss_14 * DetCalc_14 & + + calc_loss_gra_14 * calc_diss_guts & + - calcification_14 & + ) * dt_b + sms(k, idic_14) + + !=================================================================== + ! PhyC_14 + !=================================================================== + sms(k, iphyc_14) = ( & + + Cphot * PhyC_14 & + - lossC * limitFacN * PhyC_14 & + - phyRespRate * PhyC_14 & + - aggregationRate * PhyC_14 & + - grazingFlux_phy * recipQuota_14 & + ) * dt_b + sms(k, iphyc_14) + + !=================================================================== + ! DetC_14 + !=================================================================== + sms(k, idetc_14) = ( & + + grazingFlux_phy * recipQuota_14 & + - grazingFlux_phy * recipQuota_14 * grazEff & + + grazingFlux_Dia * recipQuota_dia_14 & + - grazingFlux_Dia * recipQuota_dia_14 * grazEff & + + aggregationRate * phyC_14 & + + aggregationRate * DiaC_14 & + + hetLossFlux * recipQZoo_14 & + - reminC * arrFunc * DetC_14 & + ) * dt_b + sms(k, idetc_14) + + !=================================================================== + ! HetC_14 + !=================================================================== + sms(k, ihetc_14) = ( & + + grazingFlux_phy * recipQuota_14 * grazEff & + + grazingFlux_Dia * recipQuota_dia_14 * grazEff & + - hetLossFlux * recipQZoo_14 & + - lossC_z * HetC_14 & + - hetRespFlux_14 & + ) * dt_b + sms(k, ihetc_14) + + !=================================================================== + ! EOC_14 + !=================================================================== + sms(k, idoc_14) = ( & + + lossC * limitFacN * phyC_14 & + + lossC_d * limitFacN_dia * DiaC_14 & + + reminC * arrFunc * DetC_14 & + + lossC_z * HetC_14 & + - rho_c1 * arrFunc * EOC_14 & + + LocRiverDOC * r_iorg_14 & + ) * dt_b + sms(k, idoc_14) + + !=================================================================== + ! DiaC_14 + !=================================================================== + sms(k, idiac_14) = ( & + + Cphot_dia * DiaC_14 & + - lossC_d * limitFacN_dia * DiaC_14 & + - phyRespRate_dia * DiaC_14 & + - aggregationRate * DiaC_14 & + - grazingFlux_dia * recipQuota_dia_14 & + ) * dt_b + sms(k, idiac_14) + + !=================================================================== + ! PhyCalc_14 + !=================================================================== + sms(k, iphycal_14) = ( & + + calcification_14 & + - lossC * limitFacN * phyCalc_14 & + - phyRespRate * phyCalc_14 & + - calc_loss_agg_14 & + - calc_loss_gra_14 & + ) * dt_b + sms(k, iphycal_14) + + !=================================================================== + ! DetCalc_14 + !=================================================================== + sms(k, idetcal_14) = ( & + + lossC * limitFacN * phyCalc_14 & + + phyRespRate * phyCalc_14 & + + calc_loss_agg_14 & + + calc_loss_gra_14 & + - calc_loss_gra_14 * calc_diss_guts & + - calc_diss_14 * DetCalc_14 & + ) * dt_b + sms(k, idetcal_14) + + else + + !=================================================================== + ! ABIOTIC DIC_14 (SIMPLIFIED MODE) + !=================================================================== + ! "Abiotic" 14C tracking without explicit organic pools + ! DIC_14 tracks total carbon with radioactive decay only + ! + ! Use Case: + ! - Simplified radiocarbon tracer + ! - Tracks ventilation/mixing without biology + ! - Computationally efficient + ! - Decay handled in forcing module (recom_forcing) + ! + ! Equation: + ! DIC_14 changes identically to DIC (conservative tracer) + ! Plus: Radioactive decay (handled separately) + ! + ! Limitation: + ! - No isotope fractionation during biological processes + ! - Cannot capture biological isotope signals + ! - Suitable only for physical circulation studies + !------------------------------------------------------------------- + + sms(k, idic_14) = sms(k, idic) + + end if ! ciso_organic_14 + + end if ! ciso_14 + + end if ! ciso + !------------------------------------------------------------------------------- + ! DIAGNOSTIC ACCUMULATION INITIALIZATION + !------------------------------------------------------------------------------- + ! Calculate averaging weight for accumulating diagnostics over biogeochemical + ! sub-time steps. + ! + ! Variables: + ! recipbiostep : Reciprocal of number of bio sub-steps (averaging weight) [-] + ! biostep : Number of biogeochemistry steps per physics step [-] + ! + ! Averaging Approach: + ! Each sub-step contributes: (1/biostep) × rate + ! After biostep iterations: average rate over physics time step + ! + ! Example: + ! If biostep = 4 (4 bio steps per physics step) + ! recipbiostep = 0.25 + ! Each contribution weighted by 0.25 + ! Sum of 4 contributions = time-averaged rate + !------------------------------------------------------------------------------- + + recipbiostep = 1.d0 / real(biostep) + + if (Diags) then + + !=========================================================================== + ! PRIMARY PRODUCTION DIAGNOSTICS + !=========================================================================== + ! Net Primary Production (NPP) = Gross Production - Autotrophic Respiration + ! Gross Primary Production (GPP) = Photosynthetic carbon fixation only + ! + ! NPP represents carbon available for: + ! - Growth (biomass increase) + ! - Exudation (DOC production) + ! - Grazing by herbivores + ! + ! Units: mmolC m-3 day-1 + !--------------------------------------------------------------------------- + + !=========================================================================== + ! NET PRIMARY PRODUCTION (NPP) + !=========================================================================== + ! NPP = Photosynthesis - Respiration + ! Carbon available after meeting metabolic maintenance costs + ! + ! Variables (Small phytoplankton): + ! vertNPPn(k) : Time-averaged NPP for small phyto [mmolC m-3 day-1] + ! Cphot : Carbon-specific photosynthesis rate [day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! PhyRespRate : Respiration rate [day-1] + ! + ! Ecological Interpretation: + ! High NPP: Nutrient replete, optimal growth conditions + ! Low NPP: Nutrient/light limited, high respiration costs + ! Negative NPP: Respiration exceeds photosynthesis (rare, stress) + ! + ! Validation Targets: + ! - 14C uptake measurements + ! - Satellite-based NPP estimates (VGPM, CbPM, CAFE) + ! - Time series stations (HOT, BATS) + ! - Typical range: 0.1-10 mmolC m-3 day-1 (surface) + !--------------------------------------------------------------------------- + + ! Small phytoplankton NPP + vertNPPn(k) = vertNPPn(k) + ( & + + Cphot * PhyC & ! Photosynthetic production + - PhyRespRate * PhyC & ! Minus respiration costs + ) * recipbiostep + + ! Diatom NPP + vertNPPd(k) = vertNPPd(k) + ( & + + Cphot_dia * DiaC & + - PhyRespRate_dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore NPP + vertNPPc(k) = vertNPPc(k) + ( & + + Cphot_cocco * CoccoC & + - PhyRespRate_cocco * CoccoC & + ) * recipbiostep + + ! Phaeocystis NPP + vertNPPp(k) = vertNPPp(k) + ( & + + Cphot_phaeo * PhaeoC & + - PhyRespRate_phaeo * PhaeoC & + ) * recipbiostep + endif + + !=========================================================================== + ! GROSS PRIMARY PRODUCTION (GPP) + !=========================================================================== + ! GPP = Total photosynthetic carbon fixation (before respiration) + ! Represents maximum potential carbon uptake + ! + ! Relationship: + ! GPP = NPP + Respiration + ! Growth efficiency = NPP / GPP (typically 0.6-0.8) + ! + ! Uses: + ! - Calculate carbon use efficiency + ! - Compare to oxygen evolution (photosynthetic quotient) + ! - Understand temperature effects (GPP and R differ) + ! + ! Typical Values: + ! Surface: 1-20 mmolC m-3 day-1 + ! Deep chlorophyll max: 0.1-5 mmolC m-3 day-1 + ! Below euphotic zone: <0.01 mmolC m-3 day-1 + !--------------------------------------------------------------------------- + + ! Small phytoplankton GPP + vertGPPn(k) = vertGPPn(k) + ( & + + Cphot * PhyC & ! Total photosynthetic fixation + ) * recipbiostep + + ! Diatom GPP + vertGPPd(k) = vertGPPd(k) + ( & + + Cphot_dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore GPP + vertGPPc(k) = vertGPPc(k) + ( & + + Cphot_cocco * CoccoC & + ) * recipbiostep + + ! Phaeocystis GPP + vertGPPp(k) = vertGPPp(k) + ( & + + Cphot_phaeo * PhaeoC & + ) * recipbiostep + endif + + !=========================================================================== + ! NET NITROGEN ASSIMILATION + !=========================================================================== + ! Net nitrogen uptake = Assimilation - Exudation losses + ! Represents nitrogen incorporation into biomass + ! + ! Variables (Small phytoplankton): + ! vertNNAn(k) : Net N assimilation for small phyto [mmolN m-3 day-1] + ! N_assim : N-specific assimilation rate [mmolN mmolC-1 day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! lossN : N exudation rate constant [day-1] + ! limitFacN : Nutrient limitation factor [0-1] + ! PhyN : Small phytoplankton nitrogen [mmolN m-3] + ! + ! Ecological Interpretation: + ! Positive: Net nitrogen accumulation (growth) + ! Negative: Net nitrogen loss (stress-induced exudation) + ! Zero: Balanced uptake and loss (steady state) + ! + ! Relationship to C:N Ratio: + ! Net N assimilation / NPP = change in N:C quota + ! High ratio -> decreasing C:N (N accumulation) + ! Low ratio -> increasing C:N (N limitation) + ! + ! Validation: + ! - 15N tracer studies + ! - Nutrient depletion experiments + ! - Typical range: 0.01-2 mmolN m-3 day-1 + !--------------------------------------------------------------------------- + + ! Small phytoplankton net N assimilation + vertNNAn(k) = vertNNAn(k) + ( & + + N_assim * PhyC & ! Nitrogen uptake from DIN + - lossN * limitFacN * PhyN & ! Minus exudation (stress-induced) + ) * recipbiostep + + ! Diatom net N assimilation + vertNNAd(k) = vertNNAd(k) + ( & + + N_assim_dia * DiaC & + - lossN * limitFacN_dia * DiaN & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore net N assimilation + vertNNAc(k) = vertNNAc(k) + ( & + + N_assim_cocco * CoccoC & + - lossN * limitFacN_cocco * CoccoN & + ) * recipbiostep + + ! Phaeocystis net N assimilation + vertNNAp(k) = vertNNAp(k) + ( & + + N_assim_phaeo * PhaeoC & + - lossN * limitFacN_phaeo * PhaeoN & + ) * recipbiostep + endif + + !=========================================================================== + ! CHLOROPHYLL DEGRADATION RATES + !=========================================================================== + ! Tracks chlorophyll turnover rates (photodamage + senescence) + ! Important for understanding chlorophyll:carbon dynamics + ! + ! Variables: + ! vertChldegn(k) : Small phyto Chl degradation rate [day-1] + ! KOchl : Chlorophyll degradation rate coefficient [day-1] + ! + ! Rate Components: + ! - Base degradation: Constant senescence (~0.01-0.05 day-1) + ! - Photodamage: Light-dependent additional degradation + ! - Total: KOchl = base + photodamage component + ! + ! Ecological Significance: + ! - High rates: Photodamage stress, high light + ! - Low rates: Low light, minimal photoinhibition + ! - Affects Chl:C ratio and satellite retrievals + ! + ! Applications: + ! - Understand Chl:C variability + ! - Validate photoacclimation dynamics + ! - Interpret satellite chlorophyll trends + ! + ! Note: Changed from gross N-assimilation diagnostic (previous version) + !--------------------------------------------------------------------------- + + ! Small phytoplankton Chl degradation + vertChldegn(k) = vertChldegn(k) + ( & + + KOchl & ! Degradation rate [day-1] + ) * recipbiostep + + ! Diatom Chl degradation + vertChldegd(k) = vertChldegd(k) + ( & + + KOchl_dia & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore Chl degradation + vertChldegc(k) = vertChldegc(k) + ( & + + KOchl_cocco & + ) * recipbiostep + + ! Phaeocystis Chl degradation + vertChldegp(k) = vertChldegp(k) + ( & + + KOchl_phaeo & + ) * recipbiostep + endif + + !=========================================================================== + ! ZOOPLANKTON RESPIRATION + !=========================================================================== + ! Tracks heterotrophic respiration (metabolic CO2 release) + ! Key component of carbon cycling and food web energetics + ! + ! Variables: + ! vertrespmeso(k) : Mesozooplankton respiration [mmolC m-3 day-1] + ! HetRespFlux : Meso respiration flux [mmolC m-3 day-1] + ! + ! Ecological Significance: + ! - Represents metabolic carbon loss + ! - Typically 20-40% of ingested carbon + ! - Temperature-dependent (Q10 ≈ 2-3) + ! - Increases with activity level + ! + ! Validation: + ! - Incubation experiments (O2 consumption) + ! - ETS (electron transport system) measurements + ! - Typical range: 0.01-1 mmolC m-3 day-1 + !--------------------------------------------------------------------------- + + ! Mesozooplankton respiration + vertrespmeso(k) = vertrespmeso(k) + ( & + + HetRespFlux & ! Carbon respiration flux + ) * recipbiostep + + if (enable_3zoo2det) then + ! Macrozooplankton (krill) respiration + vertrespmacro(k) = vertrespmacro(k) + ( & + + Zoo2RespFlux & + ) * recipbiostep + + ! Microzooplankton respiration + vertrespmicro(k) = vertrespmicro(k) + ( & + + MicZooRespFlux & + ) * recipbiostep + endif + + !=========================================================================== + ! CALCITE DISSOLUTION + !=========================================================================== + ! Tracks calcium carbonate dissolution in water column + ! Critical for carbonate counter-pump and alkalinity cycling + ! + ! Variables: + ! vertcalcdiss(k) : Calcite dissolution rate [mmolC m-3 day-1] + ! calc_diss : Dissolution rate coefficient [day-1] + ! DetCalc : Detrital calcite concentration [mmolC m-3] + ! + ! Process: + ! CaCO3 -> Ca²⁺ + CO3²⁻ + ! Releases DIC (+1) and alkalinity (+2) + ! + ! Controls: + ! - Saturation state (Ω < 1 favors dissolution) + ! - Temperature (higher T -> faster kinetics) + ! - Pressure (higher P -> lower Ω) + ! + ! Depth Pattern: + ! - Surface: Minimal (supersaturated, Ω > 1) + ! - Intermediate: Moderate (Ω ≈ 1) + ! - Deep: High (undersaturated, Ω < 1) + ! + ! Applications: + ! - Ocean acidification impacts + ! - Carbon export efficiency + ! - Sediment CaCO3 preservation + !--------------------------------------------------------------------------- + + vertcalcdiss(k) = vertcalcdiss(k) + ( & + + calc_diss * DetCalc & ! Dissolution flux + ) * recipbiostep + + !=========================================================================== + ! PARTICLE AGGREGATION + !=========================================================================== + ! Tracks formation of large particles through aggregation + ! Key process for biological pump and carbon export + ! + ! Variables: + ! vertaggn(k) : Small phyto aggregation [mmolC m-3 day-1] + ! aggregationrate : Aggregation rate coefficient [day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! + ! Aggregation Mechanisms: + ! - Brownian motion (small particles) + ! - Differential settling (size-dependent) + ! - Shear aggregation (turbulence) + ! - Mucus/TEP gluing (especially diatoms) + ! + ! Enhancement Factors: + ! - High phytoplankton concentration + ! - Nutrient limitation (mucus production) + ! - Turbulence (increased collision rate) + ! - Sticky exudates (TEP, polysaccharides) + ! + ! Ecological Significance: + ! - Increases sinking velocity (export) + ! - Forms marine snow + ! - Provides food for deep-sea organisms + ! - Removes surface biomass + ! + ! Typical Rates: + ! - Low aggregation: <0.01 day-1 + ! - Moderate: 0.01-0.1 day-1 + ! - High (bloom collapse): >0.1 day-1 + !--------------------------------------------------------------------------- + + ! Small phytoplankton aggregation + vertaggn(k) = vertaggn(k) + ( & + + aggregationrate * PhyC & ! Aggregate formation + ) * recipbiostep + + ! Diatom aggregation + vertaggd(k) = vertaggd(k) + ( & + + aggregationrate * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore aggregation + vertaggc(k) = vertaggc(k) + ( & + + aggregationrate * CoccoC & + ) * recipbiostep + + ! Phaeocystis aggregation + vertaggp(k) = vertaggp(k) + ( & + + aggregationrate * PhaeoC & + ) * recipbiostep + endif + + !=========================================================================== + ! DOC EXCRETION + !=========================================================================== + ! Tracks dissolved organic carbon release by phytoplankton + ! Important for microbial loop and carbon cycling + ! + ! Variables: + ! vertdocexn(k) : Small phyto DOC excretion [mmolC m-3 day-1] + ! lossC : Carbon exudation rate constant [day-1] + ! limitFacN : Nutrient limitation factor [0-1] + ! phyC : Small phytoplankton carbon [mmolC m-3] + ! + ! Exudation Mechanisms: + ! - Passive leakage (diffusion across membranes) + ! - Overflow metabolism (excess photosynthate) + ! - Stress response (nutrient limitation) + ! - Viral lysis (cell breakage) + ! + ! Nutrient Stress Effect: + ! - High limitFacN (replete): Low exudation + ! - Low limitFacN (limited): High exudation + ! - C:N imbalance drives carbon overflow + ! + ! DOC Fate: + ! - Labile fraction: Rapid bacterial uptake (hours-days) + ! - Semi-labile: Slower degradation (weeks-months) + ! - Refractory: Accumulates (years-millennia) + ! + ! Ecological Role: + ! - Fuels microbial loop + ! - Carbon loss without grazing + ! - Nutrient regeneration (after remineralization) + ! + ! Typical Rates: + ! - Percent of GPP: 5-30% + ! - Higher under nutrient stress + ! - Lower for healthy, growing cells + !--------------------------------------------------------------------------- + + ! Small phytoplankton DOC excretion + vertdocexn(k) = vertdocexn(k) + ( & + + lossC * limitFacN * phyC & ! Stress-induced exudation + ) * recipbiostep + + ! Diatom DOC excretion + vertdocexd(k) = vertdocexd(k) + ( & + + lossC_d * limitFacN_dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore DOC excretion + vertdocexc(k) = vertdocexc(k) + ( & + + lossC_c * limitFacN_cocco * CoccoC & + ) * recipbiostep + + ! Phaeocystis DOC excretion + vertdocexp(k) = vertdocexp(k) + ( & + + lossC_p * limitFacN_phaeo * PhaeoC & + ) * recipbiostep + endif + + !=========================================================================== + ! CALCIFICATION + !=========================================================================== + ! Tracks calcium carbonate precipitation by phytoplankton + ! Key process for carbonate counter-pump + ! + ! Variables: + ! vertcalcif(k) : Calcification rate [mmolC m-3 day-1] + ! calcification : CaCO3 precipitation flux [mmolC m-3 day-1] + ! + ! Process: + ! Ca²⁺ + 2HCO3⁻ -> CaCO3 + CO2 + H2O + ! Consumes DIC (-1) and alkalinity (-2) + ! Releases CO2 (carbonate counter-pump) + ! + ! Organisms: + ! - Coccolithophores (calcite plates) + ! - Foraminifera (calcite shells) + ! - Pteropods (aragonite shells - not in this model) + ! + ! Environmental Controls: + ! - Temperature (warmer favors calcification) + ! - Carbonate saturation (Ω > 1 required) + ! - pH/CO2 (ocean acidification reduces rate) + ! - Nutrient availability (affects PIC:POC ratio) + ! + ! Ecological Significance: + ! - Ballast for sinking (increases export) + ! - Protection from grazers + ! - CO2 source (opposite to photosynthesis) + ! - Sensitive to ocean acidification + ! + ! Typical Rates: + ! - Surface (bloom): 0.1-2 mmolC m-3 day-1 + ! - Background: 0.001-0.05 mmolC m-3 day-1 + !--------------------------------------------------------------------------- + + vertcalcif(k) = vertcalcif(k) + ( & + + calcification & ! CaCO3 precipitation + ) * recipbiostep + + !=========================================================================== + ! PHYTOPLANKTON RESPIRATION + !=========================================================================== + ! Tracks autotrophic respiration (maintenance costs) + ! Component of community respiration, complement to GPP + ! + ! Variables: + ! vertrespn(k) : Small phyto respiration [mmolC m-3 day-1] + ! PhyRespRate : Respiration rate coefficient [day-1] + ! PhyC : Small phytoplankton carbon [mmolC m-3] + ! + ! Respiration Components: + ! - Basal metabolism: Maintenance of cellular machinery + ! - Biosynthesis: Costs of growth (protein synthesis, etc.) + ! - Active transport: Nutrient uptake against gradients + ! - Photorespiration: Oxygenase activity of Rubisco + ! + ! Temperature Dependence: + ! - Q10 ≈ 2-3 (doubles per 10degC increase) + ! - Often higher than photosynthesis Q10 + ! - Creates temperature-dependent growth efficiency + ! + ! Relationship to NPP: + ! GPP = NPP + Respiration + ! Growth efficiency = NPP/GPP = 1 - (Resp/GPP) + ! Typical: 0.6-0.8 (60-80% efficiency) + ! + ! Ecological Patterns: + ! - Increases with biomass (proportional) + ! - Higher in warm waters (temperature effect) + ! - Lower in nutrient-replete conditions (efficient growth) + ! - Higher during stress (maintenance costs) + !--------------------------------------------------------------------------- + + ! Small phytoplankton respiration + vertrespn(k) = vertrespn(k) + ( & + + PhyRespRate * PhyC & ! Maintenance respiration + ) * recipbiostep + + ! Diatom respiration + vertrespd(k) = vertrespd(k) + ( & + + PhyRespRate_dia * DiaC & + ) * recipbiostep + + if (enable_coccos) then + ! Coccolithophore respiration + vertrespc(k) = vertrespc(k) + ( & + + PhyRespRate_cocco * CoccoC & + ) * recipbiostep + + ! Phaeocystis respiration + vertrespp(k) = vertrespp(k) + ( & + + PhyRespRate_phaeo * PhaeoC & + ) * recipbiostep + endif + + endif ! Diags + + end do ! Main vertikal loop ends + + !=============================================================================== + ! BENTHIC REMINERALIZATION + !=============================================================================== + ! Simulates nutrient return from sediments to the bottom water layer through + ! remineralization of organic matter and calcite dissolution. + ! + ! This part calculates: + ! 1. Remineralization of benthic organic matter (N, C, Si) + ! 2. Dissolution of benthic calcite (CaCO3) + ! 3. Carbon isotope remineralization (13C, 14C - optional) + ! 4. Nutrient flux from sediments to bottom water + ! + ! Key Features: + ! - Single benthic layer (vertically integrated) + ! - First-order decay kinetics for remineralization + ! - Separate rates for N, C, Si, and calcite + ! - Optional MEDUSA sediment flux forcing + ! - Isotope fractionation during remineralization + ! - Conservative tracer return to water column + ! + ! Benthic Processes: + ! - Aerobic respiration: Organic matter -> DIN + DIC + ! - Silica dissolution: Biogenic SiO2 -> Si(OH)4 + ! - Calcite dissolution: CaCO3 -> Ca²⁺ + CO3²⁻ (affects DIC + Alk) + ! - Denitrification: In anoxic sediments (not explicitly modeled) + ! + ! Model Structure: + ! - Benthos as single well-mixed compartment + ! - Area-integrated concentrations [mmol m-2] + ! - Decay rates calibrated to observations + ! - Instant return to bottom water layer + ! + ! Ecological/Biogeochemical Significance: + ! - Closes nutrient cycles (prevents accumulation in benthos) + ! - Critical for shallow shelf ecosystems + ! - Supports benthic-pelagic coupling + ! - Affects bottom water oxygen and pH + ! - Important for coastal carbon budgets + ! + ! Limitations: + ! - No explicit burial (all material eventually remineralized) + ! - No bioturbation or bioirrigation + ! - No redox zonation in sediments + ! - Simplified single-layer representation + ! + ! References: + ! - Schourup-Kristensen et al. (2013) - REcoM benthic module + ! - MEDUSA forcing for data-constrained sediment fluxes + !=============================================================================== + + !=============================================================================== + ! REMINERALIZATION MODE SELECTION + !=============================================================================== + ! Determines whether to use MEDUSA sediment flux forcing or internal + ! benthic remineralization calculations. + ! + ! Variables: + ! use_MEDUSA : Flag to enable MEDUSA sediment forcing [logical] + ! sedflx_num : Number of MEDUSA sediment flux entries [-] + ! mype : Processor ID for parallel output [integer] + ! + ! MEDUSA Mode: + ! - Uses observationally-constrained sediment fluxes + ! - Overrides internal benthic calculations + ! - Typically used for hindcast simulations + ! - Requires external data file + ! + ! Internal Mode: + ! - Uses prognostic benthic compartment + ! - First-order decay kinetics + ! - Suitable for future projections + ! - No external data required + !------------------------------------------------------------------------------- + + if (use_MEDUSA .and. (sedflx_num /= 0)) then + + !=========================================================================== + ! MEDUSA SEDIMENT FLUX FORCING MODE + !=========================================================================== + ! Use externally prescribed sediment nutrient fluxes + ! This overrides all internal benthic calculations + !--------------------------------------------------------------------------- + + if (mype == 0) then + ! Print message only on master processor (parallel computing) + write(*, *) ' --> Sedimentary input of nutrients through MEDUSA' + endif + + ! Note: MEDUSA fluxes are applied elsewhere in the code + ! This section simply skips internal benthic calculations - end do ! Main time loop ends + else + !=========================================================================== + ! INTERNAL BENTHIC REMINERALIZATION (DEFAULT MODE) + !=========================================================================== + ! Calculates nutrient return from benthic compartment using first-order + ! decay kinetics for each element. + !--------------------------------------------------------------------------- + + !=========================================================================== + ! DISSOLVED INORGANIC NITROGEN (DIN) REMINERALIZATION + !=========================================================================== + ! Aerobic remineralization of organic nitrogen in sediments releases + ! bioavailable nitrogen (NH4+ and NO3-) back to the water column. + ! + ! Variables: + ! decayBenthos(1) : N remineralization flux [mmolN m-2 day-1] + ! decayRateBenN : Benthic N remineralization rate [day-1] + ! LocBenthos(1) : Benthic N pool (area-integrated) [mmolN m-2] + ! dt_b : REcoM time step [day] + ! + ! Equation: + ! Flux = decayRateBenN × LocBenthos(1) + ! LocBenthos(1)_new = LocBenthos(1)_old - Flux × dt_b + ! + ! Process Representation: + ! Organic N (proteins, amino acids, etc.) -> NH4+ -> NO3- + ! First-order decay: rate proportional to benthic N pool + ! + ! Typical Values: + ! decayRateBenN ~ 0.01-0.1 day-1 (10-100 day turnover) + ! Higher rates in warm, oxygenated sediments + !--------------------------------------------------------------------------- + + ! Calculate N remineralization flux [mmolN m-2 day-1] + call update_benthos_decay(decayRateBenN, 1) + + !=========================================================================== + ! DISSOLVED INORGANIC CARBON (DIC) REMINERALIZATION + !=========================================================================== + ! Aerobic respiration of organic carbon releases CO2 to bottom water. + ! Affects carbonate system (pH, pCO2, saturation state). + ! + ! Variables: + ! decayBenthos(2) : C remineralization flux [mmolC m-2 day-1] + ! decayRateBenC : Benthic C remineralization rate [day-1] + ! LocBenthos(2) : Benthic C pool (area-integrated) [mmolC m-2] + ! + ! Process Representation: + ! Organic C (carbohydrates, lipids, etc.) + O2 -> CO2 + H2O + ! Releases DIC and consumes O2 (not explicitly tracked) + ! + ! Stoichiometry: + ! C:N remineralization ratio typically near Redfield (6.6:1) + ! Can vary with organic matter source and degradation state + ! + ! Typical Values: + ! decayRateBenC ~ 0.01-0.1 day-1 + ! May differ from N rate due to preferential degradation + !--------------------------------------------------------------------------- + + ! Calculate C remineralization flux [mmolC m-2 day-1] + call update_benthos_decay(decayRateBenC, 2) + + !=========================================================================== + ! SILICATE (Si) DISSOLUTION + !=========================================================================== + ! Dissolution of biogenic silica (diatom frustules) releases Si(OH)4. + ! Temperature-dependent process (faster in warm water). + ! + ! Variables: + ! decayBenthos(3) : Si dissolution flux [mmolSi m-2 day-1] + ! decayRateBenSi : Benthic Si dissolution rate [day-1] + ! LocBenthos(3) : Benthic Si pool (area-integrated) [mmolSi m-2] + ! + ! Process Representation: + ! Biogenic SiO2 (opal) + H2O -> Si(OH)4 (silicic acid) + ! Thermodynamically driven dissolution (opal undersaturated in seawater) + ! + ! Typical Values: + ! decayRateBenSi ~ 0.001-0.01 day-1 (100-1000 day turnover) + ! Slower than organic matter (opal is recalcitrant) + ! Temperature-dependent (see reminSiT calculation earlier) + ! + ! Ecological Significance: + ! - Returns Si to support diatom production + ! - Critical in Si-limited regions + ! - Permanent burial in deep sediments affects long-term Si cycle + !--------------------------------------------------------------------------- + + ! Calculate Si dissolution flux [mmolSi m-2 day-1] + call update_benthos_decay(decayRateBenSi, 3) + + !=========================================================================== + ! CALCITE (CaCO3) DISSOLUTION + !=========================================================================== + ! Dissolution of calcium carbonate affects both DIC and alkalinity. + ! Rate depends on saturation state (calculated in deepest water layer). + ! + ! Variables: + ! decayBenthos(4) : Calcite dissolution flux [mmolC m-2 day-1] + ! calc_diss_ben : Benthic calcite dissolution rate [day-1] + ! LocBenthos(4) : Benthic calcite pool [mmolC m-2] + ! + ! Process Representation: + ! CaCO3 + CO2 + H2O ⇌ Ca²⁺ + 2HCO3- + ! Increases DIC (+1) and alkalinity (+2) + ! + ! Rate Determination: + ! calc_diss_ben taken from deepest water layer + ! Uses either saturation-state or depth-dependent formulation + ! (see calcite dissolution module earlier in code) + ! + ! Carbonate Chemistry Effect: + ! - Raises pH (consumes CO2) + ! - Increases carbonate saturation + ! - Buffers ocean acidification locally + ! + ! Note: Changed from calc_diss to calc_diss_ben to allow independent + ! control when using OmegaC_diss switch + !--------------------------------------------------------------------------- + + ! Calculate calcite dissolution flux [mmolC m-2 day-1] + call update_benthos_decay(calc_diss_ben, 4) + + if (ciso) then + + !======================================================================= + ! CARBON ISOTOPE REMINERALIZATION (OPTIONAL) + !======================================================================= + ! Tracks 13C and 14C through benthic remineralization processes. + ! Important for paleoclimate reconstructions and carbon cycle studies. + !----------------------------------------------------------------------- + + !======================================================================= + ! Carbon-13 (13C) Remineralization + !======================================================================= + ! Organic matter remineralization with isotopic fractionation + ! + ! Variables: + ! decayBenthos(5) : 13C remineralization flux [mmol13C m-2 day-1] + ! alpha_dcal_13 : 13C fractionation factor for remineralization [-] + ! LocBenthos(5) : Benthic 13C pool [mmol13C m-2] + ! + ! Note: Assumes same decay rate as total carbon (decayRateBenC) + ! Fractionation factor typically near 1.0 (minimal fractionation) + !----------------------------------------------------------------------- + + ! Calculate 13C remineralization flux + ! Ignores isotopic fractionation during remineralization (alpha ≈ 1) + call update_benthos_decay(alpha_dcal_13 * decayRateBenC, 5) + + !======================================================================= + ! Carbon-13 Calcite Dissolution + !======================================================================= + ! Dissolution of 13C-containing calcite + ! + ! Variables: + ! decayBenthos(6) : 13C calcite dissolution flux [mmol13C m-2 day-1] + ! calc_diss_13 : 13C calcite dissolution rate [day-1] + ! LocBenthos(6) : Benthic 13C-calcite pool [mmol13C m-2] + !----------------------------------------------------------------------- + + ! Calculate 13C calcite dissolution flux + call update_benthos_decay(calc_diss_13, 6) + + if (ciso_14) then + + if (ciso_organic_14) then + + !=============================================================== + ! Carbon-14 (14C) Remineralization + !=============================================================== + ! Radiocarbon remineralization for age dating and residence times + ! + ! Variables: + ! decayBenthos(7) : 14C remineralization flux [mmol14C m-2 day-1] + ! alpha_dcal_14 : 14C fractionation factor [-] + ! LocBenthos(7) : Benthic 14C pool [mmol14C m-2] + ! + ! Note: 14C also subject to radioactive decay (half-life ~5730 years) + ! This is typically handled separately in full carbon cycle models + !--------------------------------------------------------------- + + ! Calculate 14C remineralization flux + ! Ignores isotopic fractionation during remineralization + call update_benthos_decay(alpha_dcal_14 * decayRateBenC, 7) + + !=============================================================== + ! 3.4 Carbon-14 Calcite Dissolution + !=============================================================== + ! Dissolution of 14C-containing calcite + ! + ! Variables: + ! decayBenthos(8) : 14C calcite dissolution flux [mmol14C m-2 day-1] + ! calc_diss_14 : 14C calcite dissolution rate [day-1] + ! LocBenthos(8) : Benthic 14C-calcite pool [mmol14C m-2] + !--------------------------------------------------------------- + + ! Calculate 14C calcite dissolution flux + call update_benthos_decay(calc_diss_14, 8) + + else + !--------------------------------------------------------------- + ! Alternative 14C handling + !--------------------------------------------------------------- + ! When ciso_organic_14 = FALSE: + ! 14C defined as proportional to total DIC elsewhere in code + ! No separate remineralization calculation needed + ! (sms(idic_14) = sms(idic) × isotope_ratio) + !--------------------------------------------------------------- + + end if ! ciso_organic_14 + + end if ! ciso_14 + + end if ! ciso + + endif ! use_MEDUSA + + end do ! Main time loop ends + +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 @@ -2190,7 +7091,7 @@ function recom_limiter(slope,qa,qb) Real(kind=8) :: recom_limiter Real(kind=8) :: slope, qa, qb Real(kind=8) :: dq - + dq = qa - qb if (REcoM_Geider_limiter) then recom_limiter = max(min( -slope*dq, 1.d0),0.d0) @@ -2259,7 +7160,7 @@ function iron_chemistry(Fe, totalLigand, ligandStabConst) b = ligandstabConst * (Fe - totalLigand) + 1.d0 c = -totalLigand discrim = b*b - 4.d0 * a * c - + if (a .ne. 0.d0 .and. discrim .ge. 0.d0) then ligand = ( -b + sqrt(discrim) ) / (2.d0 * a) FeL = totalLigand - ligand diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 7d02fd6ab..9eeab03cc 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -704,6 +704,32 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) 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 +! ciso +CASE ('benC_13 ') + 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 + end if +CASE ('benC_14 ') + 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 + end if +CASE ('benCalc_13') + 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 + end if +CASE ('benCalc_14') + 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 + end if +!ciso CASE ('NPPn ') 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) @@ -766,6 +792,30 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) 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 + +CASE ('NPPp ') + 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 + end if + +CASE ('GPPp ') + 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 + end if + +CASE ('NNAp ') + 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 + endif + +CASE ('Chldegp ') + 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 endif #endif @@ -783,6 +833,10 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PAR', 'PAR', 'W/m2', PAR3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if +CASE ('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) +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) CASE ('respmeso ') if (use_REcoM) then @@ -824,6 +878,11 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) 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 + 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) @@ -839,6 +898,11 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) 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 ') + 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 + endif + CASE ('respn ') 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) @@ -854,6 +918,11 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) 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 + 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) @@ -868,6 +937,117 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'NPPc3D','Net primary production of coccolithophores', 'mmolC/m2/d', NPPc3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) endif + +CASE ('NPPp3D ') + 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 + endif + +CASE ('TTemp_diatoms ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'TTemp_diatoms','Temperature dependence of diatoms PS', 'per day',TTemp_diatoms(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + 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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + #endif !CASE ('otracers ') @@ -885,9 +1065,35 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) 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 + else if (tracers%data(j)%ID==1002) then ! NOTE Divide tracers%work%tra_advvert(:,:,j) by dt 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) + + ! 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) + + ! 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) + + if (.not. 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) + 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) + + ! 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) + + ! 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) + end if + endif else if (tracers%data(j)%ID==1003) then @@ -1037,10 +1243,25 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) 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) + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoN', 'PhaeoN', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW endif else if (tracers%data(j)%ID==1033) then + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoC', 'PhaeoC', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW + endif + + else if (tracers%data(j)%ID==1034) then + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'PhaeoChl', 'PhaeoChl', '[mg/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) ! NEW + endif + + else if (tracers%data(j)%ID==1035) then + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'Zoo3N', 'Zoo3N', '[mmol/m3]', tracers%data(j)%values(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + endif + + else if (tracers%data(j)%ID==1036) then 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 diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 0fe2667cb..c58c17bc2 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -297,6 +297,24 @@ subroutine ini_bio_io(tracers, partit, mesh) call bio_files%def_node_var('BenSi', 'Benthos Silicate', 'mmol/m3', Benthos(:,3), mesh, partit); call bio_files%def_node_var('BenCalc', 'Benthos Calcite', 'mmol/m3', Benthos(:,4), mesh, partit); call bio_files%def_node_var('HPlus', 'Conc. of H-plus ions in the surface water', 'mol/kg', GloHplus, mesh, partit); + if (ciso) then + call bio_files%def_node_var('BenC_13', 'Benthos Carbon-13', 'mmol/m3', Benthos(:,5), mesh, partit); + call bio_files%def_node_var('BenCalc_13', 'Benthos Calcite-13', 'mmol/m3', Benthos(:,6), mesh, partit); + if (ciso_14 .and. ciso_organic_14) then + call bio_files%def_node_var('BenC_14', 'Benthos Carbon-14', 'mmol/m3', Benthos(:,7), mesh, partit); + call bio_files%def_node_var('BenCalc_14', 'Benthos Calcite-14', 'mmol/m3', Benthos(:,8), mesh, partit); + end if ! ciso_14 + end if ! ciso + if (use_atbox) then + call bio_files%def_node_var('xCO2', 'Atm. CO2 mixing ratio', 'mol / mol', x_co2atm(:), mesh, partit); + if (ciso) then + call bio_files%def_node_var('xCO2_13', 'Atm. 13CO2 mixing ratio', 'mol / mol', x_co2atm_13(:), mesh, partit); + if (ciso_14) then + call bio_files%def_node_var('xCO2_14', 'Atm. 14CO2 mixing ratio', 'mol / mol', x_co2atm_14(:), mesh, partit); + call bio_files%def_node_var('cosmic_14', 'Cosmic 14C production', 'mol / s', cosmic_14(:), mesh, partit); + end if + end if + end if ! use_atbox end subroutine ini_bio_io #endif diff --git a/src/io_restart_file_group.F90 b/src/io_restart_file_group.F90 index 31c9263f5..27e34a5f7 100644 --- a/src/io_restart_file_group.F90 +++ b/src/io_restart_file_group.F90 @@ -17,7 +17,7 @@ module restart_file_group_module type restart_file_group private - type(restart_file_type), public :: files(112) + type(restart_file_type), public :: files(200) integer, public :: nfiles = 0 ! todo: allow dynamically allocated size without messing with shallow copied pointers contains diff --git a/src/oce_adv_tra_driver.F90 b/src/oce_adv_tra_driver.F90 index 9b9606ea8..fa0cd7c65 100644 --- a/src/oce_adv_tra_driver.F90 +++ b/src/oce_adv_tra_driver.F90 @@ -209,6 +209,27 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, #endif #endif + +! O:G - tra_diag +! LO solution +! fct_LO is zero before adv_flux_hor +! Up to now only horizontal +! contribution + + +!#if defined (__recom) + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ! Horizontal advection part for LO (FCT is .TRUE.) + tracers%work%tra_advhoriz(nz,n,tr_num) = fct_LO(nz,n) * dt/areasvol(nz,n)/hnode_new(nz,n) + end do + end do + end if +!#endif + ! compute the low order upwind vertical flux (explicit part only) ! zero the input/output flux before computation call adv_tra_ver_upw1(we, ttf, partit, mesh, adv_flux_ver, o_init_zero=.true.) @@ -277,6 +298,24 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, end if +! O:G - tra_diag +! LO solution +! fct_LO is zero before adv_flux_ver +! vertical contribution + +!#if defined (__recom) + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ! Vertical advection part for LO (FCT is .TRUE.) + tracers%work%tra_advvert (nz,n,tr_num) = (adv_flux_ver(nz, n)-adv_flux_ver(nz+1, n))*dt/areasvol(nz,n)/hnode_new(nz,n) + end do + end do + end if +!#endif + !_______________________________________________________________________ if (dynamics%use_wsplit) then !wvel/=wvel_e @@ -301,7 +340,7 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, ! do horizontal tracer advection, in case of FCT high order solution SELECT CASE(trim(tracers%data(tr_num)%tra_adv_hor)) CASE('MUSCL') - ! compute the untidiffusive horizontal flux (o_init_zero=.false.: input is the LO horizontal flux computed above) + ! compute the antidiffusive horizontal flux (o_init_zero=.false.: input is the LO horizontal flux computed above) call adv_tra_hor_muscl(vel, ttfAB, partit, mesh, opth, adv_flux_hor, edge_up_dn_grad, nboundary_lay, o_init_zero=do_zero_flux) CASE('MFCT') call adv_tra_hor_mfct(vel, ttfAB, partit, mesh, opth, adv_flux_hor, edge_up_dn_grad, o_init_zero=do_zero_flux) @@ -416,6 +455,36 @@ subroutine do_oce_adv_tra(dt, vel, w, wi, we, tr_num, dynamics, tracers, partit, end if end if !-->if ((ldiag_DVD) .and. (tr_num<=2)) then + + +! 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 ! ! diff --git a/src/oce_ale_tracer.F90 b/src/oce_ale_tracer.F90 index dd4ce9101..b1c3b8691 100644 --- a/src/oce_ale_tracer.F90 +++ b/src/oce_ale_tracer.F90 @@ -165,6 +165,8 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) type(t_mesh) , intent(in) , target :: mesh !___________________________________________________________________________ integer :: i, tr_num, node, elem, nzmax, nzmin + real(kind=WP) :: ttf_rhs_bak (mesh%nl-1, partit%myDim_nod2D+partit%eDim_elem2D) ! local variable + integer :: nz, n, nu1, nl1 !___________________________________________________________________________ ! pointer on necessary derived types real(kind=WP), dimension(:,:,:), pointer :: UV, fer_UV @@ -210,6 +212,14 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) !$OMP END PARALLEL DO end if + ! Set advective and diffusive components of total tracer fluxes to zero + ! Before tr_num loop +!#if defined (__recom) ! not necessarily should belong to recom case +! tracers%work%tra_advhoriz = 0.0 ! O:G - tra_diag +! tracers%work%tra_advvert = 0.0 + ttf_rhs_bak = 0.0 +!#endif + !___________________________________________________________________________ ! loop over all tracers !$ACC UPDATE DEVICE(dynamics%w, dynamics%w_e, dynamics%uv) !!! async(1) @@ -217,6 +227,15 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) !$ACC UPDATE DEVICE (mesh%helem, mesh%hnode, mesh%hnode_new, mesh%zbar_3d_n, mesh%z_3d_n) do tr_num=1, tracers%num_tracers +#if defined(__recom) +!YY: sinkflx needs to be reset at each time step + if(use_MEDUSA) then + SinkFlx = 0.0d0 + endif + SinkingVel1 = 0.0d0 ! OG 16.03.23 + SinkingVel2 = 0.0d0 ! OG 16.03.23 +#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' @@ -246,10 +265,20 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) if (flag_debug .and. mype==0) print *, achar(27)//'[37m'//' --> call diff_tracers_ale'//achar(27)//'[0m' call diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) + !___________________________________________________________________________ ! Radioactive decay of 14C and 39Ar if (tracers%data(tr_num)%ID == 14) tracers%data(tr_num)%values(:,:) = tracers%data(tr_num)%values(:,:) * exp(-decay14 * dt) if (tracers%data(tr_num)%ID == 39) tracers%data(tr_num)%values(:,:) = tracers%data(tr_num)%values(:,:) * exp(-decay39 * dt) - + +!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' @@ -272,6 +301,17 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) !!! !$ACC UPDATE HOST (tracers%work%fct_ttf_min, tracers%work%fct_ttf_max, tracers%work%fct_plus, tracers%work%fct_minus) & !!! !$ACC HOST (tracers%work%edge_up_dn_grad) +#if defined(__recom) + do tr_num = 1, tracers%num_tracers + if (use_MEDUSA) then + SinkFlx = SinkFlx + SinkFlx_tr(:, :, tr_num) + endif +! Benthos = Benthos + Benthos_tr(:, :, tr_num) + Sinkingvel1(:,:) = Sinkingvel1(:,:) + Sinkvel1_tr(:, :, tr_num) + Sinkingvel2(:,:) = Sinkingvel2(:,:) + Sinkvel2_tr(:, :, tr_num) + end do +#endif + !___________________________________________________________________________ ! 3D restoring for "passive" tracers !!!$OMPTODO: add OpenMP later, not needed right now! @@ -364,6 +404,8 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) type(t_mesh) , intent(in) , target :: mesh !___________________________________________________________________________ integer :: n, nzmax, nzmin + real(kind=WP) :: ttf_rhs_bak (mesh%nl-1, partit%myDim_nod2D+partit%eDim_nod2D) + integer :: nz, nu1, nl1 !___________________________________________________________________________ ! pointer on necessary derived types real(kind=WP), pointer :: del_ttf(:,:) @@ -378,21 +420,51 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) vert_sink = 0.0_WP #endif + ttf_rhs_bak = 0.0 + + if (tracers%data(tr_num)%ltra_diag) then + call backup_ttf_rhs(del_ttf, ttf_rhs_bak, ulevels_nod2D, nlevels_nod2D, myDim_nod2D, eDim_nod2D) + end if !___________________________________________________________________________ - ! do horizontal diffusiion + ! do horizontal diffusion ! write there also horizontal diffusion rhs to del_ttf which is equal the R_T^n ! in danilovs srcipt ! includes Redi diffusivity if Redi=.true. call diff_part_hor_redi(tracers, partit, mesh) ! seems to be ~9% faster than diff_part_hor - + + if (tracers%data(tr_num)%ltra_diag) then + 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)) + 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) + end if !___________________________________________________________________________ ! do vertical diffusion: explicit if (.not. tracers%data(tr_num)%i_vert_diff) call diff_ver_part_expl_ale(tr_num, tracers, partit, mesh) - + + ! OG i_vert_diff = TRUE so, we dont call explicit scheme + ! If we use this, check surface forcing for recom variables (They are not updated) + if ((.not. tracers%data(tr_num)%i_vert_diff) .and. tracers%data(tr_num)%ltra_diag) then + 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)) + 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) + 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)) + end if + ! if (recom_debug .and. mype==0) print *, tracers%data(tr_num)%ID #if defined(__recom) @@ -479,7 +551,32 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) !___________________________________________________________________________ if (tracers%data(tr_num)%i_vert_diff) then ! do vertical diffusion: implicite + + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + ttf_rhs_bak(nz,n) = tracers%data(tr_num)%values(nz,n) + end do + end do + end if + + ! (w/out Redi) call diff_ver_part_impl_ale(tr_num, dynamics, tracers, ice, partit, mesh) + + ! vertical diffusion: implicit + if (tracers%data(tr_num)%ltra_diag) then + do n=1, myDim_nod2D+eDim_nod2D + nu1 = ulevels_nod2D(n) + nl1 = nlevels_nod2D(n) + do nz = nu1, nl1-1 + tracers%work%tra_diff_part_ver_impl(nz,n,tr_num) = tracers%data(tr_num)%values(nz,n) - ttf_rhs_bak(nz,n) + !if (mype==0) print *, tra_diff_part_ver_impl(:,:,tr_num) + end do + end do + end if + end if !We DO not set del_ttf to zero because it will not be used in this timestep anymore @@ -487,7 +584,49 @@ subroutine diff_tracers_ale(tr_num, dynamics, tracers, ice, partit, mesh) 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 ! ! @@ -1482,6 +1621,10 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit, mesh, sst, sss, aice) #if defined (__recom) use recoM_declarations use recom_glovar + use recom_config +#endif +#if defined (__ciso) + use recom_ciso #endif use mod_transit use g_clock @@ -1609,16 +1752,35 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit, mesh, sst, sss, aice) !--- Done with boundary conditions for transient tracers. #if defined(__recom) CASE (1001) ! DIN + if (use_MEDUSA .and. add_loopback) then ! OG: add is_MEDUSA_loopback flag is_MEDUSA_loopback flag * lb_flux(n,1) + bc_surface= dt*(AtmNInput(n) + RiverDIN2D(n) * is_riverinput & + + ErosionTON2D(n) * is_erosioninput + lb_flux(n,1)) + else bc_surface= dt*(AtmNInput(n) + RiverDIN2D(n) * is_riverinput & + ErosionTON2D(n) * is_erosioninput) + end if + CASE (1002) ! DIC + if (use_MEDUSA .and. add_loopback) then + bc_surface= dt*(GloCO2flux_seaicemask(n) & + + RiverDIC2D(n) * is_riverinput & + + ErosionTOC2D(n) * is_erosioninput & + + lb_flux(n,2) + lb_flux(n,5)) + else bc_surface= dt*(GloCO2flux_seaicemask(n) & + RiverDIC2D(n) * is_riverinput & + 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) - !bc_surface=0.0_WP + end if CASE (1004:1010) bc_surface=0.0_WP CASE (1011) ! DON @@ -1628,16 +1790,58 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit, mesh, sst, sss, aice) CASE (1013:1017) bc_surface=0.0_WP CASE (1018) ! DSi - bc_surface=dt*(RiverDSi2D(n) * is_riverinput + ErosionTSi2D(n) * is_erosioninput) + 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 bc_surface=0.0_WP CASE (1022) ! OXY bc_surface= dt*GloO2flux_seaicemask(n) ! bc_surface=0.0_WP - CASE (1023:1035) + CASE (1023:1036) bc_surface=0.0_WP ! OG added bc for recom fields + CASE (1302) ! Before (1037) ! DIC_13 + +#if defined (__ciso) + if (ciso) then + if (use_MEDUSA .and. add_loopback) then + bc_surface= dt*(GloCO2flux_seaicemask_13(n) & + + lb_flux(n,6) + lb_flux(n,7)) + else + bc_surface= dt*(GloCO2flux_seaicemask_13(n)) + end if + else + bc_surface=0.0_WP + end if +#endif + CASE (1305:1321) + bc_surface=0.0_WP ! organic 13C + CASE (1402) ! Before (1034) ! DIC_14 +#if defined (__ciso) + if (ciso .and. ciso_14) then + if (use_MEDUSA .and. add_loopback .and. ciso_organic_14) then + bc_surface= dt*(GloCO2flux_seaicemask_14(n) & + + lb_flux(n,8) + lb_flux(n,9)) + else + bc_surface= dt*GloCO2flux_seaicemask_14(n) + end if + else + bc_surface=0.0_WP + end if +#endif + CASE (1405:1421) + bc_surface=0.0_WP ! organic 14C #endif CASE (101) ! apply boundary conditions to tracer ID=101 bc_surface= dt*(prec_rain(n))! - real_salt_flux(n)*is_nonlinfs) diff --git a/src/oce_setup_step.F90 b/src/oce_setup_step.F90 index 68c2b4f2e..984ab9764 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -315,12 +315,12 @@ SUBROUTINE tracer_init(tracers, partit, mesh) !___________________________________________________________________________ ! define tracer namelist parameter integer :: num_tracers - logical :: i_vert_diff, smooth_bh_tra + logical :: i_vert_diff, smooth_bh_tra , ltra_diag real(kind=WP) :: gamma0_tra, gamma1_tra, gamma2_tra integer :: AB_order = 2 namelist /tracer_listsize/ num_tracers namelist /tracer_list / nml_tracer_list - namelist /tracer_general / smooth_bh_tra, gamma0_tra, gamma1_tra, gamma2_tra, i_vert_diff, AB_order + namelist /tracer_general / smooth_bh_tra, gamma0_tra, gamma1_tra, gamma2_tra, i_vert_diff, AB_order, ltra_diag !___________________________________________________________________________ ! pointer on necessary derived types #include "associate_part_def.h" @@ -478,6 +478,7 @@ SUBROUTINE tracer_init(tracers, partit, mesh) tracers%data(n)%valuesAB = 0. tracers%data(n)%valuesold = 0. tracers%data(n)%i_vert_diff = i_vert_diff + tracers%data(n)%ltra_diag = ltra_diag end do allocate(tracers%work%del_ttf(nl-1,node_size)) allocate(tracers%work%del_ttf_advhoriz(nl-1,node_size),tracers%work%del_ttf_advvert(nl-1,node_size)) @@ -490,6 +491,20 @@ SUBROUTINE tracer_init(tracers, partit, mesh) tracers%work%dvd_trflx_hor = 0.0_WP tracers%work%dvd_trflx_ver = 0.0_WP end if + if (ltra_diag) then + allocate(tracers%work%tra_advhoriz(nl-1,node_size,num_tracers),tracers%work%tra_advvert(nl-1,node_size,num_tracers)) + tracers%work%tra_advhoriz = 0.0_WP + tracers%work%tra_advvert = 0.0_WP + allocate(tracers%work%tra_diff_part_hor_redi(nl-1,node_size,num_tracers),tracers%work%tra_diff_part_ver_expl(nl-1,node_size,num_tracers)) + allocate(tracers%work%tra_diff_part_ver_redi_expl(nl-1,node_size,num_tracers),tracers%work%tra_diff_part_ver_impl(nl-1,node_size,num_tracers)) + allocate(tracers%work%tra_recom_sms(nl-1,node_size,num_tracers)) + 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 + + end if END SUBROUTINE tracer_init ! ! @@ -1194,7 +1209,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write (id_string, "(I4)") id write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if - CASE (1023:1033) + CASE (1023:1036) tracers%data(i)%values(:,:)=0.0_WP if (mype==0) then write (i_string, "(I4)") i diff --git a/test/input/recom/DustClimMonthlyAlbani_pimesh.nc b/test/input/recom/DustClimMonthlyAlbani_pimesh.nc new file mode 100644 index 000000000..01d17125e Binary files /dev/null and b/test/input/recom/DustClimMonthlyAlbani_pimesh.nc differ diff --git a/test/input/recom/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc b/test/input/recom/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc new file mode 100644 index 000000000..f2ede08cb Binary files /dev/null and b/test/input/recom/GLODAPv2.2016b.PI_TCO2_fesom2_mmol_fix_z_Fillvalue.nc differ diff --git a/test/input/recom/MonthlyAtmCO2_gcb2024.nc b/test/input/recom/MonthlyAtmCO2_gcb2024.nc new file mode 100644 index 000000000..1874cf8f3 Binary files /dev/null and b/test/input/recom/MonthlyAtmCO2_gcb2024.nc differ diff --git a/test/input/recom/din5deg.nc b/test/input/recom/din5deg.nc new file mode 100644 index 000000000..e3a0e7db5 Binary files /dev/null and b/test/input/recom/din5deg.nc differ diff --git a/test/input/recom/fe5deg.nc b/test/input/recom/fe5deg.nc new file mode 100644 index 000000000..76d5c8e4b Binary files /dev/null and b/test/input/recom/fe5deg.nc differ diff --git a/test/input/recom/namelist.recom.working b/test/input/recom/namelist.recom.working new file mode 100755 index 000000000..9f08fecce --- /dev/null +++ b/test/input/recom/namelist.recom.working @@ -0,0 +1,361 @@ +! This is the namelist file for recom + +&nam_rsbc +fe_data_source ='Albani' +nm_fe_data_file ='DustClimMonthlyAlbani_pimesh.nc' +nm_aen_data_file ='' +nm_river_data_file ='' +nm_erosion_data_file ='' +nm_co2_data_file ='MonthlyAtmCO2_gcb2024.nc' +/ + +&parecomsetup +enable_3zoo2det = .true. +enable_coccos = .false. +/ + +&pavariables +use_REcoM =.true. +REcoM_restart =.false. + +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. +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 = './' +restore_alkalinity = .true. +useRivers = .false. +useRivFe = .false. ! When set to true, riverine Fe source is activated +useErosion = .false. +NitrogenSS = .false. ! When set to true, external sources and sinks of nitrogen are activated (Riverine, aeolian and denitrification) +useAeolianN = .false. ! When set to true, aeolian nitrogen deposition is activated +firstyearoffesomcycle = 1958 ! The first year of the actual physical forcing (e.g. JRA-55) used +lastyearoffesomcycle = 2024 ! Last year of the actual physical forcing used +numofCO2cycles = 1 ! Number of cycles of the forcing planned +currentCO2cycle = 1 ! Which CO2 cycle we are currently running +DIC_PI = .true. +Nmocsy = 1 ! Length of the vector that is passed to mocsy (always one for recom) +recom_debug =.false. +ciso =.false. ! Main switch to enable/disable carbon isotopes (13|14C) +benthos_num = 4 ! number of benthic BGC tracers -> 8 if (ciso == .true.) otherwise -> 4 +use_MEDUSA = .false. ! Main switch for the sediment model MEDUSA +sedflx_num = 0 ! if 0: no file from MEDUSA is read but default sediment +bottflx_num = 4 ! if ciso&ciso_14: =8; if .not.ciso_14: =6; no ciso: =4 +use_atbox = .false. +add_loopback = .false. ! add loopback fluxes through rivers to the surface +lb_tscale = 1.0 ! /year: fraction of loopback fluxes yearly added to the surface +/ + +&pasinking +Vdet_a = 0.0288 ! [1/day] +Vcalc = 0.0144 ! [1/day] +/ + +&painitialization_N +cPhyN = 0.2d0 +cHetN = 0.2d0 +cZoo2N = 0.2d0 +/ + +&paArrhenius +recom_Tref = 288.15d0 ! [K] +C2K = 273.15d0 ! Conversion from degrees C to K +Ae = 4500.d0 ! [K] Slope of the linear part of the Arrhenius function +reminSi = 0.02d0 +k_o2_remin = 15.d0 ! O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 +/ + +&palimiter_function +NMinSlope = 50.d0 +SiMinSlope = 1000.d0 +NCmin = 0.04d0 +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 +/ + +&palight_calculations +k_w = 0.04d0 ! [1/m] Light attenuation coefficient +a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific attenuation coefficients +/ + +&paphotosynthesis +alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] +alfa_d = 0.19d0 ! An initial slope of the P-I curve +alfa_c = 0.10d0 +parFrac = 0.43d0 +/ + +&paassimilation +V_cm_fact = 0.7d0 ! scaling factor for temperature dependent maximum of C-specific N-uptake +V_cm_fact_d = 0.7d0 +V_cm_fact_c = 0.7d0 +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 +/ + +&pairon_chem +totalligand = 1.d0 ! [mumol/m3] order 1. Total free ligand +ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron stability constant +/ + +&pazooplankton +graz_max = 0.31d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilonr = 0.09d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss +res_het = 0.028d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +Redfield = 6.625 ! [mmol C/mmol N] Redfield ratio of C:N = 106:16 +loss_het = 0.04d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) +pzDia = 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. +/ + +&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 +/ + +&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 +/ + +&pagrazingdetritus +pzDet = 0.5d0 ! Maximum small detritus prefence by first zooplankton +sDetNsq = 0.d0 +pzDetZ2 = 0.5d0 ! Maximum large detritus preference by first zooplankton +sDetZ2Nsq = 0.d0 +pzDet2 = 0.5d0 ! Maximum small detritus prefence by second zooplankton +sDetNsq2 = 0.d0 +pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton +sDetZ2Nsq2 = 0.d0 +/ + +&paaggregation +agg_PD = 0.165d0 ! [m3/(mmol N * day)] Maximum aggregation loss parameter for DetN +agg_PP = 0.015d0 ! [m3/(mmol N * day)] Maximum aggregation loss parameter for PhyN and DiaN (plankton) +/ + +&padin_rho_N +rho_N = 0.11d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) (Remineralization of DON) +/ + +&padic_rho_C1 +rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradation of extracellular organic C (EOC) +/ + +&paphytoplankton_N +lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds +lossN_d = 0.05d0 +lossN_c = 0.05d0 +/ + +&paphytoplankton_C +lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon +lossC_d = 0.10d0 +lossC_c = 0.10d0 +/ + +&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 +/ + +&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 +/ + +&padetritus_C +reminC = 0.15d0 ! [1/day] Temperature dependent remineralisation rate of detritus +rho_c2 = 0.1d0 ! [1/day] Temperature dependent C degradation of TEP-C +/ + +&paheterotrophs +lossN_z = 0.1d0 +lossC_z = 0.1d0 +/ + +&paseczooloss +lossN_z2 = 0.02d0 +lossC_z2 = 0.02d0 +/ + +&pathirdzooloss +lossN_z3 = 0.05d0 +lossC_z3 = 0.05d0 +/ + +&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] +/ + +&pairon +Fe2N = 0.033d0 ! Fe2C * 6.625 +Fe2N_benthos = 0.15d0 ! test, default was 0.14 Fe2C_benthos * 6.625 - will have to be tuned. [umol/m2/day] +kScavFe = 0.07d0 +dust_sol = 0.02d0 ! Dissolution of Dust for bioavaliable +RiverFeConc = 100 +/ + +&pacalc +calc_prod_ratio = 0.02 +calc_diss_guts = 0.0d0 ! 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 +/ + +&pabenthos_decay_rate +decayRateBenN = 0.005d0 +decayRateBenC = 0.005d0 +decayRateBenSi = 0.005d0 +q_NC_Denit = 0.86d0 ! N:C quota of the denitrification process +/ + +&paco2_flux_param +permil = 0.000000976 ! 1.e-3/1024.5d0 ! Converting DIC from [mmol/m3] to [mol/kg] +permeg = 1.e-6 ! [atm/uatm] Changes units from uatm to atm +!X1 = exp(-5.d0*log(10.d0)) ! Lowest ph-value = 7.7 (phlo) +!X2 = exp(-9.d0*log(10.d0)) ! Highest ph-value = 9.5 (phhi) +Xacc = 1.e-12 ! Accuracy for ph-iteration (phacc) +CO2_for_spinup = 278.d0 ! [uatm] Atmospheric partial pressure of CO2 +/ + +&paalkalinity_restoring +surf_relax_Alk = 3.2e-07 !10.d0/31536000.d0 +/ + +&paballasting +rho_POC = 1033.d0 ! kg m-3; density of POC (see Table 1 in Cram et al., 2018) +rho_PON = 1033.d0 ! kg m-3; density of PON (see Table 1 in Cram et al., 2018) +rho_CaCO3 = 2830.d0 ! kg m-3; density of CaCO3 (see Table 1 in Cram et al., 2018) +rho_opal = 2090.d0 ! kg m-3; density of Opal (see Table 1 in Cram et al., 2018) +rho_ref_part = 1230.d0 ! kg m-3; reference particle density (see Cram et al., 2018) +rho_ref_water = 1027.d0 ! kg m-3; reference seawater density (see Cram et al., 2018) +visc_ref_water = 0.00158d0 ! kg m-1 s-1; reference seawater viscosity, at Temp=4 degC (see Cram et al., 2018) +w_ref1 = 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) +/ + +&paciso +ciso_init = .false. ! initial fractionation of bulk organic matter +ciso_14 = .false. ! include inorganic radiocarbon +ciso_organic_14 = .false. ! include organic radiocarbon +lambda_14 = 3.8561e-12 ! corresponding to 1 year = 365.00 days +delta_CO2_13 = -6.61 ! atmospheric d13C (permil), global-mean value +big_delta_CO2_14(1) = 0. ! atmospheric D14C (permil), northern hemisphere polewards of 30°N +big_delta_CO2_14(2) = 0. ! atmospheric D14C (permil), (sub) tropical zone 30°N - 30°S +big_delta_CO2_14(3) = 0. ! atmospheric D14C (permil), southern hemisphere polewards of 30°S +atbox_spinup = .false. +cosmic_14_init = 2.0 +/ + + diff --git a/test/input/recom/namelist.tra.working b/test/input/recom/namelist.tra.working new file mode 100644 index 000000000..ae1a4515d --- /dev/null +++ b/test/input/recom/namelist.tra.working @@ -0,0 +1,90 @@ +&tracer_listsize +num_tracers=100 !number of tracers to allocate. shallbe large or equal to the number of streams in &nml_list +/ + +&tracer_list +nml_tracer_list = +1 , 'MFCT', 'QR4C', 'FCT ', 1., 1., +2 , 'MFCT', 'QR4C', 'FCT ', 1., 1., +1001, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1002, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1003, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1004, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1005, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1006, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1007, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1008, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1009, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1010, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1011, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1012, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1013, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1014, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1015, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1016, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1017, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1018, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1019, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1020, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1021, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1022, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1023, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1024, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1025, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1026, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1027, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1028, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1029, 'MFCT', 'QR4C', 'FCT ', 1., 1., +1030, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1031, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1032, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!1033, 'MFCT', 'QR4C', 'FCT ', 1., 1., +!101, 'UPW1', 'UPW1', 'NON ', 0., 0. +/ + +&tracer_init3d ! initial conditions for tracers +n_ic3d = 8 ! number of tracers to initialize +idlist = 1019, 1022, 1018, 1003, 1002, 1001, 2, 1 ! their IDs (0 is temperature, 1 is salinity, etc.). The reading order is defined here! +filelist = 'fe5deg.nc', 'oxy5deg.nc', 'si5deg.nc', 'talk5deg.nc', 'tco2_5deg.nc', 'din5deg.nc', 'woa18_netcdf_5deg.nc', 'woa18_netcdf_5deg.nc' +varlist = 'Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp' ! variables to read from specified files +t_insitu = .true. ! if T is insitu it will be converted to potential after reading it +/ + +&tracer_init2d ! initial conditions for 2D tracers (sea ice) +n_ic2d = 3 ! number of tracers to initialize +idlist = 1, 2, 3 ! their IDs (0 is a_ice, 1 is m_ice, 3 m_snow). The reading order is defined here! +filelist = 'fe5deg.nc', 'oxy5deg.nc', 'si5deg.nc', 'talk5deg.nc', 'tco2_5deg.nc', 'din5deg.nc', 'woa18_netcdf_5deg.nc', 'woa18_netcdf_5deg.nc' +varlist = 'a_ice', 'm_ice', 'm_snow' ! variables to read from specified files +ini_ice_from_file=.false. +/ + +&tracer_general +! bharmonic diffusion for tracers. We recommend to use this option in very high resolution runs (Redi is generally off there). +smooth_bh_tra =.false. ! use biharmonic diffusion (filter implementation) for tracers +gamma0_tra = 0.0005 ! gammaX_tra are analogous to those in the dynamical part +gamma1_tra = 0.0125 +gamma2_tra = 0. +i_vert_diff =.true. +/ + +&tracer_phys +use_momix = .true. ! switch on/off !Monin-Obukhov -> TB04 mixing +momix_lat = -50.0 ! latitidinal treshhold for TB04, =90 --> global +momix_kv = 0.01 ! PP/KPP, mixing coefficient within MO length +use_instabmix = .true. ! enhance convection in case of instable stratification +instabmix_kv = 0.1 +use_windmix = .false. ! enhance mixing trough wind only for PP mixing (for stability) +windmix_kv = 1.e-3 +windmix_nl = 2 +diff_sh_limit=5.0e-3 ! for KPP, max diff due to shear instability +Kv0_const=.true. +double_diffusion=.false. ! for KPP,dd switch +K_ver=1.0e-5 +K_hor=3000. +surf_relax_T=0.0 +surf_relax_S=1.929e-06 ! 50m/300days 6.43e-07! m/s 10./(180.*86400.) +balance_salt_water =.true. ! balance virtual-salt or freshwater flux or not +clim_relax=0.0 ! 1/s, geometrical information has to be supplied +ref_sss_local=.true. +ref_sss=34. +/ diff --git a/test/input/recom/oxy5deg.nc b/test/input/recom/oxy5deg.nc new file mode 100644 index 000000000..4a1d8c992 Binary files /dev/null and b/test/input/recom/oxy5deg.nc differ diff --git a/test/input/recom/si5deg.nc b/test/input/recom/si5deg.nc new file mode 100644 index 000000000..ebe088dbd Binary files /dev/null and b/test/input/recom/si5deg.nc differ diff --git a/test/input/recom/talk5deg.nc b/test/input/recom/talk5deg.nc new file mode 100644 index 000000000..c62089056 Binary files /dev/null and b/test/input/recom/talk5deg.nc differ diff --git a/test/input/recom/tco2_5deg.nc b/test/input/recom/tco2_5deg.nc new file mode 100644 index 000000000..7fdad5948 Binary files /dev/null and b/test/input/recom/tco2_5deg.nc differ diff --git a/test/input/recom/woa18_netcdf_5deg.nc b/test/input/recom/woa18_netcdf_5deg.nc new file mode 100644 index 000000000..2215b266a Binary files /dev/null and b/test/input/recom/woa18_netcdf_5deg.nc differ diff --git a/work/run_recom_ci.sh b/work/run_recom_ci.sh new file mode 100755 index 000000000..bd18a5cd5 --- /dev/null +++ b/work/run_recom_ci.sh @@ -0,0 +1,73 @@ +#!/bin/bash +#SBATCH --job-name=recom_ci +#SBATCH -p compute +#SBATCH --ntasks=2 +#SBATCH --time=00:30:00 +#SBATCH -o recom_ci_%j.out +#SBATCH -e recom_ci_%j.err +#SBATCH -A ba0989 + +set -e + +REPO_DIR="/work/ab0246/a270092/model_codes/fesom-2.7" +SIF="${REPO_DIR}/fesom2-ci.sif" + +module load singularity + +# The SIF must be pre-pulled on the login node (SLURM compute nodes +# have a read-only TMPDIR that breaks singularity pull). To pull: +# module load singularity +# singularity pull "$SIF" docker://ghcr.io/fesom/fesom2_docker:fesom2_test_refactoring-master +if [ ! -f "$SIF" ]; then + echo "ERROR: $SIF not found. Pull it on the login node first (see script comments)." + exit 1 +fi + +echo "==> Running RECOM CI test inside container..." +singularity exec --bind "${REPO_DIR}:/fesom/fesom2" "$SIF" bash -l -c ' +set -e +cd /fesom/fesom2 + +echo "==> Cleaning stale build cache..." +rm -rf build + +echo "==> Compiling with REcoM..." +./configure.sh ubuntu -DRECOM_COUPLED=ON + +echo "==> Creating test run directory..." +mkrun recom test_pi_recom -m docker + +echo "==> Setting up REcoM namelists..." +cp config/bin_2p3z2d/namelist.recom work_recom/ +cp config/bin_2p3z2d/namelist.tra work_recom/ + +cd work_recom +sed -i "/^&nam_rsbc/,/^\//d" namelist.recom +sed -i "s|REcoM_restart.*=.*\.true\.|REcoM_restart =.false.|" namelist.recom +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 +sed -i "s|woa13_all_i00_01_fesom2\.nc|si5deg.nc|" namelist.tra +sed -i "s|GLODAPv2\.2016b\.TAlk_fesom2_mmol_fix_z_Fillvalue\.nc|talk5deg.nc|" namelist.tra +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 +sed -i "s|l_mslp *= *\.false\.|l_mslp=.true.|" namelist.forcing +cd .. + +echo "==> Copying input data..." +cp test/input/recom/*.nc work_recom/ +(cd test/input/recom && ln -sf DustClimMonthlyAlbani_pimesh.nc DustClimMonthlyAlbani.nc) +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/ + +echo "==> Running FESOM2 + REcoM (32 timesteps, 1 day)..." +cd work_recom +chmod +x job_docker_new +./job_docker_new + +echo "==> Validating results..." +fcheck . + +echo "==> RECOM CI test completed successfully!" +'