ROMS
Loading...
Searching...
No Matches
set_weights.F
Go to the documentation of this file.
1#include "cppdefs.h"
2#ifdef SOLVE3D
3 SUBROUTINE set_weights (ng)
4!
5!git $Id$
6!=======================================================================
7! Copyright (c) 2002-2025 The ROMS Group !
8! Licensed under a MIT/X style license !
9! See License_ROMS.md Hernan G. Arango !
10!========================================== Alexander F. Shchepetkin ===
11! !
12! This routine sets the weigth functions for the time averaging of !
13! 2D fields over all short time-steps. !
14! !
15!=======================================================================
16!
17 USE mod_param
18 USE mod_parallel
19 USE mod_iounits
20 USE mod_scalars
21!
22 implicit none
23!
24! Imported variable declarations.
25!
26 integer, intent(in) :: ng
27!
28! Local variable declarations.
29!
30 integer :: i, j, iter
31
32# ifdef POWER_LAW
33 real(dp) :: gamma, scale
34# elif defined COSINE2
35 real(dp) :: arg
36# endif
37 real(dp) :: cff1, cff2
38
39 real(r16) :: wsum, shift, cff
40!
41!=======================================================================
42! Compute time-averaging filter for barotropic fields.
43!=======================================================================
44!
45! Initialize both sets of weights to zero.
46!
47 nfast(ng)=0
48 DO i=1,2*ndtfast(ng)
49 weight(1,i,ng)=0.0_dp
50 weight(2,i,ng)=0.0_dp
51 END DO
52
53# ifdef POWER_LAW
54!
55!-----------------------------------------------------------------------
56! Power-law shape filters.
57!-----------------------------------------------------------------------
58!
59! The power-law shape filters are given by:
60!
61! F(xi)=xi^Falpha*(1-xi^Fbeta)-Fgamma*xi
62!
63! where xi=scale*i/ndtfast; and scale, Falpha, Fbeta, Fgamma, and
64! normalization are chosen to yield the correct zeroth-order
65! (normalization), first-order (consistency), and second-order moments,
66! resulting in overall second-order temporal accuracy for time-averaged
67! barotropic motions resolved by baroclinic time step. There parameters
68! are set in "mod_scalars".
69!
70 scale=(falpha+1.0_dp)*(falpha+fbeta+1.0_dp)/ &
71 & ((falpha+2.0_dp)*(falpha+fbeta+2.0_dp)*real(ndtfast(ng),dp))
72!
73! Find center of gravity of the primary weighting shape function and
74! iteratively adjust "scale" to place the centroid exactly at
75! "ndtfast".
76!
77 gamma=fgamma*max(0.0_dp, 1.0_dp-10.0_dp/real(ndtfast(ng),dp))
78 DO iter=1,16
79 nfast(ng)=0
80 DO i=1,2*ndtfast(ng)
81 cff=scale*real(i,dp)
82 weight(1,i,ng)=cff**falpha-cff**(falpha+fbeta)-gamma*cff
83 IF (weight(1,i,ng).gt.0.0_dp) nfast(ng)=i
84 IF ((nfast(ng).gt.0).and.(weight(1,i,ng).lt.0.0_dp)) THEN
85 weight(1,i,ng)=0.0_dp
86 END IF
87 END DO
88 wsum=0.0_r16
89 shift=0.0_r16
90 DO i=1,nfast(ng)
91 wsum=wsum+weight(1,i,ng)
92 shift=shift+weight(1,i,ng)*real(i,dp)
93 END DO
94 scale=scale*shift/(wsum*real(ndtfast(ng),dp))
95 END DO
96
97# elif defined COSINE2
98!
99!-----------------------------------------------------------------------
100! Cosine-squared shaped filter.
101!-----------------------------------------------------------------------
102!
103 cff=pi/real(ndtfast(ng),dp)
104 DO i=1,2*ndtfast(ng)
105 arg=cff*float(i-ndtfast(ng))
106 IF ((2.0_dp*abs(arg)).lt.pi) THEN
107!! weight(1,i,ng)=1.0_dp ! flat
108!! weight(1,i,ng)=(COS(arg))**2
109 weight(1,i,ng)=0.0882_dp+(cos(arg))**2 ! hamming window
110 nfast(ng)=i
111 END IF
112 END DO
113# endif
114!
115!-----------------------------------------------------------------------
116! Post-processing of primary weights.
117!-----------------------------------------------------------------------
118!
119! Although it is assumed that the initial settings of the primary
120! weights has its center of gravity "reasonably close" to NDTFAST,
121! it may be not so according to the discrete rules of integration.
122! The following procedure is designed to put the center of gravity
123! exactly to NDTFAST by computing mismatch (NDTFAST-shift) and
124! applying basically an upstream advection of weights to eliminate
125! the mismatch iteratively. Once this procedure is complete primary
126! weights are normalized.
127!
128! Find center of gravity of the primary weights and subsequently
129! calculate the mismatch to be compensated.
130!
131 DO iter=1,ndtfast(ng)
132 wsum=0.0_r16
133 shift=0.0_r16
134 DO i=1,nfast(ng)
135 wsum=wsum+weight(1,i,ng)
136 shift=shift+real(i,dp)*weight(1,i,ng)
137 END DO
138 shift=shift/wsum
139 cff=real(ndtfast(ng),dp)-shift
140!
141! Apply advection step using either whole, or fractional shifts.
142! Notice that none of the four loops here is reversible.
143!
144 IF (cff.gt.1.0_r16) THEN
145 nfast(ng)=nfast(ng)+1
146 DO i=nfast(ng),2,-1
147 weight(1,i,ng)=weight(1,i-1,ng)
148 END DO
149 weight(1,1,ng)=0.0_dp
150 ELSE IF (cff.gt.0.0_r16) THEN
151 wsum=1.0_r16-cff
152 DO i=nfast(ng),2,-1
153 weight(1,i,ng)=wsum*weight(1,i,ng)+cff*weight(1,i-1,ng)
154 END DO
155 weight(1,1,ng)=wsum*weight(1,1,ng)
156 ELSE IF (cff.lt.-1.0_r16) THEN
157 nfast(ng)=nfast(ng)-1
158 DO i=1,nfast(ng),+1
159 weight(1,i,ng)=weight(1,i+1,ng)
160 END DO
161 weight(1,nfast(ng)+1,ng)=0.0_dp
162 ELSE IF (cff.lt.0.0_r16) THEN
163 wsum=1.0_r16+cff
164 DO i=1,nfast(ng)-1,+1
165 weight(1,i,ng)=wsum*weight(1,i,ng)-cff*weight(1,i+1,ng)
166 END DO
167 weight(1,nfast(ng),ng)=wsum*weight(1,nfast(ng),ng)
168 END IF
169 END DO
170!
171! Set SECONDARY weights assuming that backward Euler time step is used
172! for free surface. Notice that array weight(2,i,ng) is assumed to
173! have all-zero status at entry in this segment of code.
174!
175 DO j=1,nfast(ng)
176 cff=weight(1,j,ng)
177 DO i=1,j
178 weight(2,i,ng)=weight(2,i,ng)+cff
179 END DO
180 END DO
181!
182! Normalize both set of weights.
183!
184 wsum=0.0_r16
185 cff=0.0_r16
186 DO i=1,nfast(ng)
187 wsum=wsum+weight(1,i,ng)
188 cff=cff+weight(2,i,ng)
189 END DO
190 wsum=1.0_r16/wsum
191 cff=1.0_r16/cff
192 DO i=1,nfast(ng)
193 weight(1,i,ng)=wsum*weight(1,i,ng)
194 weight(2,i,ng)=cff*weight(2,i,ng)
195 END DO
196!
197! Report weights.
198!
199 IF (master.and.lwrtinfo(ng)) THEN
200 WRITE (stdout,10) ng, ndtfast(ng), nfast(ng)
201 cff=0.0_r16
202 cff1=0.0_dp
203 cff2=0.0_dp
204 wsum=0.0_r16
205 shift=0.0_r16
206 DO i=1,nfast(ng)
207 cff=cff+weight(1,i,ng)
208 cff1=cff1+weight(1,i,ng)*real(i,dp)
209 cff2=cff2+weight(1,i,ng)*real(i*i,dp)
210 wsum=wsum+weight(2,i,ng)
211 shift=shift+weight(2,i,ng)*(real(i,dp)-0.5_dp)
212 WRITE (stdout,20) i, weight(1,i,ng), weight(2,i,ng), cff, wsum
213 END DO
214 cff1=cff1/real(ndtfast(ng),dp)
215 cff2=cff2/(real(ndtfast(ng),dp)*real(ndtfast(ng),dp))
216 shift=shift/real(ndtfast(ng),dp)
217 WRITE (stdout,30) ndtfast(ng), nfast(ng), &
218 & real(nfast(ng),dp)/real(ndtfast(ng),dp)
219# ifdef POWER_LAW
220 WRITE (stdout,40) cff1, cff2, shift, cff, wsum, fgamma, gamma
221 IF (cff2.lt.1.0001_dp) WRITE (stdout,50)
222# endif
223 END IF
224!
225 10 FORMAT (/,' Time Splitting Weights for Grid ',i2.2, &
226 & ':',4x,'ndtfast = ',i3,4x,'nfast = ',i3,/, &
227 & ' ==================================',/, &
228 & /,4x,'Primary',12x,'Secondary',12x, &
229 & 'Accumulated to Current Step',/)
230 20 FORMAT (i3,4f19.16)
231 30 FORMAT (/,1x,'ndtfast, nfast = ',2i4,3x,'nfast/ndtfast = ',f8.5)
232# ifdef POWER_LAW
233 40 FORMAT (/,1x,'Centers of gravity and integrals ', &
234 & '(values must be 1, 1, approx 1/2, 1, 1):',/, &
235 & /,3x,5f15.12,/,/,1x,'Power filter parameters, ', &
236 & 'Fgamma, gamma = ', f8.5,2x,f8.5)
237 50 FORMAT (/,' WARNING: unstable weights, reduce parameter', &
238 & ' Fgamma in mod_scalars.F',/)
239# endif
240#else
241 SUBROUTINE set_weights
242#endif
243 RETURN
244 END SUBROUTINE set_weights
integer stdout
logical master
real(dp) fbeta
real(dp) falpha
real(dp), dimension(:,:,:), allocatable weight
integer, dimension(:), allocatable nfast
integer, dimension(:), allocatable ndtfast
logical, dimension(:), allocatable lwrtinfo
real(dp) fgamma
real(dp), parameter pi
subroutine set_weights(ng)
Definition set_weights.F:4