Skip to content

Commit

Permalink
Added new option for surface restoration for T,S (for long-term
Browse files Browse the repository at this point in the history
large-sclae runs)
  • Loading branch information
josephzhang8 committed Sep 17, 2024
1 parent 8de1f3b commit 9503032
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 66 deletions.
11 changes: 11 additions & 0 deletions sample_inputs/param.nml
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,17 @@

step_nu_tr = 86400. !time step [sec] in all [MOD]_nu.nc (for inu_[MOD]=2)

!-----------------------------------------------------------------------
! Surface T,S restoration (for large-scale long-term runs). If invoked,
! the input is surface_restore.nc
!-----------------------------------------------------------------------
iref_ts = 0 !on/off
ref_ts_restore_depth = 50. !restoration depth [m]
ref_ts_tscale = 365. !restoration time scale [days]
ref_ts_h1 = 100. !ramp-down depth 1 [m] (to turn off restoration in shallows)
ref_ts_h2 = 60. !ramp-down depth 2 [m]; must <ref_ts_h1
ref_ts_dt = 30. !time step in surface_restore.nc [days]

!-----------------------------------------------------------------------
! Cut-off depth for cubic spline interpolation near bottom when computing horizontal gradients
! e.g. using hgrad_nodes() (radiation stress, and gradients of qnon and qhat in non-hydro model).
Expand Down
10 changes: 6 additions & 4 deletions src/Core/schism_glbl.F90
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,16 @@ module schism_glbl
&xlsc0,rearth_pole,rearth_eq,hvis_coef0,disch_coef(10),hw_depth,hw_ratio, &
&slr_rate,rho0,shw,gen_wsett,turbinj,turbinjds,alphaw,h1_bcc,h2_bcc,vclose_surf_frac, &
&hmin_airsea_ex,hmin_salt_ex,shapiro0,loadtide_coef,h_massconsv,rinflation_icm, &
&stemp_stc,stemp_dz(2)
&stemp_stc,stemp_dz(2),ref_ts_h1,ref_ts_h2,ref_ts_restore_depth,ref_ts_tscale, &
&ref_ts_dt
real(rkind),save,allocatable :: veg_vert_z(:),veg_vert_scale_cd(:),veg_vert_scale_N(:),veg_vert_scale_D(:)

! Misc. variables shared between routines
integer,save :: nz_r,ieqstate,kr_co, &
&ihconsv,isconsv,i_hmin_airsea_ex,i_hmin_salt_ex,ihdif,ntracers, &
&ihydraulics,irouse_test,iwbl_itmax,nettype,nfltype, &
&ntetype,nsatype,ntrtype1(natrm),nettype2,nnode_et,nfltype2,nnode_fl, &
&ntetype2,nsatype2,nnode_tr2(natrm),inu_tr(natrm), &
&ntetype2,nsatype2,nnode_tr2(natrm),inu_tr(natrm),iref_ts, &
&nvar_sta,nout_sta,ntip,nbfr,itr_met,if_source,mass_source,nsources,nsinks, &
&max_flreg,irange_tr(2,natrm),nea_wwm,mnei_wwm,ne_wwm,neg_wwm, &
&max_iadjust_mass_consv,nsteps_from_cold
Expand All @@ -126,7 +127,7 @@ module schism_glbl
&vis_coe1,vis_coe2,h_bcc1,velmin_btrack,h_tvd,rmaxvel1,rmaxvel2, &
&difnum_max_l2,wtime1,wtime2,cmiu0, &
&cpsi2,rpub,rmub,rnub,cpsi1,psimin,eps_min,tip_dp,veg_di0,veg_h0,veg_nv0, &
&veg_cd0,dtb_min_transport,bounds_lon(2)
&veg_cd0,dtb_min_transport,bounds_lon(2),time_ref_ts

! logical,save :: lm2d !2D or 3D model
logical,save :: lhas_quad=.false. !existence of quads
Expand Down Expand Up @@ -164,7 +165,7 @@ module schism_glbl
character(len= 4),save :: a_4
integer,save :: ncid_nu(natrm),ncid_tr3D(natrm),ncid_elev2D,ncid_uv3D,irec0_schout, &
&istack0_schout,ncid_source,ncid_schout(7),ncid_schout_2(7),nrec_schout,nstride_schout, &
&ncid_atmos
&ncid_atmos,ncid_ref_ts

! ADT for global-to-local linked-lists
type :: llist_type
Expand Down Expand Up @@ -494,6 +495,7 @@ module schism_glbl
logical,save :: lice_free_gb

real(4),save,dimension(:,:,:),allocatable :: trnd_nu1,trnd_nu2,trnd_nu
real(4),save,dimension(:,:),allocatable :: ref_ts1,ref_ts2,ref_ts
integer,save,allocatable :: iadv(:),iwater_type(:)

!weno>
Expand Down
62 changes: 58 additions & 4 deletions src/Hydro/misc_subs.F90
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,17 @@ subroutine other_hot_init(time)

real(rkind), intent(in) :: time

integer :: it_now,it,i,j,k,m,mm,ntr_l,ninv,nd,itmp,itmp1,itmp2,ntmp,istat,ip,icount,n1,n2,kl
integer :: it_now,it,i,j,k,m,mm,ntr_l,ninv,nd,itmp,itmp1,itmp2,ntmp, &
&istat,ip,icount,n1,n2,kl,nwild(2)
real :: floatout
real(rkind) :: tmp,wx1,wx2,wy1,wy2,wtratio,ttt,dep,eqstate
character(len=48) :: inputfile
real(rkind), allocatable :: swild(:)
real(4), allocatable :: swild9(:,:) !used in tracer nudging
real(4), allocatable :: rwild(:,:) !used in nws=4

allocate(swild9(nvrt,mnu_pts),swild(nsa+nvrt+12+ntracers),stat=istat)
if(istat/=0) call parallel_abort('MISC: swild9')
allocate(swild(nsa+nvrt+12+ntracers),stat=istat)
if(istat/=0) call parallel_abort('MISC: swild')
if(nws==4) then
allocate(rwild(7,np_global),stat=istat)
if(istat/=0) call parallel_abort('MISC: failed to alloc. (71)')
Expand Down Expand Up @@ -419,6 +420,9 @@ subroutine other_hot_init(time)
#endif

!... Nudging
allocate(swild9(nvrt,mnu_pts),stat=istat)
if(istat/=0) call parallel_abort('MISC: swild9')

!Shared variables for inu_tr=2 (not used if none of inu_tr=2)
ntmp=time/step_nu_tr+1
time_nu_tr=real(ntmp,rkind)*step_nu_tr !points to next time pt
Expand Down Expand Up @@ -477,6 +481,56 @@ subroutine other_hot_init(time)
enddo !m
endif !inu_tr(k)
enddo !k
deallocate(swild9)

!... Surface TS restore
if(iref_ts/=0) then
allocate(swild9(np_global,1),stat=istat)
if(istat/=0) call parallel_abort('MISC: swild9(2)')

!Shared variables
ntmp=time/ref_ts_dt/86400.d0+1 !next time record
time_ref_ts=real(ntmp,rkind)*ref_ts_dt*86400.d0 ![sec]; points to next time pt
ref_ts1=-9999.; ref_ts2=-9999. !init

if(myrank==0) then
j=nf90_inq_varid(ncid_ref_ts, "reference_sst",nwild(1))
if(j/=NF90_NOERR) call parallel_abort('MISC: ref SST')
j=nf90_inq_varid(ncid_ref_ts, "reference_sss",nwild(2))
if(j/=NF90_NOERR) call parallel_abort('MISC: ref SSS')
endif

do m=1,2 !T,S
swild9=-9999.
if(myrank==0) then
j=nf90_get_var(ncid_ref_ts,nwild(m),swild9(1:np_global,1), &
&(/1,ntmp/),(/np_global,1/))
if(j/=NF90_NOERR) call parallel_abort('MISC: surface relax (2)')
endif !myrank
call mpi_bcast(swild9,np_global,mpi_real,0,comm,istat)
do i=1,np_global
if(ipgl(i)%rank==myrank) then
ip=ipgl(i)%id
ref_ts1(ip,m)=swild9(i,1)
endif
enddo !i

swild9=-9999.
if(myrank==0) then
j=nf90_get_var(ncid_ref_ts,nwild(m),swild9(1:np_global,1), &
&(/1,ntmp+1/),(/np_global,1/))
if(j/=NF90_NOERR) call parallel_abort('MISC: surface relax(2.2)')
endif !myrank
call mpi_bcast(swild9,np_global,mpi_real,0,comm,istat)
do i=1,np_global
if(ipgl(i)%rank==myrank) then
ip=ipgl(i)%id
ref_ts2(ip,m)=swild9(i,1)
endif
enddo !i
enddo !m: T,S
deallocate(swild9)
endif !iref_ts/=0

! The following to init th_dt*, th_time* and ath* is only done by
! rank 0, not bcast'ed, b/c in _step we'll continue the reading
Expand Down Expand Up @@ -909,7 +963,7 @@ subroutine other_hot_init(time)


if(allocated(rwild)) deallocate(rwild)
deallocate(swild,swild9)
deallocate(swild)

end subroutine other_hot_init

Expand Down
30 changes: 29 additions & 1 deletion src/Hydro/schism_init.F90
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ subroutine schism_init(iorder,indir,iths,ntime)
&ibcc_mean,flag_ic,start_year,start_month,start_day,start_hour,utc_start, &
&itr_met,h_tvd,eps1_tvd_imp,eps2_tvd_imp,ip_weno, &
&courant_weno,ntd_weno,nquad,epsilon1,i_epsilon2,epsilon2,epsilon3,ielad_weno,small_elad, &
&i_prtnftl_weno,inu_tr,step_nu_tr,vnh1,vnh2,vnf1,vnf2, &
&i_prtnftl_weno,inu_tr,step_nu_tr,vnh1,vnh2,vnf1,vnf2,iref_ts, &
&ref_ts_h1,ref_ts_h2,ref_ts_restore_depth,ref_ts_tscale,ref_ts_dt, &
&moitn0,mxitn0,rtol0,iflux,inter_mom,h_bcc1,inu_elev,inu_uv, &
&ihhat,kr_co,rmaxvel,velmin_btrack,btrack_nudge,ibtrack_test,irouse_test, &
&inunfl,shorewafo,ic_elev,nramp_elev,inv_atm_bnd,prmsl_ref,s1_mxnbt,s2_mxnbt, &
Expand Down Expand Up @@ -471,6 +472,8 @@ subroutine schism_init(iorder,indir,iths,ntime)
courant_weno=0.5_rkind; ntd_weno=1; nquad=2; epsilon1=1.d-15; i_epsilon2=1; epsilon2=1.d-10; epsilon3=1.d-25;
ielad_weno=0; small_elad=1.d-4; i_prtnftl_weno=0;
inu_tr(:)=0; step_nu_tr=86400._rkind; vnh1=400._rkind; vnh2=500._rkind; vnf1=0._rkind; vnf2=0._rkind;
iref_ts=0; ref_ts_h1=100.d0; ref_ts_h2=60.d0; ref_ts_restore_depth=50.d0
ref_ts_tscale=365.d0; ref_ts_dt=30.d0
moitn0=50; mxitn0=1500; rtol0=1.d-12; iflux=0; inter_mom=0;
h_bcc1=100._rkind; inu_elev=0; inu_uv=0;
ihhat=1; kr_co=1; rmaxvel=5._rkind; velmin_btrack=1.d-4; btrack_nudge=9.013d-3;
Expand Down Expand Up @@ -938,6 +941,20 @@ subroutine schism_init(iorder,indir,iths,ntime)
call parallel_abort(errmsg)
endif

!... Surface T,S relax for long-term simulations
if(iref_ts/=0.and.iref_ts/=1) then
write(errmsg,*)'Wrong iref_ts:',iref_ts
call parallel_abort(errmsg)
endif
if(iref_ts/=0.and.isconsv==0) then
write(errmsg,*)'Surface relax requires air-sea ex:',iref_ts,isconsv
call parallel_abort(errmsg)
endif

if(ref_ts_h1<=ref_ts_h2.or.ref_ts_restore_depth<=0.d0.or.ref_ts_tscale<=0.d0.or.ref_ts_dt<=0.d0) then
write(errmsg,*)'Wrong surface relax:',ref_ts_h1,ref_ts_h2,ref_ts_restore_depth,ref_ts_tscale,ref_ts_dt
call parallel_abort(errmsg)
endif

!... input information about hot start output
if(nhot/=0.and.nhot/=1.or.nhot*mod(nhot_write,ihfskip)/=0) then
Expand Down Expand Up @@ -1417,6 +1434,11 @@ subroutine schism_init(iorder,indir,iths,ntime)
endif
if(istat/=0) call parallel_abort('INIT: alloc sdbt failure')

if(iref_ts/=0) then
allocate(ref_ts1(npa,2),ref_ts2(npa,2),ref_ts(npa,2),stat=itmp)
if(itmp/=0) call parallel_abort('INIT: alloc failed (57)')
endif

! Offline transport
if(itransport_only/=0) then
allocate(ts_offline(4,nvrt,nea),stat=istat)
Expand Down Expand Up @@ -3755,6 +3777,12 @@ subroutine schism_init(iorder,indir,iths,ntime)
endif
enddo !k

! Surface T,S restoration: open nc handle
if(iref_ts/=0.and.myrank==0) then
j=nf90_open(in_dir(1:len_in_dir)//'surface_restore.nc',OR(NF90_NETCDF4,NF90_NOWRITE),ncid_ref_ts)
if(j/=NF90_NOERR) call parallel_abort('init: surface_restore.nc not found')
endif !iref_ts

! Vegetation inputs: veg_*.gr3
veg_alpha0=0.d0 !=D*Nv*Cdv/2; init; D is diameter or leaf width; Cdv is form drag (veg_cd)
veg_h=0.d0 !veg height; not used at 2D sides
Expand Down
84 changes: 72 additions & 12 deletions src/Hydro/schism_step.F90
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,6 @@ subroutine schism_step(it)
&dr_dxy(2,nvrt,nea),bcc(2,nvrt,nsa),stat=istat)
if(istat/=0) call parallel_abort('STEP: other allocation failure')

allocate(swild9(nvrt,mnu_pts),stat=istat)
if(istat/=0) call parallel_abort('STEP: alloc failure (3)')

! Source
if(if_source/=0) then
allocate(msource(ntracers,nea),stat=istat)
Expand Down Expand Up @@ -1049,6 +1046,9 @@ subroutine schism_step(it)
if(myrank==0) write(16,*)'done adjusting wind stress ...'

!... Read in tracer nudging
allocate(swild9(nvrt,mnu_pts),stat=istat)
if(istat/=0) call parallel_abort('STEP: alloc failure (3)')

if(time>time_nu_tr) then
icount3=time/step_nu_tr+2 !time record #
do k=1,natrm
Expand Down Expand Up @@ -1123,6 +1123,54 @@ subroutine schism_step(it)
!$OMP end parallel workshare
endif !inu_tr(k)
enddo !k
deallocate(swild9)

!... Read in surface relax
if(iref_ts/=0) then
allocate(swild9(np_global,1),stat=istat)
if(istat/=0) call parallel_abort('STEP: alloc failure (3.0)')
if(time>time_ref_ts) then
icount3=time/ref_ts_dt/86400.d0+2 !next time record #
ref_ts1=ref_ts2
if(myrank==0) then
j=nf90_inq_varid(ncid_ref_ts,"reference_sst",nwild(1))
if(j/=NF90_NOERR) call parallel_abort('STEP: surf relax (1)')
j=nf90_inq_varid(ncid_ref_ts,"reference_sss",nwild(2))
if(j/=NF90_NOERR) call parallel_abort('STEP: surf relax (2)')
endif

do k=1,2 !T,S
swild9=-9999.
if(myrank==0) then
j=nf90_get_var(ncid_ref_ts,nwild(k),swild9(1:np_global,1), &
&(/1,icount3/),(/np_global,1/))
if(j/=NF90_NOERR) call parallel_abort('STEP: surf relax(2.1)')
endif !myrank
call mpi_bcast(swild9,np_global,mpi_real,0,comm,istat)
do i=1,np_global
if(ipgl(i)%rank==myrank) then
ip=ipgl(i)%id
ref_ts2(ip,k)=swild9(i,1)
!Debug
!write(12,*)'Step nu:',i,nd,swild9(i,1)
endif
enddo !i
enddo !k
time_ref_ts=time_ref_ts+ref_ts_dt*86400.d0 ![sec]; shared among all tracers
endif !time>time_nu_tr

! Compute tracer
rat=(time_ref_ts-time)/ref_ts_dt/86400.d0
if(rat<0.d0.or.rat>1.d0) then
write(errmsg,*)'Impossible 82.2:',rat
call parallel_abort(errmsg)
endif
!$OMP parallel workshare default(shared)
!may be junk (check later)
ref_ts=rat*ref_ts1+(1.d0-rat)*ref_ts2
!$OMP end parallel workshare
deallocate(swild9)
endif !iref_ts/=0

!... Compute hydraulic transfer blocks together with reading in flux values
!... in case the blocks are taken out
Expand Down Expand Up @@ -7375,7 +7423,7 @@ subroutine schism_step(it)
!... Initialize S,T as flags
! tr_nd(1:2,:,:)=-99 !flags

!$OMP parallel default(shared) private(i,evap,precip,sflux_e,itmp,rr,d_1,d_2,k,dp1,dp2,l,srad1,srad2,j)
!$OMP parallel default(shared) private(i,evap,precip,sflux_e,itmp,rr,d_1,d_2,k,dp1,dp2,l,srad1,srad2,j,tmp,tmp2)

!$OMP workshare
bdy_frc=0.d0; flx_sf=0.d0; flx_bt=0.d0
Expand All @@ -7393,15 +7441,19 @@ subroutine schism_step(it)
if(ze(nvrt,i)-ze(kbe(i),i)<hmin_salt_ex) cycle
endif

!#ifdef IMPOSE_NET_FLUX
! precip=sum(fluxprc(elnode(1:i34(i),i)))/real(i34(i),rkind) !P-E
! flx_sf(2,i)=tr_el(2,nvrt,i)*(-precip)/rho0
!#else
evap=sum(fluxevp(elnode(1:i34(i),i)))/real(i34(i),rkind)
precip=sum(fluxprc(elnode(1:i34(i),i)))/real(i34(i),rkind)
flx_sf(2,i)=tr_el(2,nvrt,i)*(evap-precip)/rho0
! endif !impose_net_flux
!#endif

!Virtual flux (surface restoration)
if(iref_ts/=0) then
tmp=sum(ref_ts(elnode(1:i34(i),i),2))/real(i34(i),rkind)
if(tmp>0.d0) then
tmp2=max(0.d0,min(1.d0,(dpe(i)-ref_ts_h2)/(ref_ts_h1-ref_ts_h2)))
flx_sf(2,i)=flx_sf(2,i)+ref_ts_restore_depth/ref_ts_tscale/86400.d0*tmp2* &
&(tmp-tr_el(2,nvrt,i))
endif !tmp>
endif !iref_ts/
enddo !i
!$OMP end do
endif !isconsv/=0
Expand All @@ -7423,6 +7475,16 @@ subroutine schism_step(it)
sflux_e=sum(sflux(elnode(1:i34(i),i)))/real(i34(i),rkind)
flx_sf(1,i)=sflux_e/rho0/shw

!Virtual flux (surface restoration)
if(iref_ts/=0) then
tmp=sum(ref_ts(elnode(1:i34(i),i),1))/real(i34(i),rkind)
if(tmp>-99.d0) then
tmp2=max(0.d0,min(1.d0,(dpe(i)-ref_ts_h2)/(ref_ts_h1-ref_ts_h2)))
flx_sf(1,i)=flx_sf(1,i)+ref_ts_restore_depth/ref_ts_tscale/86400.d0*tmp2* &
&(tmp-tr_el(1,nvrt,i))
endif !tmp>
endif !iref_ts/

! Solar
! Calculate water type
! solar flux= R*exp(z/d_1))+(1-R)*exp(z/d_2) (d_[1,2] are attentuation depths; smaller values for muddier water)
Expand Down Expand Up @@ -10609,8 +10671,6 @@ subroutine schism_step(it)
deallocate(hp_int,uth,vth,d2uv,dr_dxy,bcc)
if(allocated(rwild)) deallocate(rwild)
if(allocated(rwild6)) deallocate(rwild6)
deallocate(swild9)
!if(allocated(ts_offline)) deallocate(ts_offline)

#ifdef USE_NAPZD
deallocate(Bio_bdefp)
Expand Down
1 change: 1 addition & 0 deletions src/Readme.beta_notes
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This beta notes are divided into 5 part:

Github versions:

- `` : added surfac T,S restoration (for large-scale long-term runs); related parameters are iref_ts,ref_ts_h1,ref_ts_h2,ref_ts_restore_depth,ref_ts_tscale,ref_ts_dt, and the input is surface_restore.nc;
- `ab71be44` (26 Aug 2024): ptrack4 added biofouling option; new parameter ibiofoul and related values;
- `2f88fc5` (7 Aug 2024): changed horizontal diffusion method to filter; added an optional
parameter niter_hdif, and hdif.gr3 now specifies the filter strength (<=0.2);
Expand Down
Loading

0 comments on commit 9503032

Please sign in to comment.