Line data Source code
1 : #if defined( UNICOSMP ) || defined ( NEC_SX )
2 : #define VECTORIZE
3 : #endif
4 : module tp_core
5 : !BOP
6 : !
7 : ! !MODULE: tp_core --- Utilities for the transport core
8 : !
9 : ! !USES:
10 : use shr_kind_mod, only : r8 => shr_kind_r8
11 :
12 : !
13 : ! !PUBLIC MEMBER FUNCTIONS:
14 : public tp2c, tp2d, xtp, xtpv, fxppm, xmist, steepx, lmppm
15 : public huynh, ytp, ymist, fyppm, tpcc, ycc
16 : !
17 : ! !DESCRIPTION:
18 : !
19 : ! This module provides
20 : !
21 : ! \begin{tabular}{|l|l|} \hline \hline
22 : ! tp2c & \\ \hline
23 : ! tp2d & \\ \hline
24 : ! xtp & \\ \hline
25 : ! fxppm & \\ \hline
26 : ! xmist & \\ \hline
27 : ! steepx & \\ \hline
28 : ! lmppm & \\ \hline
29 : ! huynh & \\ \hline
30 : ! ytp & \\ \hline
31 : ! ymist & \\ \hline
32 : ! fyppm & \\ \hline
33 : ! tpcc & \\ \hline
34 : ! ycc & \\ \hline
35 : ! \hline
36 : ! \end{tabular}
37 : !
38 : ! !REVISION HISTORY:
39 : ! 01.01.15 Lin Routines coalesced into this module
40 : ! 01.03.26 Sawyer Additional ProTeX documentation
41 : ! 03.11.19 Sawyer Merged in CAM changes by Mirin
42 : ! 04.10.07 Sawyer ompinner now from dynamics_vars
43 : ! 05.03.25 Todling shr_kind_r8 can only be referenced once (MIPSpro-7.4.2)
44 : ! 05.05.25 Sawyer Merged CAM and GEOS5 versions (mostly CAM)
45 : ! 06.09.06 Sawyer Turned "magic numbers" into F90 parameters
46 : !
47 : !EOP
48 : !-----------------------------------------------------------------------
49 :
50 : ! Magic numbers used in this module
51 :
52 : private
53 : real(r8), parameter :: D0_0 = 0.0_r8
54 : real(r8), parameter :: D0_05 = 0.05_r8
55 : real(r8), parameter :: D0_25 = 0.25_r8
56 : real(r8), parameter :: D0_5 = 0.5_r8
57 : real(r8), parameter :: D1_0 = 1.0_r8
58 : real(r8), parameter :: D2_0 = 2.0_r8
59 : real(r8), parameter :: D3_0 = 3.0_r8
60 : real(r8), parameter :: D4_0 = 4.0_r8
61 : real(r8), parameter :: D8_0 = 8.0_r8
62 : real(r8), parameter :: D12_0 = 12.0_r8
63 : real(r8), parameter :: D24_0 = 24.0_r8
64 :
65 : CONTAINS
66 :
67 : !-----------------------------------------------------------------------
68 : !BOP
69 : ! !IROUTINE: tp2c --- Perform transport on a C grid
70 : !
71 : ! !INTERFACE:
72 42663936 : subroutine tp2c(dh, va, h, crx, cry, im, jm, &
73 42663936 : iord, jord, ng, fx, fy, ffsl, &
74 42663936 : rcap, acosp, xfx, yfx, cosp, id, jfirst, jlast)
75 : !-----------------------------------------------------------------------
76 :
77 : implicit none
78 :
79 : ! !INPUT PARAMETERS:
80 : integer im, jm ! Dimensions
81 : integer jfirst, jlast ! Latitude strip
82 : integer iord, jord ! Interpolation order in x,y
83 : integer ng ! Max. NS dependencies
84 : integer id ! density (0) (mfx = C)
85 : real (r8) rcap ! Ask S.-J. (polar constant?)
86 : real (r8) acosp(jm) ! Ask S.-J. (difference to cosp??)
87 : logical ffsl(jm) ! Use flux-form semi-Lagrangian trans.?
88 : ! (N*NG S*NG)
89 : real (r8) cosp(jm) ! Critical angle
90 : real (r8) va(im,jfirst:jlast) ! Courant (unghosted)
91 : real (r8) h(im,jfirst-ng:jlast+ng) ! Pressure ( N*NG S*NG )
92 : real (r8) crx(im,jfirst-ng:jlast+ng) ! Ask S.-J. ( N*NG S*NG )
93 : real (r8) cry(im,jfirst:jlast+1) ! Ask S.-J. ( N like FY )
94 : real (r8) xfx(im,jfirst:jlast) ! Ask S.-J. ( unghosted like FX )
95 : real (r8) yfx(im,jfirst:jlast+1) ! Ask S.-J. ( N like FY )
96 :
97 : ! !OUTPUT PARAMETERS:
98 : real (r8) dh(im,jfirst:jlast) ! Ask S.-J. ( unghosted )
99 : real (r8) fx(im,jfirst:jlast) ! Flux in x ( unghosted )
100 : real (r8) fy(im,jfirst:jlast+1) ! Flux in y ( N, see tp2c )
101 :
102 : ! !DESCRIPTION:
103 : ! Perform transport on a C grid. The number of ghost
104 : ! latitudes (NG) depends on what method (JORD) will be used
105 : ! subsequentally. NG is equal to MIN(ABS(JORD),3).
106 : ! Ask S.-J. how exactly this differs from TP2C.
107 : !
108 : ! !REVISION HISTORY:
109 : !
110 : !EOP
111 : !-----------------------------------------------------------------------
112 : !BOC
113 : integer i, j, js2g0, jn2g0
114 : real (r8) sum1
115 :
116 42663936 : js2g0 = max(2,jfirst) ! No ghosting
117 42663936 : jn2g0 = min(jm-1,jlast) ! No ghosting
118 :
119 : call tp2d(va, h, crx, cry, im, jm, iord, jord, ng,fx, fy, ffsl, &
120 42663936 : xfx, yfx, cosp, id, jfirst, jlast)
121 :
122 169322496 : do j=js2g0,jn2g0
123 36477665280 : do i=1,im-1
124 36477665280 : dh(i,j) = fx(i,j) - fx(i+1,j) + (fy(i,j)-fy(i,j+1))*acosp(j)
125 : enddo
126 169322496 : dh(im,j) = fx(im,j) - fx(1,j) + (fy(im,j)-fy(im,j+1))*acosp(j)
127 : enddo
128 :
129 : ! Poles
130 42663936 : if ( jfirst == 1 ) then
131 : ! sum1 = - SUM( fy(1:im, 2) ) * rcap
132 666624 : sum1 = D0_0
133 192654336 : do i=1,im
134 192654336 : sum1 = sum1 + fy(i,2)
135 : enddo
136 666624 : sum1 = -sum1*rcap
137 192654336 : do i=1,im
138 192654336 : dh(i, 1) = sum1
139 : enddo
140 : endif
141 :
142 42663936 : if ( jlast == jm ) then
143 : ! sum1 = SUM( fy(1:im,jm) ) * rcap
144 666624 : sum1 = D0_0
145 192654336 : do i=1,im
146 192654336 : sum1 = sum1 + fy(i,jm)
147 : enddo
148 666624 : sum1 = sum1*rcap
149 192654336 : do i=1,im
150 192654336 : dh(i,jm) = sum1
151 : enddo
152 : endif
153 42663936 : return
154 : !EOC
155 : end subroutine tp2c
156 : !-----------------------------------------------------------------------
157 :
158 : !-----------------------------------------------------------------------
159 : !BOP
160 : ! !IROUTINE: tp2d --- Perform transport on a D grid
161 : !
162 : ! !INTERFACE:
163 43008000 : subroutine tp2d(va, q, crx, cry, im, jm, iord, jord, ng, fx, fy, &
164 43008000 : ffsl, xfx, yfx, cosp, id, jfirst, jlast)
165 : !-----------------------------------------------------------------------
166 : ! !USES:
167 :
168 : implicit none
169 :
170 : ! !INPUT PARAMETERS:
171 : integer im, jm ! Dimensions
172 : integer jfirst, jlast ! Latitude strip
173 : integer iord, jord ! Interpolation order in x,y
174 : integer ng ! Max. NS dependencies
175 : integer id ! density (0) (mfx = C)
176 : ! mixing ratio (1) (mfx = mass flux)
177 : logical ffsl(jm) ! Use flux-form semi-Lagrangian trans.?
178 : ! ghosted N*ng S*ng
179 : real (r8) cosp(jm) ! Critical angle
180 : real (r8) va(im,jfirst:jlast) ! Courant (unghosted)
181 : real (r8) q(im,jfirst-ng:jlast+ng) ! transported scalar ( N*NG S*NG )
182 : real (r8) crx(im,jfirst-ng:jlast+ng) ! Ask S.-J. ( N*NG S*NG )
183 : real (r8) cry(im,jfirst:jlast+1) ! Ask S.-J. ( N like FY )
184 : real (r8) xfx(im,jfirst:jlast) ! Ask S.-J. ( unghosted like FX )
185 : real (r8) yfx(im,jfirst:jlast+1) ! Ask S.-J. ( N like FY )
186 :
187 : ! !OUTPUT PARAMETERS:
188 : real (r8) fx(im,jfirst:jlast) ! Flux in x ( unghosted )
189 : real (r8) fy(im,jfirst:jlast+1) ! Flux in y ( N, see tp2c )
190 :
191 : ! !DESCRIPTION:
192 : ! Perform transport on a D grid. The number of ghost
193 : ! latitudes (NG) depends on what method (JORD) will be used
194 : ! subsequentally. NG is equal to MIN(ABS(JORD),3).
195 : !
196 : !
197 : ! !REVISION HISTORY:
198 : ! WS 99.04.13: Added jfirst:jlast concept
199 : ! 99.04.21: Removed j1 and j2 (j1=2, j2=jm-1 consistently)
200 : ! 99.04.27: Removed dc, wk2 as arguments (local to YTP)
201 : ! 99.04.27: Removed adx as arguments (local here)
202 : ! SJL 99.07.26: ffsl flag added
203 : ! WS 99.09.07: Restructuring, cleaning, documentation
204 : ! WS 99.10.22: NG now argument; arrays pruned
205 : ! WS 00.05.14: Renamed ghost indices as per Kevin's definitions
206 : !
207 : !EOP
208 : !---------------------------------------------------------------------
209 : !BOC
210 :
211 : ! Local:
212 : integer i, j, iad, jp, js2g0, js2gng, jn2g0, jn2gng
213 86016000 : real (r8) adx(im,jfirst-ng:jlast+ng)
214 86016000 : real (r8) wk1v(im,jfirst-ng:jlast+ng)
215 86016000 : real (r8) dm(-im/3:im+im/3)
216 86016000 : real (r8) qtmpv(-im/3:im+im/3,jfirst-ng:jlast+ng)
217 86016000 : real (r8) al(-im/3:im+im/3)
218 86016000 : real (r8) ar(-im/3:im+im/3)
219 86016000 : real (r8) a6(-im/3:im+im/3)
220 :
221 : ! Number of ghost latitudes
222 43008000 : js2g0 = max(2,jfirst) ! No ghosting
223 43008000 : js2gng = max(2,jfirst-ng) ! Number needed on S
224 43008000 : jn2g0 = min(jm-1,jlast) ! No ghosting
225 43008000 : jn2gng = min(jm-1,jlast+ng) ! Number needed on N
226 43008000 : iad = 1
227 :
228 : call xtpv(im, ffsl, wk1v, q, crx, iad, crx, &
229 : cosp, 0, dm, qtmpv, al, ar, a6, &
230 : jfirst, jlast, js2gng, jn2gng, jm, &
231 : 1, jm, jfirst-ng, jlast+ng, &
232 : jfirst-ng, jlast+ng, jfirst-ng, jlast+ng, &
233 43008000 : jfirst-ng, jlast+ng, jfirst-ng, jlast+ng)
234 :
235 422026752 : do j=js2gng,jn2gng ! adx needed on N*ng S*ng
236 :
237 >10915*10^7 : do i=1,im-1
238 >21755*10^7 : adx(i,j) = q(i,j) + D0_5 * &
239 >32671*10^7 : (wk1v(i,j)-wk1v(i+1,j) + q(i,j)*(crx(i+1,j)-crx(i,j)))
240 : enddo
241 758037504 : adx(im,j) = q(im,j) + D0_5 * &
242 1180064256 : (wk1v(im,j)-wk1v(1,j) + q(im,j)*(crx(1,j)-crx(im,j)))
243 : enddo
244 :
245 : ! WS 99.09.07 : Split up north and south pole
246 :
247 43008000 : if ( jfirst-ng <= 1 ) then
248 385308672 : do i=1,im
249 385308672 : adx(i, 1) = q(i,1)
250 : enddo
251 : endif
252 43008000 : if ( jlast+ng >= jm ) then
253 385308672 : do i=1,im
254 385308672 : adx(i,jm) = q(i,jm)
255 : enddo
256 : endif
257 :
258 43008000 : call ytp(im,jm,fy, adx,cry,yfx,ng,jord,0,jfirst,jlast)
259 :
260 170688000 : do j=js2g0,jn2g0
261 36942528000 : do i=1,im
262 36771840000 : jp = j-va(i,j)
263 36899520000 : wk1v(i,j) = q(i,j) +D0_5*va(i,j)*(q(i,jp)-q(i,jp+1))
264 : enddo
265 : enddo
266 :
267 : call xtpv(im, ffsl, fx, wk1v, crx, iord, xfx, &
268 : cosp, id, dm, qtmpv, al, ar, a6, &
269 : jfirst, jlast, js2g0, jn2g0, jm, &
270 : 1, jm, jfirst, jlast, &
271 : jfirst-ng, jlast+ng, jfirst-ng, jlast+ng, &
272 43008000 : jfirst, jlast, jfirst-ng, jlast+ng)
273 :
274 43008000 : return
275 : !EOC
276 : end subroutine tp2d
277 : !-----------------------------------------------------------------------
278 :
279 : #ifndef VECTORIZE
280 : !-----------------------------------------------------------------------
281 : !BOP
282 : ! !IROUTINE: xtpv
283 : !
284 : ! !INTERFACE:
285 87392256 : subroutine xtpv(im, ffslv, fxv, qv, cv, iord, mfxv, &
286 87392256 : cosav, id, dmw, qtmpv, alw, arw, a6w, &
287 : jfirst, jlast, jlow, jhigh, jm, &
288 : jl2, jh2, jl3, jh3, &
289 : jl4, jh4, jl5, jh5, &
290 : jl7, jh7, jl11, jh11)
291 : !-----------------------------------------------------------------------
292 :
293 : implicit none
294 :
295 : ! !INPUT PARAMETERS:
296 : integer id ! ID = 0: density (mfx = C)
297 : ! ID = 1: mixing ratio (mfx is mass flux)
298 :
299 : integer im ! Total longitudes
300 : integer iord
301 : integer jfirst, jlast, jlow, jhigh, jm
302 : integer jl2, jh2, jl3, jh3, jl4, jh4, jl5, jh5
303 : integer jl7, jh7, jl11, jh11
304 : real (r8) cv(im,jl5:jh5) ! Courant numbers
305 : real (r8) qv(im,jl4:jh4)
306 : real (r8) mfxv(im,jl7:jh7)
307 : logical ffslv(jl2:jh2)
308 : real (r8) cosav(jm)
309 :
310 : ! !INPUT/OUTPUT PARAMETERS:
311 : real (r8) qtmpv(-im/3:im+im/3,jl11:jh11) ! Input work arrays:
312 : real (r8) dmw(-im/3:im+im/3)
313 : real (r8) alw(-im/3:im+im/3)
314 : real (r8) arw(-im/3:im+im/3)
315 : real (r8) a6w(-im/3:im+im/3)
316 :
317 : ! !OUTPUT PARAMETERS:
318 : real (r8) fxv(im,jl3:jh3)
319 :
320 : ! !DESCRIPTION:
321 : !
322 : !
323 : ! !REVISION HISTORY:
324 : ! 99.01.01 Lin Creation
325 : ! 01.03.27 Sawyer Additional ProTeX documentation
326 : !
327 : !EOP
328 : !-----------------------------------------------------------------------
329 : !BOC
330 :
331 : ! Local:
332 : real (r8) cos_upw !critical cosine for upwind
333 : real (r8) cos_van !critical cosine for van Leer
334 : real (r8) cos_ppm !critical cosine for ppm
335 :
336 : parameter (cos_upw = D0_05) !roughly at 87 deg.
337 : parameter (cos_van = D0_25) !roughly at 75 deg.
338 : parameter (cos_ppm = D0_25)
339 :
340 : integer i, imp, j
341 : real (r8) qmax, qmin
342 : real (r8) rut, tmp
343 : integer iu, itmp, ist
344 174784512 : integer isave(im)
345 : integer iuw, iue
346 174784512 : real (r8) dm(-im/3:im+im/3)
347 174784512 : real (r8) al(-im/3:im+im/3)
348 174784512 : real (r8) ar(-im/3:im+im/3)
349 174784512 : real (r8) a6(-im/3:im+im/3)
350 :
351 87392256 : imp = im + 1
352 :
353 599801664 : do j = jlow, jhigh
354 :
355 >14808*10^7 : do i=1,im
356 >14808*10^7 : qtmpv(i,j) = qv(i,j)
357 : enddo
358 :
359 599801664 : if( ffslv(j) ) then
360 : ! Flux-Form Semi-Lagrangian transport
361 :
362 : ! Figure out ghost zone for the western edge:
363 15378664 : iuw = -cv(1,j)
364 15378664 : iuw = min(0, iuw)
365 :
366 30757328 : do i=iuw, 0
367 30757328 : qtmpv(i,j) = qv(im+i,j)
368 : enddo
369 :
370 : ! Figure out ghost zone for the eastern edge:
371 15378664 : iue = im - cv(im,j)
372 15378664 : iue = max(imp, iue)
373 :
374 33246870 : do i=imp, iue
375 33246870 : qtmpv(i,j) = qv(i-im,j)
376 : enddo
377 :
378 15378664 : if( iord == 1 .or. cosav(j) < cos_upw) then
379 3926388391 : do i=1,im
380 3912802272 : iu = cv(i,j)
381 3912802272 : if(cv(i,j) .le. D0_0) then
382 1558489343 : itmp = i - iu
383 1558489343 : isave(i) = itmp - 1
384 : else
385 2354312929 : itmp = i - iu - 1
386 2354312929 : isave(i) = itmp + 1
387 : endif
388 3926388391 : fxv(i,j) = (cv(i,j)-iu) * qtmpv(itmp,j)
389 : enddo
390 : else
391 :
392 518045505 : do i=1,im
393 : ! 2nd order slope
394 516252960 : tmp = D0_25*(qtmpv(i+1,j) - qtmpv(i-1,j))
395 516252960 : qmax = max(qtmpv(i-1,j), qtmpv(i,j), qtmpv(i+1,j)) - qtmpv(i,j)
396 516252960 : qmin = qtmpv(i,j) - min(qtmpv(i-1,j), qtmpv(i,j), qtmpv(i+1,j))
397 518045505 : dm(i) = sign(min(abs(tmp),qmax,qmin), tmp)
398 : enddo
399 :
400 :
401 3585090 : do i=iuw, 0
402 3585090 : dm(i) = dm(im+i)
403 : enddo
404 :
405 3585090 : do i=imp, iue
406 3585090 : dm(i) = dm(i-im)
407 : enddo
408 :
409 1792545 : if(iord .ge. 3 .and. cosav(j) .gt. cos_ppm) then
410 : call fxppm(im, cv(:,j), mfxv(:,j), qtmpv(:,j), dm, fxv(:,j), iord, al, ar, a6, &
411 262560 : iuw, iue, ffslv(j), isave)
412 : else
413 442165665 : do i=1,im
414 440635680 : iu = cv(i,j)
415 440635680 : rut = cv(i,j) - iu
416 442165665 : if(cv(i,j) .le. D0_0) then
417 124549908 : itmp = i - iu
418 124549908 : isave(i) = itmp - 1
419 124549908 : fxv(i,j) = rut*(qtmpv(itmp,j)-dm(itmp)*(D1_0+rut))
420 : else
421 316085772 : itmp = i - iu - 1
422 316085772 : isave(i) = itmp + 1
423 316085772 : fxv(i,j) = rut*(qtmpv(itmp,j)+dm(itmp)*(D1_0-rut))
424 : endif
425 : enddo
426 : endif
427 :
428 : endif
429 :
430 4444433896 : do i=1,im
431 4444433896 : if(cv(i,j) .ge. D1_0) then
432 2863285989 : do ist = isave(i),i-1
433 2863285989 : fxv(i,j) = fxv(i,j) + qtmpv(ist,j)
434 : enddo
435 3352868707 : elseif(cv(i,j) .le. -D1_0) then
436 1632720550 : do ist = i,isave(i)
437 1632720550 : fxv(i,j) = fxv(i,j) - qtmpv(ist,j)
438 : enddo
439 : endif
440 : enddo
441 :
442 15378664 : if(id .ne. 0) then
443 1241335920 : do i=1,im
444 1241335920 : fxv(i,j) = fxv(i,j)*mfxv(i,j)
445 : enddo
446 : endif
447 :
448 : else
449 : ! Regular PPM (Eulerian without FFSL extension)
450 :
451 497030744 : qtmpv(imp,j) = qv(1,j)
452 497030744 : qtmpv( 0,j) = qv(im,j)
453 :
454 497030744 : if(iord == 1 .or. cosav(j) < cos_upw) then
455 >10756*10^7 : do i=1,im
456 >10719*10^7 : iu = real(i,r8) - cv(i,j)
457 >10756*10^7 : fxv(i,j) = mfxv(i,j)*qtmpv(iu,j)
458 : enddo
459 : else
460 :
461 124819311 : qtmpv(-1,j) = qv(im-1,j)
462 124819311 : qtmpv(imp+1,j) = qv(2,j)
463 :
464 124819311 : if(iord > 0 .or. cosav(j) < cos_van) then
465 121554735 : call xmist(im, qtmpv(:,j), dm, 2)
466 : else
467 3264576 : call xmist(im, qtmpv(:,j), dm, iord)
468 : endif
469 :
470 124819311 : dm(0) = dm(im)
471 :
472 124819311 : if( abs(iord).eq.2 .or. cosav(j) .lt. cos_van ) then
473 5374849455 : do i=1,im
474 5356251360 : iu = real(i,r8) - cv(i,j)
475 5374849455 : fxv(i,j) = mfxv(i,j)*(qtmpv(iu,j)+dm(iu)*(sign(D1_0,cv(i,j))-cv(i,j)))
476 :
477 : ! if(cv(i,j) .le. 0.) then
478 : ! fxv(i,j) = qtmpv(i,j) - dm(i)*(1.+cv(i,j))
479 : ! else
480 : ! fxv(i,j) = qtmpv(i-1,j) + dm(i-1)*(1.-cv(i,j))
481 : ! endif
482 : ! fxv(i,j) = fxv(i,j)*mfxv(i,j)
483 :
484 : enddo
485 : else
486 : call fxppm(im, cv(:,j), mfxv(:,j), qtmpv(:,j), dm, fxv(:,j), iord, al, ar, a6, &
487 106221216 : iuw, iue, ffslv(j), isave)
488 : endif
489 : endif
490 :
491 : endif
492 :
493 : enddo
494 :
495 87392256 : return
496 : !EOC
497 : end subroutine xtpv
498 : !-----------------------------------------------------------------------
499 :
500 : !-----------------------------------------------------------------------
501 : !BOP
502 : ! !IROUTINE: xmist
503 : !
504 : ! !INTERFACE:
505 124819311 : subroutine xmist(im, q, dm, id)
506 : !-----------------------------------------------------------------------
507 :
508 : implicit none
509 :
510 : ! !INPUT PARAMETERS:
511 : integer im ! Total number of longitudes
512 : integer id ! ID = 0: density (mfx = C)
513 : ! ID = 1: mixing ratio (mfx is mass flux)
514 : real(r8) q(-im/3:im+im/3) ! Input latitude
515 :
516 : ! !OUTPUT PARAMETERS:
517 : real(r8) dm(-im/3:im+im/3) !
518 :
519 : ! !DESCRIPTION:
520 : !
521 : !
522 : ! !REVISION HISTORY:
523 : ! 99.01.01 Lin Creation
524 : ! 01.03.27 Sawyer Additional ProTeX documentation
525 : !
526 : !EOP
527 : !-----------------------------------------------------------------------
528 : !BOC
529 :
530 : real(r8) r24
531 : parameter( r24 = D1_0/D24_0)
532 :
533 : integer i
534 : real(r8) qmin, qmax
535 :
536 124819311 : if(id .le. 2) then
537 36072780879 : do i=1,im
538 36072780879 : dm(i) = r24*(D8_0*(q(i+1) - q(i-1)) + q(i-2) - q(i+2))
539 : enddo
540 : else
541 0 : do i=1,im
542 0 : dm(i) = D0_25*(q(i+1) - q(i-1))
543 : enddo
544 : endif
545 :
546 124819311 : if( id < 0 ) return
547 :
548 : ! Apply monotonicity constraint (Lin et al. 1994, MWR)
549 35129318415 : do i=1,im
550 35007763680 : qmax = max( q(i-1), q(i), q(i+1) ) - q(i)
551 35007763680 : qmin = q(i) - min( q(i-1), q(i), q(i+1) )
552 35129318415 : dm(i) = sign( min(abs(dm(i)), qmax, qmin), dm(i) )
553 : enddo
554 : return
555 : !EOC
556 : end subroutine xmist
557 : !-----------------------------------------------------------------------
558 :
559 : !-----------------------------------------------------------------------
560 : !BOP
561 : ! !IROUTINE: fxppm
562 : !
563 : ! !INTERFACE:
564 106483776 : subroutine fxppm(im, c, mfx, p, dm, fx, iord, al, ar, a6, &
565 106483776 : iuw, iue, ffsl, isave)
566 : !-----------------------------------------------------------------------
567 : !
568 : ! !USES:
569 : implicit none
570 :
571 : ! !INPUT PARAMETERS:
572 : integer im, iord
573 : real (r8) c(im)
574 : real (r8) p(-im/3:im+im/3)
575 : real (r8) dm(-im/3:im+im/3)
576 : real (r8) mfx(im)
577 : integer iuw, iue
578 : logical ffsl
579 : integer isave(im)
580 :
581 : ! !INPUT/OUTPUT PARAMETERS:
582 : real (r8) al(-im/3:im+im/3)
583 : real (r8) ar(-im/3:im+im/3)
584 : real (r8) a6(-im/3:im+im/3)
585 :
586 : ! !OUTPUT PARAMETERS:
587 : real (r8) fx(im)
588 :
589 : ! !DESCRIPTION:
590 : !
591 : !
592 : ! !REVISION HISTORY:
593 : ! 99.01.01 Lin Creation
594 : ! 01.03.27 Sawyer Additional ProTeX documentation
595 : !
596 : !EOP
597 : !-----------------------------------------------------------------------
598 : !BOC
599 : !
600 : ! !LOCAL VARIABLES:
601 : real (r8) r3, r23
602 : parameter ( r3 = D1_0/D3_0, r23 = D2_0/D3_0 )
603 :
604 : integer i, lmt
605 : integer iu, itmp
606 : real (r8) ru
607 : logical steep
608 :
609 106483776 : if( iord == 6 ) then
610 : steep = .true.
611 : else
612 106483776 : steep = .false.
613 : endif
614 :
615 30773811264 : do i=1,im
616 30773811264 : al(i) = D0_5*(p(i-1)+p(i)) + (dm(i-1) - dm(i))*r3
617 : enddo
618 :
619 106483776 : if( steep ) call steepx( im, p, al(1), dm )
620 :
621 30667327488 : do i=1,im-1
622 30667327488 : ar(i) = al(i+1)
623 : enddo
624 106483776 : ar(im) = al(1)
625 :
626 106483776 : if(iord == 7) then
627 : call huynh(im, ar(1), al(1), p(1), a6(1), dm(1))
628 : else
629 106483776 : if(iord .eq. 3 .or. iord .eq. 5) then
630 0 : do i=1,im
631 0 : a6(i) = D3_0*(p(i)+p(i) - (al(i)+ar(i)))
632 : enddo
633 : endif
634 106483776 : lmt = iord - 3
635 : call lmppm( dm(1), a6(1), ar(1), al(1), p(1), im, lmt )
636 : endif
637 :
638 106483776 : if( ffsl ) then
639 :
640 525120 : do i=iuw, 0
641 262560 : al(i) = al(im+i)
642 262560 : ar(i) = ar(im+i)
643 525120 : a6(i) = a6(im+i)
644 : enddo
645 :
646 525120 : do i=im+1, iue
647 262560 : al(i) = al(i-im)
648 262560 : ar(i) = ar(i-im)
649 525120 : a6(i) = a6(i-im)
650 : enddo
651 :
652 75879840 : do i=1,im
653 75617280 : iu = c(i)
654 75617280 : ru = c(i) - iu
655 75879840 : if(c(i) .gt. D0_0) then
656 75500160 : itmp = i - iu - 1
657 75500160 : isave(i) = itmp + 1
658 75500160 : fx(i) = ru*(ar(itmp)+D0_5*ru*(al(itmp)-ar(itmp) + &
659 151000320 : a6(itmp)*(D1_0-r23*ru)) )
660 : else
661 117120 : itmp = i - iu
662 117120 : isave(i) = itmp - 1
663 117120 : fx(i) = ru*(al(itmp)-D0_5*ru*(ar(itmp)-al(itmp) + &
664 234240 : a6(itmp)*(D1_0+r23*ru)) )
665 : endif
666 : enddo
667 :
668 : else
669 106221216 : al(0) = al(im)
670 106221216 : ar(0) = ar(im)
671 106221216 : a6(0) = a6(im)
672 30697931424 : do i=1,im
673 30591710208 : if(c(i) .gt. D0_0) then
674 18555299150 : fx(i) = ar(i-1) + D0_5*c(i)*(al(i-1) - ar(i-1) + &
675 18555299150 : a6(i-1)*(D1_0-r23*c(i)) )
676 : else
677 12036411058 : fx(i) = al(i) - D0_5*c(i)*(ar(i) - al(i) + &
678 12036411058 : a6(i)*(D1_0+r23*c(i)))
679 : endif
680 30697931424 : fx(i) = mfx(i) * fx(i)
681 : enddo
682 : endif
683 106483776 : return
684 : !EOC
685 : end subroutine fxppm
686 : !-----------------------------------------------------------------------
687 :
688 : !-----------------------------------------------------------------------
689 : !BOP
690 : ! !IROUTINE: steepx
691 : !
692 : ! !INTERFACE:
693 0 : subroutine steepx(im, p, al, dm)
694 : !-----------------------------------------------------------------------
695 :
696 : ! !USES:
697 : implicit none
698 :
699 : ! !INPUT PARAMETERS:
700 : integer im
701 : real (r8) p(-im/3:im+im/3)
702 : real (r8) dm(-im/3:im+im/3)
703 :
704 : ! !INPUT/OUTPUT PARAMETERS:
705 : real (r8) al(im)
706 :
707 : ! !DESCRIPTION:
708 : !
709 : !
710 : ! !REVISION HISTORY:
711 : ! 99.01.01 Lin Creation
712 : ! 01.03.27 Sawyer Additional ProTeX documentation
713 : !
714 : !EOP
715 : !-----------------------------------------------------------------------
716 : !BOC
717 : !
718 : ! !LOCAL VARIABLES:
719 : integer i
720 : real (r8) r3
721 : parameter ( r3 = D1_0/D3_0 )
722 :
723 0 : real (r8) dh(0:im)
724 0 : real (r8) d2(0:im+1)
725 0 : real (r8) eta(0:im)
726 : real (r8) xxx, bbb, ccc
727 :
728 0 : do i=0,im
729 0 : dh(i) = p(i+1) - p(i)
730 : enddo
731 :
732 : ! Needs dh(0:im)
733 0 : do i=1,im
734 0 : d2(i) = dh(i) - dh(i-1)
735 : enddo
736 0 : d2(0) = d2(im)
737 0 : d2(im+1) = d2(1)
738 :
739 : ! needs p(-1:im+2), d2(0:im+1)
740 0 : do i=1,im
741 0 : if( d2(i+1)*d2(i-1).lt.D0_0 .and. p(i+1).ne.p(i-1) ) then
742 0 : xxx = D1_0 - D0_5 * ( p(i+2) - p(i-2) ) / ( p(i+1) - p(i-1) )
743 0 : eta(i) = max(D0_0, min(xxx, D0_5) )
744 : else
745 0 : eta(i) = D0_0
746 : endif
747 : enddo
748 :
749 0 : eta(0) = eta(im)
750 :
751 : ! needs eta(0:im), dh(0:im-1), dm(0:im)
752 0 : do i=1,im
753 0 : bbb = ( D2_0*eta(i ) - eta(i-1) ) * dm(i-1)
754 0 : ccc = ( D2_0*eta(i-1) - eta(i ) ) * dm(i )
755 0 : al(i) = al(i) + D0_5*( eta(i-1) - eta(i)) * dh(i-1) + (bbb - ccc) * r3
756 : enddo
757 0 : return
758 : !EOC
759 : end subroutine steepx
760 : !-----------------------------------------------------------------------
761 :
762 : !-----------------------------------------------------------------------
763 : !BOP
764 : ! !IROUTINE: lmppm
765 : !
766 : ! !INTERFACE:
767 148975680 : subroutine lmppm(dm, a6, ar, al, p, im, lmt)
768 : !-----------------------------------------------------------------------
769 :
770 : implicit none
771 :
772 : ! !INPUT PARAMETERS:
773 : integer im ! Total longitudes
774 : integer lmt ! LMT = 0: full monotonicity
775 : ! LMT = 1: Improved and simplified full monotonic constraint
776 : ! LMT = 2: positive-definite constraint
777 : ! LMT = 3: Quasi-monotone constraint
778 : real(r8) p(im)
779 : real(r8) dm(im)
780 :
781 : ! !OUTPUT PARAMETERS:
782 : real(r8) a6(im)
783 : real(r8) ar(im)
784 : real(r8) al(im)
785 :
786 : ! !DESCRIPTION:
787 : !
788 : !
789 : ! !REVISION HISTORY:
790 : ! 99.01.01 Lin Creation
791 : ! 01.03.27 Sawyer Additional ProTeX documentation
792 : !
793 : !EOP
794 : !-----------------------------------------------------------------------
795 : !BOC
796 : !
797 : ! !LOCAL VARIABLES:
798 : real (r8) r12
799 : parameter ( r12 = D1_0/D12_0 )
800 :
801 : real (r8) da1, da2, fmin, a6da
802 : real (r8) dr, dl
803 :
804 : integer i
805 :
806 : ! LMT = 0: full monotonicity
807 : ! LMT = 1: Improved and simplified full monotonic constraint
808 : ! LMT = 2: positive-definite constraint
809 : ! LMT = 3: Quasi-monotone constraint
810 :
811 148975680 : if( lmt == 0 ) then
812 :
813 : ! Full constraint
814 0 : do i=1,im
815 0 : if(dm(i) .eq. D0_0) then
816 0 : ar(i) = p(i)
817 0 : al(i) = p(i)
818 0 : a6(i) = D0_0
819 : else
820 0 : da1 = ar(i) - al(i)
821 0 : da2 = da1**2
822 0 : a6da = a6(i)*da1
823 0 : if(a6da .lt. -da2) then
824 0 : a6(i) = D3_0*(al(i)-p(i))
825 0 : ar(i) = al(i) - a6(i)
826 0 : elseif(a6da .gt. da2) then
827 0 : a6(i) = D3_0*(ar(i)-p(i))
828 0 : al(i) = ar(i) - a6(i)
829 : endif
830 : endif
831 : enddo
832 :
833 148975680 : elseif( lmt == 1 ) then
834 :
835 : ! Improved (Lin 2001?) full constraint
836 91622217792 : do i=1,im
837 91473242112 : da1 = dm(i) + dm(i)
838 91473242112 : dl = sign(min(abs(da1),abs(al(i)-p(i))), da1)
839 91473242112 : dr = sign(min(abs(da1),abs(ar(i)-p(i))), da1)
840 91473242112 : ar(i) = p(i) + dr
841 91473242112 : al(i) = p(i) - dl
842 91622217792 : a6(i) = D3_0*(dl-dr)
843 : enddo
844 :
845 0 : elseif( lmt == 2 ) then
846 : ! Positive definite constraint
847 0 : do 250 i=1,im
848 0 : if(abs(ar(i)-al(i)) .ge. -a6(i)) go to 250
849 0 : fmin = p(i) + D0_25*(ar(i)-al(i))**2/a6(i) + a6(i)*r12
850 0 : if(fmin.ge.D0_0) go to 250
851 0 : if(p(i).lt.ar(i) .and. p(i).lt.al(i)) then
852 0 : ar(i) = p(i)
853 0 : al(i) = p(i)
854 0 : a6(i) = D0_0
855 0 : elseif(ar(i) .gt. al(i)) then
856 0 : a6(i) = D3_0*(al(i)-p(i))
857 0 : ar(i) = al(i) - a6(i)
858 : else
859 0 : a6(i) = D3_0*(ar(i)-p(i))
860 0 : al(i) = ar(i) - a6(i)
861 : endif
862 0 : 250 continue
863 :
864 0 : elseif(lmt .eq. 3) then
865 : ! Quasi-monotone constraint
866 0 : do i=1,im
867 0 : da1 = D4_0*dm(i)
868 0 : dl = sign(min(abs(da1),abs(al(i)-p(i))), da1)
869 0 : dr = sign(min(abs(da1),abs(ar(i)-p(i))), da1)
870 0 : ar(i) = p(i) + dr
871 0 : al(i) = p(i) - dl
872 0 : a6(i) = D3_0*(dl-dr)
873 : enddo
874 : endif
875 148975680 : return
876 : !EOC
877 : end subroutine lmppm
878 : !-----------------------------------------------------------------------
879 :
880 : !-----------------------------------------------------------------------
881 : !BOP
882 : ! !IROUTINE: huynh --- Enforce Huynh's 2nd constraint in 1D periodic domain
883 : !
884 : ! !INTERFACE:
885 0 : subroutine huynh(im, ar, al, p, d2, d1)
886 : !-----------------------------------------------------------------------
887 :
888 : ! !USES:
889 :
890 : implicit none
891 :
892 : ! !INPUT PARAMETERS:
893 : integer im
894 : real(r8) p(im)
895 :
896 : ! !OUTPUT PARAMETERS:
897 : real(r8) ar(im)
898 : real(r8) al(im)
899 : real(r8) d2(im)
900 : real(r8) d1(im)
901 :
902 : ! !DESCRIPTION:
903 : !
904 : ! Enforce Huynh's 2nd constraint in 1D periodic domain
905 : !
906 : ! !REVISION HISTORY:
907 : ! 99.01.01 Lin Creation
908 : ! 01.03.27 Sawyer Additional ProTeX documentation
909 : !
910 : !EOP
911 : !-----------------------------------------------------------------------
912 : !BOC
913 : !
914 : ! !LOCAL VARIABLES:
915 : integer i
916 : real(r8) pmp
917 : real(r8) lac
918 : real(r8) pmin
919 : real(r8) pmax
920 :
921 : ! Compute d1 and d2
922 0 : d1(1) = p(1) - p(im)
923 0 : do i=2,im
924 0 : d1(i) = p(i) - p(i-1)
925 : enddo
926 :
927 0 : do i=1,im-1
928 0 : d2(i) = d1(i+1) - d1(i)
929 : enddo
930 0 : d2(im) = d1(1) - d1(im)
931 :
932 : ! Constraint for AR
933 : ! i = 1
934 0 : pmp = p(1) + D2_0 * d1(1)
935 0 : lac = p(1) + D0_5 * (d1(1)+d2(im)) + d2(im)
936 0 : pmin = min(p(1), pmp, lac)
937 0 : pmax = max(p(1), pmp, lac)
938 0 : ar(1) = min(pmax, max(ar(1), pmin))
939 :
940 0 : do i=2, im
941 0 : pmp = p(i) + D2_0*d1(i)
942 0 : lac = p(i) + D0_5*(d1(i)+d2(i-1)) + d2(i-1)
943 0 : pmin = min(p(i), pmp, lac)
944 0 : pmax = max(p(i), pmp, lac)
945 0 : ar(i) = min(pmax, max(ar(i), pmin))
946 : enddo
947 :
948 : ! Constraint for AL
949 0 : do i=1, im-1
950 0 : pmp = p(i) - D2_0*d1(i+1)
951 0 : lac = p(i) + D0_5*(d2(i+1)-d1(i+1)) + d2(i+1)
952 0 : pmin = min(p(i), pmp, lac)
953 0 : pmax = max(p(i), pmp, lac)
954 0 : al(i) = min(pmax, max(al(i), pmin))
955 : enddo
956 :
957 : ! i=im
958 0 : i = im
959 0 : pmp = p(im) - D2_0*d1(1)
960 0 : lac = p(im) + D0_5*(d2(1)-d1(1)) + d2(1)
961 0 : pmin = min(p(im), pmp, lac)
962 0 : pmax = max(p(im), pmp, lac)
963 0 : al(im) = min(pmax, max(al(im), pmin))
964 :
965 : ! compute A6 (d2)
966 0 : do i=1, im
967 0 : d2(i) = D3_0*(p(i)+p(i) - (al(i)+ar(i)))
968 : enddo
969 0 : return
970 : !EOC
971 : end subroutine huynh
972 : !-----------------------------------------------------------------------
973 : #endif
974 :
975 : !-----------------------------------------------------------------------
976 : !BOP
977 : ! !IROUTINE: ytp
978 : !
979 : ! !INTERFACE:
980 43352064 : subroutine ytp(im, jm, fy, q, c, yfx, ng, jord, iv, jfirst, jlast)
981 : !-----------------------------------------------------------------------
982 :
983 : ! !USES:
984 : implicit none
985 :
986 : ! !INPUT PARAMETERS:
987 : integer im, jm ! Dimensions
988 : integer jfirst, jlast ! Latitude strip
989 : integer ng ! Max. NS dependencies
990 : integer jord ! order of subgrid dist
991 : integer iv ! Scalar=0, Vector=1
992 : real (r8) q(im,jfirst-ng:jlast+ng) ! advected scalar N*jord S*jord
993 : real (r8) c(im,jfirst:jlast+1) ! Courant N (like FY)
994 : real (r8) yfx(im,jfirst:jlast+1) ! Backgrond mass flux
995 :
996 : ! !OUTPUT PARAMETERS:
997 : real (r8) fy(im,jfirst:jlast+1) ! Flux N (see tp2c)
998 :
999 : ! !DESCRIPTION:
1000 : ! This routine calculates the flux FX. The method chosen
1001 : ! depends on the order of the calculation JORD (currently
1002 : ! 1, 2 or 3).
1003 : !
1004 : ! !CALLED FROM:
1005 : ! cd_core
1006 : ! tp2d
1007 : !
1008 : ! !REVISION HISTORY:
1009 : !
1010 : ! SJL 99.04.13: Delivery
1011 : ! WS 99.04.13: Added jfirst:jlast concept
1012 : ! WS 99.04.21: Removed j1 and j2 (j1=2, j2=jm-1 consistently)
1013 : ! removed a6,ar,al from argument list
1014 : ! WS 99.04.27: DM made local to this routine
1015 : ! WS 99.09.09: Documentation; indentation; cleaning
1016 : ! WS 99.10.22: Added NG as argument; pruned arrays
1017 : ! SJL 99.12.24: Revised documentation; optimized for better cache usage
1018 : ! WS 00.05.14: Renamed ghost indices as per Kevin's definitions
1019 : !
1020 : !EOP
1021 : !---------------------------------------------------------------------
1022 : !BOC
1023 : !
1024 : ! !LOCAL VARIABLES:
1025 : integer i, j, jt
1026 : integer js2g0, jn1g1
1027 :
1028 : ! work arrays (should pass in eventually for performance enhancement):
1029 86704128 : real (r8) dm(im,jfirst-ng:jlast+ng)
1030 :
1031 : ! real (r8) ar(im,jfirst-1:jlast+1) ! AR needs to be ghosted on NS
1032 : ! real (r8) al(im,jfirst-1:jlast+2) ! AL needs to be ghosted on N2S
1033 : ! real (r8) a6(im,jfirst-1:jlast+1) ! A6 needs to be ghosted on NS
1034 :
1035 43352064 : js2g0 = max(2,jfirst) ! No ghosting
1036 43352064 : jn1g1 = min(jm,jlast+1) ! Ghost N*1
1037 :
1038 43352064 : if(jord == 1) then
1039 641088 : do j=js2g0,jn1g1
1040 148115520 : do i=1,im
1041 147474432 : jt = real(j,r8) - c(i,j)
1042 147986496 : fy(i,j) = q(i,jt)
1043 : enddo
1044 : enddo
1045 : else
1046 :
1047 : !
1048 : ! YMIST requires q on NS; Only call to YMIST here
1049 : !
1050 43223040 : call ymist(im, jm, q, dm, ng, jord, iv, jfirst, jlast)
1051 :
1052 43223040 : if( abs(jord) .ge. 3 ) then
1053 :
1054 42491904 : call fyppm(c,q,dm,fy,im,jm,ng,jord,iv,jfirst,jlast)
1055 :
1056 : else
1057 : !
1058 : ! JORD can either have the value 2 or -2 at this point
1059 : !
1060 3632832 : do j=js2g0,jn1g1
1061 839321280 : do i=1,im
1062 835688448 : jt = real(j,r8) - c(i,j)
1063 838590144 : fy(i,j) = q(i,jt) + (sign(D1_0,c(i,j))-c(i,j))*dm(i,jt)
1064 : enddo
1065 : enddo
1066 : endif
1067 : endif
1068 :
1069 215405568 : do j=js2g0,jn1g1
1070 49766814720 : do i=1,im
1071 49723462656 : fy(i,j) = fy(i,j)*yfx(i,j)
1072 : enddo
1073 : enddo
1074 43352064 : return
1075 : !EOC
1076 : end subroutine ytp
1077 : !-----------------------------------------------------------------------
1078 :
1079 : !-----------------------------------------------------------------------
1080 : !BOP
1081 : ! !IROUTINE: ymist
1082 : !
1083 : ! !INTERFACE:
1084 43223040 : subroutine ymist(im, jm, q, dm, ng, jord, iv, jfirst, jlast)
1085 : !-----------------------------------------------------------------------
1086 :
1087 : ! !USES:
1088 : implicit none
1089 :
1090 : ! !INPUT PARAMETERS:
1091 : integer im, jm ! Dimensions
1092 : integer jfirst, jlast ! Latitude strip
1093 : integer ng ! NS dependencies
1094 : integer jord ! order of subgrid distribution
1095 : integer iv ! Scalar (==0) Vector (==1)
1096 : real (r8) q(im,jfirst-ng:jlast+ng) ! transported scalar N*ng S*ng
1097 :
1098 : ! !OUTPUT PARAMETERS:
1099 : real (r8) dm(im,jfirst-ng:jlast+ng) ! Slope only N*(ng-1) S*(ng-1) used
1100 :
1101 : ! !DESCRIPTION:
1102 : ! Calculate the slope of the pressure. The number of ghost
1103 : ! latitudes (NG) depends on what method (JORD) will be used
1104 : ! subsequentally. NG is equal to MIN(ABS(JORD),3).
1105 : !
1106 : ! !CALLED FROM:
1107 : ! ytp
1108 : !
1109 : ! !REVISION HISTORY:
1110 : !
1111 : ! SJL 99.04.13: Delivery
1112 : ! WS 99.04.13: Added jfirst:jlast concept
1113 : ! WS 99.09.09: Documentation; indentation; cleaning
1114 : ! SJL 00.01.06: Documentation
1115 : ! WS 00.05.14: Renamed ghost indices as per Kevin's definitions
1116 : !
1117 : !EOP
1118 : !---------------------------------------------------------------------
1119 : !BOC
1120 :
1121 : ! Local variables
1122 :
1123 : integer i, j, jm1, im2, js2gng1, jn2gng1
1124 : real (r8) qmax, qmin, tmp
1125 :
1126 43223040 : js2gng1 = max(2, jfirst-ng+1) ! Number needed on S
1127 43223040 : jn2gng1 = min(jm-1,jlast+ng-1) ! Number needed on N
1128 :
1129 43223040 : jm1 = jm - 1
1130 43223040 : im2 = im / 2
1131 :
1132 340546752 : do j=js2gng1,jn2gng1
1133 85969775808 : do i=1,im
1134 85926552768 : dm(i,j) = D0_25*(q(i,j+1) - q(i,j-1))
1135 : enddo
1136 : enddo
1137 :
1138 43223040 : if( iv == 0 ) then
1139 :
1140 42889728 : if ( jfirst-ng <= 1 ) then
1141 : ! S pole
1142 192979920 : do i=1,im2
1143 191649024 : tmp = D0_25*(q(i,2)-q(i+im2,2))
1144 191649024 : qmax = max(q(i,2),q(i,1), q(i+im2,2)) - q(i,1)
1145 191649024 : qmin = q(i,1) - min(q(i,2),q(i,1), q(i+im2,2))
1146 192979920 : dm(i,1) = sign(min(abs(tmp),qmax,qmin),tmp)
1147 : enddo
1148 :
1149 192979920 : do i=im2+1,im
1150 192979920 : dm(i, 1) = - dm(i-im2, 1)
1151 : enddo
1152 : endif
1153 :
1154 42889728 : if ( jlast+ng >= jm ) then
1155 : ! N pole
1156 192979920 : do i=1,im2
1157 191649024 : tmp = D0_25*(q(i+im2,jm1)-q(i,jm1))
1158 191649024 : qmax = max(q(i+im2,jm1),q(i,jm), q(i,jm1)) - q(i,jm)
1159 191649024 : qmin = q(i,jm) - min(q(i+im2,jm1),q(i,jm), q(i,jm1))
1160 192979920 : dm(i,jm) = sign(min(abs(tmp),qmax,qmin),tmp)
1161 : enddo
1162 :
1163 192979920 : do i=im2+1,im
1164 192979920 : dm(i,jm) = - dm(i-im2,jm)
1165 : enddo
1166 : endif
1167 :
1168 : else
1169 :
1170 333312 : if ( jfirst-ng <= 1 ) then
1171 : ! South
1172 1510320 : do i=1,im2
1173 1499904 : tmp = D0_25*(q(i,2)+q(i+im2,2))
1174 1499904 : qmax = max(q(i,2),q(i,1), -q(i+im2,2)) - q(i,1)
1175 1499904 : qmin = q(i,1) - min(q(i,2),q(i,1),-q(i+im2,2))
1176 1510320 : dm(i,1) = sign(min(abs(tmp),qmax,qmin),tmp)
1177 : enddo
1178 :
1179 1510320 : do i=im2+1,im
1180 1510320 : dm(i, 1) = dm(i-im2, 1)
1181 : enddo
1182 : endif
1183 :
1184 333312 : if ( jlast+ng >= jm ) then
1185 : ! North
1186 1510320 : do i=1,im2
1187 1499904 : tmp = -D0_25*(q(i+im2,jm1)+q(i,jm1))
1188 1499904 : qmax = max(-q(i+im2,jm1),q(i,jm), q(i,jm1)) - q(i,jm)
1189 1499904 : qmin = q(i,jm) - min(-q(i+im2,jm1),q(i,jm), q(i,jm1))
1190 1510320 : dm(i,jm) = sign(min(abs(tmp),qmax,qmin),tmp)
1191 : enddo
1192 :
1193 1510320 : do i=im2+1,im
1194 1510320 : dm(i,jm) = dm(i-im2,jm)
1195 : enddo
1196 : endif
1197 :
1198 : endif
1199 :
1200 43223040 : if( jord > 0 ) then
1201 : !
1202 : ! Applies monotonic slope constraint (off if jord less than zero)
1203 : !
1204 336971712 : do j=js2gng1,jn2gng1
1205 85109997504 : do i=1,im
1206 84773025792 : qmax = max(q(i,j-1),q(i,j),q(i,j+1)) - q(i,j)
1207 84773025792 : qmin = q(i,j) - min(q(i,j-1),q(i,j),q(i,j+1))
1208 85067376576 : dm(i,j) = sign(min(abs(dm(i,j)),qmin,qmax),dm(i,j))
1209 : enddo
1210 : enddo
1211 : endif
1212 43223040 : return
1213 : !EOC
1214 : end subroutine ymist
1215 : !-----------------------------------------------------------------------
1216 :
1217 : !-----------------------------------------------------------------------
1218 : !BOP
1219 : ! !IROUTINE: fyppm
1220 : !
1221 : ! !INTERFACE:
1222 42491904 : subroutine fyppm(c, q, dm, flux, im, jm, ng, jord, iv, jfirst, jlast)
1223 : !-----------------------------------------------------------------------
1224 :
1225 : ! !USES:
1226 : implicit none
1227 :
1228 : ! !INPUT PARAMETERS:
1229 : integer im, jm ! Dimensions
1230 : integer jfirst, jlast ! Latitude strip
1231 : integer ng ! Max. NS dependencies
1232 : integer jord ! Approximation order
1233 : integer iv ! Scalar=0, Vector=1
1234 : real (r8) q(im,jfirst-ng:jlast+ng) ! mean value needed only N*2 S*2
1235 : real (r8) dm(im,jfirst-ng:jlast+ng) ! Slope needed only N*2 S*2
1236 : real (r8) c(im,jfirst:jlast+1) ! Courant N (like FLUX)
1237 :
1238 : ! !INPUT/OUTPUT PARAMETERS:
1239 84983808 : real (r8) ar(im,jfirst-1:jlast+1) ! AR needs to be ghosted on NS
1240 84983808 : real (r8) al(im,jfirst-1:jlast+2) ! AL needs to be ghosted on N2S
1241 84983808 : real (r8) a6(im,jfirst-1:jlast+1) ! A6 needs to be ghosted on NS
1242 :
1243 : ! !OUTPUT PARAMETERS:
1244 : real (r8) flux(im,jfirst:jlast+1) ! Flux N (see tp2c)
1245 :
1246 : ! !DESCRIPTION:
1247 : !
1248 : ! NG is passed from YTP for convenience -- it is actually 1 more in NS
1249 : ! than the actual number of latitudes needed here. But in the shared-memory
1250 : ! case it becomes 0, which is much cleaner.
1251 : !
1252 : ! !CALLED FROM:
1253 : ! ytp
1254 : !
1255 : ! !REVISION HISTORY:
1256 : !
1257 : ! SJL 99.04.13: Delivery
1258 : ! WS 99.04.19: Added jfirst:jlast concept; FYPPM only called from YTP
1259 : ! WS 99.04.21: Removed j1, j2 (j1=2, j2=jm-1 consistently)
1260 : ! removed a6,ar,al from argument list
1261 : ! WS 99.09.09: Documentation; indentation; cleaning
1262 : ! WS 99.10.22: Added ng as argument; Pruned arrays
1263 : ! WS 00.05.14: Renamed ghost indices as per Kevin's definitions
1264 : !
1265 : !EOP
1266 : !---------------------------------------------------------------------
1267 : !BOC
1268 : real (r8) r3, r23
1269 : parameter ( r3 = D1_0/D3_0, r23 = D2_0/D3_0 )
1270 : integer i, j, imh, jm1, lmt
1271 : integer js1g1, js2g0, js2g1, jn1g2, jn1g1, jn2g1
1272 : integer jan, jlow, jhigh, ilow, ihigh
1273 : integer ja(jlast-jfirst+3)
1274 : ! logical steep
1275 :
1276 : ! if(jord .eq. 6) then
1277 : ! steep = .true.
1278 : ! else
1279 : ! steep = .false.
1280 : ! endif
1281 :
1282 42491904 : imh = im / 2
1283 42491904 : jm1 = jm - 1
1284 :
1285 42491904 : js1g1 = max(1,jfirst-1) ! Ghost S*1
1286 42491904 : js2g0 = max(2,jfirst) ! No ghosting
1287 42491904 : js2g1 = max(2,jfirst-1) ! Ghost S*1
1288 42491904 : jn1g1 = min(jm,jlast+1) ! Ghost N*1
1289 42491904 : jn1g2 = min(jm,jlast+2) ! Ghost N*2
1290 42491904 : jn2g1 = min(jm-1,jlast+1) ! Ghost N*1
1291 :
1292 294787584 : do j=js2g1,jn1g2 ! AL needed N2S
1293 72955943424 : do i=1,im ! P, dm ghosted N2S2 (at least)
1294 72913451520 : al(i,j) = D0_5*(q(i,j-1)+q(i,j)) + r3*(dm(i,j-1) - dm(i,j))
1295 : enddo
1296 : enddo
1297 :
1298 : ! Yeh's steepening procedure; to be implemented
1299 : ! if(steep) call steepy(im, jm, jfirst, jlast, &
1300 : ! ng, q, al, dm )
1301 :
1302 252959616 : do j=js1g1,jn2g1 ! AR needed NS
1303 60867660672 : do i=1,im
1304 60825168768 : ar(i,j) = al(i,j+1) ! AL ghosted N2S
1305 : enddo
1306 : enddo
1307 :
1308 : ! WS 990726 : Added condition to decide if poles are on this processor
1309 :
1310 : ! Poles:
1311 :
1312 42491904 : if( iv == 0 ) then
1313 :
1314 42190848 : if ( jfirst == 1 ) then
1315 95588640 : do i=1,imh
1316 94929408 : al(i, 1) = al(i+imh,2)
1317 95588640 : al(i+imh,1) = al(i, 2)
1318 : enddo
1319 : endif
1320 :
1321 42190848 : if ( jlast == jm ) then
1322 95588640 : do i=1,imh
1323 94929408 : ar(i, jm) = ar(i+imh,jm1)
1324 95588640 : ar(i+imh,jm) = ar(i, jm1)
1325 : enddo
1326 : endif
1327 :
1328 : else
1329 :
1330 301056 : if ( jfirst == 1 ) then
1331 682080 : do i=1,imh
1332 677376 : al(i, 1) = -al(i+imh,2)
1333 682080 : al(i+imh,1) = -al(i, 2)
1334 : enddo
1335 : endif
1336 :
1337 301056 : if ( jlast == jm ) then
1338 682080 : do i=1,imh
1339 677376 : ar(i, jm) = -ar(i+imh,jm1)
1340 682080 : ar(i+imh,jm) = -ar(i, jm1)
1341 : enddo
1342 : endif
1343 :
1344 : endif
1345 :
1346 42491904 : if( jord == 3 .or. jord == 5 ) then
1347 0 : do j=js1g1,jn1g1 ! A6 needed NS
1348 0 : do i=1,im
1349 0 : a6(i,j) = D3_0*(q(i,j)+q(i,j) - (al(i,j)+ar(i,j)))
1350 : enddo
1351 : enddo
1352 : endif
1353 :
1354 42491904 : lmt = jord - 3
1355 :
1356 : ! do j=js1g1,jn1g1 ! A6, AR, AL needed NS
1357 : ! call lmppm(dm(1,j),a6(1,j),ar(1,j),al(1,j),q(1,j),im,lmt)
1358 : ! enddo
1359 :
1360 : #ifdef VECTORIZE
1361 : jan = 1
1362 : ja(1) = 1
1363 : ilow = 1
1364 : ihigh = im*(jn1g1-js1g1+1)
1365 : jlow = 1
1366 : jhigh = 1
1367 : call lmppmv(dm(1,js1g1), a6(1,js1g1), ar(1,js1g1), &
1368 : al(1,js1g1), q(1,js1g1), im*(jn1g1-js1g1+1), lmt, &
1369 : jan, ja, ilow, ihigh, jlow, jhigh, jlow, jhigh)
1370 : #else
1371 42491904 : call lmppm(dm(1,js1g1), a6(1,js1g1), ar(1,js1g1), &
1372 84983808 : al(1,js1g1), q(1,js1g1), im*(jn1g1-js1g1+1), lmt)
1373 : #endif
1374 :
1375 211131648 : do j=js2g0,jn1g1 ! flux needed N
1376 48779377920 : do i=1,im
1377 48736886016 : if(c(i,j).gt.D0_0) then
1378 23504592994 : flux(i,j) = ar(i,j-1) + D0_5*c(i,j)*(al(i,j-1) - ar(i,j-1) + &
1379 47009185988 : a6(i,j-1)*(D1_0-r23*c(i,j)) )
1380 : else
1381 25063653278 : flux(i,j) = al(i,j) - D0_5*c(i,j)*(ar(i,j) - al(i,j) + &
1382 25063653278 : a6(i,j)*(D1_0+r23*c(i,j)))
1383 : endif
1384 : enddo
1385 : enddo
1386 42491904 : return
1387 : !EOC
1388 : end subroutine fyppm
1389 : !-----------------------------------------------------------------------
1390 :
1391 : !-----------------------------------------------------------------------
1392 : !BOP
1393 : ! !IROUTINE: tpcc
1394 : !
1395 : ! !INTERFACE:
1396 344064 : subroutine tpcc(va, ymass, q, crx, cry, im, jm, ng_c, ng_d, &
1397 344064 : iord, jord, fx, fy, ffsl, cose, jfirst, jlast, &
1398 344064 : dm, qtmp, al, ar, a6 )
1399 : !-----------------------------------------------------------------------
1400 :
1401 : ! !USES:
1402 : implicit none
1403 :
1404 : ! !INPUT PARAMETERS:
1405 : integer im, jm ! Dimensions
1406 : integer ng_c !
1407 : integer ng_d !
1408 : integer jfirst, jlast ! Latitude strip
1409 : integer iord, jord ! Interpolation order in x,y
1410 : logical ffsl(jm) ! Flux-form semi-Lagrangian transport?
1411 : real (r8) cose(jm) ! Critical cosine (replicated)
1412 : real (r8) va(im,jfirst:jlast) ! Courant (unghosted like FX)
1413 : real (r8) q(im,jfirst-ng_d:jlast+ng_d) !
1414 : real (r8) crx(im,jfirst-ng_c:jlast+ng_c)
1415 : real (r8) cry(im,jfirst:jlast) ! Courant # (ghosted like FY)
1416 : real (r8) ymass(im,jfirst:jlast) ! Background y-mass-flux (ghosted like FY)
1417 :
1418 : ! Input 1D work arrays:
1419 : real (r8) dm(-im/3:im+im/3)
1420 : real (r8) qtmp(-im/3:im+im/3)
1421 : real (r8) al(-im/3:im+im/3)
1422 : real (r8) ar(-im/3:im+im/3)
1423 : real (r8) a6(-im/3:im+im/3)
1424 :
1425 : ! !OUTPUT PARAMETERS:
1426 : real (r8) fx(im,jfirst:jlast) ! Flux in x (unghosted)
1427 : real (r8) fy(im,jfirst:jlast) ! Flux in y (unghosted since iv==0)
1428 :
1429 : ! !DESCRIPTION:
1430 : ! In this routine the number
1431 : ! of north ghosted latitude min(abs(jord),2), and south ghosted
1432 : ! latitudes is XXXX
1433 : !
1434 : ! !CALLED FROM:
1435 : ! cd_core
1436 : !
1437 : ! !REVISION HISTORY:
1438 : ! SJL 99.04.13: Delivery
1439 : ! WS 99.04.13: Added jfirst:jlast concept
1440 : ! WS 99.05.10: Replaced JNP with JM, JMR with JM-1, IMR with IM
1441 : ! WS 99.05.10: Removed fvcore.h and JNP, IMH, IML definitions
1442 : ! WS 99.10.20: Pruned arrays
1443 : ! WS 00.05.14: Renamed ghost indices as per Kevin's definitions
1444 : !
1445 : !EOP
1446 : !-----------------------------------------------------------------------
1447 : !BOC
1448 : !
1449 : ! !LOCAL VARIABLES:
1450 :
1451 688128 : real (r8) adx(im,jfirst-1:jlast+2)
1452 : integer north, south
1453 : integer i, j, jp, im2, js2g0, js2gs, jn2g0, jn1g0, jn1gn
1454 688128 : real (r8) wk1v(im,jfirst-1:jlast+2)
1455 688128 : real (r8) fx1(im)
1456 688128 : real (r8) qtmpv(-im/3:im+im/3,jfirst-1:jlast+2)
1457 :
1458 344064 : im2 = im/2
1459 344064 : north = min(2,abs(jord)) ! north == 1 or 2
1460 344064 : south = north-1 ! south == 0 or 1
1461 344064 : js2g0 = max(2,jfirst)
1462 344064 : js2gs = max(2,jfirst-south)
1463 344064 : jn2g0 = min(jm-1,jlast)
1464 344064 : jn1gn = min(jm,jlast+north)
1465 344064 : jn1g0 = min(jm,jlast)
1466 :
1467 : ! This loop must be ghosted N*NG, S*NG
1468 :
1469 : call xtpv( im, ffsl, wk1v, q, crx, 1, crx, &
1470 : cose, 0, dm, qtmpv, al, ar, a6, &
1471 : jfirst, jlast, js2gs, jn1gn, jm, &
1472 : 1, jm, jfirst-1, jlast+2, &
1473 : jfirst-ng_d, jlast+ng_d, jfirst-ng_c, jlast+ng_c, &
1474 344064 : jfirst-ng_c, jlast+ng_c, jfirst-1, jlast+2)
1475 :
1476 2302272 : do j=js2gs,jn1gn
1477 :
1478 563963904 : do i=1,im-1
1479 1124011392 : adx(i,j) = q(i,j) + D0_5 * &
1480 1687975296 : (wk1v(i,j)-wk1v(i+1,j) + q(i,j)*(crx(i+1,j)-crx(i,j)))
1481 : enddo
1482 :
1483 3916416 : adx(im,j) = q(im,j) + D0_5 * &
1484 6218688 : (wk1v(im,j)-wk1v(1,j) + q(im,j)*(crx(1,j)-crx(im,j)))
1485 : enddo
1486 :
1487 344064 : call ycc(im, jm, fy, adx, cry, ymass, jord, 0,jfirst,jlast)
1488 :
1489 : ! For Scalar only!!!
1490 344064 : if ( jfirst == 1 ) then ! ( jfirst -ng_d <= 1 ) fails when
1491 : ! ng_d=3, ng_c=2, jlast-jfirst+1 = 3
1492 779520 : do i=1,im2
1493 779520 : q(i,1) = q(i+im2, 2)
1494 : enddo
1495 779520 : do i=im2+1,im
1496 779520 : q(i,1) = q(i-im2, 2)
1497 : enddo
1498 : endif
1499 :
1500 344064 : if ( jlast == jm ) then
1501 779520 : do i=1,im2
1502 779520 : fx1(i) = q(i+im2,jm)
1503 : enddo
1504 779520 : do i=im2+1,im
1505 779520 : fx1(i) = q(i-im2,jm)
1506 : enddo
1507 :
1508 1553664 : do i=1,im
1509 1553664 : if(va(i,jm) .gt. D0_0) then
1510 770789 : adx(i,jm) = q(i,jm) + D0_5*va(i,jm)*(q(i,jm-1)-q(i,jm))
1511 : else
1512 777499 : adx(i,jm) = q(i,jm) + D0_5*va(i,jm)*(q(i,jm)-fx1(i))
1513 : endif
1514 : enddo
1515 : endif
1516 :
1517 1365504 : do j=js2g0,jn2g0
1518 295540224 : do i=1,im
1519 294174720 : jp = j-va(i,j)
1520 : ! jp = j if va < 0
1521 : ! jp = j -1 if va < 0
1522 : ! q needed max(1, jfirst-1)
1523 295196160 : adx(i,j) = q(i,j) + D0_5*va(i,j)*(q(i,jp)-q(i,jp+1))
1524 : enddo
1525 : enddo
1526 :
1527 : call xtpv( im, ffsl, fx, adx, crx, iord, crx, &
1528 : cose, 0, dm, qtmpv, al, ar, a6, &
1529 : jfirst, jlast, js2g0, jn1g0, jm, &
1530 : 1, jm, jfirst, jlast, &
1531 : jfirst-1, jlast+2,jfirst-ng_c, jlast+ng_c, &
1532 344064 : jfirst-ng_c, jlast+ng_c, jfirst-1, jlast+2)
1533 :
1534 344064 : return
1535 : !EOC
1536 : end subroutine tpcc
1537 : !-----------------------------------------------------------------------
1538 :
1539 : !-----------------------------------------------------------------------
1540 : !BOP
1541 : ! !IROUTINE: ycc
1542 : !
1543 : ! !INTERFACE:
1544 688128 : subroutine ycc(im, jm, fy, q, vc, ymass, jord, iv, jfirst, jlast)
1545 : !-----------------------------------------------------------------------
1546 :
1547 : ! !USES:
1548 : implicit none
1549 :
1550 : ! !INPUT PARAMETERS:
1551 : integer im, jm ! Dimensions
1552 : integer jfirst, jlast ! Latitude strip
1553 : integer jord ! Approximation order
1554 : integer iv ! Scalar=0, Vector=1
1555 : real (r8) q(im,jfirst-1-iv:jlast+2) ! Field (N*2 S*(iv+1))
1556 : real (r8) vc(im,jfirst-iv:jlast) ! Courant (like FY)
1557 : real (r8) ymass(im,jfirst-iv:jlast) ! background mass flux
1558 :
1559 : ! !OUTPUT PARAMETERS:
1560 : real (r8) fy(im,jfirst-iv:jlast) ! Flux (S if iv=1)
1561 :
1562 : ! !DESCRIPTION:
1563 : ! Will Sawyer's note: In this routine the number
1564 : ! of ghosted latitudes NG is min(abs(jord),2). The scalar/vector
1565 : ! flag determines whether the flux FY needs to be ghosted on the
1566 : ! south. If called from CD\_CORE (iv==1) then it does, if called
1567 : ! from TPCC (iv==0) it does not.
1568 : !
1569 : ! !CALLED FROM:
1570 : ! cd_core
1571 : ! tpcc
1572 : !
1573 : ! !REVISION HISTORY:
1574 : !
1575 : ! SJL 99.04.13: Delivery
1576 : ! WS 99.04.19: Added jfirst:jlast concept
1577 : ! WS 99.04.27: DC removed as argument (local to this routine); DC on N
1578 : ! WS 99.05.10: Replaced JNP with JM, JMR with JM-1, IMR with IM
1579 : ! WS 99.05.10: Removed fvcore.h
1580 : ! WS 99.07.27: Built in tests for SP or NP
1581 : ! WS 99.09.09: Documentation; indentation; cleaning; pole treatment
1582 : ! WS 99.09.14: Loop limits
1583 : ! WS 00.05.14: Renamed ghost indices as per Kevin's definitions
1584 : !
1585 : !EOP
1586 : !---------------------------------------------------------------------
1587 : !BOC
1588 :
1589 : ! !LOCAL VARIABLES:
1590 1376256 : real (r8) dc(im,jfirst-iv:jlast+1)
1591 : real (r8) qmax, qmin
1592 : integer i, j, jt, im2, js2giv, js3giv, jn2g1, jn2g0
1593 :
1594 :
1595 688128 : im2 = im/2
1596 :
1597 688128 : js2giv = max(2,jfirst-iv)
1598 688128 : js3giv = max(3,jfirst-iv)
1599 688128 : jn2g1 = min(jm-1,jlast+1)
1600 688128 : jn2g0 = min(jm-1,jlast)
1601 :
1602 688128 : if(jord == 1) then
1603 383712 : do j=js2giv,jn2g0 ! FY needed on S*iv
1604 86120160 : do i=1,im
1605 : ! jt=j if vc > 0; jt=j+1 if vc <=0
1606 85736448 : jt = real(j+1,r8) - vc(i,j) ! VC ghosted like fy
1607 86034144 : fy(i,j) = q(i,jt)*ymass(i,j) ! ymass ghosted like fy
1608 : enddo ! q ghosted N*1, S*iv
1609 : enddo
1610 :
1611 : else
1612 :
1613 3269280 : do j=js3giv,jn2g1 ! dc needed N*1, S*iv
1614 771413664 : do i=1,im
1615 770811552 : dc(i,j) = D0_25*(q(i,j+1)-q(i,j-1)) ! q ghosted N*2, S*(iv+1)
1616 : enddo
1617 : enddo
1618 :
1619 602112 : if(iv.eq.0) then
1620 : ! Scalar.
1621 :
1622 : ! WS 99.07.27 : Split loops in SP and NP regions, added SP/NP tests
1623 :
1624 301056 : if ( jfirst-iv <= 2 ) then
1625 682080 : do i=1,im2
1626 682080 : dc(i, 2) = D0_25 * ( q(i,3) - q(i+im2,2) )
1627 : enddo
1628 :
1629 682080 : do i=im2+1,im
1630 682080 : dc(i, 2) = D0_25 * ( q(i,3) - q(i-im2,2) )
1631 : enddo
1632 : endif
1633 :
1634 301056 : if ( jlast == jm ) then
1635 682080 : do i=1,im2
1636 682080 : dc(i,jm) = D0_25 * ( q(i+im2,jm) - q(i,jm-1) )
1637 : enddo
1638 :
1639 682080 : do i=im2+1,im
1640 682080 : dc(i,jm) = D0_25 * ( q(i-im2,jm) - q(i,jm-1) )
1641 : enddo
1642 : endif
1643 :
1644 : else
1645 : ! Vector winds
1646 :
1647 : ! WS 99.07.27 : Split loops in SP and NP regions, added SP/NP tests
1648 :
1649 301056 : if ( jfirst-iv <= 2 ) then
1650 682080 : do i=1,im2
1651 682080 : dc(i, 2) = D0_25 * ( q(i,3) + q(i+im2,2) )
1652 : enddo
1653 :
1654 682080 : do i=im2+1,im
1655 682080 : dc(i, 2) = D0_25 * ( q(i,3) + q(i-im2,2) )
1656 : enddo
1657 : endif
1658 :
1659 301056 : if ( jlast == jm ) then
1660 682080 : do i=1,im2
1661 682080 : dc(i,jm) = -D0_25 * ( q(i,jm-1) + q(i+im2,jm) )
1662 : enddo
1663 :
1664 682080 : do i=im2+1,im
1665 682080 : dc(i,jm) = -D0_25 * ( q(i,jm-1) + q(i-im2,jm) )
1666 : enddo
1667 : endif
1668 :
1669 : endif
1670 :
1671 602112 : if( jord > 0 ) then
1672 : ! Monotonic constraint
1673 0 : do j=js3giv,jn2g1 ! DC needed N*1, S*iv
1674 0 : do i=1,im ! P ghosted N*2, S*(iv+1)
1675 0 : qmax = max(q(i,j-1),q(i,j),q(i,j+1)) - q(i,j)
1676 0 : qmin = q(i,j) - min(q(i,j-1),q(i,j),q(i,j+1))
1677 0 : dc(i,j) = sign(min(abs(dc(i,j)),qmin,qmax),dc(i,j))
1678 : enddo
1679 : enddo
1680 : !
1681 : ! WS 99.08.03 : Following loop split into SP and NP part
1682 : !
1683 0 : if ( jfirst-iv <= 2 ) then
1684 0 : do i=1,im
1685 0 : dc(i, 2) = D0_0
1686 : enddo
1687 : endif
1688 0 : if ( jlast == jm ) then
1689 0 : do i=1,im
1690 0 : dc(i,jm) = D0_0
1691 : enddo
1692 : endif
1693 : endif
1694 :
1695 2685984 : do j=js2giv,jn2g0 ! fy needed S*iv
1696 602841120 : do i=1,im
1697 600155136 : jt = real(j+1,r8) - vc(i,j) ! vc, ymass ghosted like fy
1698 602239008 : fy(i,j) = (q(i,jt)+(sign(D1_0,vc(i,j))-vc(i,j))*dc(i,jt))*ymass(i,j)
1699 : enddo
1700 : enddo
1701 : endif
1702 688128 : return
1703 : !EOC
1704 : end subroutine ycc
1705 : !-----------------------------------------------------------------------
1706 :
1707 : #ifdef VECTORIZE
1708 : !-----------------------------------------------------------------------
1709 : !BOP
1710 : ! !IROUTINE: xtpv
1711 : !
1712 : ! !INTERFACE:
1713 : subroutine xtpv(im, ffslv, fxv, qv, cv, iord, mfxv, &
1714 : cosav, id, dm, qtmpv, al, ar, a6, &
1715 : jfirst, jlast, jlow, jhigh, jm, &
1716 : jl2, jh2, jl3, jh3, &
1717 : jl4, jh4, jl5, jh5, &
1718 : jl7, jh7, jl11, jh11)
1719 : !-----------------------------------------------------------------------
1720 :
1721 : implicit none
1722 :
1723 : ! !INPUT PARAMETERS:
1724 : integer id ! ID = 0: density (mfx = C)
1725 : ! ID = 1: mixing ratio (mfx is mass flux)
1726 :
1727 : integer im ! Total longitudes
1728 : real (r8) cv(im,jl5:jh5) ! Courant numbers
1729 : real (r8) qv(im,jl4:jh4)
1730 : real (r8) mfxv(im,jl7:jh7)
1731 : logical ffslv(jl2:jh2)
1732 : integer iord
1733 : integer jfirst, jlast, jlow, jhigh, jm
1734 : integer jl2, jh2, jl3, jh3, jl4, jh4, jl5, jh5
1735 : integer jl7, jh7, jl11, jh11
1736 : real (r8) cosav(jm)
1737 :
1738 : ! !INPUT/OUTPUT PARAMETERS:
1739 : real (r8) qtmpv(-im/3:im+im/3,jl11:jh11) ! Input work arrays:
1740 : real (r8) dm(-im/3:im+im/3)
1741 : real (r8) al(-im/3:im+im/3)
1742 : real (r8) ar(-im/3:im+im/3)
1743 : real (r8) a6(-im/3:im+im/3)
1744 :
1745 : ! !OUTPUT PARAMETERS:
1746 : real (r8) fxv(im,jl3:jh3)
1747 :
1748 : ! !DESCRIPTION:
1749 : !
1750 : !
1751 : ! !REVISION HISTORY:
1752 : ! 99.01.01 Lin Creation
1753 : ! 01.03.27 Sawyer Additional ProTeX documentation
1754 : !
1755 : !EOP
1756 : !-----------------------------------------------------------------------
1757 : !BOC
1758 :
1759 : ! Local:
1760 : real (r8) cos_upw !critical cosine for upwind
1761 : real (r8) cos_van !critical cosine for van Leer
1762 : real (r8) cos_ppm !critical cosine for ppm
1763 :
1764 : parameter (cos_upw = D0_05) !roughly at 87 deg.
1765 : parameter (cos_van = D0_25) !roughly at 75 deg.
1766 : parameter (cos_ppm = D0_25)
1767 :
1768 : real (r8) r24
1769 : parameter (r24 = D1_0/D24_0)
1770 :
1771 : integer i, imp, j
1772 : real (r8) qmax, qmin
1773 : real (r8) rut, tmp
1774 : real (r8) dmv(-im/3:im+im/3,jlow:jhigh)
1775 : integer iu, itmp, ist
1776 : integer isave(im,jlow:jhigh)
1777 : integer iuwv(jlow:jhigh), iuev(jlow:jhigh)
1778 :
1779 : integer jatn, jafn, ja
1780 : integer jat(jhigh-jlow+1), jaf(jhigh-jlow+1)
1781 : integer jattn, jatfn, jaftn, jaffn
1782 : integer jatt(jhigh-jlow+1), jatf(jhigh-jlow+1)
1783 : integer jaft(jhigh-jlow+1), jaff(jhigh-jlow+1)
1784 : integer jatftn, jatffn
1785 : integer jatft(jhigh-jlow+1), jatff(jhigh-jlow+1)
1786 : integer jafftn1, jafffn1
1787 : integer jafft1(jhigh-jlow+1), jafff1(jhigh-jlow+1)
1788 : integer jafftn2, jafffn2
1789 : integer jafft2(jhigh-jlow+1), jafff2(jhigh-jlow+1)
1790 : real (r8) qsum((-im/3)-1:im+im/3,jlow:jhigh) ! work arrays
1791 :
1792 :
1793 : jatn = 0
1794 : jafn = 0
1795 : jattn = 0
1796 : jatfn = 0
1797 : jaftn = 0
1798 : jaffn = 0
1799 : jatftn = 0
1800 : jatffn = 0
1801 : jafftn1 = 0
1802 : jafffn1 = 0
1803 : jafftn2 = 0
1804 : jafffn2 = 0
1805 : !call ftrace_region_begin("xtpv_1")
1806 : do j = jlow, jhigh
1807 : if (ffslv(j)) then
1808 : jatn = jatn + 1
1809 : jat(jatn) = j
1810 : if( iord == 1 .or. cosav(j) < cos_upw) then
1811 : jattn = jattn + 1
1812 : jatt(jattn) = j
1813 : else
1814 : jatfn = jatfn + 1
1815 : jatf(jatfn) = j
1816 : if(iord .ge. 3 .and. cosav(j) .gt. cos_ppm) then
1817 : jatftn = jatftn + 1
1818 : jatft(jatftn) = j
1819 : else
1820 : jatffn = jatffn + 1
1821 : jatff(jatffn) = j
1822 : endif
1823 : endif
1824 : else
1825 : jafn = jafn + 1
1826 : jaf(jafn) = j
1827 : if( iord == 1 .or. cosav(j) < cos_upw) then
1828 : jaftn = jaftn + 1
1829 : jaft(jaftn) = j
1830 : else
1831 : jaffn = jaffn + 1
1832 : jaff(jaffn) = j
1833 : if(iord > 0 .or. cosav(j) < cos_van) then
1834 : jafftn1 = jafftn1 + 1
1835 : jafft1(jafftn1) = j
1836 : else
1837 : jafffn1 = jafffn1 + 1
1838 : jafff1(jafffn1) = j
1839 : endif
1840 : if( abs(iord).eq.2 .or. cosav(j) .lt. cos_van ) then
1841 : jafftn2 = jafftn2 + 1
1842 : jafft2(jafftn2) = j
1843 : else
1844 : jafffn2 = jafffn2 + 1
1845 : jafff2(jafffn2) = j
1846 : endif
1847 : endif
1848 : endif
1849 : enddo
1850 : !call ftrace_region_end("xtpv_1")
1851 :
1852 : imp = im + 1
1853 :
1854 : do j = jlow, jhigh
1855 : do i=1,im
1856 : qtmpv(i,j) = qv(i,j)
1857 : enddo
1858 : enddo
1859 :
1860 : ! Flux-Form Semi-Lagrangian transport
1861 :
1862 : !call ftrace_region_begin("xtpv_2")
1863 : do ja = 1, jatn
1864 : j = jat(ja)
1865 :
1866 : ! Figure out ghost zone for the western edge:
1867 : iuwv(j) = -cv(1,j)
1868 : iuwv(j) = min(0, iuwv(j))
1869 :
1870 : do i=iuwv(j), 0
1871 : qtmpv(i,j) = qv(im+i,j)
1872 : enddo
1873 :
1874 : ! Figure out ghost zone for the eastern edge:
1875 : iuev(j) = im - cv(im,j)
1876 : iuev(j) = max(imp, iuev(j))
1877 :
1878 : do i=imp, iuev(j)
1879 : qtmpv(i,j) = qv(i-im,j)
1880 : enddo
1881 :
1882 : enddo
1883 : !call ftrace_region_end("xtpv_2")
1884 :
1885 : !call ftrace_region_begin("xtpv_3")
1886 : do ja = 1, jattn
1887 : j = jatt(ja)
1888 :
1889 : do i=1,im
1890 : iu = cv(i,j)
1891 : if(cv(i,j) .le. D0_0) then
1892 : itmp = i - iu
1893 : isave(i,j) = itmp - 1
1894 : else
1895 : itmp = i - iu - 1
1896 : isave(i,j) = itmp + 1
1897 : endif
1898 : fxv(i,j) = (cv(i,j)-iu) * qtmpv(itmp,j)
1899 : enddo
1900 :
1901 : enddo
1902 : !call ftrace_region_end("xtpv_3")
1903 :
1904 : !call ftrace_region_begin("xtpv_4")
1905 : do ja = 1, jatfn
1906 : j = jatf(ja)
1907 :
1908 : do i=1,im
1909 : ! 2nd order slope
1910 : tmp = D0_25*(qtmpv(i+1,j) - qtmpv(i-1,j))
1911 : qmax = max(qtmpv(i-1,j), qtmpv(i,j), qtmpv(i+1,j)) - qtmpv(i,j)
1912 : qmin = qtmpv(i,j) - min(qtmpv(i-1,j), qtmpv(i,j), qtmpv(i+1,j))
1913 : dmv(i,j) = sign(min(abs(tmp),qmax,qmin), tmp)
1914 : enddo
1915 :
1916 : do i=iuwv(j), 0
1917 : dmv(i,j) = dmv(im+i,j)
1918 : enddo
1919 :
1920 : do i=imp, iuev(j)
1921 : dmv(i,j) = dmv(i-im,j)
1922 : enddo
1923 :
1924 : enddo
1925 : !call ftrace_region_end("xtpv_4")
1926 :
1927 : call fxppmv(im, cv, mfxv, qtmpv, dmv, fxv, iord, &
1928 : iuwv, iuev, ffslv, isave, jatftn, jatft, jlow, jhigh, &
1929 : jl2, jh2, jl3, jh3, jl5, jh5, jl7, jh7, jl11, jh11)
1930 :
1931 : !call ftrace_region_begin("xtpv_5")
1932 : do ja = 1, jatffn
1933 : j = jatff(ja)
1934 :
1935 : do i=1,im
1936 : iu = cv(i,j)
1937 : rut = cv(i,j) - iu
1938 : if(cv(i,j) .le. D0_0) then
1939 : itmp = i - iu
1940 : isave(i,j) = itmp - 1
1941 : fxv(i,j) = rut*(qtmpv(itmp,j)-dmv(itmp,j)*(D1_0+rut))
1942 : else
1943 : itmp = i - iu - 1
1944 : isave(i,j) = itmp + 1
1945 : fxv(i,j) = rut*(qtmpv(itmp,j)+dmv(itmp,j)*(D1_0-rut))
1946 : endif
1947 : enddo
1948 :
1949 : enddo
1950 : !call ftrace_region_end("xtpv_5")
1951 :
1952 : !call ftrace_region_begin("xtpv_6")
1953 : do ja = 1, jatn
1954 : j = jat(ja)
1955 : qsum(iuwv(j)-1,j) = D0_0
1956 : do i = iuwv(j), iuev(j)
1957 : qsum(i,j) = qsum(i-1,j) + qtmpv(i,j)
1958 : end do
1959 :
1960 : !
1961 : ! The boolean terms:
1962 : ! a) .and. (isave(i,j) < i)
1963 : ! b) .and. (i <= isave(i,j))
1964 : ! are needed in the IF statements below because I cannot prove to myself
1965 : ! that the relationship between i and isave are such to guarantee that
1966 : ! there is always at least one term from qsum (qtmpv,j) contributed to fxv.
1967 : !
1968 :
1969 : do i=1,im
1970 : if(cv(i,j) >= D1_0 .and. (isave(i,j) < i) ) then
1971 : fxv(i,j) = fxv(i,j) + (qsum(i-1,j) - qsum(isave(i,j) - 1,j))
1972 : else if (cv(i,j) <= -D1_0 .and. (i <= isave(i,j)) ) then
1973 : fxv(i,j) = fxv(i,j) - (qsum(isave(i,j),j) - qsum(i-1,j))
1974 : end if
1975 : end do
1976 :
1977 : if(id .ne. 0) then
1978 : do i=1,im
1979 : fxv(i,j) = fxv(i,j)*mfxv(i,j)
1980 : enddo
1981 : endif
1982 :
1983 : enddo
1984 : !call ftrace_region_end("xtpv_6")
1985 :
1986 : ! Regular PPM (Eulerian without FFSL extension)
1987 :
1988 : !call ftrace_region_begin("xtpv_7")
1989 : do ja = 1, jafn
1990 : j = jaf(ja)
1991 :
1992 : qtmpv(imp,j) = qv(1,j)
1993 : qtmpv( 0,j) = qv(im,j)
1994 : enddo
1995 :
1996 : do ja = 1, jaftn
1997 : j = jaft(ja)
1998 :
1999 : do i=1,im
2000 : iu = real(i,r8) - cv(i,j)
2001 : fxv(i,j) = mfxv(i,j)*qtmpv(iu,j)
2002 : enddo
2003 : enddo
2004 :
2005 : do ja = 1, jaffn
2006 : j = jaff(ja)
2007 :
2008 : qtmpv(-1,j) = qv(im-1,j)
2009 : qtmpv(imp+1,j) = qv(2,j)
2010 :
2011 : enddo
2012 : !call ftrace_region_end("xtpv_7")
2013 :
2014 : !call ftrace_region_begin("xtpv_8")
2015 : do ja = 1, jafftn1
2016 : j = jafft1(ja)
2017 :
2018 : ! In-line xmist
2019 :
2020 : do i=1,im
2021 : dmv(i,j) = r24*(D8_0*(qtmpv(i+1,j) - qtmpv(i-1,j)) + qtmpv(i-2,j) - qtmpv(i+2,j))
2022 : enddo
2023 :
2024 : ! Apply monotonicity constraint (Lin et al. 1994, MWR)
2025 : do i=1,im
2026 : qmax = max( qtmpv(i-1,j), qtmpv(i,j), qtmpv(i+1,j) ) - qtmpv(i,j)
2027 : qmin = qtmpv(i,j) - min( qtmpv(i-1,j), qtmpv(i,j), qtmpv(i+1,j) )
2028 : dmv(i,j) = sign( min(abs(dmv(i,j)), qmax, qmin), dmv(i,j) )
2029 : enddo
2030 :
2031 : enddo
2032 : !call ftrace_region_end("xtpv_8")
2033 :
2034 : !call ftrace_region_begin("xtpv_9")
2035 : do ja = 1, jafffn1
2036 : j = jafff1(ja)
2037 :
2038 : ! In-line xmist
2039 :
2040 : if(iord .le. 2) then
2041 : do i=1,im
2042 : dmv(i,j) = r24*(D8_0*(qtmpv(i+1,j) - qtmpv(i-1,j)) + qtmpv(i-2,j) - qtmpv(i+2,j))
2043 : enddo
2044 : else
2045 : do i=1,im
2046 : dmv(i,j) = D0_25*(qtmpv(i+1,j) - qtmpv(i-1,j))
2047 : enddo
2048 : endif
2049 :
2050 : if( iord >= 0 ) then
2051 :
2052 : ! Apply monotonicity constraint (Lin et al. 1994, MWR)
2053 : do i=1,im
2054 : qmax = max( qtmpv(i-1,j), qtmpv(i,j), qtmpv(i+1,j) ) - qtmpv(i,j)
2055 : qmin = qtmpv(i,j) - min( qtmpv(i-1,j), qtmpv(i,j), qtmpv(i+1,j) )
2056 : dmv(i,j) = sign( min(abs(dmv(i,j)), qmax, qmin), dmv(i,j) )
2057 : enddo
2058 : endif
2059 :
2060 : enddo
2061 : !call ftrace_region_end("xtpv_9")
2062 :
2063 : !call ftrace_region_begin("xtpv_10")
2064 : do ja = 1, jaffn
2065 : j = jaff(ja)
2066 :
2067 : dmv(0,j) = dmv(im,j)
2068 :
2069 : enddo
2070 : !call ftrace_region_end("xtpv_10")
2071 :
2072 : !call ftrace_region_begin("xtpv_11")
2073 : do ja = 1, jafftn2
2074 : j = jafft2(ja)
2075 :
2076 : do i=1,im
2077 : iu = real(i,r8) - cv(i,j)
2078 : fxv(i,j) = mfxv(i,j)*(qtmpv(iu,j)+dmv(iu,j)*(sign(D1_0,cv(i,j))-cv(i,j)))
2079 : enddo
2080 :
2081 : enddo
2082 : !call ftrace_region_end("xtpv_11")
2083 :
2084 : call fxppmv(im, cv, mfxv, qtmpv, dmv, fxv, iord, &
2085 : iuwv, iuev, ffslv, isave, jafffn2, jafff2, jlow, jhigh, &
2086 : jl2, jh2, jl3, jh3, jl5, jh5, jl7, jh7, jl11, jh11)
2087 :
2088 : return
2089 : !EOC
2090 : end subroutine xtpv
2091 : !-----------------------------------------------------------------------
2092 :
2093 : !-----------------------------------------------------------------------
2094 : !BOP
2095 : ! !IROUTINE: fxppmv
2096 : !
2097 : ! !INTERFACE:
2098 :
2099 : subroutine fxppmv(im, c, mfx, p, dm, fx, iord, &
2100 : iuw, iue, ffsl, isave, jan, ja, jlow, jhigh, &
2101 : jl2, jh2, jl3, jh3, jl5, jh5, jl7, jh7, jl11, jh11)
2102 : !-----------------------------------------------------------------------
2103 : !
2104 : ! !USES:
2105 : implicit none
2106 :
2107 : ! !INPUT PARAMETERS:
2108 : integer jan, ja(jan), jlow, jhigh, jj, j
2109 : integer jl2, jh2, jl3, jh3, jl5, jh5, jl7, jh7, jl11, jh11
2110 : integer im, iord
2111 : real (r8) c(im,jl5:jh5)
2112 : real (r8) p(-im/3:im+im/3,jl11:jh11)
2113 : real (r8) dm(-im/3:im+im/3,jlow:jhigh)
2114 : real (r8) mfx(im,jl7:jh7)
2115 : integer iuw(jlow:jhigh), iue(jlow:jhigh)
2116 : logical ffsl(jl2:jh2)
2117 : integer isave(im,jlow:jhigh)
2118 :
2119 : ! !OUTPUT PARAMETERS:
2120 : real (r8) fx(im,jl3:jh3)
2121 :
2122 : ! !DESCRIPTION:
2123 : !
2124 : !
2125 : ! !REVISION HISTORY:
2126 : ! 99.01.01 Lin Creation
2127 : ! 01.03.27 Sawyer Additional ProTeX documentation
2128 : !
2129 : !EOP
2130 : !-----------------------------------------------------------------------
2131 : !BOC
2132 : !
2133 : ! !LOCAL VARIABLES:
2134 : real (r8) r3, r23
2135 : parameter ( r3 = D1_0/D3_0, r23 = D2_0/D3_0 )
2136 :
2137 : integer i, lmt
2138 : integer iu, itmp
2139 : real (r8) ru
2140 : logical steep
2141 : real (r8) al(-im/3:im+im/3,jlow:jhigh)
2142 : real (r8) ar(-im/3:im+im/3,jlow:jhigh)
2143 : real (r8) a6(-im/3:im+im/3,jlow:jhigh)
2144 :
2145 : integer jbtn, jbfn
2146 : integer jbt(jan), jbf(jan)
2147 : integer ilow, ihigh
2148 :
2149 : ilow = -im/3
2150 : ihigh = im + im/3
2151 :
2152 : if( iord == 6 ) then
2153 : steep = .true.
2154 : else
2155 : steep = .false.
2156 : endif
2157 :
2158 : do jj = 1, jan
2159 : j = ja(jj)
2160 :
2161 : do i=1,im
2162 : al(i,j) = D0_5*(p(i-1,j)+p(i,j)) + (dm(i-1,j) - dm(i,j))*r3
2163 : enddo
2164 :
2165 : enddo
2166 :
2167 : if (steep) then
2168 :
2169 : call steepxv( im, p, al, dm, jan, ja, jlow, jhigh, jl11, jh11 )
2170 :
2171 : endif
2172 :
2173 : do jj = 1, jan
2174 : j = ja(jj)
2175 :
2176 : do i=1,im-1
2177 : ar(i,j) = al(i+1,j)
2178 : enddo
2179 : ar(im,j) = al(1,j)
2180 :
2181 : enddo
2182 :
2183 : if(iord == 7) then
2184 :
2185 : call huynhv(im, ar, al, p, a6, dm, jan, ja, jlow, jhigh, jl11, jh11 )
2186 :
2187 : else
2188 :
2189 : if(iord .eq. 3 .or. iord .eq. 5) then
2190 :
2191 : do jj = 1, jan
2192 : j = ja(jj)
2193 :
2194 : do i=1,im
2195 : a6(i,j) = D3_0*(p(i,j)+p(i,j) - (al(i,j)+ar(i,j)))
2196 : enddo
2197 :
2198 : enddo
2199 : endif
2200 :
2201 : lmt = iord - 3
2202 :
2203 : call lmppmv( dm, a6, ar, al, p, im, lmt, jan, ja, ilow, ihigh, &
2204 : jlow, jhigh, jl11, jh11 )
2205 :
2206 : endif
2207 :
2208 : jbtn = 0
2209 : jbfn = 0
2210 : do jj = 1, jan
2211 : j = ja(jj)
2212 : if( ffsl(j) ) then
2213 : jbtn = jbtn + 1
2214 : jbt(jbtn) = j
2215 : else
2216 : jbfn = jbfn + 1
2217 : jbf(jbfn) = j
2218 : endif
2219 : enddo
2220 :
2221 : do jj = 1, jbtn
2222 : j = jbt(jj)
2223 :
2224 : do i=iuw(j), 0
2225 : al(i,j) = al(im+i,j)
2226 : ar(i,j) = ar(im+i,j)
2227 : a6(i,j) = a6(im+i,j)
2228 : enddo
2229 :
2230 : do i=im+1, iue(j)
2231 : al(i,j) = al(i-im,j)
2232 : ar(i,j) = ar(i-im,j)
2233 : a6(i,j) = a6(i-im,j)
2234 : enddo
2235 :
2236 : do i=1,im
2237 : iu = c(i,j)
2238 : ru = c(i,j) - iu
2239 : if(c(i,j) .gt. D0_0) then
2240 : itmp = i - iu - 1
2241 : isave(i,j) = itmp + 1
2242 : fx(i,j) = ru*(ar(itmp,j)+D0_5*ru*(al(itmp,j)-ar(itmp,j) + &
2243 : a6(itmp,j)*(D1_0-r23*ru)) )
2244 : else
2245 : itmp = i - iu
2246 : isave(i,j) = itmp - 1
2247 : fx(i,j) = ru*(al(itmp,j)-D0_5*ru*(ar(itmp,j)-al(itmp,j) + &
2248 : a6(itmp,j)*(D1_0+r23*ru)) )
2249 : endif
2250 : enddo
2251 :
2252 : enddo
2253 :
2254 : do jj = 1, jbfn
2255 : j = jbf(jj)
2256 :
2257 : al(0,j) = al(im,j)
2258 : ar(0,j) = ar(im,j)
2259 : a6(0,j) = a6(im,j)
2260 : do i=1,im
2261 : if(c(i,j) .gt. D0_0) then
2262 : fx(i,j) = ar(i-1,j) + D0_5*c(i,j)*(al(i-1,j) - ar(i-1,j) + &
2263 : a6(i-1,j)*(D1_0-r23*c(i,j)) )
2264 : else
2265 : fx(i,j) = al(i,j) - D0_5*c(i,j)*(ar(i,j) - al(i,j) + &
2266 : a6(i,j)*(D1_0+r23*c(i,j)))
2267 : endif
2268 : fx(i,j) = mfx(i,j) * fx(i,j)
2269 : enddo
2270 :
2271 : enddo
2272 :
2273 : return
2274 : !EOC
2275 : end subroutine fxppmv
2276 : !-----------------------------------------------------------------------
2277 :
2278 : !-----------------------------------------------------------------------
2279 : !BOP
2280 : ! !IROUTINE: steepxv
2281 : !
2282 : ! !INTERFACE:
2283 : subroutine steepxv(im, p, al, dm, jan, ja, jlow, jhigh, jl11, jh11 )
2284 : !-----------------------------------------------------------------------
2285 :
2286 : ! !USES:
2287 : implicit none
2288 :
2289 : ! !INPUT PARAMETERS:
2290 : integer im
2291 : integer jan, ja(jan), jlow, jhigh, jl11, jh11
2292 : real (r8) p(-im/3:im+im/3,jl11:jh11)
2293 : real (r8) dm(-im/3:im+im/3,jlow:jhigh)
2294 :
2295 : ! !INPUT/OUTPUT PARAMETERS:
2296 : real (r8) al(im,jlow:jhigh)
2297 :
2298 : ! !DESCRIPTION:
2299 : !
2300 : !
2301 : ! !REVISION HISTORY:
2302 : ! 99.01.01 Lin Creation
2303 : ! 01.03.27 Sawyer Additional ProTeX documentation
2304 : !
2305 : !EOP
2306 : !-----------------------------------------------------------------------
2307 : !BOC
2308 : !
2309 : ! !LOCAL VARIABLES:
2310 : integer i, jj, j
2311 : real (r8) r3
2312 : parameter ( r3 = D1_0/D3_0 )
2313 :
2314 : real (r8) dh(0:im,jlow:jhigh)
2315 : real (r8) d2(0:im+1,jlow:jhigh)
2316 : real (r8) eta(0:im,jlow:jhigh)
2317 : real (r8) xxx, bbb, ccc
2318 :
2319 : do jj = 1, jan
2320 : j = ja(jj)
2321 :
2322 : do i=0,im
2323 : dh(i,j) = p(i+1,j) - p(i,j)
2324 : enddo
2325 :
2326 : ! Needs dh(0:im,j)
2327 : do i=1,im
2328 : d2(i,j) = dh(i,j) - dh(i-1,j)
2329 : enddo
2330 : d2(0,j) = d2(im,j)
2331 : d2(im+1,j) = d2(1,j)
2332 :
2333 : ! needs p(-1:im+2,j), d2(0:im+1,j)
2334 : do i=1,im
2335 : if( d2(i+1,j)*d2(i-1,j).lt.D0_0 .and. p(i+1,j).ne.p(i-1,j) ) then
2336 : xxx = D1_0 - D0_5 * ( p(i+2,j) - p(i-2,j) ) / ( p(i+1,j) - p(i-1,j) )
2337 : eta(i,j) = max(D0_0, min(xxx, D0_5) )
2338 : else
2339 : eta(i,j) = D0_0
2340 : endif
2341 : enddo
2342 :
2343 : eta(0,j) = eta(im,j)
2344 :
2345 : ! needs eta(0:im,j), dh(0:im-1,j), dm(0:im,j)
2346 : do i=1,im
2347 : bbb = ( D2_0*eta(i,j ) - eta(i-1,j) ) * dm(i-1,j)
2348 : ccc = ( D2_0*eta(i-1,j) - eta(i,j ) ) * dm(i,j )
2349 : al(i,j) = al(i,j) + D0_5*( eta(i-1,j) - eta(i,j)) * dh(i-1,j) + (bbb - ccc) * r3
2350 : enddo
2351 :
2352 : enddo
2353 :
2354 : return
2355 : !EOC
2356 : end subroutine steepxv
2357 : !-----------------------------------------------------------------------
2358 :
2359 : !-----------------------------------------------------------------------
2360 : !BOP
2361 : ! !IROUTINE: huynhv --- Enforce Huynh's 2nd constraint in 1D periodic domain
2362 : !
2363 : ! !INTERFACE:
2364 : subroutine huynhv(im, ar, al, p, d2, d1, jan, ja, jlow, jhigh, jl11, jh11)
2365 : !-----------------------------------------------------------------------
2366 :
2367 : ! !USES:
2368 :
2369 : implicit none
2370 :
2371 : ! !INPUT PARAMETERS:
2372 : integer im
2373 : integer jan, ja(jan), jlow, jhigh, jl11, jh11
2374 : real(r8) p(im,jl11:jh11)
2375 :
2376 : ! !OUTPUT PARAMETERS:
2377 : real(r8) ar(im,jlow:jhigh)
2378 : real(r8) al(im,jlow:jhigh)
2379 : real(r8) d2(im,jlow:jhigh)
2380 : real(r8) d1(im,jlow:jhigh)
2381 :
2382 : ! !DESCRIPTION:
2383 : !
2384 : ! Enforce Huynh's 2nd constraint in 1D periodic domain
2385 : !
2386 : ! !REVISION HISTORY:
2387 : ! 99.01.01 Lin Creation
2388 : ! 01.03.27 Sawyer Additional ProTeX documentation
2389 : !
2390 : !EOP
2391 : !-----------------------------------------------------------------------
2392 : !BOC
2393 : !
2394 : ! !LOCAL VARIABLES:
2395 : integer i, jj, j
2396 : real(r8) pmp
2397 : real(r8) lac
2398 : real(r8) pmin
2399 : real(r8) pmax
2400 :
2401 : do jj = 1, jan
2402 : j = ja(jj)
2403 :
2404 : ! Compute d1 and d2
2405 : d1(1,j) = p(1,j) - p(im,j)
2406 : do i=2,im
2407 : d1(i,j) = p(i,j) - p(i-1,j)
2408 : enddo
2409 :
2410 : do i=1,im-1
2411 : d2(i,j) = d1(i+1,j) - d1(i,j)
2412 : enddo
2413 : d2(im,j) = d1(1,j) - d1(im,j)
2414 :
2415 : ! Constraint for AR
2416 : ! i = 1
2417 : pmp = p(1,j) + D2_0 * d1(1,j)
2418 : lac = p(1,j) + D0_5 * (d1(1,j)+d2(im,j)) + d2(im,j)
2419 : pmin = min(p(1,j), pmp, lac)
2420 : pmax = max(p(1,j), pmp, lac)
2421 : ar(1,j) = min(pmax, max(ar(1,j), pmin))
2422 :
2423 : do i=2, im
2424 : pmp = p(i,j) + D2_0*d1(i,j)
2425 : lac = p(i,j) + D0_5*(d1(i,j)+d2(i-1,j)) + d2(i-1,j)
2426 : pmin = min(p(i,j), pmp, lac)
2427 : pmax = max(p(i,j), pmp, lac)
2428 : ar(i,j) = min(pmax, max(ar(i,j), pmin))
2429 : enddo
2430 :
2431 : ! Constraint for AL
2432 : do i=1, im-1
2433 : pmp = p(i,j) - D2_0*d1(i+1,j)
2434 : lac = p(i,j) + D0_5*(d2(i+1,j)-d1(i+1,j)) + d2(i+1,j)
2435 : pmin = min(p(i,j), pmp, lac)
2436 : pmax = max(p(i,j), pmp, lac)
2437 : al(i,j) = min(pmax, max(al(i,j), pmin))
2438 : enddo
2439 :
2440 : ! i=im
2441 : i = im
2442 : pmp = p(im,j) - D2_0*d1(1,j)
2443 : lac = p(im,j) + D0_5*(d2(1,j)-d1(1,j)) + d2(1,j)
2444 : pmin = min(p(im,j), pmp, lac)
2445 : pmax = max(p(im,j), pmp, lac)
2446 : al(im,j) = min(pmax, max(al(im,j), pmin))
2447 :
2448 : ! compute A6 (d2)
2449 : do i=1, im
2450 : d2(i,j) = D3_0*(p(i,j)+p(i,j) - (al(i,j)+ar(i,j)))
2451 : enddo
2452 :
2453 : enddo
2454 :
2455 : return
2456 : !EOC
2457 : end subroutine huynhv
2458 : !-----------------------------------------------------------------------
2459 :
2460 : !-----------------------------------------------------------------------
2461 : !BOP
2462 : ! !IROUTINE: lmppmv
2463 : !
2464 : ! !INTERFACE:
2465 : subroutine lmppmv(dm, a6, ar, al, p, im, lmt, jan, ja, &
2466 : ilow, ihigh, jlow, jhigh, jl11, jh11)
2467 : !-----------------------------------------------------------------------
2468 :
2469 : implicit none
2470 :
2471 : ! !INPUT PARAMETERS:
2472 : integer im ! Total longitudes
2473 : integer jan, ja(jan), ilow, ihigh, jlow, jhigh, jl11, jh11
2474 : integer lmt ! LMT = 0: full monotonicity
2475 : ! LMT = 1: Improved and simplified full monotonic constraint
2476 : ! LMT = 2: positive-definite constraint
2477 : ! LMT = 3: Quasi-monotone constraint
2478 : real(r8) p(ilow:ihigh,jl11:jh11)
2479 : real(r8) dm(ilow:ihigh,jlow:jhigh)
2480 :
2481 : ! !OUTPUT PARAMETERS:
2482 : real(r8) a6(ilow:ihigh,jlow:jhigh)
2483 : real(r8) ar(ilow:ihigh,jlow:jhigh)
2484 : real(r8) al(ilow:ihigh,jlow:jhigh)
2485 :
2486 : ! !DESCRIPTION:
2487 : !
2488 : !
2489 : ! !REVISION HISTORY:
2490 : ! 99.01.01 Lin Creation
2491 : ! 01.03.27 Sawyer Additional ProTeX documentation
2492 : !
2493 : !EOP
2494 : !-----------------------------------------------------------------------
2495 : !BOC
2496 : !
2497 : ! !LOCAL VARIABLES:
2498 : real (r8) r12
2499 : parameter ( r12 = D1_0/D12_0 )
2500 :
2501 : real (r8) da1, da2, fmin, a6da
2502 : real (r8) dr, dl
2503 :
2504 : integer i, jj, j
2505 :
2506 : ! LMT = 0: full monotonicity
2507 : ! LMT = 1: Improved and simplified full monotonic constraint
2508 : ! LMT = 2: positive-definite constraint
2509 : ! LMT = 3: Quasi-monotone constraint
2510 :
2511 : if( lmt == 0 ) then
2512 :
2513 : ! Full constraint
2514 :
2515 : do jj = 1, jan
2516 : j = ja(jj)
2517 :
2518 : do i=1,im
2519 : if(dm(i,j) .eq. D0_0) then
2520 : ar(i,j) = p(i,j)
2521 : al(i,j) = p(i,j)
2522 : a6(i,j) = D0_0
2523 : else
2524 : da1 = ar(i,j) - al(i,j)
2525 : da2 = da1**2
2526 : a6da = a6(i,j)*da1
2527 : if(a6da .lt. -da2) then
2528 : a6(i,j) = D3_0*(al(i,j)-p(i,j))
2529 : ar(i,j) = al(i,j) - a6(i,j)
2530 : elseif(a6da .gt. da2) then
2531 : a6(i,j) = D3_0*(ar(i,j)-p(i,j))
2532 : al(i,j) = ar(i,j) - a6(i,j)
2533 : endif
2534 : endif
2535 : enddo
2536 :
2537 : enddo
2538 :
2539 : elseif( lmt == 1 ) then
2540 :
2541 : ! Improved (Lin 2001?) full constraint
2542 :
2543 : do jj = 1, jan
2544 : j = ja(jj)
2545 :
2546 : do i=1,im
2547 : da1 = dm(i,j) + dm(i,j)
2548 : dl = sign(min(abs(da1),abs(al(i,j)-p(i,j))), da1)
2549 : dr = sign(min(abs(da1),abs(ar(i,j)-p(i,j))), da1)
2550 : ar(i,j) = p(i,j) + dr
2551 : al(i,j) = p(i,j) - dl
2552 : a6(i,j) = D3_0*(dl-dr)
2553 : enddo
2554 :
2555 : enddo
2556 :
2557 : elseif( lmt == 2 ) then
2558 :
2559 : ! Positive definite constraint
2560 :
2561 : do jj = 1, jan
2562 : j = ja(jj)
2563 :
2564 : do i=1,im
2565 : if(abs(ar(i,j)-al(i,j)) .lt. -a6(i,j)) then
2566 : fmin = p(i,j) + D0_25*(ar(i,j)-al(i,j))**2/a6(i,j) + a6(i,j)*r12
2567 : if(fmin.lt.D0_0) then
2568 : if(p(i,j).lt.ar(i,j) .and. p(i,j).lt.al(i,j)) then
2569 : ar(i,j) = p(i,j)
2570 : al(i,j) = p(i,j)
2571 : a6(i,j) = D0_0
2572 : elseif(ar(i,j) .gt. al(i,j)) then
2573 : a6(i,j) = D3_0*(al(i,j)-p(i,j))
2574 : ar(i,j) = al(i,j) - a6(i,j)
2575 : else
2576 : a6(i,j) = D3_0*(ar(i,j)-p(i,j))
2577 : al(i,j) = ar(i,j) - a6(i,j)
2578 : endif
2579 : endif
2580 : endif
2581 : enddo
2582 :
2583 : enddo
2584 :
2585 : elseif(lmt .eq. 3) then
2586 :
2587 : ! Quasi-monotone constraint
2588 :
2589 : do jj = 1, jan
2590 : j = ja(jj)
2591 :
2592 : do i=1,im
2593 : da1 = D4_0*dm(i,j)
2594 : dl = sign(min(abs(da1),abs(al(i,j)-p(i,j))), da1)
2595 : dr = sign(min(abs(da1),abs(ar(i,j)-p(i,j))), da1)
2596 : ar(i,j) = p(i,j) + dr
2597 : al(i,j) = p(i,j) - dl
2598 : a6(i,j) = D3_0*(dl-dr)
2599 : enddo
2600 :
2601 : enddo
2602 :
2603 : endif
2604 : return
2605 : !EOC
2606 : end subroutine lmppmv
2607 : !-----------------------------------------------------------------------
2608 : #endif
2609 :
2610 : end module tp_core
|