Line data Source code
1 : module edyn_mudmod
2 : use shr_kind_mod, only: r8 => shr_kind_r8
3 : use cam_logfile, only: iulog
4 : use edyn_mud, only: dismd2cr, mud2cr1, adjmd2cr, kcymd2cr, relmd2cr, resmd2cr
5 : use edyn_mudcom, only: swk2, trsfc2, prolon2, cor2, res2
6 :
7 : implicit none
8 :
9 : private
10 :
11 : public :: mudmod
12 :
13 : contains
14 : !-----------------------------------------------------------------------
15 19 : subroutine mudmod(pe,phi_out,jntl,isolve,nlev,ier)
16 : use edyn_solver_coefs,only: cee
17 : use edyn_params, only: pi
18 :
19 : integer,intent(in) :: jntl, isolve, nlev
20 : integer,intent(out) :: ier ! output: not converged ier < 0
21 : !
22 : ! set grid size params
23 : !
24 : integer iixp,jjyq,iiex,jjey,nnx,nny,llwork
25 : parameter (iixp = 5 , jjyq = 3)
26 : !
27 : ! estimate work space for point relaxation (see mud2cr.d)
28 : !
29 : real(r8) :: phi_out(0:iixp*2**(nlev-1)+1+1,0:jjyq*2**(nlev-1)+1+1)
30 19 : real(r8),allocatable :: phi(:,:),rhs(:,:),work(:)
31 : !
32 : ! put integer and floating point argument names in contiguous
33 : ! storage for labelling in vectors iprm,fprm
34 : !
35 : integer iprm(17),mgopt(4)
36 : real(r8) :: fprm(6)
37 : integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nx,ny,&
38 : iguess,maxcy,method,nwork,lwrkqd,itero
39 : common/itmud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nx,ny, &
40 : iguess,maxcy,method,nwork,lwrkqd,itero
41 : real(r8) :: xa,xb,yc,yd,tolmax,relmax
42 : common/ftmud2cr/xa,xb,yc,yd,tolmax,relmax
43 : equivalence(intl,iprm)
44 : equivalence(xa,fprm)
45 : integer i,j,ierror
46 : real(r8) :: PE(iixp*2**(nlev-1)+1,*)
47 : integer, parameter :: maxcya=50
48 : integer jj,jjj,ij
49 :
50 19 : iiex = nlev
51 19 : jjey = nlev
52 19 : nnx=iixp*2**(iiex-1)+1
53 19 : nny=jjyq*2**(jjey-1)+1
54 19 : llwork=(7*(nnx+2)*(nny+2)+76*nnx*nny)/3
55 :
56 152 : allocate(phi(nnx,nny),rhs(nnx,nny),work(llwork))
57 : !
58 : ! SET INPUT INTEGER PARAMETERS
59 : !
60 19 : INTL = JNTL
61 : !
62 : ! set boundary condition flags
63 : !
64 19 : nxa = 0
65 19 : nxb = 0
66 19 : nyc = 2
67 19 : nyd = 1
68 : !
69 : ! set grid sizes from parameter statements
70 : !
71 19 : ixp = iixp
72 19 : jyq = jjyq
73 19 : iex = iiex
74 19 : jey = jjey
75 19 : nx = nnx
76 19 : ny = nny
77 : !
78 : ! set multigrid arguments (w(2,1) cycling with fully weighted
79 : ! residual restriction and cubic prolongation)
80 : !
81 19 : mgopt(1) = 2
82 19 : mgopt(2) = 3
83 19 : mgopt(3) = 2
84 19 : mgopt(4) = 3
85 : !
86 : ! set for one cycle
87 : !
88 19 : maxcy = maxcya
89 : !
90 : ! set no initial guess forcing full multigrid cycling
91 : !
92 19 : iguess = 0
93 : !
94 : ! set work space length approximation from parameter statement
95 : !
96 19 : nwork = llwork
97 : !
98 : ! set line z relaxation
99 : !
100 19 : method = 3
101 : !
102 : ! set end points of solution rectangle in (x,y) space
103 : !
104 19 : xa = -pi
105 19 : xb = pi
106 19 : yc = 0.0_r8
107 19 : yd = 0.5_r8*pi
108 : !
109 : ! set error control flag
110 : !
111 19 : tolmax = 0.001_r8
112 : !
113 : ! set right hand side in rhs
114 : ! initialize phi to zero
115 : !
116 1558 : do i=1,nx
117 76969 : do j=1,ny
118 150822 : rhs(i,j) = cee(i+(j-1)*nx+9*nx*ny)
119 76950 : phi(i,j) = 0.0_r8
120 : end do
121 : end do
122 : !
123 : ! set specified boundaries in phi
124 : !
125 1558 : do i=1,nx
126 3097 : phi(i,ny) = rhs(i,ny)/cee(i+(ny-1)*nx+8*nx*ny)
127 : end do
128 :
129 19 : call mud2cm(iprm,fprm,work,rhs,phi,mgopt,ierror,isolve)
130 :
131 : !
132 : ! attempt solution
133 : !
134 19 : intl = 1
135 :
136 19 : call mud2cm(iprm,fprm,work,rhs,phi,mgopt,ierror,isolve)
137 19 : ier = ierror ! ier < 0 not converged
138 19 : if(ier < 0 ) goto 108
139 : !
140 : ! COPY PHI TO PE
141 : !
142 950 : DO J = 1,NY
143 931 : JJ = NY+J-1
144 931 : JJJ = NY+1-J
145 76361 : DO I = 1,NX
146 75411 : PE(I,JJ) = PHI(I,J)
147 76342 : PE(I,JJJ) = PHI(I,J)
148 : END DO
149 : END DO
150 :
151 : ! am 8/10 for calculating residual: convert work array (solution) into array
152 : ! sized as coefficient stencil (c0, cofum) including values at index 0, nmlon0+1
153 : ! and nmlat0+1
154 :
155 988 : do j=0,ny+1
156 969 : jj = j*(nx+2)
157 81415 : do i=0,nx+1
158 80427 : ij = jj+i+1
159 81396 : phi_out(i,j) = work(ij)
160 : end do
161 : end do
162 :
163 : 108 continue
164 :
165 19 : deallocate(phi,rhs,work)
166 :
167 19 : end subroutine mudmod
168 : !-------------------------------------------------------------------
169 38 : subroutine mud2cm(iparm,fparm,work,rhs,phi,mgopt,ierror,isolve)
170 :
171 : integer,intent(in) :: isolve
172 : integer iparm,mgopt,ierror
173 : integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess, &
174 : maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur, &
175 : kcycle,iprer,ipost,intpol,kps
176 : real(r8) :: fparm,xa,xb,yc,yd,tolmax,relmax
177 : integer kpbgn,kcbgn,ktxbgn,ktybgn,nxk,nyk,isx,jsy
178 : integer int,iw,k,kb,nx,ny,ic,itx,ity
179 : dimension iparm(17),fparm(6),mgopt(4)
180 : real(r8) :: work(*),phi(*),rhs(*)
181 : common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy, &
182 : iguess, maxcy,method,nwork,lwork,itero,ngrid, &
183 : klevel,kcur,kcycle,iprer,ipost,intpol,kps
184 : common/fmud2cr/xa,xb,yc,yd,tolmax,relmax
185 : common/mud2crc/kpbgn(50),kcbgn(50),ktxbgn(50),ktybgn(50), &
186 : nxk(50),nyk(50),isx,jsy
187 :
188 : data int / 0 /
189 : save int
190 :
191 38 : ierror = 1
192 38 : intl = iparm(1) ! set and check intl on all calls
193 38 : if (intl*(intl-1).ne.0) return
194 38 : if (int.eq.0) then
195 2 : int = 1
196 2 : if (intl.ne.0) return ! very first call is not intl=0
197 : end if
198 38 : ierror = 0
199 : !
200 : ! set arguments internally
201 : ! these will not be rechecked if intl=1!
202 : !
203 38 : nxa = iparm(2)
204 38 : nxb = iparm(3)
205 38 : nyc = iparm(4)
206 38 : nyd = iparm(5)
207 38 : ixp = iparm(6)
208 38 : jyq = iparm(7)
209 38 : iex = iparm(8)
210 38 : jey = iparm(9)
211 38 : ngrid = max0(iex,jey)
212 38 : nfx = iparm(10)
213 38 : nfy = iparm(11)
214 38 : iguess = iparm(12)
215 38 : maxcy = iparm(13)
216 38 : method = iparm(14)
217 38 : nwork = iparm(15)
218 38 : kcycle = mgopt(1)
219 38 : if (kcycle .eq. 0) then
220 : ! set defaults
221 0 : kcycle = 2
222 0 : iprer = 2
223 0 : ipost = 1
224 0 : intpol = 3
225 : else
226 38 : iprer = mgopt(2)
227 38 : ipost = mgopt(3)
228 38 : intpol = mgopt(4)
229 : end if
230 38 : xa = fparm(1)
231 38 : xb = fparm(2)
232 38 : yc = fparm(3)
233 38 : yd = fparm(4)
234 38 : tolmax = fparm(5)
235 38 : if (intl .eq. 0) then ! intialization call
236 : !
237 : ! check input arguments
238 : !
239 19 : ierror = 2 ! check boundary condition flags
240 19 : if (max0(nxa,nxb,nyc,nyd).gt.2) return
241 19 : if (min0(nxa,nxb,nyc,nyd).lt.0) return
242 19 : if (nxa.eq.0.and.nxb.ne.0) return
243 19 : if (nxa.ne.0.and.nxb.eq.0) return
244 19 : if (nyc.eq.0.and.nyd.ne.0) return
245 19 : if (nyc.ne.0.and.nyd.eq.0) return
246 19 : ierror = 3 ! check grid sizes
247 19 : if (ixp.lt.2) return
248 19 : if (jyq.lt.2) return
249 19 : ierror = 4
250 19 : ngrid = max0(iex,jey)
251 19 : if (iex.lt.1) return
252 19 : if (jey.lt.1) return
253 19 : if (ngrid.gt.50) return
254 19 : ierror = 5
255 19 : if (nfx.ne.ixp*2**(iex-1)+1) return
256 19 : if (nfy.ne.jyq*2**(jey-1)+1) return
257 19 : ierror = 6
258 19 : if (iguess*(iguess-1).ne.0) return
259 19 : ierror = 7
260 19 : if (maxcy.lt.1) return
261 19 : ierror = 8
262 19 : if (method.lt.0 .or. method.gt.3) return
263 19 : ierror = 9
264 : ! compute and test minimum work space
265 19 : isx = 0
266 19 : if (method.eq.1 .or. method.eq.3) then
267 0 : if (nxa.ne.0) isx = 3
268 19 : if (nxa.eq.0) isx = 5
269 : end if
270 19 : jsy = 0
271 19 : if (method.eq.2 .or. method.eq.3) then
272 19 : if (nyc.ne.0) jsy = 3
273 19 : if (nyc.eq.0) jsy = 5
274 : end if
275 19 : kps = 1
276 114 : do k=1,ngrid
277 : ! set subgrid sizes
278 190 : nxk(k) = ixp*2**(max0(k+iex-ngrid,1)-1)+1
279 95 : nyk(k) = jyq*2**(max0(k+jey-ngrid,1)-1)+1
280 95 : nx = nxk(k)
281 95 : ny = nyk(k)
282 19 : kps = kps+(nx+2)*(ny+2)+nx*ny*(10+isx+jsy)
283 : end do
284 19 : iparm(16) = kps+(nfx+2)*(nfy+2) ! exact minimum work space
285 19 : lwork = iparm(16)
286 19 : if (lwork .gt. nwork) return
287 19 : ierror = 10 ! check solution region
288 19 : if (xb.le.xa .or. yd.le.yc) return
289 19 : ierror = 11
290 19 : if (tolmax .lt. 0.0_r8) return
291 19 : ierror = 12 ! multigrid parameters
292 19 : if (kcycle.lt.0) return
293 19 : if (min0(iprer,ipost).lt.1) return
294 19 : if ((intpol-1)*(intpol-3).ne.0) return
295 19 : if (max0(kcycle,iprer,ipost).gt.2) then
296 19 : ierror = -5 ! inefficient multigrid cycling
297 : end if
298 19 : if (ierror .gt. 0) ierror = 0 ! no fatal errors
299 : !
300 : ! set work space pointers and discretize pde at each grid level
301 : !
302 19 : iw = 1
303 114 : do kb=1,ngrid
304 95 : k = ngrid-kb+1
305 95 : nx = nxk(k)
306 95 : ny = nyk(k)
307 95 : kpbgn(k) = iw
308 95 : kcbgn(k) = kpbgn(k)+(nx+2)*(ny+2)
309 95 : ktxbgn(k) = kcbgn(k)+10*nx*ny
310 95 : ktybgn(k) = ktxbgn(k)+isx*nx*ny
311 95 : iw = ktybgn(k)+jsy*nx*ny
312 95 : ic = kcbgn(k)
313 95 : itx = ktxbgn(k)
314 95 : ity = ktybgn(k)
315 95 : klevel = k
316 0 : call dismd2cr(nx,ny,work(ic),work(itx),work(ity), &
317 114 : work,ierror,isolve)
318 : end do
319 : return
320 : end if ! end of intl=0 initialization call block
321 19 : nx = nfx
322 19 : ny = nfy
323 19 : call mud2c1m(nx,ny,rhs,phi,work)
324 19 : iparm(17) = itero
325 19 : if (tolmax.gt.0.0_r8) then ! check for convergence
326 19 : fparm(6) = relmax
327 19 : if (relmax.gt.tolmax) then
328 :
329 : ! ierror = -1 ! flag convergenc failure
330 0 : write(iulog,*) "no convergence with mudmod"
331 : !
332 0 : iguess = 1
333 0 : iparm(12)= iguess
334 0 : call mud2cr1(nx,ny,rhs,phi,work) ! solve with modified stencils
335 :
336 0 : fparm(6) = relmax
337 0 : if (relmax.gt.tolmax) then
338 0 : write(iulog,*) "no convergence with mud"
339 0 : ierror = -1 ! flag convergenc failure
340 : end if
341 :
342 : end if
343 : end if
344 :
345 : return
346 80408 : end subroutine mud2cm
347 : !------------------------------------------------------------------------
348 38 : subroutine mud2c1m(nx,ny,rhsf,phif,wk)
349 :
350 : integer nx,ny
351 : real(r8) :: phif(nx,ny),rhsf(nx,ny),wk(*)
352 : integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess, &
353 : maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur, &
354 : kcycle,iprer,ipost,intpol,kps
355 : real(r8) :: xa,xb,yc,yd,tolmax,relmax,phmax
356 : integer kpbgn,kcbgn,ktxbgn,ktybgn,nxk,nyk,isx,jsy
357 : integer k,kb,ip,ic,ir,ipc,irc,icc
358 : integer ncx,ncy,jj,ij,i,j,iter
359 :
360 : common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy, &
361 : iguess, maxcy,method,nwork,lwork,itero,ngrid, &
362 : klevel,kcur,kcycle,iprer,ipost,intpol,kps
363 : common/fmud2cr/xa,xb,yc,yd,tolmax,relmax
364 : common/mud2crc/kpbgn(50),kcbgn(50),ktxbgn(50),ktybgn(50), &
365 : nxk(50),nyk(50),isx,jsy
366 :
367 19 : nx = nxk(ngrid)
368 19 : ny = nyk(ngrid)
369 19 : ip = kpbgn(ngrid)
370 19 : ic = kcbgn(ngrid)
371 19 : ir = ic+9*nx*ny
372 : !
373 : ! set phif,rhsf in wk and adjust right hand side
374 : !
375 19 : call swk2(nx,ny,phif,rhsf,wk(ip),wk(ir))
376 19 : if (iguess.eq.0) then
377 : !
378 : ! no initial guess at finest grid level!
379 : !
380 95 : do kb=2,ngrid
381 76 : k = ngrid-kb+1
382 76 : nx = nxk(k+1)
383 76 : ny = nyk(k+1)
384 76 : ip = kpbgn(k+1)
385 76 : ir = kcbgn(k+1)+9*nx*ny
386 76 : ncx = nxk(k)
387 76 : ncy = nyk(k)
388 76 : ipc = kpbgn(k)
389 76 : icc = kcbgn(k)
390 76 : irc = icc+9*ncx*ncy
391 : !
392 : ! transfer down to all grid levels
393 : !
394 95 : call trsfc2(nx,ny,wk(ip),wk(ir),ncx,ncy,wk(ipc),wk(irc))
395 : end do
396 : !
397 : ! adjust right hand side at all grid levels in case
398 : ! rhs or specified b.c. in phi or gbdy changed
399 : !
400 114 : do k=1,ngrid
401 95 : nx = nxk(k)
402 95 : ny = nyk(k)
403 95 : ip = kpbgn(k)
404 95 : ic = kcbgn(k)
405 114 : call adjmd2cr(nx,ny,wk(ip),wk(ic))
406 : end do
407 : !
408 : ! execute one full multigrid cycle
409 : !
410 95 : do k=1,ngrid-1
411 76 : kcur = k
412 76 : call kcymd2cr(wk)
413 76 : nx = nxk(k+1)
414 76 : ny = nyk(k+1)
415 76 : ip = kpbgn(k+1)
416 76 : ipc = kpbgn(k)
417 76 : ncx = nxk(k)
418 76 : ncy = nyk(k)
419 : !
420 : ! lift or prolong approximation from k to k+1
421 : !
422 95 : call prolon2(ncx,ncy,wk(ipc),nx,ny,wk(ip),nxa,nxb,nyc,nyd,intpol)
423 : end do
424 : else
425 : !
426 : ! adjust rhs at finest grid level only
427 : !
428 0 : nx = nxk(ngrid)
429 0 : ny = nyk(ngrid)
430 0 : ip = kpbgn(ngrid)
431 0 : ic = kcbgn(ngrid)
432 0 : call adjmd2cr(nx,ny,wk(ip),wk(ic))
433 : end if
434 : !
435 : ! execute maxcy more multigrid k cycles from finest level
436 : !
437 19 : kcur = ngrid
438 76 : do iter=1,maxcy
439 76 : itero = iter
440 76 : call kcym2cm(wk)
441 0 : if (tolmax.gt.0.0_r8) then
442 : !
443 : ! error control
444 : !
445 76 : relmax = 0.0_r8
446 76 : phmax = 0.0_r8
447 :
448 3800 : do j=1,nfy
449 3724 : jj = j*(nfx+2)
450 305444 : do i=1,nfx
451 301644 : ij = jj+i+1
452 301644 : phmax = max(phmax,abs(wk(ij)))
453 301644 : relmax = max(relmax,abs(wk(ij)-phif(i,j)))
454 :
455 305368 : phif(i,j) = wk(ij)
456 : end do
457 : end do
458 : !
459 : ! set maximum relative difference and check for convergence
460 : !
461 76 : if (phmax.gt.0.0_r8) relmax = relmax/phmax
462 76 : if (relmax.le.tolmax) return
463 : end if
464 : end do
465 : !
466 : ! set final interate after maxcy cycles in phif
467 : !
468 0 : do j=1,nfy
469 0 : jj = j*(nfx+2)
470 0 : do i=1,nfx
471 0 : ij = jj+i+1
472 0 : phif(i,j) = wk(ij)
473 : end do
474 : end do
475 : return
476 646 : end subroutine mud2c1m
477 :
478 : !------------------------------------------------------------------------
479 152 : subroutine kcym2cm(wk)
480 4066 : use edyn_solver_coefs,only: cofum
481 : !
482 : ! execute multigrid k cycle from kcur grid level
483 : ! kcycle=1 for v cycles, kcycle=2 for w cycles
484 : !
485 : real(r8) :: wk(*)
486 : integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess, &
487 : maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur, &
488 : kcycle,iprer,ipost,intpol,kps
489 : integer nx,ny,ip,ic,ipc,irc,itx,ity,ncx,ncy,l,nrel
490 : real(r8) :: xa,xb,yc,yd,tolmax,relmax
491 : integer kpbgn,kcbgn,ktxbgn,ktybgn,nxk,nyk,isx,jsy
492 : common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy, &
493 : iguess, maxcy,method,nwork,lwork,itero,ngrid, &
494 : klevel,kcur,kcycle,iprer,ipost,intpol,kps
495 : common/fmud2cr/xa,xb,yc,yd,tolmax,relmax
496 : common/mud2crc/kpbgn(50),kcbgn(50),ktxbgn(50),ktybgn(50), &
497 : nxk(50),nyk(50),isx,jsy
498 : integer kount(50)
499 : ! real(r8) :: :: cofum
500 : ! common/mudmd/cofum(1)
501 :
502 76 : klevel = kcur
503 76 : nx = nxk(klevel)
504 76 : ny = nyk(klevel)
505 76 : ip = kpbgn(klevel)
506 76 : ic = kcbgn(klevel)
507 76 : itx = ktxbgn(klevel)
508 76 : ity = ktybgn(klevel)
509 : !
510 : ! prerelax at current finest grid level
511 : !
512 304 : do l=1,iprer
513 532 : call relmd2cr(nx,ny,wk(ip),wk(ic),wk(itx),wk(ity),wk(kps))
514 : end do
515 76 : if (kcur .eq. 1) go to 5
516 : !
517 : ! restrict residual to kcur-1 level
518 : !
519 76 : ipc = kpbgn(klevel-1)
520 76 : ncx = nxk(klevel-1)
521 76 : ncy = nyk(klevel-1)
522 76 : irc = kcbgn(klevel-1)+9*ncx*ncy
523 : ! call resmd2cr(nx,ny,wk(ip),ncx,ncy,wk(ipc),wk(irc),wk(ic),wk(kps))
524 :
525 0 : call resm2cm(nx,ny,wk(ip),ncx,ncy,wk(ipc),wk(irc),wk(ic), &
526 152 : wk(kps),cofum)
527 : !
528 : ! set counter for grid levels to zero
529 : !
530 456 : do l = 1,kcur
531 456 : kount(l) = 0
532 : end do
533 : !
534 : ! set new grid level and continue k-cycling
535 : !
536 76 : klevel = kcur-1
537 76 : nrel = iprer
538 : !
539 : ! kcycle control point
540 : !
541 : 10 continue
542 : !
543 : ! post relax when kcur revisited
544 : !
545 2280 : if (klevel .eq. kcur) go to 5
546 : !
547 : ! count hit at current level
548 : !
549 2204 : kount(klevel) = kount(klevel)+1
550 : !
551 : ! relax at current level
552 : !
553 2204 : nx = nxk(klevel)
554 2204 : ny = nyk(klevel)
555 2204 : ip = kpbgn(klevel)
556 2204 : ic = kcbgn(klevel)
557 2204 : itx = ktxbgn(klevel)
558 2204 : ity = ktybgn(klevel)
559 7752 : do l=1,nrel
560 13300 : call relmd2cr(nx,ny,wk(ip),wk(ic),wk(itx),wk(ity),wk(kps))
561 : end do
562 2204 : if (kount(klevel) .eq. kcycle+1) then
563 : !
564 : ! kcycle complete at klevel
565 : !
566 684 : ipc = ip
567 684 : ip = kpbgn(klevel+1)
568 684 : ncx = nxk(klevel)
569 684 : ncy = nyk(klevel)
570 684 : nx = nxk(klevel+1)
571 684 : ny = nyk(klevel+1)
572 : !
573 : ! inject correction to finer grid
574 : !
575 0 : call cor2(nx,ny,wk(ip),ncx,ncy,wk(ipc),nxa,nxb,nyc,nyd, &
576 1368 : intpol,wk(kps))
577 : !
578 : ! reset counter to zero
579 : !
580 684 : kount(klevel) = 0
581 : !
582 : ! ascend to next higher level and set to postrelax there
583 : !
584 684 : klevel = klevel+1
585 684 : nrel = ipost
586 684 : go to 10
587 : else
588 1520 : if (klevel .gt. 1) then
589 : !
590 : ! kcycle not complete so descend unless at coarsest grid
591 : !
592 1064 : ipc = kpbgn(klevel-1)
593 1064 : ncx = nxk(klevel-1)
594 1064 : ncy = nyk(klevel-1)
595 1064 : irc = kcbgn(klevel-1)+9*ncx*ncy
596 0 : call resmd2cr(nx,ny,wk(ip),ncx,ncy,wk(ipc),wk(irc),wk(ic), &
597 2128 : wk(kps))
598 : !
599 : ! prerelax at next coarser level
600 : !
601 1064 : klevel = klevel-1
602 1064 : nrel = iprer
603 1064 : go to 10
604 : else
605 : !
606 : ! postrelax at coarsest level
607 : !
608 1368 : do l=1,ipost
609 2280 : call relmd2cr(nx,ny,wk(ip),wk(ic),wk(itx),wk(ity),wk(kps))
610 : end do
611 456 : ipc = ip
612 456 : ip = kpbgn(2)
613 456 : ncx = nxk(1)
614 456 : ncy = nyk(1)
615 456 : nx = nxk(2)
616 456 : ny = nyk(2)
617 : !
618 : ! inject correction to level 2
619 : !
620 0 : call cor2(nx,ny,wk(ip),ncx,ncy,wk(ipc),nxa,nxb,nyc,nyd, &
621 912 : intpol,wk(kps))
622 : !
623 : ! set to postrelax at level 2
624 : !
625 456 : nrel = ipost
626 456 : klevel = 2
627 532 : go to 10
628 : end if
629 : end if
630 : 5 continue
631 : !
632 : ! post relax at current finest grid level
633 : !
634 76 : nx = nxk(kcur)
635 76 : ny = nyk(kcur)
636 76 : ip = kpbgn(kcur)
637 76 : ic = kcbgn(kcur)
638 76 : itx = ktxbgn(kcur)
639 76 : ity = ktybgn(kcur)
640 228 : do l=1,ipost
641 380 : call relmd2cr(nx,ny,wk(ip),wk(ic),wk(itx),wk(ity),wk(kps))
642 : end do
643 76 : return
644 : end subroutine kcym2cm
645 : !----------------------------------------------------------------------
646 76 : subroutine resm2cm(nx,ny,phi,ncx,ncy,phic,rhsc,cof,resf,cofum)
647 : !
648 : ! restrict residual from fine to coarse mesh using fully weighted
649 : ! residual restriction
650 : !
651 : integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess, &
652 : maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur, &
653 : kcycle,iprer,ipost,intpol,kps
654 : integer nx,ny,ncx,ncy,i,j,ic,jc
655 : common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy, &
656 : iguess, maxcy,method,nwork,lwork,itero,ngrid, &
657 : klevel,kcur,kcycle,iprer,ipost,intpol,kps
658 : real(r8) :: rhsc(ncx,ncy),resf(nx,ny)
659 : real(r8) :: phi(0:nx+1,0:ny+1),phic(0:ncx+1,0:ncy+1)
660 : real(r8) :: cof(nx,ny,10),cofum(nx,ny,9)
661 : real(r8) :: l2norm
662 : !
663 : ! set phic zero
664 : !
665 2128 : do jc=0,ncy+1
666 90364 : do ic=0,ncx+1
667 90288 : phic(ic,jc) = 0.0_r8
668 : end do
669 : end do
670 :
671 76 : call bnd2cm(nx,ny,cofum)
672 : !
673 : ! compute residual on fine mesh in resf
674 : !
675 76 : l2norm = 0._r8
676 : !$OMP PARALLEL DO SHARED(resf,cof,phi,nx,ny) PRIVATE(i,j)
677 3800 : do j=1,ny
678 305444 : do i=1,nx
679 603288 : resf(i,j) = cof(i,j,10)-( &
680 603288 : cofum(i,j,1)*phi(i+1,j)+ &
681 301644 : cofum(i,j,2)*phi(i+1,j+1)+ &
682 301644 : cofum(i,j,3)*phi(i,j+1)+ &
683 301644 : cofum(i,j,4)*phi(i-1,j+1)+ &
684 : cofum(i,j,5)*phi(i-1,j)+ &
685 301644 : cofum(i,j,6)*phi(i-1,j-1)+ &
686 : cofum(i,j,7)*phi(i,j-1)+ &
687 : cofum(i,j,8)*phi(i+1,j-1)+ &
688 1809864 : cofum(i,j,9)*phi(i,j))
689 :
690 305368 : l2norm = l2norm + resf(i,j)*resf(i,j)
691 : end do
692 : end do
693 : !
694 : ! restrict resf to coarse mesh in rhsc
695 : !
696 76 : call res2(nx,ny,resf,ncx,ncy,rhsc,nxa,nxb,nyc,nyd)
697 76 : return
698 17784 : end subroutine resm2cm
699 :
700 : !-----------------------------------------------------------------------
701 76 : subroutine bnd2cm(nx,ny,cf)
702 : !
703 : ! set stencil & boundary condition for finest stencil
704 : !
705 : integer intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy,iguess, &
706 : maxcy,method,nwork,lwork,itero,ngrid,klevel,kcur, &
707 : kcycle,iprer,ipost,intpol,kps
708 : real(r8) :: xa,xb,yc,yd,tolmax,relmax
709 : integer nx,ny,i,j,l
710 : real(r8) :: cf(nx,ny,*)
711 : common/imud2cr/intl,nxa,nxb,nyc,nyd,ixp,jyq,iex,jey,nfx,nfy, &
712 : iguess, maxcy,method,nwork,lwork,itero,ngrid, &
713 : klevel,kcur,kcycle,iprer,ipost,intpol,kps
714 : common/fmud2cr/xa,xb,yc,yd,tolmax,relmax
715 :
716 : !
717 : ! set coefficient for specified boundaries
718 : !
719 76 : if (nxa.eq.1) then
720 0 : i = 1
721 0 : do j=1,ny
722 0 : do l=1,9
723 0 : cf(i,j,l) = 0.0_r8
724 : end do
725 0 : cf(i,j,9) = 1.0_r8
726 : end do
727 : end if
728 76 : if (nxb.eq.1) then
729 0 : i = nx
730 0 : do j=1,ny
731 0 : do l=1,9
732 0 : cf(i,j,l) = 0.0_r8
733 : end do
734 0 : cf(i,j,9) = 1.0_r8
735 : end do
736 : end if
737 76 : if (nyc.eq.1) then
738 0 : j = 1
739 0 : do i=1,nx
740 0 : do l=1,9
741 0 : cf(i,j,l) = 0.0_r8
742 : end do
743 0 : cf(i,j,9) = 1.0_r8
744 : end do
745 : end if
746 76 : if (nyd.eq.1) then
747 76 : j = ny
748 6232 : do i=1,nx
749 61560 : do l=1,9
750 61560 : cf(i,j,l) = 0.0_r8
751 : end do
752 6232 : cf(i,j,9) = 1.0_r8
753 : end do
754 : end if
755 : !
756 76 : return
757 : end subroutine bnd2cm
758 : !-----------------------------------------------------------------------
759 : end module edyn_mudmod
|