diff --git a/config/namelist.config.toy_soufflet b/config/namelist.config.toy_soufflet index 6f63269d9..c2a6534de 100644 --- a/config/namelist.config.toy_soufflet +++ b/config/namelist.config.toy_soufflet @@ -1,3 +1,4 @@ + ! This is the namelist file for model general configuration &modelname @@ -6,26 +7,30 @@ runid='fesom' ×tep step_per_day=72 !96 !96 !72 !72 !45 !72 !96 -run_length= 10 !62 !62 !62 !28 -run_length_unit='y' ! y, m, d, s +run_length=10 !62 !62 !62 !28 +run_length_unit='d' ! y, m, d, s / &clockinit ! the model starts at timenew=0.0 daynew=1 -yearnew=1948 +yearnew=1958 / &paths -MeshPath='/work/ollie/sjuricke/Soufflet_20/' -ClimateDataPath='/work/ollie/dsidoren/input/hydrography/phc3.0/' -ResultPath='/home/ollie/dsidoren/test_visc/' +MeshPath='/albedo/home/pscholz/fesom2/test/meshes/soufflet/' +ClimateDataPath='/albedo/work/projects/p_fesom/FROM-OLLIE/FESOM2/hydrography/phc3.0/' +ResultPath='../result_tmp/' / &restart_log -restart_length=1 !only required for d,h,s cases, y, m take 1 -restart_length_unit='y' !output period: y, d, h, s -logfile_outfreq=960 !in logfile info. output frequency, # steps +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=72 !in logfile info. output frequency, # steps / &ale_def @@ -34,10 +39,10 @@ use_partial_cell=.false. / &geometry -cartesian=.false. +cartesian=.true. fplane=.false. cyclic_length=4.5 ![degree] -rotated_grid=.false. !option only valid for coupled model case now +rotated_grid=.false. !option only valid for coupled model case now force_rotation=.false. alphaEuler=50. ![degree] Euler angles, convention: betaEuler=15. ![degree] first around z, then around new x, @@ -49,15 +54,22 @@ include_fleapyear=.false. / &run_config -use_ice=.false. ! ocean+ice +use_ice=.false. ! ocean+ice +use_cavity=.false. ! +use_cavity_partial_cell=.false. use_floatice = .false. use_sw_pene=.false. +flag_debug=.false. +flag_warn_cflz=.false. toy_ocean=.true. which_toy="soufflet" -flag_debug=.true. +flag_debug=.false. + / &machine -n_levels=2 -n_part= 12, 36 ! 432 number of partitions on each hierarchy level +!PS n_levels=2 +!PS n_part= 70, 128 ! 432 number of partitions on each hierarchy level +n_levels=1 +n_part= 128 !6096 ! 432 number of partitions on each hierarchy level / diff --git a/config/namelist.cvmix b/config/namelist.cvmix index 18a90c979..2bf06d887 100644 --- a/config/namelist.cvmix +++ b/config/namelist.cvmix @@ -26,7 +26,9 @@ 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 diff --git a/config/namelist.dyn b/config/namelist.dyn index 91816a5e4..43ab9d0ba 100644 --- a/config/namelist.dyn +++ b/config/namelist.dyn @@ -21,5 +21,6 @@ use_wsplit = .false. ! Switch for implicite/explicte splitting of vert. veloci 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 / diff --git a/config/namelist.io b/config/namelist.io index f49eb58ef..1e32cc8b4 100644 --- a/config/namelist.io +++ b/config/namelist.io @@ -9,6 +9,7 @@ ldiag_dMOC =.false. ldiag_DVD =.false. ldiag_forc =.false. ldiag_extflds =.false. +ldiag_trflx =.false. / &nml_general @@ -21,6 +22,7 @@ vec_autorotate =.false. ! 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 +! for 'utemp', 'vtemp', 'usalt', 'vsalt' output, set ldiag_trflx=.true. &nml_list io_list = 'sst ',1, 'm', 4, 'sss ',1, 'm', 4, diff --git a/config/namelist.oce.toy_soufflet b/config/namelist.oce.toy_soufflet index f367c9f0c..99dde1154 100644 --- a/config/namelist.oce.toy_soufflet +++ b/config/namelist.oce.toy_soufflet @@ -3,81 +3,25 @@ &oce_dyn state_equation=0 ! 1 - full equation of state, 0 - linear equation of state C_d=0.0025 ! Bottom drag, nondimensional -gamma0=0.00 ! [m/s], backgroung viscosity= gamma0*len, it should be as small as possible (keep it < 0.01 m/s). -gamma1=0.002 ! [nodim], for computation of the flow aware viscosity -gamma2=0.02 ! [s/m], is only used in easy backscatter option -Div_c=.5 ! the strength of the modified Leith viscosity, nondimensional, 0.3 -- 1.0 -Leith_c=.5 ! the strength of the Leith viscosity -visc_option=5 ! 1=Harmonic Leith parameterization; - ! 2=Laplacian+Leith+biharmonic background - ! 3=Biharmonic Leith parameterization - ! 4=Biharmonic flow aware - ! 5=Easy Backscatter - ! 6=Biharmonic flow aware (viscosity depends on velocity Laplacian) - ! 7=Biharmonic flow aware (viscosity depends on velocity differences) -easy_bs_return= 1.5 ! coefficient for returned sub-gridscale energy, to be used with visc_option=5 (easy backscatter) A_ver= 1.e-4 ! Vertical viscosity, m^2/s scale_area=5.8e9 ! Visc. and diffus. are for an element with scale_area -mom_adv=2 ! 1=vector CV, p1 vel, 2=sca. CV, 3=vector inv. -free_slip=.false. ! Switch on free slip -i_vert_visc=.true. -w_split=.false. -w_exp_max=1.e-3 SPP=.false. ! Salt Plume Parameterization -Fer_GM=.false. ! to swith on/off GM after Ferrari et al. 2010 -K_GM_max = 3000.0 ! max. GM thickness diffusivity (m2/s) +Fer_GM=.false. ! 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 = 40.0 ! Resol >K_GM_rampmax[km] GM on -K_GM_rampmin = 30.0 ! Resol K_GM_rampmax[km] GM on +K_GM_rampmin = -1.0 ! Resol TB04 mixing -momix_lat = -50.0 ! latitidinal treshhold for TB04, =90 --> global -momix_kv = 0.01 ! PP/KPP, mixing coefficient within MO length -use_instabmix = .true. ! enhance convection in case of instable stratification -instabmix_kv = 0.1 -use_windmix = .false. ! enhance mixing trough wind only for PP mixing (for stability) -windmix_kv = 1.e-3 -windmix_nl = 2 - -diff_sh_limit=5.0e-3 ! for KPP, max diff due to shear instability -Kv0_const=.false. -double_diffusion=.false. ! for KPP,dd switch -K_ver=1.0e-5 -K_hor=10. -surf_relax_T=0.0 -surf_relax_S=0.0 ! 50m/300days 6.43e-07! m/s 10./(180.*86400.) -balance_salt_water =.false. ! 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. -i_vert_diff=.true. ! true -tracer_adv =2 ! 1=MUSCL, 2=MUSCL+FCT -! Implemented trassers (3d restoring): -! 301 - Fram strait. -! 302 - Bering Strait -! 303 - BSO -num_tracers=2 !number of all tracers -tracer_ID =0,1 !their IDs (0 and 1 are reserved for temperature and salinity) -/ - -&oce_init3d ! initial conditions for tracers -n_ic3d = 2 ! number of tracers to initialize -idlist = 1, 0 ! their IDs (0 is temperature, 1 is salinity, etc.). The reading order is defined here! -filelist = 'phc3.0_winter.nc', 'phc3.0_winter.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist -varlist = 'salt', 'temp' ! variables to read from specified files -t_insitu = .true. ! if T is insitu it will be converted to potential after reading it -/ diff --git a/config/namelist.tra b/config/namelist.tra index 9286412bb..fe40711f3 100644 --- a/config/namelist.tra +++ b/config/namelist.tra @@ -32,6 +32,7 @@ gamma0_tra = 0.0005 ! gammaX_tra are analogous to those in the dynamical gamma1_tra = 0.0125 gamma2_tra = 0. i_vert_diff =.true. +AB_order = 2 / &tracer_phys diff --git a/config/namelist.tra.toy_soufflet b/config/namelist.tra.toy_soufflet new file mode 100755 index 000000000..0fbca7d5b --- /dev/null +++ b/config/namelist.tra.toy_soufflet @@ -0,0 +1,57 @@ +&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., +!101, 'UPW1', 'UPW1', 'NON ', 0., 0. +/ + +&tracer_init3d ! initial conditions for tracers +n_ic3d = 2 ! number of tracers to initialize +idlist = 2, 1 ! their IDs (0 is temperature, 1 is salinity, etc.). The reading order is defined here! +filelist = 'phc3.0_winter.nc', 'phc3.0_winter.nc' ! list of files in ClimateDataPath to read (one file per tracer), same order as idlist +varlist = '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 = .false. ! 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=.false. +double_diffusion=.false. ! for KPP,dd switch +K_ver=1.0e-5 +K_hor=10. +surf_relax_T=0.0 +surf_relax_S=1.929e-06 ! 50m/300days 6.43e-07! m/s 10./(180.*86400.) +balance_salt_water =.false. ! balance virtual-salt or freshwater flux or not +clim_relax=0.0 ! 1/s, geometrical information has to be supplied +ref_sss_local=.true. +ref_sss=34. +/ diff --git a/src/MOD_DYN.F90 b/src/MOD_DYN.F90 index ded902231..3d7dab074 100644 --- a/src/MOD_DYN.F90 +++ b/src/MOD_DYN.F90 @@ -51,8 +51,9 @@ MODULE MOD_DYN TYPE T_DYN !___________________________________________________________________________ ! instant zonal merdional velocity & Adams-Bashfort rhs - real(kind=WP), allocatable, dimension(:,:,:):: uv, uv_rhs, uv_rhsAB, fer_uv - + real(kind=WP), allocatable, dimension(:,:,:) :: uv, uv_rhs, fer_uv + real(kind=WP), allocatable, dimension(:,:,:,:) :: uv_rhsAB + integer :: AB_order=2 ! horizontal velocities at nodes real(kind=WP), allocatable, dimension(:,:,:):: uvnode @@ -108,12 +109,12 @@ MODULE MOD_DYN real(kind=WP), allocatable, dimension(:,:,:) :: ke_adv, ke_cor, ke_pre, ke_hvis, ke_vvis, ke_du2, ke_umean, ke_u2mean real(kind=WP), allocatable, dimension(:,:) :: ke_wind, ke_drag ! same as above but multiplied by velocity. we need both for later computation of turbulent fluxes - real(kind=WP), allocatable, dimension(:,:,:) :: ke_adv_xVEL, ke_cor_xVEL, ke_pre_xVEL, ke_hvis_xVEL, ke_vvis_xVEL - real(kind=WP), allocatable, dimension(:,:) :: ke_wind_xVEL, ke_drag_xVEL - real(kind=WP), allocatable, dimension(:,:) :: ke_wrho !we use pressure to compute (W*dens) as it appeares much easier to compute (P*dW) instead of (dP*w) - real(kind=WP), allocatable, dimension(:,:) :: ke_dW, ke_Pfull !for later computation of turbulent fluxes from the term above - real(kind=WP), allocatable, dimension(:,:,:) :: ke_adv_AB, ke_cor_AB - real(kind=WP), allocatable, dimension(:,:,:) :: ke_rhs_bak + real(kind=WP), allocatable, dimension(:,:,:) :: ke_adv_xVEL, ke_cor_xVEL, ke_pre_xVEL, ke_hvis_xVEL, ke_vvis_xVEL + real(kind=WP), allocatable, dimension(:,:) :: ke_wind_xVEL, ke_drag_xVEL + real(kind=WP), allocatable, dimension(:,:) :: ke_wrho !we use pressure to compute (W*dens) as it appeares much easier to compute (P*dW) instead of (dP*w) + real(kind=WP), allocatable, dimension(:,:) :: ke_dW, ke_Pfull !for later computation of turbulent fluxes from the term above + real(kind=WP), allocatable, dimension(:,:,:,:) :: ke_adv_AB, ke_cor_AB + real(kind=WP), allocatable, dimension(:,:,:) :: ke_rhs_bak ! surface fields to compute APE generation real(kind=WP), allocatable, dimension(:) :: ke_J, ke_D, ke_G, ke_D2, ke_n0, ke_JD, ke_GD, ke_swA, ke_swB diff --git a/src/MOD_READ_BINARY_ARRAYS.F90 b/src/MOD_READ_BINARY_ARRAYS.F90 index 9d8e7614b..60de11673 100644 --- a/src/MOD_READ_BINARY_ARRAYS.F90 +++ b/src/MOD_READ_BINARY_ARRAYS.F90 @@ -7,7 +7,7 @@ MODULE MOD_READ_BINARY_ARRAYS private public :: read_bin_array, read1d_int_static INTERFACE read_bin_array - MODULE PROCEDURE read1d_real, read1d_int, read1d_char, read2d_real, read2d_int, read3d_real, read3d_int + MODULE PROCEDURE read1d_real, read1d_int, read1d_char, read2d_real, read2d_int, read3d_real, read3d_int, read4d_real, read4d_int END INTERFACE contains subroutine read1d_real(arr, unit, iostat, iomsg) @@ -113,5 +113,31 @@ subroutine read3d_int(arr, unit, iostat, iomsg) if (.not. allocated(arr)) allocate(arr(s1,s2,s3)) read(unit, iostat=iostat, iomsg=iomsg) arr(1:s1, 1:s2, 1:s3) end subroutine read3d_int + +subroutine read4d_real(arr, unit, iostat, iomsg) + real(kind=WP), intent(inout), allocatable :: arr(:,:,:,:) + integer, intent(in) :: unit + integer, intent(out) :: iostat + character(*), intent(inout) :: iomsg + integer :: s1, s2, s3, s4 + + read(unit, iostat=iostat, iomsg=iomsg) s1, s2, s3, s4 + if ((s1==0) .or. (s2==0) .or. (s3==0) .or. (s4==0)) return + if (.not. allocated(arr)) allocate(arr(s1,s2,s3,s4)) + read(unit, iostat=iostat, iomsg=iomsg) arr(1:s1, 1:s2, 1:s3, 1:s4) +end subroutine read4d_real + +subroutine read4d_int(arr, unit, iostat, iomsg) + integer, intent(inout), allocatable :: arr(:,:,:,:) + integer, intent(in) :: unit + integer, intent(out) :: iostat + character(*), intent(inout) :: iomsg + integer :: s1, s2, s3, s4 + + read(unit, iostat=iostat, iomsg=iomsg) s1, s2, s3, s4 + if ((s1==0) .or. (s2==0) .or. (s3==0) .or. (s4==0)) return + if (.not. allocated(arr)) allocate(arr(s1,s2,s3,s4)) + read(unit, iostat=iostat, iomsg=iomsg) arr(1:s1, 1:s2, 1:s3, 1:s4) +end subroutine read4d_int end module MOD_READ_BINARY_ARRAYS !========================================================== diff --git a/src/MOD_TRACER.F90 b/src/MOD_TRACER.F90 index 0e66e96aa..fe2f73118 100644 --- a/src/MOD_TRACER.F90 +++ b/src/MOD_TRACER.F90 @@ -8,14 +8,18 @@ MODULE MOD_TRACER SAVE TYPE T_TRACER_DATA -real(kind=WP), allocatable, dimension(:,:) :: values, valuesAB ! instant values & Adams-Bashfort interpolation -logical :: smooth_bh_tra=.false. -real(kind=WP) :: gamma0_tra, gamma1_tra, gamma2_tra -logical :: i_vert_diff =.false. -character(20) :: tra_adv_hor, tra_adv_ver, tra_adv_lim ! type of the advection scheme for this tracer -real(kind=WP) :: tra_adv_ph = 1. ! a parameter to be used in horizontal advection (for MUSCL it is the fraction of fourth-order contribution in the solution) -real(kind=WP) :: tra_adv_pv = 1. ! a parameter to be used in horizontal advection (for QR4C it is the fraction of fourth-order contribution in the solution) -integer :: ID +real(kind=WP), allocatable, dimension(:,:) :: values ! instant values +real(kind=WP), allocatable, dimension(:,:) :: valuesAB ! Adams-Bashfort interpolation +real(kind=WP), allocatable, dimension(:,:,:) :: valuesold ! previous timesteps + +logical :: smooth_bh_tra=.false. +real(kind=WP) :: gamma0_tra, gamma1_tra, gamma2_tra +logical :: i_vert_diff =.false. +character(20) :: tra_adv_hor, tra_adv_ver, tra_adv_lim ! type of the advection scheme for this tracer +real(kind=WP) :: tra_adv_ph = 1. ! a parameter to be used in horizontal advection (for MUSCL it is the fraction of fourth-order contribution in the solution) +real(kind=WP) :: tra_adv_pv = 1. ! a parameter to be used in horizontal advection (for QR4C it is the fraction of fourth-order contribution in the solution) +integer :: AB_order=2 +integer :: ID contains procedure WRITE_T_TRACER_DATA @@ -95,6 +99,7 @@ subroutine WRITE_T_TRACER_DATA(tdata, unit) character(len=1024) :: iomsg call write_bin_array(tdata%values, unit, iostat, iomsg) + call write_bin_array(tdata%valuesold,unit, iostat, iomsg) call write_bin_array(tdata%valuesAB, unit, iostat, iomsg) write(unit, iostat=iostat, iomsg=iomsg) tdata%smooth_bh_tra write(unit, iostat=iostat, iomsg=iomsg) tdata%gamma0_tra @@ -117,8 +122,9 @@ subroutine READ_T_TRACER_DATA(tdata, unit) integer :: iostat character(len=1024) :: iomsg - call read_bin_array(tdata%values, unit, iostat, iomsg) - call read_bin_array(tdata%valuesAB, unit, iostat, iomsg) + call read_bin_array(tdata%values, unit, iostat, iomsg) + call read_bin_array(tdata%valuesold,unit, iostat, iomsg) + call read_bin_array(tdata%valuesAB, unit, iostat, iomsg) read(unit, iostat=iostat, iomsg=iomsg) tdata%smooth_bh_tra read(unit, iostat=iostat, iomsg=iomsg) tdata%gamma0_tra read(unit, iostat=iostat, iomsg=iomsg) tdata%gamma1_tra diff --git a/src/MOD_WRITE_BINARY_ARRAYS.F90 b/src/MOD_WRITE_BINARY_ARRAYS.F90 index 119563c17..366542a4b 100644 --- a/src/MOD_WRITE_BINARY_ARRAYS.F90 +++ b/src/MOD_WRITE_BINARY_ARRAYS.F90 @@ -7,7 +7,7 @@ MODULE MOD_WRITE_BINARY_ARRAYS private public :: write_bin_array, write1d_int_static INTERFACE write_bin_array - MODULE PROCEDURE write1d_real, write1d_int, write1d_char, write2d_real, write2d_int, write3d_real, write3d_int + MODULE PROCEDURE write1d_real, write1d_int, write1d_char, write2d_real, write2d_int, write3d_real, write3d_int, write4d_real, write4d_int END INTERFACE contains @@ -155,5 +155,51 @@ subroutine write3d_int(arr, unit, iostat, iomsg) write(unit, iostat=iostat, iomsg=iomsg) s1, s2, s3 end if end subroutine write3d_int +subroutine write4d_real(arr, unit, iostat, iomsg) + real(kind=WP), intent(in), allocatable :: arr(:,:,:,:) + integer, intent(in) :: unit + integer, intent(out) :: iostat + character(*), intent(inout) :: iomsg + integer :: s1, s2, s3, s4 + + if (allocated(arr)) then + s1=size(arr, 1) + s2=size(arr, 2) + s3=size(arr, 3) + s4=size(arr, 4) + write(unit, iostat=iostat, iomsg=iomsg) s1, s2, s3, s4 + write(unit, iostat=iostat, iomsg=iomsg) arr(1:s1, 1:s2, 1:s3, 1:s4) + else + s1=0 + s2=0 + s3=0 + s4=0 + write(unit, iostat=iostat, iomsg=iomsg) s1, s2, s3, s4 + end if +end subroutine write4d_real + +subroutine write4d_int(arr, unit, iostat, iomsg) + integer, intent(in), allocatable :: arr(:,:,:,:) + integer, intent(in) :: unit + integer, intent(out) :: iostat + character(*), intent(inout) :: iomsg + integer :: s1, s2, s3, s4 + + if (allocated(arr)) then + s1=size(arr, 1) + s2=size(arr, 2) + s3=size(arr, 3) + s4=size(arr, 4) + write(unit, iostat=iostat, iomsg=iomsg) s1, s2, s3, s4 + write(unit, iostat=iostat, iomsg=iomsg) arr(1:s1, 1:s2, 1:s3, 1:s4) + else + s1=0 + s2=0 + s3=0 + s4=0 + write(unit, iostat=iostat, iomsg=iomsg) s1, s2, s3, s4 + end if +end subroutine write4d_int + end module MOD_WRITE_BINARY_ARRAYS !========================================================== diff --git a/src/gen_model_setup.F90 b/src/gen_model_setup.F90 index 02b71726a..c0be423f4 100755 --- a/src/gen_model_setup.F90 +++ b/src/gen_model_setup.F90 @@ -6,7 +6,7 @@ subroutine setup_model(partit) ! use i_therm_param use g_forcing_param use g_config - use diagnostics, only: ldiag_solver,lcurt_stress_surf,lcurt_stress_surf, ldiag_Ri, ldiag_TurbFlux, & + use diagnostics, only: ldiag_solver,lcurt_stress_surf,lcurt_stress_surf, ldiag_Ri, ldiag_TurbFlux, ldiag_trflx, & ldiag_dMOC, ldiag_DVD, diag_list use g_clock, only: timenew, daynew, yearnew use g_ic3d diff --git a/src/gen_modules_diag.F90 b/src/gen_modules_diag.F90 index e0156774e..acff5c43f 100644 --- a/src/gen_modules_diag.F90 +++ b/src/gen_modules_diag.F90 @@ -19,10 +19,10 @@ module diagnostics public :: ldiag_solver, lcurt_stress_surf, ldiag_Ri, ldiag_TurbFlux, ldiag_dMOC, ldiag_DVD, & ldiag_forc, ldiag_salt3D, ldiag_curl_vel3, diag_list, ldiag_vorticity, ldiag_extflds, & compute_diagnostics, rhs_diag, curl_stress_surf, curl_vel3, shear, Ri, KvdTdZ, KvdSdZ, & - std_dens_min, std_dens_max, std_dens_N, std_dens, & + std_dens_min, std_dens_max, std_dens_N, std_dens, ldiag_trflx, & std_dens_UVDZ, std_dens_DIV, std_dens_DIV_fer, std_dens_Z, std_dens_H, std_dens_dVdT, std_dens_flux, & dens_flux_e, vorticity, zisotherm, tempzavg, saltzavg, compute_diag_dvd_2ndmoment_klingbeil_etal_2014, & - compute_diag_dvd_2ndmoment_burchard_etal_2008, compute_diag_dvd + compute_diag_dvd_2ndmoment_burchard_etal_2008, compute_diag_dvd, tuv, suv ! Arrays used for diagnostics, some shall be accessible to the I/O ! 1. solver diagnostics: A*x=rhs? @@ -55,6 +55,7 @@ module diagnostics real(kind=WP), save, target :: std_dens_min=1030., std_dens_max=1040. real(kind=WP), save, allocatable, target :: std_dens_UVDZ(:,:,:), std_dens_flux(:,:,:), std_dens_dVdT(:,:), std_dens_DIV(:,:), std_dens_DIV_fer(:,:), std_dens_Z(:,:), std_dens_H(:,:) real(kind=WP), save, allocatable, target :: dens_flux_e(:) + real(kind=WP), save, allocatable, target :: tuv(:,:,:), suv(:,:,:) logical :: ldiag_solver =.false. logical :: lcurt_stress_surf=.false. @@ -75,8 +76,10 @@ module diagnostics logical :: ldiag_vorticity =.false. logical :: ldiag_extflds =.false. - - namelist /diag_list/ ldiag_solver, lcurt_stress_surf, ldiag_curl_vel3, ldiag_Ri, ldiag_TurbFlux, ldiag_dMOC, ldiag_DVD, ldiag_salt3D, ldiag_forc, ldiag_vorticity, ldiag_extflds + logical :: ldiag_trflx =.false. + + namelist /diag_list/ ldiag_solver, lcurt_stress_surf, ldiag_curl_vel3, ldiag_Ri, ldiag_TurbFlux, ldiag_dMOC, ldiag_DVD, & + ldiag_salt3D, ldiag_forc, ldiag_vorticity, ldiag_extflds, ldiag_trflx contains @@ -281,6 +284,61 @@ subroutine diag_turbflux(mode, dynamics, tracers, partit, mesh) end do end subroutine diag_turbflux ! ============================================================== +! +subroutine diag_trflx(mode, dynamics, tracers, partit, mesh) + implicit none + type(t_dyn) , intent(inout), target :: dynamics + type(t_tracer), intent(in) , target :: tracers + type(t_partit), intent(inout), target :: partit + type(t_mesh) , intent(in) , target :: mesh + integer, intent(in) :: mode + logical, save :: firstcall=.true. + integer :: elem, nz, nzu, nzl, elnodes(3) + real(kind=WP), dimension(:,:,:), pointer :: UV, fer_UV + real(kind=WP), dimension(:,:), pointer :: temp, salt + +#include "associate_part_def.h" +#include "associate_mesh_def.h" +#include "associate_part_ass.h" +#include "associate_mesh_ass.h" +UV => dynamics%uv(:,:,:) +temp => tracers%data(1)%values(:,:) +salt => tracers%data(2)%values(:,:) +fer_UV => dynamics%fer_uv(:,:,:) +!===================== + if (firstcall) then !allocate the stuff at the first call + allocate(tuv(2,nl-1,myDim_elem2D+eDim_elem2D)) + allocate(suv(2,nl-1,myDim_elem2D+eDim_elem2D)) + tuv = 0.0_WP + suv = 0.0_WP + firstcall=.false. + if (mode==0) return + end if + + !___________________________________________________________________________ + ! compute tracer fluxes + do elem=1,myDim_elem2D + elnodes = elem2D_nodes(:,elem) + nzu = ulevels(elem) + nzl = nlevels(elem)-1 + if (Fer_GM) then + do nz=nzu, nzl + tuv(1,nz,elem) = (UV(1,nz,elem) + fer_UV(1,nz, elem)) * sum(temp(nz,elnodes))/3._WP + tuv(2,nz,elem) = (UV(2,nz,elem) + fer_UV(2,nz, elem)) * sum(temp(nz,elnodes))/3._WP + suv(1,nz,elem) = (UV(1,nz,elem) + fer_UV(1,nz, elem)) * sum(salt(nz,elnodes))/3._WP + suv(2,nz,elem) = (UV(2,nz,elem) + fer_UV(2,nz, elem)) * sum(salt(nz,elnodes))/3._WP + end do + else + do nz=nzu, nzl + tuv(1,nz,elem) = UV(1,nz,elem) * sum(temp(nz,elnodes))/3._WP + tuv(2,nz,elem) = UV(2,nz,elem) * sum(temp(nz,elnodes))/3._WP + suv(1,nz,elem) = UV(1,nz,elem) * sum(salt(nz,elnodes))/3._WP + suv(2,nz,elem) = UV(2,nz,elem) * sum(salt(nz,elnodes))/3._WP + end do + end if + end do +end subroutine diag_trflx +! ============================================================== ! subroutine diag_Ri(mode, dynamics, partit, mesh) implicit none @@ -858,6 +916,8 @@ subroutine compute_diagnostics(mode, dynamics, tracers, partit, mesh) if (ldiag_dMOC) call diag_densMOC(mode, dynamics, tracers, partit, mesh) !7. compute turbulent fluxes if (ldiag_turbflux) call diag_turbflux(mode, dynamics, tracers, partit, mesh) + !8. compute tracers fluxes + if (ldiag_trflx) call diag_trflx(mode, dynamics, tracers, partit, mesh) ! compute relative vorticity if (ldiag_vorticity) call relative_vorticity(mode, dynamics, partit, mesh) ! soe exchanged fields requested by IFS/FESOM in NextGEMS. diff --git a/src/io_blowup.F90 b/src/io_blowup.F90 index 60832dd37..87e570c3b 100644 --- a/src/io_blowup.F90 +++ b/src/io_blowup.F90 @@ -115,8 +115,8 @@ subroutine ini_blowup_io(year, ice, dynamics, tracers, partit, mesh) call def_variable(bid, 'v' , (/nl-1, elem2D/) , 'meridional velocity', 'm/s', dynamics%uv(2,:,:)); call def_variable(bid, 'u_rhs' , (/nl-1, elem2D/) , 'zonal velocity', 'm/s', dynamics%uv_rhs(1,:,:)); call def_variable(bid, 'v_rhs' , (/nl-1, elem2D/) , 'meridional velocity', 'm/s', dynamics%uv_rhs(2,:,:)); - call def_variable(bid, 'urhs_AB' , (/nl-1, elem2D/) , 'Adams–Bashforth for u', 'm/s', dynamics%uv_rhsAB(1,:,:)); - call def_variable(bid, 'vrhs_AB' , (/nl-1, elem2D/) , 'Adams–Bashforth for v', 'm/s', dynamics%uv_rhsAB(2,:,:)); + call def_variable(bid, 'urhs_AB' , (/nl-1, elem2D/) , 'Adams-Bashforth for u', 'm/s', dynamics%uv_rhsAB(1,1,:,:)); + call def_variable(bid, 'vrhs_AB' , (/nl-1, elem2D/) , 'Adams-Bashforth for v', 'm/s', dynamics%uv_rhsAB(1,2,:,:)); call def_variable(bid, 'zbar_n_bot' , (/nod2D/) , 'node bottom depth', 'm', zbar_n_bot); call def_variable(bid, 'zbar_e_bot' , (/elem2d/) , 'elem bottom depth', 'm', zbar_e_bot); call def_variable(bid, 'bottom_node_thickness' , (/nod2D/) , 'node bottom thickness', 'm', bottom_node_thickness); diff --git a/src/io_meandata.F90 b/src/io_meandata.F90 index 03af7c5d7..14daf4ed2 100644 --- a/src/io_meandata.F90 +++ b/src/io_meandata.F90 @@ -395,13 +395,14 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) end if CASE ('tx_sur ') sel_forcvar(11) = 1 - call def_stream(elem2D, myDim_elem2D, 'tx_sur', 'zonal wind str. to ocean', 'm/s2', stress_surf(1, :), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(elem2D, myDim_elem2D, 'tx_sur', 'total zonal str. to ocean', 'm/s2', stress_surf(1, :), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) CASE ('ty_sur ') sel_forcvar(12) = 1 - call def_stream(elem2D, myDim_elem2D, 'ty_sur', 'meridional wind str. to ocean', 'm/s2', stress_surf(2, :), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(elem2D, myDim_elem2D, 'ty_sur', 'total meridional str. to ocean', 'm/s2', stress_surf(2, :), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) CASE ('curl_surf ') if (lcurt_stress_surf) then - call def_stream(nod2D, myDim_nod2D, 'curl_surf', 'vorticity of the surface stress','none', curl_stress_surf(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + call def_stream(nod2D, myDim_nod2D, 'curl_surf', 'vorticity of the surface stress', 'none', curl_stress_surf(:), io_list(i)%freq, io_list(i)%unit, io_list(i)%precision, partit, mesh) + end if !___________________________________________________________________________________________________________________________________ @@ -642,6 +643,14 @@ subroutine ini_mean_io(ice, dynamics, tracers, partit, mesh) call def_stream((/nl, nod2D/), (/nl, myDim_nod2D/), 'KvdSdz', 'KvdSdz', 'PSU m/s', KvdSdz(:,:), 1, 'm', i_real8, partit, mesh) end if !___________________________________________________________________________ + ! Tracers flux diagnostics + if (ldiag_trflx) then + call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'utemp', 'u*temp', 'm/s*°C', tuv(1,:,:), 1, 'm', i_real8, partit, mesh) + call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'vtemp', 'v*temp', 'm/s*°C', tuv(2,:,:), 1, 'm', i_real8, partit, mesh) + call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'usalt', 'u*salt', 'm/s*psu', suv(1,:,:), 1, 'm', i_real8, partit, mesh) + call def_stream((/nl-1, elem2D/), (/nl-1, myDim_elem2D/), 'vsalt', 'v*salt', 'm/s*psu', suv(2,:,:), 1, 'm', i_real8, partit, mesh) + end if + !___________________________________________________________________________ ! output Redi parameterisation if (Redi) then call def_stream((/nl-1 , nod2D /), (/nl-1, myDim_nod2D /), 'Redi_K', 'Redi diffusion coefficient', 'm2/s', Ki(:,:), 1, 'y', i_real4, partit, mesh) @@ -1674,6 +1683,8 @@ subroutine io_r2g(n, partit, mesh) IF ((trim(entry_x%name)=='atmice_x') .AND. ((trim(entry_y%name)=='atmice_y'))) do_rotation=.TRUE. IF ((trim(entry_x%name)=='atmoce_x') .AND. ((trim(entry_y%name)=='atmoce_y'))) do_rotation=.TRUE. IF ((trim(entry_x%name)=='iceoce_x') .AND. ((trim(entry_y%name)=='iceoce_y'))) do_rotation=.TRUE. + IF ((trim(entry_x%name)=='utemp' ) .AND. ((trim(entry_y%name)=='vtemp' ))) do_rotation=.TRUE. + IF ((trim(entry_x%name)=='usalt' ) .AND. ((trim(entry_y%name)=='vsalt' ))) do_rotation=.TRUE. IF (.NOT. (do_rotation)) RETURN diff --git a/src/io_restart.F90 b/src/io_restart.F90 index 33fcdb0d4..60819e928 100644 --- a/src/io_restart.F90 +++ b/src/io_restart.F90 @@ -76,10 +76,14 @@ subroutine ini_ocean_io(year, dynamics, tracers, partit, mesh) #endif call oce_files%def_elem_var('u', 'zonal velocity', 'm/s', dynamics%uv(1,:,:), mesh, partit) call oce_files%def_elem_var('v', 'meridional velocity', 'm/s', dynamics%uv(2,:,:), mesh, partit) - call oce_files%def_elem_var('urhs_AB', 'Adams–Bashforth for u', 'm/s', dynamics%uv_rhsAB(1,:,:), mesh, partit) - call oce_files%def_elem_var('vrhs_AB', 'Adams–Bashforth for v', 'm/s', dynamics%uv_rhsAB(2,:,:), mesh, partit) + call oce_files%def_elem_var('urhs_AB', 'Adams-Bashforth for u (n-1 for AB2 and n-2 for AB3)', 'm/s', dynamics%uv_rhsAB(1,1,:,:), mesh, partit) + call oce_files%def_elem_var('vrhs_AB', 'Adams-Bashforth for v (n-1 for AB2 and n-2 for AB3)', 'm/s', dynamics%uv_rhsAB(1,2,:,:), mesh, partit) + if (dynamics%AB_order==3) then + call oce_files%def_elem_var_optional('urhs_AB3', 'Adams-Bashforth for u (n-1) for AB3', 'm/s', dynamics%uv_rhsAB(2,1,:,:), mesh, partit) + call oce_files%def_elem_var_optional('vrhs_AB3', 'Adams-Bashforth for v (n-1) for AB3', 'm/s', dynamics%uv_rhsAB(2,2,:,:), mesh, partit) + end if - !___Save restart variables for TKE and IDEMIX_________________________________ +!___Save restart variables for TKE and IDEMIX_________________________________ ! if (trim(mix_scheme)=='cvmix_TKE' .or. trim(mix_scheme)=='cvmix_TKE+IDEMIX') then if (mix_scheme_nmb==5 .or. mix_scheme_nmb==56) then call oce_files%def_node_var_optional('tke', 'Turbulent Kinetic Energy', 'm2/s2', tke(:,:), mesh, partit) @@ -109,8 +113,11 @@ subroutine ini_ocean_io(year, dynamics, tracers, partit, mesh) units='none' END SELECT call oce_files%def_node_var(trim(trname), trim(longname), trim(units), tracers%data(j)%values(:,:), mesh, partit) - longname=trim(longname)//', Adams–Bashforth' - call oce_files%def_node_var(trim(trname)//'_AB', trim(longname), trim(units), tracers%data(j)%valuesAB(:,:), mesh, partit) + longname=trim(longname)//', Adams-Bashforth' + call oce_files%def_node_var(trim(trname)//'_AB', trim(longname), trim(units), tracers%data(j)%valuesAB(:,:), mesh, partit) + call oce_files%def_node_var_optional(trim(trname)//'_M1', trim(longname), trim(units), tracers%data(j)%valuesold(1,:,:), mesh, partit) + if (tracers%data(j)%AB_order==3) & + call oce_files%def_node_var_optional(trim(trname)//'_M2', trim(longname), trim(units), tracers%data(j)%valuesold(2,:,:), mesh, partit) end do call oce_files%def_node_var('w', 'vertical velocity', 'm/s', dynamics%w, mesh, partit) call oce_files%def_node_var('w_expl', 'vertical velocity', 'm/s', dynamics%w_e, mesh, partit) diff --git a/src/io_restart_file_group.F90 b/src/io_restart_file_group.F90 index 772c8e1d0..03a2115d6 100644 --- a/src/io_restart_file_group.F90 +++ b/src/io_restart_file_group.F90 @@ -17,7 +17,7 @@ module restart_file_group_module type restart_file_group private - type(restart_file_type), public :: files(20) + type(restart_file_type), public :: files(22) integer, public :: nfiles = 0 ! todo: allow dynamically allocated size without messing with shallow copied pointers contains generic, public :: def_node_var => def_node_var_2d, def_node_var_3d diff --git a/src/oce_ale_tracer.F90 b/src/oce_ale_tracer.F90 index 932110adf..92c6ce552 100644 --- a/src/oce_ale_tracer.F90 +++ b/src/oce_ale_tracer.F90 @@ -148,7 +148,7 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) type(t_partit), intent(inout), target :: partit type(t_mesh) , intent(in) , target :: mesh !___________________________________________________________________________ - integer :: tr_num, node, elem, nzmax, nzmin + integer :: i, tr_num, node, elem, nzmax, nzmin !___________________________________________________________________________ ! pointer on necessary derived types real(kind=WP), dimension(:,:,:), pointer :: UV, fer_UV @@ -227,14 +227,6 @@ subroutine solve_tracers_ale(ice, dynamics, tracers, partit, mesh) do node=1, myDim_nod2d tracers%work%del_ttf(:, node)=tracers%work%del_ttf(:, node)+tracers%work%del_ttf_advhoriz(:, node)+tracers%work%del_ttf_advvert(:, node) end do -!$OMP END PARALLEL DO - !___________________________________________________________________________ - ! AB is not needed after the advection step. Initialize it with the current tracer before it is modified. - ! call init_tracers_AB at the beginning of this loop will compute AB for the next time step then. -!$OMP PARALLEL DO - do node=1, myDim_nod2d+eDim_nod2D - tracers%data(tr_num)%valuesAB(:, node)=tracers%data(tr_num)%values(:, node) !DS: check that this is the right place! - end do !$OMP END PARALLEL DO ! diffuse tracers if (flag_debug .and. mype==0) print *, achar(27)//'[37m'//' --> call diff_tracers_ale'//achar(27)//'[0m' diff --git a/src/oce_ale_vel_rhs.F90 b/src/oce_ale_vel_rhs.F90 index b951767cb..164a7df4a 100644 --- a/src/oce_ale_vel_rhs.F90 +++ b/src/oce_ale_vel_rhs.F90 @@ -60,17 +60,19 @@ subroutine compute_vel_rhs(ice, dynamics, partit, mesh) integer :: use_pice !___________________________________________________________________________ ! pointer on necessary derived types - real(kind=WP), dimension(:,:,:), pointer :: UV, UV_rhsAB, UV_rhs - real(kind=WP), dimension(:) , pointer :: eta_n - real(kind=WP), dimension(:) , pointer :: m_ice, m_snow, a_ice - real(kind=WP) , pointer :: rhoice, rhosno, inv_rhowat + real(kind=WP), dimension(:,:,:), pointer :: UV, UV_rhs + real(kind=WP), dimension(:,:,:,:), pointer :: UV_rhsAB + real(kind=WP), dimension(:) , pointer :: eta_n + real(kind=WP), dimension(:) , pointer :: m_ice, m_snow, a_ice + real(kind=WP) , pointer :: rhoice, rhosno, inv_rhowat + real(kind=WP) :: ab1, ab2, ab3 !Adams-Bashforth coefficients #include "associate_part_def.h" #include "associate_mesh_def.h" #include "associate_part_ass.h" #include "associate_mesh_ass.h" UV => dynamics%uv(:,:,:) UV_rhs => dynamics%uv_rhs(:,:,:) - UV_rhsAB => dynamics%uv_rhsAB(:,:,:) + UV_rhsAB => dynamics%uv_rhsAB(:,:,:,:) eta_n => dynamics%eta_n(:) m_ice => ice%data(2)%values(:) m_snow => ice%data(3)%values(:) @@ -83,6 +85,20 @@ subroutine compute_vel_rhs(ice, dynamics, partit, mesh) if (use_floatice .and. .not. trim(which_ale)=='linfs') use_pice=1 if ((toy_ocean) .and. (trim(which_toy)=="soufflet")) use_pice=0 + IF (dynamics%AB_order==2) THEN + ab1=-(0.5_WP+epsilon) + ab2= (1.5_WP+epsilon) + ab3= 0.0_WP + ELSEIF (dynamics%AB_order==3) THEN + ab1= 5.0_WP/12.0_WP + ab2=-16.0_WP/12.0_WP + ab3= 23.0_WP/12.0_WP + ELSE + write(*,*) 'unsuppported AB scheme for momentum, use 2 or 3' + call par_ex(partit%MPI_COMM_FESOM, partit%mype, 1) + stop + END IF + !$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(elem, nz, nzmin, nzmax, elnodes, ff, mm, Fx, Fy, pre, p_ice, p_air, p_eta) do elem=1, myDim_elem2D nzmax = nlevels(elem) @@ -90,16 +106,29 @@ subroutine compute_vel_rhs(ice, dynamics, partit, mesh) !___________________________________________________________________________ ! Take care of the AB part !!PS do nz=1,nl-1 + IF (dynamics%AB_order==2) THEN do nz=nzmin,nzmax-1 - UV_rhs(1,nz,elem)=-(0.5_WP+epsilon)*UV_rhsAB(1,nz,elem) - UV_rhs(2,nz,elem)=-(0.5_WP+epsilon)*UV_rhsAB(2,nz,elem) + UV_rhs(1,nz,elem)=ab1*UV_rhsAB(1,1,nz,elem) + UV_rhs(2,nz,elem)=ab1*UV_rhsAB(1,2,nz,elem) end do if (dynamics%ldiag_ke) then do nz=nzmin,nzmax-1 - dynamics%ke_adv(:,nz,elem)=-(0.5_WP+epsilon)*dynamics%ke_adv_AB(:,nz,elem) - dynamics%ke_cor(:,nz,elem)=-(0.5_WP+epsilon)*dynamics%ke_cor_AB(:,nz,elem) + dynamics%ke_adv(:,nz,elem)=ab1*dynamics%ke_adv_AB(1, :,nz,elem) + dynamics%ke_cor(:,nz,elem)=ab1*dynamics%ke_cor_AB(1, :,nz,elem) end do end if + ELSEIF (dynamics%AB_order==3) THEN + do nz=nzmin,nzmax-1 + UV_rhs(1,nz,elem)=ab1*UV_rhsAB(2,1,nz,elem)+ab2*UV_rhsAB(1,1,nz,elem) + UV_rhs(2,nz,elem)=ab1*UV_rhsAB(2,2,nz,elem)+ab2*UV_rhsAB(1,2,nz,elem) + end do + if (dynamics%ldiag_ke) then + do nz=nzmin,nzmax-1 + dynamics%ke_adv(:,nz,elem)=ab1*dynamics%ke_adv_AB(2,:,nz,elem)+ab2*dynamics%ke_adv_AB(1,:,nz,elem) + dynamics%ke_cor(:,nz,elem)=ab1*dynamics%ke_cor_AB(2,:,nz,elem)+ab2*dynamics%ke_cor_AB(1,:,nz,elem) + end do + end if + END IF !___________________________________________________________________________ ! Sea level and pressure contribution -\nabla(\eta +hpressure/rho_0) @@ -150,22 +179,37 @@ subroutine compute_vel_rhs(ice, dynamics, partit, mesh) ! add pressure gradient terms UV_rhs(1,nz,elem) = UV_rhs(1,nz,elem) + (Fx-pgf_x(nz,elem))*elem_area(elem) UV_rhs(2,nz,elem) = UV_rhs(2,nz,elem) + (Fy-pgf_y(nz,elem))*elem_area(elem) - + + IF (dynamics%AB_order==2) THEN ! add coriolis force - UV_rhsAB(1,nz,elem) = UV(2,nz,elem)*ff! + mm*UV(1,nz,elem)*UV(2,nz,elem) - UV_rhsAB(2,nz,elem) =-UV(1,nz,elem)*ff! - mm*UV(1,nz,elem)*UV(2,nz,elem) + UV_rhsAB(1,1,nz,elem) = UV(2,nz,elem)*ff! + mm*UV(1,nz,elem)*UV(2,nz,elem) + UV_rhsAB(1,2,nz,elem) =-UV(1,nz,elem)*ff! - mm*UV(1,nz,elem)*UV(2,nz,elem) + ELSEIF (dynamics%AB_order==3) THEN + UV_rhsAB(2,1,nz,elem) = UV_rhsAB(1,1,nz,elem) + UV_rhsAB(2,2,nz,elem) = UV_rhsAB(1,2,nz,elem) + UV_rhsAB(1,1,nz,elem) = UV(2,nz,elem)*ff + UV_rhsAB(1,2,nz,elem) =-UV(1,nz,elem)*ff + END IF end do if (dynamics%ldiag_ke) then do nz=nzmin,nzmax-1 dynamics%ke_pre(1,nz,elem)= (Fx-pgf_x(nz,elem))*dt!*elem_area(elem) !not to divide it aterwards (at the end of this subroutine) - dynamics%ke_pre(2,nz,elem)= (Fy-pgf_y(nz,elem))*dt!*elem_area(elem) !but account for DT here + dynamics%ke_pre(2,nz,elem)= (Fy-pgf_y(nz,elem))*dt!*elem_area(elem) !but account for DT here - dynamics%ke_cor_AB(1,nz,elem)= UV(2,nz,elem)*ff - dynamics%ke_cor_AB(2,nz,elem)=-UV(1,nz,elem)*ff + IF (dynamics%AB_order==3) THEN + dynamics%ke_cor_AB(2,1,nz,elem) = dynamics%ke_cor_AB(1,1,nz,elem) + dynamics%ke_cor_AB(2,2,nz,elem) = dynamics%ke_cor_AB(1,2,nz,elem) - dynamics%ke_adv_AB(1,nz,elem)= 0.0_WP - dynamics%ke_adv_AB(2,nz,elem)= 0.0_WP + dynamics%ke_adv_AB(2,1,nz,elem)= dynamics%ke_adv_AB(1,1,nz,elem) + dynamics%ke_adv_AB(2,2,nz,elem)= dynamics%ke_adv_AB(1,2,nz,elem) + END IF + + dynamics%ke_cor_AB(1,1,nz,elem)= UV(2,nz,elem)*ff + dynamics%ke_cor_AB(1,2,nz,elem)=-UV(1,nz,elem)*ff + + dynamics%ke_adv_AB(1,1,nz,elem)= 0.0_WP + dynamics%ke_adv_AB(1,2,nz,elem)= 0.0_WP end do end if @@ -181,8 +225,13 @@ subroutine compute_vel_rhs(ice, dynamics, partit, mesh) call momentum_adv_scalar(dynamics, partit, mesh) end if !___________________________________________________________________________ - ! Update the rhs - ff=(1.5_WP+epsilon) + ! Update the rhs + IF (dynamics%AB_order==2) THEN + ff=ab2 + ELSEIF (dynamics%AB_order==3) THEN + ff=ab3 + END IF + if (lfirst.and.(.not.r_restart)) then ff=1.0_WP lfirst=.false. @@ -192,8 +241,8 @@ subroutine compute_vel_rhs(ice, dynamics, partit, mesh) nzmax = nlevels(elem) nzmin = ulevels(elem) do nz=nzmin,nzmax-1 - UV_rhs(1,nz,elem)=dt*(UV_rhs(1,nz,elem)+UV_rhsAB(1,nz,elem)*ff)/elem_area(elem) - UV_rhs(2,nz,elem)=dt*(UV_rhs(2,nz,elem)+UV_rhsAB(2,nz,elem)*ff)/elem_area(elem) + UV_rhs(1,nz,elem)=dt*(UV_rhs(1,nz,elem)+UV_rhsAB(1,1,nz,elem)*ff)/elem_area(elem) + UV_rhs(2,nz,elem)=dt*(UV_rhs(2,nz,elem)+UV_rhsAB(1,2,nz,elem)*ff)/elem_area(elem) end do end do !$OMP END PARALLEL DO @@ -204,8 +253,8 @@ subroutine compute_vel_rhs(ice, dynamics, partit, mesh) nzmax = nlevels(elem) nzmin = ulevels(elem) do nz=nzmin,nzmax-1 - dynamics%ke_adv(:,nz,elem)=dt*(dynamics%ke_adv(:,nz,elem)+dynamics%ke_adv_AB(:,nz,elem)*ff)/elem_area(elem) - dynamics%ke_cor(:,nz,elem)=dt*(dynamics%ke_cor(:,nz,elem)+dynamics%ke_cor_AB(:,nz,elem)*ff)/elem_area(elem) + dynamics%ke_adv(:,nz,elem)=dt*(dynamics%ke_adv(:,nz,elem)+dynamics%ke_adv_AB(1,:,nz,elem)*ff)/elem_area(elem) + dynamics%ke_cor(:,nz,elem)=dt*(dynamics%ke_cor(:,nz,elem)+dynamics%ke_cor_AB(1,:,nz,elem)*ff)/elem_area(elem) end do end do !$OMP END PARALLEL DO @@ -238,14 +287,15 @@ subroutine momentum_adv_scalar(dynamics, partit, mesh) real(kind=WP) :: wu(1:mesh%nl), wv(1:mesh%nl) !___________________________________________________________________________ ! pointer on necessary derived types - real(kind=WP), dimension(:,:,:), pointer :: UV, UV_rhsAB, UVnode_rhs - real(kind=WP), dimension(:,:) , pointer :: Wvel_e + real(kind=WP), dimension(:,:,:), pointer :: UV, UVnode_rhs + real(kind=WP), dimension(:,:,:,:), pointer :: UV_rhsAB + real(kind=WP), dimension(:,:) , pointer :: Wvel_e #include "associate_part_def.h" #include "associate_mesh_def.h" #include "associate_part_ass.h" #include "associate_mesh_ass.h" UV =>dynamics%uv(:,:,:) - UV_rhsAB =>dynamics%uv_rhsAB(:,:,:) + UV_rhsAB =>dynamics%uv_rhsAB(:,:,:,:) UVnode_rhs=>dynamics%work%uvnode_rhs(:,:,:) Wvel_e =>dynamics%w_e(:,:) @@ -452,7 +502,7 @@ subroutine momentum_adv_scalar(dynamics, partit, mesh) do el=1, myDim_elem2D nl1 = nlevels(el)-1 ul1 = ulevels(el) - UV_rhsAB(1:2,ul1:nl1,el) = UV_rhsAB(1:2,ul1:nl1,el) & + UV_rhsAB(1,1:2,ul1:nl1,el) = UV_rhsAB(1,1:2,ul1:nl1,el) & + elem_area(el)*(UVnode_rhs(1:2,ul1:nl1,elem2D_nodes(1,el)) & + UVnode_rhs(1:2,ul1:nl1,elem2D_nodes(2,el)) & + UVnode_rhs(1:2,ul1:nl1,elem2D_nodes(3,el))) / 3.0_WP @@ -465,7 +515,7 @@ subroutine momentum_adv_scalar(dynamics, partit, mesh) do el=1, myDim_elem2D nl1 = nlevels(el)-1 ul1 = ulevels(el) - dynamics%ke_adv_AB(1:2,ul1:nl1,el) = dynamics%ke_adv_AB(1:2,ul1:nl1,el) & + dynamics%ke_adv_AB(1,1:2,ul1:nl1,el) = dynamics%ke_adv_AB(1,1:2,ul1:nl1,el) & + elem_area(el)*(UVnode_rhs(1:2,ul1:nl1,elem2D_nodes(1,el)) & + UVnode_rhs(1:2,ul1:nl1,elem2D_nodes(2,el)) & + UVnode_rhs(1:2,ul1:nl1,elem2D_nodes(3,el))) / 3.0_WP diff --git a/src/oce_setup_step.F90 b/src/oce_setup_step.F90 index e6ea48722..8a57e0960 100755 --- a/src/oce_setup_step.F90 +++ b/src/oce_setup_step.F90 @@ -101,7 +101,7 @@ subroutine ocean_setup(dynamics, tracers, partit, mesh) type(t_partit), intent(inout), target :: partit type(t_mesh) , intent(inout), target :: mesh !___________________________________________________________________________ - integer :: n + integer :: i, n !___setup virt_salt_flux____________________________________________________ ! if the ale thinkness remain unchanged (like in 'linfs' case) the vitrual @@ -234,7 +234,9 @@ subroutine ocean_setup(dynamics, tracers, partit, mesh) if (.not.r_restart) then do n=1, tracers%num_tracers - tracers%data(n)%valuesAB=tracers%data(n)%values + do i=1, tracers%data(n)%AB_order-1 + tracers%data(n)%valuesold(i,:,:)=tracers%data(n)%values + end do end do end if @@ -288,9 +290,10 @@ SUBROUTINE tracer_init(tracers, partit, mesh) integer :: num_tracers logical :: i_vert_diff, smooth_bh_tra real(kind=WP) :: gamma0_tra, gamma1_tra, gamma2_tra + integer :: AB_order namelist /tracer_listsize/ num_tracers namelist /tracer_list / nml_tracer_list - namelist /tracer_general / smooth_bh_tra, gamma0_tra, gamma1_tra, gamma2_tra, i_vert_diff + namelist /tracer_general / smooth_bh_tra, gamma0_tra, gamma1_tra, gamma2_tra, i_vert_diff, AB_order !___________________________________________________________________________ ! pointer on necessary derived types #include "associate_part_def.h" @@ -337,8 +340,10 @@ SUBROUTINE tracer_init(tracers, partit, mesh) ! Temperature (index=1), Salinity (index=2), etc. allocate(tracers%data(num_tracers)) do n=1, tracers%num_tracers - allocate(tracers%data(n)%values (nl-1,node_size)) - allocate(tracers%data(n)%valuesAB(nl-1,node_size)) + allocate(tracers%data(n)%values ( nl-1, node_size)) + allocate(tracers%data(n)%valuesAB ( nl-1, node_size)) + tracers%data(n)%AB_order = AB_order + allocate(tracers%data(n)%valuesold(tracers%data(n)%AB_order-1, nl-1, node_size)) tracers%data(n)%ID = nml_tracer_list(n)%id tracers%data(n)%tra_adv_hor = TRIM(nml_tracer_list(n)%adv_hor) tracers%data(n)%tra_adv_ver = TRIM(nml_tracer_list(n)%adv_ver) @@ -351,6 +356,7 @@ SUBROUTINE tracer_init(tracers, partit, mesh) tracers%data(n)%gamma2_tra = gamma2_tra tracers%data(n)%values = 0. tracers%data(n)%valuesAB = 0. + tracers%data(n)%valuesold = 0. tracers%data(n)%i_vert_diff = i_vert_diff end do allocate(tracers%work%del_ttf(nl-1,node_size)) @@ -391,11 +397,12 @@ SUBROUTINE dynamics_init(dynamics, partit, mesh) logical :: use_freeslip =.false. logical :: use_wsplit =.false. logical :: ldiag_KE =.false. + integer :: AB_order = 2 logical :: check_opt_visc=.true. real(kind=WP) :: wsplit_maxcfl namelist /dynamics_visc / opt_visc, check_opt_visc, visc_gamma0, visc_gamma1, visc_gamma2, & use_ivertvisc, visc_easybsreturn - namelist /dynamics_general/ momadv_opt, use_freeslip, use_wsplit, wsplit_maxcfl, ldiag_KE + namelist /dynamics_general/ momadv_opt, use_freeslip, use_wsplit, wsplit_maxcfl, ldiag_KE, AB_order !___________________________________________________________________________ ! pointer on necessary derived types #include "associate_part_def.h" @@ -431,6 +438,7 @@ SUBROUTINE dynamics_init(dynamics, partit, mesh) dynamics%use_wsplit = use_wsplit dynamics%wsplit_maxcfl = wsplit_maxcfl dynamics%ldiag_KE = ldiag_KE + dynamics%AB_order = AB_order !___________________________________________________________________________ ! define local vertice & elem array size elem_size=myDim_elem2D+eDim_elem2D @@ -440,7 +448,7 @@ SUBROUTINE dynamics_init(dynamics, partit, mesh) ! allocate/initialise horizontal velocity arrays in derived type allocate(dynamics%uv( 2, nl-1, elem_size)) allocate(dynamics%uv_rhs( 2, nl-1, elem_size)) - allocate(dynamics%uv_rhsAB( 2, nl-1, elem_size)) + allocate(dynamics%uv_rhsAB( dynamics%AB_order-1, 2, nl-1, elem_size)) allocate(dynamics%uvnode( 2, nl-1, node_size)) dynamics%uv = 0.0_WP dynamics%uv_rhs = 0.0_WP @@ -504,8 +512,8 @@ SUBROUTINE dynamics_init(dynamics, partit, mesh) allocate(dynamics%ke_umean (2, nl-1, elem_size)) allocate(dynamics%ke_u2mean (2, nl-1, elem_size)) allocate(dynamics%ke_du2 (2, nl-1, elem_size)) - allocate(dynamics%ke_adv_AB (2, nl-1, elem_size)) - allocate(dynamics%ke_cor_AB (2, nl-1, elem_size)) + allocate(dynamics%ke_adv_AB (dynamics%AB_order-1, 2, nl-1, elem_size)) + allocate(dynamics%ke_cor_AB (dynamics%AB_order-1, 2, nl-1, elem_size)) allocate(dynamics%ke_rhs_bak(2, nl-1, elem_size)) allocate(dynamics%ke_wrho (nl-1, node_size)) allocate(dynamics%ke_dW (nl-1, node_size)) diff --git a/src/oce_tracer_mod.F90 b/src/oce_tracer_mod.F90 index f374ca5d2..54636428a 100755 --- a/src/oce_tracer_mod.F90 +++ b/src/oce_tracer_mod.F90 @@ -24,6 +24,7 @@ SUBROUTINE init_tracers_AB(tr_num, tracers, partit, mesh) type(t_partit), intent(inout), target :: partit type(t_tracer), intent(inout), target :: tracers integer :: n,nz + !$OMP PARALLEL DO do n=1, partit%myDim_nod2D+partit%eDim_nod2D ! del_ttf will contain all advection / diffusion contributions for this tracer. Set it to 0 at the beginning! @@ -31,10 +32,30 @@ SUBROUTINE init_tracers_AB(tr_num, tracers, partit, mesh) tracers%work%del_ttf_advhoriz (:, n) = 0.0_WP tracers%work%del_ttf_advvert (:, n) = 0.0_WP ! AB interpolation - tracers%data(tr_num)%valuesAB(:, n) =-(0.5_WP+epsilon)*tracers%data(tr_num)%valuesAB(:, n)+(1.5_WP+epsilon)*tracers%data(tr_num)%values(:, n) + if (tracers%data(tr_num)%AB_order==2) then + tracers%data(tr_num)%valuesAB(:, n) =-(0.5_WP+epsilon)*tracers%data(tr_num)%valuesold(1, :, n)+(1.5_WP+epsilon)*tracers%data(tr_num)%values(:, n) + elseif (tracers%data(tr_num)%AB_order==3) then + tracers%data(tr_num)%valuesAB(:, n) =5.0_WP*tracers%data(tr_num)%valuesold(2, :, n)-16.0_WP*tracers%data(tr_num)%valuesold(1, :, n)+23.0_WP*tracers%data(tr_num)%values(:, n) + tracers%data(tr_num)%valuesAB(:, n) =tracers%data(tr_num)%valuesAB(:, n)/12.0_WP + end if end do !$OMP END PARALLEL DO + if (tracers%data(tr_num)%AB_order==2) then +!$OMP PARALLEL DO + do n=1, partit%myDim_nod2d+partit%eDim_nod2D + tracers%data(tr_num)%valuesold(1, :, n)=tracers%data(tr_num)%values(:, n) + end do +!$OMP END PARALLEL DO + elseif (tracers%data(tr_num)%AB_order==3) then +!$OMP PARALLEL DO + do n=1, partit%myDim_nod2d+partit%eDim_nod2D + tracers%data(tr_num)%valuesold(2, :, n)=tracers%data(tr_num)%valuesold(1, :, n) + tracers%data(tr_num)%valuesold(1, :, n)=tracers%data(tr_num)%values(:, n) + end do +!$OMP END PARALLEL DO + end if + if (flag_debug .and. partit%mype==0) print *, achar(27)//'[38m'//' --> call tracer_gradient_elements'//achar(27)//'[0m' call tracer_gradient_elements(tracers%data(tr_num)%valuesAB, partit, mesh) call exchange_elem_begin(tr_xy, partit) diff --git a/src/write_step_info.F90 b/src/write_step_info.F90 index 9b1087248..cae90ae33 100644 --- a/src/write_step_info.F90 +++ b/src/write_step_info.F90 @@ -268,7 +268,7 @@ subroutine check_blowup(istep, ice, dynamics, tracers, partit, mesh) USE MOD_PARTIT USE MOD_PARSUP USE MOD_MESH - use g_config, only: logfile_outfreq, which_ALE + use g_config, only: logfile_outfreq, which_ALE, toy_ocean, use_ice use o_PARAM use o_ARRAYS, only: water_flux, stress_surf, & heat_flux, Kv, Av @@ -344,14 +344,18 @@ subroutine check_blowup(istep, ice, dynamics, tracers, partit, mesh) write(*,*) write(*,*) 'wflux = ',water_flux(n) write(*,*) - write(*,*) 'u_wind = ',u_wind(n),', v_wind = ',v_wind(n) - write(*,*) - do nz=1,nod_in_elem2D_num(n) - write(*,*) 'stress_surf(1:2,',nz,') = ',stress_surf(:,nod_in_elem2D(nz,n)) - end do + if (.not. toy_ocean) then + write(*,*) 'u_wind = ',u_wind(n),', v_wind = ',v_wind(n) + write(*,*) + do nz=1,nod_in_elem2D_num(n) + write(*,*) 'stress_surf(1:2,',nz,') = ',stress_surf(:,nod_in_elem2D(nz,n)) + end do + end if + if (use_ice) then write(*,*) write(*,*) 'm_ice = ',m_ice(n),', m_ice_old = ',m_ice_old(n) write(*,*) 'a_ice = ',a_ice(n),', a_ice_old = ',a_ice_old(n) + end if write(*,*) write(*,*) 'Wvel(:, n) = ',Wvel(ulevels_nod2D(n):nlevels_nod2D(n),n) write(*,*) @@ -448,11 +452,13 @@ subroutine check_blowup(istep, ice, dynamics, tracers, partit, mesh) write(*,*) 'ssh_rhs = ',ssh_rhs(n) write(*,*) 'ssh_rhs_old = ',ssh_rhs_old(n) write(*,*) - write(*,*) 'm_ice = ',m_ice(n) - write(*,*) 'm_ice_old = ',m_ice_old(n) - write(*,*) 'm_snow = ',m_snow(n) - write(*,*) 'm_snow_old = ',m_snow_old(n) - write(*,*) + if (use_ice) then + write(*,*) 'm_ice = ',m_ice(n) + write(*,*) 'm_ice_old = ',m_ice_old(n) + write(*,*) 'm_snow = ',m_snow(n) + write(*,*) 'm_snow_old = ',m_snow_old(n) + write(*,*) + end if write(*,*) 'hnode = ',hnode(:,n) write(*,*) 'hnode_new = ',hnode_new(:,n) write(*,*)