From a3dfd9f03339c37eef9b1038d41eb553f9680e05 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 24 Jan 2025 09:47:47 +0100 Subject: [PATCH 01/68] changes in src for tracer parallelisation --- src/CMakeLists.txt | 2 +- src/MOD_PARTIT.F90 | 13 ++ src/associate_part_ass.h | 7 + src/associate_part_def.h | 7 + src/cpl_driver.F90 | 70 ++++++- src/fesom_module.F90 | 344 +++++++++++++++++++++++++++++++- src/gen_forcing_couple.F90 | 38 +++- src/gen_ic3d.F90 | 7 +- src/gen_model_setup.F90 | 28 +++ src/gen_modules_config.F90 | 8 +- src/gen_surface_forcing.F90 | 166 +++++++++++++-- src/int_recom/recom_sinking.F90 | 1 + src/io_restart.F90 | 120 ++++++++++- src/oce_ale.F90 | 19 +- src/oce_ale_tracer.F90 | 197 +++++++++++++++++- src/oce_modules.F90 | 9 + src/oce_setup_step.F90 | 109 +++++++++- 17 files changed, 1106 insertions(+), 39 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54de5c3ea..f19e11403 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -237,7 +237,7 @@ if(OPENMP_REPRODUCIBLE) endif() if(${RECOM_COUPLED}) - target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __3Zoo2Det __coccos)# __usetp) + target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __usetp) #__3Zoo2Det __coccos) endif() if(${CISO_COUPLED}) diff --git a/src/MOD_PARTIT.F90 b/src/MOD_PARTIT.F90 index 6603b8922..07cba793f 100644 --- a/src/MOD_PARTIT.F90 +++ b/src/MOD_PARTIT.F90 @@ -71,6 +71,14 @@ module MOD_PARTIT integer :: MPI_COMM_FESOM ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) integer :: MPI_COMM_WORLD ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) +#if defined(__usetp) +! kh 11.11.21 communicator for multi FESOM group loop parallelization + integer :: MPI_COMM_FESOM_WORLD + +! kh 17.11.21 communicator for multi FESOM group loop parallelization + integer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS +#endif + ! MPI Datatypes for interface exchange ! Element fields (2D; 2D integer; 3D with nl-1 or nl levels, 1 - 4 values) ! small halo and / or full halo @@ -87,6 +95,11 @@ module MOD_PARTIT integer, allocatable :: s_mpitype_nod3D(:,:,:), r_mpitype_nod3D(:,:,:) integer :: MPIERR + +#if defined(__usetp) +! kh 11.11.21 multi FESOM group loop parallelization + integer :: my_fesom_group +#endif !!! remPtr_* are constructed during the runtime and shall not be dumped!!! integer, allocatable :: remPtr_nod2D(:), remList_nod2D(:) diff --git a/src/associate_part_ass.h b/src/associate_part_ass.h index d2ee2010d..d3d5963c6 100644 --- a/src/associate_part_ass.h +++ b/src/associate_part_ass.h @@ -1,3 +1,7 @@ +#if defined(__usetp) +MPI_COMM_FESOM_WORLD => partit%MPI_COMM_FESOM_WORLD +MPI_COMM_FESOM_SAME_RANK_IN_GROUPS => partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS +#endif MPI_COMM_FESOM => partit%MPI_COMM_FESOM MPI_COMM_FESOM_IB => partit%MPI_COMM_FESOM_IB com_nod2D => partit%com_nod2D @@ -16,6 +20,9 @@ MPIERR => partit%MPIERR MPIERR_IB => partit%MPIERR_IB npes => partit%npes mype => partit%mype +#if defined(__usetp) +my_fesom_group => my_fesom_group +#endif maxPEnum => partit%maxPEnum part => partit%part diff --git a/src/associate_part_def.h b/src/associate_part_def.h index 262780a4a..05e9e32b1 100644 --- a/src/associate_part_def.h +++ b/src/associate_part_def.h @@ -1,3 +1,7 @@ +#if defined(__usetp) + integer, pointer :: MPI_COMM_FESOM_WORLD + integer, pointer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS +#endif integer, pointer :: MPI_COMM_FESOM ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) integer, pointer :: MPI_COMM_FESOM_IB ! FESOM communicator copy for icebergs LA: 2023-05-22 type(com_struct), pointer :: com_nod2D @@ -20,6 +24,9 @@ integer, pointer :: MPIERR_IB ! copy for icebergs LA: 2023-05-22 integer, pointer :: npes integer, pointer :: mype +#if defined(__usetp) + integer, pointer :: my_fesom_group +#endif integer, pointer :: maxPEnum integer, dimension(:), pointer :: part diff --git a/src/cpl_driver.F90 b/src/cpl_driver.F90 index 0c2ad2bc1..58df2a5e6 100644 --- a/src/cpl_driver.F90 +++ b/src/cpl_driver.F90 @@ -14,6 +14,9 @@ module cpl_driver ! use mod_oasis ! oasis module use g_config, only : dt, use_icebergs, lwiso +#if defined(__usetp) + use g_config, only : num_fesom_groups ! kh 03.12.21 OG 08.09.23 +#endif use o_param, only : rad USE MOD_PARTIT implicit none @@ -310,7 +313,13 @@ subroutine node_contours(my_x_corners, my_y_corners, partit, mesh) my_y_corners=my_y_corners/rad end subroutine node_contours - subroutine cpl_oasis3mct_init(partit, localCommunicator ) +! kh 02.12.21 +#if defined(__usetp) + subroutine cpl_oasis3mct_init(partit, localCommunicator, num_fesom_groups) +#else + subroutine cpl_oasis3mct_init(partit, localCommunicator) +#endif + USE MOD_PARTIT implicit none save @@ -324,6 +333,10 @@ subroutine cpl_oasis3mct_init(partit, localCommunicator ) ! integer, intent(OUT) :: localCommunicator type(t_partit), intent(inout), target :: partit +#if defined(__usetp) +! kh 02.12.21 + integer, intent(inout) :: num_fesom_groups +#endif ! ! Local declarations ! @@ -345,7 +358,12 @@ subroutine cpl_oasis3mct_init(partit, localCommunicator ) !------------------------------------------------------------------ ! 1st Initialize the OASIS3-MCT coupling system for the application !------------------------------------------------------------------ +! kh 02.12.21 +#if defined(__usetp) + CALL oasis_init_comp(comp_id, comp_name, ierror, num_program_groups = num_fesom_groups) +#else CALL oasis_init_comp(comp_id, comp_name, ierror ) +#endif IF (ierror /= 0) THEN CALL oasis_abort(comp_id, 'cpl_oasis3mct_init', 'Init_comp failed.') ENDIF @@ -356,7 +374,12 @@ subroutine cpl_oasis3mct_init(partit, localCommunicator ) CALL oasis_abort(comp_id, 'cpl_oasis3mct_init', 'comm_rank failed.') ENDIF +! kh 02.12.21 +#if defined(__usetp) + CALL oasis_get_localcomm_all_groups( localCommunicator, ierror ) +#else CALL oasis_get_localcomm( localCommunicator, ierror ) +#endif IF (ierror /= 0) THEN CALL oasis_abort(comp_id, 'cpl_oasis3mct_init', 'get_local_comm failed.') ENDIF @@ -606,6 +629,11 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) print *, 'FESOM after Barrier' endif +! kh 30.11.21 +#if defined(__usetp) + if(my_fesom_group == 0) then +#endif + if (mype .eq. localroot) then print *, 'FESOM before grid writing to oasis grid files' CALL oasis_start_grids_writing(il_flag) @@ -632,6 +660,9 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) print *, 'FESOM after terminate_grids_writing' endif !localroot +#if defined(__usetp) + end if !(my_fesom_group == 0) then +#endif DEALLOCATE(all_x_coords, all_y_coords, my_x_coords, my_y_coords, displs_from_all_pes, counts_from_all_pes) @@ -900,15 +931,52 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) endif #endif +#if defined(__usetp) +! kh 06.12.21 the coupling is in principle as it was before, i.e. the fesom processes - in group 0 - receive their data from echam + if(my_fesom_group == 0) then +#endif + call oasis_get(recv_id(ind), seconds_til_now, exfld,info) + +#if defined(__usetp) + else + +! kh 06.12.21 defensive: assignment statement "action=(info==3 ..." below is "don't care" in this case, because the actual value for action +! is received via MPI_Bcast anyway + info = 0 + + end if +#endif + t2=MPI_Wtime() ! ! FESOM's interpolation routine interpolates structured ! VarStrLoc coming from OASIS3MCT to local unstructured data_array ! and delivered back to FESOM. action=(info==3 .OR. info==10 .OR. info==11 .OR. info==12 .OR. info==13) + +#if defined(__usetp) +! kh 03.12.21 + if(num_fesom_groups > 1) then + call MPI_Bcast(action, 1, MPI_LOGICAL, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) + end if +#endif + if (action) then +#if defined(__usetp) +! kh 03.12.21 + if(my_fesom_group == 0) then +#endif data_array(1:partit%myDim_nod2d) = exfld +#if defined(__usetp) + end if + +! kh 03.12.21 + if(num_fesom_groups > 1) then + call MPI_Bcast(data_array, myDim_nod2d, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) + end if +#endif + call exchange_nod(data_array, partit) end if t3=MPI_Wtime() diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 3302f61f4..dafc13eca 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -60,6 +60,9 @@ module fesom_main_storage_module integer :: which_readr ! read which restart files (0=netcdf, 1=core dump,2=dtype) integer :: total_nsteps integer, pointer :: mype, npes, MPIerr, MPI_COMM_FESOM, MPI_COMM_WORLD, MPI_COMM_FESOM_IB +#if defined(__usetp) + integer, pointer :: my_fesom_group, MPI_COMM_FESOM_WORLD, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS +#endif real(kind=WP) :: t0, t1, t2, t3, t4, t5, t6, t7, t8, t0_ice, t1_ice, t0_frc, t1_frc real(kind=WP) :: rtime_fullice, rtime_write_restart, rtime_write_means, rtime_compute_diag, rtime_read_forcing real(kind=real32) :: rtime_setup_mesh, rtime_setup_ocean, rtime_setup_forcing @@ -116,6 +119,19 @@ subroutine fesom_init(fesom_total_nsteps) ! EO parameters logical mpi_is_initialized integer :: tr_num + +#if defined(__usetp) +! kh 11.11.21 multi FESOM group loop parallelization + integer :: npes_fesom_world + integer :: mype_fesom_world + integer :: processes_per_group + integer :: npes_check + integer :: mype_check + +! kh 26.11.21 get current value for num_fesom_groups + call read_namelist_run_config +#endif + #if !defined __ifsinterface if(command_argument_count() > 0) then call command_line_options%parse() @@ -147,8 +163,13 @@ subroutine fesom_init(fesom_total_nsteps) #endif #if defined (__oasis) - - call cpl_oasis3mct_init(f%partit,f%partit%MPI_COMM_FESOM) +! call cpl_oasis3mct_init(f%partit,f%partit%MPI_COMM_FESOM) +! kh 02.12.21 +#if defined(__usetp) + call cpl_oasis3mct_init(f%partit, f%partit%localCommunicator, num_fesom_groups) +#else + call cpl_oasis3mct_init(f%partit, f%partit%localCommunicator) +#endif #endif f%t1 = MPI_Wtime() @@ -162,6 +183,108 @@ subroutine fesom_init(fesom_total_nsteps) f%npes =>f%partit%npes +#if defined(__usetp) +! kh 26.11.21 prepare communicator splitting for multi FESOM group loop parallelization + f%my_fesom_group=>f%partit%my_fesom_group + + f%MPI_COMM_FESOM_WORLD=> f%partit%MPI_COMM_FESOM_WORLD + f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS=> f%partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS + + f%MPI_COMM_FESOM_WORLD = f%MPI_COMM_FESOM + npes_fesom_world = f%npes + mype_fesom_world = f%mype + if(mype_fesom_world == 0) then + write(*,*) 'npes_fesom_world, num_fesom_groups', npes_fesom_world, num_fesom_groups + end if + if(mod(npes_fesom_world, num_fesom_groups) /= 0) then + if(mype_fesom_world == 0) then + write(*,*) 'MPI_comm_split mismatch npes_fesom_world, num_fesom_groups', npes_fesom_world, num_fesom_groups + end if + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + + processes_per_group = npes_fesom_world / num_fesom_groups + if(mype_fesom_world == 0) then + write(*,*) 'processes_per_group', processes_per_group + end if + f%npes = processes_per_group + f%my_fesom_group = mype_fesom_world / processes_per_group + f%mype = mod(mype_fesom_world, processes_per_group) + +! kh 26.11.21 split to num_fesom_groups + call MPI_comm_split(f%MPI_COMM_FESOM_WORLD, f%my_fesom_group, 0, f%MPI_COMM_FESOM, f%MPIerr) + if (f%MPIerr /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_split(MPI_COMM_FESOM_WORLD, my_fesom_group, 0, MPI_COMM_FESOM, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + + call MPI_comm_size(f%MPI_COMM_FESOM, npes_check, f%MPIerr) + if(f%MPIerr /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_size(MPI_COMM_FESOM, npes_check, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + + call MPI_comm_rank(f%MPI_COMM_FESOM, mype_check, f%MPIerr) + if(f%MPIerr /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_rank(MPI_COMM_FESOM, mype_check, MPIERR) failed' + call par_ex(f%partit%MPI_COMM_FESOM, f%mype) + stop + end if + + if(npes_check /= f%npes) then + write(*,*) 'npes mismatch, npes, npes_check', f%npes, npes_check + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + + if(mype_check /= f%mype) then + write(*,*) 'mype mismatch, mype, mype_check', f%mype, mype_check + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + +! kh 17.11.21 group same ranks in each group for broadcasting +! write(*,*) 'mype, my_fesom_group', mype, my_fesom_group + + call MPI_comm_split(f%MPI_COMM_FESOM_WORLD, f%mype, f%my_fesom_group, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIERR) + if (f%MPIERR /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_split(MPI_COMM_FESOM_WORLD, mype, my_fesom_group, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + + call MPI_comm_size(f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, npes_check, f%MPIERR) + if(f%MPIERR /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_size(MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, npes_check, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + + call MPI_comm_rank(f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, mype_check, f%MPIERR) + if(f%MPIERR /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_rank(MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, mype_check, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + + if(npes_check /= num_fesom_groups) then + write(*,*) 'npes mismatch, num_fesom_groups, npes_check', num_fesom_groups, npes_check + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + + if(mype_check /= f%my_fesom_group) then + write(*,*) 'mype mismatch, my_fesom_group, mype_check', f%my_fesom_group, mype_check + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if + +! kh 29.02.22 + if(f%my_fesom_group==0) then +#endif if(f%mype==0) then write(*,*) @@ -171,6 +294,11 @@ subroutine fesom_init(fesom_total_nsteps) print *, achar(27)//'[32m' //'____________________________________________________________'//achar(27)//'[0m' print *, achar(27)//'[7;32m'//' --> FESOM BUILDS UP MODEL CONFIGURATION '//achar(27)//'[0m' end if + +#if defined(__usetp) + end if +#endif + !===================== ! Read configuration data, ! load the mesh and fill in @@ -183,8 +311,17 @@ subroutine fesom_init(fesom_total_nsteps) if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call mesh_setup'//achar(27)//'[0m' call mesh_setup(f%partit, f%mesh) +! kh 29.02.22 +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + if (f%mype==0) write(*,*) 'FESOM mesh_setup... complete' +#if defined(__usetp) + end if +#endif + !===================== ! Allocate field variables ! and additional arrays needed for @@ -220,15 +357,43 @@ subroutine fesom_init(fesom_total_nsteps) ! recom setup #if defined (__recom) +#if defined (__usetp) + if(f%my_fesom_group==0) then +#endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call recom_init'//achar(27)//'[0m' +#if defined (__usetp) + end if +#endif + f%t0_recom=MPI_Wtime() call recom_init(f%tracers, f%partit, f%mesh) ! adjust values for recom tracers (derived type "t_tracer") f%t1_recom=MPI_Wtime() + +#if defined (__usetp) + if(f%my_fesom_group==0) then +#endif + if (f%mype==0) write(*,*) 'RECOM recom_init... complete' + +#if defined (__usetp) + end if +#endif + #endif if (f%mype==0) then + +! kh 29.02.22 +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + write(*,*) 'FESOM ocean_setup... complete' + +#if defined(__usetp) + end if +#endif + f%t3=MPI_Wtime() endif call forcing_setup(f%partit, f%mesh) @@ -239,7 +404,17 @@ subroutine fesom_init(fesom_total_nsteps) call ice_setup(f%ice, f%tracers, f%partit, f%mesh) f%ice%ice_steps_since_upd = f%ice%ice_ave_steps-1 f%ice%ice_update=.true. + +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + if (f%mype==0) write(*,*) 'EVP scheme option=', f%ice%whichEVP + +#if defined(__usetp) + end if +#endif + else ! create a dummy ice derived type with only a_ice, m_ice, m_snow and ! uvice since oce_timesteps still needs in moment @@ -264,9 +439,32 @@ subroutine fesom_init(fesom_total_nsteps) !---age-code-end #if defined (__oasis) +! kh 30.11.21 only mype == 0 in my_fesom_group == 0 handles coupling with extern models +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + call cpl_oasis3mct_define_unstr(f%partit, f%mesh) if(f%mype==0) write(*,*) 'FESOM ----> cpl_oasis3mct_define_unstr nsend, nrecv:',nsend, nrecv + +#if defined(__usetp) + end if +#endif + +#if defined(__usetp) +! kh 03.12.21 +! call MPI_Barrier(f%MPI_COMM_FESOM_WORLD, f%MPIERR) + if(num_fesom_groups > 1) then + + call MPI_Bcast(cpl_send, sizeof(cpl_send), MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + call MPI_Bcast(cpl_recv, sizeof(cpl_recv), MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + +! kh 10.12.21 needed in SUBROUTINE net_rec_from_atm(action) + call MPI_Bcast(target_root, 1, MPI_INTEGER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + end if +#endif + #endif ! -------------- @@ -292,8 +490,19 @@ subroutine fesom_init(fesom_total_nsteps) call restart(0, 0, 0, r_restart, f%which_readr, f%ice, f%dynamics, f%tracers, f%partit, f%mesh) if (f%mype==0) f%t7=MPI_Wtime() ! store grid information into netcdf file + +! kh 29.03.22 +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + if (.not. r_restart) call write_mesh_info(f%partit, f%mesh) +! kh 29.03.22 +#if defined(__usetp) + end if +#endif + !___IF RESTART WITH ZLEVEL OR ZSTAR IS DONE, ALSO THE ACTUAL LEVELS AND ____ !___MIDDEPTH LEVELS NEEDS TO BE CALCULATET AT RESTART_______________________ if (r_restart .and. .not. f%which_readr==2) then @@ -313,6 +522,11 @@ subroutine fesom_init(fesom_total_nsteps) f%rtime_setup_recom = real( f%t1_recom - f%t0_recom ,real32) #endif +! kh 29.03.22 +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + write(*,*) '==========================================' write(*,*) 'MODEL SETUP took on mype=0 [seconds] ' write(*,*) 'runtime setup total ',real(f%t8-f%t1,real32) @@ -326,6 +540,12 @@ subroutine fesom_init(fesom_total_nsteps) write(*,*) ' > runtime setup recom ',f%rtime_setup_recom #endif write(*,*) '============================================' + +! kh 29.03.22 +#if defined(__usetp) + end if +#endif + endif #if defined(__MULTIO) @@ -443,24 +663,61 @@ subroutine fesom_runloop(current_nsteps) ! -------------- ! LA icebergs: 2023-05-17 +!YY: only when using icebergs? + if (use_icebergs) then f%MPI_COMM_FESOM_IB = f%MPI_COMM_FESOM if (f%mype==0) then ! write (*,*) 'ib_async_mode, initial omp_num_threads ', ib_async_mode, omp_get_num_threads() write (*,*) 'current_nsteps, steps_per_ib_step, icb_outfreq :', current_nsteps, steps_per_ib_step, icb_outfreq end if + end if ! -------------- +! kh 29.03.22 +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif if (f%mype==0) write(*,*) 'FESOM start iteration before the barrier...' + +! kh 29.03.22 +#if defined(__usetp) + end if +#endif + call MPI_Barrier(f%MPI_COMM_FESOM, f%MPIERR) if (f%mype==0) then + +! kh 29.03.22 +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + write(*,*) 'FESOM start iteration after the barrier...' + +! kh 29.03.22 +#if defined(__usetp) + end if +#endif + f%t0 = MPI_Wtime() endif + +! kh 29.03.22 +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + if(f%mype==0) then write(*,*) print *, achar(27)//'[32m' //'____________________________________________________________'//achar(27)//'[0m' print *, achar(27)//'[7;32m'//' --> FESOM STARTS TIME LOOP '//achar(27)//'[0m' end if + +! kh 29.03.22 +#if defined(__usetp) + end if +#endif + !___MODEL TIME STEPPING LOOP________________________________________________ if (use_global_tides) then call foreph_ini(yearnew, month, f%partit) @@ -526,12 +783,24 @@ subroutine fesom_runloop(current_nsteps) call foreph(f%partit, f%mesh) end if mstep = n + +! kh 29.03.22 +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + if (mod(n,logfile_outfreq)==0 .and. f%mype==0) then write(*,*) 'FESOM =======================================================' ! write(*,*) 'FESOM step:',n,' day:', n*dt/24./3600., write(*,*) 'FESOM step:',n,' day:', daynew,' year:',yearnew write(*,*) end if + +! kh 29.03.22 +#if defined(__usetp) + end if +#endif + #if defined (__oifs) || defined (__oasis) seconds_til_now=INT(dt)*(n-1) #endif @@ -590,25 +859,53 @@ subroutine fesom_runloop(current_nsteps) !___now recom____________________________________________________ #if defined (__recom) +! kh 29.03.22 +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + if (f%mype==0 .and. n==1) print *, achar(27)//'[46' //'_____________________________________________________________'//achar(27)//'[0m' if (f%mype==0 .and. n==1) print *, achar(27)//'[46;1m'//' --> call REcoM '//achar(27)//'[0m' + +#if defined(__usetp) + end if +#endif + f%t0_recom = MPI_Wtime() call recom(f%ice, f%dynamics, f%tracers, f%partit, f%mesh) f%t1_recom = MPI_Wtime() #endif !___model ocean step____________________________________________________ +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call oce_timestep_ale'//achar(27)//'[0m' +#if defined(__usetp) + end if +#endif call oce_timestep_ale(n, f%ice, f%dynamics, f%tracers, f%partit, f%mesh) f%t3 = MPI_Wtime() !___compute energy diagnostics..._______________________________________ +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call compute_diagnostics(1)'//achar(27)//'[0m' +#if defined(__usetp) + end if +#endif call compute_diagnostics(1, f%dynamics, f%tracers, f%ice, f%partit, f%mesh) f%t4 = MPI_Wtime() !___prepare output______________________________________________________ +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call output (n)'//achar(27)//'[0m' +#if defined(__usetp) + end if +#endif call output (n, f%ice, f%dynamics, f%tracers, f%partit, f%mesh) ! LA icebergs: 2023-05-17 @@ -646,18 +943,45 @@ subroutine fesom_finalize() ! EO parameters real(kind=real32) :: mean_rtime(15), max_rtime(15), min_rtime(15) integer :: tr_num + integer :: i !YY ! -------------- ! LA icebergs: 2023-05-17 if (use_icebergs) then call iceberg_out(f%partit) end if ! -------------- +! kh 11.11.21 multi FESOM group loop parallelization +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + call finalize_output() call finalize_restart() +! kh 29.03.22 +#if defined(__usetp) + end if +#endif + !___FINISH MODEL RUN________________________________________________________ +#if !defined (__usetp) +! kh 11.11.21 multi FESOM group loop parallelization call MPI_Barrier(f%MPI_COMM_FESOM, f%MPIERR) +#endif +#if defined (__usetp) +! kh 11.11.21 list statistics for all fesom_groups +! fesom groups are listed backwards, so info for the main fesom group 0 is at the end in the log + do i = num_fesom_groups - 1, 0, -1 + +! kh 29.03.22 use a barrier to "sort" the output but the mpi output can still get a bit mixed up, +! because MPI does not define the handling of the order of the output lines + call MPI_Barrier(f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIERR) + +! kh 29.03.22 for the sake of output clarity produce output only for my_fesom_group == 0 for now + if(i == f%my_fesom_group .and. f%my_fesom_group == 0) then +#endif + !$ACC EXIT DATA DELETE (f%ice%delta_min, f%ice%Tevp_inv, f%ice%cd_oce_ice) !$ACC EXIT DATA DELETE (f%ice%work%fct_tmax, f%ice%work%fct_tmin) !$ACC EXIT DATA DELETE (f%ice%work%fct_fluxes, f%ice%work%fct_plus, f%ice%work%fct_minus) @@ -745,10 +1069,20 @@ subroutine fesom_finalize() call par_ex(f%partit%MPI_COMM_FESOM, f%partit%mype) #endif +#if defined (__usetp) + end if + end do ! i = num_fesom_groups - 1, 0, -1 +#endif + #if defined(__MULTIO) && !defined(__ifsinterface) && !defined(__oasis) call mpp_stop #endif if(f%fesom_did_mpi_init) call par_ex(f%partit%MPI_COMM_FESOM, f%partit%mype) ! finalize MPI before FESOM prints its stats block, otherwise there is sometimes output from other processes from an earlier time in the programm AFTER the starts block (with parastationMPI) + +#if defined(__usetp) + if (f%my_fesom_group==0) then +#endif + if (f%mype==0) then 41 format (a35,a10,2a15) !Format for table heading 42 format (a30,3f15.4) !Format for table content @@ -787,6 +1121,12 @@ subroutine fesom_finalize() write(*,*) '======================================================' write(*,*) end if + +! kh 29.03.22 +#if defined(__usetp) + end if +#endif + ! call clock_finish end subroutine diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index be12855ce..af59bafe7 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -269,7 +269,15 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) print *, 'not installed yet or error in cpl_oasis3mct_send', mype #endif ! oifs endif + +! kh 30.11.21 +#if defined(__usetp) + if(my_fesom_group == 0) then +#endif call cpl_oasis3mct_send(i, exchange, action, partit) +#if defined(__usetp) + endif +#endif end do #ifdef VERBOSE do i=1, nsend @@ -836,9 +844,18 @@ SUBROUTINE net_rec_from_atm(action, partit) USE MOD_PARSUP IMPLICIT NONE +#if defined(__usetp) +! kh 10.21.21 + use g_config, only: num_fesom_groups +#endif + LOGICAL, INTENT (IN) :: action type(t_partit), intent(inout), target :: partit INTEGER :: my_global_rank, ierror +#if defined(__usetp) +! kh 10.12.21 + INTEGER :: my_global_rank_test +#endif INTEGER :: n INTEGER :: status(MPI_STATUS_SIZE,partit%npes) INTEGER :: request(2) @@ -851,11 +868,30 @@ SUBROUTINE net_rec_from_atm(action, partit) CALL MPI_COMM_RANK(MPI_COMM_WORLD, my_global_rank, ierror) atm_net_fluxes_north=0. atm_net_fluxes_south=0. +#if defined(__usetp) +! kh 10.12.21 + my_global_rank_test = my_global_rank - (my_fesom_group * npes) +#endif + +#if defined(__usetp) +! kh 10.12.21 check for is root in group + if (my_global_rank_test==target_root) then + if(my_fesom_group == 0) then +#else if (my_global_rank==target_root) then - CALL MPI_IRecv(atm_net_fluxes_north(1), nrecv, MPI_DOUBLE_PRECISION, source_root, 111, MPI_COMM_WORLD, request(1), partit%MPIerr) +#endif + CALL MPI_IRecv(atm_net_fluxes_north(1), nrecv, MPI_DOUBLE_PRECISION, source_root, 111, MPI_COMM_WORLD, request(1), partit%MPIerr) CALL MPI_IRecv(atm_net_fluxes_south(1), nrecv, MPI_DOUBLE_PRECISION, source_root, 112, MPI_COMM_WORLD, request(2), partit%MPIerr) CALL MPI_Waitall(2, request, status, partit%MPIerr) end if + +#if defined(__usetp) + if(num_fesom_groups > 1) then + call MPI_Bcast(atm_net_fluxes_north(1), nrecv, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) + call MPI_Bcast(atm_net_fluxes_south(1), nrecv, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) + end if + end if ! (my_global_rank_test==target_root) then +#endif call MPI_Barrier(partit%MPI_COMM_FESOM, partit%MPIerr) call MPI_AllREDUCE(atm_net_fluxes_north(1), aux, nrecv, MPI_DOUBLE_PRECISION, MPI_SUM, partit%MPI_COMM_FESOM, partit%MPIerr) atm_net_fluxes_north=aux diff --git a/src/gen_ic3d.F90 b/src/gen_ic3d.F90 index 7513fec4b..50681b76c 100644 --- a/src/gen_ic3d.F90 +++ b/src/gen_ic3d.F90 @@ -613,7 +613,9 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) call MPI_AllREDUCE(locSmin , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, partit%MPI_COMM_FESOM, partit%MPIerr) if (partit%mype==0) write(*,*) ' `-> gobal min init. salt. =', glo #if defined(__recom) - +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (partit%mype==0) write(*,*) "Sanity check for REcoM variables" call MPI_AllREDUCE(locDINmax , glo , 1, MPI_DOUBLE_PRECISION, MPI_MAX, partit%MPI_COMM_FESOM, partit%MPIerr) if (partit%mype==0) write(*,*) ' |-> gobal max init. DIN. =', glo @@ -640,6 +642,9 @@ SUBROUTINE do_ic3d(tracers, partit, mesh) if (partit%mype==0) write(*,*) ' |-> gobal max init. O2. =', glo call MPI_AllREDUCE(locO2min , glo , 1, MPI_DOUBLE_PRECISION, MPI_MIN, partit%MPI_COMM_FESOM, partit%MPIerr) if (partit%mype==0) write(*,*) ' `-> gobal min init. O2. =', glo +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif #endif END SUBROUTINE do_ic3d diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index 13a669a3a..47d95f718 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -174,6 +174,34 @@ subroutine setup_model(partit) endif ! if ((output_length_unit=='s').or.(int(real(step_per_day)/24.0)<=1)) use_means=.false. end subroutine setup_model + + +#if defined(__usetp) +! kh 11.11.21 read num_fesom_groups for multi FESOM group loop parallelization +! ================================================================= +subroutine read_namelist_run_config(partit) + ! Reads run_config namelist and overwrite default parameters. + ! + ! kh 11.11.21 Copied by Kai Himstedt (based on read_namelist) + !-------------------------------------------------------------- + USE MOD_PARTIT + USE MOD_PARSUP + use g_config + implicit none + type(t_partit), intent(inout), target :: partit + + character(len=100) :: nmlfile + integer fileunit + + nmlfile ='namelist.config' ! name of general configuration namelist file + open (newunit=fileunit, file=nmlfile) + + open (fileunit,file=nmlfile) +! read (fileunit,NML=run_config) + read (fileunit,NML=run_config_tp) + close (fileunit) +end subroutine read_namelist_run_config +#endif ! ================================================================= subroutine get_run_steps(nsteps, partit) ! Coded by Qiang Wang diff --git a/src/gen_modules_config.F90 b/src/gen_modules_config.F90 index a12ff8c9a..8f6a06e22 100755 --- a/src/gen_modules_config.F90 +++ b/src/gen_modules_config.F90 @@ -151,7 +151,13 @@ module g_config use_cavity_partial_cell, cavity_partial_cell_thresh, & use_cavity_fw2press, toy_ocean, which_toy, flag_debug, flag_warn_cflz, lwiso, & use_transit - + +#if defined(__recom) & defined(__usetp) +! kh 11.11.21 number of groups for multi FESOM group loop parallelization + integer :: num_fesom_groups=1 + namelist /run_config_tp/ num_fesom_groups +#endif + !_____________________________________________________________________________ ! *** others *** real(kind=WP) :: dt diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index 75d393164..b312fe69f 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -1220,9 +1220,22 @@ SUBROUTINE sbc_ini(partit, mesh) ! OPEN and read namelist for SBC REcoM open( unit=nm_sbc_unit+1, file='namelist.recom', form='formatted', access='sequential', status='old', iostat=iost ) if (iost == 0) then +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) WRITE(*,*) ' file : ', 'namelist.recom for sbc',' open ok' +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif else +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif + if (mype==0) WRITE(*,*) 'ERROR: --> bad opening file : ', 'namelist.recom for sbc',' ; iostat=',iost +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif call par_ex(partit%MPI_COMM_FESOM, partit%mype) stop endif @@ -1439,8 +1452,14 @@ SUBROUTINE sbc_do(partit, mesh) if (constant_CO2) then AtmCO2(:) = CO2_for_spinup +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'Constant_CO2 = ', CO2_for_spinup if (mype==0) write(*,*),'Atm CO2=', AtmCO2 +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif if (ciso) then AtmCO2_13 = CO2_for_spinup * (1. + 0.001 * delta_co2_13) if (ciso_14) then @@ -1463,7 +1482,13 @@ SUBROUTINE sbc_do(partit, mesh) end if else filename=trim(nm_co2_data_file) +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'Updating CO2 climatology for month ', i,' from ', trim(filename) +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif totnumyear = lastyearoffesomcycle-firstyearoffesomcycle+1 firstyearofcurrentCO2cycle = lastyearoffesomcycle-numofCO2cycles*totnumyear+(currentCO2cycle-1)*totnumyear @@ -1490,20 +1515,32 @@ SUBROUTINE sbc_do(partit, mesh) status=nf_get_vara_double(ncid,varid,CO2start,CO2count,ncdata) AtmCO2(:)=ncdata(:) deallocate(ncdata) +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*),'Current carbon year=',currentCO2year if (mype==0) write(*,*),'Atm CO2=', AtmCO2 +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif status=nf_close(ncid) end if end if ! atmospheric box model or prescribed CO2 values ! Control output of atmospheric CO2 values if (mype==0) then !OG +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif 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." +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif end if @@ -1512,10 +1549,22 @@ SUBROUTINE sbc_do(partit, mesh) !-Checking if files need to be opened--------------------------------------------- if(use_MEDUSA .and. (sedflx_num .ne. 0)) then allocate(ncdata(9)) +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Sed_input'//achar(27)//'[0m' +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif ! MEDUSA input needs to be renamed via jobscript sedfilename = trim(ResultPath)//'medusa_flux2fesom.nc' +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'Updating sedimentary input first time from', sedfilename +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif !-Opening files-------------------------------------------------------------------- @@ -1548,7 +1597,13 @@ SUBROUTINE sbc_do(partit, mesh) ! read loopback fluxes from the same file if(add_loopback) then +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'adding loopback fluxes through runoff for the first time' !OG +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif istart = (/1,1/) icount = (/1,1/) @@ -1563,57 +1618,57 @@ SUBROUTINE sbc_do(partit, mesh) 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 +! 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 +! 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 +! 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 +! 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 (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 +! 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 (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 +! 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 +! if (mype==0) write(*,*) mype, 'loopback_caco314:', ncdata(9) !OG end if ! ciso_14 .and. ciso_organic_14 end if ! ciso @@ -1635,7 +1690,14 @@ SUBROUTINE sbc_do(partit, mesh) if(do_read) then ! file is opened and read every year i=month if (i > 12) i=1 +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'Updating sedimentary input for month', i, 'from', sedfilename !OG +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif + 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)) @@ -1666,8 +1728,13 @@ SUBROUTINE sbc_do(partit, mesh) ! read loopback fluxes from the same file if(add_loopback) then +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'adding loopback fluxes into the ocean monthly' !OG - +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif istart = (/1,1/) icount = (/1,1/) ncdata = 0.d0 @@ -1681,57 +1748,57 @@ SUBROUTINE sbc_do(partit, mesh) 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 +! 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 +! 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 +! 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 +! 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 (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 +! 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 (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 +! 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 +! if (mype==0) write(*,*) mype, 'loopback_caco314:', ncdata(9) !OG end if ! ciso_14 .and. ciso_organic_14 end if ! ciso @@ -1747,8 +1814,13 @@ SUBROUTINE sbc_do(partit, mesh) end if ! do_read +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'sedimentary input from MEDUSA not used!' !OG - +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif end if ! use_MEDUSA and sedflx_num not 0 end if @@ -1761,11 +1833,23 @@ SUBROUTINE sbc_do(partit, mesh) if (mstep > 1) i=i+1 if (i > 12) i=1 filename=trim(nm_fe_data_file) +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'Updating iron climatology for month ', i,' from ', trim(filename) +#if defined(__usetp) + endif +#endif call read_2ddata_on_grid_NetCDF(filename,'DustClim', i, GloFeDust, partit, mesh) end if else +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'Albani is switched off --> Check namelist.recom' +#if defined(__usetp) + endif +#endif end if ! ******** N deposition ********* @@ -1777,7 +1861,13 @@ SUBROUTINE sbc_do(partit, mesh) ! if (i > 12) i=1 ! if (mype==0) write(*,*) 'Updating iron climatology for month ', i filename=trim(nm_aen_data_file) +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'Updating nitrogen climatology for month ', i,' from ', trim(filename) +#if defined(__usetp) + endif +#endif if (yearnew .gt. 2009) then Nvari = 'NDep2009' else if (yearnew .lt. 1850) then @@ -1790,7 +1880,13 @@ SUBROUTINE sbc_do(partit, mesh) end if else GloNDust = 0.0_WP +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mstep==1 .and. mype==0) write(*,*) 'useAeolianN is switched off' +#if defined(__usetp) + endif +#endif end if ! ******** Riverine input (Nutrients) ********* @@ -1807,7 +1903,13 @@ SUBROUTINE sbc_do(partit, mesh) if (mstep > 1) i=i+1 if (i > 12) i=1 filename=trim(nm_river_data_file) +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'Updating riverine restoring data for month', i,' from ', trim(filename) +#if defined(__usetp) + endif +#endif call read_2ddata_on_grid_NetCDF(filename,'Alkalinity', i, RiverAlk2D, partit, mesh) ! write(*,*) mype, 'RiverAlk2D', maxval(RiverAlk2D(:)), minval(RiverAlk2D(:)) ! molar convertion of [CaCo3] * 2 -> [total Alkalinity] @@ -1829,7 +1931,13 @@ SUBROUTINE sbc_do(partit, mesh) end if else is_riverinput = 0.0d0 +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0 .and. mstep==1) write(*,*) 'No riverine input' +#if defined(__usetp) + endif +#endif end if ! ******** Riverine input of iron ********* @@ -1847,7 +1955,13 @@ SUBROUTINE sbc_do(partit, mesh) !< read erosion input ! *** River inputs are in mmol/m2/s *** ! add erosion nutrients as surface boundary condition (surface_bc function in oce_ale_tracers) +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Erosion_input'//achar(27)//'[0m' +#if defined(__usetp) + endif +#endif is_erosioninput = 1.0d0 @@ -1856,7 +1970,13 @@ SUBROUTINE sbc_do(partit, mesh) if (mstep > 1) i=i+1 if (i > 12) i=1 filename=trim(nm_erosion_data_file) +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0) write(*,*) 'Updating erosion restoring data for month ', i,' from ', trim(filename) +#if defined(__usetp) + endif +#endif call read_2ddata_on_grid_NetCDF(filename,'POC', i, ErosionTOC2D, partit, mesh) ! write(*,*) mype, 'ErosionTOC2D', maxval(ErosionTOC2D(:)), minval(ErosionTOC2D(:)) @@ -1868,7 +1988,13 @@ SUBROUTINE sbc_do(partit, mesh) end if else is_erosioninput = 0.0d0 +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if (mype==0 .and. mstep==1) write(*,*) 'No erosion input' +#if defined(__usetp) + endif +#endif end if #endif diff --git a/src/int_recom/recom_sinking.F90 b/src/int_recom/recom_sinking.F90 index b772569ec..fdebc604f 100644 --- a/src/int_recom/recom_sinking.F90 +++ b/src/int_recom/recom_sinking.F90 @@ -148,6 +148,7 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) ! now SinkFlx hat the unit mmol/time step ! but mmol/m2/time is needed for MEDUSA: thus /area endif + !YY: check if benthos_tr should be needed for usetp if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then ! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel Benthos_tr(n,1,tr_num)= Benthos_tr(n,1,tr_num) + add_benthos_2d(n) ![mmol] diff --git a/src/io_restart.F90 b/src/io_restart.F90 index fb659e2cb..9c7f9fa35 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -270,8 +270,19 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr logical rawfiles_exist, binfiles_exist logical, save :: initialized_raw = .false. logical, save :: initialized_bin = .false. - integer mpierr - +! integer mpierr + +#if defined(__recom) || defined ( __usetp) +! kh 31.03.22 + integer :: tr_arr_slice_count_fix_1 + integer :: group_i + integer :: tr_num_start + integer :: tr_num_end + integer :: tr_num_in_group + logical :: has_one_added_tracer + integer :: num_tracers +#endif + !which_readr = ... ! 0 ... read netcdf restart ! 1 ... read dump file restart (binary) @@ -279,6 +290,16 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr integer, intent(out):: which_readr integer :: cstep + +#if defined(__recom) || defined ( __usetp) +! kh 31.03.22 nl is required +#include "associate_part_def.h" +#include "associate_mesh_def.h" +#include "associate_part_ass.h" +#include "associate_mesh_ass.h" + + num_tracers = tracers%num_tracers +#endif !_____________________________________________________________________________ ! initialize directory for core dump restart if(.not. initialized_raw) then @@ -286,11 +307,18 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr raw_restart_dirpath = trim(ResultPath)//"fesom_raw_restart/np"//int_to_txt(partit%npes) raw_restart_infopath = trim(ResultPath)//"fesom_raw_restart/np"//int_to_txt(partit%npes)//".info" if(raw_restart_length_unit /= "off") then + +#if defined(__recom) & defined(__usetp) + if(partit%my_fesom_group == 0) then ! OG master rank creates the folder +#endif if(partit%mype == RAW_RESTART_METADATA_RANK) then ! execute_command_line with mkdir sometimes fails, use a custom implementation around mkdir from C instead call mkdir(trim(ResultPath)//"fesom_raw_restart") ! we have no mkdir -p, create the intermediate dirs separately call mkdir(raw_restart_dirpath) end if +#if defined(__recom) & defined(__usetp) + end if ! (my_fesom_group == 0) then +#endif call MPI_Barrier(partit%MPI_COMM_FESOM, mpierr) ! make sure the dir has been created before we continue... end if end if @@ -302,11 +330,17 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr bin_restart_dirpath = trim(ResultPath)//"fesom_bin_restart/np"//int_to_txt(partit%npes) bin_restart_infopath = trim(ResultPath)//"fesom_bin_restart/np"//int_to_txt(partit%npes)//".info" if(bin_restart_length_unit /= "off") then +#if defined(__recom) & defined(__usetp) + if(partit%my_fesom_group == 0) then ! OG +#endif if(partit%mype == RAW_RESTART_METADATA_RANK) then ! execute_command_line with mkdir sometimes fails, use a custom implementation around mkdir from C instead call mkdir(trim(ResultPath)//"fesom_bin_restart") ! we have no mkdir -p, create the intermediate dirs separately call mkdir(bin_restart_dirpath) end if +#if defined(__recom) & defined(__usetp) + end if ! (my_fesom_group == 0) then +#endif call MPI_Barrier(partit%MPI_COMM_FESOM, mpierr) ! make sure the dir has been created before we continue... end if end if @@ -377,10 +411,22 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! read netcdf file restart else which_readr = 0 +#if defined(__recom) & defined(__usetp) + if(partit%my_fesom_group == 0) then !OG +#endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: ocean'//achar(27)//'[0m' +#if defined(__recom) & defined(__usetp) + endif !(partit%my_fesom_group == 0) then ! OG +#endif call read_restart(oce_path, oce_files, partit%MPI_COMM_FESOM, partit%mype) if (use_ice) then +#if defined(__recom) & defined(__usetp) + if(partit%my_fesom_group == 0) then ! OG +#endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: ice'//achar(27)//'[0m' +#if defined(__recom) & defined(__usetp) + endif !(partit%my_fesom_group == 0) then ! OG +#endif call read_restart(ice_path, ice_files, partit%MPI_COMM_FESOM, partit%mype) end if @@ -388,19 +434,34 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr !RECOM restart !read here if (REcoM_restart) then +#if defined(__usetp) + if(partit%my_fesom_group == 0) then +#endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: bio'//achar(27)//'[0m' +#if defined(__usetp) + endif !(partit%my_fesom_group == 0) then +#endif call read_restart(bio_path, bio_files, partit%MPI_COMM_FESOM, partit%mype) end if #endif ! immediately create a raw core dump restart if(raw_restart_length_unit /= "off") then +#if defined(__recom) & defined(__usetp) + if(partit%my_fesom_group == 0) then ! OG master rank reads +#endif call write_all_raw_restarts(istep, partit%MPI_COMM_FESOM, partit%mype) +#if defined(__recom) & defined(__usetp) + end if ! (my_fesom_group == 0) then +#endif end if ! immediately create a derived type binary restart if(bin_restart_length_unit /= "off") then ! current (total) model step --> cstep = globalstep+istep +#if defined(__recom) & defined(__usetp) + if(partit%my_fesom_group == 0) then ! OG +#endif call write_all_bin_restarts((/globalstep+istep, int(ctime), yearnew/), & bin_restart_dirpath, & bin_restart_infopath, & @@ -409,6 +470,9 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ice, & dynamics, & tracers ) +#if defined(__recom) & defined(__usetp) + end if ! (my_fesom_group == 0) then +#endif end if end if end if @@ -438,15 +502,40 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr is_bin_restart_write = is_due(trim(bin_restart_length_unit), bin_restart_length, istep) end if +#if defined(__recom) & defined(__usetp) + if(num_fesom_groups > 1) then + tr_arr_slice_count_fix_1 = 1 * (nl - 1) * (myDim_nod2D + eDim_nod2D) + + do group_i = 0, num_fesom_groups - 1 + call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group, has_one_added_tracer) + + call MPI_Bcast(tracers%data(tr_num_start)%valuesAB(:, :), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, mpierr) + end do + end if +#endif + !_____________________________________________________________________________ ! finally write restart for netcdf, core dump and derived type binary ! write netcdf restart if(is_portable_restart_write) then +#if defined(__usetp) + if(partit%my_fesom_group == 0) then +#endif ! if(partit%mype==0) write(*,*)'Do output (netCDF, restart) ...' if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: ocean'//achar(27)//'[0m' +#if defined(__usetp) + endif !(partit%my_fesom_group == 0) then +#endif + call write_restart(oce_path, oce_files, istep) if(use_ice) then +#if defined(__usetp) + if(partit%my_fesom_group == 0) then +#endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: ice'//achar(27)//'[0m' +#if defined(__usetp) + endif !(partit%my_fesom_group == 0) then +#endif call write_restart(ice_path, ice_files, istep) end if @@ -454,8 +543,14 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr !RECOM restart !write here if (REcoM_restart .or. use_REcoM) then - +#if defined(__usetp) + if(partit%my_fesom_group == 0) then +#endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: bio'//achar(27)//'[0m' +#if defined(__usetp) + endif !(partit%my_fesom_group == 0) then +#endif + call write_restart(bio_path, bio_files, istep) end if #endif @@ -463,12 +558,27 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! write core dump if(is_raw_restart_write) then + +#if defined(__recom) & defined(__usetp) + if(partit%my_fesom_group == 0) then ! OG master rank reads +#endif + call write_all_raw_restarts(istep, partit%MPI_COMM_FESOM, partit%mype) + +#if defined(__recom) & defined(__usetp) + end if ! (my_fesom_group == 0) then +#endif + end if ! write derived type binary if(is_bin_restart_write) then ! current (total) model step --> cstep = globalstep+istep + +#if defined(__recom) & defined(__usetp) + if(partit%my_fesom_group == 0) then ! OG master rank reads +#endif + call write_all_bin_restarts((/globalstep+istep, int(ctime), yearnew/), & bin_restart_dirpath, & bin_restart_infopath, & @@ -487,6 +597,10 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr end if end if +#if defined(__recom) & defined(__usetp) + end if ! (my_fesom_group == 0) then +#endif + end subroutine restart ! ! diff --git a/src/oce_ale.F90 b/src/oce_ale.F90 index 681bfa51e..0a1a10570 100644 --- a/src/oce_ale.F90 +++ b/src/oce_ale.F90 @@ -3757,6 +3757,10 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) !___________________________________________________________________________ ! write out global fields for debugging if (flag_debug .and. mype==0) print *, achar(27)//'[36m'//' --> call write_step_info'//achar(27)//'[0m' +#if defined(__usetp) +! kh 19.11.21 + if(partit%my_fesom_group == 0) then +#endif call write_step_info(n,logfile_outfreq, ice, dynamics, tracers, partit, mesh) !___________________________________________________________________________ @@ -3769,6 +3773,10 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) ! togeather around 2.5% of model runtime if (flag_debug .and. mype==0) print *, achar(27)//'[36m'//' --> call check_blowup'//achar(27)//'[0m' call check_blowup(n, ice, dynamics, tracers, partit, mesh) +#if defined(__usetp) + endif +#endif + t10=MPI_Wtime() !___________________________________________________________________________ @@ -3781,6 +3789,11 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) rtime_oce_GMRedi = rtime_oce_GMRedi + (t6-t5) rtime_oce_solvetra = rtime_oce_solvetra + (t8-t7) rtime_tot = rtime_tot + (t10-t0)-(t10-t9) + +#if defined(__usetp) +! kh 19.11.21 + if(partit%my_fesom_group == 0) then +#endif if(mod(n,logfile_outfreq)==0 .and. mype==0) then write(*,*) '___ALE OCEAN STEP EXECUTION TIMES______________________' write(*,"(A, ES10.3)") ' Oce. Mix,Press.. :', t1-t0 @@ -3799,6 +3812,10 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) write(*,"(A, ES10.3)") ' Oce. TOTAL :', t10-t0 write(*,*) write(*,*) - end if + end if +#if defined(__usetp) + endif +#endif + end subroutine oce_timestep_ale diff --git a/src/oce_ale_tracer.F90 b/src/oce_ale_tracer.F90 index 20f921e94..028d43550 100644 --- a/src/oce_ale_tracer.F90 +++ b/src/oce_ale_tracer.F90 @@ -163,6 +163,8 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) #if defined(__recom) use recom_glovar use recom_config + use recom_ciso + use o_arrays #endif use diagnostics, only: ldiag_DVD use g_forcing_param, only: use_age_tracer !---age-code @@ -173,6 +175,38 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) type(t_tracer), intent(inout), target :: tracers type(t_partit), intent(inout), target :: partit type(t_mesh) , intent(in) , target :: mesh + +#if defined(__recom) || defined ( __usetp) +! kh 11.11.21 multi FESOM group loop parallelization + integer :: num_tracers + integer :: tr_num_start_memo + +! kh 15.11.21 + integer :: group_i + integer :: tr_num_start + +! kh 19.11.21 + logical :: has_one_added_tracer + logical :: has_one_added_tracer_local_dummy + logical :: tr_num_end_local_dummy + logical :: tr_num_in_group_local_dummy + integer :: tr_num_end + logical :: tr_num_in_group_dummy + integer :: tr_arr_slice_count_fix_1 + +! kh 28.03.22 + integer :: Sinkflx_tr_slice_count_fix_1 + integer :: Benthos_tr_slice_count_fix_1 + + integer :: tr_num_start_local + integer :: tr_num_to_send + +! kh 22.11.21 + logical :: completed + + logical :: bBreak +#endif + !___________________________________________________________________________ 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 ! OG - tra_diag @@ -196,6 +230,10 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) end if del_ttf => tracers%work%del_ttf +#if defined(__recom) || defined ( __usetp) + num_tracers=tracers%num_tracers +#endif + !___________________________________________________________________________ if (SPP) call cal_rejected_salt(ice, partit, mesh) if (SPP) call app_rejected_salt(tracers%data(2)%values, partit, mesh) @@ -231,13 +269,42 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) !$ACC UPDATE DEVICE(dynamics%w, dynamics%w_e, dynamics%uv) !!! async(1) !!! !$ACC UPDATE DEVICE(tracers%work%fct_ttf_min, tracers%work%fct_ttf_max, tracers%work%fct_plus, tracers%work%fct_minus) !$ACC UPDATE DEVICE (mesh%helem, mesh%hnode, mesh%hnode_new, mesh%zbar_3d_n, mesh%z_3d_n) + +#if defined(__usetp) +! kh 11.11.21 multi FESOM group loop parallelization + call calc_slice(num_tracers, num_fesom_groups, partit%my_fesom_group, tr_num_start, tr_num_end, tr_num_in_group_dummy, has_one_added_tracer) + +! kh 19.11.21 + tr_arr_slice_count_fix_1 = 1 * (nl - 1) * (myDim_nod2D + eDim_nod2D) + +! kh 28.03.22 + Sinkflx_tr_slice_count_fix_1 = 1 * (myDim_nod2D + eDim_nod2D) * bottflx_num + Benthos_tr_slice_count_fix_1 = 1 * (myDim_nod2D + eDim_nod2D) * benthos_num + + tr_num_start_memo = tr_num_start + +! kh 22.11.21 + request_count = 0 +#endif + +#if defined(__usetp) + do tr_num = tr_num_start, tr_num_end +#else do tr_num=1, tracers%num_tracers +#endif -!YY: sinkflx needs to be reset at each time step - if(use_MEDUSA) then +#if defined(__recom) + if(use_MEDUSA) then SinkFlx = 0.0d0 - endif - +#if defined(__usetp) + SinkFlx_tr(:, :, tr_num) = 0.0d0 +#endif + endif +#if defined(__usetp) + Benthos_tr(:, :, tr_num) = 0.0d0 +#endif +#endif !__recom + ! 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' @@ -322,10 +389,93 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) end if call exchange_nod(tracers%data(tr_num)%values(:,:), partit) !$OMP BARRIER - end do +! end do !!! !$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(__usetp) +! kh 19.11.21 broadcast tracer results to fesom groups + if(num_fesom_groups > 1) then + + do group_i = 0, num_fesom_groups - 1 + call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start_local, tr_num_end_local_dummy, tr_num_in_group_local_dummy, has_one_added_tracer_local_dummy) + + tr_num_to_send = tr_num_start_local + (tr_num - tr_num_start_memo) + + if((tr_num == tr_num_end) .and. has_one_added_tracer) then + ! skip: if last tracer in group was added to compensate for fragementation it is skipped here and handled after the loop + else + request_count = request_count + 1 + +! kh 22.11.21 non-blocking communication overlapped with computation in loop + call MPI_IBcast(tracers%data(tr_num_to_send)%values(:, :), tr_arr_slice_count_fix_1, MPI_DOUBLE_PRECISION, & + group_i, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, tr_arr_requests(request_count), MPIerr) + + if(use_MEDUSA) then + call MPI_IBcast(Sinkflx_tr (:, :, tr_num_to_send), Sinkflx_tr_slice_count_fix_1, MPI_DOUBLE_PRECISION, & + group_i, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, SinkFlx_tr_requests(request_count), MPIerr) + endif + call MPI_IBcast(Benthos_tr (:, :, tr_num_to_send), Benthos_tr_slice_count_fix_1, MPI_DOUBLE_PRECISION, & + group_i, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, Benthos_tr_requests(request_count), MPIerr) + end if + end do + end if ! (num_fesom_groups > 1) then +#endif + end do ! tr_num = tr_num_start, tr_num_end + +#if defined(__usetp) +! kh 19.11.21 if tracer in group was added to compensate for fragmentation its broadcast of the last index is handled here + if(num_fesom_groups > 1) then + do group_i = 0, num_fesom_groups - 1 + call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group_dummy, has_one_added_tracer) + + if(has_one_added_tracer) then + + request_count = request_count + 1 + + call MPI_IBcast(tracers%data(tr_num_end)%values(:, :), tr_arr_slice_count_fix_1, MPI_DOUBLE_PRECISION, & + group_i, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, tr_arr_requests(request_count), MPIerr) + if(use_MEDUSA) then + call MPI_IBcast(Sinkflx_tr (:, :, tr_num_end), Sinkflx_tr_slice_count_fix_1, MPI_DOUBLE_PRECISION, & + group_i, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, SinkFlx_tr_requests(request_count), MPIerr) + endif + call MPI_IBcast(Benthos_tr (:, :, tr_num_end), Benthos_tr_slice_count_fix_1, MPI_DOUBLE_PRECISION, & + group_i, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, Benthos_tr_requests(request_count), MPIerr) + end if + end do + end if !(num_fesom_groups > 1) then + + if(num_fesom_groups > 1) then + completed = .false. + do while (.not. completed) + call MPI_TESTALL(request_count, tr_arr_requests(:), completed, MPI_STATUSES_IGNORE, MPIerr) + end do + + if(use_MEDUSA) then + completed = .false. + do while (.not. completed) + call MPI_TESTALL(request_count, SinkFlx_tr_requests(:), completed, MPI_STATUSES_IGNORE, MPIerr) + end do + endif ! (use_MEDUSA) then + + completed = .false. + do while (.not. completed) + call MPI_TESTALL(request_count, Benthos_tr_requests(:), completed, MPI_STATUSES_IGNORE, MPIerr) + end do + end if ! (num_fesom_groups > 1) then +#endif + +#if defined(__recom) +! kh 25.03.22 SinkFlx and Benthos values are buffered per tracer index in the loop above and now summed up to +! avoid non bit identical results regarding global sums when running the tracer loop in parallel + do tr_num = 1, num_tracers + if(use_MEDUSA) then + SinkFlx = SinkFlx + SinkFlx_tr(:, :, tr_num) + endif + Benthos = Benthos + Benthos_tr(:, :, tr_num) + end do +#endif + !___________________________________________________________________________ ! 3D restoring for "passive" tracers !!!$OMPTODO: add OpenMP later, not needed right now! @@ -1608,6 +1758,8 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit) #if defined (__recom) use recoM_declarations use recom_glovar + use recom_config + use recom_ciso #endif use mod_transit implicit none @@ -1893,3 +2045,38 @@ FUNCTION transit_bc_surface(n, id, sst, sss, aice, sval, nzmin, partit, mesh) END FUNCTION +!=============================================================================== +! kh 11.11.21 divide the range specified by indexcount into fesom_group_count equal slices and calculate +! the start_index and end_index for the given fesom_group_id. +! if necessary to compensate for fragmentation, the end index of the first n slices +! might be one higher than for the remaining slices. this is indicated by end_index_is_one_higher +subroutine calc_slice(index_count, fesom_group_count, fesom_group_id, start_index, end_index, index_count_in_group, end_index_is_one_higher) +! use g_config + + implicit none + integer, intent(in) :: index_count + integer, intent(in) :: fesom_group_count + integer, intent(in) :: fesom_group_id + integer, intent(out) :: start_index + integer, intent(out) :: end_index + integer, intent(out) :: index_count_in_group + logical, intent(out) :: end_index_is_one_higher + + integer :: group_id_limit_to_adjust_end_index + + index_count_in_group = index_count / fesom_group_count + group_id_limit_to_adjust_end_index = mod(index_count, fesom_group_count) + start_index = (fesom_group_id * index_count_in_group) + 1 + +! kh 11.11.21 adjust loop start and number of loop iterations by 1 if necessary + if(fesom_group_id < group_id_limit_to_adjust_end_index) then + start_index = start_index + fesom_group_id + index_count_in_group = index_count_in_group + 1 + end_index_is_one_higher = .true. + else + start_index = start_index + group_id_limit_to_adjust_end_index + end_index_is_one_higher = .false. + end if + + end_index = start_index + index_count_in_group - 1 +end subroutine calc_slice diff --git a/src/oce_modules.F90 b/src/oce_modules.F90 index 57f647e25..99ef44827 100755 --- a/src/oce_modules.F90 +++ b/src/oce_modules.F90 @@ -220,6 +220,15 @@ MODULE o_ARRAYS #if defined(__recom) real(kind=WP), allocatable :: dtr_bf(:,:), str_bf(:,:) real(kind=WP), allocatable :: vert_sink(:,:) +#if defined ( __usetp) +! kh 22.11.21 +integer :: request_count +integer, allocatable :: tr_arr_requests(:), tr_arr_old_requests(:) + +! kh 28.03.22 +integer, allocatable :: SinkFlx_tr_requests(:) +integer, allocatable :: Benthos_tr_requests(:) +#endif #endif !Viscosity and diff coefs diff --git a/src/oce_setup_step.F90 b/src/oce_setup_step.F90 index 51d310f77..e024cc353 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -811,6 +811,12 @@ SUBROUTINE arrays_init(num_tracers, partit, mesh) allocate(str_bf ( nl-1, node_size )) allocate(vert_sink ( nl-1, node_size )) allocate(Alk_surf ( node_size )) +#if defined (__usetp) +! kh 22.11.21 + allocate(tr_arr_requests(num_tracers), tr_arr_old_requests(num_tracers)) + allocate(SinkFlx_tr_requests(num_tracers)) + allocate(Benthos_tr_requests(num_tracers)) +#endif #endif ! ================= ! Visc and Diff coefs @@ -920,6 +926,13 @@ SUBROUTINE arrays_init(num_tracers, partit, mesh) str_bf = 0.0_WP vert_sink = 0.0_WP Alk_surf = 0.0_WP +#if defined (__usetp) +! kh 23.03.22 + tr_arr_requests = 0 + tr_arr_old_requests = 0 + SinkFlx_tr_requests = 0 + Benthos_tr_requests = 0 +#endif #endif ! init field for pressure force @@ -1015,6 +1028,9 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) end if if (mype==0) then +#if defined (__usetp) + if (my_fesom_group==0) then +#endif write(*,*) print *, achar(27)//'[36m'//'*************************'//achar(27)//'[0m' print *, achar(27)//'[36m'//' --> RECOM ON'//achar(27)//'[0m' @@ -1039,6 +1055,9 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'read Nitrate climatology from:', trim(filelist(6)) write(*,*) 'read Salt climatology from:', trim(filelist(7)) write(*,*) 'read Temperature climatology from:', trim(filelist(8)) +#if defined ( __usetp) + end if ! (my_fesom_group==0) then +#endif end if ! read ocean state ! this must be always done! First two tracers with IDs 0 and 1 are the temperature and salinity. @@ -1055,9 +1074,10 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) ! this must be always done! First two tracers with IDs 0 and 1 are the temperature and salinity. if(mype==0) write(*,*) 'read Temperature climatology from:', trim(filelist(1)) if(mype==0) write(*,*) 'read Salinity climatology from:', trim(filelist(2)) - #endif + if(any(idlist == 14) .and. mype==0) write(*,*) 'read radiocarbon climatology from:', trim(filelist(3)) + call do_ic3d(tracers, partit, mesh) Tclim=tracers%data(1)%values @@ -1075,9 +1095,17 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) #if defined(__recom) if (restore_alkalinity) then + +#if defined ( __usetp) + if (my_fesom_group==0) then +#endif if (mype==0) write(*,*) if (mype==0) print *, achar(27)//'[46;1m'//' --> Set surface field for alkalinity restoring'//achar(27)//'[0m' - if (mype==0) write(*,*) + if (mype==0) write(*,*),'Alkalinity restoring = true. Field is read.' +#if defined ( __usetp) + endif !(my_fesom_group==0) then +#endif + Alk_surf = tracers%data(5)%values(1,:) ! alkalinity is the 5th tracer endif @@ -1112,26 +1140,101 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) !_______________________________________________________________________ CASE (1004:1017) tracers%data(i)%values(:,:)=0.0_WP +#if defined ( __usetp) + if (my_fesom_group==0) then +#endif if (mype==0) then write (i_string, "(I4)") i write (id_string, "(I4)") id write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if +#if defined ( __usetp) + endif !(my_fesom_group==0) then +#endif CASE (1020:1021) tracers%data(i)%values(:,:)=0.0_WP +#if defined ( __usetp) + if (my_fesom_group==0) then +#endif if (mype==0) then write (i_string, "(I4)") i write (id_string, "(I4)") id write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if +#if defined ( __usetp) + endif !(my_fesom_group==0) then +#endif CASE (1023:1033) tracers%data(i)%values(:,:)=0.0_WP +#if defined ( __usetp) + if (my_fesom_group==0) then +#endif if (mype==0) then write (i_string, "(I4)") i write (id_string, "(I4)") id write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if - !_______________________________________________________________________ +#if defined ( __usetp) + endif !(my_fesom_group==0) then +#endif +!_______________________________________________________________________ +! Carbon isotopes +! Carbon-13 + CASE (1302) + tracers%data(i)%values(:,:)=0.0_WP +#if defined ( __usetp) + if (my_fesom_group==0) then +#endif + if (mype==0) then + write (i_string, "(I4)") i + write (id_string, "(I4)") id + write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) + end if +#if defined ( __usetp) + endif !(my_fesom_group==0) then +#endif + CASE (1305:1321) + tracers%data(i)%values(:,:)=0.0_WP +#if defined ( __usetp) + if (my_fesom_group==0) then +#endif + if (mype==0) then + write (i_string, "(I4)") i + write (id_string, "(I4)") id + write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) + end if +#if defined ( __usetp) + endif !(my_fesom_group==0) then +#endif +! Radiocarbon + CASE (1402) + tracers%data(i)%values(:,:)=0.0_WP +#if defined ( __usetp) + if (my_fesom_group==0) then +#endif + if (mype==0) then + write (i_string, "(I4)") i + write (id_string, "(I4)") id + write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) + end if +#if defined ( __usetp) + endif !(my_fesom_group==0) then +#endif + CASE (1405:1421) + tracers%data(i)%values(:,:)=0.0_WP +#if defined ( __usetp) + if (my_fesom_group==0) then +#endif + if (mype==0) then + write (i_string, "(I4)") i + write (id_string, "(I4)") id + write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) + end if +#if defined ( __usetp) + endif !(my_fesom_group==0) then +#endif +! End of carbon isotopes section +!_______________________________________________________________________ CASE (101) ! initialize tracer ID=101 tracers%data(i)%values(:,:)=0.0_WP if (mype==0) then From 911fd3c0e9bdbc005742df809f5e043774b1a5b6 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 24 Jan 2025 12:00:41 +0100 Subject: [PATCH 02/68] change defined(__recom)||defined(__usetp) to only defined(__usetp) in io_restart.F90 --- src/io_restart.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 9c7f9fa35..63a82e7ad 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -272,7 +272,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr logical, save :: initialized_bin = .false. ! integer mpierr -#if defined(__recom) || defined ( __usetp) +#if defined ( __usetp) ! kh 31.03.22 integer :: tr_arr_slice_count_fix_1 integer :: group_i @@ -291,7 +291,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr integer :: cstep -#if defined(__recom) || defined ( __usetp) +#if defined ( __usetp) ! kh 31.03.22 nl is required #include "associate_part_def.h" #include "associate_mesh_def.h" From 358082d6c8994833ed11bf5d98f2d34e7d9c9807 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Mon, 27 Jan 2025 16:52:19 +0100 Subject: [PATCH 03/68] corrections to compile with tracer parallelisation on --- src/int_recom/recom_modules.F90 | 2 +- src/int_recom/recom_sinking.F90 | 112 ++++++++++++++------------------ src/io_restart.F90 | 24 +++---- src/oce_ale_tracer.F90 | 10 +-- 4 files changed, 66 insertions(+), 82 deletions(-) diff --git a/src/int_recom/recom_modules.F90 b/src/int_recom/recom_modules.F90 index c4113377c..ca4918da8 100644 --- a/src/int_recom/recom_modules.F90 +++ b/src/int_recom/recom_modules.F90 @@ -110,7 +110,7 @@ module recom_config 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_base_num = 22 ! standard tracers + integer :: bgc_base_num = 22 ! tracer number for case 2phy 1zoo 1det Integer :: diags3d_num = 28 ! 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 diff --git a/src/int_recom/recom_sinking.F90 b/src/int_recom/recom_sinking.F90 index fdebc604f..7b56314a8 100644 --- a/src/int_recom/recom_sinking.F90 +++ b/src/int_recom/recom_sinking.F90 @@ -142,18 +142,16 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1025 ) then !idetz2n Benthos(n,1)= Benthos(n,1) + add_benthos_2d(n) ![mmol] - if (use_MEDUSA) then +#if defined(__usetp) ! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Benthos_tr(n,1,tr_num)= Benthos_tr(n,1,tr_num) + add_benthos_2d(n) ![mmol] + + if (use_MEDUSA) then SinkFlx_tr(n,1,tr_num) = SinkFlx_tr(n,1,tr_num) + add_benthos_2d(n) / area(1,n)/dt ![mmol/m2] ! now SinkFlx hat the unit mmol/time step ! but mmol/m2/time is needed for MEDUSA: thus /area endif - !YY: check if benthos_tr should be needed for usetp - if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel - Benthos_tr(n,1,tr_num)= Benthos_tr(n,1,tr_num) + add_benthos_2d(n) ![mmol] - endif - +#endif endif !! * Particulate Organic Carbon * @@ -163,15 +161,13 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1026 ) then !idetz2c Benthos(n,2)= Benthos(n,2) + add_benthos_2d(n) +#if defined(__usetp) + Benthos_tr(n,2,tr_num)= Benthos_tr(n,2,tr_num) + add_benthos_2d(n) + if (use_MEDUSA) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel SinkFlx_tr(n,2,tr_num) = SinkFlx_tr(n,2,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif - if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel - Benthos_tr(n,2,tr_num)= Benthos_tr(n,2,tr_num) + add_benthos_2d(n) - endif - +#endif endif !! *Particulate Organic Silicon * @@ -180,15 +176,13 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1027 ) then !idetz2si Benthos(n,3)= Benthos(n,3) + add_benthos_2d(n) +#if defined(__usetp) + Benthos_tr(n,3,tr_num)= Benthos_tr(n,3,tr_num) + add_benthos_2d(n) + if (use_MEDUSA) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel SinkFlx_tr(n,3,tr_num) = SinkFlx_tr(n,3,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif - if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel - Benthos_tr(n,3,tr_num)= Benthos_tr(n,3,tr_num) + add_benthos_2d(n) - endif - +#endif endif !! * Cal * @@ -197,95 +191,85 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) tracers%data(tr_num)%ID==1028 ) then !idetz2cal Benthos(n,4)= Benthos(n,4) + add_benthos_2d(n) +#if defined(__usetp) + Benthos_tr(n,4,tr_num)= Benthos_tr(n,4,tr_num) + add_benthos_2d(n) + if (use_MEDUSA) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel SinkFlx_tr(n,4,tr_num) = SinkFlx_tr(n,4,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif - if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel - Benthos_tr(n,4,tr_num)= Benthos_tr(n,4,tr_num) + add_benthos_2d(n) - endif - +#endif 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 + tracers%data(tr_num)%ID==1314 ) then !idiac_13 + Benthos(n,5)= Benthos(n,5) + add_benthos_2d(n) +#if defined(__usetp) + Benthos_tr(n,5,tr_num)= Benthos_tr(n,5,tr_num) + add_benthos_2d(n) if (use_MEDUSA) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel SinkFlx_tr(n,5,tr_num) = SinkFlx_tr(n,5,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif - if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel - Benthos_tr(n,5,tr_num)= Benthos_tr(n,5,tr_num) + add_benthos_2d(n) - endif - +#endif endif - if( tracers%data(tr_num)%ID==1320 .or. & !iphycal - tracers%data(tr_num)%ID==1321 ) then !idetcal + if( tracers%data(tr_num)%ID==1320 .or. & !iphycal_13 + tracers%data(tr_num)%ID==1321 ) then !idetcal_13 + Benthos(n,6)= Benthos(n,6) + add_benthos_2d(n) +#if defined(__usetp) + Benthos_tr(n,6,tr_num)= Benthos_tr(n,6,tr_num) + add_benthos_2d(n) if (use_MEDUSA) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel SinkFlx_tr(n,6,tr_num) = SinkFlx_tr(n,6,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif - if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel - Benthos_tr(n,6,tr_num)= Benthos_tr(n,6,tr_num) + add_benthos_2d(n) - endif - +#endif endif 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 + if( tracers%data(tr_num)%ID==1405 .or. & !iphyc_14 + tracers%data(tr_num)%ID==1408 .or. & !idetc_14 tracers%data(tr_num)%ID==1414 ) then !idiac_14 + Benthos(n,7)= Benthos(n,7) + add_benthos_2d(n) +#if defined(__usetp) + Benthos_tr(n,7,tr_num)= Benthos_tr(n,7,tr_num) + add_benthos_2d(n) if (use_MEDUSA) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel SinkFlx_tr(n,7,tr_num) = SinkFlx_tr(n,7,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif - if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel - Benthos_tr(n,7,tr_num)= Benthos_tr(n,7,tr_num) + add_benthos_2d(n) - endif - +#endif endif - if( tracers%data(tr_num)%ID==1420 .or. & !iphycal - tracers%data(tr_num)%ID==1421 ) then !idetcal + if( tracers%data(tr_num)%ID==1420 .or. & !iphycal_14 + tracers%data(tr_num)%ID==1421 ) then !idetcal_14 + Benthos(n,8)= Benthos(n,8) + add_benthos_2d(n) +#if defined(__usetp) + Benthos_tr(n,8,tr_num)= Benthos_tr(n,8,tr_num) + add_benthos_2d(n) if (use_MEDUSA) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel SinkFlx_tr(n,8,tr_num) = SinkFlx_tr(n,8,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif - if ((.not.use_MEDUSA).or.(sedflx_num.eq.0)) then -! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel - Benthos_tr(n,8,tr_num)= Benthos_tr(n,8,tr_num) + add_benthos_2d(n) - endif +#endif endif - endif end do +#if defined(__usetp) 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 +#endif 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 +#if defined(__usetp) call exchange_nod(Benthos_tr(:,n,tr_num), partit) - +#endif call exchange_nod(Benthos(:,n), partit) end do @@ -605,7 +589,7 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) endif #endif - end do + end do !nz=nzmin,nzmax+1 dt_sink = dt vd_flux = 0.0d0 @@ -646,7 +630,7 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) tv= (0.5 * wPs * (trarr(nz,n) + psiM * Rj)+ & 0.5 * wM * (trarr(max(nzmin,nz-1),n) + psiP * Rj)) vd_flux(nz)= - tv*area(nz,n) - end do + end do !nz=nzmax, nzmin+1,-1 end if ! 3rd Order DST Sceheme with flux limiting if (.FALSE.) then ! simple upwind @@ -670,12 +654,12 @@ subroutine ver_sinking_recom(tr_num, tracers, partit, mesh) trarr(nz ,n)*(Wvel_flux(nz)+abs(Wvel_flux(nz)))) vd_flux(nz)= tv*area(nz,n) - end do + end do !nz=nzmin+1,nzmax end if ! simple upwind do nz=nzmin,nzmax vert_sink(nz,n) = vert_sink(nz,n) + (vd_flux(nz)-vd_flux(nz+1))*dt/areasvol(nz,n)/hnode_new(nz,n) !/(zbar_3d_n(nz,n)-zbar_3d_n(nz+1,n)) end do - end do + end do !n = 1,myDim_nod2D end if ! Vsink .gt. 0.1 end subroutine ver_sinking_recom diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 63a82e7ad..b91cd3e53 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -309,15 +309,15 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr if(raw_restart_length_unit /= "off") then #if defined(__recom) & defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG master rank creates the folder + if(partit%my_fesom_group == 0) then ! OG master rank creates the folder #endif - if(partit%mype == RAW_RESTART_METADATA_RANK) then + if(partit%mype == RAW_RESTART_METADATA_RANK) then ! execute_command_line with mkdir sometimes fails, use a custom implementation around mkdir from C instead - call mkdir(trim(ResultPath)//"fesom_raw_restart") ! we have no mkdir -p, create the intermediate dirs separately - call mkdir(raw_restart_dirpath) - end if + call mkdir(trim(ResultPath)//"fesom_raw_restart") ! we have no mkdir -p, create the intermediate dirs separately + call mkdir(raw_restart_dirpath) + end if #if defined(__recom) & defined(__usetp) - end if ! (my_fesom_group == 0) then + end if ! (my_fesom_group == 0) then #endif call MPI_Barrier(partit%MPI_COMM_FESOM, mpierr) ! make sure the dir has been created before we continue... end if @@ -331,15 +331,15 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr bin_restart_infopath = trim(ResultPath)//"fesom_bin_restart/np"//int_to_txt(partit%npes)//".info" if(bin_restart_length_unit /= "off") then #if defined(__recom) & defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG + if(partit%my_fesom_group == 0) then ! OG #endif - if(partit%mype == RAW_RESTART_METADATA_RANK) then + if(partit%mype == RAW_RESTART_METADATA_RANK) then ! execute_command_line with mkdir sometimes fails, use a custom implementation around mkdir from C instead - call mkdir(trim(ResultPath)//"fesom_bin_restart") ! we have no mkdir -p, create the intermediate dirs separately - call mkdir(bin_restart_dirpath) - end if + call mkdir(trim(ResultPath)//"fesom_bin_restart") ! we have no mkdir -p, create the intermediate dirs separately + call mkdir(bin_restart_dirpath) + end if #if defined(__recom) & defined(__usetp) - end if ! (my_fesom_group == 0) then + end if ! (my_fesom_group == 0) then #endif call MPI_Barrier(partit%MPI_COMM_FESOM, mpierr) ! make sure the dir has been created before we continue... end if diff --git a/src/oce_ale_tracer.F90 b/src/oce_ale_tracer.F90 index 028d43550..64577ff16 100644 --- a/src/oce_ale_tracer.F90 +++ b/src/oce_ale_tracer.F90 @@ -176,7 +176,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) type(t_partit), intent(inout), target :: partit type(t_mesh) , intent(in) , target :: mesh -#if defined(__recom) || defined ( __usetp) +#if defined ( __usetp) ! kh 11.11.21 multi FESOM group loop parallelization integer :: num_tracers integer :: tr_num_start_memo @@ -230,7 +230,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) end if del_ttf => tracers%work%del_ttf -#if defined(__recom) || defined ( __usetp) +#if defined ( __usetp) num_tracers=tracers%num_tracers #endif @@ -465,7 +465,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) end if ! (num_fesom_groups > 1) then #endif -#if defined(__recom) +#if defined(__usetp) ! kh 25.03.22 SinkFlx and Benthos values are buffered per tracer index in the loop above and now summed up to ! avoid non bit identical results regarding global sums when running the tracer loop in parallel do tr_num = 1, num_tracers @@ -1840,7 +1840,7 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit) ! bc_surface=0.0_WP CASE (1023:1033) bc_surface=0.0_WP ! OG added bc for recom fields - CASE (1302) ! Before (1033) ! DIC_13 + CASE (1302) if (ciso) then if (use_MEDUSA .and. add_loopback) then bc_surface= dt*(GloCO2flux_seaicemask_13(n) & @@ -1853,7 +1853,7 @@ FUNCTION bc_surface(n, id, sval, nzmin, partit) end if CASE (1305:1321) bc_surface=0.0_WP ! organic 13C - CASE (1402) ! Before (1034) ! DIC_14 + CASE (1402) if (ciso .and. ciso_14) then if (use_MEDUSA .and. add_loopback .and. ciso_organic_14) then bc_surface= dt*(GloCO2flux_seaicemask_14(n) & From 0d3834a271744b4f2e203f0fc2c74b4d7c4e3e96 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 29 Jan 2025 16:52:57 +0100 Subject: [PATCH 04/68] cleanup and small corrections of flags for recom and tracer parallelisation --- src/CMakeLists.txt | 4 +- src/MOD_PARTIT.F90 | 4 +- src/associate_part_ass.h | 4 +- src/associate_part_def.h | 4 +- src/cpl_driver.F90 | 24 ++++++------ src/fesom_module.F90 | 74 +++++++++++++++++++------------------ src/gen_forcing_couple.F90 | 14 +++---- src/gen_model_setup.F90 | 2 +- src/gen_modules_config.F90 | 2 +- src/gen_surface_forcing.F90 | 2 +- src/io_restart.F90 | 54 +++++++++++++-------------- src/oce_ale.F90 | 8 ++-- src/oce_ale_tracer.F90 | 14 +++---- src/oce_mesh.F90 | 6 +++ src/oce_modules.F90 | 2 +- src/oce_setup_step.F90 | 40 ++++++++++---------- 16 files changed, 134 insertions(+), 124 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f19e11403..4b4610718 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -237,7 +237,9 @@ if(OPENMP_REPRODUCIBLE) endif() if(${RECOM_COUPLED}) - target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __usetp) #__3Zoo2Det __coccos) +# target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __usetp) +# target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2) + target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __3Zoo2Det __coccos __usetp) endif() if(${CISO_COUPLED}) diff --git a/src/MOD_PARTIT.F90 b/src/MOD_PARTIT.F90 index 07cba793f..29dc44327 100644 --- a/src/MOD_PARTIT.F90 +++ b/src/MOD_PARTIT.F90 @@ -71,7 +71,7 @@ module MOD_PARTIT integer :: MPI_COMM_FESOM ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) integer :: MPI_COMM_WORLD ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 11.11.21 communicator for multi FESOM group loop parallelization integer :: MPI_COMM_FESOM_WORLD @@ -96,7 +96,7 @@ module MOD_PARTIT integer :: MPIERR -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 11.11.21 multi FESOM group loop parallelization integer :: my_fesom_group #endif diff --git a/src/associate_part_ass.h b/src/associate_part_ass.h index d3d5963c6..f8065f592 100644 --- a/src/associate_part_ass.h +++ b/src/associate_part_ass.h @@ -1,4 +1,4 @@ -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) MPI_COMM_FESOM_WORLD => partit%MPI_COMM_FESOM_WORLD MPI_COMM_FESOM_SAME_RANK_IN_GROUPS => partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS #endif @@ -20,7 +20,7 @@ MPIERR => partit%MPIERR MPIERR_IB => partit%MPIERR_IB npes => partit%npes mype => partit%mype -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) my_fesom_group => my_fesom_group #endif maxPEnum => partit%maxPEnum diff --git a/src/associate_part_def.h b/src/associate_part_def.h index 05e9e32b1..3d4f75334 100644 --- a/src/associate_part_def.h +++ b/src/associate_part_def.h @@ -1,4 +1,4 @@ -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) integer, pointer :: MPI_COMM_FESOM_WORLD integer, pointer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS #endif @@ -24,7 +24,7 @@ integer, pointer :: MPIERR_IB ! copy for icebergs LA: 2023-05-22 integer, pointer :: npes integer, pointer :: mype -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) integer, pointer :: my_fesom_group #endif integer, pointer :: maxPEnum diff --git a/src/cpl_driver.F90 b/src/cpl_driver.F90 index 58df2a5e6..af1e0a05f 100644 --- a/src/cpl_driver.F90 +++ b/src/cpl_driver.F90 @@ -14,7 +14,7 @@ module cpl_driver ! use mod_oasis ! oasis module use g_config, only : dt, use_icebergs, lwiso -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) use g_config, only : num_fesom_groups ! kh 03.12.21 OG 08.09.23 #endif use o_param, only : rad @@ -314,7 +314,7 @@ subroutine node_contours(my_x_corners, my_y_corners, partit, mesh) end subroutine node_contours ! kh 02.12.21 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) subroutine cpl_oasis3mct_init(partit, localCommunicator, num_fesom_groups) #else subroutine cpl_oasis3mct_init(partit, localCommunicator) @@ -333,7 +333,7 @@ subroutine cpl_oasis3mct_init(partit, localCommunicator) ! integer, intent(OUT) :: localCommunicator type(t_partit), intent(inout), target :: partit -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 02.12.21 integer, intent(inout) :: num_fesom_groups #endif @@ -359,7 +359,7 @@ subroutine cpl_oasis3mct_init(partit, localCommunicator) ! 1st Initialize the OASIS3-MCT coupling system for the application !------------------------------------------------------------------ ! kh 02.12.21 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) CALL oasis_init_comp(comp_id, comp_name, ierror, num_program_groups = num_fesom_groups) #else CALL oasis_init_comp(comp_id, comp_name, ierror ) @@ -375,7 +375,7 @@ subroutine cpl_oasis3mct_init(partit, localCommunicator) ENDIF ! kh 02.12.21 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) CALL oasis_get_localcomm_all_groups( localCommunicator, ierror ) #else CALL oasis_get_localcomm( localCommunicator, ierror ) @@ -630,7 +630,7 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) endif ! kh 30.11.21 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if(my_fesom_group == 0) then #endif @@ -660,7 +660,7 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) print *, 'FESOM after terminate_grids_writing' endif !localroot -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if !(my_fesom_group == 0) then #endif @@ -931,14 +931,14 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) endif #endif -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 06.12.21 the coupling is in principle as it was before, i.e. the fesom processes - in group 0 - receive their data from echam if(my_fesom_group == 0) then #endif call oasis_get(recv_id(ind), seconds_til_now, exfld,info) -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) else ! kh 06.12.21 defensive: assignment statement "action=(info==3 ..." below is "don't care" in this case, because the actual value for action @@ -955,7 +955,7 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) ! and delivered back to FESOM. action=(info==3 .OR. info==10 .OR. info==11 .OR. info==12 .OR. info==13) -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 03.12.21 if(num_fesom_groups > 1) then call MPI_Bcast(action, 1, MPI_LOGICAL, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) @@ -963,12 +963,12 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) #endif if (action) then -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 03.12.21 if(my_fesom_group == 0) then #endif data_array(1:partit%myDim_nod2d) = exfld -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if ! kh 03.12.21 diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index dafc13eca..557707206 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -60,7 +60,7 @@ module fesom_main_storage_module integer :: which_readr ! read which restart files (0=netcdf, 1=core dump,2=dtype) integer :: total_nsteps integer, pointer :: mype, npes, MPIerr, MPI_COMM_FESOM, MPI_COMM_WORLD, MPI_COMM_FESOM_IB -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) integer, pointer :: my_fesom_group, MPI_COMM_FESOM_WORLD, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS #endif real(kind=WP) :: t0, t1, t2, t3, t4, t5, t6, t7, t8, t0_ice, t1_ice, t0_frc, t1_frc @@ -120,7 +120,7 @@ subroutine fesom_init(fesom_total_nsteps) logical mpi_is_initialized integer :: tr_num -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 11.11.21 multi FESOM group loop parallelization integer :: npes_fesom_world integer :: mype_fesom_world @@ -130,6 +130,8 @@ subroutine fesom_init(fesom_total_nsteps) ! kh 26.11.21 get current value for num_fesom_groups call read_namelist_run_config + print *,"reading number of tracer groups " + #endif #if !defined __ifsinterface @@ -165,7 +167,7 @@ subroutine fesom_init(fesom_total_nsteps) #if defined (__oasis) ! call cpl_oasis3mct_init(f%partit,f%partit%MPI_COMM_FESOM) ! kh 02.12.21 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) call cpl_oasis3mct_init(f%partit, f%partit%localCommunicator, num_fesom_groups) #else call cpl_oasis3mct_init(f%partit, f%partit%localCommunicator) @@ -183,7 +185,7 @@ subroutine fesom_init(fesom_total_nsteps) f%npes =>f%partit%npes -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 26.11.21 prepare communicator splitting for multi FESOM group loop parallelization f%my_fesom_group=>f%partit%my_fesom_group @@ -295,7 +297,7 @@ subroutine fesom_init(fesom_total_nsteps) print *, achar(27)//'[7;32m'//' --> FESOM BUILDS UP MODEL CONFIGURATION '//achar(27)//'[0m' end if -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -312,13 +314,13 @@ subroutine fesom_init(fesom_total_nsteps) call mesh_setup(f%partit, f%mesh) ! kh 29.02.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif if (f%mype==0) write(*,*) 'FESOM mesh_setup... complete' -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -384,13 +386,13 @@ subroutine fesom_init(fesom_total_nsteps) if (f%mype==0) then ! kh 29.02.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif write(*,*) 'FESOM ocean_setup... complete' -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -440,7 +442,7 @@ subroutine fesom_init(fesom_total_nsteps) #if defined (__oasis) ! kh 30.11.21 only mype == 0 in my_fesom_group == 0 handles coupling with extern models -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif @@ -448,11 +450,11 @@ subroutine fesom_init(fesom_total_nsteps) if(f%mype==0) write(*,*) 'FESOM ----> cpl_oasis3mct_define_unstr nsend, nrecv:',nsend, nrecv -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 03.12.21 ! call MPI_Barrier(f%MPI_COMM_FESOM_WORLD, f%MPIERR) if(num_fesom_groups > 1) then @@ -492,14 +494,14 @@ subroutine fesom_init(fesom_total_nsteps) ! store grid information into netcdf file ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif if (.not. r_restart) call write_mesh_info(f%partit, f%mesh) ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -523,7 +525,7 @@ subroutine fesom_init(fesom_total_nsteps) #endif ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif @@ -542,7 +544,7 @@ subroutine fesom_init(fesom_total_nsteps) write(*,*) '============================================' ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -673,14 +675,14 @@ subroutine fesom_runloop(current_nsteps) end if ! -------------- ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif if (f%mype==0) write(*,*) 'FESOM start iteration before the barrier...' ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -688,14 +690,14 @@ subroutine fesom_runloop(current_nsteps) if (f%mype==0) then ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif write(*,*) 'FESOM start iteration after the barrier...' ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -703,7 +705,7 @@ subroutine fesom_runloop(current_nsteps) endif ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif @@ -714,7 +716,7 @@ subroutine fesom_runloop(current_nsteps) end if ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -785,7 +787,7 @@ subroutine fesom_runloop(current_nsteps) mstep = n ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif @@ -797,7 +799,7 @@ subroutine fesom_runloop(current_nsteps) end if ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -877,33 +879,33 @@ subroutine fesom_runloop(current_nsteps) #endif !___model ocean step____________________________________________________ -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call oce_timestep_ale'//achar(27)//'[0m' -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif call oce_timestep_ale(n, f%ice, f%dynamics, f%tracers, f%partit, f%mesh) f%t3 = MPI_Wtime() !___compute energy diagnostics..._______________________________________ -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call compute_diagnostics(1)'//achar(27)//'[0m' -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif call compute_diagnostics(1, f%dynamics, f%tracers, f%ice, f%partit, f%mesh) f%t4 = MPI_Wtime() !___prepare output______________________________________________________ -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call output (n)'//achar(27)//'[0m' -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif call output (n, f%ice, f%dynamics, f%tracers, f%partit, f%mesh) @@ -951,7 +953,7 @@ subroutine fesom_finalize() end if ! -------------- ! kh 11.11.21 multi FESOM group loop parallelization -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif @@ -959,7 +961,7 @@ subroutine fesom_finalize() call finalize_restart() ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif @@ -969,7 +971,7 @@ subroutine fesom_finalize() ! kh 11.11.21 multi FESOM group loop parallelization call MPI_Barrier(f%MPI_COMM_FESOM, f%MPIERR) #endif -#if defined (__usetp) +#if defined(__recom) && defined (__usetp) ! kh 11.11.21 list statistics for all fesom_groups ! fesom groups are listed backwards, so info for the main fesom group 0 is at the end in the log do i = num_fesom_groups - 1, 0, -1 @@ -1069,7 +1071,7 @@ subroutine fesom_finalize() call par_ex(f%partit%MPI_COMM_FESOM, f%partit%mype) #endif -#if defined (__usetp) +#if defined(__recom) && defined (__usetp) end if end do ! i = num_fesom_groups - 1, 0, -1 #endif @@ -1079,7 +1081,7 @@ subroutine fesom_finalize() #endif if(f%fesom_did_mpi_init) call par_ex(f%partit%MPI_COMM_FESOM, f%partit%mype) ! finalize MPI before FESOM prints its stats block, otherwise there is sometimes output from other processes from an earlier time in the programm AFTER the starts block (with parastationMPI) -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif @@ -1123,7 +1125,7 @@ subroutine fesom_finalize() end if ! kh 29.03.22 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) end if #endif diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index af59bafe7..986444e2e 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -271,11 +271,11 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) endif ! kh 30.11.21 -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if(my_fesom_group == 0) then #endif call cpl_oasis3mct_send(i, exchange, action, partit) -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) endif #endif end do @@ -844,7 +844,7 @@ SUBROUTINE net_rec_from_atm(action, partit) USE MOD_PARSUP IMPLICIT NONE -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 10.21.21 use g_config, only: num_fesom_groups #endif @@ -852,7 +852,7 @@ SUBROUTINE net_rec_from_atm(action, partit) LOGICAL, INTENT (IN) :: action type(t_partit), intent(inout), target :: partit INTEGER :: my_global_rank, ierror -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 10.12.21 INTEGER :: my_global_rank_test #endif @@ -868,12 +868,12 @@ SUBROUTINE net_rec_from_atm(action, partit) CALL MPI_COMM_RANK(MPI_COMM_WORLD, my_global_rank, ierror) atm_net_fluxes_north=0. atm_net_fluxes_south=0. -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 10.12.21 my_global_rank_test = my_global_rank - (my_fesom_group * npes) #endif -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 10.12.21 check for is root in group if (my_global_rank_test==target_root) then if(my_fesom_group == 0) then @@ -885,7 +885,7 @@ SUBROUTINE net_rec_from_atm(action, partit) CALL MPI_Waitall(2, request, status, partit%MPIerr) end if -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if(num_fesom_groups > 1) then call MPI_Bcast(atm_net_fluxes_north(1), nrecv, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) call MPI_Bcast(atm_net_fluxes_south(1), nrecv, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index 47d95f718..deaa3a789 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -176,7 +176,7 @@ subroutine setup_model(partit) end subroutine setup_model -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 11.11.21 read num_fesom_groups for multi FESOM group loop parallelization ! ================================================================= subroutine read_namelist_run_config(partit) diff --git a/src/gen_modules_config.F90 b/src/gen_modules_config.F90 index 8f6a06e22..d557ed771 100755 --- a/src/gen_modules_config.F90 +++ b/src/gen_modules_config.F90 @@ -152,7 +152,7 @@ module g_config use_cavity_fw2press, toy_ocean, which_toy, flag_debug, flag_warn_cflz, lwiso, & use_transit -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 11.11.21 number of groups for multi FESOM group loop parallelization integer :: num_fesom_groups=1 namelist /run_config_tp/ num_fesom_groups diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index b312fe69f..1600b9639 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -1433,7 +1433,7 @@ SUBROUTINE sbc_do(partit, mesh) end if -#if defined (__recom) +#if defined(__recom) !< read surface atmospheric deposition for Fe, N, CO2 if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Atm_input'//achar(27)//'[0m' diff --git a/src/io_restart.F90 b/src/io_restart.F90 index b91cd3e53..03c2c087a 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -272,7 +272,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr logical, save :: initialized_bin = .false. ! integer mpierr -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) ! kh 31.03.22 integer :: tr_arr_slice_count_fix_1 integer :: group_i @@ -291,7 +291,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr integer :: cstep -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) ! kh 31.03.22 nl is required #include "associate_part_def.h" #include "associate_mesh_def.h" @@ -308,7 +308,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr raw_restart_infopath = trim(ResultPath)//"fesom_raw_restart/np"//int_to_txt(partit%npes)//".info" if(raw_restart_length_unit /= "off") then -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then ! OG master rank creates the folder #endif if(partit%mype == RAW_RESTART_METADATA_RANK) then @@ -316,10 +316,10 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr call mkdir(trim(ResultPath)//"fesom_raw_restart") ! we have no mkdir -p, create the intermediate dirs separately call mkdir(raw_restart_dirpath) end if -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) end if ! (my_fesom_group == 0) then #endif - call MPI_Barrier(partit%MPI_COMM_FESOM, mpierr) ! make sure the dir has been created before we continue... + call MPI_Barrier(partit%MPI_COMM_FESOM, partit%mpierr) ! make sure the dir has been created before we continue... end if end if @@ -330,7 +330,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr bin_restart_dirpath = trim(ResultPath)//"fesom_bin_restart/np"//int_to_txt(partit%npes) bin_restart_infopath = trim(ResultPath)//"fesom_bin_restart/np"//int_to_txt(partit%npes)//".info" if(bin_restart_length_unit /= "off") then -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then ! OG #endif if(partit%mype == RAW_RESTART_METADATA_RANK) then @@ -338,10 +338,10 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr call mkdir(trim(ResultPath)//"fesom_bin_restart") ! we have no mkdir -p, create the intermediate dirs separately call mkdir(bin_restart_dirpath) end if -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) end if ! (my_fesom_group == 0) then #endif - call MPI_Barrier(partit%MPI_COMM_FESOM, mpierr) ! make sure the dir has been created before we continue... + call MPI_Barrier(partit%MPI_COMM_FESOM, partit%mpierr) ! make sure the dir has been created before we continue... end if end if @@ -375,13 +375,13 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr if(partit%mype == RAW_RESTART_METADATA_RANK) then inquire(file=raw_restart_infopath, exist=rawfiles_exist) end if - call MPI_Bcast(rawfiles_exist, 1, MPI_LOGICAL, RAW_RESTART_METADATA_RANK, partit%MPI_COMM_FESOM, mpierr) + call MPI_Bcast(rawfiles_exist, 1, MPI_LOGICAL, RAW_RESTART_METADATA_RANK, partit%MPI_COMM_FESOM, partit%mpierr) ! check if folder for derived type binary restarts exist if(partit%mype == RAW_RESTART_METADATA_RANK) then inquire(file=bin_restart_infopath, exist=binfiles_exist) end if - call MPI_Bcast(binfiles_exist, 1, MPI_LOGICAL, RAW_RESTART_METADATA_RANK, partit%MPI_COMM_FESOM, mpierr) + call MPI_Bcast(binfiles_exist, 1, MPI_LOGICAL, RAW_RESTART_METADATA_RANK, partit%MPI_COMM_FESOM, partit%mpierr) !___________________________________________________________________________ ! read core dump file restart @@ -411,20 +411,20 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! read netcdf file restart else which_readr = 0 -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then !OG #endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: ocean'//achar(27)//'[0m' -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) endif !(partit%my_fesom_group == 0) then ! OG #endif call read_restart(oce_path, oce_files, partit%MPI_COMM_FESOM, partit%mype) if (use_ice) then -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then ! OG #endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: ice'//achar(27)//'[0m' -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) endif !(partit%my_fesom_group == 0) then ! OG #endif call read_restart(ice_path, ice_files, partit%MPI_COMM_FESOM, partit%mype) @@ -447,11 +447,11 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! immediately create a raw core dump restart if(raw_restart_length_unit /= "off") then -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then ! OG master rank reads #endif call write_all_raw_restarts(istep, partit%MPI_COMM_FESOM, partit%mype) -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) end if ! (my_fesom_group == 0) then #endif end if @@ -459,7 +459,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! immediately create a derived type binary restart if(bin_restart_length_unit /= "off") then ! current (total) model step --> cstep = globalstep+istep -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then ! OG #endif call write_all_bin_restarts((/globalstep+istep, int(ctime), yearnew/), & @@ -470,7 +470,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ice, & dynamics, & tracers ) -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) end if ! (my_fesom_group == 0) then #endif end if @@ -502,7 +502,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr is_bin_restart_write = is_due(trim(bin_restart_length_unit), bin_restart_length, istep) end if -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) if(num_fesom_groups > 1) then tr_arr_slice_count_fix_1 = 1 * (nl - 1) * (myDim_nod2D + eDim_nod2D) @@ -518,22 +518,22 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! finally write restart for netcdf, core dump and derived type binary ! write netcdf restart if(is_portable_restart_write) then -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then #endif ! if(partit%mype==0) write(*,*)'Do output (netCDF, restart) ...' if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: ocean'//achar(27)//'[0m' -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) endif !(partit%my_fesom_group == 0) then #endif call write_restart(oce_path, oce_files, istep) if(use_ice) then -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then #endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: ice'//achar(27)//'[0m' -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) endif !(partit%my_fesom_group == 0) then #endif call write_restart(ice_path, ice_files, istep) @@ -559,13 +559,13 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! write core dump if(is_raw_restart_write) then -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then ! OG master rank reads #endif call write_all_raw_restarts(istep, partit%MPI_COMM_FESOM, partit%mype) -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) end if ! (my_fesom_group == 0) then #endif @@ -575,7 +575,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr if(is_bin_restart_write) then ! current (total) model step --> cstep = globalstep+istep -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then ! OG master rank reads #endif @@ -597,7 +597,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr end if end if -#if defined(__recom) & defined(__usetp) +#if defined(__recom) && defined(__usetp) end if ! (my_fesom_group == 0) then #endif diff --git a/src/oce_ale.F90 b/src/oce_ale.F90 index 0a1a10570..30dc7d793 100644 --- a/src/oce_ale.F90 +++ b/src/oce_ale.F90 @@ -3757,7 +3757,7 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) !___________________________________________________________________________ ! write out global fields for debugging if (flag_debug .and. mype==0) print *, achar(27)//'[36m'//' --> call write_step_info'//achar(27)//'[0m' -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 19.11.21 if(partit%my_fesom_group == 0) then #endif @@ -3773,7 +3773,7 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) ! togeather around 2.5% of model runtime if (flag_debug .and. mype==0) print *, achar(27)//'[36m'//' --> call check_blowup'//achar(27)//'[0m' call check_blowup(n, ice, dynamics, tracers, partit, mesh) -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) endif #endif @@ -3790,7 +3790,7 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) rtime_oce_solvetra = rtime_oce_solvetra + (t8-t7) rtime_tot = rtime_tot + (t10-t0)-(t10-t9) -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 19.11.21 if(partit%my_fesom_group == 0) then #endif @@ -3813,7 +3813,7 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) write(*,*) write(*,*) end if -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) endif #endif diff --git a/src/oce_ale_tracer.F90 b/src/oce_ale_tracer.F90 index 64577ff16..82e1ed93b 100644 --- a/src/oce_ale_tracer.F90 +++ b/src/oce_ale_tracer.F90 @@ -176,7 +176,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) type(t_partit), intent(inout), target :: partit type(t_mesh) , intent(in) , target :: mesh -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) ! kh 11.11.21 multi FESOM group loop parallelization integer :: num_tracers integer :: tr_num_start_memo @@ -230,7 +230,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) end if del_ttf => tracers%work%del_ttf -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) num_tracers=tracers%num_tracers #endif @@ -270,7 +270,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) !!! !$ACC UPDATE DEVICE(tracers%work%fct_ttf_min, tracers%work%fct_ttf_max, tracers%work%fct_plus, tracers%work%fct_minus) !$ACC UPDATE DEVICE (mesh%helem, mesh%hnode, mesh%hnode_new, mesh%zbar_3d_n, mesh%z_3d_n) -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 11.11.21 multi FESOM group loop parallelization call calc_slice(num_tracers, num_fesom_groups, partit%my_fesom_group, tr_num_start, tr_num_end, tr_num_in_group_dummy, has_one_added_tracer) @@ -287,7 +287,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) request_count = 0 #endif -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) do tr_num = tr_num_start, tr_num_end #else do tr_num=1, tracers%num_tracers @@ -393,7 +393,7 @@ 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(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 19.11.21 broadcast tracer results to fesom groups if(num_fesom_groups > 1) then @@ -423,7 +423,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) #endif end do ! tr_num = tr_num_start, tr_num_end -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 19.11.21 if tracer in group was added to compensate for fragmentation its broadcast of the last index is handled here if(num_fesom_groups > 1) then do group_i = 0, num_fesom_groups - 1 @@ -465,7 +465,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) end if ! (num_fesom_groups > 1) then #endif -#if defined(__usetp) +#if defined(__recom) && defined(__usetp) ! kh 25.03.22 SinkFlx and Benthos values are buffered per tracer index in the loop above and now summed up to ! avoid non bit identical results regarding global sums when running the tracer loop in parallel do tr_num = 1, num_tracers diff --git a/src/oce_mesh.F90 b/src/oce_mesh.F90 index 1843e345b..f3eab41f1 100755 --- a/src/oce_mesh.F90 +++ b/src/oce_mesh.F90 @@ -307,7 +307,13 @@ SUBROUTINE read_mesh(partit, mesh) read(fileID,*) n ! nod2D, we know it already error_status=0 if (n/=mesh%nod2D) error_status=1 !set the error status for consistency between rpart and nod2D +#if defined(__recom) && defined(__usetp) + if (partit%my_fesom_group==0) then +#endif write(*,*) 'reading '// trim(file_name) +#if defined(__recom) && defined(__usetp) + end if +#endif end if ! check the error status call MPI_BCast(error_status, 1, MPI_INTEGER, 0, MPI_COMM_FESOM, ierror) diff --git a/src/oce_modules.F90 b/src/oce_modules.F90 index 99ef44827..92d767fe0 100755 --- a/src/oce_modules.F90 +++ b/src/oce_modules.F90 @@ -220,7 +220,7 @@ MODULE o_ARRAYS #if defined(__recom) real(kind=WP), allocatable :: dtr_bf(:,:), str_bf(:,:) real(kind=WP), allocatable :: vert_sink(:,:) -#if defined ( __usetp) +#if defined(__usetp) ! kh 22.11.21 integer :: request_count integer, allocatable :: tr_arr_requests(:), tr_arr_old_requests(:) diff --git a/src/oce_setup_step.F90 b/src/oce_setup_step.F90 index e024cc353..9f1462504 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -811,7 +811,7 @@ SUBROUTINE arrays_init(num_tracers, partit, mesh) allocate(str_bf ( nl-1, node_size )) allocate(vert_sink ( nl-1, node_size )) allocate(Alk_surf ( node_size )) -#if defined (__usetp) +#if defined(__usetp) ! kh 22.11.21 allocate(tr_arr_requests(num_tracers), tr_arr_old_requests(num_tracers)) allocate(SinkFlx_tr_requests(num_tracers)) @@ -926,7 +926,7 @@ SUBROUTINE arrays_init(num_tracers, partit, mesh) str_bf = 0.0_WP vert_sink = 0.0_WP Alk_surf = 0.0_WP -#if defined (__usetp) +#if defined(__usetp) ! kh 23.03.22 tr_arr_requests = 0 tr_arr_old_requests = 0 @@ -1028,7 +1028,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) end if if (mype==0) then -#if defined (__usetp) +#if defined(__usetp) if (my_fesom_group==0) then #endif write(*,*) @@ -1055,7 +1055,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'read Nitrate climatology from:', trim(filelist(6)) write(*,*) 'read Salt climatology from:', trim(filelist(7)) write(*,*) 'read Temperature climatology from:', trim(filelist(8)) -#if defined ( __usetp) +#if defined(__usetp) end if ! (my_fesom_group==0) then #endif end if @@ -1096,13 +1096,13 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) #if defined(__recom) if (restore_alkalinity) then -#if defined ( __usetp) +#if defined(__usetp) if (my_fesom_group==0) then #endif if (mype==0) write(*,*) if (mype==0) print *, achar(27)//'[46;1m'//' --> Set surface field for alkalinity restoring'//achar(27)//'[0m' if (mype==0) write(*,*),'Alkalinity restoring = true. Field is read.' -#if defined ( __usetp) +#if defined(__usetp) endif !(my_fesom_group==0) then #endif @@ -1140,7 +1140,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) !_______________________________________________________________________ CASE (1004:1017) tracers%data(i)%values(:,:)=0.0_WP -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) if (my_fesom_group==0) then #endif if (mype==0) then @@ -1148,12 +1148,12 @@ 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 -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) endif !(my_fesom_group==0) then #endif CASE (1020:1021) tracers%data(i)%values(:,:)=0.0_WP -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) if (my_fesom_group==0) then #endif if (mype==0) then @@ -1161,12 +1161,12 @@ 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 -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) endif !(my_fesom_group==0) then #endif CASE (1023:1033) tracers%data(i)%values(:,:)=0.0_WP -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) if (my_fesom_group==0) then #endif if (mype==0) then @@ -1174,7 +1174,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 -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) endif !(my_fesom_group==0) then #endif !_______________________________________________________________________ @@ -1182,7 +1182,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) ! Carbon-13 CASE (1302) tracers%data(i)%values(:,:)=0.0_WP -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) if (my_fesom_group==0) then #endif if (mype==0) then @@ -1190,12 +1190,12 @@ 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 -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) endif !(my_fesom_group==0) then #endif CASE (1305:1321) tracers%data(i)%values(:,:)=0.0_WP -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) if (my_fesom_group==0) then #endif if (mype==0) then @@ -1203,13 +1203,13 @@ 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 -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) endif !(my_fesom_group==0) then #endif ! Radiocarbon CASE (1402) tracers%data(i)%values(:,:)=0.0_WP -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) if (my_fesom_group==0) then #endif if (mype==0) then @@ -1217,12 +1217,12 @@ 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 -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) endif !(my_fesom_group==0) then #endif CASE (1405:1421) tracers%data(i)%values(:,:)=0.0_WP -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) if (my_fesom_group==0) then #endif if (mype==0) then @@ -1230,7 +1230,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 -#if defined ( __usetp) +#if defined(__recom) && defined(__usetp) endif !(my_fesom_group==0) then #endif ! End of carbon isotopes section From 74a5e598e2721f15dfe283ca1d68e471c80e3040 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Thu, 30 Jan 2025 14:48:36 +0100 Subject: [PATCH 05/68] corrections in array allocation for Diags and initialization for use_atbox --- src/cpl_driver.F90 | 8 ++-- src/fesom_module.F90 | 2 - src/gen_surface_forcing.F90 | 1 - src/int_recom/recom_init.F90 | 82 +++++++++++++++++++++++++++++++++ src/int_recom/recom_main.F90 | 3 ++ src/int_recom/recom_sinking.F90 | 17 ++----- src/oce_setup_step.F90 | 36 +++++++-------- 7 files changed, 111 insertions(+), 38 deletions(-) diff --git a/src/cpl_driver.F90 b/src/cpl_driver.F90 index af1e0a05f..4b95c5799 100644 --- a/src/cpl_driver.F90 +++ b/src/cpl_driver.F90 @@ -631,7 +631,7 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) ! kh 30.11.21 #if defined(__recom) && defined(__usetp) - if(my_fesom_group == 0) then + if(partit%my_fesom_group == 0) then #endif if (mype .eq. localroot) then @@ -661,7 +661,7 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) endif !localroot #if defined(__recom) && defined(__usetp) - end if !(my_fesom_group == 0) then + end if !(partit%my_fesom_group == 0) then #endif @@ -933,7 +933,7 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) #if defined(__recom) && defined(__usetp) ! kh 06.12.21 the coupling is in principle as it was before, i.e. the fesom processes - in group 0 - receive their data from echam - if(my_fesom_group == 0) then + if(partit%my_fesom_group == 0) then #endif call oasis_get(recv_id(ind), seconds_til_now, exfld,info) @@ -965,7 +965,7 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) if (action) then #if defined(__recom) && defined(__usetp) ! kh 03.12.21 - if(my_fesom_group == 0) then + if(partit%my_fesom_group == 0) then #endif data_array(1:partit%myDim_nod2d) = exfld #if defined(__recom) && defined(__usetp) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 557707206..3171f64c7 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -130,8 +130,6 @@ subroutine fesom_init(fesom_total_nsteps) ! kh 26.11.21 get current value for num_fesom_groups call read_namelist_run_config - print *,"reading number of tracer groups " - #endif #if !defined __ifsinterface diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index 1600b9639..182ec3b77 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -1449,7 +1449,6 @@ SUBROUTINE sbc_do(partit, mesh) end if else ! Prescribed atmospheric CO2 values - if (constant_CO2) then AtmCO2(:) = CO2_for_spinup #if defined(__usetp) diff --git a/src/int_recom/recom_init.F90 b/src/int_recom/recom_init.F90 index e2b45b0ab..0186199c5 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -258,6 +258,88 @@ subroutine recom_init(tracers, partit, mesh) lb_flux(:,:) = 0.d0 end if + if (useRivFe) then + allocate(RiverFe ( node_size )) + RiverFe(:) = 0.d0 + end if + +! Atmospheric box model + if (use_atbox) then +! if (mype==0 .and. my_fesom_group == 0) print *, "Initializing the atmospheric isoCO2 box model ..." !OG + allocate(x_co2atm(node_size)) + x_co2atm = CO2_for_spinup + if (ciso) then + allocate(x_co2atm_13(node_size)) + r_atm_spinup_13 = 1. + 0.001 * delta_co2_13 + x_co2atm_13 = CO2_for_spinup * r_atm_spinup_13 + if (ciso_14) then + allocate(x_co2atm_14(node_size)) + allocate(cosmic_14(node_size)) + if (ciso_organic_14) then + delta_co2_14 = (big_delta_co2_14(1) + 2. * delta_co2_13 + 50.) / (0.95 - 0.002 * delta_co2_13) + else + delta_co2_14 = big_delta_co2_14(1) + end if + r_atm_spinup_14 = 1. + 0.001 * delta_co2_14 + x_co2atm_14 = CO2_for_spinup * r_atm_spinup_14 +! Conversion of initial cosmogenic 14C production rates (mol / s) to fluxes (atoms / s / cm**2) +! Since 14C values are scaled to 12C, we need to include the standard 14C / 12C ratio here: +! 1.176e-12 (Karlen et al., 1964) * 6.0221e23 (Avogadro constant) * 1.e-4 (cm**2 / m**2) +! = 7.0820e7 cm**2 / m**2 + production_rate_to_flux_14 = 7.0820e7 / ocean_area + cosmic_14 = cosmic_14_init / production_rate_to_flux_14 + end if + end if + end if ! use_atbox + + if (ciso) then +!! Define ciso variables assigning additional ciso tracer indices +! idic_13 = bgc_base_num + 1 +! iphyc_13 = bgc_base_num + 2 +! idetc_13 = bgc_base_num + 3 +! ihetc_13 = bgc_base_num + 4 +! idoc_13 = bgc_base_num + 5 +! idiac_13 = bgc_base_num + 6 +! iphycal_13 = bgc_base_num + 7 +! idetcal_13 = bgc_base_num + 8 +! idic_14 = bgc_base_num + 9 +! iphyc_14 = bgc_base_num + 10 +! idetc_14 = bgc_base_num + 11 +! ihetc_14 = bgc_base_num + 12 +! idoc_14 = bgc_base_num + 13 +! idiac_14 = bgc_base_num + 14 +! iphycal_14 = bgc_base_num + 15 +! idetcal_14 = bgc_base_num + 16 + + !< Allocate 13CO2 surface fields + allocate(GloPCO2surf_13 ( node_size )) + allocate(GloCO2flux_13 ( node_size )) + allocate(GloCO2flux_seaicemask_13 ( node_size )) + + GloPCO2surf_13 = 0.d0 + GloCO2flux_13 = 0.d0 + GloCO2flux_seaicemask_13 = 0.0d0 + + !< Allocate auxiliary inital delta13C_DIC field + allocate(delta_dic_13_init (nl-1, nod2D )) + + if (ciso_14) then + !< Allocate 14CO2 surface fields + allocate(GloPCO2surf_14 ( node_size )) + allocate(GloCO2flux_14 ( node_size )) + allocate(GloCO2flux_seaicemask_14 ( node_size )) + + GloPCO2surf_14 = 0.d0 + GloCO2flux_14 = 0.d0 + GloCO2flux_seaicemask_14 = 0.0d0 + + !< Allocate auxiliary inital d|Delta14C_DIC fields + allocate(delta_dic_14_init ( nl-1, nod2D )) + allocate(big_delta_dic_14_init ( nl-1, nod2D )) + end if ! ciso_14 + + end if ! ciso + DO i=num_tracers-bgc_num+1, num_tracers id=tracers%data(i)%ID diff --git a/src/int_recom/recom_main.F90 b/src/int_recom/recom_main.F90 index 34e759e87..c19041a81 100755 --- a/src/int_recom/recom_main.F90 +++ b/src/int_recom/recom_main.F90 @@ -391,12 +391,15 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) NPPc3D (1:nzmax,n) = vertNPPc (1:nzmax) #endif +!YY: why printing this? if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> ciso after REcoM_Forcing'//achar(27)//'[0m' !! * Deallocating 2D diagnostics * deallocate(vertNPPn, vertGPPn, vertNNAn, vertChldegn) deallocate(vertNPPd, vertGPPd, vertNNAd, vertChldegd) +#if defined (__coccos) deallocate(vertNPPc, vertGPPc, vertNNAc, vertChldegc) +#endif !! * Deallocating 3D Diagnostics * deallocate(vertrespmeso) diff --git a/src/int_recom/recom_sinking.F90 b/src/int_recom/recom_sinking.F90 index 7b56314a8..2cbbe48c4 100644 --- a/src/int_recom/recom_sinking.F90 +++ b/src/int_recom/recom_sinking.F90 @@ -41,11 +41,6 @@ subroutine ver_sinking_recom_benthos(tr_num, tracer, partit, mesh) end interface end module !=============================================================================== -! YY: sinking of second detritus adapted from Ozgur's code -! but not using recom_det_tracer_id, since -! second detritus has a different sinking speed than the first -! define recom_det2_tracer_id to make it consistent??? -!=============================================================================== subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) use MOD_MESH @@ -138,8 +133,7 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) !! * Particulate Organic Nitrogen * if( tracers%data(tr_num)%ID==1004 .or. & !iphyn tracers%data(tr_num)%ID==1007 .or. & !idetn - tracers%data(tr_num)%ID==1013 .or. & !idian - tracers%data(tr_num)%ID==1025 ) then !idetz2n + tracers%data(tr_num)%ID==1013 ) then !idian Benthos(n,1)= Benthos(n,1) + add_benthos_2d(n) ![mmol] #if defined(__usetp) @@ -157,8 +151,7 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) !! * Particulate Organic Carbon * if( tracers%data(tr_num)%ID==1005 .or. & !iphyc tracers%data(tr_num)%ID==1008 .or. & !idetc - tracers%data(tr_num)%ID==1014 .or. & !idiac - tracers%data(tr_num)%ID==1026 ) then !idetz2c + tracers%data(tr_num)%ID==1014 ) then Benthos(n,2)= Benthos(n,2) + add_benthos_2d(n) #if defined(__usetp) @@ -172,8 +165,7 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) !! *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 + tracers%data(tr_num)%ID==1017 ) then Benthos(n,3)= Benthos(n,3) + add_benthos_2d(n) #if defined(__usetp) @@ -187,8 +179,7 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) !! * 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 + tracers%data(tr_num)%ID==1021 ) then !idetcal Benthos(n,4)= Benthos(n,4) + add_benthos_2d(n) #if defined(__usetp) diff --git a/src/oce_setup_step.F90 b/src/oce_setup_step.F90 index 9f1462504..b7cab9719 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -1029,7 +1029,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) if (mype==0) then #if defined(__usetp) - if (my_fesom_group==0) then + if (partit%my_fesom_group==0) then #endif write(*,*) print *, achar(27)//'[36m'//'*************************'//achar(27)//'[0m' @@ -1056,7 +1056,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'read Salt climatology from:', trim(filelist(7)) write(*,*) 'read Temperature climatology from:', trim(filelist(8)) #if defined(__usetp) - end if ! (my_fesom_group==0) then + end if ! (partit%my_fesom_group==0) then #endif end if ! read ocean state @@ -1097,13 +1097,13 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) if (restore_alkalinity) then #if defined(__usetp) - if (my_fesom_group==0) then + if (partit%my_fesom_group==0) then #endif if (mype==0) write(*,*) if (mype==0) print *, achar(27)//'[46;1m'//' --> Set surface field for alkalinity restoring'//achar(27)//'[0m' if (mype==0) write(*,*),'Alkalinity restoring = true. Field is read.' #if defined(__usetp) - endif !(my_fesom_group==0) then + endif !(partit%my_fesom_group==0) then #endif Alk_surf = tracers%data(5)%values(1,:) ! alkalinity is the 5th tracer @@ -1141,7 +1141,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) CASE (1004:1017) tracers%data(i)%values(:,:)=0.0_WP #if defined(__recom) && defined(__usetp) - if (my_fesom_group==0) then + if (partit%my_fesom_group==0) then #endif if (mype==0) then write (i_string, "(I4)") i @@ -1149,12 +1149,12 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if #if defined(__recom) && defined(__usetp) - endif !(my_fesom_group==0) then + endif !(partit%my_fesom_group==0) then #endif CASE (1020:1021) tracers%data(i)%values(:,:)=0.0_WP #if defined(__recom) && defined(__usetp) - if (my_fesom_group==0) then + if (partit%my_fesom_group==0) then #endif if (mype==0) then write (i_string, "(I4)") i @@ -1162,12 +1162,12 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if #if defined(__recom) && defined(__usetp) - endif !(my_fesom_group==0) then + endif !(partit%my_fesom_group==0) then #endif CASE (1023:1033) tracers%data(i)%values(:,:)=0.0_WP #if defined(__recom) && defined(__usetp) - if (my_fesom_group==0) then + if (partit%my_fesom_group==0) then #endif if (mype==0) then write (i_string, "(I4)") i @@ -1175,7 +1175,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if #if defined(__recom) && defined(__usetp) - endif !(my_fesom_group==0) then + endif !(partit%my_fesom_group==0) then #endif !_______________________________________________________________________ ! Carbon isotopes @@ -1183,7 +1183,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) CASE (1302) tracers%data(i)%values(:,:)=0.0_WP #if defined(__recom) && defined(__usetp) - if (my_fesom_group==0) then + if (partit%my_fesom_group==0) then #endif if (mype==0) then write (i_string, "(I4)") i @@ -1191,12 +1191,12 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if #if defined(__recom) && defined(__usetp) - endif !(my_fesom_group==0) then + endif !(partit%my_fesom_group==0) then #endif CASE (1305:1321) tracers%data(i)%values(:,:)=0.0_WP #if defined(__recom) && defined(__usetp) - if (my_fesom_group==0) then + if (partit%my_fesom_group==0) then #endif if (mype==0) then write (i_string, "(I4)") i @@ -1204,13 +1204,13 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if #if defined(__recom) && defined(__usetp) - endif !(my_fesom_group==0) then + endif !(partit%my_fesom_group==0) then #endif ! Radiocarbon CASE (1402) tracers%data(i)%values(:,:)=0.0_WP #if defined(__recom) && defined(__usetp) - if (my_fesom_group==0) then + if (partit%my_fesom_group==0) then #endif if (mype==0) then write (i_string, "(I4)") i @@ -1218,12 +1218,12 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if #if defined(__recom) && defined(__usetp) - endif !(my_fesom_group==0) then + endif !(partit%my_fesom_group==0) then #endif CASE (1405:1421) tracers%data(i)%values(:,:)=0.0_WP #if defined(__recom) && defined(__usetp) - if (my_fesom_group==0) then + if (partit%my_fesom_group==0) then #endif if (mype==0) then write (i_string, "(I4)") i @@ -1231,7 +1231,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) write(*,*) 'initializing '//trim(i_string)//'th tracer with ID='//trim(id_string) end if #if defined(__recom) && defined(__usetp) - endif !(my_fesom_group==0) then + endif !(partit%my_fesom_group==0) then #endif ! End of carbon isotopes section !_______________________________________________________________________ From e8117d87949504d77eeb2777cb708ebd48e5d273 Mon Sep 17 00:00:00 2001 From: ackerlar Date: Wed, 5 Feb 2025 21:17:53 +0100 Subject: [PATCH 06/68] make MPI calls consistent fix?? cpl_oasis3mct_init call in fesom_module --- src/cpl_driver.F90 | 4 ++-- src/fesom_module.F90 | 5 +++-- src/gen_forcing_couple.F90 | 12 ++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/cpl_driver.F90 b/src/cpl_driver.F90 index 4b95c5799..fe16ae423 100644 --- a/src/cpl_driver.F90 +++ b/src/cpl_driver.F90 @@ -958,7 +958,7 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) #if defined(__recom) && defined(__usetp) ! kh 03.12.21 if(num_fesom_groups > 1) then - call MPI_Bcast(action, 1, MPI_LOGICAL, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) + call MPI_Bcast(action, 1, MPI_LOGICAL, 0, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%MPIerr) end if #endif @@ -973,7 +973,7 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) ! kh 03.12.21 if(num_fesom_groups > 1) then - call MPI_Bcast(data_array, myDim_nod2d, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) + call MPI_Bcast(data_array, partit%myDim_nod2d, MPI_DOUBLE_PRECISION, 0, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%MPIerr) end if #endif diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 3171f64c7..ed3f407e9 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -115,6 +115,7 @@ subroutine fesom_init(fesom_total_nsteps) #if defined(__MULTIO) use iom #endif + use cpl_driver integer, intent(out) :: fesom_total_nsteps ! EO parameters logical mpi_is_initialized @@ -166,9 +167,9 @@ subroutine fesom_init(fesom_total_nsteps) ! call cpl_oasis3mct_init(f%partit,f%partit%MPI_COMM_FESOM) ! kh 02.12.21 #if defined(__recom) && defined(__usetp) - call cpl_oasis3mct_init(f%partit, f%partit%localCommunicator, num_fesom_groups) + call cpl_oasis3mct_init(f%partit, f%partit%MPI_COMM_FESOM, num_fesom_groups) #else - call cpl_oasis3mct_init(f%partit, f%partit%localCommunicator) + call cpl_oasis3mct_init(f%partit, f%partit%MPI_COMM_FESOM) #endif #endif f%t1 = MPI_Wtime() diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index 986444e2e..0a0bdcbc5 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -272,7 +272,7 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) ! kh 30.11.21 #if defined(__recom) && defined(__usetp) - if(my_fesom_group == 0) then + if(partit%my_fesom_group == 0) then #endif call cpl_oasis3mct_send(i, exchange, action, partit) #if defined(__recom) && defined(__usetp) @@ -842,12 +842,12 @@ SUBROUTINE net_rec_from_atm(action, partit) use o_PARAM, only: WP USE MOD_PARTIT USE MOD_PARSUP - IMPLICIT NONE #if defined(__recom) && defined(__usetp) ! kh 10.21.21 use g_config, only: num_fesom_groups #endif + IMPLICIT NONE LOGICAL, INTENT (IN) :: action type(t_partit), intent(inout), target :: partit @@ -870,13 +870,13 @@ SUBROUTINE net_rec_from_atm(action, partit) atm_net_fluxes_south=0. #if defined(__recom) && defined(__usetp) ! kh 10.12.21 - my_global_rank_test = my_global_rank - (my_fesom_group * npes) + my_global_rank_test = my_global_rank - (partit%my_fesom_group * partit%npes) #endif #if defined(__recom) && defined(__usetp) ! kh 10.12.21 check for is root in group if (my_global_rank_test==target_root) then - if(my_fesom_group == 0) then + if(partit%my_fesom_group == 0) then #else if (my_global_rank==target_root) then #endif @@ -887,8 +887,8 @@ SUBROUTINE net_rec_from_atm(action, partit) #if defined(__recom) && defined(__usetp) if(num_fesom_groups > 1) then - call MPI_Bcast(atm_net_fluxes_north(1), nrecv, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) - call MPI_Bcast(atm_net_fluxes_south(1), nrecv, MPI_DOUBLE_PRECISION, 0, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIerr) + call MPI_Bcast(atm_net_fluxes_north(1), nrecv, MPI_DOUBLE_PRECISION, 0, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%MPIerr) + call MPI_Bcast(atm_net_fluxes_south(1), nrecv, MPI_DOUBLE_PRECISION, 0, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%MPIerr) end if end if ! (my_global_rank_test==target_root) then #endif From 604a88a2af3589616a8eea115cd70554ff2cbe44 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Thu, 6 Feb 2025 00:04:54 +0100 Subject: [PATCH 07/68] localcommunicator removed in fesom_module.F90 --- src/fesom_module.F90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 3171f64c7..dcfe1d6e8 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -166,9 +166,9 @@ subroutine fesom_init(fesom_total_nsteps) ! call cpl_oasis3mct_init(f%partit,f%partit%MPI_COMM_FESOM) ! kh 02.12.21 #if defined(__recom) && defined(__usetp) - call cpl_oasis3mct_init(f%partit, f%partit%localCommunicator, num_fesom_groups) + call cpl_oasis3mct_init(f%partit, f%partit%MPI_COMM_FESOM, num_fesom_groups) #else - call cpl_oasis3mct_init(f%partit, f%partit%localCommunicator) + call cpl_oasis3mct_init(f%partit, f%partit%MPI_COMM_FESOM) #endif #endif f%t1 = MPI_Wtime() @@ -454,7 +454,7 @@ subroutine fesom_init(fesom_total_nsteps) #if defined(__recom) && defined(__usetp) ! kh 03.12.21 -! call MPI_Barrier(f%MPI_COMM_FESOM_WORLD, f%MPIERR) + call MPI_Barrier(f%MPI_COMM_FESOM_WORLD, f%MPIERR) if(num_fesom_groups > 1) then call MPI_Bcast(cpl_send, sizeof(cpl_send), MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) From dd226972c538c50cb93701607d9f4f57817d6bbb Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Thu, 6 Feb 2025 21:38:13 +0100 Subject: [PATCH 08/68] set code version without tracer parallelisation as default --- src/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4b4610718..cfc9c4606 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -238,8 +238,8 @@ endif() if(${RECOM_COUPLED}) # target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __usetp) -# target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2) - target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __3Zoo2Det __coccos __usetp) + target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2) +# target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __3Zoo2Det __coccos __usetp) endif() if(${CISO_COUPLED}) From 076bc7171ddbe34524695a3054f45b4c1ed0ebae Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Thu, 6 Feb 2025 21:46:00 +0100 Subject: [PATCH 09/68] set recom_coupled off as default --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36e7a41d1..5c2fc8a85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ set(OIFS_COUPLED OFF CACHE BOOL "compile fesom coupled to OpenIFS. (Also needs F set(CRAY OFF CACHE BOOL "compile with cray ftn") set(USE_ICEPACK OFF CACHE BOOL "compile fesom with the Iceapck modules for sea ice column physics.") set(OPENMP_REPRODUCIBLE OFF CACHE BOOL "serialize OpenMP loops that are critical for reproducible results") -set(RECOM_COUPLED ON CACHE BOOL "compile fesom including biogeochemistry, REcoM3") +set(RECOM_COUPLED OFF CACHE BOOL "compile fesom including biogeochemistry, REcoM3") set(CISO_COUPLED OFF CACHE BOOL "compile ciso coupled to REcoM3. RECOM_COUPLED has to be active") set(USE_MULTIO OFF CACHE BOOL "Use MULTIO for IO, either grib or binary for now. This also means path to MULTIO installation has to provided using env MULTIO_INSTALL_PATH='..' and multio configuration yamls must be present to run the model with MULTIO") set(OASIS_WITH_YAC OFF CACHE BOOL "Useing a version of OASIS compiled with YAC instead of SCRIP for interpolation?") From 9f3c6d6a843e5c31de388d9d8e10d3dc8d7f04b0 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 7 Feb 2025 16:56:33 +0100 Subject: [PATCH 10/68] clean up kh comments --- src/cpl_driver.F90 | 14 +--- src/fesom_module.F90 | 155 ++++++++++++++++++++++++------------------- 2 files changed, 91 insertions(+), 78 deletions(-) diff --git a/src/cpl_driver.F90 b/src/cpl_driver.F90 index fe16ae423..3e402cd19 100644 --- a/src/cpl_driver.F90 +++ b/src/cpl_driver.F90 @@ -15,7 +15,7 @@ module cpl_driver use mod_oasis ! oasis module use g_config, only : dt, use_icebergs, lwiso #if defined(__recom) && defined(__usetp) - use g_config, only : num_fesom_groups ! kh 03.12.21 OG 08.09.23 + use g_config, only : num_fesom_groups #endif use o_param, only : rad USE MOD_PARTIT @@ -313,7 +313,6 @@ subroutine node_contours(my_x_corners, my_y_corners, partit, mesh) my_y_corners=my_y_corners/rad end subroutine node_contours -! kh 02.12.21 #if defined(__recom) && defined(__usetp) subroutine cpl_oasis3mct_init(partit, localCommunicator, num_fesom_groups) #else @@ -334,7 +333,6 @@ subroutine cpl_oasis3mct_init(partit, localCommunicator) integer, intent(OUT) :: localCommunicator type(t_partit), intent(inout), target :: partit #if defined(__recom) && defined(__usetp) -! kh 02.12.21 integer, intent(inout) :: num_fesom_groups #endif ! @@ -358,7 +356,6 @@ subroutine cpl_oasis3mct_init(partit, localCommunicator) !------------------------------------------------------------------ ! 1st Initialize the OASIS3-MCT coupling system for the application !------------------------------------------------------------------ -! kh 02.12.21 #if defined(__recom) && defined(__usetp) CALL oasis_init_comp(comp_id, comp_name, ierror, num_program_groups = num_fesom_groups) #else @@ -374,7 +371,6 @@ subroutine cpl_oasis3mct_init(partit, localCommunicator) CALL oasis_abort(comp_id, 'cpl_oasis3mct_init', 'comm_rank failed.') ENDIF -! kh 02.12.21 #if defined(__recom) && defined(__usetp) CALL oasis_get_localcomm_all_groups( localCommunicator, ierror ) #else @@ -629,7 +625,6 @@ subroutine cpl_oasis3mct_define_unstr(partit, mesh) print *, 'FESOM after Barrier' endif -! kh 30.11.21 #if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then #endif @@ -932,7 +927,7 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) #endif #if defined(__recom) && defined(__usetp) -! kh 06.12.21 the coupling is in principle as it was before, i.e. the fesom processes - in group 0 - receive their data from echam +! the coupling is in principle as it was before, i.e. the fesom processes - in group 0 - receive their data from echam if(partit%my_fesom_group == 0) then #endif @@ -941,7 +936,7 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) #if defined(__recom) && defined(__usetp) else -! kh 06.12.21 defensive: assignment statement "action=(info==3 ..." below is "don't care" in this case, because the actual value for action +! defensive: assignment statement "action=(info==3 ..." below is "don't care" in this case, because the actual value for action ! is received via MPI_Bcast anyway info = 0 @@ -956,7 +951,6 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) action=(info==3 .OR. info==10 .OR. info==11 .OR. info==12 .OR. info==13) #if defined(__recom) && defined(__usetp) -! kh 03.12.21 if(num_fesom_groups > 1) then call MPI_Bcast(action, 1, MPI_LOGICAL, 0, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%MPIerr) end if @@ -964,14 +958,12 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) if (action) then #if defined(__recom) && defined(__usetp) -! kh 03.12.21 if(partit%my_fesom_group == 0) then #endif data_array(1:partit%myDim_nod2d) = exfld #if defined(__recom) && defined(__usetp) end if -! kh 03.12.21 if(num_fesom_groups > 1) then call MPI_Bcast(data_array, partit%myDim_nod2d, MPI_DOUBLE_PRECISION, 0, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%MPIerr) end if diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 07d9984c0..71d3a84cf 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -122,14 +122,15 @@ subroutine fesom_init(fesom_total_nsteps) integer :: tr_num #if defined(__recom) && defined(__usetp) -! kh 11.11.21 multi FESOM group loop parallelization +! multi FESOM group loop parallelization +! moved from fvom_main.F90 integer :: npes_fesom_world integer :: mype_fesom_world integer :: processes_per_group integer :: npes_check integer :: mype_check -! kh 26.11.21 get current value for num_fesom_groups +! get current value for num_fesom_groups call read_namelist_run_config #endif @@ -164,13 +165,14 @@ subroutine fesom_init(fesom_total_nsteps) #endif #if defined (__oasis) -! call cpl_oasis3mct_init(f%partit,f%partit%MPI_COMM_FESOM) -! kh 02.12.21 + +! pass num_fesom_groups to coupler #if defined(__recom) && defined(__usetp) call cpl_oasis3mct_init(f%partit, f%partit%MPI_COMM_FESOM, num_fesom_groups) #else call cpl_oasis3mct_init(f%partit, f%partit%MPI_COMM_FESOM) #endif + #endif f%t1 = MPI_Wtime() @@ -185,7 +187,7 @@ subroutine fesom_init(fesom_total_nsteps) f%npes =>f%partit%npes #if defined(__recom) && defined(__usetp) -! kh 26.11.21 prepare communicator splitting for multi FESOM group loop parallelization +! prepare communicator splitting for multi FESOM group loop parallelization f%my_fesom_group=>f%partit%my_fesom_group f%MPI_COMM_FESOM_WORLD=> f%partit%MPI_COMM_FESOM_WORLD @@ -213,7 +215,7 @@ subroutine fesom_init(fesom_total_nsteps) f%my_fesom_group = mype_fesom_world / processes_per_group f%mype = mod(mype_fesom_world, processes_per_group) -! kh 26.11.21 split to num_fesom_groups +! split to num_fesom_groups call MPI_comm_split(f%MPI_COMM_FESOM_WORLD, f%my_fesom_group, 0, f%MPI_COMM_FESOM, f%MPIerr) if (f%MPIerr /= MPI_SUCCESS) then write(*,*) 'MPI_comm_split(MPI_COMM_FESOM_WORLD, my_fesom_group, 0, MPI_COMM_FESOM, MPIERR) failed' @@ -231,7 +233,7 @@ subroutine fesom_init(fesom_total_nsteps) call MPI_comm_rank(f%MPI_COMM_FESOM, mype_check, f%MPIerr) if(f%MPIerr /= MPI_SUCCESS) then write(*,*) 'MPI_comm_rank(MPI_COMM_FESOM, mype_check, MPIERR) failed' - call par_ex(f%partit%MPI_COMM_FESOM, f%mype) + call par_ex(f%MPI_COMM_FESOM, f%mype) stop end if @@ -247,8 +249,7 @@ subroutine fesom_init(fesom_total_nsteps) stop end if -! kh 17.11.21 group same ranks in each group for broadcasting -! write(*,*) 'mype, my_fesom_group', mype, my_fesom_group +! group same ranks in each group for broadcasting call MPI_comm_split(f%MPI_COMM_FESOM_WORLD, f%mype, f%my_fesom_group, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIERR) if (f%MPIERR /= MPI_SUCCESS) then @@ -283,7 +284,6 @@ subroutine fesom_init(fesom_total_nsteps) stop end if -! kh 29.02.22 if(f%my_fesom_group==0) then #endif @@ -305,14 +305,19 @@ subroutine fesom_init(fesom_total_nsteps) ! load the mesh and fill in ! auxiliary mesh arrays !===================== + if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call setup_model'//achar(27)//'[0m' call setup_model(f%partit) ! Read Namelists, always before clock_init + + if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call clock_init'//achar(27)//'[0m' call clock_init(f%partit) ! read the clock file + + if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call get_run_steps'//achar(27)//'[0m' call get_run_steps(fesom_total_nsteps, f%partit) f%total_nsteps=fesom_total_nsteps + if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call mesh_setup'//achar(27)//'[0m' call mesh_setup(f%partit, f%mesh) -! kh 29.02.22 #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif @@ -323,6 +328,20 @@ subroutine fesom_init(fesom_total_nsteps) end if #endif +! Transient tracers: control output of initial input values + if(use_transit .and. anthro_transit .and. f%mype==0) then + write (*,*) + write (*,*) "*** Transient tracers: Initial atmospheric input values >>>" + write (*,*) "Year CE, xCO2, D14C_NH, D14C_TZ, D14C_SH, xCFC-11_NH, xCFC-11_SH, xCFC-12_NH, xCFC-12_SH, xSF6_NH, xSF6_SH" + write (*, fmt="(2x,i4,10(2x,f6.2))") & + year_ce(ti_transit), xCO2_ti(ti_transit) * 1.e6, & + (r14c_nh(ti_transit) - 1.) * 1000., (r14c_tz(ti_transit) - 1.) * 1000., (r14c_sh(ti_transit) - 1.) * 1000., & + xf11_nh(ti_transit) * 1.e12, xf11_sh(ti_transit) * 1.e12, & + xf12_nh(ti_transit) * 1.e12, xf12_sh(ti_transit) * 1.e12, & + xsf6_nh(ti_transit) * 1.e12, xsf6_sh(ti_transit) * 1.e12 + write (*,*) + end if + !===================== ! Allocate field variables ! and additional arrays needed for @@ -373,24 +392,17 @@ subroutine fesom_init(fesom_total_nsteps) #if defined (__usetp) if(f%my_fesom_group==0) then #endif - if (f%mype==0) write(*,*) 'RECOM recom_init... complete' - #if defined (__usetp) end if #endif - #endif if (f%mype==0) then - -! kh 29.02.22 #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif - write(*,*) 'FESOM ocean_setup... complete' - #if defined(__recom) && defined(__usetp) end if #endif @@ -409,9 +421,7 @@ subroutine fesom_init(fesom_total_nsteps) #if defined(__usetp) if (f%my_fesom_group==0) then #endif - if (f%mype==0) write(*,*) 'EVP scheme option=', f%ice%whichEVP - #if defined(__usetp) end if #endif @@ -440,33 +450,29 @@ subroutine fesom_init(fesom_total_nsteps) !---age-code-end #if defined (__oasis) -! kh 30.11.21 only mype == 0 in my_fesom_group == 0 handles coupling with extern models +! only mype == 0 in my_fesom_group == 0 handles coupling with extern models #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif - call cpl_oasis3mct_define_unstr(f%partit, f%mesh) - if(f%mype==0) write(*,*) 'FESOM ----> cpl_oasis3mct_define_unstr nsend, nrecv:',nsend, nrecv - #if defined(__recom) && defined(__usetp) end if #endif #if defined(__recom) && defined(__usetp) -! kh 03.12.21 call MPI_Barrier(f%MPI_COMM_FESOM_WORLD, f%MPIERR) if(num_fesom_groups > 1) then call MPI_Bcast(cpl_send, sizeof(cpl_send), MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) call MPI_Bcast(cpl_recv, sizeof(cpl_recv), MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) -! kh 10.12.21 needed in SUBROUTINE net_rec_from_atm(action) +! needed in SUBROUTINE net_rec_from_atm(action) call MPI_Bcast(target_root, 1, MPI_INTEGER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) end if #endif -#endif +#endif ! defined (__oasis) ! -------------- ! LA icebergs: 2023-05-17 @@ -485,6 +491,7 @@ subroutine fesom_init(fesom_total_nsteps) call init_icepack(f%ice, f%tracers%data(1), f%mesh) if (f%mype==0) write(*,*) 'Icepack: setup complete' #endif + call clock_newyear ! check if it is a new year if (f%mype==0) f%t6=MPI_Wtime() !___CREATE NEW RESTART FILE IF APPLICABLE___________________________________ @@ -492,14 +499,10 @@ subroutine fesom_init(fesom_total_nsteps) if (f%mype==0) f%t7=MPI_Wtime() ! store grid information into netcdf file -! kh 29.03.22 #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif - if (.not. r_restart) call write_mesh_info(f%partit, f%mesh) - -! kh 29.03.22 #if defined(__recom) && defined(__usetp) end if #endif @@ -523,7 +526,6 @@ subroutine fesom_init(fesom_total_nsteps) f%rtime_setup_recom = real( f%t1_recom - f%t0_recom ,real32) #endif -! kh 29.03.22 #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif @@ -542,7 +544,6 @@ subroutine fesom_init(fesom_total_nsteps) #endif write(*,*) '============================================' -! kh 29.03.22 #if defined(__recom) && defined(__usetp) end if #endif @@ -673,48 +674,33 @@ subroutine fesom_runloop(current_nsteps) end if end if ! -------------- -! kh 29.03.22 #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif - if (f%mype==0) write(*,*) 'FESOM start iteration before the barrier...' - -! kh 29.03.22 #if defined(__recom) && defined(__usetp) end if #endif - call MPI_Barrier(f%MPI_COMM_FESOM, f%MPIERR) if (f%mype==0) then - -! kh 29.03.22 #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif - write(*,*) 'FESOM start iteration after the barrier...' - -! kh 29.03.22 #if defined(__recom) && defined(__usetp) end if #endif - f%t0 = MPI_Wtime() endif -! kh 29.03.22 #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif - if(f%mype==0) then write(*,*) print *, achar(27)//'[32m' //'____________________________________________________________'//achar(27)//'[0m' print *, achar(27)//'[7;32m'//' --> FESOM STARTS TIME LOOP '//achar(27)//'[0m' end if - -! kh 29.03.22 #if defined(__recom) && defined(__usetp) end if #endif @@ -785,19 +771,15 @@ subroutine fesom_runloop(current_nsteps) end if mstep = n -! kh 29.03.22 #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif - if (mod(n,logfile_outfreq)==0 .and. f%mype==0) then write(*,*) 'FESOM =======================================================' ! write(*,*) 'FESOM step:',n,' day:', n*dt/24./3600., write(*,*) 'FESOM step:',n,' day:', daynew,' year:',yearnew write(*,*) end if - -! kh 29.03.22 #if defined(__recom) && defined(__usetp) end if #endif @@ -807,7 +789,13 @@ subroutine fesom_runloop(current_nsteps) #endif call clock !___compute horizontal velocity on nodes (originaly on elements)________ +#if defined(__recom) && defined(__usetp) + if (f%my_fesom_group==0) then +#endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call compute_vel_nodes'//achar(27)//'[0m' +#if defined(__recom) && defined(__usetp) + end if +#endif call compute_vel_nodes(f%dynamics, f%partit, f%mesh) ! -------------- ! LA icebergs: 2023-05-17 @@ -821,11 +809,23 @@ subroutine fesom_runloop(current_nsteps) f%t1 = MPI_Wtime() if(use_ice) then !___compute fluxes from ocean to ice________________________________ +#if defined(__recom) && defined(__usetp) + if (f%my_fesom_group==0) then +#endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call ocean2ice(n)'//achar(27)//'[0m' +#if defined(__recom) && defined(__usetp) + end if +#endif call ocean2ice(f%ice, f%dynamics, f%tracers, f%partit, f%mesh) !___compute update of atmospheric forcing____________________________ +#if defined(__recom) && defined(__usetp) + if (f%my_fesom_group==0) then +#endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call update_atm_forcing(n)'//achar(27)//'[0m' +#if defined(__recom) && defined(__usetp) + end if +#endif f%t0_frc = MPI_Wtime() call update_atm_forcing(n, f%ice, f%tracers, f%dynamics, f%partit, f%mesh) f%t1_frc = MPI_Wtime() @@ -837,7 +837,13 @@ subroutine fesom_runloop(current_nsteps) f%ice%ice_update=.false. f%ice%ice_steps_since_upd=f%ice%ice_steps_since_upd+1 endif +#if defined(__recom) && defined(__usetp) + if (f%my_fesom_group==0) then +#endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call ice_timestep(n)'//achar(27)//'[0m' +#if defined(__recom) && defined(__usetp) + end if +#endif if (f%ice%ice_update) call ice_timestep(n, f%ice, f%partit, f%mesh) @@ -851,7 +857,13 @@ subroutine fesom_runloop(current_nsteps) !___compute fluxes to the ocean: heat, freshwater, momentum_________ +#if defined(__recom) && defined(__usetp) + if (f%my_fesom_group==0) then +#endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call oce_fluxes_mom...'//achar(27)//'[0m' +#if defined(__recom) && defined(__usetp) + end if +#endif call oce_fluxes_mom(f%ice, f%dynamics, f%partit, f%mesh) ! momentum only call oce_fluxes(f%ice, f%dynamics, f%tracers, f%partit, f%mesh) end if @@ -860,14 +872,11 @@ subroutine fesom_runloop(current_nsteps) !___now recom____________________________________________________ #if defined (__recom) -! kh 29.03.22 #if defined(__usetp) if (f%my_fesom_group==0) then #endif - if (f%mype==0 .and. n==1) print *, achar(27)//'[46' //'_____________________________________________________________'//achar(27)//'[0m' if (f%mype==0 .and. n==1) print *, achar(27)//'[46;1m'//' --> call REcoM '//achar(27)//'[0m' - #if defined(__usetp) end if #endif @@ -904,10 +913,10 @@ subroutine fesom_runloop(current_nsteps) if (f%my_fesom_group==0) then #endif if (flag_debug .and. f%mype==0) print *, achar(27)//'[34m'//' --> call output (n)'//achar(27)//'[0m' + call output (n, f%ice, f%dynamics, f%tracers, f%partit, f%mesh) #if defined(__recom) && defined(__usetp) end if -#endif - call output (n, f%ice, f%dynamics, f%tracers, f%partit, f%mesh) +#endif ! LA icebergs: 2023-05-17 if (use_icebergs .and. mod(n, steps_per_ib_step)==0.0) then @@ -927,6 +936,24 @@ subroutine fesom_runloop(current_nsteps) #if defined (__recom) f%rtime_compute_recom = f%rtime_compute_recom + f%t1_recom - f%t0_recom #endif + +! Transient tracers: update of input values between restarts + if(use_transit .and. anthro_transit .and. (daynew == ndpyr) .and. (timenew==86400.)) then + ti_transit = ti_transit + 1 + if (f%mype==0) then + write (*,*) + write (*,*) "*** Transient tracers: Updated atmospheric input values >>>" + write (*,*) "Year CE, xCO2, D14C_NH, D14C_TZ, D14C_SH, xCFC-11_NH, xCFC-11_SH, xCFC-12_NH, xCFC-12_SH, xSF6_NH, xSF6_SH" + write (*, fmt="(2x,i4,10(2x,f6.2))") & + year_ce(ti_transit), xCO2_ti(ti_transit) * 1.e6, & + (r14c_nh(ti_transit) - 1.) * 1000., (r14c_tz(ti_transit) - 1.) * 1000., (r14c_sh(ti_transit) - 1.) * 1000., & + xf11_nh(ti_transit) * 1.e12, xf11_sh(ti_transit) * 1.e12, & + xf12_nh(ti_transit) * 1.e12, xf12_sh(ti_transit) * 1.e12, & + xsf6_nh(ti_transit) * 1.e12, xsf6_sh(ti_transit) * 1.e12 + write (*,*) + end if + endif + end do !call cray_acc_set_debug_global_level(3) f%from_nstep = f%from_nstep+current_nsteps @@ -934,7 +961,6 @@ subroutine fesom_runloop(current_nsteps) ! write(0,*) 'f%from_nstep after the loop:', f%from_nstep end subroutine - subroutine fesom_finalize() use fesom_main_storage_module #if defined(__MULTIO) @@ -951,15 +977,11 @@ subroutine fesom_finalize() call iceberg_out(f%partit) end if ! -------------- -! kh 11.11.21 multi FESOM group loop parallelization #if defined(__recom) && defined(__usetp) if (f%my_fesom_group==0) then #endif - call finalize_output() call finalize_restart() - -! kh 29.03.22 #if defined(__recom) && defined(__usetp) end if #endif @@ -967,19 +989,19 @@ subroutine fesom_finalize() !___FINISH MODEL RUN________________________________________________________ #if !defined (__usetp) -! kh 11.11.21 multi FESOM group loop parallelization +! multi FESOM group loop parallelization call MPI_Barrier(f%MPI_COMM_FESOM, f%MPIERR) #endif #if defined(__recom) && defined (__usetp) -! kh 11.11.21 list statistics for all fesom_groups +! list statistics for all fesom_groups ! fesom groups are listed backwards, so info for the main fesom group 0 is at the end in the log do i = num_fesom_groups - 1, 0, -1 -! kh 29.03.22 use a barrier to "sort" the output but the mpi output can still get a bit mixed up, +! use a barrier to "sort" the output but the mpi output can still get a bit mixed up, ! because MPI does not define the handling of the order of the output lines call MPI_Barrier(f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIERR) -! kh 29.03.22 for the sake of output clarity produce output only for my_fesom_group == 0 for now +! for the sake of output clarity produce output only for my_fesom_group == 0 for now if(i == f%my_fesom_group .and. f%my_fesom_group == 0) then #endif @@ -1123,7 +1145,6 @@ subroutine fesom_finalize() write(*,*) end if -! kh 29.03.22 #if defined(__recom) && defined(__usetp) end if #endif From 4a053a9a234c1b1e5f2941007c0b4895962a8a74 Mon Sep 17 00:00:00 2001 From: ackerlar Date: Wed, 12 Feb 2025 18:52:02 +0100 Subject: [PATCH 11/68] point only when defined --- src/associate_part_ass.h | 10 +++++----- src/associate_part_def.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/associate_part_ass.h b/src/associate_part_ass.h index f8065f592..9d4c7a3c9 100644 --- a/src/associate_part_ass.h +++ b/src/associate_part_ass.h @@ -1,7 +1,7 @@ -#if defined(__recom) && defined(__usetp) +!DIR$ if defined(__recom) .AND. defined(__usetp) MPI_COMM_FESOM_WORLD => partit%MPI_COMM_FESOM_WORLD MPI_COMM_FESOM_SAME_RANK_IN_GROUPS => partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -#endif +!DIR$ endif MPI_COMM_FESOM => partit%MPI_COMM_FESOM MPI_COMM_FESOM_IB => partit%MPI_COMM_FESOM_IB com_nod2D => partit%com_nod2D @@ -17,12 +17,12 @@ eDim_edge2D => partit%eDim_edge2D pe_status => partit%pe_status elem_full_flag => partit%elem_full_flag MPIERR => partit%MPIERR -MPIERR_IB => partit%MPIERR_IB +MPIERR_IB => partit%MPIERR_IB npes => partit%npes mype => partit%mype -#if defined(__recom) && defined(__usetp) +!DIR$ if defined(__recom) .AND. defined(__usetp) my_fesom_group => my_fesom_group -#endif +!DIR$ endif maxPEnum => partit%maxPEnum part => partit%part diff --git a/src/associate_part_def.h b/src/associate_part_def.h index 3d4f75334..8baef3a9d 100644 --- a/src/associate_part_def.h +++ b/src/associate_part_def.h @@ -1,7 +1,7 @@ -#if defined(__recom) && defined(__usetp) +!DIR$ if defined(__recom) .AND. defined(__usetp) integer, pointer :: MPI_COMM_FESOM_WORLD integer, pointer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -#endif +!DIR$ endif integer, pointer :: MPI_COMM_FESOM ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) integer, pointer :: MPI_COMM_FESOM_IB ! FESOM communicator copy for icebergs LA: 2023-05-22 type(com_struct), pointer :: com_nod2D @@ -24,9 +24,9 @@ integer, pointer :: MPIERR_IB ! copy for icebergs LA: 2023-05-22 integer, pointer :: npes integer, pointer :: mype -#if defined(__recom) && defined(__usetp) +!DIR$ if defined(__recom) .AND. defined(__usetp) integer, pointer :: my_fesom_group -#endif +!DIR$ endif integer, pointer :: maxPEnum integer, dimension(:), pointer :: part From 45d7fd33ac1aeb302021a6fde1eded481faef47e Mon Sep 17 00:00:00 2001 From: ackerlar Date: Wed, 12 Feb 2025 18:52:22 +0100 Subject: [PATCH 12/68] add missing tracer --- src/fesom_module.F90 | 1 + src/mod_transit.F90 | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 71d3a84cf..097b9e5f9 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -36,6 +36,7 @@ module fesom_main_storage_module use age_tracer_init_interface use iceberg_params use iceberg_step + use mod_transit ! Define icepack module #if defined (__icepack) diff --git a/src/mod_transit.F90 b/src/mod_transit.F90 index 6713032eb..4daffd2f4 100644 --- a/src/mod_transit.F90 +++ b/src/mod_transit.F90 @@ -16,6 +16,7 @@ MODULE mod_transit r39ar_a = 1.0, & ! 39Ar / 40 Ar (homogeneous) xarg_a = 9.34e-3, & ! Argon (homogeneous) xCO2_a = 284.32e-6, & ! CO2 (CMIP6 & OMIP-BGC: 284.32e-6 for 1700-1850, PMIP4: 190.00e-6 for 21 ka BP) + xf11_a = 0.0, & ! CFC-11 (latitude dependent) xf12_a = 0.0, & ! CFC-12 (latitude dependent) xsf6_a = 0.0 ! SF6 (latitude dependent) @@ -23,6 +24,7 @@ MODULE mod_transit real(kind=8), allocatable, dimension(:) :: r14c_nh, r14c_tz, r14c_sh, & ! 14CO2 / 12CO2, latitude-dependent (e.g., bomb 14C) r14c_ti, & ! 14CO2 / 12CO2, homogenous (e.g., IntCal) xCO2_ti, & ! CO2 + xf11_nh, xf11_sh, & ! CFC-11, latitude-dependent xf12_nh, xf12_sh, & ! CFC-12, latitude-dependent xsf6_nh, xsf6_sh ! SF6, latitude-dependent integer, allocatable, dimension(:) :: year_ce ! current year in anthropenic runs (control output) From 4f01ed80cff4814f362d017d4dc0a03f88087f2f Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 25 Jun 2025 11:21:54 +0200 Subject: [PATCH 13/68] remove spurious leftover end if --- src/io_restart.F90 | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 58e2b62b5..efa55d479 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -465,14 +465,13 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr end if #if defined(__recom) && defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG + if(partit%my_fesom_group == 0) then ! OG #endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: ice'//achar(27)//'[0m' #if defined(__recom) && defined(__usetp) endif !(partit%my_fesom_group == 0) then ! OG #endif call read_restart(ice_path, ice_files, partit%MPI_COMM_FESOM, partit%mype) - end if #if defined(__recom) !RECOM restart @@ -519,7 +518,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr #if defined(__recom) && defined(__usetp) end if ! (my_fesom_group == 0) then #endif - end if + end if ! bin_restart_length_unit /= "off" end if end if From 6f37080b972fc1bd63e3e8cb5d3a5d904050bc15 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Wed, 25 Jun 2025 11:37:56 +0200 Subject: [PATCH 14/68] try different preprocessor flags in .h file, hopefully passing CI --- src/associate_part_ass.h | 8 ++++---- src/associate_part_def.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/associate_part_ass.h b/src/associate_part_ass.h index cf173371c..2e7739d01 100644 --- a/src/associate_part_ass.h +++ b/src/associate_part_ass.h @@ -1,7 +1,7 @@ -!DIR$ if defined(__recom) .AND. defined(__usetp) +#if defined(__recom) && defined(__usetp) MPI_COMM_FESOM_WORLD => partit%MPI_COMM_FESOM_WORLD MPI_COMM_FESOM_SAME_RANK_IN_GROUPS => partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -!DIR$ endif +#endif MPI_COMM_FESOM => partit%MPI_COMM_FESOM MPI_COMM_FESOM_IB => partit%MPI_COMM_FESOM_IB com_nod2D => partit%com_nod2D @@ -20,9 +20,9 @@ MPIERR => partit%MPIERR MPIERR_IB => partit%MPIERR_IB npes => partit%npes mype => partit%mype -!DIR$ if defined(__recom) .AND. defined(__usetp) +#if defined(__recom) && defined(__usetp) my_fesom_group => my_fesom_group -!DIR$ endif +#endif maxPEnum => partit%maxPEnum part => partit%part diff --git a/src/associate_part_def.h b/src/associate_part_def.h index 8baef3a9d..3d4f75334 100644 --- a/src/associate_part_def.h +++ b/src/associate_part_def.h @@ -1,7 +1,7 @@ -!DIR$ if defined(__recom) .AND. defined(__usetp) +#if defined(__recom) && defined(__usetp) integer, pointer :: MPI_COMM_FESOM_WORLD integer, pointer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -!DIR$ endif +#endif integer, pointer :: MPI_COMM_FESOM ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) integer, pointer :: MPI_COMM_FESOM_IB ! FESOM communicator copy for icebergs LA: 2023-05-22 type(com_struct), pointer :: com_nod2D @@ -24,9 +24,9 @@ integer, pointer :: MPIERR_IB ! copy for icebergs LA: 2023-05-22 integer, pointer :: npes integer, pointer :: mype -!DIR$ if defined(__recom) .AND. defined(__usetp) +#if defined(__recom) && defined(__usetp) integer, pointer :: my_fesom_group -!DIR$ endif +#endif integer, pointer :: maxPEnum integer, dimension(:), pointer :: part From ade5fd9417816506b84495f95d484b2032574271 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 25 Jun 2025 12:10:06 +0200 Subject: [PATCH 15/68] remove kh comments and fix for partit --- src/MOD_PARTIT.F90 | 6 +-- src/fesom_module.F90 | 31 --------------- src/gen_forcing_couple.F90 | 7 +--- src/gen_model_setup.F90 | 4 +- src/gen_modules_config.F90 | 1 + src/int_recom/recom_init.F90 | 8 ++-- src/int_recom/recom_modules.F90 | 4 +- src/int_recom/recom_sinking.F90 | 2 +- src/io_restart.F90 | 67 ++++++++++++++------------------- src/oce_ale.F90 | 6 +-- src/oce_ale_tracer.F90 | 22 ++++------- src/oce_modules.F90 | 2 - src/oce_setup_step.F90 | 2 - 13 files changed, 53 insertions(+), 109 deletions(-) diff --git a/src/MOD_PARTIT.F90 b/src/MOD_PARTIT.F90 index 76abddb12..734fa8e84 100644 --- a/src/MOD_PARTIT.F90 +++ b/src/MOD_PARTIT.F90 @@ -72,10 +72,10 @@ module MOD_PARTIT integer :: MPI_COMM_WORLD ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) #if defined(__recom) && defined(__usetp) -! kh 11.11.21 communicator for multi FESOM group loop parallelization +! communicator for multi FESOM group loop parallelization integer :: MPI_COMM_FESOM_WORLD -! kh 17.11.21 communicator for multi FESOM group loop parallelization +! communicator for multi FESOM group loop parallelization integer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS #endif @@ -97,7 +97,7 @@ module MOD_PARTIT integer :: MPIERR #if defined(__recom) && defined(__usetp) -! kh 11.11.21 multi FESOM group loop parallelization +! multi FESOM group loop parallelization integer :: my_fesom_group #endif diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index d7784577a..88da396aa 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -336,20 +336,6 @@ subroutine fesom_init(fesom_total_nsteps) end if #endif -! Transient tracers: control output of initial input values - if(use_transit .and. anthro_transit .and. f%mype==0) then - write (*,*) - write (*,*) "*** Transient tracers: Initial atmospheric input values >>>" - write (*,*) "Year CE, xCO2, D14C_NH, D14C_TZ, D14C_SH, xCFC-11_NH, xCFC-11_SH, xCFC-12_NH, xCFC-12_SH, xSF6_NH, xSF6_SH" - write (*, fmt="(2x,i4,10(2x,f6.2))") & - year_ce(ti_transit), xCO2_ti(ti_transit) * 1.e6, & - (r14c_nh(ti_transit) - 1.) * 1000., (r14c_tz(ti_transit) - 1.) * 1000., (r14c_sh(ti_transit) - 1.) * 1000., & - xf11_nh(ti_transit) * 1.e12, xf11_sh(ti_transit) * 1.e12, & - xf12_nh(ti_transit) * 1.e12, xf12_sh(ti_transit) * 1.e12, & - xsf6_nh(ti_transit) * 1.e12, xsf6_sh(ti_transit) * 1.e12 - write (*,*) - end if - !===================== ! Allocate field variables ! and additional arrays needed for @@ -943,23 +929,6 @@ subroutine fesom_runloop(current_nsteps) f%rtime_compute_recom = f%rtime_compute_recom + f%t1_recom - f%t0_recom #endif -! Transient tracers: update of input values between restarts - if(use_transit .and. anthro_transit .and. (daynew == ndpyr) .and. (timenew==86400.)) then - ti_transit = ti_transit + 1 - if (f%mype==0) then - write (*,*) - write (*,*) "*** Transient tracers: Updated atmospheric input values >>>" - write (*,*) "Year CE, xCO2, D14C_NH, D14C_TZ, D14C_SH, xCFC-11_NH, xCFC-11_SH, xCFC-12_NH, xCFC-12_SH, xSF6_NH, xSF6_SH" - write (*, fmt="(2x,i4,10(2x,f6.2))") & - year_ce(ti_transit), xCO2_ti(ti_transit) * 1.e6, & - (r14c_nh(ti_transit) - 1.) * 1000., (r14c_tz(ti_transit) - 1.) * 1000., (r14c_sh(ti_transit) - 1.) * 1000., & - xf11_nh(ti_transit) * 1.e12, xf11_sh(ti_transit) * 1.e12, & - xf12_nh(ti_transit) * 1.e12, xf12_sh(ti_transit) * 1.e12, & - xsf6_nh(ti_transit) * 1.e12, xsf6_sh(ti_transit) * 1.e12 - write (*,*) - end if - endif - end do !call cray_acc_set_debug_global_level(3) f%from_nstep = f%from_nstep+current_nsteps diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index aa3f2fde2..e940ad035 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -270,7 +270,6 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) #endif ! oifs endif -! kh 30.11.21 #if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then #endif @@ -855,16 +854,15 @@ SUBROUTINE net_rec_from_atm(action, partit) USE MOD_PARSUP #if defined(__recom) && defined(__usetp) -! kh 10.21.21 use g_config, only: num_fesom_groups #endif + IMPLICIT NONE LOGICAL, INTENT (IN) :: action type(t_partit), intent(inout), target :: partit INTEGER :: my_global_rank, ierror #if defined(__recom) && defined(__usetp) -! kh 10.12.21 INTEGER :: my_global_rank_test #endif INTEGER :: n @@ -880,12 +878,11 @@ SUBROUTINE net_rec_from_atm(action, partit) atm_net_fluxes_north=0. atm_net_fluxes_south=0. #if defined(__recom) && defined(__usetp) -! kh 10.12.21 my_global_rank_test = my_global_rank - (partit%my_fesom_group * partit%npes) #endif #if defined(__recom) && defined(__usetp) -! kh 10.12.21 check for is root in group +! check for is root in group if (my_global_rank_test==target_root) then if(partit%my_fesom_group == 0) then #else diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index a1f243e1d..e922ba220 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -312,12 +312,12 @@ end subroutine setup_model #if defined(__recom) && defined(__usetp) -! kh 11.11.21 read num_fesom_groups for multi FESOM group loop parallelization +! read num_fesom_groups for multi FESOM group loop parallelization ! ================================================================= subroutine read_namelist_run_config(partit) ! Reads run_config namelist and overwrite default parameters. ! - ! kh 11.11.21 Copied by Kai Himstedt (based on read_namelist) + ! Copied by Kai Himstedt (based on read_namelist) !-------------------------------------------------------------- USE MOD_PARTIT USE MOD_PARSUP diff --git a/src/gen_modules_config.F90 b/src/gen_modules_config.F90 index cab4b788a..68cd01d89 100755 --- a/src/gen_modules_config.F90 +++ b/src/gen_modules_config.F90 @@ -159,6 +159,7 @@ module g_config use_transit, compute_oasis_corners #if defined(__recom) && defined(__usetp) +! number of groups for multi FESOM group loop parallelization integer :: num_fesom_groups=1 namelist /run_config_tp/ num_fesom_groups #endif diff --git a/src/int_recom/recom_init.F90 b/src/int_recom/recom_init.F90 index 0186199c5..7bcb7987f 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -89,7 +89,7 @@ subroutine recom_init(tracers, partit, mesh) allocate(GlodPCO2surf ( node_size )) allocate(GlodecayBenthos ( node_size, benthos_num )) allocate(Benthos ( node_size, benthos_num )) - allocate(Benthos_tr ( node_size, benthos_num, num_tracers )) ! kh 25.03.22 buffer per tracer index + allocate(Benthos_tr ( node_size, benthos_num, num_tracers )) ! buffer per tracer index allocate(GloHplus ( node_size )) allocate(DenitBen ( node_size )) @@ -124,7 +124,7 @@ subroutine recom_init(tracers, partit, mesh) GlodPCO2surf = 0.d0 GlodecayBenthos = 0.d0 Benthos = 0.d0 - Benthos_tr(:,:,:) = 0.0d0 ! kh 25.03.22 + Benthos_tr(:,:,:) = 0.0d0 GloHplus = exp(-8.d0 * log(10.d0)) ! = 10**(-8) DenitBen = 0.d0 @@ -249,10 +249,10 @@ subroutine recom_init(tracers, partit, mesh) 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 + allocate(SinkFlx_tr(node_size,bottflx_num,num_tracers)) ! buffer sums per tracer index SinkFlx(:,:) = 0.d0 - SinkFlx_tr(:,:,:) = 0.0d0 ! kh 25.03.22 + SinkFlx_tr(:,:,:) = 0.0d0 GloSed(:,:) = 0.d0 allocate(lb_flux(node_size,9)) lb_flux(:,:) = 0.d0 diff --git a/src/int_recom/recom_modules.F90 b/src/int_recom/recom_modules.F90 index ca4918da8..b10745c8a 100644 --- a/src/int_recom/recom_modules.F90 +++ b/src/int_recom/recom_modules.F90 @@ -688,7 +688,7 @@ Module REcoM_GloVar save Real(kind=8),allocatable,dimension(:,:) :: Benthos ! 4 types of benthos-tracers with size [4 n2d] - Real(kind=8),allocatable,dimension(:,:,:) :: Benthos_tr ! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Real(kind=8),allocatable,dimension(:,:,:) :: Benthos_tr ! buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel Real(kind=8),allocatable,dimension(:) :: GloFeDust ! [umol/m2/s] Monthly 2D field of iron soluted in surface water from dust Real(kind=8),allocatable,dimension(:) :: GloNDust ! [mmol/m2/s] 10-year mean 2D fields of nitrogen soluted in surface water from dust @@ -766,7 +766,7 @@ Module REcoM_GloVar ! for using MEDUSA Real(kind=8),allocatable,dimension(:,:) :: SinkFlx ! Diagnostics in 2D [4 n2d] or [6 n2d] with ciso - Real(kind=8),allocatable,dimension(:,:,:) :: SinkFlx_tr ! kh 25.03.22 buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel + Real(kind=8),allocatable,dimension(:,:,:) :: SinkFlx_tr ! buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel Real(kind=8),allocatable,dimension(:,:) :: Sinkingvel1 ! Diagnostics for vertical sinking Real(kind=8),allocatable,dimension(:,:) :: Sinkingvel2 ! Diagnostics for vertical sinking Real(kind=8),allocatable,dimension(:,:,:) :: Sinkvel1_tr ! Sinking speed of particle class 1 OG 16.03.23 diff --git a/src/int_recom/recom_sinking.F90 b/src/int_recom/recom_sinking.F90 index 2cbbe48c4..efe9a48b0 100644 --- a/src/int_recom/recom_sinking.F90 +++ b/src/int_recom/recom_sinking.F90 @@ -137,7 +137,7 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) Benthos(n,1)= Benthos(n,1) + add_benthos_2d(n) ![mmol] #if defined(__usetp) -! 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 +! buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel Benthos_tr(n,1,tr_num)= Benthos_tr(n,1,tr_num) + add_benthos_2d(n) ![mmol] if (use_MEDUSA) then diff --git a/src/io_restart.F90 b/src/io_restart.F90 index efa55d479..77d0ee2cf 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -287,14 +287,13 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! integer mpierr #if defined(__recom) && defined(__usetp) -! kh 31.03.22 - integer :: tr_arr_slice_count_fix_1 - integer :: group_i - integer :: tr_num_start - integer :: tr_num_end - integer :: tr_num_in_group - logical :: has_one_added_tracer - integer :: num_tracers + integer :: tr_arr_slice_count_fix_1 + integer :: group_i + integer :: tr_num_start + integer :: tr_num_end + integer :: tr_num_in_group + logical :: has_one_added_tracer + integer :: num_tracers #endif !which_readr = ... @@ -306,6 +305,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr integer :: cstep #if defined(__recom) && defined(__usetp) +! nl is required #include "associate_part_def.h" #include "associate_mesh_def.h" #include "associate_part_ass.h" @@ -323,7 +323,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr if(raw_restart_length_unit /= "off") then #if defined(__recom) && defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG master rank creates the folder + if(partit%my_fesom_group == 0) then ! master rank creates the folder #endif if(partit%mype == RAW_RESTART_METADATA_RANK) then ! execute_command_line with mkdir sometimes fails, use a custom implementation around mkdir from C instead @@ -331,7 +331,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr call mkdir(raw_restart_dirpath) end if #if defined(__recom) && defined(__usetp) - end if ! (my_fesom_group == 0) then + end if #endif call MPI_Barrier(partit%MPI_COMM_FESOM, partit%mpierr) ! make sure the dir has been created before we continue... end if @@ -345,7 +345,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr bin_restart_infopath = trim(ResultPath)//"fesom_bin_restart/np"//int_to_txt(partit%npes)//".info" if(bin_restart_length_unit /= "off") then #if defined(__recom) && defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG + if(partit%my_fesom_group == 0) then #endif if(partit%mype == RAW_RESTART_METADATA_RANK) then ! execute_command_line with mkdir sometimes fails, use a custom implementation around mkdir from C instead @@ -353,7 +353,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr call mkdir(bin_restart_dirpath) end if #if defined(__recom) && defined(__usetp) - end if ! (my_fesom_group == 0) then + end if #endif call MPI_Barrier(partit%MPI_COMM_FESOM, partit%mpierr) ! make sure the dir has been created before we continue... end if @@ -447,7 +447,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: ocean'//achar(27)//'[0m' #if defined(__recom) && defined(__usetp) - endif !(partit%my_fesom_group == 0) then ! OG + endif #endif call read_restart(oce_path, oce_files, partit%MPI_COMM_FESOM, partit%mype) @@ -465,11 +465,11 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr end if #if defined(__recom) && defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG + if(partit%my_fesom_group == 0) then #endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: ice'//achar(27)//'[0m' #if defined(__recom) && defined(__usetp) - endif !(partit%my_fesom_group == 0) then ! OG + endif #endif call read_restart(ice_path, ice_files, partit%MPI_COMM_FESOM, partit%mype) @@ -482,7 +482,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr #endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: bio'//achar(27)//'[0m' #if defined(__usetp) - endif !(partit%my_fesom_group == 0) then + endif #endif call read_restart(bio_path, bio_files, partit%MPI_COMM_FESOM, partit%mype) end if @@ -493,11 +493,11 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! immediately create a raw core dump restart if(raw_restart_length_unit /= "off") then #if defined(__recom) && defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG master rank reads + if(partit%my_fesom_group == 0) then ! master rank reads #endif call write_all_raw_restarts(istep, partit%MPI_COMM_FESOM, partit%mype) #if defined(__recom) && defined(__usetp) - end if ! (my_fesom_group == 0) then + end if #endif end if @@ -505,7 +505,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr if(bin_restart_length_unit /= "off") then ! current (total) model step --> cstep = globalstep+istep #if defined(__recom) && defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG + if(partit%my_fesom_group == 0) then #endif call write_all_bin_restarts((/globalstep+istep, int(ctime), yearnew/), & bin_restart_dirpath, & @@ -516,7 +516,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr dynamics, & tracers ) #if defined(__recom) && defined(__usetp) - end if ! (my_fesom_group == 0) then + end if #endif end if ! bin_restart_length_unit /= "off" end if @@ -554,7 +554,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr do group_i = 0, num_fesom_groups - 1 call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group, has_one_added_tracer) - call MPI_Bcast(tracers%data(tr_num_start)%valuesAB(:, :), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, mpierr) + call MPI_Bcast(tracers%data(tr_num_start)%valuesAB(:, :), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) end do end if #endif @@ -609,27 +609,12 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! write core dump if(is_raw_restart_write) then - -#if defined(__recom) && defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG master rank reads -#endif - call write_all_raw_restarts(istep, partit%MPI_COMM_FESOM, partit%mype) - -#if defined(__recom) && defined(__usetp) - end if ! (my_fesom_group == 0) then -#endif - end if ! write derived type binary if(is_bin_restart_write) then ! current (total) model step --> cstep = globalstep+istep - -#if defined(__recom) && defined(__usetp) - if(partit%my_fesom_group == 0) then ! OG master rank reads -#endif - call write_all_bin_restarts((/globalstep+istep, int(ctime), yearnew/), & bin_restart_dirpath, & bin_restart_infopath, & @@ -643,14 +628,18 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! actualize clock file to latest restart point if (partit%mype==0) then if(is_portable_restart_write .or. is_raw_restart_write .or. is_bin_restart_write) then +#if defined(__recom) && defined(__usetp) + if(partit%my_fesom_group == 0) then +#endif + write(*,*) ' --> actualize clock file to latest restart point' call clock_finish - end if - end if #if defined(__recom) && defined(__usetp) - end if ! (my_fesom_group == 0) then + end if #endif + end if + end if end subroutine restart ! diff --git a/src/oce_ale.F90 b/src/oce_ale.F90 index 5988bccf4..931b8958d 100644 --- a/src/oce_ale.F90 +++ b/src/oce_ale.F90 @@ -3751,11 +3751,11 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) !___________________________________________________________________________ ! write out global fields for debugging - if (flag_debug .and. mype==0) print *, achar(27)//'[36m'//' --> call write_step_info'//achar(27)//'[0m' #if defined(__recom) && defined(__usetp) -! kh 19.11.21 if(partit%my_fesom_group == 0) then #endif + + if (flag_debug .and. mype==0) print *, achar(27)//'[36m'//' --> call write_step_info'//achar(27)//'[0m' call write_step_info(n,logfile_outfreq, ice, dynamics, tracers, partit, mesh) !___________________________________________________________________________ @@ -3768,6 +3768,7 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) ! togeather around 2.5% of model runtime if (flag_debug .and. mype==0) print *, achar(27)//'[36m'//' --> call check_blowup'//achar(27)//'[0m' call check_blowup(n, ice, dynamics, tracers, partit, mesh) + #if defined(__recom) && defined(__usetp) endif #endif @@ -3786,7 +3787,6 @@ subroutine oce_timestep_ale(n, ice, dynamics, tracers, partit, mesh) rtime_tot = rtime_tot + (t10-t0)-(t10-t9) #if defined(__recom) && defined(__usetp) -! kh 19.11.21 if(partit%my_fesom_group == 0) then #endif if(mod(n,logfile_outfreq)==0 .and. mype==0) then diff --git a/src/oce_ale_tracer.F90 b/src/oce_ale_tracer.F90 index 1ab798376..731b90be1 100644 --- a/src/oce_ale_tracer.F90 +++ b/src/oce_ale_tracer.F90 @@ -166,15 +166,13 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) type(t_mesh) , intent(in) , target :: mesh #if defined(__recom) && defined(__usetp) -! kh 11.11.21 multi FESOM group loop parallelization +! multi FESOM group loop parallelization integer :: num_tracers integer :: tr_num_start_memo -! kh 15.11.21 integer :: group_i integer :: tr_num_start -! kh 19.11.21 logical :: has_one_added_tracer logical :: has_one_added_tracer_local_dummy logical :: tr_num_end_local_dummy @@ -183,14 +181,12 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) logical :: tr_num_in_group_dummy integer :: tr_arr_slice_count_fix_1 -! kh 28.03.22 integer :: Sinkflx_tr_slice_count_fix_1 integer :: Benthos_tr_slice_count_fix_1 integer :: tr_num_start_local integer :: tr_num_to_send -! kh 22.11.21 logical :: completed logical :: bBreak @@ -264,19 +260,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) #if defined(__recom) && defined(__usetp) -! kh 11.11.21 multi FESOM group loop parallelization call calc_slice(num_tracers, num_fesom_groups, partit%my_fesom_group, tr_num_start, tr_num_end, tr_num_in_group_dummy, has_one_added_tracer) -! kh 19.11.21 tr_arr_slice_count_fix_1 = 1 * (nl - 1) * (myDim_nod2D + eDim_nod2D) -! kh 28.03.22 Sinkflx_tr_slice_count_fix_1 = 1 * (myDim_nod2D + eDim_nod2D) * bottflx_num Benthos_tr_slice_count_fix_1 = 1 * (myDim_nod2D + eDim_nod2D) * benthos_num tr_num_start_memo = tr_num_start -! kh 22.11.21 request_count = 0 #endif @@ -387,7 +379,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) !!! !$ACC HOST (tracers%work%edge_up_dn_grad) #if defined(__recom) && defined(__usetp) -! kh 19.11.21 broadcast tracer results to fesom groups +! broadcast tracer results to fesom groups if(num_fesom_groups > 1) then do group_i = 0, num_fesom_groups - 1 @@ -400,7 +392,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) else request_count = request_count + 1 -! kh 22.11.21 non-blocking communication overlapped with computation in loop +! non-blocking communication overlapped with computation in loop call MPI_IBcast(tracers%data(tr_num_to_send)%values(:, :), tr_arr_slice_count_fix_1, MPI_DOUBLE_PRECISION, & group_i, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, tr_arr_requests(request_count), MPIerr) @@ -417,7 +409,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) end do ! EITHER: tr_num = tr_num_start, tr_num_end OR 1, tracers%num_tracers, depending on __usetp #if defined(__recom) && defined(__usetp) -! kh 19.11.21 if tracer in group was added to compensate for fragmentation its broadcast of the last index is handled here +! if tracer in group was added to compensate for fragmentation its broadcast of the last index is handled here if(num_fesom_groups > 1) then do group_i = 0, num_fesom_groups - 1 call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group_dummy, has_one_added_tracer) @@ -459,7 +451,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) #endif #if defined(__recom) && defined(__usetp) -! kh 25.03.22 SinkFlx and Benthos values are buffered per tracer index in the loop above and now summed up to +! SinkFlx and Benthos values are buffered per tracer index in the loop above and now summed up to ! avoid non bit identical results regarding global sums when running the tracer loop in parallel do tr_num = 1, num_tracers if(use_MEDUSA) then @@ -2164,7 +2156,7 @@ FUNCTION transit_bc_surface(n, id, sst, sss, aice, sval, nzmin, partit, mesh) END FUNCTION !=============================================================================== -! kh 11.11.21 divide the range specified by indexcount into fesom_group_count equal slices and calculate +! divide the range specified by indexcount into fesom_group_count equal slices and calculate ! the start_index and end_index for the given fesom_group_id. ! if necessary to compensate for fragmentation, the end index of the first n slices ! might be one higher than for the remaining slices. this is indicated by end_index_is_one_higher @@ -2186,7 +2178,7 @@ subroutine calc_slice(index_count, fesom_group_count, fesom_group_id, start_inde group_id_limit_to_adjust_end_index = mod(index_count, fesom_group_count) start_index = (fesom_group_id * index_count_in_group) + 1 -! kh 11.11.21 adjust loop start and number of loop iterations by 1 if necessary +! adjust loop start and number of loop iterations by 1 if necessary if(fesom_group_id < group_id_limit_to_adjust_end_index) then start_index = start_index + fesom_group_id index_count_in_group = index_count_in_group + 1 diff --git a/src/oce_modules.F90 b/src/oce_modules.F90 index c31b2cea9..0bee8fe45 100755 --- a/src/oce_modules.F90 +++ b/src/oce_modules.F90 @@ -208,11 +208,9 @@ MODULE o_ARRAYS real(kind=WP), allocatable :: dtr_bf(:,:), str_bf(:,:) real(kind=WP), allocatable :: vert_sink(:,:) #if defined(__usetp) -! kh 22.11.21 integer :: request_count integer, allocatable :: tr_arr_requests(:), tr_arr_old_requests(:) -! kh 28.03.22 integer, allocatable :: SinkFlx_tr_requests(:) integer, allocatable :: Benthos_tr_requests(:) #endif diff --git a/src/oce_setup_step.F90 b/src/oce_setup_step.F90 index ab1abc97d..f8c47fe70 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -858,7 +858,6 @@ SUBROUTINE arrays_init(num_tracers, partit, mesh) allocate(vert_sink ( nl-1, node_size )) allocate(Alk_surf ( node_size )) #if defined(__usetp) -! kh 22.11.21 allocate(tr_arr_requests(num_tracers), tr_arr_old_requests(num_tracers)) allocate(SinkFlx_tr_requests(num_tracers)) allocate(Benthos_tr_requests(num_tracers)) @@ -973,7 +972,6 @@ SUBROUTINE arrays_init(num_tracers, partit, mesh) vert_sink = 0.0_WP Alk_surf = 0.0_WP #if defined(__usetp) -! kh 23.03.22 tr_arr_requests = 0 tr_arr_old_requests = 0 SinkFlx_tr_requests = 0 From 132066d5986900a25ba1b1d7b11c62f4e6a7ab84 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Thu, 26 Jun 2025 23:27:31 +0200 Subject: [PATCH 16/68] fix for ltra_diag in recom_main and for restart with TP in io_restart.F90.F90 --- src/int_recom/recom_main.F90 | 4 ++-- src/io_restart.F90 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/int_recom/recom_main.F90 b/src/int_recom/recom_main.F90 index c19041a81..fb44e5406 100755 --- a/src/int_recom/recom_main.F90 +++ b/src/int_recom/recom_main.F90 @@ -246,7 +246,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) ttf_rhs_bak = 0.0 ! OG - tra_diag - if (tracers%data(tr_num)%ltra_diag) then ! OG - tra_diag + if (tracers%data(1)%ltra_diag) then ! OG - tra_diag do tr_num=1, num_tracers ttf_rhs_bak(1:nzmax,tr_num) = tracers%data(tr_num)%values(1:nzmax, n) end do @@ -338,7 +338,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) end do ! recom_sms - if (tracers%data(tr_num)%ltra_diag) then ! OG - tra_diag + if (tracers%data(1)%ltra_diag) then ! OG - tra_diag do tr_num=1, num_tracers tracers%work%tra_recom_sms(1:nzmax,n,tr_num) = tracers%data(tr_num)%values(1:nzmax, n) - ttf_rhs_bak(1:nzmax,tr_num) !if (mype==0) print *, tra_recom_sms(:,:,tr_num) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 77d0ee2cf..e0c130202 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -554,7 +554,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr do group_i = 0, num_fesom_groups - 1 call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group, has_one_added_tracer) - call MPI_Bcast(tracers%data(tr_num_start)%valuesAB(:, :), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) + call MPI_Bcast(tracers%data(tr_num_start)%valuesold(:, :,tr_num_start), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) end do end if #endif From 17cc3b14456d71d4423fdf4d672122369e4d8023 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 27 Jun 2025 11:29:27 +0200 Subject: [PATCH 17/68] set ltra_diag by default to false and improve alignment in fesom_module.F90 --- src/MOD_TRACER.F90 | 2 +- src/fesom_module.F90 | 158 +++++++++++++++++++++---------------------- 2 files changed, 80 insertions(+), 80 deletions(-) diff --git a/src/MOD_TRACER.F90 b/src/MOD_TRACER.F90 index d1b872a18..ae98f4a6c 100644 --- a/src/MOD_TRACER.F90 +++ b/src/MOD_TRACER.F90 @@ -22,7 +22,7 @@ MODULE MOD_TRACER integer :: ID !___________________________________________________________________________ ! TODO: Make it as a part of namelist.tra -logical :: ltra_diag = .true. ! OG - tra_diag +logical :: ltra_diag = .false. ! OG - tra_diag contains procedure WRITE_T_TRACER_DATA diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 88da396aa..749c9adf8 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -137,7 +137,7 @@ subroutine fesom_init(fesom_total_nsteps) integer :: mype_check ! get current value for num_fesom_groups - call read_namelist_run_config + call read_namelist_run_config #endif #if !defined __ifsinterface @@ -194,101 +194,101 @@ subroutine fesom_init(fesom_total_nsteps) #if defined(__recom) && defined(__usetp) ! prepare communicator splitting for multi FESOM group loop parallelization - f%my_fesom_group=>f%partit%my_fesom_group + f%my_fesom_group=>f%partit%my_fesom_group - f%MPI_COMM_FESOM_WORLD=> f%partit%MPI_COMM_FESOM_WORLD - f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS=> f%partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS + f%MPI_COMM_FESOM_WORLD=> f%partit%MPI_COMM_FESOM_WORLD + f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS=> f%partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS - f%MPI_COMM_FESOM_WORLD = f%MPI_COMM_FESOM - npes_fesom_world = f%npes - mype_fesom_world = f%mype - if(mype_fesom_world == 0) then - write(*,*) 'npes_fesom_world, num_fesom_groups', npes_fesom_world, num_fesom_groups - end if - if(mod(npes_fesom_world, num_fesom_groups) /= 0) then + f%MPI_COMM_FESOM_WORLD = f%MPI_COMM_FESOM + npes_fesom_world = f%npes + mype_fesom_world = f%mype if(mype_fesom_world == 0) then - write(*,*) 'MPI_comm_split mismatch npes_fesom_world, num_fesom_groups', npes_fesom_world, num_fesom_groups + write(*,*) 'npes_fesom_world, num_fesom_groups', npes_fesom_world, num_fesom_groups + end if + if(mod(npes_fesom_world, num_fesom_groups) /= 0) then + if(mype_fesom_world == 0) then + write(*,*) 'MPI_comm_split mismatch npes_fesom_world, num_fesom_groups', npes_fesom_world, num_fesom_groups + end if + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop end if - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if - processes_per_group = npes_fesom_world / num_fesom_groups - if(mype_fesom_world == 0) then - write(*,*) 'processes_per_group', processes_per_group - end if - f%npes = processes_per_group - f%my_fesom_group = mype_fesom_world / processes_per_group - f%mype = mod(mype_fesom_world, processes_per_group) + processes_per_group = npes_fesom_world / num_fesom_groups + if(mype_fesom_world == 0) then + write(*,*) 'processes_per_group', processes_per_group + end if + f%npes = processes_per_group + f%my_fesom_group = mype_fesom_world / processes_per_group + f%mype = mod(mype_fesom_world, processes_per_group) ! split to num_fesom_groups - call MPI_comm_split(f%MPI_COMM_FESOM_WORLD, f%my_fesom_group, 0, f%MPI_COMM_FESOM, f%MPIerr) - if (f%MPIerr /= MPI_SUCCESS) then - write(*,*) 'MPI_comm_split(MPI_COMM_FESOM_WORLD, my_fesom_group, 0, MPI_COMM_FESOM, MPIERR) failed' - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + call MPI_comm_split(f%MPI_COMM_FESOM_WORLD, f%my_fesom_group, 0, f%MPI_COMM_FESOM, f%MPIerr) + if (f%MPIerr /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_split(MPI_COMM_FESOM_WORLD, my_fesom_group, 0, MPI_COMM_FESOM, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if - call MPI_comm_size(f%MPI_COMM_FESOM, npes_check, f%MPIerr) - if(f%MPIerr /= MPI_SUCCESS) then - write(*,*) 'MPI_comm_size(MPI_COMM_FESOM, npes_check, MPIERR) failed' - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + call MPI_comm_size(f%MPI_COMM_FESOM, npes_check, f%MPIerr) + if(f%MPIerr /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_size(MPI_COMM_FESOM, npes_check, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if - call MPI_comm_rank(f%MPI_COMM_FESOM, mype_check, f%MPIerr) - if(f%MPIerr /= MPI_SUCCESS) then - write(*,*) 'MPI_comm_rank(MPI_COMM_FESOM, mype_check, MPIERR) failed' - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + call MPI_comm_rank(f%MPI_COMM_FESOM, mype_check, f%MPIerr) + if(f%MPIerr /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_rank(MPI_COMM_FESOM, mype_check, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if - if(npes_check /= f%npes) then - write(*,*) 'npes mismatch, npes, npes_check', f%npes, npes_check - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + if(npes_check /= f%npes) then + write(*,*) 'npes mismatch, npes, npes_check', f%npes, npes_check + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if - if(mype_check /= f%mype) then - write(*,*) 'mype mismatch, mype, mype_check', f%mype, mype_check - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + if(mype_check /= f%mype) then + write(*,*) 'mype mismatch, mype, mype_check', f%mype, mype_check + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if ! group same ranks in each group for broadcasting - call MPI_comm_split(f%MPI_COMM_FESOM_WORLD, f%mype, f%my_fesom_group, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIERR) - if (f%MPIERR /= MPI_SUCCESS) then - write(*,*) 'MPI_comm_split(MPI_COMM_FESOM_WORLD, mype, my_fesom_group, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIERR) failed' - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + call MPI_comm_split(f%MPI_COMM_FESOM_WORLD, f%mype, f%my_fesom_group, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIERR) + if (f%MPIERR /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_split(MPI_COMM_FESOM_WORLD, mype, my_fesom_group, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if - call MPI_comm_size(f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, npes_check, f%MPIERR) - if(f%MPIERR /= MPI_SUCCESS) then - write(*,*) 'MPI_comm_size(MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, npes_check, MPIERR) failed' - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + call MPI_comm_size(f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, npes_check, f%MPIERR) + if(f%MPIERR /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_size(MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, npes_check, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if - call MPI_comm_rank(f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, mype_check, f%MPIERR) - if(f%MPIERR /= MPI_SUCCESS) then - write(*,*) 'MPI_comm_rank(MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, mype_check, MPIERR) failed' - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + call MPI_comm_rank(f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, mype_check, f%MPIERR) + if(f%MPIERR /= MPI_SUCCESS) then + write(*,*) 'MPI_comm_rank(MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, mype_check, MPIERR) failed' + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if - if(npes_check /= num_fesom_groups) then - write(*,*) 'npes mismatch, num_fesom_groups, npes_check', num_fesom_groups, npes_check - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + if(npes_check /= num_fesom_groups) then + write(*,*) 'npes mismatch, num_fesom_groups, npes_check', num_fesom_groups, npes_check + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if - if(mype_check /= f%my_fesom_group) then - write(*,*) 'mype mismatch, my_fesom_group, mype_check', f%my_fesom_group, mype_check - call par_ex(f%MPI_COMM_FESOM, f%mype) - stop - end if + if(mype_check /= f%my_fesom_group) then + write(*,*) 'mype mismatch, my_fesom_group, mype_check', f%my_fesom_group, mype_check + call par_ex(f%MPI_COMM_FESOM, f%mype) + stop + end if if(f%my_fesom_group==0) then #endif @@ -303,7 +303,7 @@ subroutine fesom_init(fesom_total_nsteps) end if #if defined(__recom) && defined(__usetp) - end if + end if ! f%my_fesom_group==0 #endif !===================== From 9247ca4d9e1e5313db510bd3bb92f8c7c31d623f Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 27 Jun 2025 14:47:22 +0200 Subject: [PATCH 18/68] fix in io_restart.F90 for writing restart --- src/io_restart.F90 | 50 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index e0c130202..c502b679f 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -305,7 +305,6 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr integer :: cstep #if defined(__recom) && defined(__usetp) -! nl is required #include "associate_part_def.h" #include "associate_mesh_def.h" #include "associate_part_ass.h" @@ -546,7 +545,8 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr else is_bin_restart_write = is_due(trim(bin_restart_length_unit), bin_restart_length, istep) end if - + + ! --> should write #if defined(__recom) && defined(__usetp) if(num_fesom_groups > 1) then tr_arr_slice_count_fix_1 = 1 * (nl - 1) * (myDim_nod2D + eDim_nod2D) @@ -554,7 +554,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr do group_i = 0, num_fesom_groups - 1 call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group, has_one_added_tracer) - call MPI_Bcast(tracers%data(tr_num_start)%valuesold(:, :,tr_num_start), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) + call MPI_Bcast(tracers%data(tr_num_start)%valuesold(1,:,:), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) end do end if #endif @@ -572,22 +572,32 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ! if(partit%mype==0) write(*,*)'Do output (netCDF, restart) ...' if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: ocean'//achar(27)//'[0m' + call write_restart(oce_path, oce_files, istep) + #if defined(__recom) && defined(__usetp) endif !(partit%my_fesom_group == 0) then #endif - call write_restart(oce_path, oce_files, istep) - !___________________________________________________________________________ ! write ICE/ICEPACK restart if(use_ice) then + +#if defined(__recom) && defined(__usetp) + if(partit%my_fesom_group == 0) then +#endif + #if defined(__icepack) if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: icepack'//achar(27)//'[0m' call write_restart(icepack_path, icepack_files, istep) #else if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: ice'//achar(27)//'[0m' call write_restart(ice_path, ice_files, istep) -#endif +#endif + +#if defined(__recom) && defined(__usetp) + endif !(partit%my_fesom_group == 0) then +#endif + end if !___________________________________________________________________________ @@ -598,22 +608,39 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr if(partit%my_fesom_group == 0) then #endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: bio'//achar(27)//'[0m' + call write_restart(bio_path, bio_files, istep) + #if defined(__usetp) endif #endif - call write_restart(bio_path, bio_files, istep) end if #endif - end if + + end if !is_portable_restart_write ! write core dump - if(is_raw_restart_write) then + if(is_raw_restart_write) theni + +#if defined(__recom) && defined(__usetp) + if(partit%my_fesom_group == 0) then +#endif + call write_all_raw_restarts(istep, partit%MPI_COMM_FESOM, partit%mype) + +#if defined(__recom) && defined(__usetp) + endif !(partit%my_fesom_group == 0) then +#endif + end if ! write derived type binary if(is_bin_restart_write) then + +#if defined(__recom) && defined(__usetp) + if(partit%my_fesom_group == 0) then +#endif + ! current (total) model step --> cstep = globalstep+istep call write_all_bin_restarts((/globalstep+istep, int(ctime), yearnew/), & bin_restart_dirpath, & @@ -623,6 +650,11 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr ice, & dynamics, & tracers ) + +#if defined(__recom) && defined(__usetp) + endif !(partit%my_fesom_group == 0) then +#endif + end if ! actualize clock file to latest restart point From fc517d5269b56b713e15779d73ab0c806ffb9ace Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 27 Jun 2025 14:52:50 +0200 Subject: [PATCH 19/68] fix continued --- src/io_restart.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index a437eca03..e4e98975c 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -546,7 +546,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr is_bin_restart_write = is_due(trim(bin_restart_length_unit), bin_restart_length, istep) end if - ! --> should write + ! --> synchronizes tracer data within one fesom group #if defined(__recom) && defined(__usetp) if(num_fesom_groups > 1) then tr_arr_slice_count_fix_1 = 1 * (nl - 1) * (myDim_nod2D + eDim_nod2D) From 6e733228f2ea216d80061e7bef6ba46a5a001809 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 27 Jun 2025 15:06:43 +0200 Subject: [PATCH 20/68] fix in io_restart.F90 --- src/io_restart.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index e4e98975c..fd1d0cfc7 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -620,7 +620,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr end if !is_portable_restart_write ! write core dump - if(is_raw_restart_write) theni + if(is_raw_restart_write) then #if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then From bbcb3fe08e36e4a0b825e3218c2d6ce6dc3eb50a Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Fri, 27 Jun 2025 15:14:35 +0200 Subject: [PATCH 21/68] adapt recom restart writing for AB_order --- src/io_restart.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index fd1d0cfc7..b9875e7d2 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -554,7 +554,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr do group_i = 0, num_fesom_groups - 1 call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group, has_one_added_tracer) - call MPI_Bcast(tracers%data(tr_num_start)%valuesold(1,:,:), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) + call MPI_Bcast(tracers%data(tr_num_start)%valuesold(tracers%data(j)%AB_order-1,:,:), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) end do end if #endif From 96532bf940e1e00ad41c5f56d210655bbd4d2779 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 8 Jul 2025 17:45:47 +0200 Subject: [PATCH 22/68] index of data corrected --- src/io_restart.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index b9875e7d2..18f3d4781 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -554,7 +554,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr do group_i = 0, num_fesom_groups - 1 call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group, has_one_added_tracer) - call MPI_Bcast(tracers%data(tr_num_start)%valuesold(tracers%data(j)%AB_order-1,:,:), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) + call MPI_Bcast(tracers%data(tr_num_start)%valuesold(tracers%data(tr_num_start)%AB_order-1,:,:), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) end do end if #endif From ef3a7a5b5cc6af52145ec0ddbd78c490fd06ec12 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 19 Aug 2025 12:23:32 +0200 Subject: [PATCH 23/68] line with valuesold in io_restart commented --- src/io_restart.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 18f3d4781..6cacb08d8 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -554,7 +554,7 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr do group_i = 0, num_fesom_groups - 1 call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group, has_one_added_tracer) - call MPI_Bcast(tracers%data(tr_num_start)%valuesold(tracers%data(tr_num_start)%AB_order-1,:,:), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) +! call MPI_Bcast(tracers%data(tr_num_start)%valuesold(tracers%data(tr_num_start)%AB_order-1,:,:), tr_arr_slice_count_fix_1 * tr_num_in_group, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) end do end if #endif From b1e140baf5655079fb58523db76591387415cb62 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Thu, 28 Aug 2025 12:37:41 +0200 Subject: [PATCH 24/68] delete duplicates in io_restart --- src/io_restart.F90 | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 6cacb08d8..169ee1995 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -463,15 +463,6 @@ subroutine restart(istep, nstart, ntotal, l_read, which_readr, ice, dynamics, tr #endif end if -#if defined(__recom) && defined(__usetp) - if(partit%my_fesom_group == 0) then -#endif - if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> read restarts from netcdf file: ice'//achar(27)//'[0m' -#if defined(__recom) && defined(__usetp) - endif -#endif - call read_restart(ice_path, ice_files, partit%MPI_COMM_FESOM, partit%mype) - #if defined(__recom) !RECOM restart !read here From e2b740860b2466a6aa362c5f3aadf3e8c1ba1cfe Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Tue, 2 Sep 2025 21:04:21 +0200 Subject: [PATCH 25/68] Fix FESOM-2.6 compilation errors: MPI communicator structure members and duplicate SAVE attributes - Remove conditional compilation for MPI_COMM_FESOM_WORLD, MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, and my_fesom_group in MOD_PARTIT.F90 - Update associate_part_def.h to make MPI communicator pointers always available - Update associate_part_ass.h to remove conditional compilation blocks - Fix duplicate SAVE attribute warnings in cpl_driver.F90 by removing redundant save keywords Fixes compilation errors where __recom and __usetp preprocessor flags were not defined during build. --- src/MOD_PARTIT.F90 | 13 +++++-------- src/associate_part_ass.h | 6 +----- src/associate_part_def.h | 4 ---- src/cpl_driver.F90 | 10 +++++----- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/MOD_PARTIT.F90 b/src/MOD_PARTIT.F90 index 734fa8e84..4d74977d3 100644 --- a/src/MOD_PARTIT.F90 +++ b/src/MOD_PARTIT.F90 @@ -71,13 +71,11 @@ module MOD_PARTIT integer :: MPI_COMM_FESOM ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) integer :: MPI_COMM_WORLD ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) -#if defined(__recom) && defined(__usetp) ! communicator for multi FESOM group loop parallelization - integer :: MPI_COMM_FESOM_WORLD + integer :: MPI_COMM_FESOM_WORLD ! communicator for multi FESOM group loop parallelization - integer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -#endif + integer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS ! MPI Datatypes for interface exchange ! Element fields (2D; 2D integer; 3D with nl-1 or nl levels, 1 - 4 values) @@ -93,13 +91,12 @@ module MOD_PARTIT integer, allocatable :: s_mpitype_nod2D(:), r_mpitype_nod2D(:) integer, allocatable :: s_mpitype_nod2D_i(:), r_mpitype_nod2D_i(:) integer, allocatable :: s_mpitype_nod3D(:,:,:), r_mpitype_nod3D(:,:,:) + integer, allocatable :: s_mpitype_nod4D(:,:,:,:), r_mpitype_nod4D(:,:,:,:) - integer :: MPIERR + integer :: MPIERR -#if defined(__recom) && defined(__usetp) ! multi FESOM group loop parallelization - integer :: my_fesom_group -#endif + integer :: my_fesom_group !!! remPtr_* are constructed during the runtime and shall not be dumped!!! integer, allocatable :: remPtr_nod2D(:), remList_nod2D(:) diff --git a/src/associate_part_ass.h b/src/associate_part_ass.h index 2e7739d01..9034944fb 100644 --- a/src/associate_part_ass.h +++ b/src/associate_part_ass.h @@ -1,7 +1,5 @@ -#if defined(__recom) && defined(__usetp) MPI_COMM_FESOM_WORLD => partit%MPI_COMM_FESOM_WORLD MPI_COMM_FESOM_SAME_RANK_IN_GROUPS => partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -#endif MPI_COMM_FESOM => partit%MPI_COMM_FESOM MPI_COMM_FESOM_IB => partit%MPI_COMM_FESOM_IB com_nod2D => partit%com_nod2D @@ -20,9 +18,7 @@ MPIERR => partit%MPIERR MPIERR_IB => partit%MPIERR_IB npes => partit%npes mype => partit%mype -#if defined(__recom) && defined(__usetp) -my_fesom_group => my_fesom_group -#endif +my_fesom_group => partit%my_fesom_group maxPEnum => partit%maxPEnum part => partit%part diff --git a/src/associate_part_def.h b/src/associate_part_def.h index 3d4f75334..c827a8762 100644 --- a/src/associate_part_def.h +++ b/src/associate_part_def.h @@ -1,7 +1,5 @@ -#if defined(__recom) && defined(__usetp) integer, pointer :: MPI_COMM_FESOM_WORLD integer, pointer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -#endif integer, pointer :: MPI_COMM_FESOM ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) integer, pointer :: MPI_COMM_FESOM_IB ! FESOM communicator copy for icebergs LA: 2023-05-22 type(com_struct), pointer :: com_nod2D @@ -24,9 +22,7 @@ integer, pointer :: MPIERR_IB ! copy for icebergs LA: 2023-05-22 integer, pointer :: npes integer, pointer :: mype -#if defined(__recom) && defined(__usetp) integer, pointer :: my_fesom_group -#endif integer, pointer :: maxPEnum integer, dimension(:), pointer :: part diff --git a/src/cpl_driver.F90 b/src/cpl_driver.F90 index a11ce9368..91b8d8119 100644 --- a/src/cpl_driver.F90 +++ b/src/cpl_driver.F90 @@ -64,11 +64,11 @@ module cpl_driver integer :: commRank integer :: comp_id ! id returned by oasis_init_comp - logical, save :: oasis_was_initialized - logical, save :: oasis_was_terminated - integer, save :: write_grid + logical :: oasis_was_initialized + logical :: oasis_was_terminated + integer :: write_grid - integer, save :: seconds_til_now=0 + integer :: seconds_til_now=0 integer :: ierror ! return error code logical :: rootexchg =.true. ! logical switch @@ -920,7 +920,7 @@ subroutine cpl_oasis3mct_recv(ind, data_array, action, partit) ! integer :: info integer :: j - integer, save :: ncount = 0 + integer :: ncount = 0 real (kind=WP) :: t1, t2, t3 ! !-------------------------------------------------------------------- From 37d16f97eebd17d978c8fee3cf9d58caf6491689 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Thu, 4 Sep 2025 13:26:49 +0200 Subject: [PATCH 26/68] include netcdf.inc added for reading sediment input file --- src/gen_surface_forcing.F90 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index e1e7e94ca..5dd4b55b3 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -1269,6 +1269,7 @@ SUBROUTINE sbc_do(partit, mesh) #endif IMPLICIT NONE + include 'netcdf.inc' real(wp) :: rdate ! date integer :: fld_idx, i logical :: do_rotation_wind, do_rotation_stre, force_newcoeff, update_monthly_flag From 5b05ce6fff2d150e70457c4e366cc8b4a513a03f Mon Sep 17 00:00:00 2001 From: Suvarchal Kumar Cheedela <15322959+suvarchal@users.noreply.github.com> Date: Fri, 5 Sep 2025 11:26:49 +0200 Subject: [PATCH 27/68] Fix preprocessor directives fixed missing #endif after merge with profiling --- src/fesom_module.F90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 58dc27aea..70ea54133 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -961,6 +961,7 @@ subroutine fesom_runloop(current_nsteps) #if defined(__recom) && defined(__usetp) end if +#endif #if defined (FESOM_PROFILING) call fesom_profiler_start("oce_timestep_ale") @@ -987,6 +988,7 @@ subroutine fesom_runloop(current_nsteps) #if defined(__recom) && defined(__usetp) end if +#endif #if defined (FESOM_PROFILING) call fesom_profiler_start("compute_diagnostics") @@ -1012,7 +1014,7 @@ subroutine fesom_runloop(current_nsteps) #endif #if defined(__recom) && defined(__usetp) end if - +#endif ! LA icebergs: 2023-05-17 if (use_icebergs .and. mod(n, steps_per_ib_step)==0.0) then call reset_ib_fluxes From f78e7fd3989123f101186e41cdcc2d49ca3e4193 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Mon, 22 Sep 2025 09:09:03 +0200 Subject: [PATCH 28/68] delete redundant comments in CMakelists --- src/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d2b222d1e..1b269c39e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -250,9 +250,7 @@ if(OPENMP_REPRODUCIBLE) endif() if(${RECOM_COUPLED}) -# target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __usetp) - target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2) -# target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __3Zoo2Det __coccos __usetp) + target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __usetp) #__3Zoo2Det __coccos) endif() if(${CISO_COUPLED}) From 60a118cd64b717749d39ffdb0f9683d1ed2e37db Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 8 Oct 2025 22:21:31 +0200 Subject: [PATCH 29/68] add namelists to use tracer parallelisation --- config/bin_2p1z1d_tp/namelist.config | 80 ++++++ config/bin_2p1z1d_tp/namelist.cvmix | 75 +++++ config/bin_2p1z1d_tp/namelist.dyn | 36 +++ config/bin_2p1z1d_tp/namelist.forcing | 71 +++++ config/bin_2p1z1d_tp/namelist.ice | 40 +++ config/bin_2p1z1d_tp/namelist.icepack | 146 ++++++++++ config/bin_2p1z1d_tp/namelist.io | 108 ++++++++ config/bin_2p1z1d_tp/namelist.io.recom | 1 + config/bin_2p1z1d_tp/namelist.oce | 26 ++ config/bin_2p1z1d_tp/namelist.recom | 353 ++++++++++++++++++++++++ config/bin_2p1z1d_tp/namelist.tra | 78 ++++++ config/bin_2p1z1d_tp/namelist.tra.recom | 1 + 12 files changed, 1015 insertions(+) create mode 100644 config/bin_2p1z1d_tp/namelist.config create mode 100644 config/bin_2p1z1d_tp/namelist.cvmix create mode 100644 config/bin_2p1z1d_tp/namelist.dyn create mode 100644 config/bin_2p1z1d_tp/namelist.forcing create mode 100644 config/bin_2p1z1d_tp/namelist.ice create mode 100644 config/bin_2p1z1d_tp/namelist.icepack create mode 100644 config/bin_2p1z1d_tp/namelist.io create mode 120000 config/bin_2p1z1d_tp/namelist.io.recom create mode 100644 config/bin_2p1z1d_tp/namelist.oce create mode 100644 config/bin_2p1z1d_tp/namelist.recom create mode 100644 config/bin_2p1z1d_tp/namelist.tra create mode 120000 config/bin_2p1z1d_tp/namelist.tra.recom diff --git a/config/bin_2p1z1d_tp/namelist.config b/config/bin_2p1z1d_tp/namelist.config new file mode 100644 index 000000000..345e0a3a8 --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.config @@ -0,0 +1,80 @@ +! 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='m' ! y, m, d, s +/ + +&clockinit ! the model starts at +timenew=0.0 +daynew=1 +yearnew=1948 +/ + +&paths +MeshPath='/home/a/a270105/fesom_meshes/mesh_core2/' +ClimateDataPath='/home/a/a270105/initial_files/pi_init/' +ResultPath='/work/bm1030/a270105/fesommpi-output/fesom-2.6-recom-tp/' +/ + +&restart_log +restart_length=1 ! --> do netcdf restart ( only required for d,h,s cases, y, m take 1) +restart_length_unit='m' !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=1 !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=.true. +use_transit=.false. +/ + +&run_config_tp +num_fesom_groups = 2 +/ + +&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_tp/namelist.cvmix b/config/bin_2p1z1d_tp/namelist.cvmix new file mode 100644 index 000000000..a4b0a248c --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.cvmix @@ -0,0 +1,75 @@ +! namelist for Turbulent Kinetic Energy (TKE) +¶m_tke +tke_c_k = 0.1 +tke_c_eps = 0.7 +tke_alpha = 30.0 +tke_mxl_min = 1.0e-8 +tke_kappaM_min = 0.0 +tke_kappaM_max = 100.0 +tke_cd = 3.75 ! for Dirichlet boundary conditions +!tke_cd = 1.0 ! for Neumann boundary conditions +tke_surf_min = 1.0e-4 +tke_min = 1.0e-6 +! tke_mxl_choice ... Can only be 1 or 2, choice of calculation of mixing +! length; currently only Blanke, B., P. Delecluse option is implemented +tke_mxl_choice = 2 +tke_dolangmuir = .false. +/ + +! namelist for IDEMIX von Pollman et al. (2017) +¶m_idemix +idemix_tau_v = 172800.0 ! 2days ! time scale for vertical symmetrisation (sec) +idemix_tau_h = 1296000.0 !15days ! time scale for horizontal symmetrisation +idemix_gamma = 1.570 ! constant of order one derived from the shape of the spectrum in m space (dimensionless) +idemix_jstar = 5.0 ! spectral bandwidth in modes (dimensionless) +idemix_mu0 = 0.33333333 ! dissipation parameter (dimensionless) +idemix_sforcusage = 0.2 +idemix_n_hor_iwe_prop_iter = 5 ! iterations for contribution from horiz. wave propagation +idemix_surforc_file = '/work/ollie/clidyn/forcing/IDEMIX/fourier_smooth_2005_cfsr_inert_rgrid.nc' +idemix_surforc_vname= 'var706' +idemix_botforc_file = '/work/ollie/clidyn/forcing/IDEMIX/tidal_energy_gx1v6_20090205_rgrid.nc' +idemix_botforc_vname= 'wave_dissipation' +/ + +! namelist for PP +¶m_pp +pp_use_fesompp = .true. ! if true use fesom flavor off PP if false use original PP of Pacanowski & Philander +pp_Av0 = 0.01 ! mixing coeff. for PP +pp_alpha = 5.0 ! alpha param eq. (1) in Pacanowski and Philander 1981 +pp_exp = 2.0 ! n param eq. (1) in Pacanowski and Philander 1981 +pp_Avbckg = 1.0e-4 ! const. pp background viscosity +pp_Kvbckg = 1.0e-5 ! const. pp background diffusivity +pp_use_nonconstKvb = .true. ! use lat and depth dependent background diffusivity +/ + +! namelist for KPP +¶m_kpp +kpp_use_fesomkpp = .false. ! if true use cvmix MOM5 like kpp if false use cvmix MOM6 like kpp +kpp_use_enhanceKv = .true. ! If true, add enhanced diffusivity at base of boundary layer +kpp_use_compEkman = .true. ! If true, compute Ekman depth limit for OBLdepth +kpp_use_monob = .true. ! If true, compute Monin-Obukhov limit for OBLdepth +kpp_interptype_ri = "linear" ! Type of interpolation in determining OBL depth: linear,quadratic,cubic +kpp_interptype_atobl= "LMD94" ! Type of interpolation of visc and diff at obl depth: linear,quadratic,cubic,LMD94 +kpp_matchtechc = "ParabolicNonLocal" ! Setting diffusivity and NLT profile functions:SimpleShapes, MatchGradient, MatchBoth, ParabolicNonLocal +kpp_internalmix = "KPP" ! Ri-number dependet mixing scheme below the OBL: 'PP' or 'KPP' +kpp_reduce_tauuice = .false. ! If True, reduce the wind stress (ustar) under sea ice. +kpp_Av0 = 5.0e-3 ! leading coefficient of shear mixing formula, units: m^2/s: default= 5e-3 +kpp_Kv0 = 5.0e-3 +kpp_Ri0 = 0.7 ! critical Richardson number value, units: unitless (0.7 in LMD94) +kpp_pp_Av0 = 0.01 ! Parameter in case of PP mixing below the OBL +kpp_use_nonconstKvb= .true. ! If True use non constant background diffusivity of Qiang from FESOM1.4 +kpp_Avbckg = 1.0e-4 ! Values for const. background viscosity and diffusivity +kpp_Kvbckg = 1.0e-5 +/ + +! namelist for TIDAL +¶m_tidal +tidal_mixscheme = "Simmons" +tidal_efficiency = 0.2 ! units: unitless (fraction); (Gamma in Simmons et al.) +tidal_vert_decayscale= 500.0 ! units: m; zeta in Simmons et al. (used to compute the vertical deposition function) +tidal_max_coeff = 50e-4 ! units: m^2/s; largest acceptable value for diffusivity +tidal_lcl_mixfrac = 0.33 !tidal dissipation efficiency (q in Simmons et al.), i.e. fraction of energy that dissipates locally +tidal_depth_cutoff = 0.0 !depth of the shallowest column where tidal mixing is computed (positive below surface) +tidal_botforc_file = '/albedo/work/projects/p_pool_fesom1/fesom2.0/forcing/idemix/tidal_energy_gx1v6_20090205_rgrid.nc' +/ + diff --git a/config/bin_2p1z1d_tp/namelist.dyn b/config/bin_2p1z1d_tp/namelist.dyn new file mode 100644 index 000000000..545a7fe67 --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.dyn @@ -0,0 +1,36 @@ +&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 +check_opt_visc=.true. ! check if optvisc=5 is valid based on ratio resol/rossbyR +! 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 +AB_order=2 + +use_ssh_se_subcycl = .false. +se_BTsteps = 50 +se_BTtheta = 0.14 ! default: 0.14, +se_bottdrag = .true. +se_bdrag_si = .true. ! bottomdrag semi-implicite/explicite +se_visc = .true. +se_visc_gamma0 = 10 +se_visc_gamma1 = 19500 !19500 (core2@32spd), 2750 (core2@72spd) +se_visc_gamma2 = 0 +/ + diff --git a/config/bin_2p1z1d_tp/namelist.forcing b/config/bin_2p1z1d_tp/namelist.forcing new file mode 100644 index 000000000..10d706178 --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.forcing @@ -0,0 +1,71 @@ +! This is the namelist file for forcing + +&forcing_exchange_coeff +Ce_atm_oce=1.75e-3 ! exchange coeff. of latent heat over open water +Ch_atm_oce=1.75e-3 ! exchange coeff. of sensible heat over open water +Cd_atm_oce=1.0e-3 ! drag coefficient between atmosphere and water +Ce_atm_ice=1.75e-3 ! exchange coeff. of latent heat over ice +Ch_atm_ice=1.75e-3 ! exchange coeff. of sensible heat over ice +Cd_atm_ice=1.2e-3 ! 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:10m, JRA:2m) +ncar_bulk_z_tair=10.0 ! height at which temp forcing is located (CORE:10m, JRA:2m) +ncar_bulk_z_shum=10.0 ! height at which humi forcing is located (CORE:10m, JRA:2m) + +/ + +&land_ice +use_landice_water=.false. +landice_start_mon=5 +landice_end_mon=10 +/ + +&age_tracer +use_age_tracer=.false. +use_age_mask=.false. +age_tracer_path='./mesh/' +age_start_year=2000 +/ + +&nam_sbc + nm_xwind_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/u_10.15JUNE2009' ! name of file with winds, if nm_sbc=2 + nm_ywind_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/v_10.15JUNE2009' ! name of file with winds, if nm_sbc=2 + nm_humi_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/q_10.15JUNE2009' ! name of file with humidity + nm_qsr_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/ncar_rad.15JUNE2009' ! name of file with solar heat + nm_qlw_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/ncar_rad.15JUNE2009' ! name of file with Long wave + nm_tair_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/t_10.15JUNE2009' ! name of file with 2m air temperature + nm_prec_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/ncar_precip.15JUNE2009' ! name of file with total precipitation + nm_snow_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/ncar_precip.15JUNE2009' ! name of file with snow precipitation + nm_mslp_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/slp.15JUNE2009' ! air_pressure_at_sea_level + nm_xwind_var = 'U_10_MOD' ! name of variable in file with wind + nm_ywind_var = 'V_10_MOD' ! name of variable in file with wind + nm_humi_var = 'Q_10_MOD' ! name of variable in file with humidity + nm_qsr_var = 'SWDN_MOD' ! name of variable in file with solar heat + nm_qlw_var = 'LWDN_MOD' ! name of variable in file with Long wave + nm_tair_var = 'T_10_MOD' ! name of variable in file with 2m air temperature + nm_prec_var = 'RAIN' ! name of variable in file with total precipitation + nm_snow_var = 'SNOW' ! name of variable in file with total precipitation + nm_mslp_var = 'SLP' ! name of variable in file with air_pressure_at_sea_level + nm_nc_iyear = 1948 + 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 = 1 ! 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. + nm_runoff_file ='/home/a/a270105/fesom_standalone_forcing/CYNF_v2/runoff.15JUNE2009.nc' + runoff_data_source ='CORE2' !Dai09, CORE2 + nm_sss_data_file ='/home/a/a270105/fesom_standalone_forcing/CYNF_v2/PHC2_salx.2004_08_03.nc' + sss_data_source ='CORE2' + 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 ='FORCING/Sweeney/Sweeney_2005.nc' + chl_const = 0.1 + use_runoff_mapper = .FALSE. + runoff_basins_file = 'FORCING/CORE2/runoff_maps_regular.nc' + runoff_radius = 500000. +/ diff --git a/config/bin_2p1z1d_tp/namelist.ice b/config/bin_2p1z1d_tp/namelist.ice new file mode 100644 index 000000000..bf7ea69bd --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.ice @@ -0,0 +1,40 @@ +! 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. +iclasses=7 ! default = 7; in case of EM distribution ('new_iceclasses=.true.') must be set to 15 +h0=0.5 ! Lead closing parameter for Nothern Hemisphere [m], default 0.5 +h0_s=0.5 ! Lead closing parameter [m] for Southern Hemisphere, default 0.5 +hmin=0.01 ! default=0.01 +armin=0.01 ! default=0.01 +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 +snowdist=.true. ! distribution of snow depth according to ice distribution - default: .true. +new_iclasses=.false. ! default=.false.; ice thickness distribution based on EM observations (Castro-Morales et al., JGR, 2013) +open_water_albedo=0 ! 0=default; 1=taylor; 2=briegleb +c_melt=0.5 ! constant in concentration equation for melting conditions - default=0.5 +h_cutoff=3.0 ! only used for new_iclasses=.true. +/ diff --git a/config/bin_2p1z1d_tp/namelist.icepack b/config/bin_2p1z1d_tp/namelist.icepack new file mode 100644 index 000000000..3fa487147 --- /dev/null +++ b/config/bin_2p1z1d_tp/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 = .true. + 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_tp/namelist.io b/config/bin_2p1z1d_tp/namelist.io new file mode 100644 index 000000000..136296676 --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.io @@ -0,0 +1,108 @@ +&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 =100 !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, 'd', 4, +! 'sss ',1, 'd', 4, +! 'ssh ',1, 'd', 4, +! 'uice ',1, 'd', 4, +! 'vice ',1, 'd', 4, +! 'a_ice ',1, 'd', 4, +! 'd_ice ',1, 'm', 4, +! 'd_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, 'd', 4, + 'salt ',1, 'd', 8, + 'otracers ',1, 'd', 4, +! 'N2 ',1, 'm', 4, +! 'Kv ',1, 'm', 4, +! 'u ',1, 'm', 4, +! 'v ',1, 'm', 4, +! 'unod ',1, 'm', 4, +! 'vnod ',1, 'm', 4, +! 'w ',1, 'm', 4, +! 'Av ',1, 'm', 4, +! 'bolus_u ',1, 'm', 4, +! 'bolus_v ',1, 'm', 4, +! 'bolus_w ',1, 'm', 4, +! 'dpCO2s ',1, 'm', 4, +! 'pCO2s ',1, 'm', 4, +! 'CO2f ',1, 'm', 4, +! 'Hp ',1, 'm', 4, +! 'aFe ',1, 'm', 4, +! 'aN ',1, 'm', 4, +! 'denb ',1, 'm', 4, +! 'benN ',1, 'm', 4, +! 'benC ',1, 'm', 4, +! 'benSi ',1, 'm', 4, +! 'benCalc ',1, 'm', 4, +! 'Chldegd ',1, 'm', 4, +! 'Chldegn ',1, 'm', 4, +! 'NNAd ',1, 'm', 4, +! 'NNAn ',1, 'm', 4, +! 'GPPd ',1, 'm', 4, +! 'GPPn ',1, 'm', 4, +! 'NPPd ',1, 'm', 4, +! 'NPPn ',1, 'm', 4, +! 'NPPc ',1, 'm', 4, +! 'GPPc ',1, 'm', 4, +! 'NNAc ',1, 'm', 4, +! 'Chldegc ',1, 'm', 4, +! 'sinkPON ',1, 'y', 4, +! 'sinkPOC ',1, 'y', 4, +! 'sinkOpal ',1, 'y', 4, +! 'sinkCalc ',1, 'y', 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, +! 'OdegaC ',1, 'm', 4, +! 'kspc ',1, 'm', 4, +! 'rhoSW ',1, 'm', 4, +! 'wsink_det1',1, 'm', 8, +! 'wsink_det2',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, +/ diff --git a/config/bin_2p1z1d_tp/namelist.io.recom b/config/bin_2p1z1d_tp/namelist.io.recom new file mode 120000 index 000000000..11d3279b6 --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.io.recom @@ -0,0 +1 @@ +namelist.io \ No newline at end of file diff --git a/config/bin_2p1z1d_tp/namelist.oce b/config/bin_2p1z1d_tp/namelist.oce new file mode 100644 index 000000000..7af6867f7 --- /dev/null +++ b/config/bin_2p1z1d_tp/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 +reminSi = 0.02d0 +k_o2_remin = 15.d0 ! NEW O2remin mmol m-3; Table 1 in Cram 2018 cites DeVries & Weber 2017 for a range of 0-30 mmol m-3 +/ + +&palimiter_function +NMinSlope = 50.d0 +SiMinSlope = 1000.d0 +NCmin = 0.04d0 !0.05d0 +NCmin_d = 0.04d0 !0.05d0 +NCmin_c = 0.04d0 ! NEW +SiCmin = 0.04d0 +k_Fe = 0.04d0 +k_Fe_d = 0.12d0 +k_Fe_c = 0.09d0 ! NEW +k_si = 4.d0 +P_cm = 3.0d0 ! [1/day] Rate of C-specific photosynthesis +P_cm_d = 3.5d0 +P_cm_c = 2.8d0 ! NEW +/ + +&palight_calculations +k_w = 0.04d0 ! [1/m] Light attenuation coefficient +a_chl = 0.03d0 ! [1/m * 1/(mg Chl)] Chlorophyll specific attenuation coefficients +/ + +&paphotosynthesis +alfa = 0.14d0 ! [(mmol C*m2)/(mg Chl*W*day)] +alfa_d = 0.19d0 ! An initial slope of the P-I curve +alfa_c = 0.10d0 ! NEW +parFrac = 0.43d0 +/ + +&paassimilation +V_cm_fact = 0.7d0 ! scaling factor for temperature dependent maximum of C-specific N-uptake +V_cm_fact_d = 0.7d0 +V_cm_fact_c = 0.7d0 ! NEW +NMaxSlope = 1000.d0 ! Max slope for limiting function +SiMaxSlope = 1000.d0 +NCmax = 0.2d0 ! [mmol N/mmol C] Maximum cell quota of nitrogen (N:C) +NCmax_d = 0.2d0 +NCmax_c = 0.15d0 ! NEW +SiCmax = 0.8d0 +NCuptakeRatio = 0.2d0 ! [mmol N/mmol C] Maximum uptake ratio of N:C +NCUptakeRatio_d = 0.2d0 +NCUptakeRatio_c = 0.2d0 ! NEW +SiCUptakeRatio = 0.2d0 +k_din = 0.55d0 ! [mmol N/m3] Half-saturation constant for nitrate uptake +k_din_d = 1.0d0 +k_din_c = 0.9d0 ! NEW +Chl2N_max = 3.15d0 ! [mg CHL/mmol N] Maximum CHL a : N ratio = 0.3 gCHL gN^-1 +Chl2N_max_d = 4.2d0 +Chl2N_max_c = 3.5d0 ! NEW +res_phy = 0.01d0 ! [1/day] Maintenance respiration rate constant +res_phy_d = 0.01d0 +res_phy_c = 0.01d0 ! NEW +biosynth = 2.33d0 ! [mmol C/mmol N] Cost of biosynthesis +biosynthSi = 0.d0 +/ + +&pairon_chem +totalligand = 1.d0 ! [mumol/m3] order 1. Total free ligand +ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron stability constant +/ + +&pazooplankton +graz_max = 0.31d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilonr = 0.09d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss +res_het = 0.028d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +Redfield = 6.625 ! [mmol C/mmol N] Redfield ratio of C:N = 106:16 +loss_het = 0.04d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) +pzDia = 1.0d0 !0.5d0 ! Maximum diatom preference +sDiaNsq = 0.d0 +pzPhy = 0.5d0 !0.25d0 !1.0d0 ! Maximum nano-phytoplankton preference (NEW: 3/12) +sPhyNsq = 0.d0 +pzCocco = 0.666d0 ! NEW (8/12) +sCoccoNsq = 0.d0 ! NEW +pzMicZoo = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference +sMicZooNsq = 0.d0 ! NEW 3Zoo +tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. +/ + +&pasecondzooplankton +graz_max2 = 0.1d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilon2 = 0.0144d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss +res_zoo2 = 0.0107d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +loss_zoo2 = 0.003d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) +fecal_rate_n = 0.104d0 ! [1/day] Temperature dependent N degradation of \ +fecal_rate_c = 0.236d0 +fecal_rate_n_mes = 0.25d0 ! NEW 3Zoo +fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo +pzDia2 = 1.5d0 !1.d0 ! Maximum diatom preference +sDiaNsq2 = 0.d0 +pzPhy2 = 0.5d0 ! Maximum diatom preference +sPhyNsq2 = 0.d0 +pzCocco2 = 0.5d0 ! NEW +sCoccoNsq2 = 0.d0 ! NEW +pzHet = 1.5d0 !0.8d0 ! Maximum diatom preference +sHetNsq = 0.d0 +t1_zoo2 = 28145.d0 ! Krill temp. function constant1 +t2_zoo2 = 272.5d0 ! Krill temp. function constant2 +t3_zoo2 = 105234.d0 ! Krill temp. function constant3 +t4_zoo2 = 274.15d0 ! Krill temp. function constant3 +/ + +&pathirdzooplankton +graz_max3 = 0.46d0 ! NEW 3Zoo [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilon3 = 0.64d0 ! NEW 3Zoo [(mmol N)2 /m6] Half saturation constant for grazing loss +loss_miczoo = 0.01d0 ! NEW 3Zoo [1/day] Temperature dependent N degradation of extracellular organic N (EON) +res_miczoo = 0.01d0 ! NEW 3Zoo [1/day] Respiration by heterotrophs and mortality (loss to detritus) +pzDia3 = 0.5d0 ! NEW 3Zoo Maximum diatom preference +sDiaNsq3 = 0.d0 ! NEW 3Zoo +pzPhy3 = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference +sPhyNsq3 = 0.d0 ! NEW 3Zoo +pzCocco3 = 0.d0 ! NEW 3Zoo Maximum coccolithophore preference ! ATTENTION: This value needs to be tuned; I start with zero preference! +sCoccoNsq3 = 0.d0 ! NEW 3Zoo +/ + +&pagrazingdetritus +pzDet = 0.5d0 ! Maximum small detritus prefence by first zooplankton +sDetNsq = 0.d0 +pzDetZ2 = 0.5d0 ! Maximum large detritus preference by first zooplankton +sDetZ2Nsq = 0.d0 +pzDet2 = 0.5d0 ! Maximum small detritus prefence by second zooplankton +sDetNsq2 = 0.d0 +pzDetZ22 = 0.5d0 ! Maximum large detritus preference by second zooplankton +sDetZ2Nsq2 = 0.d0 +/ + +&paaggregation +agg_PD = 0.165d0 ! [m3/(mmol N * day)] Maximum aggregation loss parameter for DetN +agg_PP = 0.015d0 ! [m3/(mmol N * day)] Maximum aggregation loss parameter for PhyN and DiaN (plankton) +/ + +&padin_rho_N +rho_N = 0.11d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) (Remineralization of DON) +/ + +&padic_rho_C1 +rho_C1 = 0.1d0 ! [1/day] Temperature dependent C degradation of extracellular organic C (EOC) +/ + +&paphytoplankton_N +lossN = 0.05d0 ! [1/day] Phytoplankton loss of organic N compounds +lossN_d = 0.05d0 +lossN_c = 0.05d0 ! NEW +/ + +&paphytoplankton_C +lossC = 0.10d0 ! [1/day] Phytoplankton loss of carbon +lossC_d = 0.10d0 +lossC_c = 0.10d0 ! NEW +/ + +&paphytoplankton_ChlA +deg_Chl = 0.25d0 !0.2d0 !0.25d0 ! [1/day] +deg_Chl_d = 0.15d0 !0.2d0 !0.15d0 +deg_Chl_c = 0.2d0 ! NEW (has been 0.5) +/ + +&padetritus_N +gfin = 0.3d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into zooplankton pool) +grazEff2 = 0.8d0 ! [] Grazing efficiency (fraction of grazing flux into second zooplankton pool) +grazEff3 = 0.8d0 ! NEW 3Zoo [] Grazing efficiency (fraction of grazing flux into microzooplankton pool) +reminN = 0.165d0 ! [1/day] Temperature dependent remineralisation rate of detritus +/ + +&padetritus_C +reminC = 0.15d0 ! [1/day] Temperature dependent remineralisation rate of detritus +rho_c2 = 0.1d0 ! [1/day] Temperature dependent C degradation of TEP-C +/ + +&paheterotrophs +lossN_z = 0.1d0 +lossC_z = 0.1d0 +/ + +&paseczooloss +lossN_z2 = 0.02d0 +lossC_z2 = 0.02d0 +/ + +&pathirdzooloss +lossN_z3 = 0.05d0 ! NEW 3Zoo +lossC_z3 = 0.05d0 ! NEW 3Zoo +/ + +&paco2lim ! NEW +Cunits = 976.5625 ! Conversion factor between [mol/m3] (model) and [umol/kg] (function): (1000 * 1000) / 1024 +a_co2_phy = 1.162e+00 ! [dimensionless] +a_co2_dia = 1.040e+00 ! [dimensionless] +a_co2_cocco = 1.109e+00 ! [dimensionless] +a_co2_calc = 1.102e+00 ! [dimensionless] +b_co2_phy = 4.888e+01 ! [mol/kg] +b_co2_dia = 2.890e+01 ! [mol/kg] +b_co2_cocco = 3.767e+01 ! [mol/kg] +b_co2_calc = 4.238e+01 ! [mol/kg] +c_co2_phy = 2.255e-01 ! [kg/mol] +c_co2_dia = 8.778e-01 ! [kg/mol] +c_co2_cocco = 3.912e-01 ! [kg/mol] +c_co2_calc = 7.079e-01 ! [kg/mol] +d_co2_phy = 1.023e+07 ! [kg/mol] +d_co2_dia = 2.640e+06 ! [kg/mol] +d_co2_cocco = 9.450e+06 ! [kg/mol] +d_co2_calc = 1.343e+07 ! [kg/mol] +/ + +&pairon +Fe2N = 0.033d0 ! Fe2C * 6.625 +Fe2N_benthos = 0.15d0 ! test, default was 0.14 Fe2C_benthos * 6.625 - will have to be tuned. [umol/m2/day] +kScavFe = 0.07d0 +dust_sol = 0.02d0 ! Dissolution of Dust for bioavaliable +RiverFeConc = 100 +/ + +&pacalc +calc_prod_ratio = 0.02 +calc_diss_guts = 0.0d0 +calc_diss_rate = 0.005714 ! 20.d0/3500.d0 +calc_diss_rate2 = 0.005714d0 +calc_diss_omegac = 0.197d0 ! NEW DISS Value from Aumont et al. 2015, will be used with OmegaC_diss flag +calc_diss_exp = 1.d0 ! NEW DISS Exponent in the dissolution rate of calcite, will be used with OmegaC_diss flag +/ + +&pabenthos_decay_rate +decayRateBenN = 0.005d0 +decayRateBenC = 0.005d0 +decayRateBenSi = 0.005d0 +q_NC_Denit = 0.86d0 ! N:C quota of the denitrification process +/ + +&paco2_flux_param +permil = 0.000000976 ! 1.e-3/1024.5d0 ! Converting DIC from [mmol/m3] to [mol/kg] +permeg = 1.e-6 ! [atm/uatm] Changes units from uatm to atm +!X1 = exp(-5.d0*log(10.d0)) ! Lowest ph-value = 7.7 (phlo) +!X2 = exp(-9.d0*log(10.d0)) ! Highest ph-value = 9.5 (phhi) +Xacc = 1.e-12 ! Accuracy for ph-iteration (phacc) +CO2_for_spinup = 278.d0 ! [uatm] Atmospheric partial pressure of CO2 +/ + +&paalkalinity_restoring +surf_relax_Alk = 3.2e-07 !10.d0/31536000.d0 +/ + +&paballasting +rho_POC = 1033.d0 ! kg m-3; density of POC (see Table 1 in Cram et al., 2018) +rho_PON = 1033.d0 ! kg m-3; density of PON (see Table 1 in Cram et al., 2018) +rho_CaCO3 = 2830.d0 ! kg m-3; density of CaCO3 (see Table 1 in Cram et al., 2018) +rho_opal = 2090.d0 ! kg m-3; density of Opal (see Table 1 in Cram et al., 2018) +rho_ref_part = 1230.d0 ! kg m-3; reference particle density (see Cram et al., 2018) +rho_ref_water = 1027.d0 ! kg m-3; reference seawater density (see Cram et al., 2018) +visc_ref_water = 0.00158d0 ! kg m-1 s-1; reference seawater viscosity, at Temp=4 degC (see Cram et al., 2018) +w_ref1 = 10.d0 ! m s-1; reference sinking velocity of small detritus +w_ref2 = 200.d0 ! m s-1; reference sinking velocity of large detritus +depth_scaling1 = 0.015d0 ! s-1; factor to increase sinking speed of det1 with depth, set to 0 if not wanted +depth_scaling2 = 0.d0 ! s-1; factor to increase sinking speed of det2 with depth, set to 0 if not wanted +max_sinking_velocity = 250.d0 ! d-1; for numerical stability, set a maximum possible sinking velocity here (applies to both detritus classes) +/ + +&paciso +ciso_init = .false. ! initial fractionation of bulk organic matter +ciso_14 = .false. ! include inorganic radiocarbon +ciso_organic_14 = .false. ! include organic radiocarbon +lambda_14 = 3.8561e-12 ! corresponding to 1 year = 365.00 days +delta_CO2_13 = -6.61 ! atmospheric d13C (permil), global-mean value +big_delta_CO2_14(1) = 0. ! atmospheric D14C (permil), northern hemisphere polewards of 30°N +big_delta_CO2_14(2) = 0. ! atmospheric D14C (permil), (sub) tropical zone 30°N - 30°S +big_delta_CO2_14(3) = 0. ! atmospheric D14C (permil), southern hemisphere polewards of 30°S +atbox_spinup = .false. +cosmic_14_init = 2.0 +/ + diff --git a/config/bin_2p1z1d_tp/namelist.tra b/config/bin_2p1z1d_tp/namelist.tra new file mode 100644 index 000000000..cd80236ef --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.tra @@ -0,0 +1,78 @@ +&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. +/ + +&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/config/bin_2p1z1d_tp/namelist.tra.recom b/config/bin_2p1z1d_tp/namelist.tra.recom new file mode 120000 index 000000000..61e7b70fb --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.tra.recom @@ -0,0 +1 @@ +namelist.tra \ No newline at end of file From 360d2246bd0770dfea10c13b2f69b6baa9e90bc1 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 15 Oct 2025 12:35:53 +0200 Subject: [PATCH 30/68] change sizeof(cpl_send/recv) to nsend/nrecv in fesom_module.F90 --- src/fesom_module.F90 | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index f7534e2f4..1cc71fa97 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -140,7 +140,7 @@ subroutine fesom_init(fesom_total_nsteps) integer :: processes_per_group integer :: npes_check integer :: mype_check - + integer :: i ! get current value for num_fesom_groups call read_namelist_run_config #endif @@ -507,11 +507,10 @@ subroutine fesom_init(fesom_total_nsteps) #if defined(__recom) && defined(__usetp) call MPI_Barrier(f%MPI_COMM_FESOM_WORLD, f%MPIERR) + if(num_fesom_groups > 1) then - - call MPI_Bcast(cpl_send, sizeof(cpl_send), MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) - call MPI_Bcast(cpl_recv, sizeof(cpl_recv), MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) - + call MPI_Bcast(cpl_send, nsend, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + call MPI_Bcast(cpl_recv, nrecv, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) ! needed in SUBROUTINE net_rec_from_atm(action) call MPI_Bcast(target_root, 1, MPI_INTEGER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) end if @@ -1062,7 +1061,7 @@ subroutine fesom_finalize() ! EO parameters real(kind=real32) :: mean_rtime(15), max_rtime(15), min_rtime(15) integer :: tr_num - integer :: i !YY + integer :: i ! Start finalization profiling #if defined (FESOM_PROFILING) From 2804139ad94d9237189ad38d75d968e683aa63e7 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 22 Oct 2025 14:10:07 +0200 Subject: [PATCH 31/68] remove usetp from default to test awiesm-2.6-recom --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1b269c39e..16d9142ef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -250,7 +250,7 @@ if(OPENMP_REPRODUCIBLE) endif() if(${RECOM_COUPLED}) - target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __usetp) #__3Zoo2Det __coccos) + target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2) #__usetp) __3Zoo2Det __coccos) endif() if(${CISO_COUPLED}) From 67475c1919af55012d63d57fb58a6b005b9e0348 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 24 Oct 2025 15:28:55 +0200 Subject: [PATCH 32/68] add -fPIC in CMakeLists --- src/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 16d9142ef..a7853b010 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -250,7 +250,7 @@ if(OPENMP_REPRODUCIBLE) endif() if(${RECOM_COUPLED}) - target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2) #__usetp) __3Zoo2Det __coccos) + target_compile_definitions(${PROJECT_NAME} PRIVATE __recom USE_PRECISION=2 __usetp) #__3Zoo2Det __coccos) endif() if(${CISO_COUPLED}) @@ -265,7 +265,7 @@ endif() if(${CMAKE_Fortran_COMPILER_ID} STREQUAL Intel OR ${CMAKE_Fortran_COMPILER_ID} STREQUAL IntelLLVM ) # Base compiler flags - target_compile_options(${PROJECT_NAME} PRIVATE -O3 -r8 -i4 -fp-model precise -no-prec-div -fimf-use-svml -init=zero -no-wrap-margin -fpe0 -fpp) + target_compile_options(${PROJECT_NAME} PRIVATE -O3 -r8 -i4 -fp-model precise -no-prec-div -fimf-use-svml -init=zero -no-wrap-margin -fpe0 -fpp -fPIC) # compiler flags not supported by IntelLLVM if(${CMAKE_Fortran_COMPILER_ID} STREQUAL Intel ) @@ -360,7 +360,7 @@ elseif(${CMAKE_Fortran_COMPILER_ID} STREQUAL GNU ) # | | -mno-fma4 -mavx2 -mfma | | # | GCC/openMPI | -O3 -march=znver3 -mtune=znver3 -ftree-vectorize -flto | 280s | chatgpt recomendation # | | -mcpu=znver3 | | - target_compile_options(${PROJECT_NAME} PRIVATE -march=znver3 -mtune=znver3 -ftree-vectorize -flto) + target_compile_options(${PROJECT_NAME} PRIVATE -march=znver3 -mtune=znver3 -ftree-vectorize -flto -fPIC) else() #[[if(NOT (${FESOM_PLATFORM_STRATEGY} STREQUAL ubuntu)) target_compile_options(${PROJECT_NAME} PRIVATE -native) From 9a03b2d4d5ffdd8895067f49b07f21d15932ebd4 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Mon, 27 Oct 2025 19:08:59 +0100 Subject: [PATCH 33/68] put num_fesom_groups back to run_config --- config/bin_2p1z1d_tp/namelist.config | 3 --- src/gen_model_setup.F90 | 27 --------------------------- src/gen_modules_config.F90 | 3 +-- 3 files changed, 1 insertion(+), 32 deletions(-) diff --git a/config/bin_2p1z1d_tp/namelist.config b/config/bin_2p1z1d_tp/namelist.config index 345e0a3a8..c8d4aa31c 100644 --- a/config/bin_2p1z1d_tp/namelist.config +++ b/config/bin_2p1z1d_tp/namelist.config @@ -60,9 +60,6 @@ use_floatice = .false. use_sw_pene=.true. flag_debug=.true. use_transit=.false. -/ - -&run_config_tp num_fesom_groups = 2 / diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index b7f959766..7222e1280 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -310,33 +310,6 @@ subroutine setup_model(partit) ! if ((output_length_unit=='s').or.(int(real(step_per_day)/24.0)<=1)) use_means=.false. end subroutine setup_model - -#if defined(__recom) && defined(__usetp) -! read num_fesom_groups for multi FESOM group loop parallelization -! ================================================================= -subroutine read_namelist_run_config(partit) - ! Reads run_config namelist and overwrite default parameters. - ! - ! Copied by Kai Himstedt (based on read_namelist) - !-------------------------------------------------------------- - USE MOD_PARTIT - USE MOD_PARSUP - use g_config - implicit none - type(t_partit), intent(inout), target :: partit - - character(len=100) :: nmlfile - integer fileunit - - nmlfile ='namelist.config' ! name of general configuration namelist file - open (newunit=fileunit, file=nmlfile) - - open (fileunit,file=nmlfile) -! read (fileunit,NML=run_config) - read (fileunit,NML=run_config_tp) - close (fileunit) -end subroutine read_namelist_run_config -#endif ! ================================================================= subroutine get_run_steps(nsteps, partit) ! Coded by Qiang Wang diff --git a/src/gen_modules_config.F90 b/src/gen_modules_config.F90 index b3c36f010..7d0a99475 100755 --- a/src/gen_modules_config.F90 +++ b/src/gen_modules_config.F90 @@ -157,11 +157,10 @@ module g_config use_cavity_partial_cell, cavity_partial_cell_thresh, & use_cavity_fw2press, toy_ocean, which_toy, flag_debug, flag_warn_cflz, lwiso, & use_transit, compute_oasis_corners - #if defined(__recom) && defined(__usetp) ! number of groups for multi FESOM group loop parallelization integer :: num_fesom_groups=1 - namelist /run_config_tp/ num_fesom_groups + namelist /run_config/ num_fesom_groups #endif !_____________________________________________________________________________ From b42fbbd088b3957a8d15c0e7a6eda0af80b7e623 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Mon, 27 Oct 2025 19:34:41 +0100 Subject: [PATCH 34/68] delete read_namelist_run_config --- src/fesom_module.F90 | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 1cc71fa97..1b0cf54cd 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -141,8 +141,6 @@ subroutine fesom_init(fesom_total_nsteps) integer :: npes_check integer :: mype_check integer :: i -! get current value for num_fesom_groups - call read_namelist_run_config #endif #if !defined __ifsinterface From a8b6eb534f9182ad8401c6b9c903a28019297246 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Mon, 27 Oct 2025 22:55:59 +0100 Subject: [PATCH 35/68] turn on RECOM_COUPLED by default --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07316dabb..08bfb5c4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set(OIFS_COUPLED OFF CACHE BOOL "compile fesom coupled to OpenIFS. (Also needs F set(CRAY OFF CACHE BOOL "compile with cray ftn") set(USE_ICEPACK OFF CACHE BOOL "compile fesom with the Iceapck modules for sea ice column physics.") set(OPENMP_REPRODUCIBLE OFF CACHE BOOL "serialize OpenMP loops that are critical for reproducible results") -set(RECOM_COUPLED OFF CACHE BOOL "compile fesom including biogeochemistry, REcoM3") +set(RECOM_COUPLED ON CACHE BOOL "compile fesom including biogeochemistry, REcoM3") set(CISO_COUPLED OFF CACHE BOOL "compile ciso coupled to REcoM3. RECOM_COUPLED has to be active") set(USE_MULTIO OFF CACHE BOOL "Use MULTIO for IO, either grib or binary for now. This also means path to MULTIO installation has to provided using env MULTIO_INSTALL_PATH='..' and multio configuration yamls must be present to run the model with MULTIO") set(OASIS_WITH_YAC OFF CACHE BOOL "Useing a version of OASIS compiled with YAC instead of SCRIP for interpolation?") From 7ec55f2f2ec75673fb93a99071e53f44ebb1b935 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 29 Oct 2025 10:37:36 +0100 Subject: [PATCH 36/68] add read_namelist_run_config back to fesom_module.F90 --- src/fesom_module.F90 | 4 ++++ src/gen_model_setup.F90 | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 1b0cf54cd..72a349256 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -141,6 +141,10 @@ subroutine fesom_init(fesom_total_nsteps) integer :: npes_check integer :: mype_check integer :: i + +! get current value for num_fesom_groups + call read_namelist_run_config + #endif #if !defined __ifsinterface diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index 7222e1280..529d4003f 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -310,6 +310,36 @@ subroutine setup_model(partit) ! if ((output_length_unit=='s').or.(int(real(step_per_day)/24.0)<=1)) use_means=.false. end subroutine setup_model + +#if defined(__recom) && defined(__usetp) +! read num_fesom_groups for multi FESOM group loop parallelization +! ================================================================= +subroutine read_namelist_run_config(partit) + + ! Reads run_config namelist and overwrite default parameters. + ! Copied by Kai Himstedt (based on read_namelist) + + !-------------------------------------------------------------- + USE MOD_PARTIT + USE MOD_PARSUP + use g_config + implicit none + type(t_partit), intent(inout), target :: partit + + character(len=100) :: nmlfile + integer fileunit + + nmlfile ='namelist.config' ! name of general configuration namelist file + open (newunit=fileunit, file=nmlfile) + + open (fileunit,file=nmlfile) + read (fileunit,NML=run_config) + close (fileunit) + +end subroutine read_namelist_run_config + +#endif + ! ================================================================= subroutine get_run_steps(nsteps, partit) ! Coded by Qiang Wang From db9d64ce3570bdd153f42bc1955a085e5cfd5074 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Thu, 30 Oct 2025 17:28:05 +0100 Subject: [PATCH 37/68] replace ifdef with DEC preprocessing flags in .h files --- src/associate_part_ass.h | 8 ++++---- src/associate_part_def.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/associate_part_ass.h b/src/associate_part_ass.h index 2e7739d01..0fb1383af 100644 --- a/src/associate_part_ass.h +++ b/src/associate_part_ass.h @@ -1,7 +1,7 @@ -#if defined(__recom) && defined(__usetp) +!DEC$ IF DEFINED(__recom) .AND. DEFINED(__usetp) MPI_COMM_FESOM_WORLD => partit%MPI_COMM_FESOM_WORLD MPI_COMM_FESOM_SAME_RANK_IN_GROUPS => partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -#endif +!DEC$ ENDIF MPI_COMM_FESOM => partit%MPI_COMM_FESOM MPI_COMM_FESOM_IB => partit%MPI_COMM_FESOM_IB com_nod2D => partit%com_nod2D @@ -20,9 +20,9 @@ MPIERR => partit%MPIERR MPIERR_IB => partit%MPIERR_IB npes => partit%npes mype => partit%mype -#if defined(__recom) && defined(__usetp) +!DEC$ IF DEFINED(__recom) .AND. DEFINED(__usetp) my_fesom_group => my_fesom_group -#endif +!DEC$ ENDIF maxPEnum => partit%maxPEnum part => partit%part diff --git a/src/associate_part_def.h b/src/associate_part_def.h index 3d4f75334..f92f9ae2e 100644 --- a/src/associate_part_def.h +++ b/src/associate_part_def.h @@ -1,7 +1,7 @@ -#if defined(__recom) && defined(__usetp) +!DEC$ IF DEFINED(__recom) .AND. DEFINED(__usetp) integer, pointer :: MPI_COMM_FESOM_WORLD integer, pointer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -#endif +!DEC$ ENDIF integer, pointer :: MPI_COMM_FESOM ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) integer, pointer :: MPI_COMM_FESOM_IB ! FESOM communicator copy for icebergs LA: 2023-05-22 type(com_struct), pointer :: com_nod2D @@ -24,9 +24,9 @@ integer, pointer :: MPIERR_IB ! copy for icebergs LA: 2023-05-22 integer, pointer :: npes integer, pointer :: mype -#if defined(__recom) && defined(__usetp) +!DEC$ IF DEFINED(__recom) .AND. DEFINED(__usetp) integer, pointer :: my_fesom_group -#endif +!DEC$ ENDIF integer, pointer :: maxPEnum integer, dimension(:), pointer :: part From f04fabf85a4c14acfd6ecc53a51459a310cced0f Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 31 Oct 2025 21:58:14 +0100 Subject: [PATCH 38/68] remove preprocessor directives in .h files --- src/associate_part_ass.h | 6 +----- src/associate_part_def.h | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/associate_part_ass.h b/src/associate_part_ass.h index ea6d44711..7f182a021 100644 --- a/src/associate_part_ass.h +++ b/src/associate_part_ass.h @@ -1,7 +1,5 @@ -!DEC$ IF DEFINED(__recom) .AND. DEFINED(__usetp) MPI_COMM_FESOM_WORLD => partit%MPI_COMM_FESOM_WORLD MPI_COMM_FESOM_SAME_RANK_IN_GROUPS => partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -!DEC$ ENDIF MPI_COMM_FESOM => partit%MPI_COMM_FESOM MPI_COMM_FESOM_IB => partit%MPI_COMM_FESOM_IB com_nod2D => partit%com_nod2D @@ -20,9 +18,7 @@ MPIERR => partit%MPIERR MPIERR_IB => partit%MPIERR_IB npes => partit%npes mype => partit%mype -!DEC$ IF DEFINED(__recom) .AND. DEFINED(__usetp) -my_fesom_group => my_fesom_group -!DEC$ ENDIF +my_fesom_group => partit%my_fesom_group maxPEnum => partit%maxPEnum part => partit%part diff --git a/src/associate_part_def.h b/src/associate_part_def.h index f92f9ae2e..c827a8762 100644 --- a/src/associate_part_def.h +++ b/src/associate_part_def.h @@ -1,7 +1,5 @@ -!DEC$ IF DEFINED(__recom) .AND. DEFINED(__usetp) integer, pointer :: MPI_COMM_FESOM_WORLD integer, pointer :: MPI_COMM_FESOM_SAME_RANK_IN_GROUPS -!DEC$ ENDIF integer, pointer :: MPI_COMM_FESOM ! FESOM communicator (for ocean only runs if often a copy of MPI_COMM_WORLD) integer, pointer :: MPI_COMM_FESOM_IB ! FESOM communicator copy for icebergs LA: 2023-05-22 type(com_struct), pointer :: com_nod2D @@ -24,9 +22,7 @@ integer, pointer :: MPIERR_IB ! copy for icebergs LA: 2023-05-22 integer, pointer :: npes integer, pointer :: mype -!DEC$ IF DEFINED(__recom) .AND. DEFINED(__usetp) integer, pointer :: my_fesom_group -!DEC$ ENDIF integer, pointer :: maxPEnum integer, dimension(:), pointer :: part From e07391fc981406605b835b1ce121622adbbed81f Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 4 Nov 2025 11:59:58 +0100 Subject: [PATCH 39/68] pH/DOC dependent parameterisation of Fe-binding ligands completed --- src/int_recom/recom_sms.F90 | 2549 +---------------------------- src/int_recom/recom_sms.F90.nica | 2560 ++++++++++++++++++++++++++++++ src/int_recom/recom_sms.F90.old | 2548 +++++++++++++++++++++++++++++ 3 files changed, 5109 insertions(+), 2548 deletions(-) mode change 100644 => 120000 src/int_recom/recom_sms.F90 create mode 100644 src/int_recom/recom_sms.F90.nica create mode 100644 src/int_recom/recom_sms.F90.old diff --git a/src/int_recom/recom_sms.F90 b/src/int_recom/recom_sms.F90 deleted file mode 100644 index 7259fd893..000000000 --- a/src/int_recom/recom_sms.F90 +++ /dev/null @@ -1,2548 +0,0 @@ -subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & - , CO2_watercolumn & - , pH_watercolumn & - , pCO2_watercolumn & - , HCO3_watercolumn & - , CO3_watercolumn & - , OmegaC_watercolumn & - , kspc_watercolumn & - , rhoSW_watercolumn & - , Loc_slp, zF, PAR, Lond, Latd, ice, dynamics, tracers, partit, mesh) - - use recom_declarations - use recom_locvar - use recom_glovar - use recom_config - use recoM_ciso - use g_clock - - use g_config - use MOD_MESH - use MOD_TRACER - use MOD_DYN - USE MOD_ICE - use o_ARRAYS - use o_PARAM - USE MOD_PARTIT - USE MOD_PARSUP - - use g_forcing_arrays - use g_comm_auto - use mvars - use mdepth2press - use gsw_mod_toolbox, only: gsw_sa_from_sp,gsw_ct_from_pt,gsw_rho - - implicit none - type(t_dyn) , intent(inout), target :: dynamics - type(t_tracer), intent(inout), target :: tracers - type(t_partit), intent(inout), target :: partit - type(t_mesh) , intent(inout), target :: mesh - type(t_ice) , intent(inout), target :: ice - - 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 - - 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 - real(kind=8),intent(in) :: SurfSR !< [W/m2] ShortWave radiation at surface - - real(kind=8),dimension(mesh%nl-1,bgc_num),intent(inout) :: sms !< Source-Minus-Sinks term - real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Temp !< [degrees C] Ocean temperature - real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Sali_depth !< NEW MOCSY Salinity for the whole water column - - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO2_watercolumn !< [mol/m3] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pH_watercolumn !< on total scale - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pCO2_watercolumn !< [uatm] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: HCO3_watercolumn !< [mol/m3] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO3_watercolumn !< [mol/m3] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: OmegaC_watercolumn !< calcite saturation state - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: kspc_watercolumn !< stoichiometric solubility product [mol^2/kg^2] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: rhoSW_watercolumn !< in-situ density of seawater [kg/m3] - - real(kind=8),dimension(mesh%nl) ,intent(in) :: zF !< [m] Depth of fluxes - real(kind=8),dimension(mesh%nl-1),intent(inout) :: PAR - - real(kind=8) :: dt_d !< Size of time steps [day] - real(kind=8) :: dt_b !< Size of time steps [day] - real(kind=8),dimension(mesh%nl-1) :: Sink - real(kind=8) :: dt_sink !< Size of local time step - - real(kind=8) :: recip_hetN_plus !< MB's addition to heterotrophic respiration - real(kind=8) :: recip_res_het !< [day] Reciprocal of respiration by heterotrophs and mortality (loss to detritus) - real(kind=8) :: Sink_Vel - real(kind=8) :: aux - integer :: k,step,ii, idiags,n - - real(kind=8), intent(in) :: Loc_slp ![Pa] sea-level pressure - real(kind=8) :: Patm_depth(1) - real(kind=8) :: REcoM_T_depth(1) ! MOCSY temperature for the whole water column for mocsy minimum defined as -2 - real(kind=8) :: REcoM_S_depth(1) - real(kind=8) :: REcoM_DIC_depth(1) - real(kind=8) :: REcoM_Alk_depth(1) - real(kind=8) :: REcoM_Si_depth(1) - real(kind=8) :: REcoM_Phos_depth(1) - 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 - -#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 - - 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 - - tiny_Si = tiny_C_d/SiCmax !< SiCmax = 0.8d0 - -#if defined (__coccos) - tiny_N_c = tiny_chl/chl2N_max_c - tiny_C_c = tiny_N_c/NCmax_c -#endif - - recip_res_het = 1.d0/res_het !< res_het = 0.01d0 [1/day] Respiration by heterotrophs and mortality (loss to detritus) - - Patm_depth = Loc_slp/Pa2atm ! MOCSY convert from Pa to atm. - -!------------------------------------------------------------------------------- -!> REcoM time steps [day] -!------------------------------------------------------------------------------- - - 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] - -!------------------------------------------------------------------------------- -!Main time loop starts - do step = one,biostep - - kdzUpper = 0.d0 !< Upper light attenuation of top cell is set to zero - - if (any(abs(sms(:,:)) <= tiny)) sms(:,:) = zero ! tiny = 2.23D-16 - -!------------------------------------------------------------------------------- -! 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 - -! 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 - - if (ciso) then -!< additional variables are declared in module REcoM_ciso - 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)) - - calc_diss_13 = alpha_dcal_13 * calc_diss - - 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 - - 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 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) - -!------------------------------------------------------------------------------- -!> 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 - -!------------------------------------------------------------------------------- -! Depth component of Mocsy (see http://ocmip5.ipsl.jussieu.fr/mocsy/pyth.html) -!------------------------------------------------------------------------------- - -! 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. - 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') - CO2_watercolumn(k) = co2_depth(1) - pH_watercolumn(k) = ph_depth(1) - pCO2_watercolumn(k) = pco2_depth(1) - HCO3_watercolumn(k) = hco3_depth(1) - CO3_watercolumn(k) = co3_depth(1) - 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') - CO2_watercolumn(k) = co2_depth(1) - pH_watercolumn(k) = ph_depth(1) - pCO2_watercolumn(k) = pco2_depth(1) - HCO3_watercolumn(k) = hco3_depth(1) - CO3_watercolumn(k) = co3_depth(1) - OmegaC_watercolumn(k) = OmegaC_depth(1) - 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') - CO2_watercolumn(k) = co2_depth(1) - pH_watercolumn(k) = ph_depth(1) - pCO2_watercolumn(k) = pco2_depth(1) - HCO3_watercolumn(k) = hco3_depth(1) - CO3_watercolumn(k) = co3_depth(1) - 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] - -! 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 - -! 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 - 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) - 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?? - 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 - -!< *** Diatom photosynthesis rate *** -!< ********************************** - if ( pMax_dia .lt. 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 - - 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 - else - KOchl = deg_Chl*(real(one) - exp(-alfa * CHL2C_plast * PARave / pMax)) - KOchl = max((deg_Chl*0.1d0), KOchl) - 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 - 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 - 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 - 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 - stop - end if -#endif - end if ! photodamage - -!------------------------------------------------------------------------------- -!> Assimilation section -!------------------------------------------------------------------------------- - -!< 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 - 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 - - limitFacSi = recom_limiter(SiMaxSlope, qSiC, SiCmax) & - * limitFacN_dia - Si_assim = V_cm_fact_d * P_cm_d * arrFunc * SiCUptakeRatio & - * limitFacSi * Si/(Si + k_si) - -!------------------------------------------------------------------------------- -!< *** Iron chemistry *** -!< ********************** -! select the method to calculate freeFe - freeFe = iron_chemistry(Fe,totalligand,ligandStabConst) -!------------------------------------------------------------------------------- -!< *** Chlorophyll synthesis *** -!< ***************************** - -!< 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 ] - - 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 - 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 *** -!< ************************************* - -!< res_phy: Maintenance respiration rate constant [day−1 ] -!< biosynth: The cost of biosynthesis of N [mmol C mmol N−1 ] - - phyRespRate = res_phy * limitFacN + biosynth * N_assim - phyRespRate_dia = res_phy_d * limitFacN_dia + biosynth * N_assim_dia + biosynthSi * Si_assim -#if defined (__coccos) - phyRespRate_cocco = res_phy_c * limitFacN_cocco + biosynth * N_assim_cocco -#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 - -!< *** 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 - -!------------------------------------------------------------------------------- -! 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 - -!< *** 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 - - grazingFlux_phy2 = (grazingFlux2 * fphyN2)/food2 - grazingFlux_Dia2 = (grazingFlux2 * fDiaN2)/food2 - grazingFlux_miczoo2 = (grazingFlux2 * fMicZooN2)/food2 ! 3Zoo - -#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 - - 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 - -!------------------------------------------------------------------------------- -! Third Zooplankton (Microzooplankton) -!------------------------------------------------------------------------------- -!< Grazing on small phytoplankton, diatoms and coccolithophore (optional) - -!< *** Food availability *** -!< ************************* -!< pzPhy3: Maximum nanophytoplankton preference -!< pzDia3: Maximum diatom preference -!< pzCocco3: Maximum coccolithophore preference - - 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 - -!------------------------------------------------------------------------------- -!< 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 - endif - - if (ciso) then -!MB set HetRespFlux_plus = .true. in namelist.recom -! HetRespFlux_13 = max(zero, recip_res_het * arrFunc * (hetC_13 * recip_hetN_plus - redfield) * HetC_13) -! Numerically safer parametrization avoiding instable results which may result from different cutoff values -- CHECK - HetRespFlux_13 = HetRespFlux * HetC_13 / HetC -!! HetRespFlux_13 = HetRespFlux * (HetC_13 / HetC) **2 - if (ciso_14 .and. ciso_organic_14) then -! HetRespFlux_14 = max(zero, recip_res_het * arrFunc * (hetC_14 * recip_hetN_plus - redfield) * HetC_14) - HetRespFlux_14 = HetRespFlux * HetC_14 / HetC -!! HetRespFlux_14 = HetRespFlux * (HetC_14 / HetC) **2 - end if - end if - -!------------------------------------------------------------------------------- -!< Zooplanton mortality (Quadratic) - - hetLossFlux = loss_het * HetN * HetN - -#if defined (__3Zoo2Det) -!------------------------------------------------------------------------------- -!< Second zooplankton respiration - - call krill_resp(n, partit, mesh) - - 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) - - Zoo2LossFlux = loss_zoo2 * zoo2N * zoo2N - -!------------------------------------------------------------------------------- -!< Second zooplankton fecal pellets - - Zoo2fecalloss_n = fecal_rate_n * grazingFlux2 - Zoo2fecalloss_c = fecal_rate_c * grazingFluxcarbonzoo2 - -!------------------------------------------------------------------------------- -!< Mesozooplankton fecal pellets - - mesfecalloss_n = fecal_rate_n_mes * grazingFlux - mesfecalloss_c = fecal_rate_c_mes * grazingFluxcarbon_mes - -!------------------------------------------------------------------------------- -! Third zooplankton, microzooplankton, respiration ! 3Zoo - - MicZooRespFlux = res_miczoo * q10_mic_res * MicZooC -!------------------------------------------------------------------------------- -! Third zooplankton, microzooplankton, mortality (Quadratic) ! 3Zoo - - MicZooLossFlux = loss_miczoo * MicZooN * MicZooN -#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 - 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 - -#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 - - if (ciso) then - calcification_13 = calc_prod_ratio * Cphot * PhyC_13 * alpha_calc_13 - calcification_13 = calcification * alpha_calc_13 - calc_loss_agg_13 = aggregationRate * PhyCalc_13 - calc_loss_gra_13 = grazingFlux_phy * recipQuota_13/(PhyC_13 + tiny) * PhyCalc_13 - if (ciso_14 .and. ciso_organic_14) then - calcification_14 = calc_prod_ratio * Cphot * PhyC_14 * alpha_calc_14 - calc_loss_agg_14 = aggregationRate * PhyCalc_14 - calc_loss_gra_14 = grazingFlux_phy * recipQuota_14/(PhyC_14 + tiny) * PhyCalc_14 - end if - end if - -!------------------------------------------------------------------------------- -! Sources minus sinks (SMS) -!------------------------------------------------------------------------------- - -!< *** 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((Latd(1)<-45.0) .and. ((state(k,idic)+sms(k,idic))>2500)) then -! !co2flux(1)=0.0 -! print*,'ERROR: strange dic !' -! print*,'state(k,idic): ', state(k,idic) -! print*,'sms Cphot: ', -Cphot*PhyC -! print*,'sms resp: ', phyRespRate*PhyC -! print*,'sms Cphot dia: ', -Cphot_Dia*DiaC -! print*,'sms resp dia: ', phyRespRate_Dia * DiaC -! print*,'sms eoc: ', rho_C1* arrFunc *EOC -! print*,'sms het resp: ', HetRespFlux -! print*, 'sms co2: ', dflux(1) * recipdzF(k) * max( 2-k, 0 ) -! print*, 'sms calcdiss: ', calc_diss * DetCalc -! print*, 'sms calc_loss: ', calc_loss_gra * calc_diss_guts -! print*, 'sms calcification: ', -calcification -! 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 & ! --> grazing on small phytoplankton by third zooplankton - - grazingFlux_phy3 * grazEff3 & ! --> fraction of grazingFlux_phy3 into microzooplankton pool - + grazingFlux_dia3 & ! --> grazing on diatoms by third zooplankton - - grazingFlux_dia3 * grazEff3 & ! --> fraction of grazingFlux_dia3 into microzooplankton pool -#if defined (__coccos) - + grazingFlux_Cocco3 & ! --> grazing on coccolithophores by third zooplankton - - grazingFlux_Cocco3 * grazEff3 & ! --> fraction of grazingFlux_Cocco3 into microzooplankton pool - + aggregationRate * CoccoN & -#endif - - grazingFlux_Det * grazEff & ! --> grazing of first zoo (meso) on first detritus class - - grazingFlux_Det2 * grazEff2 & ! --> grazing of second zoo (macro) on first detritus class - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + miczooLossFlux & ! --> microzooplankton, mortality - - reminN * arrFunc * O2Func * DetN & ! --> O2remin - ) * dt_b + sms(k,idetn) -#else - sms(k,idetn) = ( & - + grazingFlux_phy & ! Technically it is mesooooooooooooooooo - - 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 * recipDet * grazEff2 & ! corrected recipDet2 -> recipDet - + 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 - 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) - else - sms(k,ihetc) = ( & - + grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco * grazEff & -#endif -#if defined (__3Zoo2Det) - + grazingFlux_miczoo * recipQZoo3 * grazEff & ! 3Zoo - - grazingFlux_het2 * recipQZoo & - - Mesfecalloss_c & ! 3Zoo -#endif - - hetLossFlux * recipQZoo & - - lossC_z * HetC & - - hetRespFlux & - ) * dt_b + sms(k,ihetc) - endif - -!< *** Macrozooplankton *** -!< ************************ - -#if defined (__3Zoo2Det) -!____________________________________________________________ -!< Second Zooplankton N - sms(k,izoo2n) = ( & - + grazingFlux2 * grazEff2 & - - Zoo2LossFlux & - - lossN_z2 * Zoo2N & - - Zoo2fecalloss_n & - ) * dt_b + sms(k,izoo2n) - -!____________________________________________________________ -!< Second Zooplankton C - if (Grazing_detritus) then - - sms(k,izoo2c) = ( & - + grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo - + grazingFlux_Det2 * recipDet * grazEff2 & - + grazingFlux_DetZ22 * recipDet2 * grazEff2 & - - zoo2LossFlux * recipQZoo2 & - - lossC_z2 * Zoo2C & - - Zoo2RespFlux & - - Zoo2fecalloss_c & - ) * dt_b + sms(k,izoo2c) - else - sms(k,izoo2c) = ( & - + grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo - - zoo2LossFlux * recipQZoo2 & - - lossC_z2 * Zoo2C & - - Zoo2RespFlux & - - Zoo2fecalloss_c & - ) * dt_b + sms(k,izoo2c) - end if - -!< *** Microzooplankton *** -!< ************************ - -!____________________________________________________________ -!< Third Zooplankton N - sms(k,imiczoon) = ( & - + grazingFlux3 * grazEff3 & - - grazingFlux_miczoo & - - grazingFlux_miczoo2 & - - MicZooLossFlux & - - lossN_z3 * MicZooN & - ) * dt_b + sms(k,imiczoon) - -!____________________________________________________________ -!< Third Zooplankton C - sms(k,imiczooc) = ( & - + grazingFlux_phy3 * recipQuota * grazEff3 & - + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & -#endif - - MicZooLossFlux * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 & - - lossC_z3 * MicZooC & - - MicZooRespFlux & - ) * dt_b + sms(k,imiczooc) - -!< *** Fast-sinking Detritus *** -!< ***************************** - -!____________________________________________________________ -!< Second Zooplankton Detritus N - if (Grazing_detritus) then - sms(k,idetz2n) = ( & - + grazingFlux_phy2 & - - grazingFlux_phy2 * grazEff2 & - + grazingFlux_dia2 & - - grazingFlux_dia2 * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco & - - grazingFlux_Cocco * grazEff & - + grazingFlux_Cocco2 & - - grazingFlux_Cocco2 * grazEff2 & -#endif - + grazingFlux_het2 & - - grazingFlux_het2 * grazEff2 & - + grazingFlux_miczoo2 & - - grazingFlux_miczoo2 * grazEff2 & - + grazingFlux_phy & - - grazingFlux_phy * grazEff & - + grazingFlux_dia & - - grazingFlux_dia * grazEff & - + grazingFlux_miczoo & - - grazingFlux_miczoo * grazEff & - - grazingFlux_DetZ2 * grazEff & - - grazingFlux_DetZ22 * grazEff2 & - + Zoo2LossFlux & - + hetLossFlux & - + Zoo2fecalloss_n & - + Mesfecalloss_n & - - reminN * arrFunc * O2Func * DetZ2N & ! O2remin - ) * dt_b + sms(k,idetz2n) - else - sms(k,idetz2n) = ( & - + grazingFlux_phy2 & - + grazingFlux_dia2 & -#if defined (__coccos) - + grazingFlux_Cocco & - + grazingFlux_Cocco2 & -#endif - + grazingFlux_het2 & - + grazingFlux_miczoo2 & - - grazingFlux2 * grazEff2 & - + grazingFlux_phy & - + grazingFlux_dia & - + grazingFlux_miczoo & - - grazingFlux * grazEff & - + Zoo2LossFlux & - + hetLossFlux & - + Zoo2fecalloss_n & - + Mesfecalloss_n & - - reminN * arrFunc * O2Func * DetZ2N & ! O2remin - ) * dt_b + sms(k,idetz2n) - end if - -!____________________________________________________________ -!< Second Zooplankton Detritus C - if (Grazing_detritus) then - sms(k,idetz2c) = ( & - + grazingFlux_phy2 * recipQuota & - - grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia & - - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + grazingFlux_Cocco2 * recipQuota_Cocco & - - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo & - - grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2 * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & - + grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 * grazEff & - - grazingFlux_DetZ2 * recipDet2 * grazEff & - - grazingFlux_DetZ22 * recipDet2 * grazEff2 & - + Zoo2LossFlux * recipQZoo2 & - + hetLossFlux * recipQZoo & - + Zoo2fecalloss_c & - + Mesfecalloss_c & - - reminC * arrFunc * O2Func * DetZ2C & ! O2remin - ) * dt_b + sms(k,idetz2c) - else - sms(k,idetz2c) = ( & - + grazingFlux_phy2 * recipQuota & - - grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia & - - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + grazingFlux_Cocco2 * recipQuota_Cocco & - - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo & - - grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2 * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & - + grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 * grazEff & - + Zoo2LossFlux * recipQZoo2 & - + hetLossFlux * recipQZoo & - + Zoo2fecalloss_c & - + Mesfecalloss_c & - - reminC * arrFunc * O2Func * DetZ2C & ! O2remin - ) * dt_b + sms(k,idetz2c) - end if - -!____________________________________________________________ -!< Second Zooplankton Detritus Si - sms(k,idetz2si) = ( & - + grazingFlux_dia2 * qSiN & ! --> qSin convert N to Si - + grazingFlux_dia * qSiN & - - reminSiT * DetZ2Si & - ) * dt_b + sms(k,idetz2si) - -!____________________________________________________________ -!< Second Zooplankton Detritus calcite - sms(k,idetz2calc) = ( & - + calc_loss_gra2 & - - calc_loss_gra2 * calc_diss_guts & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss2 * DetZ2Calc & - ) * dt_b + sms(k,idetz2calc) -#endif - -!< *** DOM *** -!< *********** - -!____________________________________________________________ -!< DON (Extracellular organic N) - - sms(k,idon) = ( & - + lossN * limitFacN * phyN & - + lossN_d * limitFacN_Dia * DiaN & -#if defined (__coccos) - + lossN_c * limitFacN_Cocco * CoccoN & -#endif - + reminN * arrFunc * O2Func * DetN & - + lossN_z * HetN & -#if defined (__3Zoo2Det) - + reminN * arrFunc * O2Func * DetZ2N & - + lossN_z2 * Zoo2N & - + lossN_z3 * MicZooN & ! 3Zoo -#endif - - rho_N * arrFunc * O2Func * DON & ! O2remin - ) * dt_b + sms(k,idon) - -!____________________________________________________________ -!< EOC - - sms(k,idoc) = ( & - + lossC * limitFacN * phyC & - + lossC_d * limitFacN_dia * DiaC & -#if defined (__coccos) - + lossC_c * limitFacN_cocco * CoccoC & -#endif - + reminC * arrFunc * O2Func * DetC & - + lossC_z * HetC & -#if defined (__3Zoo2Det) - + reminC * arrFunc * O2Func * DetZ2C & - + lossC_z2 * Zoo2C & - + lossC_z3 * MicZooC & ! 3Zoo -#endif - - rho_c1 * arrFunc * O2Func * EOC & ! O2remin - ) * dt_b + sms(k,idoc) - -!< *** Diatoms *** -!< *************** - -!____________________________________________________________ -!< Diatom N - -!< lossN: Diatom loss of organic N compounds [day^-1] -!< When N : C ratio becomes too high, excretion of DON is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers N to the detritus pool - - sms(k,idian) = ( & - + N_assim_dia * DiaC & ! --> N assimilation - - lossN_d * limitFacN_dia * DiaN & ! --> DON excretion - - aggregationRate * DiaN & ! --> Aggregation loss - - grazingFlux_Dia & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_Dia2 & - - grazingFlux_Dia3 & ! 3Zoo -#endif - ) * dt_b + sms(k,idian) - -!____________________________________________________________ -!< Diatom C - -!< lossC_d: Diatom loss of carbon [day^-1] -!< When N : C ratio becomes too high, excretion of DOC is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers C to the detritus pool - - sms(k,idiac) = ( & - + Cphot_dia * DiaC & ! -- Photosynthesis ---->/ - - lossC_d * limitFacN_dia * DiaC & ! -- Excretion of DOC --/ Net Photosynthesis - - phyRespRate_dia * DiaC & ! -- Respiration ----->/ - - aggregationRate * DiaC & - - grazingFlux_dia * recipQuota_dia & -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * recipQuota_dia & - - grazingFlux_dia3 * recipQuota_dia & ! 3Zoo -#endif - ) * dt_b + sms(k,idiac) - -!____________________________________________________________ -!< Diatom Chl - - sms(k,idchl) = ( & - + chlSynth_dia * DiaC & ! --> Chl a synthesis - - KOchl_dia * DiaChl & ! --> Degradation loss - - aggregationRate * DiaChl & ! --> Aggregation loss - - grazingFlux_dia * Chl2N_dia & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * Chl2N_dia & - - grazingFlux_dia3 * Chl2N_dia & ! 3Zoo -#endif - ) * dt_b + sms(k,idchl) - -!____________________________________________________________ -!< Diatom Si - -!< lossN_d: Diatom loss of organic nitrogen compunds [day^-1] -!< When N : C ratio becomes too high, excretion is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers Si to the detritus pool - - sms(k,idiasi) = ( & - + Si_assim * DiaC & ! -- Diatom silicon assimilation - - lossN_d * limitFacN_dia * DiaSi & ! -- Excretion to detritus - - aggregationRate * DiaSi & ! -- Aggregation loss - - grazingFlux_dia * qSiN & ! -- Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * qSiN & - - grazingFlux_dia3 * qSiN & ! 3Zoo -#endif - ) * dt_b + sms(k,idiasi) - -!< *** Coccolithophore *** -!< *********************** - -#if defined (__coccos) -!____________________________________________________________ -!< Coccolithophore N - sms(k,icocn) = ( & - + N_assim_cocco * CoccoC & - - lossN_c * limitFacN_cocco * CoccoN & - - aggregationRate * CoccoN & - - grazingFlux_Cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 & - - grazingFlux_Cocco3 & ! 3Zoo -#endif - ) * dt_b + sms(k,icocn) - -!____________________________________________________________ -!< Coccolithophore C - - sms(k,icocc) = ( & - + Cphot_cocco * CoccoC & - - lossC_c * limitFacN_cocco * CoccoC & - - phyRespRate_cocco * CoccoC & - - aggregationRate * CoccoC & - - grazingFlux_cocco * recipQuota_cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 * recipQuota_cocco & - - grazingFlux_Cocco3 * recipQuota_cocco & ! 3Zoo -#endif - ) * dt_b + sms(k,icocc) - - if(sms(k,icocc)>100) then - print*,'ERROR: strange CoccoC !' - print*,'k= ', k - print*,'dt= ', dt - print*,'dt_b= ', dt_b - print*,'state(k,icocc): ', state(k,icocc) - print*,'sms CoccoC: ', CoccoC - print*,'sms CoccoN: ', CoccoN - print*,'sms Cphot cocco: ', Cphot_cocco*CoccoC - print*,'sms lossC_c: ', lossC_c - print*,'sms limitFacN_cocco: ', limitFacN_cocco - print*,'sms phyRespRate_cocco: ', phyRespRate_cocco - print*,'sms grazingFlux_cocco: ', grazingFlux_cocco - print*,'sms grazingFlux_cocco2: ', grazingFlux_Cocco2 - print*,'sms grazingFlux_cocco3: ', grazingFlux_Cocco3 - print*,'sms recipQuota_cocco: ', recipQuota_cocco - - print*,'sms recipQuota_cocco: ', recipQuota_cocco - call par_ex(partit%MPI_COMM_FESOM, partit%mype) - stop - endif - -!____________________________________________________________ -!< Coccolithophore Chl - - sms(k,icchl) = ( & - + ChlSynth_cocco * CoccoC & - - KOchl_cocco * CoccoChl & - - aggregationRate * CoccoChl & - - grazingFlux_cocco * Chl2N_cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 * Chl2N_cocco & - - grazingFlux_Cocco3 * Chl2N_cocco & ! 3Zoo -#endif - ) * dt_b + sms(k,icchl) -#endif - -!< *** Silicate *** -!< **************** - -!____________________________________________________________ -!< Detritus Si -#if defined (__3Zoo2Det) - sms(k,idetsi) = ( & - + aggregationRate * DiaSi & - + lossN_d * limitFacN_dia * DiaSi & - + grazingFlux_dia3 * qSiN & - - reminSiT * DetSi & - ) * dt_b + sms(k,idetsi) -#else - sms(k,idetsi) = ( & - + aggregationRate * DiaSi & - + lossN_d * limitFacN_dia * DiaSi & - + grazingFlux_dia * qSiN & - - reminSiT * DetSi & - ) * dt_b + sms(k,idetsi) -#endif -!____________________________________________________________ -!< DSi, Silicate - -!< DiaC: Intracellular carbon concentration in diatoms [mmolC m-3] -!< DetSi: Detritus silicon concentration [mmolSi m-3] -!< Si_assim: Si assimilation rate for diatoms [mmolSi mmolC-1 day-1] -!< reminSiT: Remineralization rate of silicon, temperature dependency [day-1] -!< dt_b: REcoM time step [day] - -!! Schourup 2013 Eq. A3 - - sms(k,isi) = ( & - - Si_assim * DiaC & ! --> Si assimilation of diatoms - + reminSiT * DetSi & ! --> Remineralization of detritus, temperature dependent -#if defined (__3Zoo2Det) - + reminSiT * DetZ2Si & -#endif - ) * dt_b + sms(k,isi) -!< *** Iron *** -!< ************ - -!____________________________________________________________ -!< Fe - -!< Fe2N: Intracellular Fe : N ratio [μmol Fe mmol N^-1] Fe2N = Fe2C * 6.625 -!< PhyC: Intracellular carbon concentration in nanophytoplankton [mmolCm^-3] -!< Cphot: C-specific actual rate of photosynthesis for nanopyhtoplankton [day^-1] -!< DiaC: Intracellular carbon concentration in diatoms [mmol C m^-3 ] -!< Cphot_dia: C-specific actual rate of photosynthesis for diatom [day^-1] -!< phyRespRate: Nanopyhtoplankton respiration rate [day^-1] -!< phyRespRate_dia: Diatom respiration rate [day^-1] -!< lossC: Nanopyhtoplankton excretion of organic C [day^-1] -!< limitFacN: limiting factor -!< lossC_d: Diatom excretion of organic C [day^-1] -!< limitFacN_dia: limiting factor -!< detC: Detritus carbon concentration [mmol C m^-3] -!< reminC: Temperature dependent remineralisation rate of detritus [day^-1] -!< arrFunc: Arrhenius function -!< hetC: Zooplankton carbon concentration [mmol C m^-3 ] -!< lossC_z: Zooplankton excretion of organic C [day^-1 ] -!< hetRespFlux: Zooplankton respiration rate [day^-1] -!< kScavFe: Scavenging rate of iron [m3 mmol C^-1 day^-1] - - sms(k,ife) = ( Fe2N * ( & - - N_assim * PhyC & ! --> N assimilation Nanophytoplankton, [mmol N/(mmol C * day)] C specific N utilization rate - - N_assim_dia * DiaC & ! --> N assimilation Diatom -#if defined (__coccos) - - N_assim_cocco * CoccoC & - + lossN_c * limitFacN_cocco * CoccoN & -#endif - + lossN * limitFacN * PhyN & ! --> Excretion from small pythoplankton - + lossN_d * limitFacN_dia * DiaN & ! --> Excretion from diatom - + reminN * arrFunc * O2Func * DetN & ! --> Remineralization of detritus ! NEW O2remin - + lossN_z * HetN & ! --> Excretion from zooplankton -#if defined (__3Zoo2Det) - + reminN * arrFunc * O2Func * DetZ2N & ! O2remin - + lossN_z2 * Zoo2N & - + lossN_z3 * MicZooN & ! 3Zoo -#endif - ) & - - kScavFe * DetC * FreeFe & -#if defined (__3Zoo2Det) - - kScavFe * DetZ2C * FreeFe & -#endif - ) * dt_b + sms(k,ife) - -!< *** Calcification *** -!< ********************* - -!____________________________________________________________ -!< Small phytoplankton calcite - -#if defined (__coccos) - sms(k,iphycal) = ( & - + calcification & ! --> Calcification - - lossC_c * limitFacN_cocco * PhyCalc & ! --> Excretion loss - - phyRespRate_cocco * PhyCalc & ! --> Respiration - - calc_loss_agg & ! --> Aggregation loss - - calc_loss_gra & ! --> Grazing loss -#if defined (__3Zoo2Det) - - calc_loss_gra2 & - - calc_loss_gra3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphycal) -#else - sms(k,iphycal) = ( & - + calcification & ! --> Calcification - - lossC * limitFacN * PhyCalc & ! --> Excretion loss - - phyRespRate * PhyCalc & ! --> Respiration - - calc_loss_agg & ! --> Aggregation loss - - calc_loss_gra & ! --> Grazing loss -#if defined (__3Zoo2Det) - - calc_loss_gra2 & - - calc_loss_gra3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphycal) -#endif - -!____________________________________________________________ -! Detritus calcite -#if defined (__coccos) - -#if defined (__3Zoo2Det) - sms(k,idetcal) = ( & - + lossC_c * limitFacN_cocco * PhyCalc & - + phyRespRate_cocco * PhyCalc & - + calc_loss_agg & - + calc_loss_gra3 & - - calc_loss_gra3 * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) - -#else - sms(k,idetcal) = ( & - + lossC_c * limitFacN_cocco * PhyCalc & - + phyRespRate_cocco * PhyCalc & - + calc_loss_agg & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) - -#endif - -#else - -#if defined (__3Zoo2Det) - sms(k,idetcal) = ( & - + lossC * limitFacN * PhyCalc & - + phyRespRate * PhyCalc & - + calc_loss_agg & - + calc_loss_gra3 & - - calc_loss_gra3 * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) -#else - sms(k,idetcal) = ( & - + lossC * limitFacN * PhyCalc & - + phyRespRate * PhyCalc & - + calc_loss_agg & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) -#endif -#endif - -!____________________________________________________________ -! Oxygen - - sms(k,ioxy) = ( & - + Cphot * phyC & - - phyRespRate * phyC & - + Cphot_dia * diaC & - - phyRespRate_dia * diaC & -#if defined (__coccos) - + Cphot_cocco * CoccoC & - - phyRespRate_cocco * CoccoC & -#endif - - rho_C1 * arrFunc * O2Func * EOC & ! O2remin - - hetRespFlux & -#if defined (__3Zoo2Det) - - Zoo2RespFlux & - - MicZooRespFlux & ! 3Zoo -#endif - ) * redO2C * dt_b + sms(k,ioxy) -! - if (ciso) then -!------------------------------------------------------------------------------- -! DIC_13 - sms(k,idic_13) = ( & - - Cphot * PhyC_13 & - + phyRespRate * PhyC_13 & - - Cphot_Dia * DiaC_13 & - + phyRespRate_Dia * DiaC_13 & - + rho_C1 * arrFunc * EOC_13 & - + HetRespFlux_13 & - + calc_diss_13 * DetCalc_13 & - + calc_loss_gra_13 * calc_diss_guts & - - calcification_13 & - ) * dt_b + sms(k,idic_13) -!------------------------------------------------------------------------------- -! Phytoplankton C_13 - sms(k,iphyc_13) = ( & - + Cphot * PhyC_13 & - - lossC * limitFacN * PhyC_13 & - - phyRespRate * PhyC_13 & - - aggregationRate * PhyC_13 & - - grazingFlux_phy * recipQuota_13 & - ) * dt_b + sms(k,iphyc_13) -!------------------------------------------------------------------------------- -! Detritus C_13 - sms(k,idetc_13) = ( & - + grazingFlux_phy * recipQuota_13 & - - grazingFlux_phy * recipQuota_13 * grazEff & - + grazingFlux_Dia * recipQuota_dia_13 & - - grazingFlux_Dia * recipQuota_dia_13 * grazEff & - + aggregationRate * phyC_13 & - + aggregationRate * DiaC_13 & - + hetLossFlux * recipQZoo_13 & - - reminC * arrFunc * DetC_13 & - ) * dt_b + sms(k,idetc_13) -!------------------------------------------------------------------------------- -! Heterotrophic C_13 - sms(k,ihetc_13) = ( & - + grazingFlux_phy * recipQuota_13 * grazEff & - + grazingFlux_Dia * recipQuota_dia_13 * grazEff & - - hetLossFlux * recipQZoo_13 & - - lossC_z * HetC_13 & - - hetRespFlux_13 & - ) * dt_b + sms(k,ihetc_13) -!------------------------------------------------------------------------------- -! EOC_13 - sms(k,idoc_13) = ( & - + lossC * limitFacN * phyC_13 & - + lossC_d * limitFacN_dia * DiaC_13 & - + reminC * arrFunc * DetC_13 & - + lossC_z * HetC_13 & - - rho_c1 * arrFunc * EOC_13 & - + LocRiverDOC * r_iorg_13 & - ) * dt_b + sms(k,idoc_13) -!------------------------------------------------------------------------------- -! Diatom C_13 - sms(k,idiac_13) = ( & - + Cphot_dia * DiaC_13 & - - lossC_d * limitFacN_dia * DiaC_13 & - - phyRespRate_dia * DiaC_13 & - - aggregationRate * DiaC_13 & - - grazingFlux_dia * recipQuota_dia_13 & - ) * dt_b + sms(k,idiac_13) -!------------------------------------------------------------------------------- -! Small phytoplankton calcite_13 - sms(k,iphycal_13) = ( & - + calcification_13 & - - lossC * limitFacN * phyCalc_13 & - - phyRespRate * phyCalc_13 & - - calc_loss_agg_13 & - - calc_loss_gra_13 & - ) * dt_b + sms(k,iphycal_13) -!------------------------------------------------------------------------------- -! Detritus calcite_13 - sms(k,idetcal_13) = ( & - + lossC * limitFacN * phyCalc_13 & - + phyRespRate * phyCalc_13 & - + calc_loss_agg_13 & - + calc_loss_gra_13 & - - calc_loss_gra_13 * calc_diss_guts & - - calc_diss_13 * DetCalc_13 & - ) * dt_b + sms(k,idetcal_13) -!------------------------------------------------------------------------------- - if (ciso_14) then -!------------------------------------------------------------------------------- - if (ciso_organic_14) then -! 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) -!------------------------------------------------------------------------------- -! Phytoplankton C_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) -!------------------------------------------------------------------------------- -! Detritus C_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) -!------------------------------------------------------------------------------- -! Heterotrophic C_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) -!------------------------------------------------------------------------------- -! Diatom C_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) -!------------------------------------------------------------------------------- -! Small phytoplankton calcite_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) -!------------------------------------------------------------------------------- -! Detritus calcite_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, identical to DIC except for radioactive decay (-> -! recom_forcing) - sms(k,idic_14) = sms(k,idic) - end if ! ciso_organic_14 - end if ! ciso_14 - end if ! ciso -!------------------------------------------------------------------------------- -! 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 - -!------------------------------------------------------------------------------- -! Remineralization from the sediments into the bottom layer - - if (use_MEDUSA .and. (sedflx_num .ne. 0)) then - if (mype==0) then !OG - write(*,*) ' --> Sedimentary input of nutrients through MEDUSA' - endif - - else ! not use_MEDUSA or sedflx_num = 0 -!*** 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) - -!*** 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 - -!*** 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 - -!*** 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 - - if (ciso) then -!*** DIC_13 *** We ignore isotopic fractionation during remineralization. - decayBenthos(5) = alpha_dcal_13 * decayRateBenC * LocBenthos(5) - LocBenthos(5) = LocBenthos(5) - decayBenthos(5) * dt_b -!*** Calc: DIC_13 *** - decayBenthos(6) = calc_diss_13 * LocBenthos(6) - LocBenthos(6) = LocBenthos(6) - decayBenthos(6) * dt_b ! / depth of benthos - if (ciso_14) then - if (ciso_organic_14) then -!*** DIC_14 *** We ignore isotopic fractionation during remineralization. - decayBenthos(7) = alpha_dcal_14 * decayRateBenC * LocBenthos(7) - LocBenthos(7) = LocBenthos(7) - decayBenthos(7) * dt_b -!*** Calc: DIC_14 *** - decayBenthos(8) = calc_diss_14 * LocBenthos(8) - LocBenthos(8) = LocBenthos(8) - decayBenthos(8) * dt_b ! / depth of benthos - else -! Do nothing here because sms(idic_14) is defined as sms(idic) further -! above - end if ! ciso_organic_14 - end if ! ciso_14 - end if ! ciso - endif ! use_MEDUSA - - end do ! Main time loop ends - - -end subroutine REcoM_sms - -!------------------------------------------------------------------------------- -! Function for calculating limiter -!------------------------------------------------------------------------------- - -function recom_limiter(slope,qa,qb) - use recom_config - Implicit None - 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) - else - recom_limiter = 1.d0 - exp( -slope*( abs(dq)-dq )**2) - endif - return - end - -!------------------------------------------------------------------------------- -! Function for iron chemistry -!------------------------------------------------------------------------------- -function iron_chemistry_2ligands(fet,l1t,l2t,k1,k2) - implicit none - - Real(kind=8) :: iron_chemistry_2ligands - Real(kind=8) :: l1t,l2t,fet,k1,k2 - Real(kind=8) :: a3,a2,a1,a0,a,b,c,p,q,discr,rho,phi,amp,pi - Real(kind=8) :: one3rd, one27th - Real(kind=8) :: fe1,fe2,fe3 - -! coefficients of the 4th-order polynomial - a3 = k1*k2 - a2 = ( k1*k2*(l1t + l2t - fet) + k1 + k2 ) - a1 = ( 1 - (k1 + k2)*fet + k1*l1t + k2*l2t ) - a0 = -fet - -! coefficients of the normalized polynomial - a = a2/a3 - b = a1/a3 - c = a0/a3 - -! some numbers that are used several times - one3rd = 1.0/3.0 - one27th = 1.0/27.0 - -! now solve the polynomial stepwise - p = b - a*a*one3rd - q = c - a*b*one3rd + 2.0*a*a*a*one27th - discr = q*q/4.0 + p*p*p*one27th - - rho = sqrt(-(p*p*p*one27th)) - phi = acos(-q/(2.0*rho)) - amp = 2.0*rho**one3rd - pi = 3.1415926535897931 - -! the equation has three real roots - fe1 = amp*cos(phi*one3rd) - a*one3rd - fe2 = amp*cos((phi + 2.0*pi)*one3rd) - a*one3rd - fe3 = amp*cos((phi + 4.0*pi)*one3rd) - a*one3rd - - iron_chemistry_2ligands = max(fe1,fe2,fe3) - -end function iron_chemistry_2ligands -!------------------------------------------------------------------------------- -function iron_chemistry(Fe, totalLigand, ligandStabConst) - implicit none - - Real(kind=8) :: iron_chemistry - Real(kind=8) :: Fe, totalLigand, ligandStabConst ! Input - Real(kind=8) :: FreeFe ! Output - Real(kind=8) :: ligand,FeL,a,b,c,discrim - -! Abbrevations - a = 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 - freeFe = Fe - FeL - else ! No free iron - freeFe = 0.d0 - end if - - iron_chemistry = freeFe - - return - end - diff --git a/src/int_recom/recom_sms.F90 b/src/int_recom/recom_sms.F90 new file mode 120000 index 000000000..19cbaa84d --- /dev/null +++ b/src/int_recom/recom_sms.F90 @@ -0,0 +1 @@ +recom_sms.F90.nica \ No newline at end of file diff --git a/src/int_recom/recom_sms.F90.nica b/src/int_recom/recom_sms.F90.nica new file mode 100644 index 000000000..b9a4892f4 --- /dev/null +++ b/src/int_recom/recom_sms.F90.nica @@ -0,0 +1,2560 @@ +subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & + , CO2_watercolumn & + , pH_watercolumn & + , pCO2_watercolumn & + , HCO3_watercolumn & + , CO3_watercolumn & + , OmegaC_watercolumn & + , kspc_watercolumn & + , rhoSW_watercolumn & + , Loc_slp, zF, PAR, Lond, Latd, ice, dynamics, tracers, partit, mesh) + + use recom_declarations + use recom_locvar + use recom_glovar + use recom_config + use recoM_ciso + use g_clock + + use g_config + use MOD_MESH + use MOD_TRACER + use MOD_DYN + USE MOD_ICE + use o_ARRAYS + use o_PARAM + USE MOD_PARTIT + USE MOD_PARSUP + + use g_forcing_arrays + use g_comm_auto + use mvars + use mdepth2press + use gsw_mod_toolbox, only: gsw_sa_from_sp,gsw_ct_from_pt,gsw_rho + + implicit none + type(t_dyn) , intent(inout), target :: dynamics + type(t_tracer), intent(inout), target :: tracers + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + type(t_ice) , intent(inout), target :: ice + + 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 + + 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 + real(kind=8),intent(in) :: SurfSR !< [W/m2] ShortWave radiation at surface + + real(kind=8),dimension(mesh%nl-1,bgc_num),intent(inout) :: sms !< Source-Minus-Sinks term + real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Temp !< [degrees C] Ocean temperature + real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Sali_depth !< NEW MOCSY Salinity for the whole water column + + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO2_watercolumn !< [mol/m3] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pH_watercolumn !< on total scale + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pCO2_watercolumn !< [uatm] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: HCO3_watercolumn !< [mol/m3] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO3_watercolumn !< [mol/m3] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: OmegaC_watercolumn !< calcite saturation state + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: kspc_watercolumn !< stoichiometric solubility product [mol^2/kg^2] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: rhoSW_watercolumn !< in-situ density of seawater [kg/m3] + + real(kind=8),dimension(mesh%nl) ,intent(in) :: zF !< [m] Depth of fluxes + real(kind=8),dimension(mesh%nl-1),intent(inout) :: PAR + + real(kind=8) :: dt_d !< Size of time steps [day] + real(kind=8) :: dt_b !< Size of time steps [day] + real(kind=8),dimension(mesh%nl-1) :: Sink + real(kind=8) :: dt_sink !< Size of local time step + + real(kind=8) :: recip_hetN_plus !< MB's addition to heterotrophic respiration + real(kind=8) :: recip_res_het !< [day] Reciprocal of respiration by heterotrophs and mortality (loss to detritus) + real(kind=8) :: Sink_Vel + real(kind=8) :: aux + integer :: k,step,ii, idiags,n + + real(kind=8), intent(in) :: Loc_slp ![Pa] sea-level pressure + real(kind=8) :: Patm_depth(1) + real(kind=8) :: REcoM_T_depth(1) ! MOCSY temperature for the whole water column for mocsy minimum defined as -2 + real(kind=8) :: REcoM_S_depth(1) + real(kind=8) :: REcoM_DIC_depth(1) + real(kind=8) :: REcoM_Alk_depth(1) + real(kind=8) :: REcoM_Si_depth(1) + real(kind=8) :: REcoM_Phos_depth(1) + 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 + +#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 + + 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 + + tiny_Si = tiny_C_d/SiCmax !< SiCmax = 0.8d0 + +#if defined (__coccos) + tiny_N_c = tiny_chl/chl2N_max_c + tiny_C_c = tiny_N_c/NCmax_c +#endif + + recip_res_het = 1.d0/res_het !< res_het = 0.01d0 [1/day] Respiration by heterotrophs and mortality (loss to detritus) + + Patm_depth = Loc_slp/Pa2atm ! MOCSY convert from Pa to atm. + +!------------------------------------------------------------------------------- +!> REcoM time steps [day] +!------------------------------------------------------------------------------- + + 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] + +!------------------------------------------------------------------------------- +!Main time loop starts + do step = one,biostep + + kdzUpper = 0.d0 !< Upper light attenuation of top cell is set to zero + + if (any(abs(sms(:,:)) <= tiny)) sms(:,:) = zero ! tiny = 2.23D-16 + +!------------------------------------------------------------------------------- +! 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 + +! 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 + + if (ciso) then +!< additional variables are declared in module REcoM_ciso + 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)) + + calc_diss_13 = alpha_dcal_13 * calc_diss + + 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 + + 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 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) + +!------------------------------------------------------------------------------- +!> 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 + +!------------------------------------------------------------------------------- +! Depth component of Mocsy (see http://ocmip5.ipsl.jussieu.fr/mocsy/pyth.html) +!------------------------------------------------------------------------------- + +! 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. + 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') + CO2_watercolumn(k) = co2_depth(1) + pH_watercolumn(k) = ph_depth(1) + pCO2_watercolumn(k) = pco2_depth(1) + HCO3_watercolumn(k) = hco3_depth(1) + CO3_watercolumn(k) = co3_depth(1) + 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') + CO2_watercolumn(k) = co2_depth(1) + pH_watercolumn(k) = ph_depth(1) + pCO2_watercolumn(k) = pco2_depth(1) + HCO3_watercolumn(k) = hco3_depth(1) + CO3_watercolumn(k) = co3_depth(1) + OmegaC_watercolumn(k) = OmegaC_depth(1) + 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') + CO2_watercolumn(k) = co2_depth(1) + pH_watercolumn(k) = ph_depth(1) + pCO2_watercolumn(k) = pco2_depth(1) + HCO3_watercolumn(k) = hco3_depth(1) + CO3_watercolumn(k) = co3_depth(1) + 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] + +! 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 + +! 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 + 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) + 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?? + 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 + +!< *** Diatom photosynthesis rate *** +!< ********************************** + if ( pMax_dia .lt. 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 + + 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 + else + KOchl = deg_Chl*(real(one) - exp(-alfa * CHL2C_plast * PARave / pMax)) + KOchl = max((deg_Chl*0.1d0), KOchl) + 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 + 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 + 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 + 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 + stop + end if +#endif + end if ! photodamage + +!------------------------------------------------------------------------------- +!> Assimilation section +!------------------------------------------------------------------------------- + +!< 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 + 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 + + limitFacSi = recom_limiter(SiMaxSlope, qSiC, SiCmax) & + * limitFacN_dia + Si_assim = V_cm_fact_d * P_cm_d * arrFunc * SiCUptakeRatio & + * limitFacSi * Si/(Si + k_si) + +!------------------------------------------------------------------------------- +!< *** Iron chemistry *** +!< ********************** +! select the method to calculate freeFe + if (fe_2ligands) then + if (fe_compl_nica) then + logK1 = max(tiny, 24.36 - 1.67 * pH_watercolumn(k) & + + EOC * (-2.e-4 * EOC + 0.034)) + logK2 = logK1 + 2.67 + Klig1 = 10 ** (logK1 - 9) + Klig2 = 10 ** (logK2 - 9) + freeFe = iron_chemistry_2ligands(Fe,1.7,0.6,Klig1,Klig2) + endif + else + freeFe = iron_chemistry(Fe,totalligand,ligandStabConst) + endif + +!------------------------------------------------------------------------------- +!< *** Chlorophyll synthesis *** +!< ***************************** + +!< 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 ] + + 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 + 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 *** +!< ************************************* + +!< res_phy: Maintenance respiration rate constant [day−1 ] +!< biosynth: The cost of biosynthesis of N [mmol C mmol N−1 ] + + phyRespRate = res_phy * limitFacN + biosynth * N_assim + phyRespRate_dia = res_phy_d * limitFacN_dia + biosynth * N_assim_dia + biosynthSi * Si_assim +#if defined (__coccos) + phyRespRate_cocco = res_phy_c * limitFacN_cocco + biosynth * N_assim_cocco +#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 + +!< *** 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 + +!------------------------------------------------------------------------------- +! 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 + +!< *** 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 + + grazingFlux_phy2 = (grazingFlux2 * fphyN2)/food2 + grazingFlux_Dia2 = (grazingFlux2 * fDiaN2)/food2 + grazingFlux_miczoo2 = (grazingFlux2 * fMicZooN2)/food2 ! 3Zoo + +#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 + + 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 + +!------------------------------------------------------------------------------- +! Third Zooplankton (Microzooplankton) +!------------------------------------------------------------------------------- +!< Grazing on small phytoplankton, diatoms and coccolithophore (optional) + +!< *** Food availability *** +!< ************************* +!< pzPhy3: Maximum nanophytoplankton preference +!< pzDia3: Maximum diatom preference +!< pzCocco3: Maximum coccolithophore preference + + 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 + +!------------------------------------------------------------------------------- +!< 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 + endif + + if (ciso) then +!MB set HetRespFlux_plus = .true. in namelist.recom +! HetRespFlux_13 = max(zero, recip_res_het * arrFunc * (hetC_13 * recip_hetN_plus - redfield) * HetC_13) +! Numerically safer parametrization avoiding instable results which may result from different cutoff values -- CHECK + HetRespFlux_13 = HetRespFlux * HetC_13 / HetC +!! HetRespFlux_13 = HetRespFlux * (HetC_13 / HetC) **2 + if (ciso_14 .and. ciso_organic_14) then +! HetRespFlux_14 = max(zero, recip_res_het * arrFunc * (hetC_14 * recip_hetN_plus - redfield) * HetC_14) + HetRespFlux_14 = HetRespFlux * HetC_14 / HetC +!! HetRespFlux_14 = HetRespFlux * (HetC_14 / HetC) **2 + end if + end if + +!------------------------------------------------------------------------------- +!< Zooplanton mortality (Quadratic) + + hetLossFlux = loss_het * HetN * HetN + +#if defined (__3Zoo2Det) +!------------------------------------------------------------------------------- +!< Second zooplankton respiration + + call krill_resp(n, partit, mesh) + + 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) + + Zoo2LossFlux = loss_zoo2 * zoo2N * zoo2N + +!------------------------------------------------------------------------------- +!< Second zooplankton fecal pellets + + Zoo2fecalloss_n = fecal_rate_n * grazingFlux2 + Zoo2fecalloss_c = fecal_rate_c * grazingFluxcarbonzoo2 + +!------------------------------------------------------------------------------- +!< Mesozooplankton fecal pellets + + mesfecalloss_n = fecal_rate_n_mes * grazingFlux + mesfecalloss_c = fecal_rate_c_mes * grazingFluxcarbon_mes + +!------------------------------------------------------------------------------- +! Third zooplankton, microzooplankton, respiration ! 3Zoo + + MicZooRespFlux = res_miczoo * q10_mic_res * MicZooC +!------------------------------------------------------------------------------- +! Third zooplankton, microzooplankton, mortality (Quadratic) ! 3Zoo + + MicZooLossFlux = loss_miczoo * MicZooN * MicZooN +#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 + 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 + +#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 + + if (ciso) then + calcification_13 = calc_prod_ratio * Cphot * PhyC_13 * alpha_calc_13 + calcification_13 = calcification * alpha_calc_13 + calc_loss_agg_13 = aggregationRate * PhyCalc_13 + calc_loss_gra_13 = grazingFlux_phy * recipQuota_13/(PhyC_13 + tiny) * PhyCalc_13 + if (ciso_14 .and. ciso_organic_14) then + calcification_14 = calc_prod_ratio * Cphot * PhyC_14 * alpha_calc_14 + calc_loss_agg_14 = aggregationRate * PhyCalc_14 + calc_loss_gra_14 = grazingFlux_phy * recipQuota_14/(PhyC_14 + tiny) * PhyCalc_14 + end if + end if + +!------------------------------------------------------------------------------- +! Sources minus sinks (SMS) +!------------------------------------------------------------------------------- + +!< *** 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((Latd(1)<-45.0) .and. ((state(k,idic)+sms(k,idic))>2500)) then +! !co2flux(1)=0.0 +! print*,'ERROR: strange dic !' +! print*,'state(k,idic): ', state(k,idic) +! print*,'sms Cphot: ', -Cphot*PhyC +! print*,'sms resp: ', phyRespRate*PhyC +! print*,'sms Cphot dia: ', -Cphot_Dia*DiaC +! print*,'sms resp dia: ', phyRespRate_Dia * DiaC +! print*,'sms eoc: ', rho_C1* arrFunc *EOC +! print*,'sms het resp: ', HetRespFlux +! print*, 'sms co2: ', dflux(1) * recipdzF(k) * max( 2-k, 0 ) +! print*, 'sms calcdiss: ', calc_diss * DetCalc +! print*, 'sms calc_loss: ', calc_loss_gra * calc_diss_guts +! print*, 'sms calcification: ', -calcification +! 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 & ! --> grazing on small phytoplankton by third zooplankton + - grazingFlux_phy3 * grazEff3 & ! --> fraction of grazingFlux_phy3 into microzooplankton pool + + grazingFlux_dia3 & ! --> grazing on diatoms by third zooplankton + - grazingFlux_dia3 * grazEff3 & ! --> fraction of grazingFlux_dia3 into microzooplankton pool +#if defined (__coccos) + + grazingFlux_Cocco3 & ! --> grazing on coccolithophores by third zooplankton + - grazingFlux_Cocco3 * grazEff3 & ! --> fraction of grazingFlux_Cocco3 into microzooplankton pool + + aggregationRate * CoccoN & +#endif + - grazingFlux_Det * grazEff & ! --> grazing of first zoo (meso) on first detritus class + - grazingFlux_Det2 * grazEff2 & ! --> grazing of second zoo (macro) on first detritus class + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + miczooLossFlux & ! --> microzooplankton, mortality + - reminN * arrFunc * O2Func * DetN & ! --> O2remin + ) * dt_b + sms(k,idetn) +#else + sms(k,idetn) = ( & + + grazingFlux_phy & ! Technically it is mesooooooooooooooooo + - 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 * recipDet * grazEff2 & ! corrected recipDet2 -> recipDet + + 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 + 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) + else + sms(k,ihetc) = ( & + + grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia * grazEff & +#if defined (__coccos) + + grazingFlux_Cocco * recipQuota_Cocco * grazEff & +#endif +#if defined (__3Zoo2Det) + + grazingFlux_miczoo * recipQZoo3 * grazEff & ! 3Zoo + - grazingFlux_het2 * recipQZoo & + - Mesfecalloss_c & ! 3Zoo +#endif + - hetLossFlux * recipQZoo & + - lossC_z * HetC & + - hetRespFlux & + ) * dt_b + sms(k,ihetc) + endif + +!< *** Macrozooplankton *** +!< ************************ + +#if defined (__3Zoo2Det) +!____________________________________________________________ +!< Second Zooplankton N + sms(k,izoo2n) = ( & + + grazingFlux2 * grazEff2 & + - Zoo2LossFlux & + - lossN_z2 * Zoo2N & + - Zoo2fecalloss_n & + ) * dt_b + sms(k,izoo2n) + +!____________________________________________________________ +!< Second Zooplankton C + if (Grazing_detritus) then + + sms(k,izoo2c) = ( & + + grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo + + grazingFlux_Det2 * recipDet * grazEff2 & + + grazingFlux_DetZ22 * recipDet2 * grazEff2 & + - zoo2LossFlux * recipQZoo2 & + - lossC_z2 * Zoo2C & + - Zoo2RespFlux & + - Zoo2fecalloss_c & + ) * dt_b + sms(k,izoo2c) + else + sms(k,izoo2c) = ( & + + grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo + - zoo2LossFlux * recipQZoo2 & + - lossC_z2 * Zoo2C & + - Zoo2RespFlux & + - Zoo2fecalloss_c & + ) * dt_b + sms(k,izoo2c) + end if + +!< *** Microzooplankton *** +!< ************************ + +!____________________________________________________________ +!< Third Zooplankton N + sms(k,imiczoon) = ( & + + grazingFlux3 * grazEff3 & + - grazingFlux_miczoo & + - grazingFlux_miczoo2 & + - MicZooLossFlux & + - lossN_z3 * MicZooN & + ) * dt_b + sms(k,imiczoon) + +!____________________________________________________________ +!< Third Zooplankton C + sms(k,imiczooc) = ( & + + grazingFlux_phy3 * recipQuota * grazEff3 & + + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & +#if defined (__coccos) + + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & +#endif + - MicZooLossFlux * recipQZoo3 & + - grazingFlux_miczoo * recipQZoo3 & + - grazingFlux_miczoo2 * recipQZoo3 & + - lossC_z3 * MicZooC & + - MicZooRespFlux & + ) * dt_b + sms(k,imiczooc) + +!< *** Fast-sinking Detritus *** +!< ***************************** + +!____________________________________________________________ +!< Second Zooplankton Detritus N + if (Grazing_detritus) then + sms(k,idetz2n) = ( & + + grazingFlux_phy2 & + - grazingFlux_phy2 * grazEff2 & + + grazingFlux_dia2 & + - grazingFlux_dia2 * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco & + - grazingFlux_Cocco * grazEff & + + grazingFlux_Cocco2 & + - grazingFlux_Cocco2 * grazEff2 & +#endif + + grazingFlux_het2 & + - grazingFlux_het2 * grazEff2 & + + grazingFlux_miczoo2 & + - grazingFlux_miczoo2 * grazEff2 & + + grazingFlux_phy & + - grazingFlux_phy * grazEff & + + grazingFlux_dia & + - grazingFlux_dia * grazEff & + + grazingFlux_miczoo & + - grazingFlux_miczoo * grazEff & + - grazingFlux_DetZ2 * grazEff & + - grazingFlux_DetZ22 * grazEff2 & + + Zoo2LossFlux & + + hetLossFlux & + + Zoo2fecalloss_n & + + Mesfecalloss_n & + - reminN * arrFunc * O2Func * DetZ2N & ! O2remin + ) * dt_b + sms(k,idetz2n) + else + sms(k,idetz2n) = ( & + + grazingFlux_phy2 & + + grazingFlux_dia2 & +#if defined (__coccos) + + grazingFlux_Cocco & + + grazingFlux_Cocco2 & +#endif + + grazingFlux_het2 & + + grazingFlux_miczoo2 & + - grazingFlux2 * grazEff2 & + + grazingFlux_phy & + + grazingFlux_dia & + + grazingFlux_miczoo & + - grazingFlux * grazEff & + + Zoo2LossFlux & + + hetLossFlux & + + Zoo2fecalloss_n & + + Mesfecalloss_n & + - reminN * arrFunc * O2Func * DetZ2N & ! O2remin + ) * dt_b + sms(k,idetz2n) + end if + +!____________________________________________________________ +!< Second Zooplankton Detritus C + if (Grazing_detritus) then + sms(k,idetz2c) = ( & + + grazingFlux_phy2 * recipQuota & + - grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia & + - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco * recipQuota_Cocco & + - grazingFlux_Cocco * recipQuota_Cocco * grazEff & + + grazingFlux_Cocco2 * recipQuota_Cocco & + - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo & + - grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2 * recipQZoo3 & + - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & + + grazingFlux_phy * recipQuota & + - grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia & + - grazingFlux_Dia * recipQuota_Dia * grazEff & + + grazingFlux_miczoo * recipQZoo3 & + - grazingFlux_miczoo * recipQZoo3 * grazEff & + - grazingFlux_DetZ2 * recipDet2 * grazEff & + - grazingFlux_DetZ22 * recipDet2 * grazEff2 & + + Zoo2LossFlux * recipQZoo2 & + + hetLossFlux * recipQZoo & + + Zoo2fecalloss_c & + + Mesfecalloss_c & + - reminC * arrFunc * O2Func * DetZ2C & ! O2remin + ) * dt_b + sms(k,idetz2c) + else + sms(k,idetz2c) = ( & + + grazingFlux_phy2 * recipQuota & + - grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia & + - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco * recipQuota_Cocco & + - grazingFlux_Cocco * recipQuota_Cocco * grazEff & + + grazingFlux_Cocco2 * recipQuota_Cocco & + - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo & + - grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2 * recipQZoo3 & + - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & + + grazingFlux_phy * recipQuota & + - grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia & + - grazingFlux_Dia * recipQuota_Dia * grazEff & + + grazingFlux_miczoo * recipQZoo3 & + - grazingFlux_miczoo * recipQZoo3 * grazEff & + + Zoo2LossFlux * recipQZoo2 & + + hetLossFlux * recipQZoo & + + Zoo2fecalloss_c & + + Mesfecalloss_c & + - reminC * arrFunc * O2Func * DetZ2C & ! O2remin + ) * dt_b + sms(k,idetz2c) + end if + +!____________________________________________________________ +!< Second Zooplankton Detritus Si + sms(k,idetz2si) = ( & + + grazingFlux_dia2 * qSiN & ! --> qSin convert N to Si + + grazingFlux_dia * qSiN & + - reminSiT * DetZ2Si & + ) * dt_b + sms(k,idetz2si) + +!____________________________________________________________ +!< Second Zooplankton Detritus calcite + sms(k,idetz2calc) = ( & + + calc_loss_gra2 & + - calc_loss_gra2 * calc_diss_guts & + + calc_loss_gra & + - calc_loss_gra * calc_diss_guts & + - calc_diss2 * DetZ2Calc & + ) * dt_b + sms(k,idetz2calc) +#endif + +!< *** DOM *** +!< *********** + +!____________________________________________________________ +!< DON (Extracellular organic N) + + sms(k,idon) = ( & + + lossN * limitFacN * phyN & + + lossN_d * limitFacN_Dia * DiaN & +#if defined (__coccos) + + lossN_c * limitFacN_Cocco * CoccoN & +#endif + + reminN * arrFunc * O2Func * DetN & + + lossN_z * HetN & +#if defined (__3Zoo2Det) + + reminN * arrFunc * O2Func * DetZ2N & + + lossN_z2 * Zoo2N & + + lossN_z3 * MicZooN & ! 3Zoo +#endif + - rho_N * arrFunc * O2Func * DON & ! O2remin + ) * dt_b + sms(k,idon) + +!____________________________________________________________ +!< EOC + + sms(k,idoc) = ( & + + lossC * limitFacN * phyC & + + lossC_d * limitFacN_dia * DiaC & +#if defined (__coccos) + + lossC_c * limitFacN_cocco * CoccoC & +#endif + + reminC * arrFunc * O2Func * DetC & + + lossC_z * HetC & +#if defined (__3Zoo2Det) + + reminC * arrFunc * O2Func * DetZ2C & + + lossC_z2 * Zoo2C & + + lossC_z3 * MicZooC & ! 3Zoo +#endif + - rho_c1 * arrFunc * O2Func * EOC & ! O2remin + ) * dt_b + sms(k,idoc) + +!< *** Diatoms *** +!< *************** + +!____________________________________________________________ +!< Diatom N + +!< lossN: Diatom loss of organic N compounds [day^-1] +!< When N : C ratio becomes too high, excretion of DON is downregulated +!< by the limiter function limitFacN_dia +!< aggregationRate transfers N to the detritus pool + + sms(k,idian) = ( & + + N_assim_dia * DiaC & ! --> N assimilation + - lossN_d * limitFacN_dia * DiaN & ! --> DON excretion + - aggregationRate * DiaN & ! --> Aggregation loss + - grazingFlux_Dia & ! --> Grazing loss +#if defined (__3Zoo2Det) + - grazingFlux_Dia2 & + - grazingFlux_Dia3 & ! 3Zoo +#endif + ) * dt_b + sms(k,idian) + +!____________________________________________________________ +!< Diatom C + +!< lossC_d: Diatom loss of carbon [day^-1] +!< When N : C ratio becomes too high, excretion of DOC is downregulated +!< by the limiter function limitFacN_dia +!< aggregationRate transfers C to the detritus pool + + sms(k,idiac) = ( & + + Cphot_dia * DiaC & ! -- Photosynthesis ---->/ + - lossC_d * limitFacN_dia * DiaC & ! -- Excretion of DOC --/ Net Photosynthesis + - phyRespRate_dia * DiaC & ! -- Respiration ----->/ + - aggregationRate * DiaC & + - grazingFlux_dia * recipQuota_dia & +#if defined (__3Zoo2Det) + - grazingFlux_dia2 * recipQuota_dia & + - grazingFlux_dia3 * recipQuota_dia & ! 3Zoo +#endif + ) * dt_b + sms(k,idiac) + +!____________________________________________________________ +!< Diatom Chl + + sms(k,idchl) = ( & + + chlSynth_dia * DiaC & ! --> Chl a synthesis + - KOchl_dia * DiaChl & ! --> Degradation loss + - aggregationRate * DiaChl & ! --> Aggregation loss + - grazingFlux_dia * Chl2N_dia & ! --> Grazing loss +#if defined (__3Zoo2Det) + - grazingFlux_dia2 * Chl2N_dia & + - grazingFlux_dia3 * Chl2N_dia & ! 3Zoo +#endif + ) * dt_b + sms(k,idchl) + +!____________________________________________________________ +!< Diatom Si + +!< lossN_d: Diatom loss of organic nitrogen compunds [day^-1] +!< When N : C ratio becomes too high, excretion is downregulated +!< by the limiter function limitFacN_dia +!< aggregationRate transfers Si to the detritus pool + + sms(k,idiasi) = ( & + + Si_assim * DiaC & ! -- Diatom silicon assimilation + - lossN_d * limitFacN_dia * DiaSi & ! -- Excretion to detritus + - aggregationRate * DiaSi & ! -- Aggregation loss + - grazingFlux_dia * qSiN & ! -- Grazing loss +#if defined (__3Zoo2Det) + - grazingFlux_dia2 * qSiN & + - grazingFlux_dia3 * qSiN & ! 3Zoo +#endif + ) * dt_b + sms(k,idiasi) + +!< *** Coccolithophore *** +!< *********************** + +#if defined (__coccos) +!____________________________________________________________ +!< Coccolithophore N + sms(k,icocn) = ( & + + N_assim_cocco * CoccoC & + - lossN_c * limitFacN_cocco * CoccoN & + - aggregationRate * CoccoN & + - grazingFlux_Cocco & +#if defined (__3Zoo2Det) + - grazingFlux_Cocco2 & + - grazingFlux_Cocco3 & ! 3Zoo +#endif + ) * dt_b + sms(k,icocn) + +!____________________________________________________________ +!< Coccolithophore C + + sms(k,icocc) = ( & + + Cphot_cocco * CoccoC & + - lossC_c * limitFacN_cocco * CoccoC & + - phyRespRate_cocco * CoccoC & + - aggregationRate * CoccoC & + - grazingFlux_cocco * recipQuota_cocco & +#if defined (__3Zoo2Det) + - grazingFlux_Cocco2 * recipQuota_cocco & + - grazingFlux_Cocco3 * recipQuota_cocco & ! 3Zoo +#endif + ) * dt_b + sms(k,icocc) + + if(sms(k,icocc)>100) then + print*,'ERROR: strange CoccoC !' + print*,'k= ', k + print*,'dt= ', dt + print*,'dt_b= ', dt_b + print*,'state(k,icocc): ', state(k,icocc) + print*,'sms CoccoC: ', CoccoC + print*,'sms CoccoN: ', CoccoN + print*,'sms Cphot cocco: ', Cphot_cocco*CoccoC + print*,'sms lossC_c: ', lossC_c + print*,'sms limitFacN_cocco: ', limitFacN_cocco + print*,'sms phyRespRate_cocco: ', phyRespRate_cocco + print*,'sms grazingFlux_cocco: ', grazingFlux_cocco + print*,'sms grazingFlux_cocco2: ', grazingFlux_Cocco2 + print*,'sms grazingFlux_cocco3: ', grazingFlux_Cocco3 + print*,'sms recipQuota_cocco: ', recipQuota_cocco + + print*,'sms recipQuota_cocco: ', recipQuota_cocco + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + endif + +!____________________________________________________________ +!< Coccolithophore Chl + + sms(k,icchl) = ( & + + ChlSynth_cocco * CoccoC & + - KOchl_cocco * CoccoChl & + - aggregationRate * CoccoChl & + - grazingFlux_cocco * Chl2N_cocco & +#if defined (__3Zoo2Det) + - grazingFlux_Cocco2 * Chl2N_cocco & + - grazingFlux_Cocco3 * Chl2N_cocco & ! 3Zoo +#endif + ) * dt_b + sms(k,icchl) +#endif + +!< *** Silicate *** +!< **************** + +!____________________________________________________________ +!< Detritus Si +#if defined (__3Zoo2Det) + sms(k,idetsi) = ( & + + aggregationRate * DiaSi & + + lossN_d * limitFacN_dia * DiaSi & + + grazingFlux_dia3 * qSiN & + - reminSiT * DetSi & + ) * dt_b + sms(k,idetsi) +#else + sms(k,idetsi) = ( & + + aggregationRate * DiaSi & + + lossN_d * limitFacN_dia * DiaSi & + + grazingFlux_dia * qSiN & + - reminSiT * DetSi & + ) * dt_b + sms(k,idetsi) +#endif +!____________________________________________________________ +!< DSi, Silicate + +!< DiaC: Intracellular carbon concentration in diatoms [mmolC m-3] +!< DetSi: Detritus silicon concentration [mmolSi m-3] +!< Si_assim: Si assimilation rate for diatoms [mmolSi mmolC-1 day-1] +!< reminSiT: Remineralization rate of silicon, temperature dependency [day-1] +!< dt_b: REcoM time step [day] + +!! Schourup 2013 Eq. A3 + + sms(k,isi) = ( & + - Si_assim * DiaC & ! --> Si assimilation of diatoms + + reminSiT * DetSi & ! --> Remineralization of detritus, temperature dependent +#if defined (__3Zoo2Det) + + reminSiT * DetZ2Si & +#endif + ) * dt_b + sms(k,isi) +!< *** Iron *** +!< ************ + +!____________________________________________________________ +!< Fe + +!< Fe2N: Intracellular Fe : N ratio [μmol Fe mmol N^-1] Fe2N = Fe2C * 6.625 +!< PhyC: Intracellular carbon concentration in nanophytoplankton [mmolCm^-3] +!< Cphot: C-specific actual rate of photosynthesis for nanopyhtoplankton [day^-1] +!< DiaC: Intracellular carbon concentration in diatoms [mmol C m^-3 ] +!< Cphot_dia: C-specific actual rate of photosynthesis for diatom [day^-1] +!< phyRespRate: Nanopyhtoplankton respiration rate [day^-1] +!< phyRespRate_dia: Diatom respiration rate [day^-1] +!< lossC: Nanopyhtoplankton excretion of organic C [day^-1] +!< limitFacN: limiting factor +!< lossC_d: Diatom excretion of organic C [day^-1] +!< limitFacN_dia: limiting factor +!< detC: Detritus carbon concentration [mmol C m^-3] +!< reminC: Temperature dependent remineralisation rate of detritus [day^-1] +!< arrFunc: Arrhenius function +!< hetC: Zooplankton carbon concentration [mmol C m^-3 ] +!< lossC_z: Zooplankton excretion of organic C [day^-1 ] +!< hetRespFlux: Zooplankton respiration rate [day^-1] +!< kScavFe: Scavenging rate of iron [m3 mmol C^-1 day^-1] + + sms(k,ife) = ( Fe2N * ( & + - N_assim * PhyC & ! --> N assimilation Nanophytoplankton, [mmol N/(mmol C * day)] C specific N utilization rate + - N_assim_dia * DiaC & ! --> N assimilation Diatom +#if defined (__coccos) + - N_assim_cocco * CoccoC & + + lossN_c * limitFacN_cocco * CoccoN & +#endif + + lossN * limitFacN * PhyN & ! --> Excretion from small pythoplankton + + lossN_d * limitFacN_dia * DiaN & ! --> Excretion from diatom + + reminN * arrFunc * O2Func * DetN & ! --> Remineralization of detritus ! NEW O2remin + + lossN_z * HetN & ! --> Excretion from zooplankton +#if defined (__3Zoo2Det) + + reminN * arrFunc * O2Func * DetZ2N & ! O2remin + + lossN_z2 * Zoo2N & + + lossN_z3 * MicZooN & ! 3Zoo +#endif + ) & + - kScavFe * DetC * FreeFe & +#if defined (__3Zoo2Det) + - kScavFe * DetZ2C * FreeFe & +#endif + ) * dt_b + sms(k,ife) + +!< *** Calcification *** +!< ********************* + +!____________________________________________________________ +!< Small phytoplankton calcite + +#if defined (__coccos) + sms(k,iphycal) = ( & + + calcification & ! --> Calcification + - lossC_c * limitFacN_cocco * PhyCalc & ! --> Excretion loss + - phyRespRate_cocco * PhyCalc & ! --> Respiration + - calc_loss_agg & ! --> Aggregation loss + - calc_loss_gra & ! --> Grazing loss +#if defined (__3Zoo2Det) + - calc_loss_gra2 & + - calc_loss_gra3 & ! 3Zoo +#endif + ) * dt_b + sms(k,iphycal) +#else + sms(k,iphycal) = ( & + + calcification & ! --> Calcification + - lossC * limitFacN * PhyCalc & ! --> Excretion loss + - phyRespRate * PhyCalc & ! --> Respiration + - calc_loss_agg & ! --> Aggregation loss + - calc_loss_gra & ! --> Grazing loss +#if defined (__3Zoo2Det) + - calc_loss_gra2 & + - calc_loss_gra3 & ! 3Zoo +#endif + ) * dt_b + sms(k,iphycal) +#endif + +!____________________________________________________________ +! Detritus calcite +#if defined (__coccos) + +#if defined (__3Zoo2Det) + sms(k,idetcal) = ( & + + lossC_c * limitFacN_cocco * PhyCalc & + + phyRespRate_cocco * PhyCalc & + + calc_loss_agg & + + calc_loss_gra3 & + - calc_loss_gra3 * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + +#else + sms(k,idetcal) = ( & + + lossC_c * limitFacN_cocco * PhyCalc & + + phyRespRate_cocco * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + +#endif + +#else + +#if defined (__3Zoo2Det) + sms(k,idetcal) = ( & + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra3 & + - calc_loss_gra3 * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) +#else + sms(k,idetcal) = ( & + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) +#endif +#endif + +!____________________________________________________________ +! Oxygen + + sms(k,ioxy) = ( & + + Cphot * phyC & + - phyRespRate * phyC & + + Cphot_dia * diaC & + - phyRespRate_dia * diaC & +#if defined (__coccos) + + Cphot_cocco * CoccoC & + - phyRespRate_cocco * CoccoC & +#endif + - rho_C1 * arrFunc * O2Func * EOC & ! O2remin + - hetRespFlux & +#if defined (__3Zoo2Det) + - Zoo2RespFlux & + - MicZooRespFlux & ! 3Zoo +#endif + ) * redO2C * dt_b + sms(k,ioxy) +! + if (ciso) then +!------------------------------------------------------------------------------- +! DIC_13 + sms(k,idic_13) = ( & + - Cphot * PhyC_13 & + + phyRespRate * PhyC_13 & + - Cphot_Dia * DiaC_13 & + + phyRespRate_Dia * DiaC_13 & + + rho_C1 * arrFunc * EOC_13 & + + HetRespFlux_13 & + + calc_diss_13 * DetCalc_13 & + + calc_loss_gra_13 * calc_diss_guts & + - calcification_13 & + ) * dt_b + sms(k,idic_13) +!------------------------------------------------------------------------------- +! Phytoplankton C_13 + sms(k,iphyc_13) = ( & + + Cphot * PhyC_13 & + - lossC * limitFacN * PhyC_13 & + - phyRespRate * PhyC_13 & + - aggregationRate * PhyC_13 & + - grazingFlux_phy * recipQuota_13 & + ) * dt_b + sms(k,iphyc_13) +!------------------------------------------------------------------------------- +! Detritus C_13 + sms(k,idetc_13) = ( & + + grazingFlux_phy * recipQuota_13 & + - grazingFlux_phy * recipQuota_13 * grazEff & + + grazingFlux_Dia * recipQuota_dia_13 & + - grazingFlux_Dia * recipQuota_dia_13 * grazEff & + + aggregationRate * phyC_13 & + + aggregationRate * DiaC_13 & + + hetLossFlux * recipQZoo_13 & + - reminC * arrFunc * DetC_13 & + ) * dt_b + sms(k,idetc_13) +!------------------------------------------------------------------------------- +! Heterotrophic C_13 + sms(k,ihetc_13) = ( & + + grazingFlux_phy * recipQuota_13 * grazEff & + + grazingFlux_Dia * recipQuota_dia_13 * grazEff & + - hetLossFlux * recipQZoo_13 & + - lossC_z * HetC_13 & + - hetRespFlux_13 & + ) * dt_b + sms(k,ihetc_13) +!------------------------------------------------------------------------------- +! EOC_13 + sms(k,idoc_13) = ( & + + lossC * limitFacN * phyC_13 & + + lossC_d * limitFacN_dia * DiaC_13 & + + reminC * arrFunc * DetC_13 & + + lossC_z * HetC_13 & + - rho_c1 * arrFunc * EOC_13 & + + LocRiverDOC * r_iorg_13 & + ) * dt_b + sms(k,idoc_13) +!------------------------------------------------------------------------------- +! Diatom C_13 + sms(k,idiac_13) = ( & + + Cphot_dia * DiaC_13 & + - lossC_d * limitFacN_dia * DiaC_13 & + - phyRespRate_dia * DiaC_13 & + - aggregationRate * DiaC_13 & + - grazingFlux_dia * recipQuota_dia_13 & + ) * dt_b + sms(k,idiac_13) +!------------------------------------------------------------------------------- +! Small phytoplankton calcite_13 + sms(k,iphycal_13) = ( & + + calcification_13 & + - lossC * limitFacN * phyCalc_13 & + - phyRespRate * phyCalc_13 & + - calc_loss_agg_13 & + - calc_loss_gra_13 & + ) * dt_b + sms(k,iphycal_13) +!------------------------------------------------------------------------------- +! Detritus calcite_13 + sms(k,idetcal_13) = ( & + + lossC * limitFacN * phyCalc_13 & + + phyRespRate * phyCalc_13 & + + calc_loss_agg_13 & + + calc_loss_gra_13 & + - calc_loss_gra_13 * calc_diss_guts & + - calc_diss_13 * DetCalc_13 & + ) * dt_b + sms(k,idetcal_13) +!------------------------------------------------------------------------------- + if (ciso_14) then +!------------------------------------------------------------------------------- + if (ciso_organic_14) then +! 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) +!------------------------------------------------------------------------------- +! Phytoplankton C_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) +!------------------------------------------------------------------------------- +! Detritus C_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) +!------------------------------------------------------------------------------- +! Heterotrophic C_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) +!------------------------------------------------------------------------------- +! Diatom C_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) +!------------------------------------------------------------------------------- +! Small phytoplankton calcite_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) +!------------------------------------------------------------------------------- +! Detritus calcite_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, identical to DIC except for radioactive decay (-> +! recom_forcing) + sms(k,idic_14) = sms(k,idic) + end if ! ciso_organic_14 + end if ! ciso_14 + end if ! ciso +!------------------------------------------------------------------------------- +! 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 + +!------------------------------------------------------------------------------- +! Remineralization from the sediments into the bottom layer + + if (use_MEDUSA .and. (sedflx_num .ne. 0)) then + if (mype==0) then !OG + write(*,*) ' --> Sedimentary input of nutrients through MEDUSA' + endif + + else ! not use_MEDUSA or sedflx_num = 0 +!*** 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) + +!*** 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 + +!*** 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 + +!*** 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 + + if (ciso) then +!*** DIC_13 *** We ignore isotopic fractionation during remineralization. + decayBenthos(5) = alpha_dcal_13 * decayRateBenC * LocBenthos(5) + LocBenthos(5) = LocBenthos(5) - decayBenthos(5) * dt_b +!*** Calc: DIC_13 *** + decayBenthos(6) = calc_diss_13 * LocBenthos(6) + LocBenthos(6) = LocBenthos(6) - decayBenthos(6) * dt_b ! / depth of benthos + if (ciso_14) then + if (ciso_organic_14) then +!*** DIC_14 *** We ignore isotopic fractionation during remineralization. + decayBenthos(7) = alpha_dcal_14 * decayRateBenC * LocBenthos(7) + LocBenthos(7) = LocBenthos(7) - decayBenthos(7) * dt_b +!*** Calc: DIC_14 *** + decayBenthos(8) = calc_diss_14 * LocBenthos(8) + LocBenthos(8) = LocBenthos(8) - decayBenthos(8) * dt_b ! / depth of benthos + else +! Do nothing here because sms(idic_14) is defined as sms(idic) further +! above + end if ! ciso_organic_14 + end if ! ciso_14 + end if ! ciso + endif ! use_MEDUSA + + end do ! Main time loop ends + + +end subroutine REcoM_sms + +!------------------------------------------------------------------------------- +! Function for calculating limiter +!------------------------------------------------------------------------------- + +function recom_limiter(slope,qa,qb) + use recom_config + Implicit None + 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) + else + recom_limiter = 1.d0 - exp( -slope*( abs(dq)-dq )**2) + endif + return + end + +!------------------------------------------------------------------------------- +! Function for iron chemistry +!------------------------------------------------------------------------------- +function iron_chemistry_2ligands(fet,l1t,l2t,k1,k2) + implicit none + + Real(kind=8) :: iron_chemistry_2ligands + Real(kind=8) :: l1t,l2t,fet,k1,k2 + Real(kind=8) :: a3,a2,a1,a0,a,b,c,p,q,discr,rho,phi,amp,pi + Real(kind=8) :: one3rd, one27th + Real(kind=8) :: fe1,fe2,fe3 + +! coefficients of the 4th-order polynomial + a3 = k1*k2 + a2 = ( k1*k2*(l1t + l2t - fet) + k1 + k2 ) + a1 = ( 1 - (k1 + k2)*fet + k1*l1t + k2*l2t ) + a0 = -fet + +! coefficients of the normalized polynomial + a = a2/a3 + b = a1/a3 + c = a0/a3 + +! some numbers that are used several times + one3rd = 1.0/3.0 + one27th = 1.0/27.0 + +! now solve the polynomial stepwise + p = b - a*a*one3rd + q = c - a*b*one3rd + 2.0*a*a*a*one27th + discr = q*q/4.0 + p*p*p*one27th + + rho = sqrt(-(p*p*p*one27th)) + phi = acos(-q/(2.0*rho)) + amp = 2.0*rho**one3rd + pi = 3.1415926535897931 + +! the equation has three real roots + fe1 = amp*cos(phi*one3rd) - a*one3rd + fe2 = amp*cos((phi + 2.0*pi)*one3rd) - a*one3rd + fe3 = amp*cos((phi + 4.0*pi)*one3rd) - a*one3rd + + iron_chemistry_2ligands = max(fe1,fe2,fe3) + +end function iron_chemistry_2ligands +!------------------------------------------------------------------------------- +function iron_chemistry(Fe, totalLigand, ligandStabConst) + implicit none + + Real(kind=8) :: iron_chemistry + Real(kind=8) :: Fe, totalLigand, ligandStabConst ! Input + Real(kind=8) :: FreeFe ! Output + Real(kind=8) :: ligand,FeL,a,b,c,discrim + +! Abbrevations + a = 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 + freeFe = Fe - FeL + else ! No free iron + freeFe = 0.d0 + end if + + iron_chemistry = freeFe + + return + end function iron_chemistry + diff --git a/src/int_recom/recom_sms.F90.old b/src/int_recom/recom_sms.F90.old new file mode 100644 index 000000000..7259fd893 --- /dev/null +++ b/src/int_recom/recom_sms.F90.old @@ -0,0 +1,2548 @@ +subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & + , CO2_watercolumn & + , pH_watercolumn & + , pCO2_watercolumn & + , HCO3_watercolumn & + , CO3_watercolumn & + , OmegaC_watercolumn & + , kspc_watercolumn & + , rhoSW_watercolumn & + , Loc_slp, zF, PAR, Lond, Latd, ice, dynamics, tracers, partit, mesh) + + use recom_declarations + use recom_locvar + use recom_glovar + use recom_config + use recoM_ciso + use g_clock + + use g_config + use MOD_MESH + use MOD_TRACER + use MOD_DYN + USE MOD_ICE + use o_ARRAYS + use o_PARAM + USE MOD_PARTIT + USE MOD_PARSUP + + use g_forcing_arrays + use g_comm_auto + use mvars + use mdepth2press + use gsw_mod_toolbox, only: gsw_sa_from_sp,gsw_ct_from_pt,gsw_rho + + implicit none + type(t_dyn) , intent(inout), target :: dynamics + type(t_tracer), intent(inout), target :: tracers + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + type(t_ice) , intent(inout), target :: ice + + 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 + + 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 + real(kind=8),intent(in) :: SurfSR !< [W/m2] ShortWave radiation at surface + + real(kind=8),dimension(mesh%nl-1,bgc_num),intent(inout) :: sms !< Source-Minus-Sinks term + real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Temp !< [degrees C] Ocean temperature + real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Sali_depth !< NEW MOCSY Salinity for the whole water column + + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO2_watercolumn !< [mol/m3] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pH_watercolumn !< on total scale + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pCO2_watercolumn !< [uatm] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: HCO3_watercolumn !< [mol/m3] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO3_watercolumn !< [mol/m3] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: OmegaC_watercolumn !< calcite saturation state + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: kspc_watercolumn !< stoichiometric solubility product [mol^2/kg^2] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: rhoSW_watercolumn !< in-situ density of seawater [kg/m3] + + real(kind=8),dimension(mesh%nl) ,intent(in) :: zF !< [m] Depth of fluxes + real(kind=8),dimension(mesh%nl-1),intent(inout) :: PAR + + real(kind=8) :: dt_d !< Size of time steps [day] + real(kind=8) :: dt_b !< Size of time steps [day] + real(kind=8),dimension(mesh%nl-1) :: Sink + real(kind=8) :: dt_sink !< Size of local time step + + real(kind=8) :: recip_hetN_plus !< MB's addition to heterotrophic respiration + real(kind=8) :: recip_res_het !< [day] Reciprocal of respiration by heterotrophs and mortality (loss to detritus) + real(kind=8) :: Sink_Vel + real(kind=8) :: aux + integer :: k,step,ii, idiags,n + + real(kind=8), intent(in) :: Loc_slp ![Pa] sea-level pressure + real(kind=8) :: Patm_depth(1) + real(kind=8) :: REcoM_T_depth(1) ! MOCSY temperature for the whole water column for mocsy minimum defined as -2 + real(kind=8) :: REcoM_S_depth(1) + real(kind=8) :: REcoM_DIC_depth(1) + real(kind=8) :: REcoM_Alk_depth(1) + real(kind=8) :: REcoM_Si_depth(1) + real(kind=8) :: REcoM_Phos_depth(1) + 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 + +#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 + + 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 + + tiny_Si = tiny_C_d/SiCmax !< SiCmax = 0.8d0 + +#if defined (__coccos) + tiny_N_c = tiny_chl/chl2N_max_c + tiny_C_c = tiny_N_c/NCmax_c +#endif + + recip_res_het = 1.d0/res_het !< res_het = 0.01d0 [1/day] Respiration by heterotrophs and mortality (loss to detritus) + + Patm_depth = Loc_slp/Pa2atm ! MOCSY convert from Pa to atm. + +!------------------------------------------------------------------------------- +!> REcoM time steps [day] +!------------------------------------------------------------------------------- + + 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] + +!------------------------------------------------------------------------------- +!Main time loop starts + do step = one,biostep + + kdzUpper = 0.d0 !< Upper light attenuation of top cell is set to zero + + if (any(abs(sms(:,:)) <= tiny)) sms(:,:) = zero ! tiny = 2.23D-16 + +!------------------------------------------------------------------------------- +! 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 + +! 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 + + if (ciso) then +!< additional variables are declared in module REcoM_ciso + 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)) + + calc_diss_13 = alpha_dcal_13 * calc_diss + + 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 + + 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 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) + +!------------------------------------------------------------------------------- +!> 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 + +!------------------------------------------------------------------------------- +! Depth component of Mocsy (see http://ocmip5.ipsl.jussieu.fr/mocsy/pyth.html) +!------------------------------------------------------------------------------- + +! 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. + 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') + CO2_watercolumn(k) = co2_depth(1) + pH_watercolumn(k) = ph_depth(1) + pCO2_watercolumn(k) = pco2_depth(1) + HCO3_watercolumn(k) = hco3_depth(1) + CO3_watercolumn(k) = co3_depth(1) + 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') + CO2_watercolumn(k) = co2_depth(1) + pH_watercolumn(k) = ph_depth(1) + pCO2_watercolumn(k) = pco2_depth(1) + HCO3_watercolumn(k) = hco3_depth(1) + CO3_watercolumn(k) = co3_depth(1) + OmegaC_watercolumn(k) = OmegaC_depth(1) + 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') + CO2_watercolumn(k) = co2_depth(1) + pH_watercolumn(k) = ph_depth(1) + pCO2_watercolumn(k) = pco2_depth(1) + HCO3_watercolumn(k) = hco3_depth(1) + CO3_watercolumn(k) = co3_depth(1) + 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] + +! 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 + +! 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 + 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) + 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?? + 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 + +!< *** Diatom photosynthesis rate *** +!< ********************************** + if ( pMax_dia .lt. 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 + + 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 + else + KOchl = deg_Chl*(real(one) - exp(-alfa * CHL2C_plast * PARave / pMax)) + KOchl = max((deg_Chl*0.1d0), KOchl) + 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 + 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 + 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 + 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 + stop + end if +#endif + end if ! photodamage + +!------------------------------------------------------------------------------- +!> Assimilation section +!------------------------------------------------------------------------------- + +!< 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 + 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 + + limitFacSi = recom_limiter(SiMaxSlope, qSiC, SiCmax) & + * limitFacN_dia + Si_assim = V_cm_fact_d * P_cm_d * arrFunc * SiCUptakeRatio & + * limitFacSi * Si/(Si + k_si) + +!------------------------------------------------------------------------------- +!< *** Iron chemistry *** +!< ********************** +! select the method to calculate freeFe + freeFe = iron_chemistry(Fe,totalligand,ligandStabConst) +!------------------------------------------------------------------------------- +!< *** Chlorophyll synthesis *** +!< ***************************** + +!< 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 ] + + 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 + 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 *** +!< ************************************* + +!< res_phy: Maintenance respiration rate constant [day−1 ] +!< biosynth: The cost of biosynthesis of N [mmol C mmol N−1 ] + + phyRespRate = res_phy * limitFacN + biosynth * N_assim + phyRespRate_dia = res_phy_d * limitFacN_dia + biosynth * N_assim_dia + biosynthSi * Si_assim +#if defined (__coccos) + phyRespRate_cocco = res_phy_c * limitFacN_cocco + biosynth * N_assim_cocco +#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 + +!< *** 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 + +!------------------------------------------------------------------------------- +! 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 + +!< *** 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 + + grazingFlux_phy2 = (grazingFlux2 * fphyN2)/food2 + grazingFlux_Dia2 = (grazingFlux2 * fDiaN2)/food2 + grazingFlux_miczoo2 = (grazingFlux2 * fMicZooN2)/food2 ! 3Zoo + +#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 + + 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 + +!------------------------------------------------------------------------------- +! Third Zooplankton (Microzooplankton) +!------------------------------------------------------------------------------- +!< Grazing on small phytoplankton, diatoms and coccolithophore (optional) + +!< *** Food availability *** +!< ************************* +!< pzPhy3: Maximum nanophytoplankton preference +!< pzDia3: Maximum diatom preference +!< pzCocco3: Maximum coccolithophore preference + + 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 + +!------------------------------------------------------------------------------- +!< 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 + endif + + if (ciso) then +!MB set HetRespFlux_plus = .true. in namelist.recom +! HetRespFlux_13 = max(zero, recip_res_het * arrFunc * (hetC_13 * recip_hetN_plus - redfield) * HetC_13) +! Numerically safer parametrization avoiding instable results which may result from different cutoff values -- CHECK + HetRespFlux_13 = HetRespFlux * HetC_13 / HetC +!! HetRespFlux_13 = HetRespFlux * (HetC_13 / HetC) **2 + if (ciso_14 .and. ciso_organic_14) then +! HetRespFlux_14 = max(zero, recip_res_het * arrFunc * (hetC_14 * recip_hetN_plus - redfield) * HetC_14) + HetRespFlux_14 = HetRespFlux * HetC_14 / HetC +!! HetRespFlux_14 = HetRespFlux * (HetC_14 / HetC) **2 + end if + end if + +!------------------------------------------------------------------------------- +!< Zooplanton mortality (Quadratic) + + hetLossFlux = loss_het * HetN * HetN + +#if defined (__3Zoo2Det) +!------------------------------------------------------------------------------- +!< Second zooplankton respiration + + call krill_resp(n, partit, mesh) + + 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) + + Zoo2LossFlux = loss_zoo2 * zoo2N * zoo2N + +!------------------------------------------------------------------------------- +!< Second zooplankton fecal pellets + + Zoo2fecalloss_n = fecal_rate_n * grazingFlux2 + Zoo2fecalloss_c = fecal_rate_c * grazingFluxcarbonzoo2 + +!------------------------------------------------------------------------------- +!< Mesozooplankton fecal pellets + + mesfecalloss_n = fecal_rate_n_mes * grazingFlux + mesfecalloss_c = fecal_rate_c_mes * grazingFluxcarbon_mes + +!------------------------------------------------------------------------------- +! Third zooplankton, microzooplankton, respiration ! 3Zoo + + MicZooRespFlux = res_miczoo * q10_mic_res * MicZooC +!------------------------------------------------------------------------------- +! Third zooplankton, microzooplankton, mortality (Quadratic) ! 3Zoo + + MicZooLossFlux = loss_miczoo * MicZooN * MicZooN +#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 + 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 + +#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 + + if (ciso) then + calcification_13 = calc_prod_ratio * Cphot * PhyC_13 * alpha_calc_13 + calcification_13 = calcification * alpha_calc_13 + calc_loss_agg_13 = aggregationRate * PhyCalc_13 + calc_loss_gra_13 = grazingFlux_phy * recipQuota_13/(PhyC_13 + tiny) * PhyCalc_13 + if (ciso_14 .and. ciso_organic_14) then + calcification_14 = calc_prod_ratio * Cphot * PhyC_14 * alpha_calc_14 + calc_loss_agg_14 = aggregationRate * PhyCalc_14 + calc_loss_gra_14 = grazingFlux_phy * recipQuota_14/(PhyC_14 + tiny) * PhyCalc_14 + end if + end if + +!------------------------------------------------------------------------------- +! Sources minus sinks (SMS) +!------------------------------------------------------------------------------- + +!< *** 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((Latd(1)<-45.0) .and. ((state(k,idic)+sms(k,idic))>2500)) then +! !co2flux(1)=0.0 +! print*,'ERROR: strange dic !' +! print*,'state(k,idic): ', state(k,idic) +! print*,'sms Cphot: ', -Cphot*PhyC +! print*,'sms resp: ', phyRespRate*PhyC +! print*,'sms Cphot dia: ', -Cphot_Dia*DiaC +! print*,'sms resp dia: ', phyRespRate_Dia * DiaC +! print*,'sms eoc: ', rho_C1* arrFunc *EOC +! print*,'sms het resp: ', HetRespFlux +! print*, 'sms co2: ', dflux(1) * recipdzF(k) * max( 2-k, 0 ) +! print*, 'sms calcdiss: ', calc_diss * DetCalc +! print*, 'sms calc_loss: ', calc_loss_gra * calc_diss_guts +! print*, 'sms calcification: ', -calcification +! 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 & ! --> grazing on small phytoplankton by third zooplankton + - grazingFlux_phy3 * grazEff3 & ! --> fraction of grazingFlux_phy3 into microzooplankton pool + + grazingFlux_dia3 & ! --> grazing on diatoms by third zooplankton + - grazingFlux_dia3 * grazEff3 & ! --> fraction of grazingFlux_dia3 into microzooplankton pool +#if defined (__coccos) + + grazingFlux_Cocco3 & ! --> grazing on coccolithophores by third zooplankton + - grazingFlux_Cocco3 * grazEff3 & ! --> fraction of grazingFlux_Cocco3 into microzooplankton pool + + aggregationRate * CoccoN & +#endif + - grazingFlux_Det * grazEff & ! --> grazing of first zoo (meso) on first detritus class + - grazingFlux_Det2 * grazEff2 & ! --> grazing of second zoo (macro) on first detritus class + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + miczooLossFlux & ! --> microzooplankton, mortality + - reminN * arrFunc * O2Func * DetN & ! --> O2remin + ) * dt_b + sms(k,idetn) +#else + sms(k,idetn) = ( & + + grazingFlux_phy & ! Technically it is mesooooooooooooooooo + - 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 * recipDet * grazEff2 & ! corrected recipDet2 -> recipDet + + 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 + 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) + else + sms(k,ihetc) = ( & + + grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia * grazEff & +#if defined (__coccos) + + grazingFlux_Cocco * recipQuota_Cocco * grazEff & +#endif +#if defined (__3Zoo2Det) + + grazingFlux_miczoo * recipQZoo3 * grazEff & ! 3Zoo + - grazingFlux_het2 * recipQZoo & + - Mesfecalloss_c & ! 3Zoo +#endif + - hetLossFlux * recipQZoo & + - lossC_z * HetC & + - hetRespFlux & + ) * dt_b + sms(k,ihetc) + endif + +!< *** Macrozooplankton *** +!< ************************ + +#if defined (__3Zoo2Det) +!____________________________________________________________ +!< Second Zooplankton N + sms(k,izoo2n) = ( & + + grazingFlux2 * grazEff2 & + - Zoo2LossFlux & + - lossN_z2 * Zoo2N & + - Zoo2fecalloss_n & + ) * dt_b + sms(k,izoo2n) + +!____________________________________________________________ +!< Second Zooplankton C + if (Grazing_detritus) then + + sms(k,izoo2c) = ( & + + grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo + + grazingFlux_Det2 * recipDet * grazEff2 & + + grazingFlux_DetZ22 * recipDet2 * grazEff2 & + - zoo2LossFlux * recipQZoo2 & + - lossC_z2 * Zoo2C & + - Zoo2RespFlux & + - Zoo2fecalloss_c & + ) * dt_b + sms(k,izoo2c) + else + sms(k,izoo2c) = ( & + + grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo + - zoo2LossFlux * recipQZoo2 & + - lossC_z2 * Zoo2C & + - Zoo2RespFlux & + - Zoo2fecalloss_c & + ) * dt_b + sms(k,izoo2c) + end if + +!< *** Microzooplankton *** +!< ************************ + +!____________________________________________________________ +!< Third Zooplankton N + sms(k,imiczoon) = ( & + + grazingFlux3 * grazEff3 & + - grazingFlux_miczoo & + - grazingFlux_miczoo2 & + - MicZooLossFlux & + - lossN_z3 * MicZooN & + ) * dt_b + sms(k,imiczoon) + +!____________________________________________________________ +!< Third Zooplankton C + sms(k,imiczooc) = ( & + + grazingFlux_phy3 * recipQuota * grazEff3 & + + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & +#if defined (__coccos) + + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & +#endif + - MicZooLossFlux * recipQZoo3 & + - grazingFlux_miczoo * recipQZoo3 & + - grazingFlux_miczoo2 * recipQZoo3 & + - lossC_z3 * MicZooC & + - MicZooRespFlux & + ) * dt_b + sms(k,imiczooc) + +!< *** Fast-sinking Detritus *** +!< ***************************** + +!____________________________________________________________ +!< Second Zooplankton Detritus N + if (Grazing_detritus) then + sms(k,idetz2n) = ( & + + grazingFlux_phy2 & + - grazingFlux_phy2 * grazEff2 & + + grazingFlux_dia2 & + - grazingFlux_dia2 * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco & + - grazingFlux_Cocco * grazEff & + + grazingFlux_Cocco2 & + - grazingFlux_Cocco2 * grazEff2 & +#endif + + grazingFlux_het2 & + - grazingFlux_het2 * grazEff2 & + + grazingFlux_miczoo2 & + - grazingFlux_miczoo2 * grazEff2 & + + grazingFlux_phy & + - grazingFlux_phy * grazEff & + + grazingFlux_dia & + - grazingFlux_dia * grazEff & + + grazingFlux_miczoo & + - grazingFlux_miczoo * grazEff & + - grazingFlux_DetZ2 * grazEff & + - grazingFlux_DetZ22 * grazEff2 & + + Zoo2LossFlux & + + hetLossFlux & + + Zoo2fecalloss_n & + + Mesfecalloss_n & + - reminN * arrFunc * O2Func * DetZ2N & ! O2remin + ) * dt_b + sms(k,idetz2n) + else + sms(k,idetz2n) = ( & + + grazingFlux_phy2 & + + grazingFlux_dia2 & +#if defined (__coccos) + + grazingFlux_Cocco & + + grazingFlux_Cocco2 & +#endif + + grazingFlux_het2 & + + grazingFlux_miczoo2 & + - grazingFlux2 * grazEff2 & + + grazingFlux_phy & + + grazingFlux_dia & + + grazingFlux_miczoo & + - grazingFlux * grazEff & + + Zoo2LossFlux & + + hetLossFlux & + + Zoo2fecalloss_n & + + Mesfecalloss_n & + - reminN * arrFunc * O2Func * DetZ2N & ! O2remin + ) * dt_b + sms(k,idetz2n) + end if + +!____________________________________________________________ +!< Second Zooplankton Detritus C + if (Grazing_detritus) then + sms(k,idetz2c) = ( & + + grazingFlux_phy2 * recipQuota & + - grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia & + - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco * recipQuota_Cocco & + - grazingFlux_Cocco * recipQuota_Cocco * grazEff & + + grazingFlux_Cocco2 * recipQuota_Cocco & + - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo & + - grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2 * recipQZoo3 & + - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & + + grazingFlux_phy * recipQuota & + - grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia & + - grazingFlux_Dia * recipQuota_Dia * grazEff & + + grazingFlux_miczoo * recipQZoo3 & + - grazingFlux_miczoo * recipQZoo3 * grazEff & + - grazingFlux_DetZ2 * recipDet2 * grazEff & + - grazingFlux_DetZ22 * recipDet2 * grazEff2 & + + Zoo2LossFlux * recipQZoo2 & + + hetLossFlux * recipQZoo & + + Zoo2fecalloss_c & + + Mesfecalloss_c & + - reminC * arrFunc * O2Func * DetZ2C & ! O2remin + ) * dt_b + sms(k,idetz2c) + else + sms(k,idetz2c) = ( & + + grazingFlux_phy2 * recipQuota & + - grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia & + - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco * recipQuota_Cocco & + - grazingFlux_Cocco * recipQuota_Cocco * grazEff & + + grazingFlux_Cocco2 * recipQuota_Cocco & + - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo & + - grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2 * recipQZoo3 & + - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & + + grazingFlux_phy * recipQuota & + - grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia & + - grazingFlux_Dia * recipQuota_Dia * grazEff & + + grazingFlux_miczoo * recipQZoo3 & + - grazingFlux_miczoo * recipQZoo3 * grazEff & + + Zoo2LossFlux * recipQZoo2 & + + hetLossFlux * recipQZoo & + + Zoo2fecalloss_c & + + Mesfecalloss_c & + - reminC * arrFunc * O2Func * DetZ2C & ! O2remin + ) * dt_b + sms(k,idetz2c) + end if + +!____________________________________________________________ +!< Second Zooplankton Detritus Si + sms(k,idetz2si) = ( & + + grazingFlux_dia2 * qSiN & ! --> qSin convert N to Si + + grazingFlux_dia * qSiN & + - reminSiT * DetZ2Si & + ) * dt_b + sms(k,idetz2si) + +!____________________________________________________________ +!< Second Zooplankton Detritus calcite + sms(k,idetz2calc) = ( & + + calc_loss_gra2 & + - calc_loss_gra2 * calc_diss_guts & + + calc_loss_gra & + - calc_loss_gra * calc_diss_guts & + - calc_diss2 * DetZ2Calc & + ) * dt_b + sms(k,idetz2calc) +#endif + +!< *** DOM *** +!< *********** + +!____________________________________________________________ +!< DON (Extracellular organic N) + + sms(k,idon) = ( & + + lossN * limitFacN * phyN & + + lossN_d * limitFacN_Dia * DiaN & +#if defined (__coccos) + + lossN_c * limitFacN_Cocco * CoccoN & +#endif + + reminN * arrFunc * O2Func * DetN & + + lossN_z * HetN & +#if defined (__3Zoo2Det) + + reminN * arrFunc * O2Func * DetZ2N & + + lossN_z2 * Zoo2N & + + lossN_z3 * MicZooN & ! 3Zoo +#endif + - rho_N * arrFunc * O2Func * DON & ! O2remin + ) * dt_b + sms(k,idon) + +!____________________________________________________________ +!< EOC + + sms(k,idoc) = ( & + + lossC * limitFacN * phyC & + + lossC_d * limitFacN_dia * DiaC & +#if defined (__coccos) + + lossC_c * limitFacN_cocco * CoccoC & +#endif + + reminC * arrFunc * O2Func * DetC & + + lossC_z * HetC & +#if defined (__3Zoo2Det) + + reminC * arrFunc * O2Func * DetZ2C & + + lossC_z2 * Zoo2C & + + lossC_z3 * MicZooC & ! 3Zoo +#endif + - rho_c1 * arrFunc * O2Func * EOC & ! O2remin + ) * dt_b + sms(k,idoc) + +!< *** Diatoms *** +!< *************** + +!____________________________________________________________ +!< Diatom N + +!< lossN: Diatom loss of organic N compounds [day^-1] +!< When N : C ratio becomes too high, excretion of DON is downregulated +!< by the limiter function limitFacN_dia +!< aggregationRate transfers N to the detritus pool + + sms(k,idian) = ( & + + N_assim_dia * DiaC & ! --> N assimilation + - lossN_d * limitFacN_dia * DiaN & ! --> DON excretion + - aggregationRate * DiaN & ! --> Aggregation loss + - grazingFlux_Dia & ! --> Grazing loss +#if defined (__3Zoo2Det) + - grazingFlux_Dia2 & + - grazingFlux_Dia3 & ! 3Zoo +#endif + ) * dt_b + sms(k,idian) + +!____________________________________________________________ +!< Diatom C + +!< lossC_d: Diatom loss of carbon [day^-1] +!< When N : C ratio becomes too high, excretion of DOC is downregulated +!< by the limiter function limitFacN_dia +!< aggregationRate transfers C to the detritus pool + + sms(k,idiac) = ( & + + Cphot_dia * DiaC & ! -- Photosynthesis ---->/ + - lossC_d * limitFacN_dia * DiaC & ! -- Excretion of DOC --/ Net Photosynthesis + - phyRespRate_dia * DiaC & ! -- Respiration ----->/ + - aggregationRate * DiaC & + - grazingFlux_dia * recipQuota_dia & +#if defined (__3Zoo2Det) + - grazingFlux_dia2 * recipQuota_dia & + - grazingFlux_dia3 * recipQuota_dia & ! 3Zoo +#endif + ) * dt_b + sms(k,idiac) + +!____________________________________________________________ +!< Diatom Chl + + sms(k,idchl) = ( & + + chlSynth_dia * DiaC & ! --> Chl a synthesis + - KOchl_dia * DiaChl & ! --> Degradation loss + - aggregationRate * DiaChl & ! --> Aggregation loss + - grazingFlux_dia * Chl2N_dia & ! --> Grazing loss +#if defined (__3Zoo2Det) + - grazingFlux_dia2 * Chl2N_dia & + - grazingFlux_dia3 * Chl2N_dia & ! 3Zoo +#endif + ) * dt_b + sms(k,idchl) + +!____________________________________________________________ +!< Diatom Si + +!< lossN_d: Diatom loss of organic nitrogen compunds [day^-1] +!< When N : C ratio becomes too high, excretion is downregulated +!< by the limiter function limitFacN_dia +!< aggregationRate transfers Si to the detritus pool + + sms(k,idiasi) = ( & + + Si_assim * DiaC & ! -- Diatom silicon assimilation + - lossN_d * limitFacN_dia * DiaSi & ! -- Excretion to detritus + - aggregationRate * DiaSi & ! -- Aggregation loss + - grazingFlux_dia * qSiN & ! -- Grazing loss +#if defined (__3Zoo2Det) + - grazingFlux_dia2 * qSiN & + - grazingFlux_dia3 * qSiN & ! 3Zoo +#endif + ) * dt_b + sms(k,idiasi) + +!< *** Coccolithophore *** +!< *********************** + +#if defined (__coccos) +!____________________________________________________________ +!< Coccolithophore N + sms(k,icocn) = ( & + + N_assim_cocco * CoccoC & + - lossN_c * limitFacN_cocco * CoccoN & + - aggregationRate * CoccoN & + - grazingFlux_Cocco & +#if defined (__3Zoo2Det) + - grazingFlux_Cocco2 & + - grazingFlux_Cocco3 & ! 3Zoo +#endif + ) * dt_b + sms(k,icocn) + +!____________________________________________________________ +!< Coccolithophore C + + sms(k,icocc) = ( & + + Cphot_cocco * CoccoC & + - lossC_c * limitFacN_cocco * CoccoC & + - phyRespRate_cocco * CoccoC & + - aggregationRate * CoccoC & + - grazingFlux_cocco * recipQuota_cocco & +#if defined (__3Zoo2Det) + - grazingFlux_Cocco2 * recipQuota_cocco & + - grazingFlux_Cocco3 * recipQuota_cocco & ! 3Zoo +#endif + ) * dt_b + sms(k,icocc) + + if(sms(k,icocc)>100) then + print*,'ERROR: strange CoccoC !' + print*,'k= ', k + print*,'dt= ', dt + print*,'dt_b= ', dt_b + print*,'state(k,icocc): ', state(k,icocc) + print*,'sms CoccoC: ', CoccoC + print*,'sms CoccoN: ', CoccoN + print*,'sms Cphot cocco: ', Cphot_cocco*CoccoC + print*,'sms lossC_c: ', lossC_c + print*,'sms limitFacN_cocco: ', limitFacN_cocco + print*,'sms phyRespRate_cocco: ', phyRespRate_cocco + print*,'sms grazingFlux_cocco: ', grazingFlux_cocco + print*,'sms grazingFlux_cocco2: ', grazingFlux_Cocco2 + print*,'sms grazingFlux_cocco3: ', grazingFlux_Cocco3 + print*,'sms recipQuota_cocco: ', recipQuota_cocco + + print*,'sms recipQuota_cocco: ', recipQuota_cocco + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + endif + +!____________________________________________________________ +!< Coccolithophore Chl + + sms(k,icchl) = ( & + + ChlSynth_cocco * CoccoC & + - KOchl_cocco * CoccoChl & + - aggregationRate * CoccoChl & + - grazingFlux_cocco * Chl2N_cocco & +#if defined (__3Zoo2Det) + - grazingFlux_Cocco2 * Chl2N_cocco & + - grazingFlux_Cocco3 * Chl2N_cocco & ! 3Zoo +#endif + ) * dt_b + sms(k,icchl) +#endif + +!< *** Silicate *** +!< **************** + +!____________________________________________________________ +!< Detritus Si +#if defined (__3Zoo2Det) + sms(k,idetsi) = ( & + + aggregationRate * DiaSi & + + lossN_d * limitFacN_dia * DiaSi & + + grazingFlux_dia3 * qSiN & + - reminSiT * DetSi & + ) * dt_b + sms(k,idetsi) +#else + sms(k,idetsi) = ( & + + aggregationRate * DiaSi & + + lossN_d * limitFacN_dia * DiaSi & + + grazingFlux_dia * qSiN & + - reminSiT * DetSi & + ) * dt_b + sms(k,idetsi) +#endif +!____________________________________________________________ +!< DSi, Silicate + +!< DiaC: Intracellular carbon concentration in diatoms [mmolC m-3] +!< DetSi: Detritus silicon concentration [mmolSi m-3] +!< Si_assim: Si assimilation rate for diatoms [mmolSi mmolC-1 day-1] +!< reminSiT: Remineralization rate of silicon, temperature dependency [day-1] +!< dt_b: REcoM time step [day] + +!! Schourup 2013 Eq. A3 + + sms(k,isi) = ( & + - Si_assim * DiaC & ! --> Si assimilation of diatoms + + reminSiT * DetSi & ! --> Remineralization of detritus, temperature dependent +#if defined (__3Zoo2Det) + + reminSiT * DetZ2Si & +#endif + ) * dt_b + sms(k,isi) +!< *** Iron *** +!< ************ + +!____________________________________________________________ +!< Fe + +!< Fe2N: Intracellular Fe : N ratio [μmol Fe mmol N^-1] Fe2N = Fe2C * 6.625 +!< PhyC: Intracellular carbon concentration in nanophytoplankton [mmolCm^-3] +!< Cphot: C-specific actual rate of photosynthesis for nanopyhtoplankton [day^-1] +!< DiaC: Intracellular carbon concentration in diatoms [mmol C m^-3 ] +!< Cphot_dia: C-specific actual rate of photosynthesis for diatom [day^-1] +!< phyRespRate: Nanopyhtoplankton respiration rate [day^-1] +!< phyRespRate_dia: Diatom respiration rate [day^-1] +!< lossC: Nanopyhtoplankton excretion of organic C [day^-1] +!< limitFacN: limiting factor +!< lossC_d: Diatom excretion of organic C [day^-1] +!< limitFacN_dia: limiting factor +!< detC: Detritus carbon concentration [mmol C m^-3] +!< reminC: Temperature dependent remineralisation rate of detritus [day^-1] +!< arrFunc: Arrhenius function +!< hetC: Zooplankton carbon concentration [mmol C m^-3 ] +!< lossC_z: Zooplankton excretion of organic C [day^-1 ] +!< hetRespFlux: Zooplankton respiration rate [day^-1] +!< kScavFe: Scavenging rate of iron [m3 mmol C^-1 day^-1] + + sms(k,ife) = ( Fe2N * ( & + - N_assim * PhyC & ! --> N assimilation Nanophytoplankton, [mmol N/(mmol C * day)] C specific N utilization rate + - N_assim_dia * DiaC & ! --> N assimilation Diatom +#if defined (__coccos) + - N_assim_cocco * CoccoC & + + lossN_c * limitFacN_cocco * CoccoN & +#endif + + lossN * limitFacN * PhyN & ! --> Excretion from small pythoplankton + + lossN_d * limitFacN_dia * DiaN & ! --> Excretion from diatom + + reminN * arrFunc * O2Func * DetN & ! --> Remineralization of detritus ! NEW O2remin + + lossN_z * HetN & ! --> Excretion from zooplankton +#if defined (__3Zoo2Det) + + reminN * arrFunc * O2Func * DetZ2N & ! O2remin + + lossN_z2 * Zoo2N & + + lossN_z3 * MicZooN & ! 3Zoo +#endif + ) & + - kScavFe * DetC * FreeFe & +#if defined (__3Zoo2Det) + - kScavFe * DetZ2C * FreeFe & +#endif + ) * dt_b + sms(k,ife) + +!< *** Calcification *** +!< ********************* + +!____________________________________________________________ +!< Small phytoplankton calcite + +#if defined (__coccos) + sms(k,iphycal) = ( & + + calcification & ! --> Calcification + - lossC_c * limitFacN_cocco * PhyCalc & ! --> Excretion loss + - phyRespRate_cocco * PhyCalc & ! --> Respiration + - calc_loss_agg & ! --> Aggregation loss + - calc_loss_gra & ! --> Grazing loss +#if defined (__3Zoo2Det) + - calc_loss_gra2 & + - calc_loss_gra3 & ! 3Zoo +#endif + ) * dt_b + sms(k,iphycal) +#else + sms(k,iphycal) = ( & + + calcification & ! --> Calcification + - lossC * limitFacN * PhyCalc & ! --> Excretion loss + - phyRespRate * PhyCalc & ! --> Respiration + - calc_loss_agg & ! --> Aggregation loss + - calc_loss_gra & ! --> Grazing loss +#if defined (__3Zoo2Det) + - calc_loss_gra2 & + - calc_loss_gra3 & ! 3Zoo +#endif + ) * dt_b + sms(k,iphycal) +#endif + +!____________________________________________________________ +! Detritus calcite +#if defined (__coccos) + +#if defined (__3Zoo2Det) + sms(k,idetcal) = ( & + + lossC_c * limitFacN_cocco * PhyCalc & + + phyRespRate_cocco * PhyCalc & + + calc_loss_agg & + + calc_loss_gra3 & + - calc_loss_gra3 * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + +#else + sms(k,idetcal) = ( & + + lossC_c * limitFacN_cocco * PhyCalc & + + phyRespRate_cocco * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + +#endif + +#else + +#if defined (__3Zoo2Det) + sms(k,idetcal) = ( & + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra3 & + - calc_loss_gra3 * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) +#else + sms(k,idetcal) = ( & + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) +#endif +#endif + +!____________________________________________________________ +! Oxygen + + sms(k,ioxy) = ( & + + Cphot * phyC & + - phyRespRate * phyC & + + Cphot_dia * diaC & + - phyRespRate_dia * diaC & +#if defined (__coccos) + + Cphot_cocco * CoccoC & + - phyRespRate_cocco * CoccoC & +#endif + - rho_C1 * arrFunc * O2Func * EOC & ! O2remin + - hetRespFlux & +#if defined (__3Zoo2Det) + - Zoo2RespFlux & + - MicZooRespFlux & ! 3Zoo +#endif + ) * redO2C * dt_b + sms(k,ioxy) +! + if (ciso) then +!------------------------------------------------------------------------------- +! DIC_13 + sms(k,idic_13) = ( & + - Cphot * PhyC_13 & + + phyRespRate * PhyC_13 & + - Cphot_Dia * DiaC_13 & + + phyRespRate_Dia * DiaC_13 & + + rho_C1 * arrFunc * EOC_13 & + + HetRespFlux_13 & + + calc_diss_13 * DetCalc_13 & + + calc_loss_gra_13 * calc_diss_guts & + - calcification_13 & + ) * dt_b + sms(k,idic_13) +!------------------------------------------------------------------------------- +! Phytoplankton C_13 + sms(k,iphyc_13) = ( & + + Cphot * PhyC_13 & + - lossC * limitFacN * PhyC_13 & + - phyRespRate * PhyC_13 & + - aggregationRate * PhyC_13 & + - grazingFlux_phy * recipQuota_13 & + ) * dt_b + sms(k,iphyc_13) +!------------------------------------------------------------------------------- +! Detritus C_13 + sms(k,idetc_13) = ( & + + grazingFlux_phy * recipQuota_13 & + - grazingFlux_phy * recipQuota_13 * grazEff & + + grazingFlux_Dia * recipQuota_dia_13 & + - grazingFlux_Dia * recipQuota_dia_13 * grazEff & + + aggregationRate * phyC_13 & + + aggregationRate * DiaC_13 & + + hetLossFlux * recipQZoo_13 & + - reminC * arrFunc * DetC_13 & + ) * dt_b + sms(k,idetc_13) +!------------------------------------------------------------------------------- +! Heterotrophic C_13 + sms(k,ihetc_13) = ( & + + grazingFlux_phy * recipQuota_13 * grazEff & + + grazingFlux_Dia * recipQuota_dia_13 * grazEff & + - hetLossFlux * recipQZoo_13 & + - lossC_z * HetC_13 & + - hetRespFlux_13 & + ) * dt_b + sms(k,ihetc_13) +!------------------------------------------------------------------------------- +! EOC_13 + sms(k,idoc_13) = ( & + + lossC * limitFacN * phyC_13 & + + lossC_d * limitFacN_dia * DiaC_13 & + + reminC * arrFunc * DetC_13 & + + lossC_z * HetC_13 & + - rho_c1 * arrFunc * EOC_13 & + + LocRiverDOC * r_iorg_13 & + ) * dt_b + sms(k,idoc_13) +!------------------------------------------------------------------------------- +! Diatom C_13 + sms(k,idiac_13) = ( & + + Cphot_dia * DiaC_13 & + - lossC_d * limitFacN_dia * DiaC_13 & + - phyRespRate_dia * DiaC_13 & + - aggregationRate * DiaC_13 & + - grazingFlux_dia * recipQuota_dia_13 & + ) * dt_b + sms(k,idiac_13) +!------------------------------------------------------------------------------- +! Small phytoplankton calcite_13 + sms(k,iphycal_13) = ( & + + calcification_13 & + - lossC * limitFacN * phyCalc_13 & + - phyRespRate * phyCalc_13 & + - calc_loss_agg_13 & + - calc_loss_gra_13 & + ) * dt_b + sms(k,iphycal_13) +!------------------------------------------------------------------------------- +! Detritus calcite_13 + sms(k,idetcal_13) = ( & + + lossC * limitFacN * phyCalc_13 & + + phyRespRate * phyCalc_13 & + + calc_loss_agg_13 & + + calc_loss_gra_13 & + - calc_loss_gra_13 * calc_diss_guts & + - calc_diss_13 * DetCalc_13 & + ) * dt_b + sms(k,idetcal_13) +!------------------------------------------------------------------------------- + if (ciso_14) then +!------------------------------------------------------------------------------- + if (ciso_organic_14) then +! 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) +!------------------------------------------------------------------------------- +! Phytoplankton C_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) +!------------------------------------------------------------------------------- +! Detritus C_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) +!------------------------------------------------------------------------------- +! Heterotrophic C_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) +!------------------------------------------------------------------------------- +! Diatom C_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) +!------------------------------------------------------------------------------- +! Small phytoplankton calcite_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) +!------------------------------------------------------------------------------- +! Detritus calcite_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, identical to DIC except for radioactive decay (-> +! recom_forcing) + sms(k,idic_14) = sms(k,idic) + end if ! ciso_organic_14 + end if ! ciso_14 + end if ! ciso +!------------------------------------------------------------------------------- +! 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 + +!------------------------------------------------------------------------------- +! Remineralization from the sediments into the bottom layer + + if (use_MEDUSA .and. (sedflx_num .ne. 0)) then + if (mype==0) then !OG + write(*,*) ' --> Sedimentary input of nutrients through MEDUSA' + endif + + else ! not use_MEDUSA or sedflx_num = 0 +!*** 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) + +!*** 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 + +!*** 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 + +!*** 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 + + if (ciso) then +!*** DIC_13 *** We ignore isotopic fractionation during remineralization. + decayBenthos(5) = alpha_dcal_13 * decayRateBenC * LocBenthos(5) + LocBenthos(5) = LocBenthos(5) - decayBenthos(5) * dt_b +!*** Calc: DIC_13 *** + decayBenthos(6) = calc_diss_13 * LocBenthos(6) + LocBenthos(6) = LocBenthos(6) - decayBenthos(6) * dt_b ! / depth of benthos + if (ciso_14) then + if (ciso_organic_14) then +!*** DIC_14 *** We ignore isotopic fractionation during remineralization. + decayBenthos(7) = alpha_dcal_14 * decayRateBenC * LocBenthos(7) + LocBenthos(7) = LocBenthos(7) - decayBenthos(7) * dt_b +!*** Calc: DIC_14 *** + decayBenthos(8) = calc_diss_14 * LocBenthos(8) + LocBenthos(8) = LocBenthos(8) - decayBenthos(8) * dt_b ! / depth of benthos + else +! Do nothing here because sms(idic_14) is defined as sms(idic) further +! above + end if ! ciso_organic_14 + end if ! ciso_14 + end if ! ciso + endif ! use_MEDUSA + + end do ! Main time loop ends + + +end subroutine REcoM_sms + +!------------------------------------------------------------------------------- +! Function for calculating limiter +!------------------------------------------------------------------------------- + +function recom_limiter(slope,qa,qb) + use recom_config + Implicit None + 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) + else + recom_limiter = 1.d0 - exp( -slope*( abs(dq)-dq )**2) + endif + return + end + +!------------------------------------------------------------------------------- +! Function for iron chemistry +!------------------------------------------------------------------------------- +function iron_chemistry_2ligands(fet,l1t,l2t,k1,k2) + implicit none + + Real(kind=8) :: iron_chemistry_2ligands + Real(kind=8) :: l1t,l2t,fet,k1,k2 + Real(kind=8) :: a3,a2,a1,a0,a,b,c,p,q,discr,rho,phi,amp,pi + Real(kind=8) :: one3rd, one27th + Real(kind=8) :: fe1,fe2,fe3 + +! coefficients of the 4th-order polynomial + a3 = k1*k2 + a2 = ( k1*k2*(l1t + l2t - fet) + k1 + k2 ) + a1 = ( 1 - (k1 + k2)*fet + k1*l1t + k2*l2t ) + a0 = -fet + +! coefficients of the normalized polynomial + a = a2/a3 + b = a1/a3 + c = a0/a3 + +! some numbers that are used several times + one3rd = 1.0/3.0 + one27th = 1.0/27.0 + +! now solve the polynomial stepwise + p = b - a*a*one3rd + q = c - a*b*one3rd + 2.0*a*a*a*one27th + discr = q*q/4.0 + p*p*p*one27th + + rho = sqrt(-(p*p*p*one27th)) + phi = acos(-q/(2.0*rho)) + amp = 2.0*rho**one3rd + pi = 3.1415926535897931 + +! the equation has three real roots + fe1 = amp*cos(phi*one3rd) - a*one3rd + fe2 = amp*cos((phi + 2.0*pi)*one3rd) - a*one3rd + fe3 = amp*cos((phi + 4.0*pi)*one3rd) - a*one3rd + + iron_chemistry_2ligands = max(fe1,fe2,fe3) + +end function iron_chemistry_2ligands +!------------------------------------------------------------------------------- +function iron_chemistry(Fe, totalLigand, ligandStabConst) + implicit none + + Real(kind=8) :: iron_chemistry + Real(kind=8) :: Fe, totalLigand, ligandStabConst ! Input + Real(kind=8) :: FreeFe ! Output + Real(kind=8) :: ligand,FeL,a,b,c,discrim + +! Abbrevations + a = 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 + freeFe = Fe - FeL + else ! No free iron + freeFe = 0.d0 + end if + + iron_chemistry = freeFe + + return + end + From 40431c5380a83ac4ff7a893b215f3115323e8157 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 11 Nov 2025 15:20:56 +0100 Subject: [PATCH 40/68] fix for tracer parallelisation in coupled setup --- src/fesom_module.F90 | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 72a349256..7ab5a585c 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -511,9 +511,22 @@ subroutine fesom_init(fesom_total_nsteps) call MPI_Barrier(f%MPI_COMM_FESOM_WORLD, f%MPIERR) if(num_fesom_groups > 1) then +! call MPI_Bcast(cpl_send, 1, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) +! call MPI_Bcast(cpl_recv, 1, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + + if(f%my_fesom_group > 0) then + ALLOCATE(cpl_send(nsend)) + ALLOCATE(cpl_recv(nrecv)) + end if + call MPI_Bcast(cpl_send, nsend, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) call MPI_Bcast(cpl_recv, nrecv, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) -! needed in SUBROUTINE net_rec_from_atm(action) + +! kh 10.11.25 it is assumed here that both nsend and nrecv are >= 1 +! call MPI_Bcast(cpl_send, len(cpl_send(1)) * nsend, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) +! call MPI_Bcast(cpl_recv, len(cpl_recv(1)) * nrecv, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + + ! needed in SUBROUTINE net_rec_from_atm(action) call MPI_Bcast(target_root, 1, MPI_INTEGER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) end if #endif @@ -1211,7 +1224,9 @@ subroutine fesom_finalize() if(f%fesom_did_mpi_init) call par_ex(f%partit%MPI_COMM_FESOM, f%partit%mype) ! finalize MPI before FESOM prints its stats block, otherwise there is sometimes output from other processes from an earlier time in the programm AFTER the starts block (with parastationMPI) #if defined(__recom) && defined(__usetp) +! kh 07.11.25 produce output currently for all groups if (f%my_fesom_group==0) then +! if (f%my_fesom_group==0 .or. .true.) then #endif if (f%mype==0) then From 53fc830664fe70da6f2540e09ae2611b44d57290 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 11 Nov 2025 21:21:22 +0100 Subject: [PATCH 41/68] correction in fesom_module.F90 to allocate nsend and nrecv for parallel groups --- src/fesom_module.F90 | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 7ab5a585c..92c122bd3 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -511,23 +511,20 @@ subroutine fesom_init(fesom_total_nsteps) call MPI_Barrier(f%MPI_COMM_FESOM_WORLD, f%MPIERR) if(num_fesom_groups > 1) then -! call MPI_Bcast(cpl_send, 1, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) -! call MPI_Bcast(cpl_recv, 1, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + call MPI_Bcast(nsend, 1, MPI_INTEGER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + call MPI_Bcast(nrecv, 1, MPI_INTEGER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) if(f%my_fesom_group > 0) then ALLOCATE(cpl_send(nsend)) ALLOCATE(cpl_recv(nrecv)) end if - call MPI_Bcast(cpl_send, nsend, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) - call MPI_Bcast(cpl_recv, nrecv, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) - ! kh 10.11.25 it is assumed here that both nsend and nrecv are >= 1 -! call MPI_Bcast(cpl_send, len(cpl_send(1)) * nsend, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) -! call MPI_Bcast(cpl_recv, len(cpl_recv(1)) * nrecv, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + call MPI_Bcast(cpl_send, len(cpl_send(1)) * nsend, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) + call MPI_Bcast(cpl_recv, len(cpl_recv(1)) * nrecv, MPI_CHARACTER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) - ! needed in SUBROUTINE net_rec_from_atm(action) - call MPI_Bcast(target_root, 1, MPI_INTEGER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) +! needed in SUBROUTINE net_rec_from_atm(action) + call MPI_Bcast(target_root, 1, MPI_INTEGER, 0, f%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, f%MPIerr) end if #endif @@ -1225,8 +1222,8 @@ subroutine fesom_finalize() #if defined(__recom) && defined(__usetp) ! kh 07.11.25 produce output currently for all groups - if (f%my_fesom_group==0) then ! if (f%my_fesom_group==0 .or. .true.) then + if (f%my_fesom_group==0) then #endif if (f%mype==0) then From b91404613cab86a126447eec859b2af5f443b6db Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 26 Nov 2025 13:07:25 +0100 Subject: [PATCH 42/68] set flag_debug to false --- config/bin_2p1z1d_tp/namelist.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/bin_2p1z1d_tp/namelist.config b/config/bin_2p1z1d_tp/namelist.config index c8d4aa31c..f7f888b23 100644 --- a/config/bin_2p1z1d_tp/namelist.config +++ b/config/bin_2p1z1d_tp/namelist.config @@ -58,7 +58,7 @@ use_cavity=.false. ! use_cavity_partial_cell=.false. use_floatice = .false. use_sw_pene=.true. -flag_debug=.true. +flag_debug=.false. use_transit=.false. num_fesom_groups = 2 / From 0a5cb63b133f49d1edb89f51c6965e4a87eb652d Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 26 Nov 2025 14:59:46 +0100 Subject: [PATCH 43/68] bugfix in io_resatart.F90 --- CMakeLists.txt | 2 +- src/io_restart.F90 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3fece347e..66ffe14d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set(OIFS_COUPLED OFF CACHE BOOL "compile fesom coupled to OpenIFS. (Also set(CRAY OFF CACHE BOOL "compile with cray ftn") set(USE_ICEPACK OFF CACHE BOOL "compile fesom with the Iceapck modules for sea ice column physics.") set(OPENMP_REPRODUCIBLE OFF CACHE BOOL "serialize OpenMP loops that are critical for reproducible results") -set(RECOM_COUPLED OFF CACHE BOOL "compile fesom including biogeochemistry, REcoM3") +set(RECOM_COUPLED ON CACHE BOOL "compile fesom including biogeochemistry, REcoM3") set(CISO_COUPLED OFF CACHE BOOL "compile ciso coupled to REcoM3. RECOM_COUPLED has to be active") set(USE_MULTIO OFF CACHE BOOL "Use MULTIO for IO, either grib or binary for now. This also means path to MULTIO installation has to provided using env MULTIO_INSTALL_PATH='..' and multio configuration yamls must be present to run the model with MULTIO") set(OASIS_WITH_YAC OFF CACHE BOOL "Useing a version of OASIS compiled with YAC instead of SCRIP for interpolation?") diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 2d01946fb..fc25eae02 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -642,7 +642,7 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn #endif call write_all_bin_restarts((/globalstep+istep, int(ctime), yearnew/), & write_bin_dirpath, & - write_bin_infopath, + write_bin_infopath, & partit, & mesh, & ice, & From c78a72abef6b1903ca8268c263bfe4d54c61a40e Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 26 Nov 2025 21:38:33 +0100 Subject: [PATCH 44/68] bugfix in io_restart.F90 after merge --- src/io_restart.F90 | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index fc25eae02..8c7399e08 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -450,8 +450,12 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn logical, save :: initialized_raw = .false. logical, save :: initialized_bin = .false. logical, save :: initialized_io = .false. - integer :: mpierr + character(:), allocatable :: write_raw_dirpath, write_raw_infopath + character(:), allocatable :: write_bin_dirpath, write_bin_infopath + character(:), allocatable :: write_oce_path, write_ice_path + character(:), allocatable :: write_icepack_path, write_bio_path + #if defined(__recom) && defined(__usetp) integer :: tr_arr_slice_count_fix_1 integer :: group_i @@ -468,15 +472,11 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn #include "associate_part_ass.h" #include "associate_mesh_ass.h" - num_tracers = tracers%num_tracers + num_tracers = tracers%num_tracers +#else + integer :: mpierr #endif - character(:), allocatable :: write_raw_dirpath, write_raw_infopath - character(:), allocatable :: write_bin_dirpath, write_bin_infopath - character(:), allocatable :: write_oce_path, write_ice_path - character(:), allocatable :: write_icepack_path, write_bio_path - - ! Build paths for reading using RestartInPath write_raw_dirpath = build_raw_restart_dirpath(RestartOutPath)//"/np"//int_to_txt(partit%npes) write_raw_infopath = build_raw_restart_infopath(RestartOutPath)//"/np"//int_to_txt(partit%npes)//".info" @@ -601,7 +601,7 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn call write_netcdf_restarts(write_icepack_path, icepack_files, istep) #else if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: ice'//achar(27)//'[0m' - call write_restart(write_ice_path, ice_files, istep) + call write_netcdf_restarts(write_ice_path, ice_files, istep) #endif #if defined(__recom) && defined(__usetp) endif !(partit%my_fesom_group == 0) then @@ -615,7 +615,7 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn if(partit%my_fesom_group == 0) then #endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: bio'//achar(27)//'[0m' - call write_netcdf_restarts(write_ice_path, ice_files, istep) + call write_netcdf_restarts(write_bio_path, ice_files, istep) #if defined(__usetp) endif #endif From 2dc882871ccd7306cec5f2f35cada817ac5cd6c5 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 28 Nov 2025 11:43:15 +0100 Subject: [PATCH 45/68] bugfix in bio_files in io_restart.F90 --- src/io_restart.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 8c7399e08..292d0801b 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -615,7 +615,7 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn if(partit%my_fesom_group == 0) then #endif if (partit%mype==RAW_RESTART_METADATA_RANK) print *, achar(27)//'[1;33m'//' --> write restarts to netcdf file: bio'//achar(27)//'[0m' - call write_netcdf_restarts(write_bio_path, ice_files, istep) + call write_netcdf_restarts(write_bio_path, bio_files, istep) #if defined(__usetp) endif #endif From 34e9e21d62095d108b5d69443ec8270aace11ec4 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Sat, 6 Dec 2025 21:38:51 +0100 Subject: [PATCH 46/68] fesom namelists updated in bin_2p1z1d_tp --- config/bin_2p1z1d_tp/namelist.config | 10 +- config/bin_2p1z1d_tp/namelist.forcing | 185 ++++++++++++++++++-------- config/bin_2p1z1d_tp/namelist.oce | 96 +++++++++---- config/bin_2p1z1d_tp/namelist.recom | 2 + 4 files changed, 209 insertions(+), 84 deletions(-) diff --git a/config/bin_2p1z1d_tp/namelist.config b/config/bin_2p1z1d_tp/namelist.config index f7f888b23..0297daa0e 100644 --- a/config/bin_2p1z1d_tp/namelist.config +++ b/config/bin_2p1z1d_tp/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='m' ! y, m, d, s +run_length=10 !62 !62 !62 !28 +run_length_unit='y' ! y, m, d, s / &clockinit ! the model starts at @@ -19,12 +19,12 @@ yearnew=1948 &paths MeshPath='/home/a/a270105/fesom_meshes/mesh_core2/' ClimateDataPath='/home/a/a270105/initial_files/pi_init/' -ResultPath='/work/bm1030/a270105/fesommpi-output/fesom-2.6-recom-tp/' +ResultPath='./' / &restart_log restart_length=1 ! --> do netcdf restart ( only required for d,h,s cases, y, m take 1) -restart_length_unit='m' !output period: y, d, h, s, off +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 @@ -65,7 +65,7 @@ num_fesom_groups = 2 &machine n_levels=2 -n_part= 12, 36 ! 432 number of partitions on each hierarchy level +n_part= 2, 128 ! 432 number of partitions on each hierarchy level / &icebergs diff --git a/config/bin_2p1z1d_tp/namelist.forcing b/config/bin_2p1z1d_tp/namelist.forcing index 10d706178..a74435acf 100644 --- a/config/bin_2p1z1d_tp/namelist.forcing +++ b/config/bin_2p1z1d_tp/namelist.forcing @@ -1,71 +1,144 @@ -! This is the namelist file for forcing +! ============================================================================ +! ============= Namelist file for FESOM2 atmospheric forcing ================ +! ============================================================================ +! This file contains configuration for atmospheric forcing and surface boundary +! conditions, including: +! - Bulk formulae exchange coefficients (heat, momentum, moisture) +! - Bulk formulae options and reference heights +! - Land ice freshwater forcing +! - Age tracer configuration +! - Surface forcing data files and variables +! - Runoff and salinity restoring +! - Chlorophyll data for shortwave penetration +! ============================================================================ +! ============================================================================ +! BULK FORMULAE EXCHANGE COEFFICIENTS +! ============================================================================ +! These coefficients control the turbulent exchange of heat, moisture, and +! momentum between the atmosphere and ocean/ice surfaces. +! ============================================================================ &forcing_exchange_coeff -Ce_atm_oce=1.75e-3 ! exchange coeff. of latent heat over open water -Ch_atm_oce=1.75e-3 ! exchange coeff. of sensible heat over open water -Cd_atm_oce=1.0e-3 ! drag coefficient between atmosphere and water -Ce_atm_ice=1.75e-3 ! exchange coeff. of latent heat over ice -Ch_atm_ice=1.75e-3 ! exchange coeff. of sensible heat over ice -Cd_atm_ice=1.2e-3 ! drag coefficient between atmosphere and ice -Swind =0.0 ! parameterization for coupled current feedback +Ce_atm_oce = 0.00175 ! exchange coefficient of latent heat over open water (dimensionless) +Ch_atm_oce = 0.00175 ! exchange coefficient of sensible heat over open water (dimensionless) +Cd_atm_oce = 0.001 ! drag coefficient between atmosphere and water (dimensionless) +Ce_atm_ice = 0.00175 ! exchange coefficient of latent heat over ice (dimensionless) +Ch_atm_ice = 0.00175 ! exchange coefficient of sensible heat over ice (dimensionless) +Cd_atm_ice = 0.0012 ! drag coefficient between atmosphere and ice (dimensionless) +Swind = 0.0 ! parameterization for coupled current feedback (0.0 = disabled) + ! non-zero values reduce wind stress based on ocean surface currents / +! ============================================================================ +! BULK FORMULAE OPTIONS +! ============================================================================ +! Configuration for bulk formulae calculations (turbulent fluxes). +! Reference heights must match the forcing data specifications. +! ============================================================================ &forcing_bulk -AOMIP_drag_coeff=.false. -ncar_bulk_formulae=.true. -ncar_bulk_z_wind=10.0 ! height at which wind forcing is located (CORE:10m, JRA:2m) -ncar_bulk_z_tair=10.0 ! height at which temp forcing is located (CORE:10m, JRA:2m) -ncar_bulk_z_shum=10.0 ! height at which humi forcing is located (CORE:10m, JRA:2m) - +AOMIP_drag_coeff = .false. ! use AOMIP drag coefficient formulation (false = use standard) +ncar_bulk_formulae = .true. ! use NCAR bulk formulae (Large & Yeager 2004, 2009) +ncar_bulk_z_wind = 10.0 ! reference height for wind forcing [m] + ! CORE2, JRA55-do: 10m; JRA55, NCEP: 2m +ncar_bulk_z_tair = 10.0 ! reference height for air temperature forcing [m] + ! CORE2, JRA55-do: 10m; JRA55, NCEP: 2m +ncar_bulk_z_shum = 10.0 ! reference height for specific humidity forcing [m] + ! CORE2, JRA55-do: 10m; JRA55, NCEP: 2m / +! ============================================================================ +! LAND ICE FRESHWATER FORCING +! ============================================================================ +! Configuration for freshwater input from land ice (glaciers, ice sheets). +! Requires use_landice_water=.true. in namelist.config to enable output. +! ============================================================================ &land_ice -use_landice_water=.false. -landice_start_mon=5 -landice_end_mon=10 +use_landice_water = .false. ! enable land ice freshwater forcing +landice_start_mon = 5 ! start month for land ice forcing (1-12) +landice_end_mon = 10 ! end month for land ice forcing (1-12) +fwf_path = '' ! path to land ice freshwater flux data files / +! ============================================================================ +! AGE TRACER CONFIGURATION +! ============================================================================ +! Configuration for passive age tracer (tracks water mass age). +! Requires use_age_tracer=.true. in namelist.config to enable output. +! ============================================================================ &age_tracer -use_age_tracer=.false. -use_age_mask=.false. -age_tracer_path='./mesh/' -age_start_year=2000 +use_age_tracer = .false. ! enable age tracer computation +use_age_mask = .false. ! use spatial mask for age tracer initialization +age_tracer_path = '' ! path to age tracer mask file (if use_age_mask=.true.) +age_start_year = 2000 ! year to start age tracer (tracer age = 0 at this year) / +! ============================================================================ +! SURFACE BOUNDARY CONDITION (FORCING DATA) +! ============================================================================ +! Specification of atmospheric forcing data files and variables. +! File paths are relative to the run directory. +! ============================================================================ &nam_sbc - nm_xwind_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/u_10.15JUNE2009' ! name of file with winds, if nm_sbc=2 - nm_ywind_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/v_10.15JUNE2009' ! name of file with winds, if nm_sbc=2 - nm_humi_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/q_10.15JUNE2009' ! name of file with humidity - nm_qsr_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/ncar_rad.15JUNE2009' ! name of file with solar heat - nm_qlw_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/ncar_rad.15JUNE2009' ! name of file with Long wave - nm_tair_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/t_10.15JUNE2009' ! name of file with 2m air temperature - nm_prec_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/ncar_precip.15JUNE2009' ! name of file with total precipitation - nm_snow_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/ncar_precip.15JUNE2009' ! name of file with snow precipitation - nm_mslp_file = '/home/a/a270105/fesom_standalone_forcing/CYNF_v2/slp.15JUNE2009' ! air_pressure_at_sea_level - nm_xwind_var = 'U_10_MOD' ! name of variable in file with wind - nm_ywind_var = 'V_10_MOD' ! name of variable in file with wind - nm_humi_var = 'Q_10_MOD' ! name of variable in file with humidity - nm_qsr_var = 'SWDN_MOD' ! name of variable in file with solar heat - nm_qlw_var = 'LWDN_MOD' ! name of variable in file with Long wave - nm_tair_var = 'T_10_MOD' ! name of variable in file with 2m air temperature - nm_prec_var = 'RAIN' ! name of variable in file with total precipitation - nm_snow_var = 'SNOW' ! name of variable in file with total precipitation - nm_mslp_var = 'SLP' ! name of variable in file with air_pressure_at_sea_level - nm_nc_iyear = 1948 - 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 = 1 ! 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. - nm_runoff_file ='/home/a/a270105/fesom_standalone_forcing/CYNF_v2/runoff.15JUNE2009.nc' - runoff_data_source ='CORE2' !Dai09, CORE2 - nm_sss_data_file ='/home/a/a270105/fesom_standalone_forcing/CYNF_v2/PHC2_salx.2004_08_03.nc' - sss_data_source ='CORE2' - 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 ='FORCING/Sweeney/Sweeney_2005.nc' - chl_const = 0.1 - use_runoff_mapper = .FALSE. - runoff_basins_file = 'FORCING/CORE2/runoff_maps_regular.nc' - runoff_radius = 500000. + ! --- Forcing file paths --- + nm_xwind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with zonal wind speeds + nm_ywind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with meridional wind speeds + nm_xstre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/huss.clim61' ! name of file with zonal wind stress + 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' + ! --- Variable names in netCDF forcing files --- + 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 + + ! --- Time axis configuration in forcing files --- + nm_nc_iyear = 1948 ! initial year of forcing data time axis + nm_nc_imm = 1 ! initial month of forcing data time axis (1-12) + nm_nc_idd = 1 ! initial day of forcing data time axis (1-31) + nm_nc_freq = 1 ! number of data points per day (1=daily, 4=6-hourly, etc.) + nm_nc_tmid = 0 ! time stamp position: 1=mid-point, 0=start of interval + y_perpetual = .true. ! use perpetual year forcing (repeat single year) + + ! --- Enable/disable individual forcing fields --- + l_xwind = .true. ! use zonal wind forcing + l_ywind = .true. ! use meridional wind forcing + l_humi = .true. ! use specific humidity forcing + l_qsr = .true. ! use shortwave radiation forcing + l_qlw = .true. ! use longwave radiation forcing + l_tair = .true. ! use air temperature forcing + l_prec = .true. ! use precipitation forcing + l_mslp = .true. ! use mean sea level pressure forcing + l_cloud = .false. ! use cloud cover forcing + l_snow = .true. ! use snow precipitation forcing + + ! --- Runoff configuration --- + runoff_data_source = 'CORE2' ! runoff data source: 'Dai09', 'JRA55, 'CORE2', or 'NONE' + nm_runoff_file = '/albedo/pool/FESOM/forcing/CORE2/runoff.nc' ! path to runoff data + + ! --- Sea surface salinity restoring --- + sss_data_source = 'CORE2' ! SSS restoring data source: 'CORE2', 'WOA', or 'NONE' + nm_sss_data_file = '/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' ! path to SSS restoring data file, e.g. PHC2_salx.nc + + ! --- Chlorophyll data for shortwave penetration --- + chl_data_source = 'Sweeney' ! chlorophyll data source: 'Sweeney' (monthly climatology) or 'None' (constant) + ! requires use_sw_pene=.true. in namelist.config + nm_chl_data_file = '/pool/data/AWICM/FESOM2/FORCING/Sweeney/Sweeney_2005.nc' ! chlorophyll data file (if Sweeney) + chl_const = 0.1 ! constant chlorophyll concentration [mg/m³] (if chl_data_source='None') + + ! --- Runoff mapper (distributes runoff over coastal area) --- + use_runoff_mapper = .false. ! enable runoff mapper (spreads runoff spatially) + runoff_basins_file = '' ! runoff basin mapping file + runoff_radius = 500000. ! radius for runoff spreading [m] (if use_runoff_mapper=.true.) / diff --git a/config/bin_2p1z1d_tp/namelist.oce b/config/bin_2p1z1d_tp/namelist.oce index 7af6867f7..c0dc986bd 100644 --- a/config/bin_2p1z1d_tp/namelist.oce +++ b/config/bin_2p1z1d_tp/namelist.oce @@ -1,26 +1,76 @@ -! The namelist file for the finite-volume ocean model +! ============================================================================ +! ============ Namelist file for FESOM2 ocean dynamics ====================== +! ============================================================================ +! This file contains configuration for ocean dynamics and parameterizations: +! - Bottom drag and vertical viscosity +! - Gent-McWilliams (GM) eddy parameterization +! - Redi isopycnal diffusion +! - Vertical mixing schemes (KPP, PP) +! - Convection parameters +! - Tidal forcing +! ============================================================================ +! ============================================================================ +! OCEAN DYNAMICS AND PARAMETERIZATIONS +! ============================================================================ &oce_dyn -C_d=0.0025 ! Bottom drag, nondimensional -A_ver= 1.e-4 ! Vertical viscosity, m^2/s -scale_area=5.8e9 ! Visc. and diffus. are for an element with scale_area -SPP=.false. ! Salt Plume Parameterization -Fer_GM=.true. ! to swith on/off GM after Ferrari et al. 2010 -K_GM_max = 2000.0 ! max. GM thickness diffusivity (m2/s) -K_GM_min = 2.0 ! max. GM thickness diffusivity (m2/s) -K_GM_bvref = 2 ! def of bvref in ferreira scaling 0=srf,1=bot mld,2=mean over mld,3=weighted mean over mld -K_GM_rampmax = -1.0 ! Resol >K_GM_rampmax[km] GM on -K_GM_rampmin = -1.0 ! Resol K_GM_rampmax[km] GM on +K_GM_rampmin = -1.0 ! Resol Date: Tue, 16 Dec 2025 11:55:33 +0100 Subject: [PATCH 47/68] namelists updated for 2.7 --- config/bin_2p1z1d_tp/namelist.config | 147 +++++++--- config/bin_2p1z1d_tp/namelist.config.old | 77 +++++ config/bin_2p1z1d_tp/namelist.dyn | 96 +++++-- config/bin_2p1z1d_tp/namelist.forcing | 2 +- config/bin_2p1z1d_tp/namelist.ice | 128 ++++++--- config/bin_2p1z1d_tp/namelist.io.recom | 344 ++++++++++++++++++++++- config/bin_2p1z1d_tp/namelist.tra | 142 +++++++--- config/bin_2p1z1d_tp/namelist.transit | 53 ++++ 8 files changed, 837 insertions(+), 152 deletions(-) create mode 100644 config/bin_2p1z1d_tp/namelist.config.old mode change 120000 => 100644 config/bin_2p1z1d_tp/namelist.io.recom create mode 100644 config/bin_2p1z1d_tp/namelist.transit diff --git a/config/bin_2p1z1d_tp/namelist.config b/config/bin_2p1z1d_tp/namelist.config index 0297daa0e..408c6d241 100644 --- a/config/bin_2p1z1d_tp/namelist.config +++ b/config/bin_2p1z1d_tp/namelist.config @@ -1,77 +1,134 @@ -! This is the namelist file for model general configuration +! ============================================================================ +! ============ Namelist file for FESOM2 general configuration ================ +! ============================================================================ +! This file contains the main configuration parameters for FESOM2, including: +! - Model identification and run settings +! - Time stepping and simulation duration +! - Initial time/date settings +! - File paths for mesh, forcing, and output +! - Restart and logging configuration +! - Vertical coordinate system (ALE) +! - Grid geometry and rotation +! - Calendar settings +! - Model components (ice, cavities, etc.) +! - Parallel decomposition +! - Iceberg settings +! ============================================================================ +! ============================================================================ +! RUN IDENTIFICATION +! ============================================================================ &modelname -runid='fesom' +runid = 'fesom' ! run identifier (used in output filenames) / +! ============================================================================ +! TIME STEPPING AND RUN LENGTH +! ============================================================================ ×tep -step_per_day=32 !96 !96 !72 !72 !45 !72 !96 -run_length=10 !62 !62 !62 !28 -run_length_unit='y' ! y, m, d, s +step_per_day = 48 ! number of time steps per day (determines dt = 86400/step_per_day seconds) + ! common values: 32 (45min), 48 (30min), 72 (20min), 96 (15min), 192 (7min 30sec), + ! 216 (6min 40sec), 240 (6min), 288 (5min), 360 (4min), 720 (2min), 1440 (1min), 2880 (30sec) +run_length = 1 ! total length of simulation run +run_length_unit = 'y' ! unit for run_length: 'y' (years), 'm' (months), 'd' (days), 's' (steps) / -&clockinit ! the model starts at -timenew=0.0 -daynew=1 -yearnew=1948 +! ============================================================================ +! INITIAL TIME/DATE SETTINGS +! ============================================================================ +&clockinit +timenew = 0.0 ! initial time within the day [seconds] (0.0 = midnight) +daynew = 1 ! initial day of the month (1-31) +yearnew = 2000 ! initial year / +! ============================================================================ +! MESH, INITIALIZATION & OUTPUT PATHS +! ============================================================================ &paths -MeshPath='/home/a/a270105/fesom_meshes/mesh_core2/' -ClimateDataPath='/home/a/a270105/initial_files/pi_init/' -ResultPath='./' +MeshPath = '/pool/data/AWICM/FESOM2/MESHES_FESOM2.1/core2/' ! path to mesh files (nod2d.out, elem2d.out, etc.) +ClimateDataPath = '/pool/data/AWICM/FESOM2/INITIAL/phc3.0/' ! path to initial conditions (temperature, salinity) +ResultPath = './' ! path for output files and fesom.clock file / +! ============================================================================ +! RESTART AND LOGGING CONFIGURATION +! ============================================================================ &restart_log -restart_length=1 ! --> do netcdf restart ( only required for d,h,s cases, y, m take 1) -restart_length_unit='y' !output period: y, d, h, s, off -raw_restart_length=1 ! --> do core dump restart -raw_restart_length_unit='off' ! e.g. y, d, h, s, off -bin_restart_length=1 ! --> do derived type binary restart -bin_restart_length_unit='off' ! e.g. y, d, h, s, off -logfile_outfreq=1 !in logfile info. output frequency, # steps +restart_length = 1 ! frequency for netCDF restart files (required for d,h,s; y,m use 1) +restart_length_unit = 'y' ! unit: 'y' (years), 'm' (months), 'd' (days), 'h' (hours), 's' (steps), 'off' (disabled) +raw_restart_length = 1 ! frequency for raw core dump restart files +raw_restart_length_unit = 'off' ! unit: 'y', 'm', 'd', 'h', 's', 'off' +bin_restart_length = 1 ! frequency for binary derived type restart files +bin_restart_length_unit = 'off' ! unit: 'y', 'm', 'd', 'h', 's', 'off' +logfile_outfreq = 960 ! log file output frequency [number of time steps] / +! ============================================================================ +! VERTICAL COORDINATE SYSTEM (ALE - Arbitrary Lagrangian-Eulerian) +! ============================================================================ &ale_def -which_ALE='zstar' ! 'linfs','zlevel', 'zstar' -use_partial_cell=.true. +which_ALE = 'zstar' ! vertical coordinate type: + ! 'linfs' = linear free surface + ! 'zlevel' = z-level (fixed depth levels) + ! 'zstar' = z-star (terrain-following with SSH scaling) +use_partial_cell = .false. ! use partial bottom cells for better topography representation (not recommended) / +! ============================================================================ +! GRID GEOMETRY AND ROTATION +! ============================================================================ &geometry -cartesian=.false. -fplane=.false. -cyclic_length=360 ![degree] -rotated_grid=.true. !option only valid for coupled model case now -force_rotation=.true. -alphaEuler=50. ![degree] Euler angles, convention: -betaEuler=15. ![degree] first around z, then around new x, -gammaEuler=-90. ![degree] then around new z. +cartesian = .false. ! use Cartesian coordinates (false = spherical Earth) +fplane = .false. ! use f-plane approximation (constant Coriolis parameter) +cyclic_length = 360 ! length of cyclic domain [degrees] (360 = global) +rotated_grid = .true. ! use rotated grid (typically for coupled models to avoid pole singularity) +force_rotation = .true. ! force grid rotation even if not coupled +alphaEuler = 50. ! first Euler angle (rotation around z-axis) [degrees] +betaEuler = 15. ! second Euler angle (rotation around new x-axis) [degrees] +gammaEuler = -90. ! third Euler angle (rotation around new z-axis) [degrees] + ! Euler angle convention: rotate first around z, then around new x, then around new z / +! ============================================================================ +! CALENDAR SETTINGS +! ============================================================================ &calendar -include_fleapyear=.false. +include_fleapyear = .true. ! include leap years in calendar (false = 365-day year, true = 365/366-day year) / +! ============================================================================ +! MODEL COMPONENTS AND FEATURES +! ============================================================================ &run_config -use_ice=.true. ! ocean+ice -use_cavity=.false. ! -use_cavity_partial_cell=.false. -use_floatice = .false. -use_sw_pene=.true. -flag_debug=.false. -use_transit=.false. -num_fesom_groups = 2 +use_ice = .true. ! enable sea ice model +use_cavity = .false. ! enable ice shelf cavities +use_cavity_partial_cell = .false. ! use partial cells in ice shelf cavities (not recommended) +use_floatice = .false. ! enable floating ice (icebergs) +use_sw_pene = .true. ! enable shortwave radiation penetration into ocean +flag_debug = .false. ! enable debug output (verbose logging) +use_transit = .false. ! enable transient tracer module (CFCs, SF6, etc.) +num_fesom_groups = 1 / +! ============================================================================ +! PARALLEL DECOMPOSITION (DOMAIN PARTITIONING) +! ============================================================================ &machine -n_levels=2 -n_part= 2, 128 ! 432 number of partitions on each hierarchy level +n_levels = 2 ! number of hierarchy levels for domain decomposition +n_part = 2, 128 ! number of partitions at each level (total CPUs = product of n_part) + ! example: 2 x 128 = 256 MPI tasks + ! adjust based on mesh size and available compute resources + ! maximum scaling reached at ~300 FESOM2 2D nodes per CPU (see first line in nod2d.out for number of 2D nodes) / +! ============================================================================ +! ICEBERG SETTINGS +! ============================================================================ &icebergs -use_icesheet_coupling=.false. -ib_num=1 -use_icebergs=.false. -steps_per_ib_step=8 -ib_async_mode=0 +use_icesheet_coupling = .false. ! enable ice sheet model +ib_num = 1 ! number of iceberg classes +use_icebergs = .false. ! enable iceberg module +steps_per_ib_step = 8 ! ocean time steps per iceberg time step (iceberg subcycling) +ib_async_mode = 0 ! iceberg asynchronous mode (0=synchronous, 1=asynchronous) / diff --git a/config/bin_2p1z1d_tp/namelist.config.old b/config/bin_2p1z1d_tp/namelist.config.old new file mode 100644 index 000000000..0297daa0e --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.config.old @@ -0,0 +1,77 @@ +! 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=10 !62 !62 !62 !28 +run_length_unit='y' ! y, m, d, s +/ + +&clockinit ! the model starts at +timenew=0.0 +daynew=1 +yearnew=1948 +/ + +&paths +MeshPath='/home/a/a270105/fesom_meshes/mesh_core2/' +ClimateDataPath='/home/a/a270105/initial_files/pi_init/' +ResultPath='./' +/ + +&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=1 !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. +num_fesom_groups = 2 +/ + +&machine +n_levels=2 +n_part= 2, 128 ! 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_tp/namelist.dyn b/config/bin_2p1z1d_tp/namelist.dyn index 545a7fe67..e670102bb 100644 --- a/config/bin_2p1z1d_tp/namelist.dyn +++ b/config/bin_2p1z1d_tp/namelist.dyn @@ -1,36 +1,72 @@ +! ============================================================================ +! ========== Namelist file for FESOM2 momentum dynamics ====================== +! ============================================================================ +! This file contains configuration for momentum equations and dynamics: +! - Horizontal viscosity schemes and parameters +! - Momentum advection options +! - Free-slip vs no-slip boundary conditions +! - Vertical velocity splitting +! - Split-explicit barotropic subcycling +! - Energy diagnostics +! ============================================================================ + +! ============================================================================ +! HORIZONTAL VISCOSITY +! ============================================================================ &dynamics_visc -visc_gamma0 = 0.003 ! [m/s], backgroung viscosity= gamma0*len, it should be as small a s possible (keep it < 0.01 m/s). -visc_gamma1 = 0.1 ! [nodim], for computation of the flow aware viscosity -visc_gamma2 = 0.285 ! [s/m], is only used in easy backscatter option -visc_easybsreturn= 1.5 - -opt_visc = 5 -check_opt_visc=.true. ! check if optvisc=5 is valid based on ratio resol/rossbyR -! 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. +! --- Viscosity Coefficients --- +visc_gamma0 = 0.003 ! background viscosity coefficient [m/s] + ! viscosity = gamma0 × element_length + ! keep < 0.01 m/s for numerical stability +visc_gamma1 = 0.1 ! flow-aware viscosity coefficient [dimensionless] +visc_gamma2 = 0.285 ! additional viscosity coefficient [s/m] + ! only used for easy backscatter (opt_visc=5) and dynamic backscatter (opt_visc=8) +visc_easybsreturn = 1.5 ! energy return parameter for easy backscatter [dimensionless] + +! --- Viscosity Scheme Selection --- +opt_visc = 5 ! horizontal viscosity scheme: + ! 5 = Kinematic (easy) Backscatter + ! 6 = Biharmonic flow-aware (depends on velocity Laplacian) + ! 7 = Biharmonic flow-aware (depends on velocity differences) + ! 8 = Dynamic Backscatter +check_opt_visc = .true. ! check if opt_visc=5 is valid based on resolution/Rossby radius ratio + +! --- Vertical Viscosity --- +use_ivertvisc = .true. ! use implicit vertical viscosity (recommended for stability) / +! ============================================================================ +! GENERAL DYNAMICS SETTINGS +! ============================================================================ &dynamics_general -momadv_opt = 2 ! option for momentum advection in moment only =2 -use_freeslip = .false. ! Switch on free slip -use_wsplit = .false. ! Switch for implicite/explicte splitting of vert. velocity -wsplit_maxcfl= 1.0 ! maximum allowed CFL criteria in vertical (0.5 < w_max_cfl < 1.) - ! in older FESOM it used to be w_exp_max=1.e-3 -ldiag_KE=.false. ! activates energy diagnostics -AB_order=2 - -use_ssh_se_subcycl = .false. -se_BTsteps = 50 -se_BTtheta = 0.14 ! default: 0.14, -se_bottdrag = .true. -se_bdrag_si = .true. ! bottomdrag semi-implicite/explicite -se_visc = .true. -se_visc_gamma0 = 10 -se_visc_gamma1 = 19500 !19500 (core2@32spd), 2750 (core2@72spd) -se_visc_gamma2 = 0 +! --- Momentum Advection --- +momadv_opt = 2 ! momentum advection option (only 2 is currently supported) + +! --- Boundary Conditions --- +use_freeslip = .false. ! enable free-slip lateral boundary conditions (false = no-slip) + +! --- Vertical Velocity Splitting --- +use_wsplit = .false. ! enable implicit/explicit splitting of vertical velocity +wsplit_maxcfl = 1.0 ! maximum allowed vertical CFL criterion (range: 0.5-1.0) + ! in older FESOM versions this was w_exp_max=1.e-3 + +! --- Energy Diagnostics --- +ldiag_KE = .false. ! enable kinetic energy diagnostics (requires additional computation) + +! --- Time Stepping --- +AB_order = 2 ! Adams-Bashforth time stepping order (2 or 3) + +! --- Split-Explicit Barotropic Subcycling --- +use_ssh_se_subcycl = .false. ! enable split-explicit subcycling for barotropic mode + ! (faster time stepping for sea surface height) +se_BTsteps = 50 ! number of barotropic subcycles per baroclinic time step +se_BTtheta = 0.14 ! implicitness parameter for barotropic solver (0-1, default: 0.14) +se_bottdrag = .true. ! include bottom drag in barotropic subcycling +se_bdrag_si = .true. ! use semi-implicit bottom drag (true) or explicit (false) +se_visc = .true. ! include viscosity in barotropic subcycling +se_visc_gamma0 = 10 ! background viscosity for barotropic mode [dimensionless] +se_visc_gamma1 = 19500 ! flow-aware viscosity for barotropic mode [dimensionless] + ! typical values: 19500 (CORE2@32spd), 2750 (CORE2@72spd) +se_visc_gamma2 = 0 ! additional viscosity for barotropic mode [dimensionless] / diff --git a/config/bin_2p1z1d_tp/namelist.forcing b/config/bin_2p1z1d_tp/namelist.forcing index a74435acf..44cdf3b74 100644 --- a/config/bin_2p1z1d_tp/namelist.forcing +++ b/config/bin_2p1z1d_tp/namelist.forcing @@ -109,7 +109,7 @@ age_start_year = 2000 ! year to start age tracer (tracer age = 0 at this nm_nc_idd = 1 ! initial day of forcing data time axis (1-31) nm_nc_freq = 1 ! number of data points per day (1=daily, 4=6-hourly, etc.) nm_nc_tmid = 0 ! time stamp position: 1=mid-point, 0=start of interval - y_perpetual = .true. ! use perpetual year forcing (repeat single year) + y_perpetual = .false. ! use perpetual year forcing (repeat single year) ! --- Enable/disable individual forcing fields --- l_xwind = .true. ! use zonal wind forcing diff --git a/config/bin_2p1z1d_tp/namelist.ice b/config/bin_2p1z1d_tp/namelist.ice index bf7ea69bd..8b29ce4bf 100644 --- a/config/bin_2p1z1d_tp/namelist.ice +++ b/config/bin_2p1z1d_tp/namelist.ice @@ -1,40 +1,98 @@ -! Ice namelist +! ============================================================================ +! ============== Namelist file for FESOM2 sea ice model ===================== +! ============================================================================ +! This file contains configuration for sea ice dynamics and thermodynamics: +! - EVP (Elastic-Viscous-Plastic) rheology options +! - Ice strength and deformation parameters +! - Ocean-ice drag +! - Ice thermodynamics and thickness distribution +! - Albedo parameterizations +! ============================================================================ + +! ============================================================================ +! SEA ICE DYNAMICS +! ============================================================================ &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 +! --- EVP Rheology Options --- +whichEVP = 0 ! EVP solver type: + ! 0 = standard EVP + ! 1 = modified EVP (mEVP) + ! 2 = adaptive EVP (aEVP) + +! --- Ice Strength Parameters --- +Pstar = 30000.0 ! ice strength parameter [N/m²] (typical: 20000-30000) +ellipse = 2.0 ! aspect ratio of yield curve ellipse (dimensionless) +c_pressure = 20.0 ! ice concentration parameter for strength computation (dimensionless) + +! --- Ice Deformation --- +delta_min = 1.0e-11 ! minimum strain rate for viscosity regularization [s⁻¹] + +! --- EVP Subcycling --- +evp_rheol_steps = 120 ! number of EVP subcycles per ice time step + +! --- mEVP Stability Parameters (for whichEVP=1) --- +alpha_evp = 250 ! mEVP stability constant (adjust with resolution) +beta_evp = 250 ! mEVP stability constant (adjust with resolution) + +! --- aEVP Tuning (for whichEVP=2) --- +c_aevp = 0.15 ! aEVP tuning constant (adjust with resolution) + +! --- Ocean-Ice Coupling --- +Cd_oce_ice = 0.0055 ! drag coefficient between ocean and ice (dimensionless, typical: 0.0055) + +! --- Numerical Stabilization --- +ice_gamma_fct = 0.5 ! smoothing parameter for ice dynamics (0.0-1.0) +ice_diff = 0.0 ! artificial diffusion for numerical stability [m²/s] +theta_io = 0.0 ! rotation angle for ice-ocean stress [degrees] + +! --- Time Stepping --- +ice_ave_steps = 1 ! ice time step = ice_ave_steps × ocean time step / +! ============================================================================ +! SEA ICE THERMODYNAMICS +! ============================================================================ &ice_therm -Sice=4.0 ! Ice salinity 3.2--5.0 ppt. -iclasses=7 ! default = 7; in case of EM distribution ('new_iceclasses=.true.') must be set to 15 -h0=0.5 ! Lead closing parameter for Nothern Hemisphere [m], default 0.5 -h0_s=0.5 ! Lead closing parameter [m] for Southern Hemisphere, default 0.5 -hmin=0.01 ! default=0.01 -armin=0.01 ! default=0.01 -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 -snowdist=.true. ! distribution of snow depth according to ice distribution - default: .true. -new_iclasses=.false. ! default=.false.; ice thickness distribution based on EM observations (Castro-Morales et al., JGR, 2013) -open_water_albedo=0 ! 0=default; 1=taylor; 2=briegleb -c_melt=0.5 ! constant in concentration equation for melting conditions - default=0.5 -h_cutoff=3.0 ! only used for new_iclasses=.true. +! --- Ice Properties --- +Sice = 4.0 ! bulk ice salinity [ppt] (typical range: 3.2-5.0) + +! --- Ice Thickness Distribution --- +iclasses = 7 ! number of ice thickness categories (default: 7) + ! set to 15 if using EM distribution (new_iceclasses=.true.) +new_iclasses = .false. ! use ice thickness distribution from EM observations + ! (Castro-Morales et al., JGR, 2013) +h_cutoff = 3.0 ! thickness cutoff for new_iclasses [m] + +! --- Lead Closing Parameters --- +h0 = 0.5 ! lead closing parameter for Northern Hemisphere [m] +h0_s = 0.5 ! lead closing parameter for Southern Hemisphere [m] + +! --- Minimum Thresholds --- +hmin = 0.01 ! minimum ice thickness [m] +armin = 0.01 ! minimum ice concentration (dimensionless) + +! --- Emissivity (Longwave Radiation) --- +emiss_ice = 0.97 ! emissivity of snow/ice surface (dimensionless, 0-1) +emiss_wat = 0.97 ! emissivity of open water (dimensionless, 0-1) + +! --- Albedo (Shortwave Radiation) --- +albsn = 0.81 ! albedo of frozen snow (dimensionless, 0-1) +albsnm = 0.77 ! albedo of melting snow (dimensionless, 0-1) +albi = 0.7 ! albedo of frozen ice (dimensionless, 0-1) +albim = 0.68 ! albedo of melting ice (dimensionless, 0-1) +albw = 0.1 ! albedo of open water (dimensionless, 0-1) +open_water_albedo = 0 ! open water albedo scheme: + ! 0 = default (constant albw) + ! 1 = Taylor et al. + ! 2 = Briegleb et al. + +! --- Thermal Conductivity --- +con = 2.1656 ! thermal conductivity of ice [W/m/K] +consn = 0.31 ! thermal conductivity of snow [W/m/K] + +! --- Snow Distribution --- +snowdist = .true. ! distribute snow depth according to ice thickness distribution + +! --- Melting Parameters --- +c_melt = 0.5 ! constant in concentration equation for melting conditions (0-1) / diff --git a/config/bin_2p1z1d_tp/namelist.io.recom b/config/bin_2p1z1d_tp/namelist.io.recom deleted file mode 120000 index 11d3279b6..000000000 --- a/config/bin_2p1z1d_tp/namelist.io.recom +++ /dev/null @@ -1 +0,0 @@ -namelist.io \ No newline at end of file diff --git a/config/bin_2p1z1d_tp/namelist.io.recom b/config/bin_2p1z1d_tp/namelist.io.recom new file mode 100644 index 000000000..2f68c6701 --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.io.recom @@ -0,0 +1,343 @@ +! ============================================================================ +! ============ Namelist file for FESOM2 output configuration ================= +! ============================================================================ +! This file contains configuration for model output and diagnostics: +! - Diagnostic flags for optional output fields +! - General output settings (compression, rotation) +! - Output variable list with frequency and precision +! - Complete catalog of all available output fields +! +! See the output catalog at the end of this file for all possible variables. +! Some outputs require specific flags in &diag_list or other namelists. +! ============================================================================ + +! ============================================================================ +! DIAGNOSTIC FLAGS +! ============================================================================ +! Enable/disable optional diagnostic computations and outputs. +! Setting these to .true. enables additional output fields (see catalog below). +! ============================================================================ +&diag_list +ldiag_solver = .false. ! enables solver diagnostics (convergence, iterations) +lcurt_stress_surf = .false. ! enables 'curl_surf' output (vorticity of surface stress) +ldiag_curl_vel3 = .false. ! enables 'curl_u' output (relative vorticity from 3D velocity) +ldiag_Ri = .false. ! enables Richardson number diagnostics ('shear', 'Ri') +ldiag_turbflux = .false. ! enables turbulent flux diagnostics ('KvdTdz', 'KvdSdz') +ldiag_salt3D = .false. ! enables 3D salinity diagnostics +ldiag_dMOC = .false. ! enables 'dMOC' output (density MOC diagnostics) +ldiag_DVD = .false. ! enables 'DVD' output (Discrete Variance Decay diagnostics) +ldiag_forc = .false. ! enables 'FORC' output (comprehensive forcing diagnostics) +ldiag_extflds = .false. ! enables extended field diagnostics +ldiag_destine = .false. ! enables heat content computation ('hc300m', 'hc700m', 'hc') +ldiag_trflx = .false. ! enables tracer flux diagnostics ('utemp', 'vtemp', 'usalt', 'vsalt') +ldiag_uvw_sqr = .false. ! enables 'UVW_SQR' output (squared velocities: u2, v2, w2) +ldiag_trgrd_xyz = .false. ! enables 'TRGRD_XYZ' output (horizontal & vertical tracer gradients) +/ + +! ============================================================================ +! GENERAL OUTPUT SETTINGS +! ============================================================================ +&nml_general +io_listsize = 120 ! total number of streams to allocate. Shall be larger or equal to the number of streams in &nml_list (max. 150) +vec_autorotate = .false. ! unrotate vector fields (velocities, winds) before writing to output files +compression_level = 1 ! compression level for netCDF output (1=fastest, 9=smallest) +/ + +! ============================================================================ +! OUTPUT VARIABLE LIST +! ============================================================================ +! Format: 'variable_id', frequency, unit, precision +! frequency = output frequency (integer) +! unit = 'y' (yearly), 'm' (monthly), 'd' (daily), 'h' (hourly), 's' (steps) +! precision = 4 (single precision) or 8 (double precision) +! ============================================================================ +&nml_list +io_list = 'sst ',1, 'm', 4, + 'sss ',1, 'm', 4, +! 'ssh ',1, 'm', 4, +! '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, +! 'N2 ',1, 'm', 4, +! 'Kv ',1, 'm', 4, + 'u ',1, 'm', 4, + 'v ',1, 'm', 4, +! 'unod ',1, 'm', 4, +! 'vnod ',1, 'm', 4, + 'w ',1, 'm', 4, +! 'Av ',1, 'm', 4, + 'bolus_u ',1, 'm', 4, + 'bolus_v ',1, 'm', 4, + 'bolus_w ',1, 'm', 4, +! 'fw ',1, 'm', 4, +! 'fh ',1, 'm', 4, + 'otracers ',1, 'm', 4, +/ + +! ============================================================================ +! COMPLETE CATALOG OF ALL POSSIBLE OUTPUT FIELDS +! ============================================================================ +! Below is a comprehensive list of all valid io_list IDs available in FESOM2. +! To enable any field, copy the line to the &nml_list section above. +! NOTE: Some fields require specific flags to be enabled (see comments). +! ============================================================================ + +! --- 2D OCEAN SURFACE FIELDS --- +! 'sst ',1, 'm', 4, ! sea surface temperature [C] +! 'sss ',1, 'm', 4, ! sea surface salinity [psu] +! 'ssh ',1, 'm', 4, ! sea surface elevation [m] +! 'vve_5 ',1, 'm', 4, ! vertical velocity at 5th level [m/s] +! 't_star ',1, 'm', 4, ! air temperature [C] +! 'qsr ',1, 'm', 4, ! solar radiation [W/s^2] + +! --- 3D OCEAN FIELDS --- +! 'temp ',1, 'm', 4, ! temperature [C] +! 'salt ',1, 'm', 8, ! salinity [psu] +! 'sigma0 ',1, 'm', 4, ! potential density [kg/m3] +! 'u ',1, 'm', 4, ! zonal velocity [m/s] +! 'v ',1, 'm', 4, ! meridional velocity [m/s] +! 'unod ',1, 'm', 4, ! zonal velocity at nodes [m/s] +! 'vnod ',1, 'm', 4, ! meridional velocity at nodes [m/s] +! 'w ',1, 'm', 4, ! vertical velocity [m/s] +! 'otracers ',1, 'm', 4, ! all other tracers if applicable +! 'age ',1, 'm', 4, ! water age tracer [year] (require use_age_tracer=.true.) + +! --- 2D SSH DIAGNOSTIC VARIABLES --- +! 'ssh_rhs ',1, 'm', 4, ! ssh rhs [m/s] +! 'ssh_rhs_old',1, 'm', 4, ! ssh rhs old [m/s] +! 'd_eta ',1, 'm', 4, ! dssh from solver [m] +! 'hbar ',1, 'm', 4, ! ssh n+0.5 tstep [m] +! 'hbar_old ',1, 'm', 4, ! ssh n-0.5 tstep [m] +! 'dhe ',1, 'm', 4, ! dhbar @ elem [m] + +! --- SEA ICE FIELDS (require use_ice=.true.) --- +! 'uice ',1, 'm', 4, ! ice velocity x [m/s] +! 'vice ',1, 'm', 4, ! ice velocity y [m/s] +! 'a_ice ',1, 'm', 4, ! ice concentration [%] +! 'm_ice ',1, 'm', 4, ! ice height per unit area [m] +! 'thdgrice ',1, 'm', 4, ! thermodynamic growth rate ice [m/s] +! 'thdgrarea ',1, 'm', 4, ! thermodynamic growth rate ice concentration [frac/s] +! 'dyngrarea' ,1, 'm', 4, ! dynamic growth rate ice concentration [frac/s] +! 'dyngrice ',1, 'm', 4, ! dynamic growth rate ice [m/s] +! 'thdgrsn ',1, 'm', 4, ! thermodynamic growth rate snow [m/s] +! 'dyngrsnw ',1, 'm', 4, ! dynamic growth rate snow [m/s] +! 'flice ',1, 'm', 4, ! flooding growth rate ice [m/s] +! 'm_snow ',1, 'm', 4, ! snow height per unit area [m] +! 'h_ice ',1, 'm', 4, ! ice thickness over ice-covered fraction [m] +! 'h_snow ',1, 'm', 4, ! snow thickness over ice-covered fraction [m] +! 'fw_ice ',1, 'm', 4, ! fresh water flux from ice ['m/s'] +! 'fw_snw ',1, 'm', 4, ! fresh water flux from snow ['m/s'] + +! --- SEA ICE DEBUG VARIABLES (require use_ice=.true.) --- +! 'strength_ice',1, 'm', 4, ! ice strength [?] +! 'inv_areamass',1, 'm', 4, ! inv_areamass [?] +! 'rhs_a ',1, 'm', 4, ! rhs_a [?] +! 'rhs_m ',1, 'm', 4, ! rhs_m [?] +! 'sgm11 ',1, 'm', 4, ! sgm11 [?] +! 'sgm12 ',1, 'm', 4, ! sgm12 [?] +! 'sgm22 ',1, 'm', 4, ! sgm22 [?] +! 'eps11 ',1, 'm', 4, ! eps11 [?] +! 'eps12 ',1, 'm', 4, ! eps12 [?] +! 'eps22 ',1, 'm', 4, ! eps22 [?] +! 'u_rhs_ice ',1, 'm', 4, ! u_rhs_ice [?] +! 'v_rhs_ice ',1, 'm', 4, ! v_rhs_ice [?] +! 'metric_fac',1, 'm', 4, ! metric_fac [?] +! 'elevat_ice',1, 'm', 4, ! elevat_ice [?] +! 'uwice ',1, 'm', 4, ! uwice [?] +! 'vwice ',1, 'm', 4, ! vwice [?] +! 'twice ',1, 'm', 4, ! twice [?] +! 'swice ',1, 'm', 4, ! swice [?] + +! --- MIXED LAYER DEPTH --- +! 'MLD1 ',1, 'm', 4, ! Mixed Layer Depth [m] Large et al. 1997, bvfreq(nz, node) > db_max +! 'MLD2 ',1, 'm', 4, ! Mixed Layer Depth [m] Levitus treshold, rhopot(nz)-rhopot(1) > 0.125_WP kg/m +! 'MLD3 ',1, 'm', 4, ! Mixed Layer Depth [m] Griffies 2016 , rhopot(nz)-rhopot(1) > 0.03_WP kg/m + +! --- HEAT CONTENT (require ldiag_destine=.true.) --- +! 'hc300m ',1, 'm', 4, ! Vertically integrated heat content upper 300m [J m**-2] +! 'hc700m ',1, 'm', 4, ! Vertically integrated heat content upper 700m [J m**-2] +! 'hc ',1, 'm', 4, ! Vertically integrated heat content total column [J m**-2] + +! --- WATER ISOTOPES IN SEA ICE (require lwiso=.true.) --- +! 'h2o18_ice ',1, 'm', 4, ! h2o18 concentration in sea ice [kmol/m**3] +! 'hDo16_ice ',1, 'm', 4, ! hDo16 concentration in sea ice [kmol/m**3] +! 'h2o16_ice ',1, 'm', 4, ! h2o16 concentration in sea ice [kmol/m**3] + +! --- FRESHWATER FLUX (require use_landice_water=.true.) --- +! 'landice ',1, 'm', 4, ! freshwater flux [m/s] + +! --- SURFACE FORCING --- +! 'tx_sur ',1, 'm', 4, ! zonal wind str. to ocean [N/m2] +! 'ty_sur ',1, 'm', 4, ! meridional wind str. to ocean [N/m2] +! 'curl_surf ',1, 'm', 4, ! vorticity of the surface stress [none] (require lcurt_stress_surf=.true.) +! 'fh ',1, 'm', 4, ! heat flux [W/m2] +! 'fw ',1, 'm', 4, ! fresh water flux [m/s] +! 'atmice_x ',1, 'm', 4, ! stress atmice x [N/m2] +! 'atmice_y ',1, 'm', 4, ! stress atmice y [N/m2] +! 'atmoce_x ',1, 'm', 4, ! stress atmoce x [N/m2] +! 'atmoce_y ',1, 'm', 4, ! stress atmoce y [N/m2] +! 'iceoce_x ',1, 'm', 4, ! stress iceoce x [N/m2] +! 'iceoce_y ',1, 'm', 4, ! stress iceoce y [N/m2] +! 'alpha ',1, 'm', 4, ! thermal expansion [none] +! 'beta ',1, 'm', 4, ! saline contraction [none] +! 'dens_flux ',1, 'm', 4, ! density flux [kg/(m3*s)] +! 'runoff ',1, 'm', 4, ! river runoff [m/s] +! 'evap ',1, 'm', 4, ! evaporation [m/s] +! 'prec ',1, 'm', 4, ! precipitation rain [m/s] +! 'snow ',1, 'm', 4, ! precipitation snow [m/s] +! 'tair ',1, 'm', 4, ! surface air temperature [°C] +! 'shum ',1, 'm', 4, ! specific humidity [] +! 'swr ',1, 'm', 4, ! short wave radiation [W/m^2] +! 'lwr ',1, 'm', 4, ! long wave radiation [W/m^2] +! 'uwind ',1, 'm', 4, ! 10m zonal surface wind velocity [m/s] +! 'vwind ',1, 'm', 4, ! 10m merid. surface wind velocity [m/s] +! 'virtsalt ',1, 'm', 4, ! virtual salt flux [m/s*psu] +! 'relaxsalt ',1, 'm', 4, ! relaxation salt flux [m/s*psu] +! 'realsalt ',1, 'm', 4, ! real salt flux from sea ice [m/s*psu] + +! --- KPP VERTICAL MIXING (require mix_scheme_nmb==1,17,3,37) --- +! 'kpp_obldepth',1, 'm', 4, ! KPP ocean boundary layer depth [m] +! 'kpp_sbuoyflx',1, 'm', 4, ! surface buoyancy flux [m2/s3] + +! --- RECOM 2D BIOGEOCHEMISTRY (require use_REcoM=.true. and __recom) --- +! 'dpCO2s ',1, 'm', 4, ! Difference of oceanic pCO2 minus atmospheric pCO2 [uatm] +! 'pCO2s ',1, 'm', 4, ! Partial pressure of oceanic CO2 [uatm] +! 'CO2f ',1, 'm', 4, ! CO2-flux into the surface water [mmolC/m2/d] +! 'O2f ',1, 'm', 4, ! O2-flux into the surface water [mmolO/m2/d] +! 'Hp ',1, 'm', 4, ! Mean of H-plus ions in the surface water [mol/kg] +! 'aFe ',1, 'm', 4, ! Atmospheric iron input [umolFe/m2/s] +! 'aN ',1, 'm', 4, ! Atmospheric DIN input [mmolN/m2/s] +! 'benN ',1, 'm', 4, ! Benthos Nitrogen [mmol] +! 'benC ',1, 'm', 4, ! Benthos Carbon [mmol] +! 'benSi ',1, 'm', 4, ! Benthos silicon [mmol] +! 'benCalc ',1, 'm', 4, ! Benthos calcite [mmol] +! 'NPPn ',1, 'm', 4, ! Mean NPP nanophytoplankton [mmolC/m2/d] +! 'NPPd ',1, 'm', 4, ! Mean NPP diatoms [mmolC/m2/d] +! 'GPPn ',1, 'm', 4, ! Mean GPP nanophytoplankton [mmolC/m2/d] +! 'GPPd ',1, 'm', 4, ! Mean GPP diatoms [mmolC/m2/d] +! 'NNAn ',1, 'm', 4, ! Net N-assimilation nanophytoplankton [mmolN/m2/d] +! 'NNAd ',1, 'm', 4, ! Net N-assimilation diatoms [mmolN/m2/d] +! 'Chldegn ',1, 'm', 4, ! Chlorophyll degradation nanophytoplankton [1/d] +! 'Chldegd ',1, 'm', 4, ! Chlorophyll degradation diatoms [1/d] +! 'NPPc ',1, 'm', 4, ! Mean NPP coccolithophores [mmolC/(m2*d)] +! 'GPPc ',1, 'm', 4, ! Mean GPP coccolithophores [mmolC/m2/d] +! 'NNAc ',1, 'm', 4, ! Net N-assimilation coccolithophores [mmolN/(m2*d)] +! 'Chldegc ',1, 'm', 4, ! Chlorophyll degradation coccolithophores [1/d] + +! --- RECOM 3D BIOGEOCHEMISTRY (require use_REcoM=.true. and __recom) --- +! 'PAR ',1, 'm', 4, ! PAR [W/m2] +! 'respmeso ',1, 'm', 4, ! Respiration rate of mesozooplankton [mmolC/m2/d] +! 'respmacro ',1, 'm', 4, ! Respiration rate of macrozooplankton [mmolC/m2/d] +! 'respmicro ',1, 'm', 4, ! Respiration rate of microzooplankton [mmolC/m2/d] +! 'calcdiss ',1, 'm', 4, ! Calcite dissolution [mmolC/m2/d] +! 'calcif ',1, 'm', 4, ! Calcification [mmolC/m2/d] +! 'aggn ',1, 'm', 4, ! Aggregation of small phytoplankton [mmolC/m2/d] +! 'aggd ',1, 'm', 4, ! Aggregation of diatoms [mmolC/m2/d] +! 'aggc ',1, 'm', 4, ! Aggregation of coccolithophores [mmolC/m2/d] +! 'docexn ',1, 'm', 4, ! DOC excretion by small phytoplankton [mmolC/m2/d] +! 'docexd ',1, 'm', 4, ! DOC excretion by diatoms [mmolC/m2/d] +! 'docexc ',1, 'm', 4, ! DOC excretion by coccolithophores [mmolC/m2/d] +! 'respn ',1, 'm', 4, ! Respiration by small phytoplankton [mmolC/m2/d] +! 'respd ',1, 'm', 4, ! Respiration by diatoms [mmolC/m2/d] +! 'respc ',1, 'm', 4, ! Respiration by coccolithophores [mmolC/(m2*d)] +! 'NPPn3D ',1, 'm', 4, ! Net primary production of small phytoplankton [mmolC/m2/d] +! 'NPPd3D ',1, 'm', 4, ! Net primary production of diatoms [mmolC/m2/d] +! 'NPPc3D ',1, 'm', 4, ! Net primary production of coccolithophores [mmolC/m2/d] + +! --- WATER ISOTOPES IN OCEAN (require lwiso=.true.) --- +! 'h2o18 ',1, 'm', 4, ! h2o18 concentration [kmol/m**3] +! 'hDo16 ',1, 'm', 4, ! hDo16 concentration [kmol/m**3] +! 'h2o16 ',1, 'm', 4, ! h2o16 concentration [kmol/m**3] + +! --- NEUTRAL SLOPES --- +! 'slopetap_x',1, 'm', 4, ! neutral slope tapered X [none] +! 'slopetap_y',1, 'm', 4, ! neutral slope tapered Y [none] +! 'slopetap_z',1, 'm', 4, ! neutral slope tapered Z [none] +! 'slope_x ',1, 'm', 4, ! neutral slope X [none] +! 'slope_y ',1, 'm', 4, ! neutral slope Y [none] +! 'slope_z ',1, 'm', 4, ! neutral slope Z [none] + +! --- MIXING AND DYNAMICS --- +! 'N2 ',1, 'm', 4, ! brunt väisälä [1/s2] +! 'Kv ',1, 'm', 4, ! vertical diffusivity Kv [m2/s] +! 'Av ',1, 'm', 4, ! vertical viscosity Av [m2/s] + +! --- VISCOSITY TENDENCIES (require dynamics%opt_visc==8) --- +! 'u_dis_tend',1, 'm', 4, ! horizontal velocity viscosity tendency [m/s] +! 'v_dis_tend',1, 'm', 4, ! meridional velocity viscosity tendency [m/s] +! 'u_back_tend',1, 'm', 4, ! horizontal velocity backscatter tendency [m2/s2] +! 'v_back_tend',1, 'm', 4, ! meridional velocity backscatter tendency [m2/s2] +! 'u_total_tend',1, 'm', 4,! horizontal velocity total viscosity tendency [m/s] +! 'v_total_tend',1, 'm', 4,! meridional velocity total viscosity tendency [m/s] + +! --- FERRARI/GM PARAMETERISATION (require Fer_GM=.true.) --- +! 'bolus_u ',1, 'm', 4, ! GM bolus velocity U [m/s] +! 'bolus_v ',1, 'm', 4, ! GM bolus velocity V [m/s] +! 'bolus_w ',1, 'm', 4, ! GM bolus velocity W [m/s] +! 'fer_K ',1, 'm', 4, ! GM, stirring diff. [m2/s] +! 'fer_scal ',1, 'm', 4, ! GM surface scaling [] +! 'fer_C ',1, 'm', 4, ! GM, depth independent speed [m/s] +! 'cfl_z ',1, 'm', 4, ! vertical CFL criteria [?] + +! --- DENSITY MOC DIAGNOSTICS (require ldiag_dMOC=.true.) --- +! 'dMOC ',1, 'm', 4, ! fluxes for density MOC (multiple variables) + +! --- PRESSURE GRADIENT FORCE --- +! 'pgf_x ',1, 'm', 4, ! zonal pressure gradient force [m/s^2] +! 'pgf_y ',1, 'm', 4, ! meridional pressure gradient force [m/s^2] + +! --- ALE LAYER THICKNESS --- +! 'hnode ',1, 'm', 4, ! vertice layer thickness [m] +! 'hnode_new ',1, 'm', 4, ! hnode_new [m] +! 'helem ',1, 'm', 4, ! elemental layer thickness [m] + +! --- OIFS/IFS INTERFACE (require __oifs or __ifsinterface) --- +! 'alb ',1, 'm', 4, ! ice albedo [none] +! 'ist ',1, 'm', 4, ! ice surface temperature [K] +! 'qsi ',1, 'm', 4, ! ice heat flux [W/m^2] +! 'qso ',1, 'm', 4, ! oce heat flux [W/m^2] +! 'enthalpy ',1, 'm', 4, ! enthalpy of fusion [W/m^2] +! 'qcon ',1, 'm', 4, ! conductive heat flux [W/m^2] +! 'qres ',1, 'm', 4, ! residual heat flux [W/m^2] +! 'runoff_liquid',1, 'm', 4, ! liquid water runoff [m/s] +! 'runoff_solid',1, 'm', 4, ! solid water runoff [m/s] + +! --- ICEBERG OUTPUTS (require use_icebergs=.true.) --- +! 'icb ',1, 'm', 4, ! iceberg outputs (multiple variables) + +! --- TKE MIXING DIAGNOSTICS (require mix_scheme_nmb==5 or 56) --- +! 'TKE ',1, 'm', 4, ! TKE diagnostics (multiple variables) + +! --- IDEMIX MIXING DIAGNOSTICS (require mod(mix_scheme_nmb,10)==6) --- +! 'IDEMIX ',1, 'm', 4, ! IDEMIX diagnostics (multiple variables) + +! --- TIDAL MIXING DIAGNOSTICS (require mod(mix_scheme_nmb,10)==7) --- +! 'TIDAL ',1, 'm', 4, ! TIDAL diagnostics (multiple variables) + +! --- FORCING DIAGNOSTICS (require ldiag_forc=.true.) --- +! 'FORC ',1, 'm', 4, ! forcing diagnostics (multiple variables) + +! --- DISCRETE VARIANCE DECAY (require ldiag_DVD=.true.) --- +! 'DVD ',1, 'm', 4, ! DVD diagnostics (multiple variables) + +! --- SPLIT-EXPLICIT SUBCYCLING (require dynamics%use_ssh_se_subcycl=.true.) --- +! 'SPLIT-EXPL',1, 'm', 4, ! split-explicit diagnostics (multiple variables) + +! --- SQUARED VELOCITIES (require ldiag_uvw_sqr=.true.) --- +! 'UVW_SQR ',1, 'm', 4, ! squared velocities (u2, v2, w2) + +! --- TRACER GRADIENTS (require ldiag_trgrd_xyz=.true.) --- +! 'TRGRD_XYZ ',1, 'm', 4, ! horizontal and vertical tracer gradients + +! ============================================================================ +! END OF CATALOG +! ============================================================================ diff --git a/config/bin_2p1z1d_tp/namelist.tra b/config/bin_2p1z1d_tp/namelist.tra index cd80236ef..852790ac9 100644 --- a/config/bin_2p1z1d_tp/namelist.tra +++ b/config/bin_2p1z1d_tp/namelist.tra @@ -1,10 +1,38 @@ +! ============================================================================ +! ============ Namelist file for FESOM2 tracer configuration ================= +! ============================================================================ +! This file contains configuration for ocean tracers (temperature, salinity, +! and passive tracers): +! - Tracer list and advection/diffusion schemes +! - Initial conditions (3D ocean and 2D sea ice) +! - Biharmonic diffusion options +! - Vertical diffusion and time stepping +! - Physical parameterizations (mixing, restoring) +! ============================================================================ + +! ============================================================================ +! TRACER ARRAY ALLOCATION +! ============================================================================ &tracer_listsize -num_tracers=100 !number of tracers to allocate. shallbe large or equal to the number of streams in &nml_list +num_tracers = 100 ! number of tracers to allocate (must be ≥ actual number of tracers) / +! ============================================================================ +! TRACER LIST AND ADVECTION SCHEMES +! ============================================================================ +! Format: ID, horizontal_advection, vertical_advection, horizontal_diffusion, Kh_factor, Kv_factor +! Advection schemes: 'MFCT' (Multidimensional FCT), 'UPW1' (1st-order upwind), 'QR4C' (4th-order) +! Diffusion schemes: 'FCT' (Flux-Corrected Transport), 'NON' (none) +! Order switches : hor./vert. Ord.=1.0 --> 4th order, =0.0 --> 3rd order, =0.5 --> mixed 3rd&4th order +! ============================================================================ +! nml_tracer_list = +! idx, hor. Adv, vert. Adv., use FCT, hor.Ord., vert. Ord. +! 1 , 'MFCT' , 'QR4C' , 'FCT ' , 1. , 1. , ! temperature +! 2 , 'MFCT' , 'QR4C' , 'FCT ' , 1. , 1. , ! salinity +!101 , 'UPW1' , 'UPW1' , 'NON ' , 0. , 0. ! example passive tracer &tracer_list -nml_tracer_list = -1 , 'MFCT', 'QR4C', 'FCT ', 1., 1., +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., @@ -28,51 +56,85 @@ nml_tracer_list = 1020, 'MFCT', 'QR4C', 'FCT ', 1., 1., 1021, 'MFCT', 'QR4C', 'FCT ', 1., 1., 1022, '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 +! ============================================================================ +! 3D TRACER INITIAL CONDITIONS (OCEAN) +! ============================================================================ +&tracer_init3d +n_ic3d = 8 ! number of 3D tracers to initialize from files +idlist = 1019, 1022, 1018, 1003, 1002, 1001, 2, 1 ! tracer IDs to initialize (1=temperature, 2=salinity) +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' ! netCDF files in ClimateDataPath (one per tracer) +varlist = 'Fe', 'oxygen_mmol', 'i_an', 'TAlk_mmol', 'TCO2_mmol', 'n_an', 'salt', 'temp' ! variable names in the netCDF files +t_insitu = .true. ! if true, convert in-situ temperature to potential temperature / -&tracer_init2d ! initial conditions for 2D tracers (sea ice) -n_ic2d = 3 ! number of tracers to initialize -idlist = 1, 2, 3 ! their IDs (0 is a_ice, 1 is m_ice, 3 m_snow). The reading order is defined here! -filelist = 'a_ice.nc', 'm_ice.nc', 'm_snow.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist -varlist = 'a_ice', 'm_ice', 'm_snow' ! variables to read from specified files -ini_ice_from_file=.false. +! ============================================================================ +! 2D TRACER INITIAL CONDITIONS (SEA ICE) +! ============================================================================ +&tracer_init2d +n_ic2d = 3 ! number of 2D tracers to initialize from files +idlist = 1, 2, 3 ! tracer IDs (1=ice concentration, 2=ice thickness, 3=snow thickness) +filelist = 'a_ice.nc', 'm_ice.nc', 'm_snow.nc' ! netCDF files in ClimateDataPath +varlist = 'a_ice', 'm_ice', 'm_snow' ! variable names in the netCDF files +ini_ice_from_file = .false. ! enable initialization from files (false = use default values) / +! ============================================================================ +! TRACER GENERAL SETTINGS +! ============================================================================ &tracer_general -! bharmonic diffusion for tracers. We recommend to use this option in very high resolution runs (Redi is generally off there). -smooth_bh_tra =.false. ! use biharmonic diffusion (filter implementation) for tracers -gamma0_tra = 0.0005 ! gammaX_tra are analogous to those in the dynamical part -gamma1_tra = 0.0125 -gamma2_tra = 0. -i_vert_diff =.true. +! --- Biharmonic Diffusion --- +! Recommended for very high resolution runs (where Redi is typically disabled) +smooth_bh_tra = .false. ! enable biharmonic diffusion (filter implementation) for tracers +gamma0_tra = 0.0005 ! background biharmonic diffusion coefficient [dimensionless] +gamma1_tra = 0.0125 ! flow-aware biharmonic diffusion coefficient [dimensionless] +gamma2_tra = 0. ! additional biharmonic diffusion coefficient [dimensionless] + +! --- Vertical Diffusion and Time Stepping --- +i_vert_diff = .true. ! use implicit vertical diffusion (recommended for stability) +AB_order = 2 ! Adams-Bashforth time stepping order (2 or 3) / +! ============================================================================ +! TRACER PHYSICS AND PARAMETERIZATIONS +! ============================================================================ &tracer_phys -use_momix = .true. ! switch on/off !Monin-Obukhov -> TB04 mixing -momix_lat = -50.0 ! latitidinal treshhold for TB04, =90 --> global -momix_kv = 0.01 ! PP/KPP, mixing coefficient within MO length -use_instabmix = .true. ! enhance convection in case of instable stratification -instabmix_kv = 0.1 -use_windmix = .false. ! enhance mixing trough wind only for PP mixing (for stability) -windmix_kv = 1.e-3 -windmix_nl = 2 -diff_sh_limit=5.0e-3 ! for KPP, max diff due to shear instability -Kv0_const=.true. -double_diffusion=.false. ! for KPP,dd switch -K_ver=1.0e-5 -K_hor=3000. -surf_relax_T=0.0 -surf_relax_S=1.929e-06 ! 50m/300days 6.43e-07! m/s 10./(180.*86400.) -balance_salt_water =.true. ! balance virtual-salt or freshwater flux or not -clim_relax=0.0 ! 1/s, geometrical information has to be supplied -ref_sss_local=.true. -ref_sss=34. +! --- Monin-Obukhov Mixing (TB04) --- +use_momix = .false. ! enable Monin-Obukhov mixing (Timmermann & Beckmann 2004) +momix_lat = -50.0 ! latitude threshold for TB04 [degrees] (90 = global, -50 = south of 50°S) +momix_kv = 0.01 ! mixing coefficient within MO length [m²/s] + +! --- Convective Instability Mixing --- +use_instabmix = .true. ! enhance mixing for unstable stratification (convection) +instabmix_kv = 0.1 ! mixing coefficient for unstable stratification [m²/s] + +! --- Wind Mixing (PP scheme only) --- +use_windmix = .false. ! enhance near-surface mixing by wind (for PP mixing stability) +windmix_kv = 1.e-3 ! wind mixing coefficient [m²/s] +windmix_nl = 2 ! number of surface layers for wind mixing + +! --- Shear Instability (KPP) --- +diff_sh_limit = 5.0e-3 ! maximum diffusivity due to shear instability [m²/s] (for KPP) + +! --- Background Diffusivity --- +Kv0_const = .true. ! use constant background vertical diffusivity +K_ver = 1.0e-5 ! background vertical diffusivity [m²/s] +K_hor = 0. ! background horizontal diffusivity [m²/s] + +! --- Double Diffusion (KPP) --- +double_diffusion = .false. ! enable double diffusion parameterization (for KPP) + +! --- Surface Restoring --- +surf_relax_T = 0.0 ! surface temperature restoring coefficient [m/s] (0 = disabled) +surf_relax_S = 1.929e-06 ! surface salinity restoring coefficient [m/s] +balance_salt_water = .true. ! balance virtual salt flux with freshwater flux + +! --- Climatology Restoring --- +clim_relax = 0.0 ! 3D climatology restoring coefficient [1/s] (0 = disabled) + +! --- Reference Salinity --- +ref_sss_local = .true. ! use local reference SSS (true) or global constant (false) +ref_sss = 34. ! global reference salinity [psu] (if ref_sss_local=false) / diff --git a/config/bin_2p1z1d_tp/namelist.transit b/config/bin_2p1z1d_tp/namelist.transit new file mode 100644 index 000000000..80313df59 --- /dev/null +++ b/config/bin_2p1z1d_tp/namelist.transit @@ -0,0 +1,53 @@ +! ============================================================================ +! ========== Namelist file for FESOM2 transient tracers ===================== +! ============================================================================ +! This file contains configuration for transient tracer simulations: +! - Radioactive isotopes (14C, 39Ar) +! - Chlorofluorocarbons (CFC-11, CFC-12) +! - Sulfur hexafluoride (SF6) +! - Anthropogenic vs paleoclimate simulations +! - Atmospheric boundary conditions +! - Decay constants +! +! Requires use_transit=.true. in namelist.config +! ============================================================================ + +! ============================================================================ +! TRANSIENT TRACER CONFIGURATION +! ============================================================================ +&transit_param +! --- Enable Individual Tracers --- +l_r14c = .false. ! enable radiocarbon (14C/C ratio) +l_r39ar = .false. ! enable 39Ar/Ar ratio +l_f11 = .false. ! enable CFC-11 (chlorofluorocarbon) +l_f12 = .false. ! enable CFC-12 (chlorofluorocarbon) +l_sf6 = .false. ! enable SF6 (sulfur hexafluoride) + +! --- Simulation Type --- +anthro_transit = .false. ! anthropogenic transient tracer simulation (modern era) +paleo_transit = .false. ! paleoclimate transient tracer simulation + +! --- Time Series Configuration --- +length_transit = 1 ! length of atmospheric forcing time series + ! use 166 for anthro_transit=.true. (1765-2020) +ti_start_transit = 1 ! starting time index in forcing file + ! use 1 for D14C, 80 for CFC-12 + +! --- Atmospheric Forcing File --- +ifile_transit = '/work/ab0246/a270108/fesom2_recom_config/input-for-awiesm/Table_CO2_isoC_CFCs1112_SF6.txt' + ! path to atmospheric boundary condition file + +! --- Atmospheric Concentrations (Global Mean) --- +r14c_a = 1.0000 ! atmospheric 14C/C ratio [dimensionless] +r39ar_a = 1.0000 ! atmospheric 39Ar/Ar ratio [dimensionless] +xarg_a = 9.34e-3 ! atmospheric Argon mole fraction [dimensionless] +xco2_a = 284.32e-6 ! atmospheric CO2 mole fraction [dimensionless] (preindustrial: 284.32 ppm) + +! --- Initial Ocean Concentrations (Global Mean) --- +dic_0 = 2.00 ! mixed layer DIC concentration [mol/m³] +arg_0 = 0.01 ! mixed layer Argon concentration [mol/m³] + +! --- Radioactive Decay Constants --- +decay14 = 3.8561e-12 ! decay constant of 14C [1/s] (half-life: 5700 years, 1 year = 365.0 days) +decay39 = 8.1708e-11 ! decay constant of 39Ar [1/s] (half-life: 269 years, 1 year = 365.0 days) +/ From 1dc0f844cc334558441f05dc52e37b022c187679 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 16 Dec 2025 15:08:56 +0100 Subject: [PATCH 48/68] fix in depth denpendecy of calcite dissolution --- src/CMakeLists.txt | 2 +- src/int_recom/recom_sms.F90 | 2563 ++++++++++++++++++++++++++++++++++- 2 files changed, 2563 insertions(+), 2 deletions(-) mode change 120000 => 100644 src/int_recom/recom_sms.F90 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7c3b5d902..62b44ce73 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -349,7 +349,7 @@ if(${CMAKE_Fortran_COMPILER_ID} STREQUAL Intel OR ${CMAKE_Fortran_COMPILER_ID} # | Intel/MPI | -O3 | 144s | # |*Intel/MPI | -03 -march=core-avx2 -mtune=core-avx2 -qopt-zmm-usage=low | 140.95s | # | | -align array64byte -unroll-aggressive -qopt-malloc-options=2 | | - #target_compile_options(${PROJECT_NAME} PRIVATE -march=core-avx2 -mtune=core-avx2 -qopt-zmm-usage=low -align array64byte -unroll-aggressive -qopt-malloc-options=2) + # target_compile_options(${PROJECT_NAME} PRIVATE -march=core-avx2 -mtune=core-avx2 -qopt-zmm-usage=low -align array64byte -unroll-aggressive -qopt-malloc-options=2 -g -traceback -check) elseif(${FESOM_PLATFORM_STRATEGY} STREQUAL leo-dcgp ) target_compile_options(${PROJECT_NAME} PRIVATE -xCORE-AVX512 -qopt-zmm-usage=high -align array64byte -ipo) elseif(${FESOM_PLATFORM_STRATEGY} STREQUAL mn5-gpp ) diff --git a/src/int_recom/recom_sms.F90 b/src/int_recom/recom_sms.F90 deleted file mode 120000 index 19cbaa84d..000000000 --- a/src/int_recom/recom_sms.F90 +++ /dev/null @@ -1 +0,0 @@ -recom_sms.F90.nica \ No newline at end of file diff --git a/src/int_recom/recom_sms.F90 b/src/int_recom/recom_sms.F90 new file mode 100644 index 000000000..31bc22ad8 --- /dev/null +++ b/src/int_recom/recom_sms.F90 @@ -0,0 +1,2562 @@ +subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & + , CO2_watercolumn & + , pH_watercolumn & + , pCO2_watercolumn & + , HCO3_watercolumn & + , CO3_watercolumn & + , OmegaC_watercolumn & + , kspc_watercolumn & + , rhoSW_watercolumn & + , Loc_slp, zF, PAR, Lond, Latd, ice, dynamics, tracers, partit, mesh) + + use recom_declarations + use recom_locvar + use recom_glovar + use recom_config + use recoM_ciso + use g_clock + + use g_config + use MOD_MESH + use MOD_TRACER + use MOD_DYN + USE MOD_ICE + use o_ARRAYS + use o_PARAM + USE MOD_PARTIT + USE MOD_PARSUP + + use g_forcing_arrays + use g_comm_auto + use mvars + use mdepth2press + use gsw_mod_toolbox, only: gsw_sa_from_sp,gsw_ct_from_pt,gsw_rho + + implicit none + type(t_dyn) , intent(inout), target :: dynamics + type(t_tracer), intent(inout), target :: tracers + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + type(t_ice) , intent(inout), target :: ice + + 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 + + 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 + real(kind=8),intent(in) :: SurfSR !< [W/m2] ShortWave radiation at surface + + real(kind=8),dimension(mesh%nl-1,bgc_num),intent(inout) :: sms !< Source-Minus-Sinks term + real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Temp !< [degrees C] Ocean temperature + real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Sali_depth !< NEW MOCSY Salinity for the whole water column + + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO2_watercolumn !< [mol/m3] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pH_watercolumn !< on total scale + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pCO2_watercolumn !< [uatm] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: HCO3_watercolumn !< [mol/m3] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO3_watercolumn !< [mol/m3] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: OmegaC_watercolumn !< calcite saturation state + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: kspc_watercolumn !< stoichiometric solubility product [mol^2/kg^2] + Real(kind=8),dimension(mesh%nl-1),intent(inout) :: rhoSW_watercolumn !< in-situ density of seawater [kg/m3] + + real(kind=8),dimension(mesh%nl) ,intent(in) :: zF !< [m] Depth of fluxes + real(kind=8),dimension(mesh%nl-1),intent(inout) :: PAR + + real(kind=8) :: dt_d !< Size of time steps [day] + real(kind=8) :: dt_b !< Size of time steps [day] + real(kind=8),dimension(mesh%nl-1) :: Sink + real(kind=8) :: dt_sink !< Size of local time step + + real(kind=8) :: recip_hetN_plus !< MB's addition to heterotrophic respiration + real(kind=8) :: recip_res_het !< [day] Reciprocal of respiration by heterotrophs and mortality (loss to detritus) + real(kind=8) :: Sink_Vel + real(kind=8) :: aux + integer :: k,step,ii, idiags,n + + real(kind=8), intent(in) :: Loc_slp ![Pa] sea-level pressure + real(kind=8) :: Patm_depth(1) + real(kind=8) :: REcoM_T_depth(1) ! MOCSY temperature for the whole water column for mocsy minimum defined as -2 + real(kind=8) :: REcoM_S_depth(1) + real(kind=8) :: REcoM_DIC_depth(1) + real(kind=8) :: REcoM_Alk_depth(1) + real(kind=8) :: REcoM_Si_depth(1) + real(kind=8) :: REcoM_Phos_depth(1) + 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 + +#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 + + 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 + + tiny_Si = tiny_C_d/SiCmax !< SiCmax = 0.8d0 + +#if defined (__coccos) + tiny_N_c = tiny_chl/chl2N_max_c + tiny_C_c = tiny_N_c/NCmax_c +#endif + + recip_res_het = 1.d0/res_het !< res_het = 0.01d0 [1/day] Respiration by heterotrophs and mortality (loss to detritus) + + Patm_depth = Loc_slp/Pa2atm ! MOCSY convert from Pa to atm. + +!------------------------------------------------------------------------------- +!> REcoM time steps [day] +!------------------------------------------------------------------------------- + + 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] + +!------------------------------------------------------------------------------- +!Main time loop starts + do step = one,biostep + + kdzUpper = 0.d0 !< Upper light attenuation of top cell is set to zero + + if (any(abs(sms(:,:)) <= tiny)) sms(:,:) = zero ! tiny = 2.23D-16 + +!------------------------------------------------------------------------------- +! 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 + +! 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 + + if (ciso) then +!< additional variables are declared in module REcoM_ciso + 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)) + + calc_diss_13 = alpha_dcal_13 * calc_diss + + 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 + + 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 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) + +!------------------------------------------------------------------------------- +!> 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 + +!------------------------------------------------------------------------------- +! Depth component of Mocsy (see http://ocmip5.ipsl.jussieu.fr/mocsy/pyth.html) +!------------------------------------------------------------------------------- + +! 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. + 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') + CO2_watercolumn(k) = co2_depth(1) + pH_watercolumn(k) = ph_depth(1) + pCO2_watercolumn(k) = pco2_depth(1) + HCO3_watercolumn(k) = hco3_depth(1) + CO3_watercolumn(k) = co3_depth(1) + 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') + CO2_watercolumn(k) = co2_depth(1) + pH_watercolumn(k) = ph_depth(1) + pCO2_watercolumn(k) = pco2_depth(1) + HCO3_watercolumn(k) = hco3_depth(1) + CO3_watercolumn(k) = co3_depth(1) + OmegaC_watercolumn(k) = OmegaC_depth(1) + 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') + CO2_watercolumn(k) = co2_depth(1) + pH_watercolumn(k) = ph_depth(1) + pCO2_watercolumn(k) = pco2_depth(1) + HCO3_watercolumn(k) = hco3_depth(1) + CO3_watercolumn(k) = co3_depth(1) + 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] + +! 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 + +! 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 +!------------------------------------------------------------------------------ +!Ying 26.12.2025: calcite dissolution applied a different depth dependence relative to sinking + Sink_Vel = Vcalc * abs(zF(k)) + Vdet +! 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 + 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) + 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?? + 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 + +!< *** Diatom photosynthesis rate *** +!< ********************************** + if ( pMax_dia .lt. 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 + + 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 + else + KOchl = deg_Chl*(real(one) - exp(-alfa * CHL2C_plast * PARave / pMax)) + KOchl = max((deg_Chl*0.1d0), KOchl) + 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 + 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 + 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 + 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 + stop + end if +#endif + end if ! photodamage + +!------------------------------------------------------------------------------- +!> Assimilation section +!------------------------------------------------------------------------------- + +!< 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 + 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 + + limitFacSi = recom_limiter(SiMaxSlope, qSiC, SiCmax) & + * limitFacN_dia + Si_assim = V_cm_fact_d * P_cm_d * arrFunc * SiCUptakeRatio & + * limitFacSi * Si/(Si + k_si) + +!------------------------------------------------------------------------------- +!< *** Iron chemistry *** +!< ********************** +! select the method to calculate freeFe + if (fe_2ligands) then + if (fe_compl_nica) then + logK1 = max(tiny, 24.36 - 1.67 * pH_watercolumn(k) & + + EOC * (-2.e-4 * EOC + 0.034)) + logK2 = logK1 + 2.67 + Klig1 = 10 ** (logK1 - 9) + Klig2 = 10 ** (logK2 - 9) + freeFe = iron_chemistry_2ligands(Fe,1.7,0.6,Klig1,Klig2) + endif + else + freeFe = iron_chemistry(Fe,totalligand,ligandStabConst) + endif + +!------------------------------------------------------------------------------- +!< *** Chlorophyll synthesis *** +!< ***************************** + +!< 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 ] + + 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 + 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 *** +!< ************************************* + +!< res_phy: Maintenance respiration rate constant [day−1 ] +!< biosynth: The cost of biosynthesis of N [mmol C mmol N−1 ] + + phyRespRate = res_phy * limitFacN + biosynth * N_assim + phyRespRate_dia = res_phy_d * limitFacN_dia + biosynth * N_assim_dia + biosynthSi * Si_assim +#if defined (__coccos) + phyRespRate_cocco = res_phy_c * limitFacN_cocco + biosynth * N_assim_cocco +#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 + +!< *** 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 + +!------------------------------------------------------------------------------- +! 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 + +!< *** 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 + + grazingFlux_phy2 = (grazingFlux2 * fphyN2)/food2 + grazingFlux_Dia2 = (grazingFlux2 * fDiaN2)/food2 + grazingFlux_miczoo2 = (grazingFlux2 * fMicZooN2)/food2 ! 3Zoo + +#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 + + 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 + +!------------------------------------------------------------------------------- +! Third Zooplankton (Microzooplankton) +!------------------------------------------------------------------------------- +!< Grazing on small phytoplankton, diatoms and coccolithophore (optional) + +!< *** Food availability *** +!< ************************* +!< pzPhy3: Maximum nanophytoplankton preference +!< pzDia3: Maximum diatom preference +!< pzCocco3: Maximum coccolithophore preference + + 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 + +!------------------------------------------------------------------------------- +!< 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 + endif + + if (ciso) then +!MB set HetRespFlux_plus = .true. in namelist.recom +! HetRespFlux_13 = max(zero, recip_res_het * arrFunc * (hetC_13 * recip_hetN_plus - redfield) * HetC_13) +! Numerically safer parametrization avoiding instable results which may result from different cutoff values -- CHECK + HetRespFlux_13 = HetRespFlux * HetC_13 / HetC +!! HetRespFlux_13 = HetRespFlux * (HetC_13 / HetC) **2 + if (ciso_14 .and. ciso_organic_14) then +! HetRespFlux_14 = max(zero, recip_res_het * arrFunc * (hetC_14 * recip_hetN_plus - redfield) * HetC_14) + HetRespFlux_14 = HetRespFlux * HetC_14 / HetC +!! HetRespFlux_14 = HetRespFlux * (HetC_14 / HetC) **2 + end if + end if + +!------------------------------------------------------------------------------- +!< Zooplanton mortality (Quadratic) + + hetLossFlux = loss_het * HetN * HetN + +#if defined (__3Zoo2Det) +!------------------------------------------------------------------------------- +!< Second zooplankton respiration + + call krill_resp(n, partit, mesh) + + 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) + + Zoo2LossFlux = loss_zoo2 * zoo2N * zoo2N + +!------------------------------------------------------------------------------- +!< Second zooplankton fecal pellets + + Zoo2fecalloss_n = fecal_rate_n * grazingFlux2 + Zoo2fecalloss_c = fecal_rate_c * grazingFluxcarbonzoo2 + +!------------------------------------------------------------------------------- +!< Mesozooplankton fecal pellets + + mesfecalloss_n = fecal_rate_n_mes * grazingFlux + mesfecalloss_c = fecal_rate_c_mes * grazingFluxcarbon_mes + +!------------------------------------------------------------------------------- +! Third zooplankton, microzooplankton, respiration ! 3Zoo + + MicZooRespFlux = res_miczoo * q10_mic_res * MicZooC +!------------------------------------------------------------------------------- +! Third zooplankton, microzooplankton, mortality (Quadratic) ! 3Zoo + + MicZooLossFlux = loss_miczoo * MicZooN * MicZooN +#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 + 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 + +#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 + + if (ciso) then + calcification_13 = calc_prod_ratio * Cphot * PhyC_13 * alpha_calc_13 + calcification_13 = calcification * alpha_calc_13 + calc_loss_agg_13 = aggregationRate * PhyCalc_13 + calc_loss_gra_13 = grazingFlux_phy * recipQuota_13/(PhyC_13 + tiny) * PhyCalc_13 + if (ciso_14 .and. ciso_organic_14) then + calcification_14 = calc_prod_ratio * Cphot * PhyC_14 * alpha_calc_14 + calc_loss_agg_14 = aggregationRate * PhyCalc_14 + calc_loss_gra_14 = grazingFlux_phy * recipQuota_14/(PhyC_14 + tiny) * PhyCalc_14 + end if + end if + +!------------------------------------------------------------------------------- +! Sources minus sinks (SMS) +!------------------------------------------------------------------------------- + +!< *** 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((Latd(1)<-45.0) .and. ((state(k,idic)+sms(k,idic))>2500)) then +! !co2flux(1)=0.0 +! print*,'ERROR: strange dic !' +! print*,'state(k,idic): ', state(k,idic) +! print*,'sms Cphot: ', -Cphot*PhyC +! print*,'sms resp: ', phyRespRate*PhyC +! print*,'sms Cphot dia: ', -Cphot_Dia*DiaC +! print*,'sms resp dia: ', phyRespRate_Dia * DiaC +! print*,'sms eoc: ', rho_C1* arrFunc *EOC +! print*,'sms het resp: ', HetRespFlux +! print*, 'sms co2: ', dflux(1) * recipdzF(k) * max( 2-k, 0 ) +! print*, 'sms calcdiss: ', calc_diss * DetCalc +! print*, 'sms calc_loss: ', calc_loss_gra * calc_diss_guts +! print*, 'sms calcification: ', -calcification +! 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 & ! --> grazing on small phytoplankton by third zooplankton + - grazingFlux_phy3 * grazEff3 & ! --> fraction of grazingFlux_phy3 into microzooplankton pool + + grazingFlux_dia3 & ! --> grazing on diatoms by third zooplankton + - grazingFlux_dia3 * grazEff3 & ! --> fraction of grazingFlux_dia3 into microzooplankton pool +#if defined (__coccos) + + grazingFlux_Cocco3 & ! --> grazing on coccolithophores by third zooplankton + - grazingFlux_Cocco3 * grazEff3 & ! --> fraction of grazingFlux_Cocco3 into microzooplankton pool + + aggregationRate * CoccoN & +#endif + - grazingFlux_Det * grazEff & ! --> grazing of first zoo (meso) on first detritus class + - grazingFlux_Det2 * grazEff2 & ! --> grazing of second zoo (macro) on first detritus class + + aggregationRate * PhyN & + + aggregationRate * DiaN & + + miczooLossFlux & ! --> microzooplankton, mortality + - reminN * arrFunc * O2Func * DetN & ! --> O2remin + ) * dt_b + sms(k,idetn) +#else + sms(k,idetn) = ( & + + grazingFlux_phy & ! Technically it is mesooooooooooooooooo + - 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 * recipDet * grazEff2 & ! corrected recipDet2 -> recipDet + + 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 + 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) + else + sms(k,ihetc) = ( & + + grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia * grazEff & +#if defined (__coccos) + + grazingFlux_Cocco * recipQuota_Cocco * grazEff & +#endif +#if defined (__3Zoo2Det) + + grazingFlux_miczoo * recipQZoo3 * grazEff & ! 3Zoo + - grazingFlux_het2 * recipQZoo & + - Mesfecalloss_c & ! 3Zoo +#endif + - hetLossFlux * recipQZoo & + - lossC_z * HetC & + - hetRespFlux & + ) * dt_b + sms(k,ihetc) + endif + +!< *** Macrozooplankton *** +!< ************************ + +#if defined (__3Zoo2Det) +!____________________________________________________________ +!< Second Zooplankton N + sms(k,izoo2n) = ( & + + grazingFlux2 * grazEff2 & + - Zoo2LossFlux & + - lossN_z2 * Zoo2N & + - Zoo2fecalloss_n & + ) * dt_b + sms(k,izoo2n) + +!____________________________________________________________ +!< Second Zooplankton C + if (Grazing_detritus) then + + sms(k,izoo2c) = ( & + + grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo + + grazingFlux_Det2 * recipDet * grazEff2 & + + grazingFlux_DetZ22 * recipDet2 * grazEff2 & + - zoo2LossFlux * recipQZoo2 & + - lossC_z2 * Zoo2C & + - Zoo2RespFlux & + - Zoo2fecalloss_c & + ) * dt_b + sms(k,izoo2c) + else + sms(k,izoo2c) = ( & + + grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo + - zoo2LossFlux * recipQZoo2 & + - lossC_z2 * Zoo2C & + - Zoo2RespFlux & + - Zoo2fecalloss_c & + ) * dt_b + sms(k,izoo2c) + end if + +!< *** Microzooplankton *** +!< ************************ + +!____________________________________________________________ +!< Third Zooplankton N + sms(k,imiczoon) = ( & + + grazingFlux3 * grazEff3 & + - grazingFlux_miczoo & + - grazingFlux_miczoo2 & + - MicZooLossFlux & + - lossN_z3 * MicZooN & + ) * dt_b + sms(k,imiczoon) + +!____________________________________________________________ +!< Third Zooplankton C + sms(k,imiczooc) = ( & + + grazingFlux_phy3 * recipQuota * grazEff3 & + + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & +#if defined (__coccos) + + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & +#endif + - MicZooLossFlux * recipQZoo3 & + - grazingFlux_miczoo * recipQZoo3 & + - grazingFlux_miczoo2 * recipQZoo3 & + - lossC_z3 * MicZooC & + - MicZooRespFlux & + ) * dt_b + sms(k,imiczooc) + +!< *** Fast-sinking Detritus *** +!< ***************************** + +!____________________________________________________________ +!< Second Zooplankton Detritus N + if (Grazing_detritus) then + sms(k,idetz2n) = ( & + + grazingFlux_phy2 & + - grazingFlux_phy2 * grazEff2 & + + grazingFlux_dia2 & + - grazingFlux_dia2 * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco & + - grazingFlux_Cocco * grazEff & + + grazingFlux_Cocco2 & + - grazingFlux_Cocco2 * grazEff2 & +#endif + + grazingFlux_het2 & + - grazingFlux_het2 * grazEff2 & + + grazingFlux_miczoo2 & + - grazingFlux_miczoo2 * grazEff2 & + + grazingFlux_phy & + - grazingFlux_phy * grazEff & + + grazingFlux_dia & + - grazingFlux_dia * grazEff & + + grazingFlux_miczoo & + - grazingFlux_miczoo * grazEff & + - grazingFlux_DetZ2 * grazEff & + - grazingFlux_DetZ22 * grazEff2 & + + Zoo2LossFlux & + + hetLossFlux & + + Zoo2fecalloss_n & + + Mesfecalloss_n & + - reminN * arrFunc * O2Func * DetZ2N & ! O2remin + ) * dt_b + sms(k,idetz2n) + else + sms(k,idetz2n) = ( & + + grazingFlux_phy2 & + + grazingFlux_dia2 & +#if defined (__coccos) + + grazingFlux_Cocco & + + grazingFlux_Cocco2 & +#endif + + grazingFlux_het2 & + + grazingFlux_miczoo2 & + - grazingFlux2 * grazEff2 & + + grazingFlux_phy & + + grazingFlux_dia & + + grazingFlux_miczoo & + - grazingFlux * grazEff & + + Zoo2LossFlux & + + hetLossFlux & + + Zoo2fecalloss_n & + + Mesfecalloss_n & + - reminN * arrFunc * O2Func * DetZ2N & ! O2remin + ) * dt_b + sms(k,idetz2n) + end if + +!____________________________________________________________ +!< Second Zooplankton Detritus C + if (Grazing_detritus) then + sms(k,idetz2c) = ( & + + grazingFlux_phy2 * recipQuota & + - grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia & + - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco * recipQuota_Cocco & + - grazingFlux_Cocco * recipQuota_Cocco * grazEff & + + grazingFlux_Cocco2 * recipQuota_Cocco & + - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo & + - grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2 * recipQZoo3 & + - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & + + grazingFlux_phy * recipQuota & + - grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia & + - grazingFlux_Dia * recipQuota_Dia * grazEff & + + grazingFlux_miczoo * recipQZoo3 & + - grazingFlux_miczoo * recipQZoo3 * grazEff & + - grazingFlux_DetZ2 * recipDet2 * grazEff & + - grazingFlux_DetZ22 * recipDet2 * grazEff2 & + + Zoo2LossFlux * recipQZoo2 & + + hetLossFlux * recipQZoo & + + Zoo2fecalloss_c & + + Mesfecalloss_c & + - reminC * arrFunc * O2Func * DetZ2C & ! O2remin + ) * dt_b + sms(k,idetz2c) + else + sms(k,idetz2c) = ( & + + grazingFlux_phy2 * recipQuota & + - grazingFlux_phy2 * recipQuota * grazEff2 & + + grazingFlux_Dia2 * recipQuota_Dia & + - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & +#if defined (__coccos) + + grazingFlux_Cocco * recipQuota_Cocco & + - grazingFlux_Cocco * recipQuota_Cocco * grazEff & + + grazingFlux_Cocco2 * recipQuota_Cocco & + - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & +#endif + + grazingFlux_het2 * recipQZoo & + - grazingFlux_het2 * recipQZoo * grazEff2 & + + grazingFlux_miczoo2 * recipQZoo3 & + - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & + + grazingFlux_phy * recipQuota & + - grazingFlux_phy * recipQuota * grazEff & + + grazingFlux_Dia * recipQuota_Dia & + - grazingFlux_Dia * recipQuota_Dia * grazEff & + + grazingFlux_miczoo * recipQZoo3 & + - grazingFlux_miczoo * recipQZoo3 * grazEff & + + Zoo2LossFlux * recipQZoo2 & + + hetLossFlux * recipQZoo & + + Zoo2fecalloss_c & + + Mesfecalloss_c & + - reminC * arrFunc * O2Func * DetZ2C & ! O2remin + ) * dt_b + sms(k,idetz2c) + end if + +!____________________________________________________________ +!< Second Zooplankton Detritus Si + sms(k,idetz2si) = ( & + + grazingFlux_dia2 * qSiN & ! --> qSin convert N to Si + + grazingFlux_dia * qSiN & + - reminSiT * DetZ2Si & + ) * dt_b + sms(k,idetz2si) + +!____________________________________________________________ +!< Second Zooplankton Detritus calcite + sms(k,idetz2calc) = ( & + + calc_loss_gra2 & + - calc_loss_gra2 * calc_diss_guts & + + calc_loss_gra & + - calc_loss_gra * calc_diss_guts & + - calc_diss2 * DetZ2Calc & + ) * dt_b + sms(k,idetz2calc) +#endif + +!< *** DOM *** +!< *********** + +!____________________________________________________________ +!< DON (Extracellular organic N) + + sms(k,idon) = ( & + + lossN * limitFacN * phyN & + + lossN_d * limitFacN_Dia * DiaN & +#if defined (__coccos) + + lossN_c * limitFacN_Cocco * CoccoN & +#endif + + reminN * arrFunc * O2Func * DetN & + + lossN_z * HetN & +#if defined (__3Zoo2Det) + + reminN * arrFunc * O2Func * DetZ2N & + + lossN_z2 * Zoo2N & + + lossN_z3 * MicZooN & ! 3Zoo +#endif + - rho_N * arrFunc * O2Func * DON & ! O2remin + ) * dt_b + sms(k,idon) + +!____________________________________________________________ +!< EOC + + sms(k,idoc) = ( & + + lossC * limitFacN * phyC & + + lossC_d * limitFacN_dia * DiaC & +#if defined (__coccos) + + lossC_c * limitFacN_cocco * CoccoC & +#endif + + reminC * arrFunc * O2Func * DetC & + + lossC_z * HetC & +#if defined (__3Zoo2Det) + + reminC * arrFunc * O2Func * DetZ2C & + + lossC_z2 * Zoo2C & + + lossC_z3 * MicZooC & ! 3Zoo +#endif + - rho_c1 * arrFunc * O2Func * EOC & ! O2remin + ) * dt_b + sms(k,idoc) + +!< *** Diatoms *** +!< *************** + +!____________________________________________________________ +!< Diatom N + +!< lossN: Diatom loss of organic N compounds [day^-1] +!< When N : C ratio becomes too high, excretion of DON is downregulated +!< by the limiter function limitFacN_dia +!< aggregationRate transfers N to the detritus pool + + sms(k,idian) = ( & + + N_assim_dia * DiaC & ! --> N assimilation + - lossN_d * limitFacN_dia * DiaN & ! --> DON excretion + - aggregationRate * DiaN & ! --> Aggregation loss + - grazingFlux_Dia & ! --> Grazing loss +#if defined (__3Zoo2Det) + - grazingFlux_Dia2 & + - grazingFlux_Dia3 & ! 3Zoo +#endif + ) * dt_b + sms(k,idian) + +!____________________________________________________________ +!< Diatom C + +!< lossC_d: Diatom loss of carbon [day^-1] +!< When N : C ratio becomes too high, excretion of DOC is downregulated +!< by the limiter function limitFacN_dia +!< aggregationRate transfers C to the detritus pool + + sms(k,idiac) = ( & + + Cphot_dia * DiaC & ! -- Photosynthesis ---->/ + - lossC_d * limitFacN_dia * DiaC & ! -- Excretion of DOC --/ Net Photosynthesis + - phyRespRate_dia * DiaC & ! -- Respiration ----->/ + - aggregationRate * DiaC & + - grazingFlux_dia * recipQuota_dia & +#if defined (__3Zoo2Det) + - grazingFlux_dia2 * recipQuota_dia & + - grazingFlux_dia3 * recipQuota_dia & ! 3Zoo +#endif + ) * dt_b + sms(k,idiac) + +!____________________________________________________________ +!< Diatom Chl + + sms(k,idchl) = ( & + + chlSynth_dia * DiaC & ! --> Chl a synthesis + - KOchl_dia * DiaChl & ! --> Degradation loss + - aggregationRate * DiaChl & ! --> Aggregation loss + - grazingFlux_dia * Chl2N_dia & ! --> Grazing loss +#if defined (__3Zoo2Det) + - grazingFlux_dia2 * Chl2N_dia & + - grazingFlux_dia3 * Chl2N_dia & ! 3Zoo +#endif + ) * dt_b + sms(k,idchl) + +!____________________________________________________________ +!< Diatom Si + +!< lossN_d: Diatom loss of organic nitrogen compunds [day^-1] +!< When N : C ratio becomes too high, excretion is downregulated +!< by the limiter function limitFacN_dia +!< aggregationRate transfers Si to the detritus pool + + sms(k,idiasi) = ( & + + Si_assim * DiaC & ! -- Diatom silicon assimilation + - lossN_d * limitFacN_dia * DiaSi & ! -- Excretion to detritus + - aggregationRate * DiaSi & ! -- Aggregation loss + - grazingFlux_dia * qSiN & ! -- Grazing loss +#if defined (__3Zoo2Det) + - grazingFlux_dia2 * qSiN & + - grazingFlux_dia3 * qSiN & ! 3Zoo +#endif + ) * dt_b + sms(k,idiasi) + +!< *** Coccolithophore *** +!< *********************** + +#if defined (__coccos) +!____________________________________________________________ +!< Coccolithophore N + sms(k,icocn) = ( & + + N_assim_cocco * CoccoC & + - lossN_c * limitFacN_cocco * CoccoN & + - aggregationRate * CoccoN & + - grazingFlux_Cocco & +#if defined (__3Zoo2Det) + - grazingFlux_Cocco2 & + - grazingFlux_Cocco3 & ! 3Zoo +#endif + ) * dt_b + sms(k,icocn) + +!____________________________________________________________ +!< Coccolithophore C + + sms(k,icocc) = ( & + + Cphot_cocco * CoccoC & + - lossC_c * limitFacN_cocco * CoccoC & + - phyRespRate_cocco * CoccoC & + - aggregationRate * CoccoC & + - grazingFlux_cocco * recipQuota_cocco & +#if defined (__3Zoo2Det) + - grazingFlux_Cocco2 * recipQuota_cocco & + - grazingFlux_Cocco3 * recipQuota_cocco & ! 3Zoo +#endif + ) * dt_b + sms(k,icocc) + + if(sms(k,icocc)>100) then + print*,'ERROR: strange CoccoC !' + print*,'k= ', k + print*,'dt= ', dt + print*,'dt_b= ', dt_b + print*,'state(k,icocc): ', state(k,icocc) + print*,'sms CoccoC: ', CoccoC + print*,'sms CoccoN: ', CoccoN + print*,'sms Cphot cocco: ', Cphot_cocco*CoccoC + print*,'sms lossC_c: ', lossC_c + print*,'sms limitFacN_cocco: ', limitFacN_cocco + print*,'sms phyRespRate_cocco: ', phyRespRate_cocco + print*,'sms grazingFlux_cocco: ', grazingFlux_cocco + print*,'sms grazingFlux_cocco2: ', grazingFlux_Cocco2 + print*,'sms grazingFlux_cocco3: ', grazingFlux_Cocco3 + print*,'sms recipQuota_cocco: ', recipQuota_cocco + + print*,'sms recipQuota_cocco: ', recipQuota_cocco + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + endif + +!____________________________________________________________ +!< Coccolithophore Chl + + sms(k,icchl) = ( & + + ChlSynth_cocco * CoccoC & + - KOchl_cocco * CoccoChl & + - aggregationRate * CoccoChl & + - grazingFlux_cocco * Chl2N_cocco & +#if defined (__3Zoo2Det) + - grazingFlux_Cocco2 * Chl2N_cocco & + - grazingFlux_Cocco3 * Chl2N_cocco & ! 3Zoo +#endif + ) * dt_b + sms(k,icchl) +#endif + +!< *** Silicate *** +!< **************** + +!____________________________________________________________ +!< Detritus Si +#if defined (__3Zoo2Det) + sms(k,idetsi) = ( & + + aggregationRate * DiaSi & + + lossN_d * limitFacN_dia * DiaSi & + + grazingFlux_dia3 * qSiN & + - reminSiT * DetSi & + ) * dt_b + sms(k,idetsi) +#else + sms(k,idetsi) = ( & + + aggregationRate * DiaSi & + + lossN_d * limitFacN_dia * DiaSi & + + grazingFlux_dia * qSiN & + - reminSiT * DetSi & + ) * dt_b + sms(k,idetsi) +#endif +!____________________________________________________________ +!< DSi, Silicate + +!< DiaC: Intracellular carbon concentration in diatoms [mmolC m-3] +!< DetSi: Detritus silicon concentration [mmolSi m-3] +!< Si_assim: Si assimilation rate for diatoms [mmolSi mmolC-1 day-1] +!< reminSiT: Remineralization rate of silicon, temperature dependency [day-1] +!< dt_b: REcoM time step [day] + +!! Schourup 2013 Eq. A3 + + sms(k,isi) = ( & + - Si_assim * DiaC & ! --> Si assimilation of diatoms + + reminSiT * DetSi & ! --> Remineralization of detritus, temperature dependent +#if defined (__3Zoo2Det) + + reminSiT * DetZ2Si & +#endif + ) * dt_b + sms(k,isi) +!< *** Iron *** +!< ************ + +!____________________________________________________________ +!< Fe + +!< Fe2N: Intracellular Fe : N ratio [μmol Fe mmol N^-1] Fe2N = Fe2C * 6.625 +!< PhyC: Intracellular carbon concentration in nanophytoplankton [mmolCm^-3] +!< Cphot: C-specific actual rate of photosynthesis for nanopyhtoplankton [day^-1] +!< DiaC: Intracellular carbon concentration in diatoms [mmol C m^-3 ] +!< Cphot_dia: C-specific actual rate of photosynthesis for diatom [day^-1] +!< phyRespRate: Nanopyhtoplankton respiration rate [day^-1] +!< phyRespRate_dia: Diatom respiration rate [day^-1] +!< lossC: Nanopyhtoplankton excretion of organic C [day^-1] +!< limitFacN: limiting factor +!< lossC_d: Diatom excretion of organic C [day^-1] +!< limitFacN_dia: limiting factor +!< detC: Detritus carbon concentration [mmol C m^-3] +!< reminC: Temperature dependent remineralisation rate of detritus [day^-1] +!< arrFunc: Arrhenius function +!< hetC: Zooplankton carbon concentration [mmol C m^-3 ] +!< lossC_z: Zooplankton excretion of organic C [day^-1 ] +!< hetRespFlux: Zooplankton respiration rate [day^-1] +!< kScavFe: Scavenging rate of iron [m3 mmol C^-1 day^-1] + + sms(k,ife) = ( Fe2N * ( & + - N_assim * PhyC & ! --> N assimilation Nanophytoplankton, [mmol N/(mmol C * day)] C specific N utilization rate + - N_assim_dia * DiaC & ! --> N assimilation Diatom +#if defined (__coccos) + - N_assim_cocco * CoccoC & + + lossN_c * limitFacN_cocco * CoccoN & +#endif + + lossN * limitFacN * PhyN & ! --> Excretion from small pythoplankton + + lossN_d * limitFacN_dia * DiaN & ! --> Excretion from diatom + + reminN * arrFunc * O2Func * DetN & ! --> Remineralization of detritus ! NEW O2remin + + lossN_z * HetN & ! --> Excretion from zooplankton +#if defined (__3Zoo2Det) + + reminN * arrFunc * O2Func * DetZ2N & ! O2remin + + lossN_z2 * Zoo2N & + + lossN_z3 * MicZooN & ! 3Zoo +#endif + ) & + - kScavFe * DetC * FreeFe & +#if defined (__3Zoo2Det) + - kScavFe * DetZ2C * FreeFe & +#endif + ) * dt_b + sms(k,ife) + +!< *** Calcification *** +!< ********************* + +!____________________________________________________________ +!< Small phytoplankton calcite + +#if defined (__coccos) + sms(k,iphycal) = ( & + + calcification & ! --> Calcification + - lossC_c * limitFacN_cocco * PhyCalc & ! --> Excretion loss + - phyRespRate_cocco * PhyCalc & ! --> Respiration + - calc_loss_agg & ! --> Aggregation loss + - calc_loss_gra & ! --> Grazing loss +#if defined (__3Zoo2Det) + - calc_loss_gra2 & + - calc_loss_gra3 & ! 3Zoo +#endif + ) * dt_b + sms(k,iphycal) +#else + sms(k,iphycal) = ( & + + calcification & ! --> Calcification + - lossC * limitFacN * PhyCalc & ! --> Excretion loss + - phyRespRate * PhyCalc & ! --> Respiration + - calc_loss_agg & ! --> Aggregation loss + - calc_loss_gra & ! --> Grazing loss +#if defined (__3Zoo2Det) + - calc_loss_gra2 & + - calc_loss_gra3 & ! 3Zoo +#endif + ) * dt_b + sms(k,iphycal) +#endif + +!____________________________________________________________ +! Detritus calcite +#if defined (__coccos) + +#if defined (__3Zoo2Det) + sms(k,idetcal) = ( & + + lossC_c * limitFacN_cocco * PhyCalc & + + phyRespRate_cocco * PhyCalc & + + calc_loss_agg & + + calc_loss_gra3 & + - calc_loss_gra3 * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + +#else + sms(k,idetcal) = ( & + + lossC_c * limitFacN_cocco * PhyCalc & + + phyRespRate_cocco * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) + +#endif + +#else + +#if defined (__3Zoo2Det) + sms(k,idetcal) = ( & + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra3 & + - calc_loss_gra3 * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) +#else + sms(k,idetcal) = ( & + + lossC * limitFacN * PhyCalc & + + phyRespRate * PhyCalc & + + calc_loss_agg & + + calc_loss_gra & + - calc_loss_gra * calc_diss_guts & + - calc_diss * DetCalc & + ) * dt_b + sms(k,idetcal) +#endif +#endif + +!____________________________________________________________ +! Oxygen + + sms(k,ioxy) = ( & + + Cphot * phyC & + - phyRespRate * phyC & + + Cphot_dia * diaC & + - phyRespRate_dia * diaC & +#if defined (__coccos) + + Cphot_cocco * CoccoC & + - phyRespRate_cocco * CoccoC & +#endif + - rho_C1 * arrFunc * O2Func * EOC & ! O2remin + - hetRespFlux & +#if defined (__3Zoo2Det) + - Zoo2RespFlux & + - MicZooRespFlux & ! 3Zoo +#endif + ) * redO2C * dt_b + sms(k,ioxy) +! + if (ciso) then +!------------------------------------------------------------------------------- +! DIC_13 + sms(k,idic_13) = ( & + - Cphot * PhyC_13 & + + phyRespRate * PhyC_13 & + - Cphot_Dia * DiaC_13 & + + phyRespRate_Dia * DiaC_13 & + + rho_C1 * arrFunc * EOC_13 & + + HetRespFlux_13 & + + calc_diss_13 * DetCalc_13 & + + calc_loss_gra_13 * calc_diss_guts & + - calcification_13 & + ) * dt_b + sms(k,idic_13) +!------------------------------------------------------------------------------- +! Phytoplankton C_13 + sms(k,iphyc_13) = ( & + + Cphot * PhyC_13 & + - lossC * limitFacN * PhyC_13 & + - phyRespRate * PhyC_13 & + - aggregationRate * PhyC_13 & + - grazingFlux_phy * recipQuota_13 & + ) * dt_b + sms(k,iphyc_13) +!------------------------------------------------------------------------------- +! Detritus C_13 + sms(k,idetc_13) = ( & + + grazingFlux_phy * recipQuota_13 & + - grazingFlux_phy * recipQuota_13 * grazEff & + + grazingFlux_Dia * recipQuota_dia_13 & + - grazingFlux_Dia * recipQuota_dia_13 * grazEff & + + aggregationRate * phyC_13 & + + aggregationRate * DiaC_13 & + + hetLossFlux * recipQZoo_13 & + - reminC * arrFunc * DetC_13 & + ) * dt_b + sms(k,idetc_13) +!------------------------------------------------------------------------------- +! Heterotrophic C_13 + sms(k,ihetc_13) = ( & + + grazingFlux_phy * recipQuota_13 * grazEff & + + grazingFlux_Dia * recipQuota_dia_13 * grazEff & + - hetLossFlux * recipQZoo_13 & + - lossC_z * HetC_13 & + - hetRespFlux_13 & + ) * dt_b + sms(k,ihetc_13) +!------------------------------------------------------------------------------- +! EOC_13 + sms(k,idoc_13) = ( & + + lossC * limitFacN * phyC_13 & + + lossC_d * limitFacN_dia * DiaC_13 & + + reminC * arrFunc * DetC_13 & + + lossC_z * HetC_13 & + - rho_c1 * arrFunc * EOC_13 & + + LocRiverDOC * r_iorg_13 & + ) * dt_b + sms(k,idoc_13) +!------------------------------------------------------------------------------- +! Diatom C_13 + sms(k,idiac_13) = ( & + + Cphot_dia * DiaC_13 & + - lossC_d * limitFacN_dia * DiaC_13 & + - phyRespRate_dia * DiaC_13 & + - aggregationRate * DiaC_13 & + - grazingFlux_dia * recipQuota_dia_13 & + ) * dt_b + sms(k,idiac_13) +!------------------------------------------------------------------------------- +! Small phytoplankton calcite_13 + sms(k,iphycal_13) = ( & + + calcification_13 & + - lossC * limitFacN * phyCalc_13 & + - phyRespRate * phyCalc_13 & + - calc_loss_agg_13 & + - calc_loss_gra_13 & + ) * dt_b + sms(k,iphycal_13) +!------------------------------------------------------------------------------- +! Detritus calcite_13 + sms(k,idetcal_13) = ( & + + lossC * limitFacN * phyCalc_13 & + + phyRespRate * phyCalc_13 & + + calc_loss_agg_13 & + + calc_loss_gra_13 & + - calc_loss_gra_13 * calc_diss_guts & + - calc_diss_13 * DetCalc_13 & + ) * dt_b + sms(k,idetcal_13) +!------------------------------------------------------------------------------- + if (ciso_14) then +!------------------------------------------------------------------------------- + if (ciso_organic_14) then +! 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) +!------------------------------------------------------------------------------- +! Phytoplankton C_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) +!------------------------------------------------------------------------------- +! Detritus C_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) +!------------------------------------------------------------------------------- +! Heterotrophic C_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) +!------------------------------------------------------------------------------- +! Diatom C_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) +!------------------------------------------------------------------------------- +! Small phytoplankton calcite_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) +!------------------------------------------------------------------------------- +! Detritus calcite_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, identical to DIC except for radioactive decay (-> +! recom_forcing) + sms(k,idic_14) = sms(k,idic) + end if ! ciso_organic_14 + end if ! ciso_14 + end if ! ciso +!------------------------------------------------------------------------------- +! 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 + +!------------------------------------------------------------------------------- +! Remineralization from the sediments into the bottom layer + + if (use_MEDUSA .and. (sedflx_num .ne. 0)) then + if (mype==0) then !OG + write(*,*) ' --> Sedimentary input of nutrients through MEDUSA' + endif + + else ! not use_MEDUSA or sedflx_num = 0 +!*** 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) + +!*** 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 + +!*** 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 + +!*** 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 + + if (ciso) then +!*** DIC_13 *** We ignore isotopic fractionation during remineralization. + decayBenthos(5) = alpha_dcal_13 * decayRateBenC * LocBenthos(5) + LocBenthos(5) = LocBenthos(5) - decayBenthos(5) * dt_b +!*** Calc: DIC_13 *** + decayBenthos(6) = calc_diss_13 * LocBenthos(6) + LocBenthos(6) = LocBenthos(6) - decayBenthos(6) * dt_b ! / depth of benthos + if (ciso_14) then + if (ciso_organic_14) then +!*** DIC_14 *** We ignore isotopic fractionation during remineralization. + decayBenthos(7) = alpha_dcal_14 * decayRateBenC * LocBenthos(7) + LocBenthos(7) = LocBenthos(7) - decayBenthos(7) * dt_b +!*** Calc: DIC_14 *** + decayBenthos(8) = calc_diss_14 * LocBenthos(8) + LocBenthos(8) = LocBenthos(8) - decayBenthos(8) * dt_b ! / depth of benthos + else +! Do nothing here because sms(idic_14) is defined as sms(idic) further +! above + end if ! ciso_organic_14 + end if ! ciso_14 + end if ! ciso + endif ! use_MEDUSA + + end do ! Main time loop ends + + +end subroutine REcoM_sms + +!------------------------------------------------------------------------------- +! Function for calculating limiter +!------------------------------------------------------------------------------- + +function recom_limiter(slope,qa,qb) + use recom_config + Implicit None + 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) + else + recom_limiter = 1.d0 - exp( -slope*( abs(dq)-dq )**2) + endif + return + end + +!------------------------------------------------------------------------------- +! Function for iron chemistry +!------------------------------------------------------------------------------- +function iron_chemistry_2ligands(fet,l1t,l2t,k1,k2) + implicit none + + Real(kind=8) :: iron_chemistry_2ligands + Real(kind=8) :: l1t,l2t,fet,k1,k2 + Real(kind=8) :: a3,a2,a1,a0,a,b,c,p,q,discr,rho,phi,amp,pi + Real(kind=8) :: one3rd, one27th + Real(kind=8) :: fe1,fe2,fe3 + +! coefficients of the 4th-order polynomial + a3 = k1*k2 + a2 = ( k1*k2*(l1t + l2t - fet) + k1 + k2 ) + a1 = ( 1 - (k1 + k2)*fet + k1*l1t + k2*l2t ) + a0 = -fet + +! coefficients of the normalized polynomial + a = a2/a3 + b = a1/a3 + c = a0/a3 + +! some numbers that are used several times + one3rd = 1.0/3.0 + one27th = 1.0/27.0 + +! now solve the polynomial stepwise + p = b - a*a*one3rd + q = c - a*b*one3rd + 2.0*a*a*a*one27th + discr = q*q/4.0 + p*p*p*one27th + + rho = sqrt(-(p*p*p*one27th)) + phi = acos(-q/(2.0*rho)) + amp = 2.0*rho**one3rd + pi = 3.1415926535897931 + +! the equation has three real roots + fe1 = amp*cos(phi*one3rd) - a*one3rd + fe2 = amp*cos((phi + 2.0*pi)*one3rd) - a*one3rd + fe3 = amp*cos((phi + 4.0*pi)*one3rd) - a*one3rd + + iron_chemistry_2ligands = max(fe1,fe2,fe3) + +end function iron_chemistry_2ligands +!------------------------------------------------------------------------------- +function iron_chemistry(Fe, totalLigand, ligandStabConst) + implicit none + + Real(kind=8) :: iron_chemistry + Real(kind=8) :: Fe, totalLigand, ligandStabConst ! Input + Real(kind=8) :: FreeFe ! Output + Real(kind=8) :: ligand,FeL,a,b,c,discrim + +! Abbrevations + a = 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 + freeFe = Fe - FeL + else ! No free iron + freeFe = 0.d0 + end if + + iron_chemistry = freeFe + + return + end function iron_chemistry + From 53c45edfc6bd9db5fc60b69d262a2be9c8a8464b Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Sun, 4 Jan 2026 21:33:58 +0100 Subject: [PATCH 49/68] DIC_PI false by default --- config/bin_2p1z1d_tp/namelist.recom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/bin_2p1z1d_tp/namelist.recom b/config/bin_2p1z1d_tp/namelist.recom index 23a264629..1aa72b9a7 100644 --- a/config/bin_2p1z1d_tp/namelist.recom +++ b/config/bin_2p1z1d_tp/namelist.recom @@ -52,7 +52,7 @@ firstyearoffesomcycle = 1958 ! The first year of the actual physical forc lastyearoffesomcycle = 2022 ! Last year of the actual physical forcing used numofCO2cycles = 1 ! Number of cycles of the forcing planned currentCO2cycle = 1 ! Which CO2 cycle we are currently running -DIC_PI = .true. +DIC_PI = .false. 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) From aa514b1d6589b3391cc861e5234ce7ff1d36eceb Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 7 Jan 2026 13:19:04 +0100 Subject: [PATCH 50/68] updating namelists and grouping iron chesmitry paramters in namelist.recom --- config/bin_2p1z1d_tp/namelist.config | 4 +- config/bin_2p1z1d_tp/namelist.forcing | 5 +- config/bin_2p1z1d_tp/namelist.io | 421 ++++++++++++++++++++------ config/bin_2p1z1d_tp/namelist.recom | 71 +++-- config/bin_2p1z1d_tp/namelist.tra | 48 +-- src/fesom_module.F90 | 1 - src/int_recom/recom_modules.F90 | 5 +- 7 files changed, 401 insertions(+), 154 deletions(-) diff --git a/config/bin_2p1z1d_tp/namelist.config b/config/bin_2p1z1d_tp/namelist.config index 408c6d241..d647c36cc 100644 --- a/config/bin_2p1z1d_tp/namelist.config +++ b/config/bin_2p1z1d_tp/namelist.config @@ -46,8 +46,8 @@ yearnew = 2000 ! initial year ! MESH, INITIALIZATION & OUTPUT PATHS ! ============================================================================ &paths -MeshPath = '/pool/data/AWICM/FESOM2/MESHES_FESOM2.1/core2/' ! path to mesh files (nod2d.out, elem2d.out, etc.) -ClimateDataPath = '/pool/data/AWICM/FESOM2/INITIAL/phc3.0/' ! path to initial conditions (temperature, salinity) +MeshPath = '/albedo/work/projects/p_recompdaf/frbunsen/FESOM2/meshes/core2/' ! path to mesh files (nod2d.out, elem2d.out, etc.) +ClimateDataPath = '/albedo/work/user/yye/fesom2/initial_files/pi_init/' ! path to initial conditions (temperature, salinity) ResultPath = './' ! path for output files and fesom.clock file / diff --git a/config/bin_2p1z1d_tp/namelist.forcing b/config/bin_2p1z1d_tp/namelist.forcing index 44cdf3b74..31d9b31ab 100644 --- a/config/bin_2p1z1d_tp/namelist.forcing +++ b/config/bin_2p1z1d_tp/namelist.forcing @@ -83,6 +83,7 @@ age_start_year = 2000 ! year to start age tracer (tracer age = 0 at this nm_xwind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/uas.clim61' ! name of file with zonal wind speeds nm_ywind_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with meridional wind speeds nm_xstre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/huss.clim61' ! name of file with zonal wind stress + nm_ystre_file = '/albedo/work/projects/MarESys/FROM-OLLIE/forcing_JRA55-do-v1.4.0_clim61/vas.clim61' ! name of file with meridional wind stress 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 @@ -114,6 +115,8 @@ age_start_year = 2000 ! year to start age tracer (tracer age = 0 at this ! --- Enable/disable individual forcing fields --- l_xwind = .true. ! use zonal wind forcing l_ywind = .true. ! use meridional wind forcing + l_xstre = .false. ! use zonal wind forcing + l_ystre = .false. ! use meridional wind forcing l_humi = .true. ! use specific humidity forcing l_qsr = .true. ! use shortwave radiation forcing l_qlw = .true. ! use longwave radiation forcing @@ -132,7 +135,7 @@ age_start_year = 2000 ! year to start age tracer (tracer age = 0 at this nm_sss_data_file = '/albedo/pool/FESOM/forcing/CORE2/PHC2_salx.nc' ! path to SSS restoring data file, e.g. PHC2_salx.nc ! --- Chlorophyll data for shortwave penetration --- - chl_data_source = 'Sweeney' ! chlorophyll data source: 'Sweeney' (monthly climatology) or 'None' (constant) + chl_data_source = 'None' ! chlorophyll data source: 'Sweeney' (monthly climatology) or 'None' (constant) ! requires use_sw_pene=.true. in namelist.config nm_chl_data_file = '/pool/data/AWICM/FESOM2/FORCING/Sweeney/Sweeney_2005.nc' ! chlorophyll data file (if Sweeney) chl_const = 0.1 ! constant chlorophyll concentration [mg/m³] (if chl_data_source='None') diff --git a/config/bin_2p1z1d_tp/namelist.io b/config/bin_2p1z1d_tp/namelist.io index 136296676..2f68c6701 100644 --- a/config/bin_2p1z1d_tp/namelist.io +++ b/config/bin_2p1z1d_tp/namelist.io @@ -1,108 +1,343 @@ +! ============================================================================ +! ============ Namelist file for FESOM2 output configuration ================= +! ============================================================================ +! This file contains configuration for model output and diagnostics: +! - Diagnostic flags for optional output fields +! - General output settings (compression, rotation) +! - Output variable list with frequency and precision +! - Complete catalog of all available output fields +! +! See the output catalog at the end of this file for all possible variables. +! Some outputs require specific flags in &diag_list or other namelists. +! ============================================================================ + +! ============================================================================ +! DIAGNOSTIC FLAGS +! ============================================================================ +! Enable/disable optional diagnostic computations and outputs. +! Setting these to .true. enables additional output fields (see catalog below). +! ============================================================================ &diag_list -ldiag_solver =.false. -lcurt_stress_surf=.false. -ldiag_curl_vel3 =.false. -ldiag_Ri =.false. -ldiag_turbflux =.false. -ldiag_salt3D =.false. -ldiag_dMOC =.false. -ldiag_DVD =.false. -ldiag_forc =.false. -ldiag_extflds =.false. +ldiag_solver = .false. ! enables solver diagnostics (convergence, iterations) +lcurt_stress_surf = .false. ! enables 'curl_surf' output (vorticity of surface stress) +ldiag_curl_vel3 = .false. ! enables 'curl_u' output (relative vorticity from 3D velocity) +ldiag_Ri = .false. ! enables Richardson number diagnostics ('shear', 'Ri') +ldiag_turbflux = .false. ! enables turbulent flux diagnostics ('KvdTdz', 'KvdSdz') +ldiag_salt3D = .false. ! enables 3D salinity diagnostics +ldiag_dMOC = .false. ! enables 'dMOC' output (density MOC diagnostics) +ldiag_DVD = .false. ! enables 'DVD' output (Discrete Variance Decay diagnostics) +ldiag_forc = .false. ! enables 'FORC' output (comprehensive forcing diagnostics) +ldiag_extflds = .false. ! enables extended field diagnostics +ldiag_destine = .false. ! enables heat content computation ('hc300m', 'hc700m', 'hc') +ldiag_trflx = .false. ! enables tracer flux diagnostics ('utemp', 'vtemp', 'usalt', 'vsalt') +ldiag_uvw_sqr = .false. ! enables 'UVW_SQR' output (squared velocities: u2, v2, w2) +ldiag_trgrd_xyz = .false. ! enables 'TRGRD_XYZ' output (horizontal & vertical tracer gradients) / +! ============================================================================ +! GENERAL OUTPUT SETTINGS +! ============================================================================ &nml_general -io_listsize =100 !number of streams to allocate. shallbe large or equal to the number of streams in &nml_list -vec_autorotate =.false. +io_listsize = 120 ! total number of streams to allocate. Shall be larger or equal to the number of streams in &nml_list (max. 150) +vec_autorotate = .false. ! unrotate vector fields (velocities, winds) before writing to output files +compression_level = 1 ! compression level for netCDF output (1=fastest, 9=smallest) / -! for sea ice related variables use_ice should be true, otherewise there will be no output -! for 'curl_surf' to work lcurt_stress_surf must be .true. otherwise no output -! for 'fer_C', 'bolus_u', 'bolus_v', 'bolus_w', 'fer_K' to work Fer_GM must be .true. otherwise no output -! 'otracers' - all other tracers if applicable -! for 'dMOC' to work ldiag_dMOC must be .true. otherwise no output +! ============================================================================ +! OUTPUT VARIABLE LIST +! ============================================================================ +! Format: 'variable_id', frequency, unit, precision +! frequency = output frequency (integer) +! unit = 'y' (yearly), 'm' (monthly), 'd' (daily), 'h' (hourly), 's' (steps) +! precision = 4 (single precision) or 8 (double precision) +! ============================================================================ &nml_list -io_list = 'sst ',1, 'd', 4, -! 'sss ',1, 'd', 4, -! 'ssh ',1, 'd', 4, -! 'uice ',1, 'd', 4, -! 'vice ',1, 'd', 4, -! 'a_ice ',1, 'd', 4, -! 'd_ice ',1, 'm', 4, -! 'd_snow ',1, 'm', 4, -! 'MLD1 ',1, 'm', 4, -! 'MLD2 ',1, 'm', 4, -! 'MLD3 ',1, 'm', 4, +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, 'd', 4, - 'salt ',1, 'd', 8, - 'otracers ',1, 'd', 4, + 'temp ',1, 'm', 4, + 'salt ',1, 'm', 8, ! 'N2 ',1, 'm', 4, ! 'Kv ',1, 'm', 4, -! 'u ',1, 'm', 4, -! 'v ',1, 'm', 4, + 'u ',1, 'm', 4, + 'v ',1, 'm', 4, ! 'unod ',1, 'm', 4, ! 'vnod ',1, 'm', 4, -! 'w ',1, 'm', 4, + 'w ',1, 'm', 4, ! 'Av ',1, 'm', 4, -! 'bolus_u ',1, 'm', 4, -! 'bolus_v ',1, 'm', 4, -! 'bolus_w ',1, 'm', 4, -! 'dpCO2s ',1, 'm', 4, -! 'pCO2s ',1, 'm', 4, -! 'CO2f ',1, 'm', 4, -! 'Hp ',1, 'm', 4, -! 'aFe ',1, 'm', 4, -! 'aN ',1, 'm', 4, -! 'denb ',1, 'm', 4, -! 'benN ',1, 'm', 4, -! 'benC ',1, 'm', 4, -! 'benSi ',1, 'm', 4, -! 'benCalc ',1, 'm', 4, -! 'Chldegd ',1, 'm', 4, -! 'Chldegn ',1, 'm', 4, -! 'NNAd ',1, 'm', 4, -! 'NNAn ',1, 'm', 4, -! 'GPPd ',1, 'm', 4, -! 'GPPn ',1, 'm', 4, -! 'NPPd ',1, 'm', 4, -! 'NPPn ',1, 'm', 4, -! 'NPPc ',1, 'm', 4, -! 'GPPc ',1, 'm', 4, -! 'NNAc ',1, 'm', 4, -! 'Chldegc ',1, 'm', 4, -! 'sinkPON ',1, 'y', 4, -! 'sinkPOC ',1, 'y', 4, -! 'sinkOpal ',1, 'y', 4, -! 'sinkCalc ',1, 'y', 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, -! 'OdegaC ',1, 'm', 4, -! 'kspc ',1, 'm', 4, -! 'rhoSW ',1, 'm', 4, -! 'wsink_det1',1, 'm', 8, -! 'wsink_det2',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, + 'bolus_u ',1, 'm', 4, + 'bolus_v ',1, 'm', 4, + 'bolus_w ',1, 'm', 4, +! 'fw ',1, 'm', 4, +! 'fh ',1, 'm', 4, + 'otracers ',1, 'm', 4, / + +! ============================================================================ +! COMPLETE CATALOG OF ALL POSSIBLE OUTPUT FIELDS +! ============================================================================ +! Below is a comprehensive list of all valid io_list IDs available in FESOM2. +! To enable any field, copy the line to the &nml_list section above. +! NOTE: Some fields require specific flags to be enabled (see comments). +! ============================================================================ + +! --- 2D OCEAN SURFACE FIELDS --- +! 'sst ',1, 'm', 4, ! sea surface temperature [C] +! 'sss ',1, 'm', 4, ! sea surface salinity [psu] +! 'ssh ',1, 'm', 4, ! sea surface elevation [m] +! 'vve_5 ',1, 'm', 4, ! vertical velocity at 5th level [m/s] +! 't_star ',1, 'm', 4, ! air temperature [C] +! 'qsr ',1, 'm', 4, ! solar radiation [W/s^2] + +! --- 3D OCEAN FIELDS --- +! 'temp ',1, 'm', 4, ! temperature [C] +! 'salt ',1, 'm', 8, ! salinity [psu] +! 'sigma0 ',1, 'm', 4, ! potential density [kg/m3] +! 'u ',1, 'm', 4, ! zonal velocity [m/s] +! 'v ',1, 'm', 4, ! meridional velocity [m/s] +! 'unod ',1, 'm', 4, ! zonal velocity at nodes [m/s] +! 'vnod ',1, 'm', 4, ! meridional velocity at nodes [m/s] +! 'w ',1, 'm', 4, ! vertical velocity [m/s] +! 'otracers ',1, 'm', 4, ! all other tracers if applicable +! 'age ',1, 'm', 4, ! water age tracer [year] (require use_age_tracer=.true.) + +! --- 2D SSH DIAGNOSTIC VARIABLES --- +! 'ssh_rhs ',1, 'm', 4, ! ssh rhs [m/s] +! 'ssh_rhs_old',1, 'm', 4, ! ssh rhs old [m/s] +! 'd_eta ',1, 'm', 4, ! dssh from solver [m] +! 'hbar ',1, 'm', 4, ! ssh n+0.5 tstep [m] +! 'hbar_old ',1, 'm', 4, ! ssh n-0.5 tstep [m] +! 'dhe ',1, 'm', 4, ! dhbar @ elem [m] + +! --- SEA ICE FIELDS (require use_ice=.true.) --- +! 'uice ',1, 'm', 4, ! ice velocity x [m/s] +! 'vice ',1, 'm', 4, ! ice velocity y [m/s] +! 'a_ice ',1, 'm', 4, ! ice concentration [%] +! 'm_ice ',1, 'm', 4, ! ice height per unit area [m] +! 'thdgrice ',1, 'm', 4, ! thermodynamic growth rate ice [m/s] +! 'thdgrarea ',1, 'm', 4, ! thermodynamic growth rate ice concentration [frac/s] +! 'dyngrarea' ,1, 'm', 4, ! dynamic growth rate ice concentration [frac/s] +! 'dyngrice ',1, 'm', 4, ! dynamic growth rate ice [m/s] +! 'thdgrsn ',1, 'm', 4, ! thermodynamic growth rate snow [m/s] +! 'dyngrsnw ',1, 'm', 4, ! dynamic growth rate snow [m/s] +! 'flice ',1, 'm', 4, ! flooding growth rate ice [m/s] +! 'm_snow ',1, 'm', 4, ! snow height per unit area [m] +! 'h_ice ',1, 'm', 4, ! ice thickness over ice-covered fraction [m] +! 'h_snow ',1, 'm', 4, ! snow thickness over ice-covered fraction [m] +! 'fw_ice ',1, 'm', 4, ! fresh water flux from ice ['m/s'] +! 'fw_snw ',1, 'm', 4, ! fresh water flux from snow ['m/s'] + +! --- SEA ICE DEBUG VARIABLES (require use_ice=.true.) --- +! 'strength_ice',1, 'm', 4, ! ice strength [?] +! 'inv_areamass',1, 'm', 4, ! inv_areamass [?] +! 'rhs_a ',1, 'm', 4, ! rhs_a [?] +! 'rhs_m ',1, 'm', 4, ! rhs_m [?] +! 'sgm11 ',1, 'm', 4, ! sgm11 [?] +! 'sgm12 ',1, 'm', 4, ! sgm12 [?] +! 'sgm22 ',1, 'm', 4, ! sgm22 [?] +! 'eps11 ',1, 'm', 4, ! eps11 [?] +! 'eps12 ',1, 'm', 4, ! eps12 [?] +! 'eps22 ',1, 'm', 4, ! eps22 [?] +! 'u_rhs_ice ',1, 'm', 4, ! u_rhs_ice [?] +! 'v_rhs_ice ',1, 'm', 4, ! v_rhs_ice [?] +! 'metric_fac',1, 'm', 4, ! metric_fac [?] +! 'elevat_ice',1, 'm', 4, ! elevat_ice [?] +! 'uwice ',1, 'm', 4, ! uwice [?] +! 'vwice ',1, 'm', 4, ! vwice [?] +! 'twice ',1, 'm', 4, ! twice [?] +! 'swice ',1, 'm', 4, ! swice [?] + +! --- MIXED LAYER DEPTH --- +! 'MLD1 ',1, 'm', 4, ! Mixed Layer Depth [m] Large et al. 1997, bvfreq(nz, node) > db_max +! 'MLD2 ',1, 'm', 4, ! Mixed Layer Depth [m] Levitus treshold, rhopot(nz)-rhopot(1) > 0.125_WP kg/m +! 'MLD3 ',1, 'm', 4, ! Mixed Layer Depth [m] Griffies 2016 , rhopot(nz)-rhopot(1) > 0.03_WP kg/m + +! --- HEAT CONTENT (require ldiag_destine=.true.) --- +! 'hc300m ',1, 'm', 4, ! Vertically integrated heat content upper 300m [J m**-2] +! 'hc700m ',1, 'm', 4, ! Vertically integrated heat content upper 700m [J m**-2] +! 'hc ',1, 'm', 4, ! Vertically integrated heat content total column [J m**-2] + +! --- WATER ISOTOPES IN SEA ICE (require lwiso=.true.) --- +! 'h2o18_ice ',1, 'm', 4, ! h2o18 concentration in sea ice [kmol/m**3] +! 'hDo16_ice ',1, 'm', 4, ! hDo16 concentration in sea ice [kmol/m**3] +! 'h2o16_ice ',1, 'm', 4, ! h2o16 concentration in sea ice [kmol/m**3] + +! --- FRESHWATER FLUX (require use_landice_water=.true.) --- +! 'landice ',1, 'm', 4, ! freshwater flux [m/s] + +! --- SURFACE FORCING --- +! 'tx_sur ',1, 'm', 4, ! zonal wind str. to ocean [N/m2] +! 'ty_sur ',1, 'm', 4, ! meridional wind str. to ocean [N/m2] +! 'curl_surf ',1, 'm', 4, ! vorticity of the surface stress [none] (require lcurt_stress_surf=.true.) +! 'fh ',1, 'm', 4, ! heat flux [W/m2] +! 'fw ',1, 'm', 4, ! fresh water flux [m/s] +! 'atmice_x ',1, 'm', 4, ! stress atmice x [N/m2] +! 'atmice_y ',1, 'm', 4, ! stress atmice y [N/m2] +! 'atmoce_x ',1, 'm', 4, ! stress atmoce x [N/m2] +! 'atmoce_y ',1, 'm', 4, ! stress atmoce y [N/m2] +! 'iceoce_x ',1, 'm', 4, ! stress iceoce x [N/m2] +! 'iceoce_y ',1, 'm', 4, ! stress iceoce y [N/m2] +! 'alpha ',1, 'm', 4, ! thermal expansion [none] +! 'beta ',1, 'm', 4, ! saline contraction [none] +! 'dens_flux ',1, 'm', 4, ! density flux [kg/(m3*s)] +! 'runoff ',1, 'm', 4, ! river runoff [m/s] +! 'evap ',1, 'm', 4, ! evaporation [m/s] +! 'prec ',1, 'm', 4, ! precipitation rain [m/s] +! 'snow ',1, 'm', 4, ! precipitation snow [m/s] +! 'tair ',1, 'm', 4, ! surface air temperature [°C] +! 'shum ',1, 'm', 4, ! specific humidity [] +! 'swr ',1, 'm', 4, ! short wave radiation [W/m^2] +! 'lwr ',1, 'm', 4, ! long wave radiation [W/m^2] +! 'uwind ',1, 'm', 4, ! 10m zonal surface wind velocity [m/s] +! 'vwind ',1, 'm', 4, ! 10m merid. surface wind velocity [m/s] +! 'virtsalt ',1, 'm', 4, ! virtual salt flux [m/s*psu] +! 'relaxsalt ',1, 'm', 4, ! relaxation salt flux [m/s*psu] +! 'realsalt ',1, 'm', 4, ! real salt flux from sea ice [m/s*psu] + +! --- KPP VERTICAL MIXING (require mix_scheme_nmb==1,17,3,37) --- +! 'kpp_obldepth',1, 'm', 4, ! KPP ocean boundary layer depth [m] +! 'kpp_sbuoyflx',1, 'm', 4, ! surface buoyancy flux [m2/s3] + +! --- RECOM 2D BIOGEOCHEMISTRY (require use_REcoM=.true. and __recom) --- +! 'dpCO2s ',1, 'm', 4, ! Difference of oceanic pCO2 minus atmospheric pCO2 [uatm] +! 'pCO2s ',1, 'm', 4, ! Partial pressure of oceanic CO2 [uatm] +! 'CO2f ',1, 'm', 4, ! CO2-flux into the surface water [mmolC/m2/d] +! 'O2f ',1, 'm', 4, ! O2-flux into the surface water [mmolO/m2/d] +! 'Hp ',1, 'm', 4, ! Mean of H-plus ions in the surface water [mol/kg] +! 'aFe ',1, 'm', 4, ! Atmospheric iron input [umolFe/m2/s] +! 'aN ',1, 'm', 4, ! Atmospheric DIN input [mmolN/m2/s] +! 'benN ',1, 'm', 4, ! Benthos Nitrogen [mmol] +! 'benC ',1, 'm', 4, ! Benthos Carbon [mmol] +! 'benSi ',1, 'm', 4, ! Benthos silicon [mmol] +! 'benCalc ',1, 'm', 4, ! Benthos calcite [mmol] +! 'NPPn ',1, 'm', 4, ! Mean NPP nanophytoplankton [mmolC/m2/d] +! 'NPPd ',1, 'm', 4, ! Mean NPP diatoms [mmolC/m2/d] +! 'GPPn ',1, 'm', 4, ! Mean GPP nanophytoplankton [mmolC/m2/d] +! 'GPPd ',1, 'm', 4, ! Mean GPP diatoms [mmolC/m2/d] +! 'NNAn ',1, 'm', 4, ! Net N-assimilation nanophytoplankton [mmolN/m2/d] +! 'NNAd ',1, 'm', 4, ! Net N-assimilation diatoms [mmolN/m2/d] +! 'Chldegn ',1, 'm', 4, ! Chlorophyll degradation nanophytoplankton [1/d] +! 'Chldegd ',1, 'm', 4, ! Chlorophyll degradation diatoms [1/d] +! 'NPPc ',1, 'm', 4, ! Mean NPP coccolithophores [mmolC/(m2*d)] +! 'GPPc ',1, 'm', 4, ! Mean GPP coccolithophores [mmolC/m2/d] +! 'NNAc ',1, 'm', 4, ! Net N-assimilation coccolithophores [mmolN/(m2*d)] +! 'Chldegc ',1, 'm', 4, ! Chlorophyll degradation coccolithophores [1/d] + +! --- RECOM 3D BIOGEOCHEMISTRY (require use_REcoM=.true. and __recom) --- +! 'PAR ',1, 'm', 4, ! PAR [W/m2] +! 'respmeso ',1, 'm', 4, ! Respiration rate of mesozooplankton [mmolC/m2/d] +! 'respmacro ',1, 'm', 4, ! Respiration rate of macrozooplankton [mmolC/m2/d] +! 'respmicro ',1, 'm', 4, ! Respiration rate of microzooplankton [mmolC/m2/d] +! 'calcdiss ',1, 'm', 4, ! Calcite dissolution [mmolC/m2/d] +! 'calcif ',1, 'm', 4, ! Calcification [mmolC/m2/d] +! 'aggn ',1, 'm', 4, ! Aggregation of small phytoplankton [mmolC/m2/d] +! 'aggd ',1, 'm', 4, ! Aggregation of diatoms [mmolC/m2/d] +! 'aggc ',1, 'm', 4, ! Aggregation of coccolithophores [mmolC/m2/d] +! 'docexn ',1, 'm', 4, ! DOC excretion by small phytoplankton [mmolC/m2/d] +! 'docexd ',1, 'm', 4, ! DOC excretion by diatoms [mmolC/m2/d] +! 'docexc ',1, 'm', 4, ! DOC excretion by coccolithophores [mmolC/m2/d] +! 'respn ',1, 'm', 4, ! Respiration by small phytoplankton [mmolC/m2/d] +! 'respd ',1, 'm', 4, ! Respiration by diatoms [mmolC/m2/d] +! 'respc ',1, 'm', 4, ! Respiration by coccolithophores [mmolC/(m2*d)] +! 'NPPn3D ',1, 'm', 4, ! Net primary production of small phytoplankton [mmolC/m2/d] +! 'NPPd3D ',1, 'm', 4, ! Net primary production of diatoms [mmolC/m2/d] +! 'NPPc3D ',1, 'm', 4, ! Net primary production of coccolithophores [mmolC/m2/d] + +! --- WATER ISOTOPES IN OCEAN (require lwiso=.true.) --- +! 'h2o18 ',1, 'm', 4, ! h2o18 concentration [kmol/m**3] +! 'hDo16 ',1, 'm', 4, ! hDo16 concentration [kmol/m**3] +! 'h2o16 ',1, 'm', 4, ! h2o16 concentration [kmol/m**3] + +! --- NEUTRAL SLOPES --- +! 'slopetap_x',1, 'm', 4, ! neutral slope tapered X [none] +! 'slopetap_y',1, 'm', 4, ! neutral slope tapered Y [none] +! 'slopetap_z',1, 'm', 4, ! neutral slope tapered Z [none] +! 'slope_x ',1, 'm', 4, ! neutral slope X [none] +! 'slope_y ',1, 'm', 4, ! neutral slope Y [none] +! 'slope_z ',1, 'm', 4, ! neutral slope Z [none] + +! --- MIXING AND DYNAMICS --- +! 'N2 ',1, 'm', 4, ! brunt väisälä [1/s2] +! 'Kv ',1, 'm', 4, ! vertical diffusivity Kv [m2/s] +! 'Av ',1, 'm', 4, ! vertical viscosity Av [m2/s] + +! --- VISCOSITY TENDENCIES (require dynamics%opt_visc==8) --- +! 'u_dis_tend',1, 'm', 4, ! horizontal velocity viscosity tendency [m/s] +! 'v_dis_tend',1, 'm', 4, ! meridional velocity viscosity tendency [m/s] +! 'u_back_tend',1, 'm', 4, ! horizontal velocity backscatter tendency [m2/s2] +! 'v_back_tend',1, 'm', 4, ! meridional velocity backscatter tendency [m2/s2] +! 'u_total_tend',1, 'm', 4,! horizontal velocity total viscosity tendency [m/s] +! 'v_total_tend',1, 'm', 4,! meridional velocity total viscosity tendency [m/s] + +! --- FERRARI/GM PARAMETERISATION (require Fer_GM=.true.) --- +! 'bolus_u ',1, 'm', 4, ! GM bolus velocity U [m/s] +! 'bolus_v ',1, 'm', 4, ! GM bolus velocity V [m/s] +! 'bolus_w ',1, 'm', 4, ! GM bolus velocity W [m/s] +! 'fer_K ',1, 'm', 4, ! GM, stirring diff. [m2/s] +! 'fer_scal ',1, 'm', 4, ! GM surface scaling [] +! 'fer_C ',1, 'm', 4, ! GM, depth independent speed [m/s] +! 'cfl_z ',1, 'm', 4, ! vertical CFL criteria [?] + +! --- DENSITY MOC DIAGNOSTICS (require ldiag_dMOC=.true.) --- +! 'dMOC ',1, 'm', 4, ! fluxes for density MOC (multiple variables) + +! --- PRESSURE GRADIENT FORCE --- +! 'pgf_x ',1, 'm', 4, ! zonal pressure gradient force [m/s^2] +! 'pgf_y ',1, 'm', 4, ! meridional pressure gradient force [m/s^2] + +! --- ALE LAYER THICKNESS --- +! 'hnode ',1, 'm', 4, ! vertice layer thickness [m] +! 'hnode_new ',1, 'm', 4, ! hnode_new [m] +! 'helem ',1, 'm', 4, ! elemental layer thickness [m] + +! --- OIFS/IFS INTERFACE (require __oifs or __ifsinterface) --- +! 'alb ',1, 'm', 4, ! ice albedo [none] +! 'ist ',1, 'm', 4, ! ice surface temperature [K] +! 'qsi ',1, 'm', 4, ! ice heat flux [W/m^2] +! 'qso ',1, 'm', 4, ! oce heat flux [W/m^2] +! 'enthalpy ',1, 'm', 4, ! enthalpy of fusion [W/m^2] +! 'qcon ',1, 'm', 4, ! conductive heat flux [W/m^2] +! 'qres ',1, 'm', 4, ! residual heat flux [W/m^2] +! 'runoff_liquid',1, 'm', 4, ! liquid water runoff [m/s] +! 'runoff_solid',1, 'm', 4, ! solid water runoff [m/s] + +! --- ICEBERG OUTPUTS (require use_icebergs=.true.) --- +! 'icb ',1, 'm', 4, ! iceberg outputs (multiple variables) + +! --- TKE MIXING DIAGNOSTICS (require mix_scheme_nmb==5 or 56) --- +! 'TKE ',1, 'm', 4, ! TKE diagnostics (multiple variables) + +! --- IDEMIX MIXING DIAGNOSTICS (require mod(mix_scheme_nmb,10)==6) --- +! 'IDEMIX ',1, 'm', 4, ! IDEMIX diagnostics (multiple variables) + +! --- TIDAL MIXING DIAGNOSTICS (require mod(mix_scheme_nmb,10)==7) --- +! 'TIDAL ',1, 'm', 4, ! TIDAL diagnostics (multiple variables) + +! --- FORCING DIAGNOSTICS (require ldiag_forc=.true.) --- +! 'FORC ',1, 'm', 4, ! forcing diagnostics (multiple variables) + +! --- DISCRETE VARIANCE DECAY (require ldiag_DVD=.true.) --- +! 'DVD ',1, 'm', 4, ! DVD diagnostics (multiple variables) + +! --- SPLIT-EXPLICIT SUBCYCLING (require dynamics%use_ssh_se_subcycl=.true.) --- +! 'SPLIT-EXPL',1, 'm', 4, ! split-explicit diagnostics (multiple variables) + +! --- SQUARED VELOCITIES (require ldiag_uvw_sqr=.true.) --- +! 'UVW_SQR ',1, 'm', 4, ! squared velocities (u2, v2, w2) + +! --- TRACER GRADIENTS (require ldiag_trgrd_xyz=.true.) --- +! 'TRGRD_XYZ ',1, 'm', 4, ! horizontal and vertical tracer gradients + +! ============================================================================ +! END OF CATALOG +! ============================================================================ diff --git a/config/bin_2p1z1d_tp/namelist.recom b/config/bin_2p1z1d_tp/namelist.recom index 1aa72b9a7..eee4d8ae2 100644 --- a/config/bin_2p1z1d_tp/namelist.recom +++ b/config/bin_2p1z1d_tp/namelist.recom @@ -2,27 +2,34 @@ &nam_rsbc fe_data_source ='Albani' -nm_fe_data_file ='/home/a/a270105/initial_files/pi_init/dust_coremesh/DustClimMonthlyAlbani.nc' -nm_aen_data_file ='/albedo/work/projects/MarESys/ogurses/input/mesh_CORE2_finaltopo_mean/AeolianNitrogenDep.nc' -nm_river_data_file ='/albedo/work/projects/MarESys/ogurses/input/mesh_CORE2_finaltopo_mean/RiverineInput.nc' -nm_erosion_data_file ='/albedo/work/projects/MarESys/ogurses/input/mesh_CORE2_finaltopo_mean/ErosionInput.nc' -nm_co2_data_file ='/albedo/work/projects/MarESys/ogurses/input/mesh_CORE2_finaltopo_mean/MonthlyAtmCO2_gcb2021.nc' +nm_fe_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/DustClimMonthlyAlbani.nc' +nm_aen_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/AeolianNitrogenDep.nc' +nm_river_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/RiverineInput.nc' +nm_erosion_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/ErosionInput.nc' +nm_co2_data_file ='/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/MonthlyAtmCO2_gcb2024.nc' / &pavariables use_REcoM =.true. REcoM_restart =.true. +recom_debug =.false. -bgc_num = 22 !33 !24 !38 +bgc_num = 22 diags3d_num = 28 ! Number of diagnostic 3d tracers to be saved bgc_base_num = 22 ! standard tracers +benthos_num = 4 ! Number of benthic BGC tracers (8 if ciso=.true., else 4) +sedflx_num = 0 ! Sediment fluxes from MEDUSA (0 = use defaults) +bottflx_num = 4 ! Bottom fluxes (8 if ciso & ciso_14, 6 if not ciso_14, 4 otherwise) + 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 = .false. @@ -34,42 +41,43 @@ 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 +use_photodamage = .false. ! 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 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 = .false. ! 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 = '/home/a/a270105/initial_files/pi_init/dust_coremesh/' -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 + +REcoMDataPath = '/albedo/work/projects/p_pool_recom/input/mesh_CORE2_finaltopo_mean/' + 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 = .false. +restore_alkalinity = .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 -fe_2ligands = .true. ! switch to consider 2 ligand classes -fe_compl_nica = .true. ! switch for pH/DOC dependent Fe-ligand binding + +use_atbox = .false. / &pasinking Vdet_a = 0.0288 ! [1/day] -Vcalc = 0.0144 ! [1/day] +Vcalc = 0.0144 ! [1/day] depth dependence of calc_diss] / &painitialization_N @@ -144,6 +152,8 @@ 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 +fe_2ligands = .true. ! switch to consider 2 ligand classes +fe_compl_nica = .true. ! switch for pH/DOC dependent Fe-ligand binding / &pazooplankton @@ -152,6 +162,7 @@ epsilonr = 0.09d0 ! [(mmol N)2 /m6] Half saturation constant f 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) +tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. pzDia = 1.0d0 !0.5d0 ! Maximum diatom preference sDiaNsq = 0.d0 pzPhy = 0.5d0 !0.25d0 !1.0d0 ! Maximum nano-phytoplankton preference (NEW: 3/12) @@ -160,29 +171,29 @@ pzCocco = 0.666d0 ! NEW (8/12) sCoccoNsq = 0.d0 ! NEW pzMicZoo = 1.0d0 ! NEW 3Zoo Maximum nano-phytoplankton preference sMicZooNsq = 0.d0 ! NEW 3Zoo -tiny_het = 1.d-5 ! for more stable computation of HetRespFlux (_plus). Value can be > tiny because HetRespFlux ~ hetC**2. / &pasecondzooplankton -graz_max2 = 0.1d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter -epsilon2 = 0.0144d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss -res_zoo2 = 0.0107d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) +graz_max2 = 0.1d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter +epsilon2 = 0.0144d0 ! [(mmol N)2 /m6] Half saturation constant for grazing loss res_zoo2 = 0.0107d0 ! [1/day] Respiration by heterotrophs and mortality (loss to detritus) loss_zoo2 = 0.003d0 ! [1/day] Temperature dependent N degradation of extracellular organic N (EON) + fecal_rate_n = 0.104d0 ! [1/day] Temperature dependent N degradation of \ fecal_rate_c = 0.236d0 fecal_rate_n_mes = 0.25d0 ! NEW 3Zoo fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo -pzDia2 = 1.5d0 !1.d0 ! Maximum diatom preference -sDiaNsq2 = 0.d0 -pzPhy2 = 0.5d0 ! Maximum diatom preference + +pzDia2 = 1.5d0 !1.d0 ! Maximum diatom preference sDiaNsq2 = 0.d0 +pzPhy2 = 0.5d0 ! Maximum diatom preference sPhyNsq2 = 0.d0 pzCocco2 = 0.5d0 ! NEW sCoccoNsq2 = 0.d0 ! NEW -pzHet = 1.5d0 !0.8d0 ! Maximum diatom preference +pzHet = 1.5d0 !0.8d0 ! Maximum diatom preference sHetNsq = 0.d0 -t1_zoo2 = 28145.d0 ! Krill temp. function constant1 -t2_zoo2 = 272.5d0 ! Krill temp. function constant2 -t3_zoo2 = 105234.d0 ! Krill temp. function constant3 + +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 / diff --git a/config/bin_2p1z1d_tp/namelist.tra b/config/bin_2p1z1d_tp/namelist.tra index 852790ac9..aa70ba432 100644 --- a/config/bin_2p1z1d_tp/namelist.tra +++ b/config/bin_2p1z1d_tp/namelist.tra @@ -32,30 +32,30 @@ num_tracers = 100 ! number of tracers to allocate (must be ≥ actual nu !101 , 'UPW1' , 'UPW1' , 'NON ' , 0. , 0. ! example passive tracer &tracer_list nml_tracer_list = -1 , 'MFCT', 'QR4C', 'FCT ', 1., 1., -2 , 'MFCT', 'QR4C', 'FCT ', 1., 1., -1001, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1002, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1003, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1004, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1005, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1006, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1007, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1008, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1009, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1010, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1011, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1012, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1013, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1014, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1015, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1016, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1017, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1018, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1019, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1020, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1021, 'MFCT', 'QR4C', 'FCT ', 1., 1., -1022, 'MFCT', 'QR4C', 'FCT ', 1., 1. +1 , 'MFCT', 'QR4C', 'FCT ', 0., 1., +2 , 'MFCT', 'QR4C', 'FCT ', 0., 1., +1001, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1002, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1003, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1004, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1005, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1006, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1007, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1008, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1009, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1010, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1011, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1012, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1013, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1014, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1015, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1016, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1017, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1018, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1019, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1020, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1021, 'MFCT', 'QR4C', 'FCT ', 0., 1., +1022, 'MFCT', 'QR4C', 'FCT ', 0., 1. !101, 'UPW1', 'UPW1', 'NON ', 0., 0. / diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 3d3964018..369d306e2 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -746,7 +746,6 @@ subroutine fesom_runloop(current_nsteps) ! -------------- ! LA icebergs: 2023-05-17 -!YY: only when using icebergs? if (use_icebergs) then f%MPI_COMM_FESOM_IB = f%MPI_COMM_FESOM if (f%mype==0) then diff --git a/src/int_recom/recom_modules.F90 b/src/int_recom/recom_modules.F90 index b10745c8a..3d70b37a0 100644 --- a/src/int_recom/recom_modules.F90 +++ b/src/int_recom/recom_modules.F90 @@ -184,8 +184,7 @@ module recom_config currentCO2cycle, DIC_PI, Nmocsy, & recom_debug, ciso, benthos_num, & use_MEDUSA, sedflx_num, bottflx_num, & - add_loopback, lb_tscale, use_atbox, & - fe_2ligands, fe_compl_nica + add_loopback, lb_tscale, use_atbox !!------------------------------------------------------------------------------ !! *** Sinking *** @@ -269,7 +268,7 @@ module recom_config !! *** Iron chemistry *** Real(kind=8) :: totalligand = 1.d0 ! [mumol/m3] order 1. Total free ligand Real(kind=8) :: ligandStabConst = 100.d0 ! [m3/mumol] order 100. Ligand-free iron stability constant - namelist /pairon_chem/ totalligand, ligandStabConst + namelist /pairon_chem/ totalligand, ligandStabConst, fe_2ligands, fe_compl_nica !!------------------------------------------------------------------------------ !! *** Zooplankton *** Real(kind=8) :: graz_max = 2.4d0 ! [mmol N/(m3 * day)] Maximum grazing loss parameter From 373785933df9c88733edabda3edf750398bdab1a Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Thu, 8 Jan 2026 22:59:20 +0100 Subject: [PATCH 51/68] bugfix for sedimentary input from MEDUSA in gen_surface_forcing.F90 --- src/gen_surface_forcing.F90 | 486 ++++++++++++-------------------- src/int_recom/recom_forcing.F90 | 2 +- 2 files changed, 186 insertions(+), 302 deletions(-) diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index a3e3d27a4..2f8f3909d 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -1490,7 +1490,6 @@ 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 @@ -1677,7 +1676,7 @@ SUBROUTINE sbc_do(partit, mesh) if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Atm_input'//achar(27)//'[0m' ! ******** Atmospheric CO2 ********* - if (mstep == 1) then ! The year has changed + if (mstep == 1) then ! The year has changed if (use_atbox) then ! Atmospheric box model CO2 values @@ -1718,7 +1717,8 @@ SUBROUTINE sbc_do(partit, mesh) end do end if end if - else + + else !not constant_CO2 filename=trim(make_full_path(nm_co2_data_file)) #if defined(__usetp) @@ -1782,295 +1782,13 @@ SUBROUTINE sbc_do(partit, mesh) endif !(partit%my_fesom_group==0) then #endif end if - - - -! ******** Sediment input ********* -!-Checking if files need to be opened--------------------------------------------- - if(use_MEDUSA .and. (sedflx_num .ne. 0)) then - allocate(ncdata(9)) -#if defined(__usetp) - if (partit%my_fesom_group==0) then -#endif - if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Sed_input'//achar(27)//'[0m' -#if defined(__usetp) - endif !(partit%my_fesom_group==0) then -#endif - ! MEDUSA input needs to be renamed via jobscript - sedfilename = trim(ResultPath)//'medusa_flux2fesom.nc' -#if defined(__usetp) - if (partit%my_fesom_group==0) then -#endif - if (mype==0) write(*,*) 'Updating sedimentary input first time from', sedfilename -#if defined(__usetp) - endif !(partit%my_fesom_group==0) then -#endif - -!-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 defined(__usetp) - if (partit%my_fesom_group==0) then -#endif - if (mype==0) write(*,*) 'adding loopback fluxes through runoff for the first time' !OG -#if defined(__usetp) - endif !(partit%my_fesom_group==0) then -#endif - - 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) - if(do_read) then ! file is opened and read every year - i=month - if (i > 12) i=1 -#if defined(__usetp) - if (partit%my_fesom_group==0) then -#endif - if (mype==0) write(*,*) 'Updating sedimentary input for month', i, 'from', sedfilename !OG -#if defined(__usetp) - endif !(partit%my_fesom_group==0) then -#endif - - - 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 defined(__usetp) - if (partit%my_fesom_group==0) then -#endif - if (mype==0) write(*,*) 'adding loopback fluxes into the ocean monthly' !OG -#if defined(__usetp) - endif !(partit%my_fesom_group==0) then -#endif - 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 defined(__usetp) - if (partit%my_fesom_group==0) then -#endif - if (mype==0) write(*,*) 'sedimentary input from MEDUSA not used!' !OG -#if defined(__usetp) - endif !(partit%my_fesom_group==0) then -#endif - end if ! use_MEDUSA and sedflx_num not 0 - - end if - + end if ! mstep ==1 ! ******** Fe deposition ********* if (fe_data_source=='Albani') then if (update_monthly_flag) then i=month - if (mstep > 1) i=i+1 + if (mstep > 1) i=i+1 if (i > 12) i=1 filename=trim(make_full_path(nm_fe_data_file)) #if defined(__usetp) @@ -2087,7 +1805,7 @@ SUBROUTINE sbc_do(partit, mesh) #if defined(__usetp) if (partit%my_fesom_group==0) then #endif - if (mype==0) write(*,*) 'Albani is switched off --> Check namelist.recom' + if (mype==0) write(*,*) 'Albani is switched off --> Check namelist.recom' #if defined(__usetp) endif #endif @@ -2125,7 +1843,7 @@ SUBROUTINE sbc_do(partit, mesh) #if defined(__usetp) if (partit%my_fesom_group==0) then #endif - if (mstep==1 .and. mype==0) write(*,*) 'useAeolianN is switched off' + if (mstep==1 .and. mype==0) write(*,*) 'useAeolianN is switched off' #if defined(__usetp) endif #endif @@ -2142,7 +1860,7 @@ SUBROUTINE sbc_do(partit, mesh) if (update_monthly_flag) then i=month - if (mstep > 1) i=i+1 + if (mstep > 1) i=i+1 if (i > 12) i=1 filename=trim(nm_river_data_file) #if defined(__usetp) @@ -2156,17 +1874,17 @@ SUBROUTINE sbc_do(partit, mesh) ! write(*,*) mype, 'RiverAlk2D', maxval(RiverAlk2D(:)), minval(RiverAlk2D(:)) ! molar convertion of [CaCo3] * 2 -> [total Alkalinity] RiverAlk2D = RiverAlk2D * 2 - - call read_2ddata_on_grid_NetCDF(filename, 'DIC', i, RiverDIC2D, partit, mesh) + + call read_2ddata_on_grid_NetCDF(filename, 'DIC', i, RiverDIC2D, partit, mesh) ! write(*,*) mype, 'RiverDIC2D', maxval(RiverDIC2D(:)), minval(RiverDIC2D(:)) - call read_2ddata_on_grid_NetCDF(filename, 'DIN', i, RiverDIN2D, partit, mesh) + call read_2ddata_on_grid_NetCDF(filename, 'DIN', i, RiverDIN2D, partit, mesh) ! write(*,*) mype, 'RiverDIN2D', maxval(RiverDIN2D(:)), minval(RiverDIN2D(:)) - call read_2ddata_on_grid_NetCDF(filename, 'DOC', i, RiverDOC2D, partit, mesh) + call read_2ddata_on_grid_NetCDF(filename, 'DOC', i, RiverDOC2D, partit, mesh) ! write(*,*) mype, 'RiverDOC2D', maxval(RiverDOC2D(:)), minval(RiverDOC2D(:)) - call read_2ddata_on_grid_NetCDF(filename, 'DON', i, RiverDON2D, partit, mesh) + call read_2ddata_on_grid_NetCDF(filename, 'DON', i, RiverDON2D, partit, mesh) ! write(*,*) mype, 'RiverDON2D', maxval(RiverDON2D(:)), minval(RiverDON2D(:)) RiverDSi2D = RiverDIN2D * (16/15) @@ -2176,7 +1894,7 @@ SUBROUTINE sbc_do(partit, mesh) #if defined(__usetp) if (partit%my_fesom_group==0) then #endif - if (mype==0 .and. mstep==1) write(*,*) 'No riverine input' + if (mype==0 .and. mstep==1) write(*,*) 'No riverine input' #if defined(__usetp) endif #endif @@ -2209,7 +1927,7 @@ SUBROUTINE sbc_do(partit, mesh) if (update_monthly_flag) then i=month - if (mstep > 1) i=i+1 + if (mstep > 1) i=i+1 if (i > 12) i=1 filename=trim(nm_erosion_data_file) #if defined(__usetp) @@ -2221,25 +1939,192 @@ SUBROUTINE sbc_do(partit, mesh) #endif call read_2ddata_on_grid_NetCDF(filename,'POC', i, ErosionTOC2D, partit, mesh) ! write(*,*) mype, 'ErosionTOC2D', maxval(ErosionTOC2D(:)), minval(ErosionTOC2D(:)) - + call read_2ddata_on_grid_NetCDF(filename,'PON', i, ErosionTON2D, partit, mesh) ! write(*,*) mype, 'ErosionTON2D', maxval(ErosionTON2D(:)), minval(ErosionTON2D(:)) ! No silicates in erosion, we convert from nitrogen with redfieldian ratio - ErosionTSi2D=ErosionTON2D * 16/15 + ErosionTSi2D=ErosionTON2D * 16/15 end if else is_erosioninput = 0.0d0 #if defined(__usetp) if (partit%my_fesom_group==0) then #endif - if (mype==0 .and. mstep==1) write(*,*) 'No erosion input' + if (mype==0 .and. mstep==1) write(*,*) 'No erosion input' #if defined(__usetp) endif #endif end if + +! ******** Sediment input ********* +!-Checking if files need to be opened--------------------------------------------- + if(use_MEDUSA .and. (sedflx_num .ne. 0)) then + allocate(ncdata(9)) +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif + if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Sed_input'//achar(27)//'[0m' +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif + ! MEDUSA input needs to be renamed via jobscript + filename=trim(make_full_path(nm_sed_data_file)) + if (update_monthly_flag) then + i=month + if (mstep > 1) i=i+1 + if (i > 12) i=1 +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif + if (mype==0) write(*,*) 'Updating sedimentary input for month', i, 'from', filename +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then #endif +!-Opening files-------------------------------------------------------------------- + + call read_2ddata_on_grid_NetCDF(filename, '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(filename, '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(filename, '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(filename, '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(filename, '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(filename, '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(filename, '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 defined(__usetp) + if (partit%my_fesom_group==0) then +#endif + if (mype==0) write(*,*) 'add loopback fluxes through river runoff for month', i +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif + + istart = (/1,1/) + icount = (/1,1/) + ncdata = 0.d0 + + total_runoff = 8.76d5*86400 + + status=nf_open(filename, 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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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) + + 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 + + else + +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif + if (mype==0) write(*,*) 'loopback fluxes not added!' +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif + + end if ! add_loopback + + end if ! update_monthly_flag + + else ! use_MEDUSA + +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif + if (mype==0) write(*,*) 'sedimentary input from MEDUSA not used!' +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif + + end if ! use_MEDUSA and sedflx_num not 0 + +#endif !defined(__recom) + !!PS if (partit%mype==0) then !!PS write(*,*) 'sbc_do --> mstep:',mstep, ' rdate=', rdate !!PS end if @@ -2248,7 +2133,6 @@ SUBROUTINE sbc_do(partit, mesh) call data_timeinterp(rdate, partit) END SUBROUTINE sbc_do - FUNCTION julday(yyyy, mm, dd, calendar) IMPLICIT NONE diff --git a/src/int_recom/recom_forcing.F90 b/src/int_recom/recom_forcing.F90 index 161fa1625..3581f6af7 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 & From 7e41192dde0b5295c6ab395aea7b53a59448a320 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 9 Jan 2026 22:01:04 +0100 Subject: [PATCH 52/68] fix of line breaks in recom namelist --- config/bin_2p1z1d_tp/namelist.recom | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/config/bin_2p1z1d_tp/namelist.recom b/config/bin_2p1z1d_tp/namelist.recom index eee4d8ae2..3a68b6602 100644 --- a/config/bin_2p1z1d_tp/namelist.recom +++ b/config/bin_2p1z1d_tp/namelist.recom @@ -174,8 +174,9 @@ sMicZooNsq = 0.d0 ! NEW 3Zoo / &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) +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 \ @@ -183,7 +184,8 @@ fecal_rate_c = 0.236d0 fecal_rate_n_mes = 0.25d0 ! NEW 3Zoo fecal_rate_c_mes = 0.32d0 ! NEW 3Zoo -pzDia2 = 1.5d0 !1.d0 ! Maximum diatom preference sDiaNsq2 = 0.d0 +pzDia2 = 1.5d0 !1.d0 ! Maximum diatom preference +sDiaNsq2 = 0.d0 pzPhy2 = 0.5d0 ! Maximum diatom preference sPhyNsq2 = 0.d0 pzCocco2 = 0.5d0 ! NEW From 7b119ff2a4747126a5ea98e45ca50c274952e8a0 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 9 Jan 2026 22:03:49 +0100 Subject: [PATCH 53/68] delete namelists not needed for 2.7 --- config/bin_2p1z1d_tp/namelist.config.old | 77 ----- config/bin_2p1z1d_tp/namelist.io.recom | 343 ----------------------- config/bin_2p1z1d_tp/namelist.tra.recom | 1 - 3 files changed, 421 deletions(-) delete mode 100644 config/bin_2p1z1d_tp/namelist.config.old delete mode 100644 config/bin_2p1z1d_tp/namelist.io.recom delete mode 120000 config/bin_2p1z1d_tp/namelist.tra.recom diff --git a/config/bin_2p1z1d_tp/namelist.config.old b/config/bin_2p1z1d_tp/namelist.config.old deleted file mode 100644 index 0297daa0e..000000000 --- a/config/bin_2p1z1d_tp/namelist.config.old +++ /dev/null @@ -1,77 +0,0 @@ -! This is the namelist file for model general configuration - -&modelname -runid='fesom' -/ - -×tep -step_per_day=32 !96 !96 !72 !72 !45 !72 !96 -run_length=10 !62 !62 !62 !28 -run_length_unit='y' ! y, m, d, s -/ - -&clockinit ! the model starts at -timenew=0.0 -daynew=1 -yearnew=1948 -/ - -&paths -MeshPath='/home/a/a270105/fesom_meshes/mesh_core2/' -ClimateDataPath='/home/a/a270105/initial_files/pi_init/' -ResultPath='./' -/ - -&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=1 !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. -num_fesom_groups = 2 -/ - -&machine -n_levels=2 -n_part= 2, 128 ! 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_tp/namelist.io.recom b/config/bin_2p1z1d_tp/namelist.io.recom deleted file mode 100644 index 2f68c6701..000000000 --- a/config/bin_2p1z1d_tp/namelist.io.recom +++ /dev/null @@ -1,343 +0,0 @@ -! ============================================================================ -! ============ Namelist file for FESOM2 output configuration ================= -! ============================================================================ -! This file contains configuration for model output and diagnostics: -! - Diagnostic flags for optional output fields -! - General output settings (compression, rotation) -! - Output variable list with frequency and precision -! - Complete catalog of all available output fields -! -! See the output catalog at the end of this file for all possible variables. -! Some outputs require specific flags in &diag_list or other namelists. -! ============================================================================ - -! ============================================================================ -! DIAGNOSTIC FLAGS -! ============================================================================ -! Enable/disable optional diagnostic computations and outputs. -! Setting these to .true. enables additional output fields (see catalog below). -! ============================================================================ -&diag_list -ldiag_solver = .false. ! enables solver diagnostics (convergence, iterations) -lcurt_stress_surf = .false. ! enables 'curl_surf' output (vorticity of surface stress) -ldiag_curl_vel3 = .false. ! enables 'curl_u' output (relative vorticity from 3D velocity) -ldiag_Ri = .false. ! enables Richardson number diagnostics ('shear', 'Ri') -ldiag_turbflux = .false. ! enables turbulent flux diagnostics ('KvdTdz', 'KvdSdz') -ldiag_salt3D = .false. ! enables 3D salinity diagnostics -ldiag_dMOC = .false. ! enables 'dMOC' output (density MOC diagnostics) -ldiag_DVD = .false. ! enables 'DVD' output (Discrete Variance Decay diagnostics) -ldiag_forc = .false. ! enables 'FORC' output (comprehensive forcing diagnostics) -ldiag_extflds = .false. ! enables extended field diagnostics -ldiag_destine = .false. ! enables heat content computation ('hc300m', 'hc700m', 'hc') -ldiag_trflx = .false. ! enables tracer flux diagnostics ('utemp', 'vtemp', 'usalt', 'vsalt') -ldiag_uvw_sqr = .false. ! enables 'UVW_SQR' output (squared velocities: u2, v2, w2) -ldiag_trgrd_xyz = .false. ! enables 'TRGRD_XYZ' output (horizontal & vertical tracer gradients) -/ - -! ============================================================================ -! GENERAL OUTPUT SETTINGS -! ============================================================================ -&nml_general -io_listsize = 120 ! total number of streams to allocate. Shall be larger or equal to the number of streams in &nml_list (max. 150) -vec_autorotate = .false. ! unrotate vector fields (velocities, winds) before writing to output files -compression_level = 1 ! compression level for netCDF output (1=fastest, 9=smallest) -/ - -! ============================================================================ -! OUTPUT VARIABLE LIST -! ============================================================================ -! Format: 'variable_id', frequency, unit, precision -! frequency = output frequency (integer) -! unit = 'y' (yearly), 'm' (monthly), 'd' (daily), 'h' (hourly), 's' (steps) -! precision = 4 (single precision) or 8 (double precision) -! ============================================================================ -&nml_list -io_list = 'sst ',1, 'm', 4, - 'sss ',1, 'm', 4, -! 'ssh ',1, 'm', 4, -! '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, -! 'N2 ',1, 'm', 4, -! 'Kv ',1, 'm', 4, - 'u ',1, 'm', 4, - 'v ',1, 'm', 4, -! 'unod ',1, 'm', 4, -! 'vnod ',1, 'm', 4, - 'w ',1, 'm', 4, -! 'Av ',1, 'm', 4, - 'bolus_u ',1, 'm', 4, - 'bolus_v ',1, 'm', 4, - 'bolus_w ',1, 'm', 4, -! 'fw ',1, 'm', 4, -! 'fh ',1, 'm', 4, - 'otracers ',1, 'm', 4, -/ - -! ============================================================================ -! COMPLETE CATALOG OF ALL POSSIBLE OUTPUT FIELDS -! ============================================================================ -! Below is a comprehensive list of all valid io_list IDs available in FESOM2. -! To enable any field, copy the line to the &nml_list section above. -! NOTE: Some fields require specific flags to be enabled (see comments). -! ============================================================================ - -! --- 2D OCEAN SURFACE FIELDS --- -! 'sst ',1, 'm', 4, ! sea surface temperature [C] -! 'sss ',1, 'm', 4, ! sea surface salinity [psu] -! 'ssh ',1, 'm', 4, ! sea surface elevation [m] -! 'vve_5 ',1, 'm', 4, ! vertical velocity at 5th level [m/s] -! 't_star ',1, 'm', 4, ! air temperature [C] -! 'qsr ',1, 'm', 4, ! solar radiation [W/s^2] - -! --- 3D OCEAN FIELDS --- -! 'temp ',1, 'm', 4, ! temperature [C] -! 'salt ',1, 'm', 8, ! salinity [psu] -! 'sigma0 ',1, 'm', 4, ! potential density [kg/m3] -! 'u ',1, 'm', 4, ! zonal velocity [m/s] -! 'v ',1, 'm', 4, ! meridional velocity [m/s] -! 'unod ',1, 'm', 4, ! zonal velocity at nodes [m/s] -! 'vnod ',1, 'm', 4, ! meridional velocity at nodes [m/s] -! 'w ',1, 'm', 4, ! vertical velocity [m/s] -! 'otracers ',1, 'm', 4, ! all other tracers if applicable -! 'age ',1, 'm', 4, ! water age tracer [year] (require use_age_tracer=.true.) - -! --- 2D SSH DIAGNOSTIC VARIABLES --- -! 'ssh_rhs ',1, 'm', 4, ! ssh rhs [m/s] -! 'ssh_rhs_old',1, 'm', 4, ! ssh rhs old [m/s] -! 'd_eta ',1, 'm', 4, ! dssh from solver [m] -! 'hbar ',1, 'm', 4, ! ssh n+0.5 tstep [m] -! 'hbar_old ',1, 'm', 4, ! ssh n-0.5 tstep [m] -! 'dhe ',1, 'm', 4, ! dhbar @ elem [m] - -! --- SEA ICE FIELDS (require use_ice=.true.) --- -! 'uice ',1, 'm', 4, ! ice velocity x [m/s] -! 'vice ',1, 'm', 4, ! ice velocity y [m/s] -! 'a_ice ',1, 'm', 4, ! ice concentration [%] -! 'm_ice ',1, 'm', 4, ! ice height per unit area [m] -! 'thdgrice ',1, 'm', 4, ! thermodynamic growth rate ice [m/s] -! 'thdgrarea ',1, 'm', 4, ! thermodynamic growth rate ice concentration [frac/s] -! 'dyngrarea' ,1, 'm', 4, ! dynamic growth rate ice concentration [frac/s] -! 'dyngrice ',1, 'm', 4, ! dynamic growth rate ice [m/s] -! 'thdgrsn ',1, 'm', 4, ! thermodynamic growth rate snow [m/s] -! 'dyngrsnw ',1, 'm', 4, ! dynamic growth rate snow [m/s] -! 'flice ',1, 'm', 4, ! flooding growth rate ice [m/s] -! 'm_snow ',1, 'm', 4, ! snow height per unit area [m] -! 'h_ice ',1, 'm', 4, ! ice thickness over ice-covered fraction [m] -! 'h_snow ',1, 'm', 4, ! snow thickness over ice-covered fraction [m] -! 'fw_ice ',1, 'm', 4, ! fresh water flux from ice ['m/s'] -! 'fw_snw ',1, 'm', 4, ! fresh water flux from snow ['m/s'] - -! --- SEA ICE DEBUG VARIABLES (require use_ice=.true.) --- -! 'strength_ice',1, 'm', 4, ! ice strength [?] -! 'inv_areamass',1, 'm', 4, ! inv_areamass [?] -! 'rhs_a ',1, 'm', 4, ! rhs_a [?] -! 'rhs_m ',1, 'm', 4, ! rhs_m [?] -! 'sgm11 ',1, 'm', 4, ! sgm11 [?] -! 'sgm12 ',1, 'm', 4, ! sgm12 [?] -! 'sgm22 ',1, 'm', 4, ! sgm22 [?] -! 'eps11 ',1, 'm', 4, ! eps11 [?] -! 'eps12 ',1, 'm', 4, ! eps12 [?] -! 'eps22 ',1, 'm', 4, ! eps22 [?] -! 'u_rhs_ice ',1, 'm', 4, ! u_rhs_ice [?] -! 'v_rhs_ice ',1, 'm', 4, ! v_rhs_ice [?] -! 'metric_fac',1, 'm', 4, ! metric_fac [?] -! 'elevat_ice',1, 'm', 4, ! elevat_ice [?] -! 'uwice ',1, 'm', 4, ! uwice [?] -! 'vwice ',1, 'm', 4, ! vwice [?] -! 'twice ',1, 'm', 4, ! twice [?] -! 'swice ',1, 'm', 4, ! swice [?] - -! --- MIXED LAYER DEPTH --- -! 'MLD1 ',1, 'm', 4, ! Mixed Layer Depth [m] Large et al. 1997, bvfreq(nz, node) > db_max -! 'MLD2 ',1, 'm', 4, ! Mixed Layer Depth [m] Levitus treshold, rhopot(nz)-rhopot(1) > 0.125_WP kg/m -! 'MLD3 ',1, 'm', 4, ! Mixed Layer Depth [m] Griffies 2016 , rhopot(nz)-rhopot(1) > 0.03_WP kg/m - -! --- HEAT CONTENT (require ldiag_destine=.true.) --- -! 'hc300m ',1, 'm', 4, ! Vertically integrated heat content upper 300m [J m**-2] -! 'hc700m ',1, 'm', 4, ! Vertically integrated heat content upper 700m [J m**-2] -! 'hc ',1, 'm', 4, ! Vertically integrated heat content total column [J m**-2] - -! --- WATER ISOTOPES IN SEA ICE (require lwiso=.true.) --- -! 'h2o18_ice ',1, 'm', 4, ! h2o18 concentration in sea ice [kmol/m**3] -! 'hDo16_ice ',1, 'm', 4, ! hDo16 concentration in sea ice [kmol/m**3] -! 'h2o16_ice ',1, 'm', 4, ! h2o16 concentration in sea ice [kmol/m**3] - -! --- FRESHWATER FLUX (require use_landice_water=.true.) --- -! 'landice ',1, 'm', 4, ! freshwater flux [m/s] - -! --- SURFACE FORCING --- -! 'tx_sur ',1, 'm', 4, ! zonal wind str. to ocean [N/m2] -! 'ty_sur ',1, 'm', 4, ! meridional wind str. to ocean [N/m2] -! 'curl_surf ',1, 'm', 4, ! vorticity of the surface stress [none] (require lcurt_stress_surf=.true.) -! 'fh ',1, 'm', 4, ! heat flux [W/m2] -! 'fw ',1, 'm', 4, ! fresh water flux [m/s] -! 'atmice_x ',1, 'm', 4, ! stress atmice x [N/m2] -! 'atmice_y ',1, 'm', 4, ! stress atmice y [N/m2] -! 'atmoce_x ',1, 'm', 4, ! stress atmoce x [N/m2] -! 'atmoce_y ',1, 'm', 4, ! stress atmoce y [N/m2] -! 'iceoce_x ',1, 'm', 4, ! stress iceoce x [N/m2] -! 'iceoce_y ',1, 'm', 4, ! stress iceoce y [N/m2] -! 'alpha ',1, 'm', 4, ! thermal expansion [none] -! 'beta ',1, 'm', 4, ! saline contraction [none] -! 'dens_flux ',1, 'm', 4, ! density flux [kg/(m3*s)] -! 'runoff ',1, 'm', 4, ! river runoff [m/s] -! 'evap ',1, 'm', 4, ! evaporation [m/s] -! 'prec ',1, 'm', 4, ! precipitation rain [m/s] -! 'snow ',1, 'm', 4, ! precipitation snow [m/s] -! 'tair ',1, 'm', 4, ! surface air temperature [°C] -! 'shum ',1, 'm', 4, ! specific humidity [] -! 'swr ',1, 'm', 4, ! short wave radiation [W/m^2] -! 'lwr ',1, 'm', 4, ! long wave radiation [W/m^2] -! 'uwind ',1, 'm', 4, ! 10m zonal surface wind velocity [m/s] -! 'vwind ',1, 'm', 4, ! 10m merid. surface wind velocity [m/s] -! 'virtsalt ',1, 'm', 4, ! virtual salt flux [m/s*psu] -! 'relaxsalt ',1, 'm', 4, ! relaxation salt flux [m/s*psu] -! 'realsalt ',1, 'm', 4, ! real salt flux from sea ice [m/s*psu] - -! --- KPP VERTICAL MIXING (require mix_scheme_nmb==1,17,3,37) --- -! 'kpp_obldepth',1, 'm', 4, ! KPP ocean boundary layer depth [m] -! 'kpp_sbuoyflx',1, 'm', 4, ! surface buoyancy flux [m2/s3] - -! --- RECOM 2D BIOGEOCHEMISTRY (require use_REcoM=.true. and __recom) --- -! 'dpCO2s ',1, 'm', 4, ! Difference of oceanic pCO2 minus atmospheric pCO2 [uatm] -! 'pCO2s ',1, 'm', 4, ! Partial pressure of oceanic CO2 [uatm] -! 'CO2f ',1, 'm', 4, ! CO2-flux into the surface water [mmolC/m2/d] -! 'O2f ',1, 'm', 4, ! O2-flux into the surface water [mmolO/m2/d] -! 'Hp ',1, 'm', 4, ! Mean of H-plus ions in the surface water [mol/kg] -! 'aFe ',1, 'm', 4, ! Atmospheric iron input [umolFe/m2/s] -! 'aN ',1, 'm', 4, ! Atmospheric DIN input [mmolN/m2/s] -! 'benN ',1, 'm', 4, ! Benthos Nitrogen [mmol] -! 'benC ',1, 'm', 4, ! Benthos Carbon [mmol] -! 'benSi ',1, 'm', 4, ! Benthos silicon [mmol] -! 'benCalc ',1, 'm', 4, ! Benthos calcite [mmol] -! 'NPPn ',1, 'm', 4, ! Mean NPP nanophytoplankton [mmolC/m2/d] -! 'NPPd ',1, 'm', 4, ! Mean NPP diatoms [mmolC/m2/d] -! 'GPPn ',1, 'm', 4, ! Mean GPP nanophytoplankton [mmolC/m2/d] -! 'GPPd ',1, 'm', 4, ! Mean GPP diatoms [mmolC/m2/d] -! 'NNAn ',1, 'm', 4, ! Net N-assimilation nanophytoplankton [mmolN/m2/d] -! 'NNAd ',1, 'm', 4, ! Net N-assimilation diatoms [mmolN/m2/d] -! 'Chldegn ',1, 'm', 4, ! Chlorophyll degradation nanophytoplankton [1/d] -! 'Chldegd ',1, 'm', 4, ! Chlorophyll degradation diatoms [1/d] -! 'NPPc ',1, 'm', 4, ! Mean NPP coccolithophores [mmolC/(m2*d)] -! 'GPPc ',1, 'm', 4, ! Mean GPP coccolithophores [mmolC/m2/d] -! 'NNAc ',1, 'm', 4, ! Net N-assimilation coccolithophores [mmolN/(m2*d)] -! 'Chldegc ',1, 'm', 4, ! Chlorophyll degradation coccolithophores [1/d] - -! --- RECOM 3D BIOGEOCHEMISTRY (require use_REcoM=.true. and __recom) --- -! 'PAR ',1, 'm', 4, ! PAR [W/m2] -! 'respmeso ',1, 'm', 4, ! Respiration rate of mesozooplankton [mmolC/m2/d] -! 'respmacro ',1, 'm', 4, ! Respiration rate of macrozooplankton [mmolC/m2/d] -! 'respmicro ',1, 'm', 4, ! Respiration rate of microzooplankton [mmolC/m2/d] -! 'calcdiss ',1, 'm', 4, ! Calcite dissolution [mmolC/m2/d] -! 'calcif ',1, 'm', 4, ! Calcification [mmolC/m2/d] -! 'aggn ',1, 'm', 4, ! Aggregation of small phytoplankton [mmolC/m2/d] -! 'aggd ',1, 'm', 4, ! Aggregation of diatoms [mmolC/m2/d] -! 'aggc ',1, 'm', 4, ! Aggregation of coccolithophores [mmolC/m2/d] -! 'docexn ',1, 'm', 4, ! DOC excretion by small phytoplankton [mmolC/m2/d] -! 'docexd ',1, 'm', 4, ! DOC excretion by diatoms [mmolC/m2/d] -! 'docexc ',1, 'm', 4, ! DOC excretion by coccolithophores [mmolC/m2/d] -! 'respn ',1, 'm', 4, ! Respiration by small phytoplankton [mmolC/m2/d] -! 'respd ',1, 'm', 4, ! Respiration by diatoms [mmolC/m2/d] -! 'respc ',1, 'm', 4, ! Respiration by coccolithophores [mmolC/(m2*d)] -! 'NPPn3D ',1, 'm', 4, ! Net primary production of small phytoplankton [mmolC/m2/d] -! 'NPPd3D ',1, 'm', 4, ! Net primary production of diatoms [mmolC/m2/d] -! 'NPPc3D ',1, 'm', 4, ! Net primary production of coccolithophores [mmolC/m2/d] - -! --- WATER ISOTOPES IN OCEAN (require lwiso=.true.) --- -! 'h2o18 ',1, 'm', 4, ! h2o18 concentration [kmol/m**3] -! 'hDo16 ',1, 'm', 4, ! hDo16 concentration [kmol/m**3] -! 'h2o16 ',1, 'm', 4, ! h2o16 concentration [kmol/m**3] - -! --- NEUTRAL SLOPES --- -! 'slopetap_x',1, 'm', 4, ! neutral slope tapered X [none] -! 'slopetap_y',1, 'm', 4, ! neutral slope tapered Y [none] -! 'slopetap_z',1, 'm', 4, ! neutral slope tapered Z [none] -! 'slope_x ',1, 'm', 4, ! neutral slope X [none] -! 'slope_y ',1, 'm', 4, ! neutral slope Y [none] -! 'slope_z ',1, 'm', 4, ! neutral slope Z [none] - -! --- MIXING AND DYNAMICS --- -! 'N2 ',1, 'm', 4, ! brunt väisälä [1/s2] -! 'Kv ',1, 'm', 4, ! vertical diffusivity Kv [m2/s] -! 'Av ',1, 'm', 4, ! vertical viscosity Av [m2/s] - -! --- VISCOSITY TENDENCIES (require dynamics%opt_visc==8) --- -! 'u_dis_tend',1, 'm', 4, ! horizontal velocity viscosity tendency [m/s] -! 'v_dis_tend',1, 'm', 4, ! meridional velocity viscosity tendency [m/s] -! 'u_back_tend',1, 'm', 4, ! horizontal velocity backscatter tendency [m2/s2] -! 'v_back_tend',1, 'm', 4, ! meridional velocity backscatter tendency [m2/s2] -! 'u_total_tend',1, 'm', 4,! horizontal velocity total viscosity tendency [m/s] -! 'v_total_tend',1, 'm', 4,! meridional velocity total viscosity tendency [m/s] - -! --- FERRARI/GM PARAMETERISATION (require Fer_GM=.true.) --- -! 'bolus_u ',1, 'm', 4, ! GM bolus velocity U [m/s] -! 'bolus_v ',1, 'm', 4, ! GM bolus velocity V [m/s] -! 'bolus_w ',1, 'm', 4, ! GM bolus velocity W [m/s] -! 'fer_K ',1, 'm', 4, ! GM, stirring diff. [m2/s] -! 'fer_scal ',1, 'm', 4, ! GM surface scaling [] -! 'fer_C ',1, 'm', 4, ! GM, depth independent speed [m/s] -! 'cfl_z ',1, 'm', 4, ! vertical CFL criteria [?] - -! --- DENSITY MOC DIAGNOSTICS (require ldiag_dMOC=.true.) --- -! 'dMOC ',1, 'm', 4, ! fluxes for density MOC (multiple variables) - -! --- PRESSURE GRADIENT FORCE --- -! 'pgf_x ',1, 'm', 4, ! zonal pressure gradient force [m/s^2] -! 'pgf_y ',1, 'm', 4, ! meridional pressure gradient force [m/s^2] - -! --- ALE LAYER THICKNESS --- -! 'hnode ',1, 'm', 4, ! vertice layer thickness [m] -! 'hnode_new ',1, 'm', 4, ! hnode_new [m] -! 'helem ',1, 'm', 4, ! elemental layer thickness [m] - -! --- OIFS/IFS INTERFACE (require __oifs or __ifsinterface) --- -! 'alb ',1, 'm', 4, ! ice albedo [none] -! 'ist ',1, 'm', 4, ! ice surface temperature [K] -! 'qsi ',1, 'm', 4, ! ice heat flux [W/m^2] -! 'qso ',1, 'm', 4, ! oce heat flux [W/m^2] -! 'enthalpy ',1, 'm', 4, ! enthalpy of fusion [W/m^2] -! 'qcon ',1, 'm', 4, ! conductive heat flux [W/m^2] -! 'qres ',1, 'm', 4, ! residual heat flux [W/m^2] -! 'runoff_liquid',1, 'm', 4, ! liquid water runoff [m/s] -! 'runoff_solid',1, 'm', 4, ! solid water runoff [m/s] - -! --- ICEBERG OUTPUTS (require use_icebergs=.true.) --- -! 'icb ',1, 'm', 4, ! iceberg outputs (multiple variables) - -! --- TKE MIXING DIAGNOSTICS (require mix_scheme_nmb==5 or 56) --- -! 'TKE ',1, 'm', 4, ! TKE diagnostics (multiple variables) - -! --- IDEMIX MIXING DIAGNOSTICS (require mod(mix_scheme_nmb,10)==6) --- -! 'IDEMIX ',1, 'm', 4, ! IDEMIX diagnostics (multiple variables) - -! --- TIDAL MIXING DIAGNOSTICS (require mod(mix_scheme_nmb,10)==7) --- -! 'TIDAL ',1, 'm', 4, ! TIDAL diagnostics (multiple variables) - -! --- FORCING DIAGNOSTICS (require ldiag_forc=.true.) --- -! 'FORC ',1, 'm', 4, ! forcing diagnostics (multiple variables) - -! --- DISCRETE VARIANCE DECAY (require ldiag_DVD=.true.) --- -! 'DVD ',1, 'm', 4, ! DVD diagnostics (multiple variables) - -! --- SPLIT-EXPLICIT SUBCYCLING (require dynamics%use_ssh_se_subcycl=.true.) --- -! 'SPLIT-EXPL',1, 'm', 4, ! split-explicit diagnostics (multiple variables) - -! --- SQUARED VELOCITIES (require ldiag_uvw_sqr=.true.) --- -! 'UVW_SQR ',1, 'm', 4, ! squared velocities (u2, v2, w2) - -! --- TRACER GRADIENTS (require ldiag_trgrd_xyz=.true.) --- -! 'TRGRD_XYZ ',1, 'm', 4, ! horizontal and vertical tracer gradients - -! ============================================================================ -! END OF CATALOG -! ============================================================================ diff --git a/config/bin_2p1z1d_tp/namelist.tra.recom b/config/bin_2p1z1d_tp/namelist.tra.recom deleted file mode 120000 index 61e7b70fb..000000000 --- a/config/bin_2p1z1d_tp/namelist.tra.recom +++ /dev/null @@ -1 +0,0 @@ -namelist.tra \ No newline at end of file From d7654e542d55e0bf0989191323c8327b8c87433b Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 9 Jan 2026 22:15:55 +0100 Subject: [PATCH 54/68] updating namelists --- config/bin_2p1z1d_tp/namelist.cvmix | 256 +++++++++++++++++++++------- config/bin_2p1z1d_tp/namelist.io | 66 ++++--- 2 files changed, 237 insertions(+), 85 deletions(-) diff --git a/config/bin_2p1z1d_tp/namelist.cvmix b/config/bin_2p1z1d_tp/namelist.cvmix index a4b0a248c..5c73d9403 100644 --- a/config/bin_2p1z1d_tp/namelist.cvmix +++ b/config/bin_2p1z1d_tp/namelist.cvmix @@ -1,75 +1,211 @@ -! namelist for Turbulent Kinetic Energy (TKE) +! ============================================================================ +! ========== Namelist file for FESOM2 CVMix parameterizations =============== +! ============================================================================ +! This file contains configuration for CVMix (Community Vertical Mixing) +! parameterizations: +! - TKE (Turbulent Kinetic Energy) scheme +! - IDEMIX (Internal Wave Dissipation, Energy, and Mixing) +! - PP (Pacanowski-Philander) scheme +! - KPP (K-Profile Parameterization) +! - TIDAL mixing parameterization +! +! Select the active scheme in namelist.oce (mix_scheme parameter) +! ============================================================================ + +! ============================================================================ +! TKE (TURBULENT KINETIC ENERGY) SCHEME +! ============================================================================ ¶m_tke -tke_c_k = 0.1 -tke_c_eps = 0.7 -tke_alpha = 30.0 -tke_mxl_min = 1.0e-8 -tke_kappaM_min = 0.0 -tke_kappaM_max = 100.0 -tke_cd = 3.75 ! for Dirichlet boundary conditions -!tke_cd = 1.0 ! for Neumann boundary conditions -tke_surf_min = 1.0e-4 -tke_min = 1.0e-6 -! tke_mxl_choice ... Can only be 1 or 2, choice of calculation of mixing -! length; currently only Blanke, B., P. Delecluse option is implemented -tke_mxl_choice = 2 -tke_dolangmuir = .false. +! --- TKE Model Parameters --- +tke_c_k = 0.1 ! TKE parameter c_k [dimensionless] +tke_c_eps = 0.7 ! TKE dissipation parameter c_eps [dimensionless] +tke_alpha = 30.0 ! TKE stability function parameter [dimensionless] + +! --- Mixing Length --- +tke_mxl_min = 1.0e-8 ! minimum mixing length [m] +tke_mxl_choice = 2 ! mixing length calculation method: + ! 1 = not implemented + ! 2 = Blanke & Delecluse option (currently only option) + +! --- Viscosity/Diffusivity Limits --- +tke_kappaM_min = 0.0 ! minimum momentum diffusivity [m²/s] +tke_kappaM_max = 100.0 ! maximum momentum diffusivity [m²/s] + +! --- Boundary Conditions --- +tke_cd = 3.75 ! surface boundary condition parameter + ! 3.75 for Dirichlet BC, 1.0 for Neumann BC + +! --- TKE Minimum Values --- +tke_surf_min = 1.0e-4 ! minimum surface TKE [m²/s²] +tke_min = 1.0e-6 ! minimum interior TKE [m²/s²] + +! --- Langmuir Turbulence --- +tke_dolangmuir = .false. ! include Langmuir turbulence parameterization / -! namelist for IDEMIX von Pollman et al. (2017) +! ============================================================================ +! IDEMIX (INTERNAL WAVE ENERGY PARAMETERIZATION) +! ============================================================================ +! Based on Olbers & Eden (2013) and von Pollmann et al. (2017) +! ============================================================================ ¶m_idemix -idemix_tau_v = 172800.0 ! 2days ! time scale for vertical symmetrisation (sec) -idemix_tau_h = 1296000.0 !15days ! time scale for horizontal symmetrisation -idemix_gamma = 1.570 ! constant of order one derived from the shape of the spectrum in m space (dimensionless) -idemix_jstar = 5.0 ! spectral bandwidth in modes (dimensionless) -idemix_mu0 = 0.33333333 ! dissipation parameter (dimensionless) -idemix_sforcusage = 0.2 -idemix_n_hor_iwe_prop_iter = 5 ! iterations for contribution from horiz. wave propagation -idemix_surforc_file = '/work/ollie/clidyn/forcing/IDEMIX/fourier_smooth_2005_cfsr_inert_rgrid.nc' -idemix_surforc_vname= 'var706' -idemix_botforc_file = '/work/ollie/clidyn/forcing/IDEMIX/tidal_energy_gx1v6_20090205_rgrid.nc' -idemix_botforc_vname= 'wave_dissipation' +! --- Time Scales --- +idemix_tau_v = 172800.0 ! vertical symmetrization time scale [s] (2 days) +idemix_tau_h = 1296000.0 ! horizontal symmetrization time scale [s] (15 days) + +! --- Spectral Parameters --- +idemix_gamma = 1.570 ! spectral shape constant [dimensionless] (order 1) +idemix_jstar = 5.0 ! spectral bandwidth in vertical modes [dimensionless] +idemix_mu0 = 0.33333333 ! dissipation parameter [dimensionless] + +! --- Energy Forcing --- +idemix_sforcusage = 0.2 ! fraction of surface forcing used [dimensionless] +idemix_n_hor_iwe_prop_iter = 5 ! iterations for horizontal wave propagation + +! --- Surface Forcing (Wind-Generated Internal Waves) --- +idemix_surforc_file = '/pool/data/AWICM/FESOM2/FORCING/IDEMIX/fourier_smooth_2005_cfsr_inert_rgrid.nc' ! path to surface forcing file +idemix_surforc_vname = 'var706' ! variable name in surface forcing file + +! --- Bottom Forcing (Tidal Internal Waves) --- +!idemix_botforc_file = '/albedo/pool/FESOM/fesom2.0/forcing/idemix/forcing_idemix_final_bin/FIN_tidal_energy_gx1v6_20090205_CESMJayne_remapnn_0.40deg.nc' ! path to bottom forcing !file +!idemix_botforc_vname = 'wave_dissipation' ! variable name in bottom forcing file +idemix_botforc_file = '/albedo/pool/FESOM/fesom2.0/forcing/idemix/forcing_idemix_final_bin/FIN_STORMTIDE2_M2_plus_NYCANDER_CnoM2_bin_0.40deg.nc' ! path to bottom forcing file, +idemix_botforc_vname = 'stormt_M2_plus_nycand_CnoM2' ! variable name in bottom forcing file + / -! namelist for PP +! ============================================================================ +! PP (PACANOWSKI-PHILANDER) SCHEME +! ============================================================================ +! Based on Pacanowski & Philander (1981) +! ============================================================================ ¶m_pp -pp_use_fesompp = .true. ! if true use fesom flavor off PP if false use original PP of Pacanowski & Philander -pp_Av0 = 0.01 ! mixing coeff. for PP -pp_alpha = 5.0 ! alpha param eq. (1) in Pacanowski and Philander 1981 -pp_exp = 2.0 ! n param eq. (1) in Pacanowski and Philander 1981 -pp_Avbckg = 1.0e-4 ! const. pp background viscosity -pp_Kvbckg = 1.0e-5 ! const. pp background diffusivity -pp_use_nonconstKvb = .true. ! use lat and depth dependent background diffusivity +! --- PP Variant --- +pp_use_fesompp = .true. ! use FESOM flavor of PP (true) or original PP (false) + +! --- Mixing Coefficients --- +pp_Av0 = 0.01 ! reference mixing coefficient [m²/s] +pp_alpha = 5.0 ! Richardson number dependency parameter [dimensionless] + ! (alpha in eq. 1 of Pacanowski & Philander 1981) +pp_exp = 2.0 ! Richardson number exponent [dimensionless] + ! (n in eq. 1 of Pacanowski & Philander 1981) + +! --- Background Mixing --- +pp_Avbckg = 1.0e-4 ! constant background viscosity [m²/s] +pp_Kvbckg = 1.0e-5 ! constant background diffusivity [m²/s] +pp_use_nonconstKvb = .true. ! use latitude and depth dependent background diffusivity / -! namelist for KPP +! ============================================================================ +! KPP (K-PROFILE PARAMETERIZATION) +! ============================================================================ +! Based on Large et al. (1994) with CVMix implementation options +! ============================================================================ ¶m_kpp -kpp_use_fesomkpp = .false. ! if true use cvmix MOM5 like kpp if false use cvmix MOM6 like kpp -kpp_use_enhanceKv = .true. ! If true, add enhanced diffusivity at base of boundary layer -kpp_use_compEkman = .true. ! If true, compute Ekman depth limit for OBLdepth -kpp_use_monob = .true. ! If true, compute Monin-Obukhov limit for OBLdepth -kpp_interptype_ri = "linear" ! Type of interpolation in determining OBL depth: linear,quadratic,cubic -kpp_interptype_atobl= "LMD94" ! Type of interpolation of visc and diff at obl depth: linear,quadratic,cubic,LMD94 -kpp_matchtechc = "ParabolicNonLocal" ! Setting diffusivity and NLT profile functions:SimpleShapes, MatchGradient, MatchBoth, ParabolicNonLocal -kpp_internalmix = "KPP" ! Ri-number dependet mixing scheme below the OBL: 'PP' or 'KPP' -kpp_reduce_tauuice = .false. ! If True, reduce the wind stress (ustar) under sea ice. -kpp_Av0 = 5.0e-3 ! leading coefficient of shear mixing formula, units: m^2/s: default= 5e-3 -kpp_Kv0 = 5.0e-3 -kpp_Ri0 = 0.7 ! critical Richardson number value, units: unitless (0.7 in LMD94) -kpp_pp_Av0 = 0.01 ! Parameter in case of PP mixing below the OBL -kpp_use_nonconstKvb= .true. ! If True use non constant background diffusivity of Qiang from FESOM1.4 -kpp_Avbckg = 1.0e-4 ! Values for const. background viscosity and diffusivity -kpp_Kvbckg = 1.0e-5 +! --- KPP Implementation --- +kpp_use_fesomkpp = .false. ! use CVMix MOM5-like KPP (true) or MOM6-like KPP (false) + +! --- Ocean Boundary Layer (OBL) Depth Calculation --- +kpp_use_enhanceKv = .true. ! add enhanced diffusivity at base of boundary layer +kpp_use_compEkman = .true. ! compute Ekman depth limit for OBL depth +kpp_use_monob = .true. ! compute Monin-Obukhov limit for OBL depth + +! --- Interpolation Methods --- +kpp_interptype_ri = "linear" ! interpolation type for OBL depth determination: + ! 'linear', 'quadratic', 'cubic' +kpp_interptype_atobl = "LMD94" ! interpolation of viscosity/diffusivity at OBL depth: + ! 'linear', 'quadratic', 'cubic', 'LMD94' +kpp_matchtechc = "ParabolicNonLocal" ! diffusivity and non-local transport profile: + ! 'SimpleShapes', 'MatchGradient', 'MatchBoth', 'ParabolicNonLocal' + +! --- Mixing Below OBL --- +kpp_internalmix = "KPP" ! Richardson number dependent mixing below OBL: + ! 'KPP' or 'PP' +kpp_pp_Av0 = 0.01 ! mixing coefficient for PP scheme below OBL [m²/s] + +! --- Shear Mixing Parameters --- +kpp_Av0 = 5.0e-3 ! leading coefficient of shear mixing [m²/s] (default: 5e-3) +kpp_Kv0 = 5.0e-3 ! leading coefficient of shear diffusion [m²/s] +kpp_Ri0 = 0.7 ! critical Richardson number [dimensionless] (0.7 in LMD94) + +! --- Background Mixing --- +kpp_use_nonconstKvb = .true. ! use non-constant background diffusivity (FESOM1.4 formulation) +kpp_Avbckg = 1.0e-4 ! constant background viscosity [m²/s] +kpp_Kvbckg = 1.0e-5 ! constant background diffusivity [m²/s] + +! --- Sea Ice Effects --- +kpp_reduce_tauuice = .false. ! reduce wind stress (u*) under sea ice + +! --- Langmuir Options in cvmix KPP --- + +! Stokes Similarty package +! If true, use Stokes Similarty package (i.e. include wave‐related / Stokes drift +! effects in the surface layer). Triggers usage of additional routines +! that alter the shape functions, or mixing formulations, incorporating wave / +! Stokes drift effects consistent with Monin–Obukhov similarity theory +! (MOST). The code logic probably augments or replaces parts of the standard boundary +! (layer similarity (or nonlocal mixing) using a Stokes‐drift‐aware correction. +kpp_use_StokesMOST= .false. !.true. + +! approximate proportionality between surface wind velocity and stokes velocity +! U_stokes ~ kpp_A_stokes * U_wind +kpp_A_stokes = 0.005 ! a + +! Langmuir option +! Option of Langmuir enhanced mixing apply an enhancement factor to the +! turbulent velocity scale +! LWF16 - MixingCoefEnhancement = Langmuir_EFactor +! RWHGK16 - MixingCoefEnhancement = cvmix_one + ShapeNoMatchAtS/NMshapeMax * & +! (Langmuir_EFactor - cvmix_one) +! NONE - Langmuir switched off, MixingCoefEnhancement=1 +kpp_langmuir_mixing= "NONE" !"LWF16" + +! Option of Langmuir turbulence enhanced entrainment - modify the unresolved shear +! LWF16 - Li Q., Webb A., Fox-Kemper B., Craig A., Danabasoglu G., +! Large W., Vertenstein M., 2016, Langmuir mixing effects on +! global climate: WAVEWATCH III in CESM, Ocean Modelling 103 (2016) 145–160 +! +! LF17 - Li Q., Fox-Kemper B., Breivik O., Webb A., 2017, Statistical +! models of global Langmuir mixing, Ocean Modelling 113 (2017) 95–114 +! +! RWHGK16 - Reichl B., Wang D., Hara T., Ginis I. and Kukulka T, 2016, Impact +! of Sea-State-Dependent Langmuir Turbulence on the Ocean +! Response to a Tropical Cyclone, Mon. Wea. Rev., 144 +! +! NONE - +kpp_langmuir_entrainment= "NONE" !"LF17" / -! namelist for TIDAL + +! ============================================================================ +! TIDAL MIXING PARAMETERIZATION +! ============================================================================ +! Based on Simmons et al. (2004) +! ============================================================================ ¶m_tidal -tidal_mixscheme = "Simmons" -tidal_efficiency = 0.2 ! units: unitless (fraction); (Gamma in Simmons et al.) -tidal_vert_decayscale= 500.0 ! units: m; zeta in Simmons et al. (used to compute the vertical deposition function) -tidal_max_coeff = 50e-4 ! units: m^2/s; largest acceptable value for diffusivity -tidal_lcl_mixfrac = 0.33 !tidal dissipation efficiency (q in Simmons et al.), i.e. fraction of energy that dissipates locally -tidal_depth_cutoff = 0.0 !depth of the shallowest column where tidal mixing is computed (positive below surface) -tidal_botforc_file = '/albedo/work/projects/p_pool_fesom1/fesom2.0/forcing/idemix/tidal_energy_gx1v6_20090205_rgrid.nc' +! --- Tidal Mixing Scheme --- +tidal_mixscheme = "Simmons" ! tidal mixing scheme (currently only 'Simmons' implemented) + +! --- Energy Dissipation Parameters --- +tidal_efficiency = 0.2 ! mixing efficiency [dimensionless, 0-1] + ! (Gamma in Simmons et al. 2004) +tidal_lcl_mixfrac = 0.33 ! local dissipation fraction [dimensionless] + ! (q in Simmons et al. 2004) + ! fraction of tidal energy dissipated locally vs radiated away + +! --- Vertical Structure --- +tidal_vert_decayscale = 500.0 ! vertical decay scale [m] + ! (zeta in Simmons et al. 2004) + ! controls vertical distribution of tidal mixing + +! --- Diffusivity Limits --- +tidal_max_coeff = 50e-4 ! maximum tidal diffusivity [m²/s] + +! --- Spatial Limits --- +tidal_depth_cutoff = 0.0 ! minimum depth for tidal mixing [m, positive downward] + ! (0.0 = compute everywhere) + +! --- Bottom Forcing (Tidal Energy Input) --- +tidal_botforc_file = '/pool/data/AWICM/FESOM2/FORCING/IDEMIX/tidal_energy_gx1v6_20090205_rgrid.nc' / diff --git a/config/bin_2p1z1d_tp/namelist.io b/config/bin_2p1z1d_tp/namelist.io index 2f68c6701..982a17079 100644 --- a/config/bin_2p1z1d_tp/namelist.io +++ b/config/bin_2p1z1d_tp/namelist.io @@ -32,6 +32,7 @@ ldiag_destine = .false. ! enables heat content computation ('hc300m', 'hc70 ldiag_trflx = .false. ! enables tracer flux diagnostics ('utemp', 'vtemp', 'usalt', 'vsalt') ldiag_uvw_sqr = .false. ! enables 'UVW_SQR' output (squared velocities: u2, v2, w2) ldiag_trgrd_xyz = .false. ! enables 'TRGRD_XYZ' output (horizontal & vertical tracer gradients) +ldiag_cmor = .false. ! enables CMOR diagnostics for CMIP6/CMIP7 ('tos', 'sos', 'pbo', 'volo', etc.) / ! ============================================================================ @@ -52,35 +53,35 @@ compression_level = 1 ! compression level for netCDF output (1=fastest, 9 ! precision = 4 (single precision) or 8 (double precision) ! ============================================================================ &nml_list -io_list = 'sst ',1, 'm', 4, - 'sss ',1, 'm', 4, -! 'ssh ',1, 'm', 4, -! 'uice ',1, 'm', 4, -! 'vice ',1, 'm', 4, +io_list = 'sst ',1, 'y', 4, + 'sss ',1, 'y', 4, +! 'ssh ',1, 'y', 4, +! 'uice ',1, 'y', 4, +! 'vice ',1, 'y', 4, 'a_ice ',1, 'm', 4, -! 'm_ice ',1, 'm', 4, -! 'm_snow ',1, 'm', 4, +! 'm_ice ',1, 'y', 4, +! 'm_snow ',1, 'y', 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, -! 'N2 ',1, 'm', 4, -! 'Kv ',1, 'm', 4, - 'u ',1, 'm', 4, - 'v ',1, 'm', 4, -! 'unod ',1, 'm', 4, -! 'vnod ',1, 'm', 4, - 'w ',1, 'm', 4, -! 'Av ',1, 'm', 4, - 'bolus_u ',1, 'm', 4, - 'bolus_v ',1, 'm', 4, - 'bolus_w ',1, 'm', 4, -! 'fw ',1, 'm', 4, -! 'fh ',1, 'm', 4, - 'otracers ',1, 'm', 4, +! 'tx_sur ',1, 'y', 4, +! 'ty_sur ',1, 'y', 4, + 'temp ',1, 'y', 4, + 'salt ',1, 'y', 8, +! '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, +! 'Av ',1, 'y', 4, + 'bolus_u ',1, 'y', 4, + 'bolus_v ',1, 'y', 4, + 'bolus_w ',1, 'y', 4, +! 'fw ',1, 'y', 4, +! 'fh ',1, 'y', 4, + 'otracers ',1, 'y', 4, / ! ============================================================================ @@ -338,6 +339,21 @@ io_list = 'sst ',1, 'm', 4, ! --- TRACER GRADIENTS (require ldiag_trgrd_xyz=.true.) --- ! 'TRGRD_XYZ ',1, 'm', 4, ! horizontal and vertical tracer gradients +! --- CMOR DIAGNOSTICS FOR CMIP6/CMIP7 (require ldiag_cmor=.true.) --- +! 'tos ',1, 'm', 8, ! sea surface temperature [degC] (CMOR standard) +! 'sos ',1, 'm', 8, ! sea surface salinity [psu] (CMOR standard) +! 'pbo ',1, 'm', 8, ! sea water pressure at sea floor [Pa] +! 'opottemptend',1, 'm', 8,! ocean potential temperature tendency [W/m^2] +! 'volo ',1, 'm', 8, ! ocean volume [m^3] (global scalar) +! 'soga ',1, 'm', 8, ! global mean sea water salinity [psu] (global scalar) +! 'thetaoga ',1, 'm', 8, ! global mean sea water potential temperature [degC] (global scalar) +! 'siarean ',1, 'm', 8, ! sea ice area Northern hemisphere [10^12 m^2] (global scalar) +! 'siareas ',1, 'm', 8, ! sea ice area Southern hemisphere [10^12 m^2] (global scalar) +! 'siextentn ',1, 'm', 8, ! sea ice extent Northern hemisphere [10^12 m^2] (global scalar) +! 'siextents ',1, 'm', 8, ! sea ice extent Southern hemisphere [10^12 m^2] (global scalar) +! 'sivoln ',1, 'm', 8, ! sea ice volume Northern hemisphere [10^9 m^3] (global scalar) +! 'sivols ',1, 'm', 8, ! sea ice volume Southern hemisphere [10^9 m^3] (global scalar) + ! ============================================================================ ! END OF CATALOG ! ============================================================================ From fc84f0443dd7351301a726d8b502b72fbb691d07 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Sun, 11 Jan 2026 22:20:11 +0100 Subject: [PATCH 55/68] changes by Kai for benthic and sinking fluxes when using tracer parallelisation, sinking fluxes needed for MEDUSA added in io_meandata.F90 --- src/int_recom/recom_sinking.F90 | 72 +++++++++++++++++++++++++++------ src/io_meandata.F90 | 65 +++++++++++++++++++++++++++++ src/io_restart.F90 | 19 +++++++-- 3 files changed, 141 insertions(+), 15 deletions(-) diff --git a/src/int_recom/recom_sinking.F90 b/src/int_recom/recom_sinking.F90 index efe9a48b0..0c37995a2 100644 --- a/src/int_recom/recom_sinking.F90 +++ b/src/int_recom/recom_sinking.F90 @@ -134,7 +134,7 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) if( tracers%data(tr_num)%ID==1004 .or. & !iphyn tracers%data(tr_num)%ID==1007 .or. & !idetn tracers%data(tr_num)%ID==1013 ) then !idian - Benthos(n,1)= Benthos(n,1) + add_benthos_2d(n) ![mmol] +! Benthos(n,1)= Benthos(n,1) + add_benthos_2d(n) ![mmol] #if defined(__usetp) ! buffer sums per tracer index to avoid non bit identical results regarding global sums when running the tracer loop in parallel @@ -145,6 +145,11 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) ! now SinkFlx hat the unit mmol/time step ! but mmol/m2/time is needed for MEDUSA: thus /area endif +#else + Benthos(n,1)= Benthos(n,1) + add_benthos_2d(n) ![mmol] + if (use_MEDUSA) then + SinkFlx(n,1) = SinkFlx(n,1) + add_benthos_2d(n) / area(1,n)/dt ![mmol/m2] + endif #endif endif @@ -152,7 +157,7 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) if( tracers%data(tr_num)%ID==1005 .or. & !iphyc tracers%data(tr_num)%ID==1008 .or. & !idetc tracers%data(tr_num)%ID==1014 ) then - Benthos(n,2)= Benthos(n,2) + add_benthos_2d(n) +! Benthos(n,2)= Benthos(n,2) + add_benthos_2d(n) #if defined(__usetp) Benthos_tr(n,2,tr_num)= Benthos_tr(n,2,tr_num) + add_benthos_2d(n) @@ -160,13 +165,19 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) if (use_MEDUSA) then SinkFlx_tr(n,2,tr_num) = SinkFlx_tr(n,2,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif +#else + Benthos(n,2)= Benthos(n,2) + add_benthos_2d(n) + if (use_MEDUSA) then + SinkFlx(n,2) = SinkFlx(n,2) + add_benthos_2d(n) / area(1,n)/dt + endif + #endif endif !! *Particulate Organic Silicon * if( tracers%data(tr_num)%ID==1016 .or. & !idiasi tracers%data(tr_num)%ID==1017 ) then - Benthos(n,3)= Benthos(n,3) + add_benthos_2d(n) +! Benthos(n,3)= Benthos(n,3) + add_benthos_2d(n) #if defined(__usetp) Benthos_tr(n,3,tr_num)= Benthos_tr(n,3,tr_num) + add_benthos_2d(n) @@ -174,13 +185,18 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) if (use_MEDUSA) then SinkFlx_tr(n,3,tr_num) = SinkFlx_tr(n,3,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif +#else + Benthos(n,3)= Benthos(n,3) + add_benthos_2d(n) + if (use_MEDUSA) then + SinkFlx(n,3) = SinkFlx(n,3) + add_benthos_2d(n) / area(1,n)/dt + endif #endif endif !! * Cal * if( tracers%data(tr_num)%ID==1020 .or. & !iphycal tracers%data(tr_num)%ID==1021 ) then !idetcal - Benthos(n,4)= Benthos(n,4) + add_benthos_2d(n) +! Benthos(n,4)= Benthos(n,4) + add_benthos_2d(n) #if defined(__usetp) Benthos_tr(n,4,tr_num)= Benthos_tr(n,4,tr_num) + add_benthos_2d(n) @@ -188,6 +204,11 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) if (use_MEDUSA) then SinkFlx_tr(n,4,tr_num) = SinkFlx_tr(n,4,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif +#else + Benthos(n,4)= Benthos(n,4) + add_benthos_2d(n) + if (use_MEDUSA) then + SinkFlx(n,4) = SinkFlx(n,4) + add_benthos_2d(n) / area(1,n)/dt + endif #endif endif @@ -196,25 +217,37 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) if( tracers%data(tr_num)%ID==1305 .or. & !iphyc_13 tracers%data(tr_num)%ID==1308 .or. & !idetc_13 tracers%data(tr_num)%ID==1314 ) then !idiac_13 - Benthos(n,5)= Benthos(n,5) + add_benthos_2d(n) +! Benthos(n,5)= Benthos(n,5) + add_benthos_2d(n) + #if defined(__usetp) Benthos_tr(n,5,tr_num)= Benthos_tr(n,5,tr_num) + add_benthos_2d(n) if (use_MEDUSA) then SinkFlx_tr(n,5,tr_num) = SinkFlx_tr(n,5,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif +#else + Benthos(n,5)= Benthos(n,5) + add_benthos_2d(n) + if (use_MEDUSA) then + SinkFlx(n,5) = SinkFlx(n,5) + add_benthos_2d(n) / area(1,n)/dt + endif #endif endif if( tracers%data(tr_num)%ID==1320 .or. & !iphycal_13 tracers%data(tr_num)%ID==1321 ) then !idetcal_13 - Benthos(n,6)= Benthos(n,6) + add_benthos_2d(n) +! Benthos(n,6)= Benthos(n,6) + add_benthos_2d(n) + #if defined(__usetp) Benthos_tr(n,6,tr_num)= Benthos_tr(n,6,tr_num) + add_benthos_2d(n) if (use_MEDUSA) then SinkFlx_tr(n,6,tr_num) = SinkFlx_tr(n,6,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif +#else + Benthos(n,6)= Benthos(n,6) + add_benthos_2d(n) + if (use_MEDUSA) then + SinkFlx(n,6) = SinkFlx(n,6) + add_benthos_2d(n) / area(1,n)/dt + endif #endif endif @@ -225,43 +258,58 @@ subroutine ver_sinking_recom_benthos(tr_num, tracers, partit, mesh) if( tracers%data(tr_num)%ID==1405 .or. & !iphyc_14 tracers%data(tr_num)%ID==1408 .or. & !idetc_14 tracers%data(tr_num)%ID==1414 ) then !idiac_14 - Benthos(n,7)= Benthos(n,7) + add_benthos_2d(n) +! Benthos(n,7)= Benthos(n,7) + add_benthos_2d(n) + #if defined(__usetp) Benthos_tr(n,7,tr_num)= Benthos_tr(n,7,tr_num) + add_benthos_2d(n) if (use_MEDUSA) then SinkFlx_tr(n,7,tr_num) = SinkFlx_tr(n,7,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif +#else + Benthos(n,7)= Benthos(n,7) + add_benthos_2d(n) + if (use_MEDUSA) then + SinkFlx(n,7) = SinkFlx(n,7) + add_benthos_2d(n) / area(1,n)/dt + endif #endif endif if( tracers%data(tr_num)%ID==1420 .or. & !iphycal_14 tracers%data(tr_num)%ID==1421 ) then !idetcal_14 - Benthos(n,8)= Benthos(n,8) + add_benthos_2d(n) +! Benthos(n,8)= Benthos(n,8) + add_benthos_2d(n) + #if defined(__usetp) Benthos_tr(n,8,tr_num)= Benthos_tr(n,8,tr_num) + add_benthos_2d(n) if (use_MEDUSA) then SinkFlx_tr(n,8,tr_num) = SinkFlx_tr(n,8,tr_num) + add_benthos_2d(n) / area(1,n)/dt endif +#else + Benthos(n,8)= Benthos(n,8) + add_benthos_2d(n) + if (use_MEDUSA) then + SinkFlx(n,8) = SinkFlx(n,8) + add_benthos_2d(n) / area(1,n)/dt + endif #endif endif endif end do -#if defined(__usetp) if(use_MEDUSA) then do n=1, bottflx_num - call exchange_nod(SinkFlx_tr(:,n,tr_num), partit) +#if defined(__usetp) + call exchange_nod(SinkFlx_tr(:,n,tr_num), partit) +#else + call exchange_nod(SinkFlx(:,n), partit) +#endif end do end if ! use_MEDUSA -#endif do n=1, benthos_num #if defined(__usetp) call exchange_nod(Benthos_tr(:,n,tr_num), partit) -#endif +#else call exchange_nod(Benthos(:,n), partit) +#endif end do end subroutine ver_sinking_recom_benthos diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 6d1fd397f..8286d4428 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -729,6 +729,71 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) end if end if !ciso +! output of sinking fluxes for MEDUSA +CASE ('sinkPON ') + if (use_REcoM) then + if (use_MEDUSA) then + call def_stream(nod2D, myDim_nod2D, 'sinkPON','sinking flux of particulate organic nitrogen','mmolN/(m2*s)', SinkFlx(:,1), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit,mesh) + end if + end if + +CASE ('sinkPOC ') + if (use_REcoM) then + if (use_MEDUSA) then + call def_stream(nod2D, myDim_nod2D, 'sinkPOC','sinking flux of particulate organic carbon','mmolC/(m2*s)', SinkFlx(:,2), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + end if + +CASE ('sinkOpal ') + if (use_REcoM) then + if (use_MEDUSA) then + call def_stream(nod2D, myDim_nod2D, 'sinkOpal','sinking flux of opal','mmol/(m2*s)', SinkFlx(:,3), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + end if + +CASE ('sinkCalc ') + if (use_REcoM) then + if (use_MEDUSA) then + call def_stream(nod2D, myDim_nod2D, 'sinkCalc','sinking flux of CaCO3','mmol/(m2*s)', SinkFlx(:,4), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + end if + +CASE ('sinkC13 ') + if (use_REcoM) then + if (use_MEDUSA) then + if (ciso) then + call def_stream(nod2D, myDim_nod2D, 'sinkC13','sinking flux of particulate organic carbon-13','mmol/(m2*s)', SinkFlx(:,5), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + end if + end if + +CASE ('sinkCal13') + if (use_REcoM) then + if (use_MEDUSA) then + if (ciso) then + call def_stream(nod2D, myDim_nod2D, 'sinkCal13','sinking flux of CaCO3-13','mmol/(m2*s)', SinkFlx(:,6), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + end if + end if + +CASE ('sinkC14 ') + if (use_REcoM) then + if (use_MEDUSA) then + if (ciso .and. ciso_14) then + call def_stream(nod2D, myDim_nod2D, 'sinkC14','sinking flux of particulate organic carbon-14','mmol/(m2*s)', SinkFlx(:,7), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + end if + end if + +CASE ('sinkCal14') + if (use_REcoM) then + if (use_MEDUSA) then + if (ciso .and. ciso_14) then + call def_stream(nod2D, myDim_nod2D, 'sinkCal14','sinking flux of CaCO3-14','mmol/(m2*s)', SinkFlx(:,8), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + end if + end if + 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) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index c8f0a4739..fddc7a47e 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -444,7 +444,7 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn type(t_dyn) , intent(inout), target :: dynamics type(t_ice) , intent(inout), target :: ice integer, intent(in) :: which_readr - + ! Local variables logical :: is_portable_restart_write, is_raw_restart_write, is_bin_restart_write logical, save :: initialized_raw = .false. @@ -464,6 +464,7 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn integer :: tr_num_in_group logical :: has_one_added_tracer integer :: num_tracers + integer :: tr_num #endif #if defined(__recom) && defined(__usetp) @@ -471,7 +472,6 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn #include "associate_mesh_def.h" #include "associate_part_ass.h" #include "associate_mesh_ass.h" - num_tracers = tracers%num_tracers #else integer :: mpierr @@ -568,13 +568,26 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn is_bin_restart_write = is_due(trim(bin_restart_length_unit), bin_restart_length, istep) end if - ! --> synchronizes tracer data within one fesom group + ! --> synchronizes tracer data within fesom groups + +! kh 09.01.26 merging of valuesold and valuesAB between all fesom groups is only necessary here, immediately before writing the corresponding restart files +! this will give better performance than merging valuesold and valuesAB in each simulation step in the main loop over all tracers in solve_tracers_ale in oce_ale_tracers.F90 + #if defined(__recom) && defined(__usetp) if(num_fesom_groups > 1) then tr_arr_slice_count_fix_1 = 1 * (nl - 1) * (myDim_nod2D + eDim_nod2D) do group_i = 0, num_fesom_groups - 1 call calc_slice(num_tracers, num_fesom_groups, group_i, tr_num_start, tr_num_end, tr_num_in_group, has_one_added_tracer) + +! kh 09.01.26 tracers%data(:)%valuesold(:,:,:) is not contigous in memory, so an explicit inner loop over the tracers of each group is required + do tr_num = tr_num_start, tr_num_end + +! kh 09.01.26 also handle additional dimension of valuesold for AB_order + call MPI_Bcast(tracers%data(tr_num)%valuesold(:,:,:), tr_arr_slice_count_fix_1 * (tracers%data(tr_num)%AB_order - 1), MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) + + call MPI_Bcast(tracers%data(tr_num)%valuesAB(:,:), tr_arr_slice_count_fix_1, MPI_DOUBLE_PRECISION, group_i, partit%MPI_COMM_FESOM_SAME_RANK_IN_GROUPS, partit%mpierr) + end do end do end if #endif From f2951aed1cda5c6cc72db13fdd77c820dac37d32 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 3 Feb 2026 13:19:25 +0100 Subject: [PATCH 56/68] modification for biological fractionation of carbon --- src/int_recom/recom_forcing.F90.new_ciso | 353 +++ ...om_sms.F90.nica => recom_sms.F90.new_ciso} | 29 +- src/int_recom/recom_sms.F90.old | 2548 ----------------- 3 files changed, 373 insertions(+), 2557 deletions(-) create mode 100644 src/int_recom/recom_forcing.F90.new_ciso rename src/int_recom/{recom_sms.F90.nica => recom_sms.F90.new_ciso} (98%) delete mode 100644 src/int_recom/recom_sms.F90.old diff --git a/src/int_recom/recom_forcing.F90.new_ciso b/src/int_recom/recom_forcing.F90.new_ciso new file mode 100644 index 000000000..155846b46 --- /dev/null +++ b/src/int_recom/recom_forcing.F90.new_ciso @@ -0,0 +1,353 @@ +!=============================================================================== +! REcoM_Forcing +!=============================================================================== +subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali_depth & + , CO2_watercolumn & + , pH_watercolumn & + , pCO2_watercolumn & + , HCO3_watercolumn & + , CO3_watercolumn & + , OmegaC_watercolumn & + , kspc_watercolumn & + , rhoSW_watercolumn & + , PAR, ice, dynamics, tracers, partit, mesh) + + use recom_declarations + use recom_locvar + use recom_config + use recom_glovar + use gasx + use recom_ciso + use g_clock + use o_PARAM + use g_rotate_grid + use g_config + use mod_mesh + USE MOD_PARTIT + USE MOD_PARSUP + use mod_tracer + use MOD_DYN + use MOD_ICE + + use o_param + use o_arrays + use g_forcing_arrays + use g_comm_auto + use g_support + implicit none + + type(t_dyn) , intent(inout), target :: dynamics + type(t_ice) , intent(inout), target :: ice + type(t_tracer), intent(inout), target :: tracers + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(inout), target :: mesh + + real(kind=8) :: Latr + integer :: n, Nn ! Nn -Total number of nodes + real(kind=8),dimension(mesh%nl-1) :: zNodes ! Depth of nodes zr(1:nzmax) = Z_3d_n(1:nzmax,n) + real(kind=8),dimension(mesh%nl-1,bgc_num) :: state + real(kind=8) :: SurfSW ! [W/m2] ShortWave radiation at surface + real(kind=8) :: Loc_slp ! [Pa] sea-level pressure + real(kind=8),dimension(mesh%nl-1) :: Temp ! [degrees C] Ocean temperature + real(kind=8),dimension(mesh%nl-1) :: Sali_depth ! Salinity for the whole water column + + !!---- Watercolumn carbonate chemistry + real(kind=8),dimension(mesh%nl-1) :: CO2_watercolumn + real(kind=8),dimension(mesh%nl-1) :: pH_watercolumn + real(kind=8),dimension(mesh%nl-1) :: pCO2_watercolumn + real(kind=8),dimension(mesh%nl-1) :: HCO3_watercolumn + real(kind=8),dimension(mesh%nl-1) :: CO3_watercolumn + real(kind=8),dimension(mesh%nl-1) :: OmegaC_watercolumn + real(kind=8),dimension(mesh%nl-1) :: kspc_watercolumn + real(kind=8),dimension(mesh%nl-1) :: rhoSW_watercolumn + + real(kind=8),dimension(mesh%nl-1) :: PAR + + !!---- 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-1) :: thick ! [m] Vertical distance between two nodes = Thickness + real(kind=8),dimension(mesh%nl-1) :: recipthick ! [1/m] reciprocal of thick + + !!---- Subroutine CO2Flux /mocsy + real(kind=8) :: REcoM_DIC(1) ! [mol/m3] Conc of DIC in the surface water, used to calculate CO2 flux + real(kind=8) :: REcoM_Alk(1) ! [mol/m3] Conc of Alk in the surface water, used to calculate CO2 flux + real(kind=8) :: REcoM_Si(1) ! [mol/m3] Conc of Si in the surface water, used to calculate CO2 flux + real(kind=8) :: REcoM_Phos(1) ! [mol/m3] Conc of Phos in the surface water, used to calculate the CO2 flux + real(kind=8) :: Sali(1) ! Salinity of current surface layer + real(kind=8) :: Latd(1) ! latitude in degree + real(kind=8) :: Lond(1) ! longitude in degree + real(kind=8) :: REcoM_T(1) ! temperature again, for mocsy minimum defined as -2 + real(kind=8) :: REcoM_S(1) ! temperature again, for mocsy minimum defined as 21 +! atm pressure, now read in as forcing!! + !!---- atm pressure + real(kind=8) :: Patm(1) ! atmospheric pressure [atm] + + !!---- Subroutine o2flux /mocsy + real(kind=8) :: ppo(1) ! atmospheric pressure, divided by 1 atm + real(kind=8) :: REcoM_O2(1) ! [mmol/m3] Conc of O2 in the surface water, used to calculate O2 flux + + !!---- Subroutine REcoM_sms + real(kind=8),dimension(mesh%nl-1,bgc_num) :: sms ! matrix that entail changes in tracer concentrations + + !!---- Diagnostics + integer :: idiags,k + + integer :: tr_num + +#include "../associate_part_def.h" +#include "../associate_mesh_def.h" +#include "../associate_part_ass.h" +#include "../associate_mesh_ass.h" + + + 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 + + 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 + + tiny_Si = tiny_C_d/SiCmax ! SiCmax = 0.8d0 + +#if defined (__coccos) + 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 + + call Cobeta(partit, mesh) + call Depth_calculations(n, Nn,SinkVel,zF,thick,recipthick, partit, mesh) + + !! *** Mocsy *** + + !!---- convert from mmol/m3 to mol/m3 + REcoM_DIC = max(tiny*1e-3, state(one,idic)*1e-3) + REcoM_Alk = max(tiny*1e-3, state(one,ialk)*1e-3) + REcoM_Si = max(tiny*1e-3, state(one,isi) *1e-3) + + !!---- convert N to P with Redfield ratio + REcoM_Phos = max(tiny*1e-3, state(one,idin)*1e-3) /16. + + !!---- minimum set to 2 degC: K1/K2 Lueker valid between 2degC-35degC and 19-43psu + REcoM_T = max(2.d0, Temp(1)) + !!---- maximum set to 40 degC: K1/K2 Lueker valid between 2degC-35degC and 19-43psu + 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)) + !!---- 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. + Patm = Loc_slp/Pa2atm + + !!---- lon + Lond=geo_coord_nod2D(1,n)/rad !! convert from rad to degree + !!---- lat + Latr=geo_coord_nod2D(2,n) + Latd=geo_coord_nod2D(2,n)/rad !! convert from rad to degree + + !!---- calculate piston velocity kw660, which is an input to the flxco2 calculation + !!---- pistonvel already scaled for ice-free area + !!---- compute piston velolicty kw660 (at 25 C) from wind speed + !!---- BUT without Schmidt number temperature correction (Sc differs each gas) + !! ULoc: wind speed at 10-m height + !! Loc_ice_conc: modeled sea-ice cover: fraction of grid cell, varying between 0.0 (no ice) and 1.0 (full cover) + !! kw660: piston velocity at 25°C [m/s], uncorrected by the Schmidt number for different temperatures + + call pistonvel(ULoc, Loc_ice_conc, Nmocsy, kw660) + + !! *** check *** + + if((REcoM_DIC(1) > 10000.d0)) then ! NEW: added this entire print statement (if to endif) + print*, 'NEW ERROR: DIC !' + print*, 'pco2surf: ',pco2surf + print*, 'co2: ',co2 + print*, 'rhoSW: ', rhoSW + print*, 'temp: ',REcoM_T + print*, 'tempis: ',tempis + print*, 'REcoM_S: ', REcoM_S + print*, 'REcoM_Alk: ', REcom_Alk + print*, 'REcoM_DIC: ', REcoM_DIC + print*, 'REcoM_Si: ', REcoM_Si + print*, 'REcoM_Phos: ', REcoM_Phos + print*, 'kw660: ',kw660 + print*, 'LocAtmCO2: ', LocAtmCO2 + print*, 'Patm: ', Patm + print*, 'thick(One): ',thick(One) + print*, 'Nmocsy: ', Nmocsy + print*, 'Lond: ', Lond + print*, 'Latd: ', Latd + print*, 'ULoc: ', ULoc + print*, 'Loc_ice_conc: ', Loc_ice_conc + stop + endif + + call flxco2(co2flux, co2ex, dpco2surf, & + ph, pco2surf, fco2, co2, hco3, co3, OmegaA, OmegaC, BetaD, rhoSW, p, tempis, & + 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') + +! changed optK1K2='l ' to 'm10' + if((co2flux(1)>1.e10) .or. (co2flux(1)<-1.e10)) then +! co2flux(1)=0.0 + print*, 'ERROR: co2 flux !' + print*, 'pco2surf: ',pco2surf + print*, 'co2: ',co2 + print*, 'rhoSW: ', rhoSW + print*, 'temp: ',REcoM_T + print*, 'tempis: ',tempis + print*, 'REcoM_S: ', REcoM_S + print*, 'REcoM_Alk: ', REcom_Alk + print*, 'REcoM_DIC: ', REcoM_DIC + print*, 'REcoM_Si: ', REcoM_Si + print*, 'REcoM_Phos: ', REcoM_Phos + print*, 'kw660: ',kw660 + print*, 'LocAtmCO2: ', LocAtmCO2 + print*, 'Patm: ', Patm + print*, 'thick(One): ',thick(One) + print*, 'Nmocsy: ', Nmocsy + print*, 'Lond: ', Lond + print*, 'Latd: ', Latd + print*, 'ULoc: ', ULoc + print*, 'Loc_ice_conc: ', Loc_ice_conc + stop + endif + +! use ice-free area and also convert from mol/m2/s to mmol/m2/d +! if(mype==0) write(*,*), 'co2flux (mol/m2/s) =',co2flux + +! ice-fraction is already considered in piston-velocity, so don't apply it here + dflux = co2flux * 1.e3 *SecondsPerDay !* (1.d0 - Loc_ice_conc) +! if(mype==0) write(*,*), 'dflux (mmol/m2/d) =',dflux + + co2flux_seaicemask = co2flux * 1.e3 ! [mmol/m2/s] * (1.d0 - Loc_ice_conc) +! if(mype==0) write(*,*), 'co2flux_seaicemask (mmol/m2/s) =',co2flux_seaicemask + +! then oxygen + ppo = Loc_slp/Pa2atm !1 !slp divided by 1 atm + REcoM_O2 = max(tiny*1e-3,state(one,ioxy)*1e-3) ! convert from mmol/m3 to mol/m3 for mocsy + + call o2flux(REcoM_T, REcoM_S, kw660, ppo, REcoM_O2, Nmocsy, o2ex) + oflux = o2ex * 1.e3 *SecondsPerDay !* (1.d0 - Loc_ice_conc) [mmol/m2/d] + o2flux_seaicemask = o2ex * 1.e3 ! back to mmol here [mmol/m2/s] + +! Source-Minus-Sinks + +if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> REcoM_sms'//achar(27)//'[0m' + +! call REcoM_sms(n, Nn, state, thick, recipthick, SurfSW, sms, Temp ,zF, PAR, mesh) + + call REcoM_sms(n, Nn, state, thick, recipthick, SurfSW, sms, Temp, Sali_depth & + , CO2_watercolumn & ! MOCSY [mol/m3] + , pH_watercolumn & ! MOCSY on total scale + , pCO2_watercolumn & ! MOCSY [uatm] + , HCO3_watercolumn & ! MOCSY [mol/m3] + , CO3_watercolumn & ! DISS [mol/m3] + , OmegaC_watercolumn & ! DISS calcite saturation state + , kspc_watercolumn & ! DISS stoichiometric solubility product [mol^2/kg^2] + , rhoSW_watercolumn & ! DISS in-situ density of seawater [kg/m3] + , Loc_slp & + , zF, PAR, Lond, Latd, ice, dynamics, tracers, partit, mesh) + + state(1:nn,:) = max(tiny,state(1:nn,:) + sms(1:nn,:)) + + state(1:nn,ipchl) = max(tiny_chl,state(1:nn,ipchl)) + state(1:nn,iphyn) = max(tiny_N, state(1:nn,iphyn)) + state(1:nn,iphyc) = max(tiny_C, state(1:nn,iphyc)) + state(1:nn,idchl) = max(tiny_chl,state(1:nn,idchl)) + state(1:nn,idian) = max(tiny_N_d,state(1:nn,idian)) + 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) + 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,imiczoon) = max(tiny,state(1:nn,imiczoon)) + state(1:nn,imiczooc) = max(tiny,state(1:nn,imiczooc)) +#endif + +if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> ciso after REcoM_Forcing'//achar(27)//'[0m' + +! 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)) + state(1:nn,iphyc_13) = max((tiny_C * r_phyc_13), state(1:nn,iphyc_13)) + state(1:nn,idiac_13) = max((tiny_C_d * r_diac_13), state(1:nn,idiac_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)) + state(1:nn,iphyc_14) = max((tiny_C * r_phyc_14), state(1:nn,iphyc_14)) + state(1:nn,idiac_14) = max((tiny_C_d * r_diac_14), state(1:nn,idiac_14)) + end if + end if +! Radiocarbon + end if +! ciso + +!------------------------------------------------------------------------------- +! Diagnostics + if (Diags) then + +! logical, optional :: lNPPn + +! if (present(lNPPn))then +! locNPPn = sum(diags3Dloc(1:nn,idiags) * thick(1:nn)) +! endif + locNPPn = sum(vertNPPn(1:nn) * thick(1:nn)) + locGPPn = sum(vertGPPn(1:nn) * thick(1:nn)) + locNNAn = sum(vertNNAn(1:nn) * thick(1:nn)) + locChldegn = sum(vertChldegn(1:nn) * thick(1:nn)) + + locNPPd = sum(vertNPPd(1:nn) * thick(1:nn)) + locGPPd = sum(vertGPPd(1:nn) * thick(1:nn)) + locNNAd = sum(vertNNAd(1:nn) * thick(1:nn)) + locChldegd = sum(vertChldegd(1:nn) * thick(1:nn)) + +#if defined (__coccos) + 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)) +#endif + + end if +end subroutine REcoM_Forcing diff --git a/src/int_recom/recom_sms.F90.nica b/src/int_recom/recom_sms.F90.new_ciso similarity index 98% rename from src/int_recom/recom_sms.F90.nica rename to src/int_recom/recom_sms.F90.new_ciso index b9a4892f4..513163130 100644 --- a/src/int_recom/recom_sms.F90.nica +++ b/src/int_recom/recom_sms.F90.new_ciso @@ -459,7 +459,9 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------ ! Calcite dissolution dependent on OmegaC ! DISS !------------------------------------------------------------------------------ - Sink_Vel = Vdet_a* abs(zF(k)) + Vdet +!Ying 26.12.2025: calcite dissolution applied a different depth dependence relative to sinking + Sink_Vel = Vcalc * abs(zF(k)) + Vdet +! 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 @@ -2086,9 +2088,11 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! DIC_13 sms(k,idic_13) = ( & - - Cphot * PhyC_13 & +! - Cphot * PhyC_13 & + - Cphot * r_phyc_13 * PhyC & + phyRespRate * PhyC_13 & - - Cphot_Dia * DiaC_13 & +! - Cphot_Dia * DiaC_13 & + - Cphot_Dia * r_diac_13 * DiaC & + phyRespRate_Dia * DiaC_13 & + rho_C1 * arrFunc * EOC_13 & + HetRespFlux_13 & @@ -2099,7 +2103,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! Phytoplankton C_13 sms(k,iphyc_13) = ( & - + Cphot * PhyC_13 & +! + Cphot * PhyC_13 & + + Cphot * r_phyc_13 * PhyC & - lossC * limitFacN * PhyC_13 & - phyRespRate * PhyC_13 & - aggregationRate * PhyC_13 & @@ -2139,7 +2144,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! Diatom C_13 sms(k,idiac_13) = ( & - + Cphot_dia * DiaC_13 & +! + Cphot_dia * DiaC_13 & + + Cphot_dia * r_diac_13 * DiaC & - lossC_d * limitFacN_dia * DiaC_13 & - phyRespRate_dia * DiaC_13 & - aggregationRate * DiaC_13 & @@ -2170,9 +2176,11 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & if (ciso_organic_14) then ! DIC_14 sms(k,idic_14) = ( & - - Cphot * PhyC_14 & +! - Cphot * PhyC_14 & + - Cphot * r_phyc_14 * PhyC & + phyRespRate * PhyC_14 & - - Cphot_Dia * DiaC_14 & +! - Cphot_Dia * DiaC_14 & + - Cphot_Dia * r_diac_14 * DiaC & + phyRespRate_Dia * DiaC_14 & + rho_C1 * arrFunc * EOC_14 & + HetRespFlux_14 & @@ -2183,7 +2191,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! Phytoplankton C_14 sms(k,iphyc_14) = ( & - + Cphot * PhyC_14 & +! + Cphot * PhyC_14 & + + Cphot * r_phyc_14 * PhyC & - lossC * limitFacN * PhyC_14 & - phyRespRate * PhyC_14 & - aggregationRate * PhyC_14 & @@ -2223,7 +2232,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! Diatom C_14 sms(k,idiac_14) = ( & - + Cphot_dia * DiaC_14 & +! + Cphot_dia * DiaC_14 & + + Cphot_dia * r_diac_14 * DiaC & - lossC_d * limitFacN_dia * DiaC_14 & - phyRespRate_dia * DiaC_14 & - aggregationRate * DiaC_14 & @@ -2252,6 +2262,7 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & else ! "Abiotic" DIC_14, identical to DIC except for radioactive decay (-> ! recom_forcing) +!YY: change of DIC14 equal to that of DIC, why? sms(k,idic_14) = sms(k,idic) end if ! ciso_organic_14 end if ! ciso_14 diff --git a/src/int_recom/recom_sms.F90.old b/src/int_recom/recom_sms.F90.old deleted file mode 100644 index 7259fd893..000000000 --- a/src/int_recom/recom_sms.F90.old +++ /dev/null @@ -1,2548 +0,0 @@ -subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & - , CO2_watercolumn & - , pH_watercolumn & - , pCO2_watercolumn & - , HCO3_watercolumn & - , CO3_watercolumn & - , OmegaC_watercolumn & - , kspc_watercolumn & - , rhoSW_watercolumn & - , Loc_slp, zF, PAR, Lond, Latd, ice, dynamics, tracers, partit, mesh) - - use recom_declarations - use recom_locvar - use recom_glovar - use recom_config - use recoM_ciso - use g_clock - - use g_config - use MOD_MESH - use MOD_TRACER - use MOD_DYN - USE MOD_ICE - use o_ARRAYS - use o_PARAM - USE MOD_PARTIT - USE MOD_PARSUP - - use g_forcing_arrays - use g_comm_auto - use mvars - use mdepth2press - use gsw_mod_toolbox, only: gsw_sa_from_sp,gsw_ct_from_pt,gsw_rho - - implicit none - type(t_dyn) , intent(inout), target :: dynamics - type(t_tracer), intent(inout), target :: tracers - type(t_partit), intent(inout), target :: partit - type(t_mesh) , intent(inout), target :: mesh - type(t_ice) , intent(inout), target :: ice - - 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 - - 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 - real(kind=8),intent(in) :: SurfSR !< [W/m2] ShortWave radiation at surface - - real(kind=8),dimension(mesh%nl-1,bgc_num),intent(inout) :: sms !< Source-Minus-Sinks term - real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Temp !< [degrees C] Ocean temperature - real(kind=8),dimension(mesh%nl-1) ,intent(in) :: Sali_depth !< NEW MOCSY Salinity for the whole water column - - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO2_watercolumn !< [mol/m3] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pH_watercolumn !< on total scale - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: pCO2_watercolumn !< [uatm] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: HCO3_watercolumn !< [mol/m3] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: CO3_watercolumn !< [mol/m3] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: OmegaC_watercolumn !< calcite saturation state - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: kspc_watercolumn !< stoichiometric solubility product [mol^2/kg^2] - Real(kind=8),dimension(mesh%nl-1),intent(inout) :: rhoSW_watercolumn !< in-situ density of seawater [kg/m3] - - real(kind=8),dimension(mesh%nl) ,intent(in) :: zF !< [m] Depth of fluxes - real(kind=8),dimension(mesh%nl-1),intent(inout) :: PAR - - real(kind=8) :: dt_d !< Size of time steps [day] - real(kind=8) :: dt_b !< Size of time steps [day] - real(kind=8),dimension(mesh%nl-1) :: Sink - real(kind=8) :: dt_sink !< Size of local time step - - real(kind=8) :: recip_hetN_plus !< MB's addition to heterotrophic respiration - real(kind=8) :: recip_res_het !< [day] Reciprocal of respiration by heterotrophs and mortality (loss to detritus) - real(kind=8) :: Sink_Vel - real(kind=8) :: aux - integer :: k,step,ii, idiags,n - - real(kind=8), intent(in) :: Loc_slp ![Pa] sea-level pressure - real(kind=8) :: Patm_depth(1) - real(kind=8) :: REcoM_T_depth(1) ! MOCSY temperature for the whole water column for mocsy minimum defined as -2 - real(kind=8) :: REcoM_S_depth(1) - real(kind=8) :: REcoM_DIC_depth(1) - real(kind=8) :: REcoM_Alk_depth(1) - real(kind=8) :: REcoM_Si_depth(1) - real(kind=8) :: REcoM_Phos_depth(1) - 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 - -#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 - - 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 - - tiny_Si = tiny_C_d/SiCmax !< SiCmax = 0.8d0 - -#if defined (__coccos) - tiny_N_c = tiny_chl/chl2N_max_c - tiny_C_c = tiny_N_c/NCmax_c -#endif - - recip_res_het = 1.d0/res_het !< res_het = 0.01d0 [1/day] Respiration by heterotrophs and mortality (loss to detritus) - - Patm_depth = Loc_slp/Pa2atm ! MOCSY convert from Pa to atm. - -!------------------------------------------------------------------------------- -!> REcoM time steps [day] -!------------------------------------------------------------------------------- - - 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] - -!------------------------------------------------------------------------------- -!Main time loop starts - do step = one,biostep - - kdzUpper = 0.d0 !< Upper light attenuation of top cell is set to zero - - if (any(abs(sms(:,:)) <= tiny)) sms(:,:) = zero ! tiny = 2.23D-16 - -!------------------------------------------------------------------------------- -! 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 - -! 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 - - if (ciso) then -!< additional variables are declared in module REcoM_ciso - 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)) - - calc_diss_13 = alpha_dcal_13 * calc_diss - - 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 - - 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 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) - -!------------------------------------------------------------------------------- -!> 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 - -!------------------------------------------------------------------------------- -! Depth component of Mocsy (see http://ocmip5.ipsl.jussieu.fr/mocsy/pyth.html) -!------------------------------------------------------------------------------- - -! 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. - 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') - CO2_watercolumn(k) = co2_depth(1) - pH_watercolumn(k) = ph_depth(1) - pCO2_watercolumn(k) = pco2_depth(1) - HCO3_watercolumn(k) = hco3_depth(1) - CO3_watercolumn(k) = co3_depth(1) - 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') - CO2_watercolumn(k) = co2_depth(1) - pH_watercolumn(k) = ph_depth(1) - pCO2_watercolumn(k) = pco2_depth(1) - HCO3_watercolumn(k) = hco3_depth(1) - CO3_watercolumn(k) = co3_depth(1) - OmegaC_watercolumn(k) = OmegaC_depth(1) - 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') - CO2_watercolumn(k) = co2_depth(1) - pH_watercolumn(k) = ph_depth(1) - pCO2_watercolumn(k) = pco2_depth(1) - HCO3_watercolumn(k) = hco3_depth(1) - CO3_watercolumn(k) = co3_depth(1) - 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] - -! 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 - -! 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 - 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) - 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?? - 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 - -!< *** Diatom photosynthesis rate *** -!< ********************************** - if ( pMax_dia .lt. 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 - - 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 - else - KOchl = deg_Chl*(real(one) - exp(-alfa * CHL2C_plast * PARave / pMax)) - KOchl = max((deg_Chl*0.1d0), KOchl) - 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 - 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 - 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 - 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 - stop - end if -#endif - end if ! photodamage - -!------------------------------------------------------------------------------- -!> Assimilation section -!------------------------------------------------------------------------------- - -!< 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 - 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 - - limitFacSi = recom_limiter(SiMaxSlope, qSiC, SiCmax) & - * limitFacN_dia - Si_assim = V_cm_fact_d * P_cm_d * arrFunc * SiCUptakeRatio & - * limitFacSi * Si/(Si + k_si) - -!------------------------------------------------------------------------------- -!< *** Iron chemistry *** -!< ********************** -! select the method to calculate freeFe - freeFe = iron_chemistry(Fe,totalligand,ligandStabConst) -!------------------------------------------------------------------------------- -!< *** Chlorophyll synthesis *** -!< ***************************** - -!< 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 ] - - 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 - 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 *** -!< ************************************* - -!< res_phy: Maintenance respiration rate constant [day−1 ] -!< biosynth: The cost of biosynthesis of N [mmol C mmol N−1 ] - - phyRespRate = res_phy * limitFacN + biosynth * N_assim - phyRespRate_dia = res_phy_d * limitFacN_dia + biosynth * N_assim_dia + biosynthSi * Si_assim -#if defined (__coccos) - phyRespRate_cocco = res_phy_c * limitFacN_cocco + biosynth * N_assim_cocco -#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 - -!< *** 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 - -!------------------------------------------------------------------------------- -! 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 - -!< *** 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 - - grazingFlux_phy2 = (grazingFlux2 * fphyN2)/food2 - grazingFlux_Dia2 = (grazingFlux2 * fDiaN2)/food2 - grazingFlux_miczoo2 = (grazingFlux2 * fMicZooN2)/food2 ! 3Zoo - -#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 - - 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 - -!------------------------------------------------------------------------------- -! Third Zooplankton (Microzooplankton) -!------------------------------------------------------------------------------- -!< Grazing on small phytoplankton, diatoms and coccolithophore (optional) - -!< *** Food availability *** -!< ************************* -!< pzPhy3: Maximum nanophytoplankton preference -!< pzDia3: Maximum diatom preference -!< pzCocco3: Maximum coccolithophore preference - - 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 - -!------------------------------------------------------------------------------- -!< 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 - endif - - if (ciso) then -!MB set HetRespFlux_plus = .true. in namelist.recom -! HetRespFlux_13 = max(zero, recip_res_het * arrFunc * (hetC_13 * recip_hetN_plus - redfield) * HetC_13) -! Numerically safer parametrization avoiding instable results which may result from different cutoff values -- CHECK - HetRespFlux_13 = HetRespFlux * HetC_13 / HetC -!! HetRespFlux_13 = HetRespFlux * (HetC_13 / HetC) **2 - if (ciso_14 .and. ciso_organic_14) then -! HetRespFlux_14 = max(zero, recip_res_het * arrFunc * (hetC_14 * recip_hetN_plus - redfield) * HetC_14) - HetRespFlux_14 = HetRespFlux * HetC_14 / HetC -!! HetRespFlux_14 = HetRespFlux * (HetC_14 / HetC) **2 - end if - end if - -!------------------------------------------------------------------------------- -!< Zooplanton mortality (Quadratic) - - hetLossFlux = loss_het * HetN * HetN - -#if defined (__3Zoo2Det) -!------------------------------------------------------------------------------- -!< Second zooplankton respiration - - call krill_resp(n, partit, mesh) - - 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) - - Zoo2LossFlux = loss_zoo2 * zoo2N * zoo2N - -!------------------------------------------------------------------------------- -!< Second zooplankton fecal pellets - - Zoo2fecalloss_n = fecal_rate_n * grazingFlux2 - Zoo2fecalloss_c = fecal_rate_c * grazingFluxcarbonzoo2 - -!------------------------------------------------------------------------------- -!< Mesozooplankton fecal pellets - - mesfecalloss_n = fecal_rate_n_mes * grazingFlux - mesfecalloss_c = fecal_rate_c_mes * grazingFluxcarbon_mes - -!------------------------------------------------------------------------------- -! Third zooplankton, microzooplankton, respiration ! 3Zoo - - MicZooRespFlux = res_miczoo * q10_mic_res * MicZooC -!------------------------------------------------------------------------------- -! Third zooplankton, microzooplankton, mortality (Quadratic) ! 3Zoo - - MicZooLossFlux = loss_miczoo * MicZooN * MicZooN -#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 - 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 - -#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 - - if (ciso) then - calcification_13 = calc_prod_ratio * Cphot * PhyC_13 * alpha_calc_13 - calcification_13 = calcification * alpha_calc_13 - calc_loss_agg_13 = aggregationRate * PhyCalc_13 - calc_loss_gra_13 = grazingFlux_phy * recipQuota_13/(PhyC_13 + tiny) * PhyCalc_13 - if (ciso_14 .and. ciso_organic_14) then - calcification_14 = calc_prod_ratio * Cphot * PhyC_14 * alpha_calc_14 - calc_loss_agg_14 = aggregationRate * PhyCalc_14 - calc_loss_gra_14 = grazingFlux_phy * recipQuota_14/(PhyC_14 + tiny) * PhyCalc_14 - end if - end if - -!------------------------------------------------------------------------------- -! Sources minus sinks (SMS) -!------------------------------------------------------------------------------- - -!< *** 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((Latd(1)<-45.0) .and. ((state(k,idic)+sms(k,idic))>2500)) then -! !co2flux(1)=0.0 -! print*,'ERROR: strange dic !' -! print*,'state(k,idic): ', state(k,idic) -! print*,'sms Cphot: ', -Cphot*PhyC -! print*,'sms resp: ', phyRespRate*PhyC -! print*,'sms Cphot dia: ', -Cphot_Dia*DiaC -! print*,'sms resp dia: ', phyRespRate_Dia * DiaC -! print*,'sms eoc: ', rho_C1* arrFunc *EOC -! print*,'sms het resp: ', HetRespFlux -! print*, 'sms co2: ', dflux(1) * recipdzF(k) * max( 2-k, 0 ) -! print*, 'sms calcdiss: ', calc_diss * DetCalc -! print*, 'sms calc_loss: ', calc_loss_gra * calc_diss_guts -! print*, 'sms calcification: ', -calcification -! 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 & ! --> grazing on small phytoplankton by third zooplankton - - grazingFlux_phy3 * grazEff3 & ! --> fraction of grazingFlux_phy3 into microzooplankton pool - + grazingFlux_dia3 & ! --> grazing on diatoms by third zooplankton - - grazingFlux_dia3 * grazEff3 & ! --> fraction of grazingFlux_dia3 into microzooplankton pool -#if defined (__coccos) - + grazingFlux_Cocco3 & ! --> grazing on coccolithophores by third zooplankton - - grazingFlux_Cocco3 * grazEff3 & ! --> fraction of grazingFlux_Cocco3 into microzooplankton pool - + aggregationRate * CoccoN & -#endif - - grazingFlux_Det * grazEff & ! --> grazing of first zoo (meso) on first detritus class - - grazingFlux_Det2 * grazEff2 & ! --> grazing of second zoo (macro) on first detritus class - + aggregationRate * PhyN & - + aggregationRate * DiaN & - + miczooLossFlux & ! --> microzooplankton, mortality - - reminN * arrFunc * O2Func * DetN & ! --> O2remin - ) * dt_b + sms(k,idetn) -#else - sms(k,idetn) = ( & - + grazingFlux_phy & ! Technically it is mesooooooooooooooooo - - 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 * recipDet * grazEff2 & ! corrected recipDet2 -> recipDet - + 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 - 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) - else - sms(k,ihetc) = ( & - + grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia * grazEff & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco * grazEff & -#endif -#if defined (__3Zoo2Det) - + grazingFlux_miczoo * recipQZoo3 * grazEff & ! 3Zoo - - grazingFlux_het2 * recipQZoo & - - Mesfecalloss_c & ! 3Zoo -#endif - - hetLossFlux * recipQZoo & - - lossC_z * HetC & - - hetRespFlux & - ) * dt_b + sms(k,ihetc) - endif - -!< *** Macrozooplankton *** -!< ************************ - -#if defined (__3Zoo2Det) -!____________________________________________________________ -!< Second Zooplankton N - sms(k,izoo2n) = ( & - + grazingFlux2 * grazEff2 & - - Zoo2LossFlux & - - lossN_z2 * Zoo2N & - - Zoo2fecalloss_n & - ) * dt_b + sms(k,izoo2n) - -!____________________________________________________________ -!< Second Zooplankton C - if (Grazing_detritus) then - - sms(k,izoo2c) = ( & - + grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo - + grazingFlux_Det2 * recipDet * grazEff2 & - + grazingFlux_DetZ22 * recipDet2 * grazEff2 & - - zoo2LossFlux * recipQZoo2 & - - lossC_z2 * Zoo2C & - - Zoo2RespFlux & - - Zoo2fecalloss_c & - ) * dt_b + sms(k,izoo2c) - else - sms(k,izoo2c) = ( & - + grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2* recipQZoo3 * grazEff2 & ! 3Zoo - - zoo2LossFlux * recipQZoo2 & - - lossC_z2 * Zoo2C & - - Zoo2RespFlux & - - Zoo2fecalloss_c & - ) * dt_b + sms(k,izoo2c) - end if - -!< *** Microzooplankton *** -!< ************************ - -!____________________________________________________________ -!< Third Zooplankton N - sms(k,imiczoon) = ( & - + grazingFlux3 * grazEff3 & - - grazingFlux_miczoo & - - grazingFlux_miczoo2 & - - MicZooLossFlux & - - lossN_z3 * MicZooN & - ) * dt_b + sms(k,imiczoon) - -!____________________________________________________________ -!< Third Zooplankton C - sms(k,imiczooc) = ( & - + grazingFlux_phy3 * recipQuota * grazEff3 & - + grazingFlux_Dia3 * recipQuota_Dia * grazEff3 & -#if defined (__coccos) - + grazingFlux_Cocco3 * recipQuota_Cocco * grazEff3 & -#endif - - MicZooLossFlux * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 & - - lossC_z3 * MicZooC & - - MicZooRespFlux & - ) * dt_b + sms(k,imiczooc) - -!< *** Fast-sinking Detritus *** -!< ***************************** - -!____________________________________________________________ -!< Second Zooplankton Detritus N - if (Grazing_detritus) then - sms(k,idetz2n) = ( & - + grazingFlux_phy2 & - - grazingFlux_phy2 * grazEff2 & - + grazingFlux_dia2 & - - grazingFlux_dia2 * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco & - - grazingFlux_Cocco * grazEff & - + grazingFlux_Cocco2 & - - grazingFlux_Cocco2 * grazEff2 & -#endif - + grazingFlux_het2 & - - grazingFlux_het2 * grazEff2 & - + grazingFlux_miczoo2 & - - grazingFlux_miczoo2 * grazEff2 & - + grazingFlux_phy & - - grazingFlux_phy * grazEff & - + grazingFlux_dia & - - grazingFlux_dia * grazEff & - + grazingFlux_miczoo & - - grazingFlux_miczoo * grazEff & - - grazingFlux_DetZ2 * grazEff & - - grazingFlux_DetZ22 * grazEff2 & - + Zoo2LossFlux & - + hetLossFlux & - + Zoo2fecalloss_n & - + Mesfecalloss_n & - - reminN * arrFunc * O2Func * DetZ2N & ! O2remin - ) * dt_b + sms(k,idetz2n) - else - sms(k,idetz2n) = ( & - + grazingFlux_phy2 & - + grazingFlux_dia2 & -#if defined (__coccos) - + grazingFlux_Cocco & - + grazingFlux_Cocco2 & -#endif - + grazingFlux_het2 & - + grazingFlux_miczoo2 & - - grazingFlux2 * grazEff2 & - + grazingFlux_phy & - + grazingFlux_dia & - + grazingFlux_miczoo & - - grazingFlux * grazEff & - + Zoo2LossFlux & - + hetLossFlux & - + Zoo2fecalloss_n & - + Mesfecalloss_n & - - reminN * arrFunc * O2Func * DetZ2N & ! O2remin - ) * dt_b + sms(k,idetz2n) - end if - -!____________________________________________________________ -!< Second Zooplankton Detritus C - if (Grazing_detritus) then - sms(k,idetz2c) = ( & - + grazingFlux_phy2 * recipQuota & - - grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia & - - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + grazingFlux_Cocco2 * recipQuota_Cocco & - - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo & - - grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2 * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & - + grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 * grazEff & - - grazingFlux_DetZ2 * recipDet2 * grazEff & - - grazingFlux_DetZ22 * recipDet2 * grazEff2 & - + Zoo2LossFlux * recipQZoo2 & - + hetLossFlux * recipQZoo & - + Zoo2fecalloss_c & - + Mesfecalloss_c & - - reminC * arrFunc * O2Func * DetZ2C & ! O2remin - ) * dt_b + sms(k,idetz2c) - else - sms(k,idetz2c) = ( & - + grazingFlux_phy2 * recipQuota & - - grazingFlux_phy2 * recipQuota * grazEff2 & - + grazingFlux_Dia2 * recipQuota_Dia & - - grazingFlux_Dia2 * recipQuota_Dia * grazEff2 & -#if defined (__coccos) - + grazingFlux_Cocco * recipQuota_Cocco & - - grazingFlux_Cocco * recipQuota_Cocco * grazEff & - + grazingFlux_Cocco2 * recipQuota_Cocco & - - grazingFlux_Cocco2 * recipQuota_Cocco * grazEff2 & -#endif - + grazingFlux_het2 * recipQZoo & - - grazingFlux_het2 * recipQZoo * grazEff2 & - + grazingFlux_miczoo2 * recipQZoo3 & - - grazingFlux_miczoo2 * recipQZoo3 * grazEff2 & - + grazingFlux_phy * recipQuota & - - grazingFlux_phy * recipQuota * grazEff & - + grazingFlux_Dia * recipQuota_Dia & - - grazingFlux_Dia * recipQuota_Dia * grazEff & - + grazingFlux_miczoo * recipQZoo3 & - - grazingFlux_miczoo * recipQZoo3 * grazEff & - + Zoo2LossFlux * recipQZoo2 & - + hetLossFlux * recipQZoo & - + Zoo2fecalloss_c & - + Mesfecalloss_c & - - reminC * arrFunc * O2Func * DetZ2C & ! O2remin - ) * dt_b + sms(k,idetz2c) - end if - -!____________________________________________________________ -!< Second Zooplankton Detritus Si - sms(k,idetz2si) = ( & - + grazingFlux_dia2 * qSiN & ! --> qSin convert N to Si - + grazingFlux_dia * qSiN & - - reminSiT * DetZ2Si & - ) * dt_b + sms(k,idetz2si) - -!____________________________________________________________ -!< Second Zooplankton Detritus calcite - sms(k,idetz2calc) = ( & - + calc_loss_gra2 & - - calc_loss_gra2 * calc_diss_guts & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss2 * DetZ2Calc & - ) * dt_b + sms(k,idetz2calc) -#endif - -!< *** DOM *** -!< *********** - -!____________________________________________________________ -!< DON (Extracellular organic N) - - sms(k,idon) = ( & - + lossN * limitFacN * phyN & - + lossN_d * limitFacN_Dia * DiaN & -#if defined (__coccos) - + lossN_c * limitFacN_Cocco * CoccoN & -#endif - + reminN * arrFunc * O2Func * DetN & - + lossN_z * HetN & -#if defined (__3Zoo2Det) - + reminN * arrFunc * O2Func * DetZ2N & - + lossN_z2 * Zoo2N & - + lossN_z3 * MicZooN & ! 3Zoo -#endif - - rho_N * arrFunc * O2Func * DON & ! O2remin - ) * dt_b + sms(k,idon) - -!____________________________________________________________ -!< EOC - - sms(k,idoc) = ( & - + lossC * limitFacN * phyC & - + lossC_d * limitFacN_dia * DiaC & -#if defined (__coccos) - + lossC_c * limitFacN_cocco * CoccoC & -#endif - + reminC * arrFunc * O2Func * DetC & - + lossC_z * HetC & -#if defined (__3Zoo2Det) - + reminC * arrFunc * O2Func * DetZ2C & - + lossC_z2 * Zoo2C & - + lossC_z3 * MicZooC & ! 3Zoo -#endif - - rho_c1 * arrFunc * O2Func * EOC & ! O2remin - ) * dt_b + sms(k,idoc) - -!< *** Diatoms *** -!< *************** - -!____________________________________________________________ -!< Diatom N - -!< lossN: Diatom loss of organic N compounds [day^-1] -!< When N : C ratio becomes too high, excretion of DON is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers N to the detritus pool - - sms(k,idian) = ( & - + N_assim_dia * DiaC & ! --> N assimilation - - lossN_d * limitFacN_dia * DiaN & ! --> DON excretion - - aggregationRate * DiaN & ! --> Aggregation loss - - grazingFlux_Dia & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_Dia2 & - - grazingFlux_Dia3 & ! 3Zoo -#endif - ) * dt_b + sms(k,idian) - -!____________________________________________________________ -!< Diatom C - -!< lossC_d: Diatom loss of carbon [day^-1] -!< When N : C ratio becomes too high, excretion of DOC is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers C to the detritus pool - - sms(k,idiac) = ( & - + Cphot_dia * DiaC & ! -- Photosynthesis ---->/ - - lossC_d * limitFacN_dia * DiaC & ! -- Excretion of DOC --/ Net Photosynthesis - - phyRespRate_dia * DiaC & ! -- Respiration ----->/ - - aggregationRate * DiaC & - - grazingFlux_dia * recipQuota_dia & -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * recipQuota_dia & - - grazingFlux_dia3 * recipQuota_dia & ! 3Zoo -#endif - ) * dt_b + sms(k,idiac) - -!____________________________________________________________ -!< Diatom Chl - - sms(k,idchl) = ( & - + chlSynth_dia * DiaC & ! --> Chl a synthesis - - KOchl_dia * DiaChl & ! --> Degradation loss - - aggregationRate * DiaChl & ! --> Aggregation loss - - grazingFlux_dia * Chl2N_dia & ! --> Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * Chl2N_dia & - - grazingFlux_dia3 * Chl2N_dia & ! 3Zoo -#endif - ) * dt_b + sms(k,idchl) - -!____________________________________________________________ -!< Diatom Si - -!< lossN_d: Diatom loss of organic nitrogen compunds [day^-1] -!< When N : C ratio becomes too high, excretion is downregulated -!< by the limiter function limitFacN_dia -!< aggregationRate transfers Si to the detritus pool - - sms(k,idiasi) = ( & - + Si_assim * DiaC & ! -- Diatom silicon assimilation - - lossN_d * limitFacN_dia * DiaSi & ! -- Excretion to detritus - - aggregationRate * DiaSi & ! -- Aggregation loss - - grazingFlux_dia * qSiN & ! -- Grazing loss -#if defined (__3Zoo2Det) - - grazingFlux_dia2 * qSiN & - - grazingFlux_dia3 * qSiN & ! 3Zoo -#endif - ) * dt_b + sms(k,idiasi) - -!< *** Coccolithophore *** -!< *********************** - -#if defined (__coccos) -!____________________________________________________________ -!< Coccolithophore N - sms(k,icocn) = ( & - + N_assim_cocco * CoccoC & - - lossN_c * limitFacN_cocco * CoccoN & - - aggregationRate * CoccoN & - - grazingFlux_Cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 & - - grazingFlux_Cocco3 & ! 3Zoo -#endif - ) * dt_b + sms(k,icocn) - -!____________________________________________________________ -!< Coccolithophore C - - sms(k,icocc) = ( & - + Cphot_cocco * CoccoC & - - lossC_c * limitFacN_cocco * CoccoC & - - phyRespRate_cocco * CoccoC & - - aggregationRate * CoccoC & - - grazingFlux_cocco * recipQuota_cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 * recipQuota_cocco & - - grazingFlux_Cocco3 * recipQuota_cocco & ! 3Zoo -#endif - ) * dt_b + sms(k,icocc) - - if(sms(k,icocc)>100) then - print*,'ERROR: strange CoccoC !' - print*,'k= ', k - print*,'dt= ', dt - print*,'dt_b= ', dt_b - print*,'state(k,icocc): ', state(k,icocc) - print*,'sms CoccoC: ', CoccoC - print*,'sms CoccoN: ', CoccoN - print*,'sms Cphot cocco: ', Cphot_cocco*CoccoC - print*,'sms lossC_c: ', lossC_c - print*,'sms limitFacN_cocco: ', limitFacN_cocco - print*,'sms phyRespRate_cocco: ', phyRespRate_cocco - print*,'sms grazingFlux_cocco: ', grazingFlux_cocco - print*,'sms grazingFlux_cocco2: ', grazingFlux_Cocco2 - print*,'sms grazingFlux_cocco3: ', grazingFlux_Cocco3 - print*,'sms recipQuota_cocco: ', recipQuota_cocco - - print*,'sms recipQuota_cocco: ', recipQuota_cocco - call par_ex(partit%MPI_COMM_FESOM, partit%mype) - stop - endif - -!____________________________________________________________ -!< Coccolithophore Chl - - sms(k,icchl) = ( & - + ChlSynth_cocco * CoccoC & - - KOchl_cocco * CoccoChl & - - aggregationRate * CoccoChl & - - grazingFlux_cocco * Chl2N_cocco & -#if defined (__3Zoo2Det) - - grazingFlux_Cocco2 * Chl2N_cocco & - - grazingFlux_Cocco3 * Chl2N_cocco & ! 3Zoo -#endif - ) * dt_b + sms(k,icchl) -#endif - -!< *** Silicate *** -!< **************** - -!____________________________________________________________ -!< Detritus Si -#if defined (__3Zoo2Det) - sms(k,idetsi) = ( & - + aggregationRate * DiaSi & - + lossN_d * limitFacN_dia * DiaSi & - + grazingFlux_dia3 * qSiN & - - reminSiT * DetSi & - ) * dt_b + sms(k,idetsi) -#else - sms(k,idetsi) = ( & - + aggregationRate * DiaSi & - + lossN_d * limitFacN_dia * DiaSi & - + grazingFlux_dia * qSiN & - - reminSiT * DetSi & - ) * dt_b + sms(k,idetsi) -#endif -!____________________________________________________________ -!< DSi, Silicate - -!< DiaC: Intracellular carbon concentration in diatoms [mmolC m-3] -!< DetSi: Detritus silicon concentration [mmolSi m-3] -!< Si_assim: Si assimilation rate for diatoms [mmolSi mmolC-1 day-1] -!< reminSiT: Remineralization rate of silicon, temperature dependency [day-1] -!< dt_b: REcoM time step [day] - -!! Schourup 2013 Eq. A3 - - sms(k,isi) = ( & - - Si_assim * DiaC & ! --> Si assimilation of diatoms - + reminSiT * DetSi & ! --> Remineralization of detritus, temperature dependent -#if defined (__3Zoo2Det) - + reminSiT * DetZ2Si & -#endif - ) * dt_b + sms(k,isi) -!< *** Iron *** -!< ************ - -!____________________________________________________________ -!< Fe - -!< Fe2N: Intracellular Fe : N ratio [μmol Fe mmol N^-1] Fe2N = Fe2C * 6.625 -!< PhyC: Intracellular carbon concentration in nanophytoplankton [mmolCm^-3] -!< Cphot: C-specific actual rate of photosynthesis for nanopyhtoplankton [day^-1] -!< DiaC: Intracellular carbon concentration in diatoms [mmol C m^-3 ] -!< Cphot_dia: C-specific actual rate of photosynthesis for diatom [day^-1] -!< phyRespRate: Nanopyhtoplankton respiration rate [day^-1] -!< phyRespRate_dia: Diatom respiration rate [day^-1] -!< lossC: Nanopyhtoplankton excretion of organic C [day^-1] -!< limitFacN: limiting factor -!< lossC_d: Diatom excretion of organic C [day^-1] -!< limitFacN_dia: limiting factor -!< detC: Detritus carbon concentration [mmol C m^-3] -!< reminC: Temperature dependent remineralisation rate of detritus [day^-1] -!< arrFunc: Arrhenius function -!< hetC: Zooplankton carbon concentration [mmol C m^-3 ] -!< lossC_z: Zooplankton excretion of organic C [day^-1 ] -!< hetRespFlux: Zooplankton respiration rate [day^-1] -!< kScavFe: Scavenging rate of iron [m3 mmol C^-1 day^-1] - - sms(k,ife) = ( Fe2N * ( & - - N_assim * PhyC & ! --> N assimilation Nanophytoplankton, [mmol N/(mmol C * day)] C specific N utilization rate - - N_assim_dia * DiaC & ! --> N assimilation Diatom -#if defined (__coccos) - - N_assim_cocco * CoccoC & - + lossN_c * limitFacN_cocco * CoccoN & -#endif - + lossN * limitFacN * PhyN & ! --> Excretion from small pythoplankton - + lossN_d * limitFacN_dia * DiaN & ! --> Excretion from diatom - + reminN * arrFunc * O2Func * DetN & ! --> Remineralization of detritus ! NEW O2remin - + lossN_z * HetN & ! --> Excretion from zooplankton -#if defined (__3Zoo2Det) - + reminN * arrFunc * O2Func * DetZ2N & ! O2remin - + lossN_z2 * Zoo2N & - + lossN_z3 * MicZooN & ! 3Zoo -#endif - ) & - - kScavFe * DetC * FreeFe & -#if defined (__3Zoo2Det) - - kScavFe * DetZ2C * FreeFe & -#endif - ) * dt_b + sms(k,ife) - -!< *** Calcification *** -!< ********************* - -!____________________________________________________________ -!< Small phytoplankton calcite - -#if defined (__coccos) - sms(k,iphycal) = ( & - + calcification & ! --> Calcification - - lossC_c * limitFacN_cocco * PhyCalc & ! --> Excretion loss - - phyRespRate_cocco * PhyCalc & ! --> Respiration - - calc_loss_agg & ! --> Aggregation loss - - calc_loss_gra & ! --> Grazing loss -#if defined (__3Zoo2Det) - - calc_loss_gra2 & - - calc_loss_gra3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphycal) -#else - sms(k,iphycal) = ( & - + calcification & ! --> Calcification - - lossC * limitFacN * PhyCalc & ! --> Excretion loss - - phyRespRate * PhyCalc & ! --> Respiration - - calc_loss_agg & ! --> Aggregation loss - - calc_loss_gra & ! --> Grazing loss -#if defined (__3Zoo2Det) - - calc_loss_gra2 & - - calc_loss_gra3 & ! 3Zoo -#endif - ) * dt_b + sms(k,iphycal) -#endif - -!____________________________________________________________ -! Detritus calcite -#if defined (__coccos) - -#if defined (__3Zoo2Det) - sms(k,idetcal) = ( & - + lossC_c * limitFacN_cocco * PhyCalc & - + phyRespRate_cocco * PhyCalc & - + calc_loss_agg & - + calc_loss_gra3 & - - calc_loss_gra3 * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) - -#else - sms(k,idetcal) = ( & - + lossC_c * limitFacN_cocco * PhyCalc & - + phyRespRate_cocco * PhyCalc & - + calc_loss_agg & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) - -#endif - -#else - -#if defined (__3Zoo2Det) - sms(k,idetcal) = ( & - + lossC * limitFacN * PhyCalc & - + phyRespRate * PhyCalc & - + calc_loss_agg & - + calc_loss_gra3 & - - calc_loss_gra3 * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) -#else - sms(k,idetcal) = ( & - + lossC * limitFacN * PhyCalc & - + phyRespRate * PhyCalc & - + calc_loss_agg & - + calc_loss_gra & - - calc_loss_gra * calc_diss_guts & - - calc_diss * DetCalc & - ) * dt_b + sms(k,idetcal) -#endif -#endif - -!____________________________________________________________ -! Oxygen - - sms(k,ioxy) = ( & - + Cphot * phyC & - - phyRespRate * phyC & - + Cphot_dia * diaC & - - phyRespRate_dia * diaC & -#if defined (__coccos) - + Cphot_cocco * CoccoC & - - phyRespRate_cocco * CoccoC & -#endif - - rho_C1 * arrFunc * O2Func * EOC & ! O2remin - - hetRespFlux & -#if defined (__3Zoo2Det) - - Zoo2RespFlux & - - MicZooRespFlux & ! 3Zoo -#endif - ) * redO2C * dt_b + sms(k,ioxy) -! - if (ciso) then -!------------------------------------------------------------------------------- -! DIC_13 - sms(k,idic_13) = ( & - - Cphot * PhyC_13 & - + phyRespRate * PhyC_13 & - - Cphot_Dia * DiaC_13 & - + phyRespRate_Dia * DiaC_13 & - + rho_C1 * arrFunc * EOC_13 & - + HetRespFlux_13 & - + calc_diss_13 * DetCalc_13 & - + calc_loss_gra_13 * calc_diss_guts & - - calcification_13 & - ) * dt_b + sms(k,idic_13) -!------------------------------------------------------------------------------- -! Phytoplankton C_13 - sms(k,iphyc_13) = ( & - + Cphot * PhyC_13 & - - lossC * limitFacN * PhyC_13 & - - phyRespRate * PhyC_13 & - - aggregationRate * PhyC_13 & - - grazingFlux_phy * recipQuota_13 & - ) * dt_b + sms(k,iphyc_13) -!------------------------------------------------------------------------------- -! Detritus C_13 - sms(k,idetc_13) = ( & - + grazingFlux_phy * recipQuota_13 & - - grazingFlux_phy * recipQuota_13 * grazEff & - + grazingFlux_Dia * recipQuota_dia_13 & - - grazingFlux_Dia * recipQuota_dia_13 * grazEff & - + aggregationRate * phyC_13 & - + aggregationRate * DiaC_13 & - + hetLossFlux * recipQZoo_13 & - - reminC * arrFunc * DetC_13 & - ) * dt_b + sms(k,idetc_13) -!------------------------------------------------------------------------------- -! Heterotrophic C_13 - sms(k,ihetc_13) = ( & - + grazingFlux_phy * recipQuota_13 * grazEff & - + grazingFlux_Dia * recipQuota_dia_13 * grazEff & - - hetLossFlux * recipQZoo_13 & - - lossC_z * HetC_13 & - - hetRespFlux_13 & - ) * dt_b + sms(k,ihetc_13) -!------------------------------------------------------------------------------- -! EOC_13 - sms(k,idoc_13) = ( & - + lossC * limitFacN * phyC_13 & - + lossC_d * limitFacN_dia * DiaC_13 & - + reminC * arrFunc * DetC_13 & - + lossC_z * HetC_13 & - - rho_c1 * arrFunc * EOC_13 & - + LocRiverDOC * r_iorg_13 & - ) * dt_b + sms(k,idoc_13) -!------------------------------------------------------------------------------- -! Diatom C_13 - sms(k,idiac_13) = ( & - + Cphot_dia * DiaC_13 & - - lossC_d * limitFacN_dia * DiaC_13 & - - phyRespRate_dia * DiaC_13 & - - aggregationRate * DiaC_13 & - - grazingFlux_dia * recipQuota_dia_13 & - ) * dt_b + sms(k,idiac_13) -!------------------------------------------------------------------------------- -! Small phytoplankton calcite_13 - sms(k,iphycal_13) = ( & - + calcification_13 & - - lossC * limitFacN * phyCalc_13 & - - phyRespRate * phyCalc_13 & - - calc_loss_agg_13 & - - calc_loss_gra_13 & - ) * dt_b + sms(k,iphycal_13) -!------------------------------------------------------------------------------- -! Detritus calcite_13 - sms(k,idetcal_13) = ( & - + lossC * limitFacN * phyCalc_13 & - + phyRespRate * phyCalc_13 & - + calc_loss_agg_13 & - + calc_loss_gra_13 & - - calc_loss_gra_13 * calc_diss_guts & - - calc_diss_13 * DetCalc_13 & - ) * dt_b + sms(k,idetcal_13) -!------------------------------------------------------------------------------- - if (ciso_14) then -!------------------------------------------------------------------------------- - if (ciso_organic_14) then -! 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) -!------------------------------------------------------------------------------- -! Phytoplankton C_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) -!------------------------------------------------------------------------------- -! Detritus C_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) -!------------------------------------------------------------------------------- -! Heterotrophic C_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) -!------------------------------------------------------------------------------- -! Diatom C_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) -!------------------------------------------------------------------------------- -! Small phytoplankton calcite_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) -!------------------------------------------------------------------------------- -! Detritus calcite_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, identical to DIC except for radioactive decay (-> -! recom_forcing) - sms(k,idic_14) = sms(k,idic) - end if ! ciso_organic_14 - end if ! ciso_14 - end if ! ciso -!------------------------------------------------------------------------------- -! 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 - -!------------------------------------------------------------------------------- -! Remineralization from the sediments into the bottom layer - - if (use_MEDUSA .and. (sedflx_num .ne. 0)) then - if (mype==0) then !OG - write(*,*) ' --> Sedimentary input of nutrients through MEDUSA' - endif - - else ! not use_MEDUSA or sedflx_num = 0 -!*** 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) - -!*** 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 - -!*** 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 - -!*** 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 - - if (ciso) then -!*** DIC_13 *** We ignore isotopic fractionation during remineralization. - decayBenthos(5) = alpha_dcal_13 * decayRateBenC * LocBenthos(5) - LocBenthos(5) = LocBenthos(5) - decayBenthos(5) * dt_b -!*** Calc: DIC_13 *** - decayBenthos(6) = calc_diss_13 * LocBenthos(6) - LocBenthos(6) = LocBenthos(6) - decayBenthos(6) * dt_b ! / depth of benthos - if (ciso_14) then - if (ciso_organic_14) then -!*** DIC_14 *** We ignore isotopic fractionation during remineralization. - decayBenthos(7) = alpha_dcal_14 * decayRateBenC * LocBenthos(7) - LocBenthos(7) = LocBenthos(7) - decayBenthos(7) * dt_b -!*** Calc: DIC_14 *** - decayBenthos(8) = calc_diss_14 * LocBenthos(8) - LocBenthos(8) = LocBenthos(8) - decayBenthos(8) * dt_b ! / depth of benthos - else -! Do nothing here because sms(idic_14) is defined as sms(idic) further -! above - end if ! ciso_organic_14 - end if ! ciso_14 - end if ! ciso - endif ! use_MEDUSA - - end do ! Main time loop ends - - -end subroutine REcoM_sms - -!------------------------------------------------------------------------------- -! Function for calculating limiter -!------------------------------------------------------------------------------- - -function recom_limiter(slope,qa,qb) - use recom_config - Implicit None - 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) - else - recom_limiter = 1.d0 - exp( -slope*( abs(dq)-dq )**2) - endif - return - end - -!------------------------------------------------------------------------------- -! Function for iron chemistry -!------------------------------------------------------------------------------- -function iron_chemistry_2ligands(fet,l1t,l2t,k1,k2) - implicit none - - Real(kind=8) :: iron_chemistry_2ligands - Real(kind=8) :: l1t,l2t,fet,k1,k2 - Real(kind=8) :: a3,a2,a1,a0,a,b,c,p,q,discr,rho,phi,amp,pi - Real(kind=8) :: one3rd, one27th - Real(kind=8) :: fe1,fe2,fe3 - -! coefficients of the 4th-order polynomial - a3 = k1*k2 - a2 = ( k1*k2*(l1t + l2t - fet) + k1 + k2 ) - a1 = ( 1 - (k1 + k2)*fet + k1*l1t + k2*l2t ) - a0 = -fet - -! coefficients of the normalized polynomial - a = a2/a3 - b = a1/a3 - c = a0/a3 - -! some numbers that are used several times - one3rd = 1.0/3.0 - one27th = 1.0/27.0 - -! now solve the polynomial stepwise - p = b - a*a*one3rd - q = c - a*b*one3rd + 2.0*a*a*a*one27th - discr = q*q/4.0 + p*p*p*one27th - - rho = sqrt(-(p*p*p*one27th)) - phi = acos(-q/(2.0*rho)) - amp = 2.0*rho**one3rd - pi = 3.1415926535897931 - -! the equation has three real roots - fe1 = amp*cos(phi*one3rd) - a*one3rd - fe2 = amp*cos((phi + 2.0*pi)*one3rd) - a*one3rd - fe3 = amp*cos((phi + 4.0*pi)*one3rd) - a*one3rd - - iron_chemistry_2ligands = max(fe1,fe2,fe3) - -end function iron_chemistry_2ligands -!------------------------------------------------------------------------------- -function iron_chemistry(Fe, totalLigand, ligandStabConst) - implicit none - - Real(kind=8) :: iron_chemistry - Real(kind=8) :: Fe, totalLigand, ligandStabConst ! Input - Real(kind=8) :: FreeFe ! Output - Real(kind=8) :: ligand,FeL,a,b,c,discrim - -! Abbrevations - a = 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 - freeFe = Fe - FeL - else ! No free iron - freeFe = 0.d0 - end if - - iron_chemistry = freeFe - - return - end - From cd362a436d99f061a05e5b4a52064994e79fa592 Mon Sep 17 00:00:00 2001 From: Jan Streffing Date: Tue, 3 Mar 2026 10:52:48 +0100 Subject: [PATCH 57/68] add partit arg to read_namelist_run_config call --- src/fesom_module.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 369d306e2..09e258917 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -143,7 +143,7 @@ subroutine fesom_init(fesom_total_nsteps) integer :: i ! get current value for num_fesom_groups - call read_namelist_run_config + call read_namelist_run_config(partit) #endif From eb707e352092895e0a568c375636085bb4d4b5e3 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 3 Mar 2026 11:26:01 +0100 Subject: [PATCH 58/68] changes wrt. C isotopes --- src/int_recom/recom_forcing.F90 | 12 +++++++---- src/int_recom/recom_init.F90 | 35 ++++++++++++++++++--------------- src/int_recom/recom_main.F90 | 2 +- src/int_recom/recom_sms.F90 | 24 ++++++++++++++-------- 4 files changed, 44 insertions(+), 29 deletions(-) diff --git a/src/int_recom/recom_forcing.F90 b/src/int_recom/recom_forcing.F90 index 3581f6af7..8c683526d 100644 --- a/src/int_recom/recom_forcing.F90 +++ b/src/int_recom/recom_forcing.F90 @@ -296,8 +296,10 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali 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)) +! 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)) + state(1:nn,iphyc_13) = max((tiny_C * r_phyc_13), state(1:nn,iphyc_13)) + state(1:nn,idiac_13) = max((tiny_C_d * r_diac_13), state(1:nn,idiac_13)) ! The same for radiocarbon, fractionation factors have been already derived above if (ciso_14) then @@ -312,8 +314,10 @@ subroutine REcoM_Forcing(zNodes, n, Nn, state, SurfSW, Loc_slp, Temp, Sali, Sali 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)) +! 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)) + state(1:nn,iphyc_14) = max((tiny_C * r_phyc_14), state(1:nn,iphyc_14)) + state(1:nn,idiac_14) = max((tiny_C_d * r_diac_14), state(1:nn,idiac_14)) end if end if ! Radiocarbon diff --git a/src/int_recom/recom_init.F90 b/src/int_recom/recom_init.F90 index 7bcb7987f..632dbc2fb 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -294,22 +294,22 @@ subroutine recom_init(tracers, partit, mesh) if (ciso) then !! Define ciso variables assigning additional ciso tracer indices -! idic_13 = bgc_base_num + 1 -! iphyc_13 = bgc_base_num + 2 -! idetc_13 = bgc_base_num + 3 -! ihetc_13 = bgc_base_num + 4 -! idoc_13 = bgc_base_num + 5 -! idiac_13 = bgc_base_num + 6 -! iphycal_13 = bgc_base_num + 7 -! idetcal_13 = bgc_base_num + 8 -! idic_14 = bgc_base_num + 9 -! iphyc_14 = bgc_base_num + 10 -! idetc_14 = bgc_base_num + 11 -! ihetc_14 = bgc_base_num + 12 -! idoc_14 = bgc_base_num + 13 -! idiac_14 = bgc_base_num + 14 -! iphycal_14 = bgc_base_num + 15 -! idetcal_14 = bgc_base_num + 16 + idic_13 = bgc_base_num + 1 + iphyc_13 = bgc_base_num + 2 + idetc_13 = bgc_base_num + 3 + ihetc_13 = bgc_base_num + 4 + idoc_13 = bgc_base_num + 5 + idiac_13 = bgc_base_num + 6 + iphycal_13 = bgc_base_num + 7 + idetcal_13 = bgc_base_num + 8 + idic_14 = bgc_base_num + 9 + iphyc_14 = bgc_base_num + 10 + idetc_14 = bgc_base_num + 11 + ihetc_14 = bgc_base_num + 12 + idoc_14 = bgc_base_num + 13 + idiac_14 = bgc_base_num + 14 + iphycal_14 = bgc_base_num + 15 + idetcal_14 = bgc_base_num + 16 !< Allocate 13CO2 surface fields allocate(GloPCO2surf_13 ( node_size )) @@ -402,6 +402,9 @@ subroutine recom_init(tracers, partit, mesh) CASE (1021) tracers%data(i)%values(:,:) = tiny ! DetCalc + CASE (1022) + tracers%data(i)%values(:,:) = tiny ! O2 + ! ******************* ! CASE 2phy 2zoo 2det ! ******************* diff --git a/src/int_recom/recom_main.F90 b/src/int_recom/recom_main.F90 index fb44e5406..0c5b02653 100755 --- a/src/int_recom/recom_main.F90 +++ b/src/int_recom/recom_main.F90 @@ -142,7 +142,7 @@ subroutine recom(ice, dynamics, tracers, partit, mesh) 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) + call annual_event(do_update,1) 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 diff --git a/src/int_recom/recom_sms.F90 b/src/int_recom/recom_sms.F90 index 31bc22ad8..339d79b2d 100644 --- a/src/int_recom/recom_sms.F90 +++ b/src/int_recom/recom_sms.F90 @@ -2088,9 +2088,11 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! DIC_13 sms(k,idic_13) = ( & - - Cphot * PhyC_13 & +! - Cphot * PhyC_13 & + - Cphot * r_phyc_13 * PhyC & + phyRespRate * PhyC_13 & - - Cphot_Dia * DiaC_13 & +! - Cphot_Dia * DiaC_13 & + - Cphot_Dia * r_diac_13 * DiaC & + phyRespRate_Dia * DiaC_13 & + rho_C1 * arrFunc * EOC_13 & + HetRespFlux_13 & @@ -2101,7 +2103,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! Phytoplankton C_13 sms(k,iphyc_13) = ( & - + Cphot * PhyC_13 & +! + Cphot * PhyC_13 & + + Cphot * r_phyc_13 * PhyC & - lossC * limitFacN * PhyC_13 & - phyRespRate * PhyC_13 & - aggregationRate * PhyC_13 & @@ -2141,7 +2144,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! Diatom C_13 sms(k,idiac_13) = ( & - + Cphot_dia * DiaC_13 & +! + Cphot_dia * DiaC_13 & + + Cphot_dia * r_diac_13 * DiaC & - lossC_d * limitFacN_dia * DiaC_13 & - phyRespRate_dia * DiaC_13 & - aggregationRate * DiaC_13 & @@ -2172,9 +2176,11 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & if (ciso_organic_14) then ! DIC_14 sms(k,idic_14) = ( & - - Cphot * PhyC_14 & +! - Cphot * PhyC_14 & + - Cphot * r_phyc_14 * PhyC & + phyRespRate * PhyC_14 & - - Cphot_Dia * DiaC_14 & +! - Cphot_Dia * DiaC_14 & + - Cphot_Dia * r_diac_14 * DiaC & + phyRespRate_Dia * DiaC_14 & + rho_C1 * arrFunc * EOC_14 & + HetRespFlux_14 & @@ -2185,7 +2191,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! Phytoplankton C_14 sms(k,iphyc_14) = ( & - + Cphot * PhyC_14 & +! + Cphot * PhyC_14 & + + Cphot * r_phyc_14 * PhyC & - lossC * limitFacN * PhyC_14 & - phyRespRate * PhyC_14 & - aggregationRate * PhyC_14 & @@ -2225,7 +2232,8 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !------------------------------------------------------------------------------- ! Diatom C_14 sms(k,idiac_14) = ( & - + Cphot_dia * DiaC_14 & +! + Cphot_dia * DiaC_14 & + + Cphot_dia * r_diac_14 * DiaC & - lossC_d * limitFacN_dia * DiaC_14 & - phyRespRate_dia * DiaC_14 & - aggregationRate * DiaC_14 & From 303f877b4ae2f934950815c26cab4ac58e1f034f Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 3 Mar 2026 13:17:55 +0100 Subject: [PATCH 59/68] fix to read num_fesom_groups --- src/fesom_module.F90 | 2 +- src/gen_model_setup.F90 | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 09e258917..369d306e2 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -143,7 +143,7 @@ subroutine fesom_init(fesom_total_nsteps) integer :: i ! get current value for num_fesom_groups - call read_namelist_run_config(partit) + call read_namelist_run_config #endif diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index 2c3fddfcf..1bf3cd133 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -335,7 +335,7 @@ end subroutine setup_model #if defined(__recom) && defined(__usetp) ! read num_fesom_groups for multi FESOM group loop parallelization ! ================================================================= -subroutine read_namelist_run_config(partit) +subroutine read_namelist_run_config ! Reads run_config namelist and overwrite default parameters. ! Copied by Kai Himstedt (based on read_namelist) @@ -345,7 +345,6 @@ subroutine read_namelist_run_config(partit) USE MOD_PARSUP use g_config implicit none - type(t_partit), intent(inout), target :: partit character(len=100) :: nmlfile integer fileunit From fe455931549ca04de2da98ed5b842f724b374481 Mon Sep 17 00:00:00 2001 From: Suvarchal Kumar Cheedela Date: Tue, 3 Mar 2026 14:36:18 +0100 Subject: [PATCH 60/68] fix preprocessor oasis and tracer parallel block --- src/fesom_module.F90 | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/fesom_module.F90 b/src/fesom_module.F90 index 74d15393f..b9b5f3e68 100755 --- a/src/fesom_module.F90 +++ b/src/fesom_module.F90 @@ -180,17 +180,20 @@ subroutine fesom_init(fesom_total_nsteps) end if #endif + #if defined (__oasis) -! pass num_fesom_groups to coupler #if defined(__recom) && defined(__usetp) +! pass num_fesom_groups to coupler call cpl_oasis3mct_init(f%partit, f%partit%MPI_COMM_FESOM, num_fesom_groups) -#elif defined (__yac) - call cpl_yac_init(f%partit%MPI_COMM_FESOM) #else call cpl_oasis3mct_init(f%partit, f%partit%MPI_COMM_FESOM) #endif +#elif defined (__yac) + call cpl_yac_init(f%partit%MPI_COMM_FESOM) +#endif + f%t1 = MPI_Wtime() ! Initialize enhanced profiler From 8f089c6e1b497b5ab9f5d3ee9f9e77eaad0dccb3 Mon Sep 17 00:00:00 2001 From: Suvarchal Kumar Cheedela Date: Tue, 3 Mar 2026 14:45:48 +0100 Subject: [PATCH 61/68] get rid of warnings of using comma before io list --- src/gen_surface_forcing.F90 | 8 ++++---- src/int_recom/recom_init.F90 | 2 +- src/oce_setup_step.F90 | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index 2f8f3909d..90e596444 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -1693,7 +1693,7 @@ SUBROUTINE sbc_do(partit, mesh) if (partit%my_fesom_group==0) then #endif if (mype==0) write(*,*) 'Constant_CO2 = ', CO2_for_spinup - if (mype==0) write(*,*),'Atm CO2=', AtmCO2 + if (mype==0) write(*,*) 'Atm CO2=', AtmCO2 #if defined(__usetp) endif !(partit%my_fesom_group==0) then #endif @@ -1734,7 +1734,7 @@ SUBROUTINE sbc_do(partit, mesh) firstyearofcurrentCO2cycle = lastyearoffesomcycle-numofCO2cycles*totnumyear+(currentCO2cycle-1)*totnumyear currentCO2year = firstyearofcurrentCO2cycle + (yearnew-firstyearoffesomcycle)+1 - if(mype==0) write(*,*),currentCO2year, firstyearofcurrentCO2cycle, yearnew, firstyearoffesomcycle + if(mype==0) write(*,*) currentCO2year, firstyearofcurrentCO2cycle, yearnew, firstyearoffesomcycle write(currentCO2year_char,'(i4)') currentCO2year CO2vari = 'AtmCO2_'//currentCO2year_char @@ -1758,8 +1758,8 @@ SUBROUTINE sbc_do(partit, mesh) #if defined(__usetp) if (partit%my_fesom_group==0) then #endif - if (mype==0) write(*,*),'Current carbon year=',currentCO2year - if (mype==0) write(*,*),'Atm CO2=', AtmCO2 + if (mype==0) write(*,*) 'Current carbon year=',currentCO2year + if (mype==0) write(*,*) 'Atm CO2=', AtmCO2 #if defined(__usetp) endif !(partit%my_fesom_group==0) then #endif diff --git a/src/int_recom/recom_init.F90 b/src/int_recom/recom_init.F90 index 632dbc2fb..b1846534d 100644 --- a/src/int_recom/recom_init.F90 +++ b/src/int_recom/recom_init.F90 @@ -496,7 +496,7 @@ subroutine recom_init(tracers, partit, mesh) tracers%data(21)%values(:,:) = max(tiny, tracers%data(21)%values(:,:)) !------------------------------------------ - if(mype==0) write(*,*),'Tracers have been initialized as spinup from WOA/glodap netcdf files' + if(mype==0) write(*,*) 'Tracers have been initialized as spinup from WOA/glodap netcdf files' locDINmax = -66666 locDINmin = 66666 locDICmax = locDINmax diff --git a/src/oce_setup_step.F90 b/src/oce_setup_step.F90 index cd651d03e..a98d078c5 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -1184,7 +1184,7 @@ SUBROUTINE oce_initial_state(tracers, partit, mesh) #endif if (mype==0) write(*,*) if (mype==0) print *, achar(27)//'[46;1m'//' --> Set surface field for alkalinity restoring'//achar(27)//'[0m' - if (mype==0) write(*,*),'Alkalinity restoring = true. Field is read.' + if (mype==0) write(*,*) 'Alkalinity restoring = true. Field is read.' #if defined(__usetp) endif !(partit%my_fesom_group==0) then #endif From a8f42a557deab9738a6d4d087f64fef8228e7726 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 13 Mar 2026 12:28:49 +0100 Subject: [PATCH 62/68] add switch for variable grazing efficiency --- src/int_recom/recom_modules.F90 | 3 ++- src/int_recom/recom_sms.F90 | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/int_recom/recom_modules.F90 b/src/int_recom/recom_modules.F90 index 3d70b37a0..a7b10dae0 100644 --- a/src/int_recom/recom_modules.F90 +++ b/src/int_recom/recom_modules.F90 @@ -121,6 +121,7 @@ module recom_config Integer :: biostep = 1 ! Number of times biology should be stepped forward for each time step Logical :: REcoM_Geider_limiter = .false. ! Decides what routine should be used to calculate limiters in sms Logical :: REcoM_Grazing_Variable_Preference = .true. ! Decides if grazing should have preference for phyN or DiaN + Logical :: REcoM_Grazing_Variable_Efficiency = .true. ! allowes grazing efficiency to vary with food availability Logical :: Grazing_detritus = .false. ! Decides grazing on detritus Logical :: het_resp_noredfield = .true. ! Decides respiratation of copepods Logical :: diatom_mucus = .true. ! Effect of nutrient limitation on the aggregation @@ -169,7 +170,7 @@ module recom_config VDet, VDet_zoo2, & VPhy, VDia, VCocco, & allow_var_sinking, biostep, REcoM_Geider_limiter, & - REcoM_Grazing_Variable_Preference, & + REcoM_Grazing_Variable_Preference, REcoM_Grazing_Variable_Efficiency, & Grazing_detritus, & het_resp_noredfield, & diatom_mucus, & diff --git a/src/int_recom/recom_sms.F90 b/src/int_recom/recom_sms.F90 index 339d79b2d..3200aaa31 100644 --- a/src/int_recom/recom_sms.F90 +++ b/src/int_recom/recom_sms.F90 @@ -806,7 +806,11 @@ subroutine REcoM_sms(n,Nn,state,thick,recipthick,SurfSR,sms,Temp, Sali_depth & !< *** Grazing efficiency *** !< ************************** - grazEff = gfin + 1/(0.2*food + 2) + if (REcoM_Grazing_Variable_Efficiency) then + grazEff = gfin + 1/(0.2*food + 2) + else + grazEff = gfin + end if grazingFluxcarbon_mes = (grazingFlux_phy * recipQuota * grazEff) & + (grazingFlux_Dia * recipQuota_Dia * grazEff) From de219173d93c260e4241807f61d86b1ab8c5f3cb Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Thu, 9 Apr 2026 10:55:47 +0200 Subject: [PATCH 63/68] merging between all tracer groups immediately before writing restart --- src/io_restart.F90 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 1cad57a52..56a1999f6 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -567,7 +567,10 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn else is_bin_restart_write = is_due(trim(bin_restart_length_unit), bin_restart_length, istep) end if - + + ! Write restart files + if(is_portable_restart_write) then + ! --> synchronizes tracer data within fesom groups ! kh 09.01.26 merging of valuesold and valuesAB between all fesom groups is only necessary here, immediately before writing the corresponding restart files @@ -592,8 +595,6 @@ subroutine write_initial_conditions(istep, nstart, ntotal, which_readr, ice, dyn end if #endif - ! Write restart files - if(is_portable_restart_write) then ! write OCEAN restart #if defined(__recom) && defined(__usetp) if(partit%my_fesom_group == 0) then From 4b524cc69fda4581d4b00233dba85aa98d2cc18a Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Tue, 14 Apr 2026 13:41:35 +0200 Subject: [PATCH 64/68] diagnostic output pH and CO3 added --- src/io_meandata.F90 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index b07dfa69e..540361365 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -875,6 +875,16 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) 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 ('pH ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'pH', 'pH', 'total scale', pH3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + +CASE ('CO3 ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CO3', 'Carbonate ion concentration', 'mol/m3', CO33D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if + CASE ('respmeso ') if (use_REcoM) then call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'respmeso','Respiration rate of mesozooplankton', 'mmolC/m2/d', respmeso(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) From 48d8a58197ffb0876656795d2865c7adf20f48ad Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 24 Jun 2026 18:14:07 +0200 Subject: [PATCH 65/68] sbc_do_recom added for a separte surface forcing for REcoM --- src/gen_forcing_couple.F90 | 6 +- src/gen_surface_forcing.F90 | 216 +++++++++++++++++++++++------------- src/io_meandata.F90 | 8 +- 3 files changed, 149 insertions(+), 81 deletions(-) diff --git a/src/gen_forcing_couple.F90 b/src/gen_forcing_couple.F90 index 349c44201..c756501be 100755 --- a/src/gen_forcing_couple.F90 +++ b/src/gen_forcing_couple.F90 @@ -265,7 +265,7 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) use g_comm_auto use g_rotate_grid use net_rec_from_atm_interface - use g_sbf, only: sbc_do + use g_sbf, only: sbc_do, sbc_do_recom use g_sbf, only: atmdata, i_totfl, i_xwind, i_ywind, i_xstre, i_ystre, i_humi, i_qsr, i_qlw, i_tair, i_prec, i_mslp, i_cloud, i_snow, & l_xwind, l_ywind, l_xstre, l_ystre, l_humi, l_qsr, l_qlw, l_tair, l_prec, l_mslp, l_cloud, l_snow #if defined (__oasis) @@ -774,6 +774,10 @@ subroutine update_atm_forcing(istep, ice, tracers, dynamics, partit, mesh) #endif /* skip all in case of __ifsinterface */ #endif /* (__oasis) */ +#if defined (__recom) /* consider in all cases */ + call sbc_do_recom(partit, mesh) +#endif + t2=MPI_Wtime() #ifdef VERBOSE diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index 90e596444..228150ce5 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -58,6 +58,7 @@ MODULE g_sbf public sbc_ini ! routine called before 1st time step (open files, read namelist,...) public sbc_do ! routine called each time step to provide a sbc fileds (wind,...) + public sbc_do_recom ! routine called each time step to provide a sbc fileds for REcoM public sbc_end ! routine called after last time step public RUNOFF_MAPPER public julday ! get julian day from date @@ -1467,11 +1468,11 @@ SUBROUTINE sbc_do(partit, mesh) !! ** Action : !!---------------------------------------------------------------------- use g_clock -#if defined (__recom) - use recom_config - use recom_glovar - use REcoM_ciso -#endif +!#if defined (__recom) +! use recom_config +! use recom_glovar +! use REcoM_ciso +!#endif IMPLICIT NONE include 'netcdf.inc' @@ -1483,18 +1484,18 @@ SUBROUTINE sbc_do(partit, mesh) real(wp), pointer :: nc_time(:) character(len=MAX_PATH) :: filename logical :: file_exist=.false. -#if defined (__recom) - character(15) :: CO2vari, Nvari - integer :: firstyearofcurrentCO2cycle, totnumyear, currentCO2year - character(4) :: currentCO2year_char - real(kind=8), allocatable :: ncdata(:) - integer :: CO2start, CO2count - integer :: status, ncid, varid - logical :: do_read=.false. - integer :: n_lb - integer, dimension(2) :: istart, icount - real(kind=8) :: total_runoff -#endif +!#if defined (__recom) +! character(15) :: CO2vari, Nvari +! integer :: firstyearofcurrentCO2cycle, totnumyear, currentCO2year +! character(4) :: currentCO2year_char +! real(kind=8), allocatable :: ncdata(:) +! integer :: CO2start, CO2count +! integer :: status, ncid, varid +! 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 @@ -1601,7 +1602,7 @@ SUBROUTINE sbc_do(partit, mesh) end if !___________________________________________________________________________ - ! read inCHL for applying shortwave penetration + ! read in CHL for applying shortwave penetration if (use_sw_pene) then if (chl_data_source=='Sweeney') then if (update_monthly_flag) then @@ -1671,55 +1672,108 @@ SUBROUTINE sbc_do(partit, mesh) end if ! --> if(update_monthly_flag) then end if ! --> if(runoff_data_source=='Dai09' .or. ... -#if defined(__recom) -!< read surface atmospheric deposition for Fe, N, CO2 -if (recom_debug .and. mype==0) print *, achar(27)//'[36m'//' --> Atm_input'//achar(27)//'[0m' - -! ******** Atmospheric CO2 ********* - if (mstep == 1) then ! The year has changed - - if (use_atbox) then -! Atmospheric box model CO2 values - AtmCO2(:) = x_co2atm(1) - if (ciso) then - AtmCO2_13(:) = x_co2atm_13(1) - if (ciso_14) AtmCO2_14(:,1) = x_co2atm_14(1) - end if - else -! Prescribed atmospheric CO2 values - if (constant_CO2) then - AtmCO2(:) = CO2_for_spinup + call data_timeinterp(rdate, partit) + END SUBROUTINE sbc_do + +#if defined (__recom) +SUBROUTINE sbc_do_recom(partit, mesh) +! ============================================================ +! Read surface atmospheric deposition for Fe, N, CO2 +! ============================================================ + !!--------------------------------------------------------------------- + !! *** ROUTINE sbc_do_recom *** + !! + !! ** Purpose : provide at each time-step: REcoM atmospheric and + !! riverine boundary conditions (CO2, Fe, N, rivers, + !! erosion) + !! ** Method : + !! ** Action : + !!---------------------------------------------------------------------- + use g_clock + use recom_config + use recom_glovar + use REcoM_ciso + IMPLICIT NONE + + integer :: i + logical :: update_monthly_flag + integer :: flag_flpyr=0 + character(len=MAX_PATH) :: filename + character(15) :: CO2vari, Nvari + integer :: firstyearofcurrentCO2cycle, totnumyear, currentCO2year + character(4) :: currentCO2year_char + real(kind=8), allocatable :: ncdata(:) + integer :: CO2start, CO2count + integer :: status, ncid, varid, ierror, n + logical :: do_read=.false. + integer :: n_lb + integer, dimension(2) :: istart, icount + real(kind=8) :: total_runoff + type(t_partit), intent(inout), target :: partit + type(t_mesh), intent(in), target :: mesh + +#include "associate_part_def.h" +#include "associate_mesh_def.h" +#include "associate_part_ass.h" +#include "associate_mesh_ass.h" + + update_monthly_flag=( (day_in_month==num_day_in_month(fleapyear,month) .AND. timenew==86400._WP) .OR. mstep==1) + + ! ---------------------------------------------------------------- + ! Atmospheric CO2 — update once per year (when mstep == 1) + ! ---------------------------------------------------------------- + + if (mstep == 1) then + + ! --- Source: Atmospheric box model --- + if (use_atbox) then + 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 + + ! --- Source: Prescribed CO2 values --- + else + + if (constant_CO2) then + AtmCO2(:) = CO2_for_spinup #if defined(__usetp) if (partit%my_fesom_group==0) then #endif - if (mype==0) write(*,*) 'Constant_CO2 = ', CO2_for_spinup - if (mype==0) write(*,*) 'Atm CO2=', AtmCO2 + if (mype == 0) then + write(*,*) 'Constant_CO2 = ', CO2_for_spinup + write(*,*) 'Atm CO2 = ', AtmCO2 + end if #if defined(__usetp) - endif !(partit%my_fesom_group==0) then + endif #endif - 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 + + if (ciso) then + AtmCO2_13 = CO2_for_spinup * (1. + 0.001 * delta_co2_13) + + if (ciso_14) then + ! Atmospheric 14C varies with latitude + do i=1, myDim_nod2D + lat_val = geo_coord_nod2D(2,i) / rad + + if (ciso_organic_14) then +! Convert Delta_14C to delta_14C + delta_co2_14 = (big_delta_co2_14(lat_zone(lat_val)) & + + 2. * delta_co2_13 + 50.) & + / (0.95 - 0.002 * delta_co2_13) + else +! "Inorganic" 14C approximation: delta_14C := Delta_14C + delta_co2_14 = big_delta_co2_14(lat_zone(lat_val)) + end if + + AtmCO2_14(lat_zone(lat_val),:) = CO2_for_spinup * (1. + 0.001 * delta_co2_14) + end do + end if end if - end if - else !not constant_CO2 - + else !Transient CO2 from file filename=trim(make_full_path(nm_co2_data_file)) #if defined(__usetp) if (partit%my_fesom_group==0) then @@ -1730,11 +1784,19 @@ SUBROUTINE sbc_do(partit, mesh) endif !(partit%my_fesom_group==0) then #endif + ! Compute the CO2 year corresponding to the current FESOM cycle totnumyear = lastyearoffesomcycle-firstyearoffesomcycle+1 firstyearofcurrentCO2cycle = lastyearoffesomcycle-numofCO2cycles*totnumyear+(currentCO2cycle-1)*totnumyear currentCO2year = firstyearofcurrentCO2cycle + (yearnew-firstyearoffesomcycle)+1 + +#if defined(__usetp) + if (partit%my_fesom_group==0) then +#endif if(mype==0) write(*,*) currentCO2year, firstyearofcurrentCO2cycle, yearnew, firstyearoffesomcycle +#if defined(__usetp) + endif !(partit%my_fesom_group==0) then +#endif write(currentCO2year_char,'(i4)') currentCO2year CO2vari = 'AtmCO2_'//currentCO2year_char @@ -1747,7 +1809,7 @@ SUBROUTINE sbc_do(partit, mesh) stop endif - ! data + ! Read 12-month CO2 array allocate(ncdata(12)) status=nf90_inq_varid(ncid, CO2vari, varid) CO2start = 1 @@ -1764,7 +1826,7 @@ SUBROUTINE sbc_do(partit, mesh) endif !(partit%my_fesom_group==0) then #endif status=nf90_close(ncid) - end if + end if ! constant_CO2 / transient CO2 end if ! atmospheric box model or prescribed CO2 values ! Control output of atmospheric CO2 values @@ -1784,7 +1846,9 @@ SUBROUTINE sbc_do(partit, mesh) end if end if ! mstep ==1 -! ******** Fe deposition ********* + ! ---------------------------------------------------------------- + ! Iron (Fe) deposition + ! ---------------------------------------------------------------- if (fe_data_source=='Albani') then if (update_monthly_flag) then i=month @@ -1794,7 +1858,6 @@ SUBROUTINE sbc_do(partit, mesh) #if defined(__usetp) if (partit%my_fesom_group==0) then #endif - if (mype==0) write(*,*) 'Updating iron climatology for month ', i,' from ', trim(filename) #if defined(__usetp) endif @@ -1811,7 +1874,9 @@ SUBROUTINE sbc_do(partit, mesh) #endif end if -! ******** N deposition ********* + ! ---------------------------------------------------------------- + ! Nitrogen (N) deposition + ! ---------------------------------------------------------------- if (useAeolianN) then ! todo: check below when useAeolianN is .true. if (mstep==1) then ! The year has changed @@ -1849,7 +1914,9 @@ SUBROUTINE sbc_do(partit, mesh) #endif end if -! ******** Riverine input (Nutrients) ********* + !----------------------------------------------------------------------------- + ! Configure river nutrient inputs + !----------------------------------------------------------------------------- if (useRivers) then !< read riverine input ! *** River inputs are in mmol/m2/s *** @@ -1900,7 +1967,9 @@ SUBROUTINE sbc_do(partit, mesh) #endif end if -! ******** Riverine input of iron ********* + !----------------------------------------------------------------------------- + ! Riverine iron input + !----------------------------------------------------------------------------- if (useRivFe) then ! River runoff (m/s) is multiplied with Fe concentration * muemolFe/m3 -> muemolFe/m2/s ! add river nutrients as surface boundary condition (surface_bc function in @@ -1957,7 +2026,9 @@ SUBROUTINE sbc_do(partit, mesh) #endif end if -! ******** Sediment input ********* + !----------------------------------------------------------------------------- + ! Sedimentary input + !----------------------------------------------------------------------------- !-Checking if files need to be opened--------------------------------------------- if(use_MEDUSA .and. (sedflx_num .ne. 0)) then allocate(ncdata(9)) @@ -2123,16 +2194,9 @@ SUBROUTINE sbc_do(partit, mesh) end if ! use_MEDUSA and sedflx_num not 0 +END SUBROUTINE sbc_do_recom #endif !defined(__recom) - !!PS if (partit%mype==0) then - !!PS write(*,*) 'sbc_do --> mstep:',mstep, ' rdate=', rdate - !!PS end if - - ! interpolate in time - call data_timeinterp(rdate, partit) - END SUBROUTINE sbc_do - FUNCTION julday(yyyy, mm, dd, calendar) IMPLICIT NONE diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 540361365..29e1d2f85 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -880,10 +880,10 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'pH', 'pH', 'total scale', pH3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -CASE ('CO3 ') - if (use_REcoM) then - call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CO3', 'Carbonate ion concentration', 'mol/m3', CO33D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) - end if +!CASE ('CO3 ') +! if (use_REcoM) then +! call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CO3', 'Carbonate ion concentration', 'mol/m3', CO33D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) +! end if CASE ('respmeso ') if (use_REcoM) then From c0faa4c9d8cb0d6738978561c278b9fdd052d775 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 26 Jun 2026 16:08:05 +0200 Subject: [PATCH 66/68] add recom directive for sbc_do_recom --- src/gen_surface_forcing.F90 | 2 ++ src/io_meandata.F90 | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index 228150ce5..02d22d355 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -58,7 +58,9 @@ MODULE g_sbf public sbc_ini ! routine called before 1st time step (open files, read namelist,...) public sbc_do ! routine called each time step to provide a sbc fileds (wind,...) +#if defined (__recom) public sbc_do_recom ! routine called each time step to provide a sbc fileds for REcoM +#endif public sbc_end ! routine called after last time step public RUNOFF_MAPPER public julday ! get julian day from date diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 29e1d2f85..540361365 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -880,10 +880,10 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'pH', 'pH', 'total scale', pH3D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) end if -!CASE ('CO3 ') -! if (use_REcoM) then -! call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CO3', 'Carbonate ion concentration', 'mol/m3', CO33D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) -! end if +CASE ('CO3 ') + if (use_REcoM) then + call def_stream((/nl-1, nod2D/), (/nl-1, myDim_nod2D/), 'CO3', 'Carbonate ion concentration', 'mol/m3', CO33D(:,:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if CASE ('respmeso ') if (use_REcoM) then From 8a34d2d2d065de450b5b540aa69828f87aee6310 Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Fri, 3 Jul 2026 12:23:00 +0200 Subject: [PATCH 67/68] sbc_ini_recom added to read nam_rsbc from namelist.recom --- src/gen_forcing_init.F90 | 8 ++++ src/gen_surface_forcing.F90 | 84 ++++++++++++++++++++++++++++--------- 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/src/gen_forcing_init.F90 b/src/gen_forcing_init.F90 index 5b0f69bcc..187b2e466 100644 --- a/src/gen_forcing_init.F90 +++ b/src/gen_forcing_init.F90 @@ -30,6 +30,9 @@ end module forcing_array_setup_dbgyre_interfaces subroutine forcing_setup(partit, mesh) use g_CONFIG use g_sbf, only: sbc_ini +#if defined(__recom) +use g_sbf, only: sbc_ini_recom +#endif use mod_mesh USE MOD_PARTIT USE MOD_PARSUP @@ -42,6 +45,11 @@ subroutine forcing_setup(partit, mesh) if (partit%mype==0) write(*,*) '****************************************************' if (use_ice) then call forcing_array_setup(partit, mesh) + +#if defined(__recom) + call sbc_ini_recom(partit) ! initialize forcing fields +#endif + #if !defined(__oasis) && !defined(__yac) call sbc_ini(partit, mesh) ! initialize forcing fields #endif diff --git a/src/gen_surface_forcing.F90 b/src/gen_surface_forcing.F90 index 02d22d355..4990de078 100644 --- a/src/gen_surface_forcing.F90 +++ b/src/gen_surface_forcing.F90 @@ -59,6 +59,7 @@ MODULE g_sbf public sbc_ini ! routine called before 1st time step (open files, read namelist,...) public sbc_do ! routine called each time step to provide a sbc fileds (wind,...) #if defined (__recom) + public sbc_ini_recom public sbc_do_recom ! routine called each time step to provide a sbc fileds for REcoM #endif public sbc_end ! routine called after last time step @@ -1052,9 +1053,9 @@ SUBROUTINE sbc_ini(partit, mesh) nm_runoff_file, runoff_data_source, runoff_climatology, nm_sss_data_file, sss_data_source, & chl_data_source, nm_chl_data_file, chl_const, use_runoff_mapper, runoff_basins_file, runoff_radius -#if defined(__recom) - namelist /nam_rsbc/ fe_data_source, nm_fe_data_file, nm_aen_data_file, nm_river_data_file, nm_erosion_data_file, nm_co2_data_file -#endif +!#if defined(__recom) +! namelist /nam_rsbc/ fe_data_source, nm_fe_data_file, nm_aen_data_file, nm_river_data_file, nm_erosion_data_file, nm_co2_data_file +!#endif #include "associate_part_def.h" #include "associate_mesh_def.h" @@ -1430,36 +1431,79 @@ SUBROUTINE sbc_ini(partit, mesh) if (mype==0) write(*,*) "DONE: Ocean forcing initialization." if (mype==0) write(*,*) 'Parts of forcing data (only constant in time fields) are read' -#if defined(__recom) - ! OPEN and read namelist for SBC REcoM - open( unit=nm_sbc_unit+1, file='namelist.recom', form='formatted', access='sequential', status='old', iostat=iost ) - if (iost == 0) then +!#if defined(__recom) +! ! OPEN and read namelist for SBC REcoM +! open( unit=nm_sbc_unit+1, file='namelist.recom', form='formatted', access='sequential', status='old', iostat=iost ) +! if (iost == 0) then +!#if defined(__usetp) +! if (partit%my_fesom_group==0) then +!#endif +! if (mype==0) WRITE(*,*) ' file : ', 'namelist.recom for sbc',' open ok' +!#if defined(__usetp) +! endif !(partit%my_fesom_group==0) then +!#endif +! else +!#if defined(__usetp) +! if (partit%my_fesom_group==0) then +!#endif +! +! if (mype==0) WRITE(*,*) 'ERROR: --> bad opening file : ', 'namelist.recom for sbc',' ; iostat=',iost +!#if defined(__usetp) +! endif !(partit%my_fesom_group==0) then +!#endif +! call par_ex(partit%MPI_COMM_FESOM, partit%mype) +! stop +! endif +! READ( nm_sbc_unit+1, nml=nam_rsbc, iostat=iost ) +! close( nm_sbc_unit+1 ) +!#endif + + if (use_runoff_mapper) call read_runoff_mapper(make_full_path(runoff_basins_file), "arrival_point_id", runoff_radius, partit, mesh) + + END SUBROUTINE sbc_ini + +#if defined (__recom) + SUBROUTINE sbc_ini_recom(partit) + !!--------------------------------------------------------------------- + !! *** ROUTINE recom_sbc_ini *** + !! + !! ** Purpose : read the REcoM surface boundary condition namelist + !! (namelist.recom / nam_rsbc). Split out of sbc_ini so it + !! can be called independently from the REcoM init sequence. + !!---------------------------------------------------------------------- + IMPLICIT NONE + type(t_partit), intent(inout), target :: partit + integer :: iost ! I/O status + + namelist /nam_rsbc/ fe_data_source, nm_fe_data_file, nm_aen_data_file, & + nm_river_data_file, nm_erosion_data_file, nm_co2_data_file + + ! OPEN and read namelist for SBC REcoM + open( unit=nm_sbc_unit+1, file='namelist.recom', form='formatted', access='sequential', status='old', iostat=iost ) + if (iost == 0) then #if defined(__usetp) if (partit%my_fesom_group==0) then #endif - if (mype==0) WRITE(*,*) ' file : ', 'namelist.recom for sbc',' open ok' + if (partit%mype==0) WRITE(*,*) ' file : ', 'namelist.recom for sbc',' open ok' #if defined(__usetp) endif !(partit%my_fesom_group==0) then #endif - else + else #if defined(__usetp) if (partit%my_fesom_group==0) then #endif - - if (mype==0) WRITE(*,*) 'ERROR: --> bad opening file : ', 'namelist.recom for sbc',' ; iostat=',iost + if (partit%mype==0) WRITE(*,*) 'ERROR: --> bad opening file : ', 'namelist.recom for sbc',' ; iostat=',iost #if defined(__usetp) endif !(partit%my_fesom_group==0) then #endif - call par_ex(partit%MPI_COMM_FESOM, partit%mype) - stop - endif - READ( nm_sbc_unit+1, nml=nam_rsbc, iostat=iost ) - close( nm_sbc_unit+1 ) -#endif - - if (use_runoff_mapper) call read_runoff_mapper(make_full_path(runoff_basins_file), "arrival_point_id", runoff_radius, partit, mesh) + call par_ex(partit%MPI_COMM_FESOM, partit%mype) + stop + endif - END SUBROUTINE sbc_ini + READ( nm_sbc_unit+1, nml=nam_rsbc, iostat=iost ) + close( nm_sbc_unit+1 ) + END SUBROUTINE sbc_ini_recom +#endif SUBROUTINE sbc_do(partit, mesh) !!--------------------------------------------------------------------- From 1a15a94baf0acf8ad16af2cc02989949acbef59d Mon Sep 17 00:00:00 2001 From: Ying Ye Date: Wed, 8 Jul 2026 13:51:56 +0200 Subject: [PATCH 68/68] reading of tp paramter improved --- src/gen_modules_config.F90 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/gen_modules_config.F90 b/src/gen_modules_config.F90 index 6159722fd..4425d3575 100755 --- a/src/gen_modules_config.F90 +++ b/src/gen_modules_config.F90 @@ -158,14 +158,19 @@ module g_config logical :: flag_warn_cflz=.true. ! switches off cflz warning logical :: use_transit=.false. ! switches off transient tracers logical :: compute_oasis_corners=.false. ! switches on corner calculation for 1st order conserv remapping + +#if defined(__recom) && defined(__usetp) +! number of groups for multi FESOM group loop parallelization + integer :: num_fesom_groups=1 + namelist /run_config/ use_ice,use_floatice, use_sw_pene, use_cavity, & + use_cavity_partial_cell, cavity_partial_cell_thresh, & + use_cavity_fw2press, toy_ocean, which_toy, flag_debug, flag_warn_cflz, lwiso, & + use_transit, compute_oasis_corners, num_fesom_groups +#else namelist /run_config/ use_ice,use_floatice, use_sw_pene, use_cavity, & use_cavity_partial_cell, cavity_partial_cell_thresh, & use_cavity_fw2press, toy_ocean, which_toy, flag_debug, flag_warn_cflz, lwiso, & use_transit, compute_oasis_corners -#if defined(__recom) && defined(__usetp) -! number of groups for multi FESOM group loop parallelization - integer :: num_fesom_groups=1 - namelist /run_config/ num_fesom_groups #endif !_____________________________________________________________________________