ADflow  v1.0
ADflow is a finite volume RANS solver tailored for gradient-based aerodynamic design optimization.
multiGrid.F90
Go to the documentation of this file.
1 module multigrid
2 
3 contains
4 
6  !
7  ! transferToCoarseGrid restricts both the solution and the
8  ! residual to the next coarser grid level and computes the
9  ! residual forcing term on this level.
10  !
11  use constants
12  use blockpointers, only: flowdoms, dw, il, jl, kl, ie, je, ke, w, &
13  p1, p, rev, w1, mgifine, mgjfine, mgkfine, ndom, wr, mgiweight, &
15  use flowvarrefstate, only: nwf, kpresent
16  use inputiteration, only: fcoll
18  use iteration, only: currentlevel, rkstage
19  use utils, only: setpointers
20  use haloexchange, only: whalo1
23  use solverutils, only: timestep
25  use bcroutines, only: applyallbc
26  implicit none
27  !
28  ! Local variables.
29  !
30  integer(kind=intType) :: nn, sps, i, j, k, l
31  integer(kind=intType) :: ii, jj, kk, ii1, jj1, kk1
32  integer(kind=intType) :: fineLevel
33 
34  integer(kind=intType), dimension(:, :, :), pointer :: iiblank
35 
36  real(kind=realtype) :: vola, tmp, weigth, blankfact
37 
38  real(kind=realtype), dimension(:, :, :, :), pointer :: ww
39  real(kind=realtype), dimension(:, :, :), pointer :: pp, vvol, rrev
40 
41  logical :: correctForK
42 
43  ! Compute the residual on the fine grid. It is assumed that the
44  ! halo's contain the correct values. The time step is computed,
45  ! because this routine also computes the spectral radii for the
46  ! artificial dissipation terms.
47 
48  rkstage = 0
49  call timestep(.true.)
50 
51  call initres(1_inttype, nwf)
52  call sourceterms()
53  call residual
54 
55  ! Store the fine grid level and update the current level such
56  ! that it corresponds to the coarse grid
57 
58  finelevel = currentlevel
60 
61  ! Set the logical correctForK.
62  correctfork = .false.
63 
64  ! Set the value of the blanking factor for the restricted
65  ! residual to 1. This will be overwritten below if needed.
66 
67  blankfact = one
68 
69  ! Loop over the number of spectral solutions and domains.
70 
71  spectralloop1: do sps = 1, ntimeintervalsspectral
72  domains1: do nn = 1, ndom
73 
74  ! Set the pointers to the coarse block and to the fine grid
75  ! solution and volumes. Note that this is not needed for the,
76  ! residual, because only the fine grid residual is allocated.
77 
78  call setpointers(nn, currentlevel, sps)
79 
80  ww => flowdoms(nn, finelevel, sps)%w
81  pp => flowdoms(nn, finelevel, sps)%p
82  vvol => flowdoms(nn, finelevel, sps)%vol
83  rrev => flowdoms(nn, finelevel, sps)%rev
84  iiblank => flowdoms(nn, finelevel, sps)%iblank
85 
86  ! Restrict the solution and the residual to the coarser
87  ! meshes. The solution is done in a volume averaged way. Note
88  ! that the sum of the fine grid volumes is used to divide and
89  ! not the coarse grid volume; these are not necessarily the
90  ! same, especially for the flexible mg used.
91 
92  do k = 2, kl
93  kk = mgkfine(k, 1)
94  kk1 = mgkfine(k, 2)
95  do j = 2, jl
96  jj = mgjfine(j, 1)
97  jj1 = mgjfine(j, 2)
98  do i = 2, il
99  ii = mgifine(i, 1)
100  ii1 = mgifine(i, 2)
101 
102  ! Determine the weight for the restricted residual. This
103  ! weight is less than 1.0 if in at least 1 direction an
104  ! irregular coarsening is used. This weight is not
105  ! applied to the solution, because volume weighting is
106  ! used there.
107 
108  weigth = mgkweight(k) * mgjweight(j) * mgiweight(i)
109 
110  ! Compute the sum of the fine grid volumes.
111 
112  vola = vvol(ii, jj, kk) + vvol(ii1, jj, kk) &
113  + vvol(ii, jj1, kk) + vvol(ii1, jj1, kk) &
114  + vvol(ii, jj, kk1) + vvol(ii1, jj, kk1) &
115  + vvol(ii, jj1, kk1) + vvol(ii1, jj1, kk1)
116 
117  ! Invert the sum of the fine grid volumes.
118 
119  vola = one / vola
120 
121  ! Store the restricted residual in wr, the residual
122  ! forcing term, and the solution in ww.
123 
124  do l = 1, nwf
125  wr(i, j, k, l) = (dw(ii, jj, kk, l) + dw(ii, jj1, kk, l) &
126  + dw(ii1, jj, kk, l) + dw(ii1, jj1, kk, l) &
127  + dw(ii, jj, kk1, l) + dw(ii, jj1, kk1, l) &
128  + dw(ii1, jj, kk1, l) + dw(ii1, jj1, kk1, l)) &
129  * weigth * blankfact
130  end do
131 
132  ! Restrict the solution.
133 
134  ! Density.
135 
136  w(i, j, k, irho) = (vvol(ii, jj, kk) * ww(ii, jj, kk, irho) &
137  + vvol(ii, jj1, kk) * ww(ii, jj1, kk, irho) &
138  + vvol(ii1, jj, kk) * ww(ii1, jj, kk, irho) &
139  + vvol(ii1, jj1, kk) * ww(ii1, jj1, kk, irho) &
140  + vvol(ii, jj, kk1) * ww(ii, jj, kk1, irho) &
141  + vvol(ii, jj1, kk1) * ww(ii, jj1, kk1, irho) &
142  + vvol(ii1, jj, kk1) * ww(ii1, jj, kk1, irho) &
143  + vvol(ii1, jj1, kk1) * ww(ii1, jj1, kk1, irho)) &
144  * vola
145 
146  ! X-velocity.
147 
148  w(i, j, k, ivx) = (vvol(ii, jj, kk) * ww(ii, jj, kk, ivx) &
149  + vvol(ii, jj1, kk) * ww(ii, jj1, kk, ivx) &
150  + vvol(ii1, jj, kk) * ww(ii1, jj, kk, ivx) &
151  + vvol(ii1, jj1, kk) * ww(ii1, jj1, kk, ivx) &
152  + vvol(ii, jj, kk1) * ww(ii, jj, kk1, ivx) &
153  + vvol(ii, jj1, kk1) * ww(ii, jj1, kk1, ivx) &
154  + vvol(ii1, jj, kk1) * ww(ii1, jj, kk1, ivx) &
155  + vvol(ii1, jj1, kk1) * ww(ii1, jj1, kk1, ivx)) &
156  * vola
157 
158  ! Y-velocity.
159 
160  w(i, j, k, ivy) = (vvol(ii, jj, kk) * ww(ii, jj, kk, ivy) &
161  + vvol(ii, jj1, kk) * ww(ii, jj1, kk, ivy) &
162  + vvol(ii1, jj, kk) * ww(ii1, jj, kk, ivy) &
163  + vvol(ii1, jj1, kk) * ww(ii1, jj1, kk, ivy) &
164  + vvol(ii, jj, kk1) * ww(ii, jj, kk1, ivy) &
165  + vvol(ii, jj1, kk1) * ww(ii, jj1, kk1, ivy) &
166  + vvol(ii1, jj, kk1) * ww(ii1, jj, kk1, ivy) &
167  + vvol(ii1, jj1, kk1) * ww(ii1, jj1, kk1, ivy)) &
168  * vola
169 
170  ! Z-velocity.
171 
172  w(i, j, k, ivz) = (vvol(ii, jj, kk) * ww(ii, jj, kk, ivz) &
173  + vvol(ii, jj1, kk) * ww(ii, jj1, kk, ivz) &
174  + vvol(ii1, jj, kk) * ww(ii1, jj, kk, ivz) &
175  + vvol(ii1, jj1, kk) * ww(ii1, jj1, kk, ivz) &
176  + vvol(ii, jj, kk1) * ww(ii, jj, kk1, ivz) &
177  + vvol(ii, jj1, kk1) * ww(ii, jj1, kk1, ivz) &
178  + vvol(ii1, jj, kk1) * ww(ii1, jj, kk1, ivz) &
179  + vvol(ii1, jj1, kk1) * ww(ii1, jj1, kk1, ivz)) &
180  * vola
181 
182  ! Pressure.
183 
184  p(i, j, k) = (vvol(ii, jj, kk) * pp(ii, jj, kk) &
185  + vvol(ii, jj1, kk) * pp(ii, jj1, kk) &
186  + vvol(ii1, jj, kk) * pp(ii1, jj, kk) &
187  + vvol(ii1, jj1, kk) * pp(ii1, jj1, kk) &
188  + vvol(ii, jj, kk1) * pp(ii, jj, kk1) &
189  + vvol(ii, jj1, kk1) * pp(ii, jj1, kk1) &
190  + vvol(ii1, jj, kk1) * pp(ii1, jj, kk1) &
191  + vvol(ii1, jj1, kk1) * pp(ii1, jj1, kk1)) * vola
192 
193  ! Restrict the eddy viscosity if needed.
194  rev(i, j, k) = (vvol(ii, jj, kk) * rrev(ii, jj, kk) &
195  + vvol(ii, jj1, kk) * rrev(ii, jj1, kk) &
196  + vvol(ii1, jj, kk) * rrev(ii1, jj, kk) &
197  + vvol(ii1, jj1, kk) * rrev(ii1, jj1, kk) &
198  + vvol(ii, jj, kk1) * rrev(ii, jj, kk1) &
199  + vvol(ii, jj1, kk1) * rrev(ii, jj1, kk1) &
200  + vvol(ii1, jj, kk1) * rrev(ii1, jj, kk1) &
201  + vvol(ii1, jj1, kk1) * rrev(ii1, jj1, kk1)) * vola
202  end do
203  end do
204  end do
205 
206  ! Compute the total energy, laminar viscosity and eddy viscosity
207  ! for the owned cells of this block.
208 
209  call computeetotblock(2_inttype, il, 2_inttype, jl, &
210  2_inttype, kl, correctfork)
211  call computelamviscosity(.false.)
212  call computeeddyviscosity(.false.)
213 
214  ! Set the values of the 1st layer of corner row halo's to avoid
215  ! divisions by zero and uninitialized variables.
216 
217  call setcornerrowhalos(nwf)
218 
219  end do domains1
220  end do spectralloop1
221 
222  ! Apply all boundary conditions to all blocks on this level.
223  ! No need to exchange the pressure before, because on the coarser
224  ! grids a constant pressure boundary condition is used for the
225  ! inviscid walls.
226 
227  call applyallbc(.false.)
228 
229  ! Exchange the solution. As on the coarse grid only the first
230  ! layer of halo's is needed, whalo1 is called.
231 
232  call whalo1(currentlevel, 1_inttype, nwf, .true., &
233  .true., .true.)
234 
235  ! The second part of the residual forcing term is the residual
236  ! of the just restricted solution.
237  ! First compute the time step.
238 
239  rkstage = 0
240  call timestep(.false.)
241 
242  ! The second part of the residual forcing term for the mean
243  ! flow equations. Furthermore the solution, primitive variables,
244  ! is stored in w1 and p1, also of the 1st level halo's. These
245  ! may be needed to determine the fine grid corrections.
246 
247  spectralloop3: do sps = 1, ntimeintervalsspectral
248  domains3: do nn = 1, ndom
249 
250  ! Have the pointers point to this block.
251 
252  call setpointers(nn, currentlevel, sps)
253 
254  ! Initialize the mean flow residual to zero.
255 
256  do k = 1, ke
257  do j = 1, je
258  do i = 1, ie
259  dw(i, j, k, irho) = zero
260  dw(i, j, k, imx) = zero
261  dw(i, j, k, imy) = zero
262  dw(i, j, k, imz) = zero
263  dw(i, j, k, irhoe) = zero
264  end do
265  end do
266  end do
267 
268  ! Store the restricted solution in w1 and p1.
269 
270  ! Flow field variables.
271 
272  do k = 1, ke
273  do j = 1, je
274  do i = 1, ie
275  w1(i, j, k, irho) = w(i, j, k, irho)
276  w1(i, j, k, ivx) = w(i, j, k, ivx)
277  w1(i, j, k, ivy) = w(i, j, k, ivy)
278  w1(i, j, k, ivz) = w(i, j, k, ivz)
279  w1(i, j, k, irhoe) = w(i, j, k, irhoe)
280 
281  p1(i, j, k) = p(i, j, k)
282  end do
283  end do
284  end do
285 
286  end do domains3
287  end do spectralloop3
288 
289  ! Compute the mean flow residual.
290 
291  call residual
292 
293  ! Substract the residual from the restricted residual and form
294  ! the residual forcing term, where the relaxation factor fcoll is
295  ! taken into account. Store the restricted residual, currently
296  ! stored in wr, in residual afterwards. This is the net result
297  ! of adding the residual to the residual forcing term.
298 
299  spectralloop4: do sps = 1, ntimeintervalsspectral
300  domains4: do nn = 1, ndom
301 
302  ! Have the pointers point to this block.
303 
304  call setpointers(nn, currentlevel, sps)
305 
306  ! Loop over the owned cells. No need to do anything on the
307  ! halo's.
308 
309  do l = 1, nwf
310  do k = 2, kl
311  do j = 2, jl
312  do i = 2, il
313  tmp = fcoll * wr(i, j, k, l)
314  wr(i, j, k, l) = tmp - dw(i, j, k, l)
315  dw(i, j, k, l) = tmp
316  end do
317  end do
318  end do
319  end do
320 
321  end do domains4
322  end do spectralloop4
323 
324  end subroutine transfertocoarsegrid
325 
326  subroutine transfertofinegrid(corrections)
327  !
328  ! transferToFineGrid interpolates either the corrections or the
329  ! solution to the next finer grid level. A standard trilinear
330  ! interpolation is used.
331  !
332  use constants
333  use blockpointers, only: flowdoms, dw, il, jl, kl, ie, je, ke, w, &
334  p1, p, rev, w1, mgicoarse, mgjcoarse, mgkcoarse, ndom, wr, mgiweight, &
337  use inputphysics, only: equations
338  use inputiteration, only: fcoll, mgboundcorr
341  use utils, only: setpointers, getcorrectfork
342  use haloexchange, only: whalo1, whalo2
345  use turbbcroutines, only: applyallturbbc
346  use bcroutines, only: applyallbc
347  implicit none
348  !
349  ! Subroutine arguments.
350  !
351  logical, intent(in) :: corrections
352  !
353  ! Local variables.
354  !
355  integer(kind=intType) :: sps, nn, i, j, k, l
356  integer(kind=intType) :: ii, jj, kk, ii1, jj1, kk1
357  integer(kind=intType) :: coarseLevel, nVarInt
358 
359  real(kind=realtype) :: fact
360  real(kind=realtype), dimension(:, :, :, :), pointer :: ww, ww1, res
361  real(kind=realtype), dimension(:, :, :), pointer :: pp, pp1
362 
363  logical :: secondHalo, correctForK
364 
365  ! Store the coarse grid level in coarseLevel.
366 
367  coarselevel = currentlevel + 1
368 
369  ! Set the number of variables for which either the corrections
370  ! or the solution must be interpolated. If the corrections must
371  ! be interpolated, this value is set to the number of variables
372  ! to which multigrid must be applied, otherwise all conservative
373  ! variables are interpolated.
374 
375  nvarint = nw
376  if (corrections) nvarint = nwf
377 
378  ! Set the value of secondHalo, depending on the situation.
379  ! In the full MG (currentLevel < groundLevel) the second halo is
380  ! always set; otherwise only on the finest mesh in the current mg
381  ! cycle.
382 
383  if (currentlevel <= groundlevel) then
384  secondhalo = .true.
385  else
386  secondhalo = .false.
387  end if
388 
389  ! Determine whether or not the total energy must be corrected
390  ! for the presence of the turbulent kinetic energy.
391  correctfork = getcorrectfork()
392 
393  ! Set fact to either 0.0 or 1.0, depending whether neumann or
394  ! dirichlet boundary conditions should be used for the boundary
395  ! halo's when interpolating.
396 
397  fact = one
398  if (corrections .and. mgboundcorr == bcdirichlet0) fact = zero
399 
400  ! Loop over the number of spectral solutions and local blocks.
401 
402  spectralloop: do sps = 1, ntimeintervalsspectral
403  domains: do nn = 1, ndom
404 
405  ! Set the pointers to the fine level, i.e. currentLevel.
406  ! Also set the pointers for ww, pp, ww1 and pp1 to the
407  ! coarse grid values.
408 
409  call setpointers(nn, currentlevel, sps)
410  ww => flowdoms(nn, coarselevel, sps)%w
411  pp => flowdoms(nn, coarselevel, sps)%p
412  ww1 => flowdoms(nn, coarselevel, sps)%w1
413  pp1 => flowdoms(nn, coarselevel, sps)%p1
414 
415  ! Store the correction in ww if the corrections must be
416  ! interpolated. The 1st level halo's are included, because
417  ! these values are needed for the interpolation. Note that
418  ! flowDoms(nn,coarseLevel)%ie, etc. must be used, because
419  ! ie is equal to the fine grid value.
420 
421  testcorrections1: if (corrections) then
422 
423  ! Flow field variables. Have res point to dw and compute the
424  ! corrections. Note that the pressure correction must be
425  ! stored instead of the total energy.
426 
427  res => dw
428 
429  do k = 1, flowdoms(nn, coarselevel, sps)%ke
430  do j = 1, flowdoms(nn, coarselevel, sps)%je
431  do i = 1, flowdoms(nn, coarselevel, sps)%ie
432  ww(i, j, k, irho) = ww(i, j, k, irho) - ww1(i, j, k, irho)
433  ww(i, j, k, ivx) = ww(i, j, k, ivx) - ww1(i, j, k, ivx)
434  ww(i, j, k, ivy) = ww(i, j, k, ivy) - ww1(i, j, k, ivy)
435  ww(i, j, k, ivz) = ww(i, j, k, ivz) - ww1(i, j, k, ivz)
436  ww(i, j, k, irhoe) = pp(i, j, k) - pp1(i, j, k)
437  end do
438  end do
439  end do
440 
441  ! The possible turbulent variables.
442 
443  do l = nt1, nvarint
444  do k = 1, flowdoms(nn, coarselevel, sps)%ke
445  do j = 1, flowdoms(nn, coarselevel, sps)%je
446  do i = 1, flowdoms(nn, coarselevel, sps)%ie
447  ww(i, j, k, l) = ww(i, j, k, l) - ww1(i, j, k, l)
448  end do
449  end do
450  end do
451  end do
452 
453  else testcorrections1
454 
455  ! The solution must be interpolated. Have res point to w and
456  ! store the pressure instead of the total energy.
457 
458  res => w
459 
460  do k = 1, flowdoms(nn, coarselevel, sps)%ke
461  do j = 1, flowdoms(nn, coarselevel, sps)%je
462  do i = 1, flowdoms(nn, coarselevel, sps)%ie
463  ww(i, j, k, irhoe) = pp(i, j, k)
464  end do
465  end do
466  end do
467 
468  end if testcorrections1
469 
470  ! Set the values of the coarse grid boundary halo cells.
471 
472  call setcorrectionscoarsehalos(sps, nn, coarselevel, &
473  fact, nvarint)
474 
475  ! Loop over the owned fine grid cells and determine res
476  ! by trilinear interpolation. Note that the coarse grid cell
477  ! ii (and jj and kk) are such that they are closest to the
478  ! fine grid cell center and ii1 is further away. This means
479  ! that in 1d ii get the weight 3/4 and ii1 1/4.
480 
481  do k = 2, kl
482 
483  ! Determine the coarse grid cells kk and kk1.
484 
485  kk = mgkcoarse(k, 1)
486  kk1 = mgkcoarse(k, 2)
487 
488  do j = 2, jl
489 
490  ! Determine the coarse grid cells jj and jj1.
491 
492  jj = mgjcoarse(j, 1)
493  jj1 = mgjcoarse(j, 2)
494 
495  do i = 2, il
496 
497  ! Determine the coarse grid cells ii and ii1.
498 
499  ii = mgicoarse(i, 1)
500  ii1 = mgicoarse(i, 2)
501 
502  ! Loop over the number of variables and interpolate them.
503  ! The weights involved are 27/64, 9/64, 3/64 and 1/64.
504  ! For computational efficiency their (exact) decimal
505  ! counterparts are used in the loop below, which are
506  ! 0.421875, 0.140625, 0.046875 and 0.015625 respectively.
507 
508  do l = 1, nvarint
509  res(i, j, k, l) = 0.421875_realtype * ww(ii, jj, kk, l) &
510  + 0.140625_realtype * (ww(ii1, jj, kk, l) &
511  + ww(ii, jj1, kk, l) &
512  + ww(ii, jj, kk1, l)) &
513  + 0.046875_realtype * (ww(ii1, jj1, kk, l) &
514  + ww(ii1, jj, kk1, l) &
515  + ww(ii, jj1, kk1, l)) &
516  + 0.015625_realtype * ww(ii1, jj1, kk1, l)
517  end do
518 
519  end do
520  end do
521  end do
522 
523  ! Possibility to do smoothing on the corrections, if desired.
524 
525  ! Compute the new state vector on the fine mesh in case the
526  ! corrections have just been interpolated.
527 
528  testcorrections2: if (corrections) then
529 
530  ! Flow field variables. Again the pressure is updated
531  ! and not the total energy. Make sure that the pressure and
532  ! density do not become negative.
533 
534  do k = 2, kl
535  do j = 2, jl
536  do i = 2, il
537  w(i, j, k, irho) = w(i, j, k, irho) + dw(i, j, k, irho)
538  w(i, j, k, ivx) = w(i, j, k, ivx) + dw(i, j, k, ivx)
539  w(i, j, k, ivy) = w(i, j, k, ivy) + dw(i, j, k, ivy)
540  w(i, j, k, ivz) = w(i, j, k, ivz) + dw(i, j, k, ivz)
541  p(i, j, k) = p(i, j, k) + dw(i, j, k, irhoe)
542 
543  w(i, j, k, irho) = max(w(i, j, k, irho), &
544  1.e-4_realtype * rhoinf)
545  p(i, j, k) = max(p(i, j, k), &
546  1.e-4_realtype * pinfcorr)
547  end do
548  end do
549  end do
550 
551  ! The possible turbulent variables.
552 
553  do l = nt1, nvarint
554  do k = 2, kl
555  do j = 2, jl
556  do i = 2, il
557  w(i, j, k, l) = w(i, j, k, l) + dw(i, j, k, l)
558  end do
559  end do
560  end do
561  end do
562 
563  else testcorrections2
564 
565  ! The solution must be interpolated. At the moment the
566  ! pressure is stored at the place of the total energy.
567  ! Copy this value in the pressure array.
568 
569  do k = 2, kl
570  do j = 2, jl
571  do i = 2, il
572  p(i, j, k) = w(i, j, k, irhoe)
573  end do
574  end do
575  end do
576 
577  end if testcorrections2
578 
579  ! Compute the total energy for the owned cells of this block.
580  ! If the solution must be interpolated, extrapolate the
581  ! solution in the halo's.
582 
583  call computeetotblock(2_inttype, il, 2_inttype, jl, &
584  2_inttype, kl, correctfork)
585  if (.not. corrections) call extrapolatesolution
586 
587  ! Compute the laminar viscosity and eddy viscosity for the
588  ! owned cells of this block. If the solution must be
589  ! interpolated, extrapolate the viscosities in the halo's.
590 
591  call computelamviscosity(.false.)
592  call computeeddyviscosity(.false.)
593  if (.not. corrections) call extrapolateviscosities
594 
595  end do domains
596  end do spectralloop
597 
598  ! Exchange the pressure if the pressure must be exchanged early.
599  ! Only the first halo's are needed, thus whalo1 is called.
600  ! On the finest mesh only.
601 
603  call whalo1(currentlevel, 1_inttype, 0_inttype, &
604  .true., .false., .false.)
605 
606  ! Apply all boundary conditions to all blocks on this level.
607  ! In case of a full mg mode, and a segegated turbulent solver,
608  ! first call the turbulent boundary conditions, such that the
609  ! turbulent kinetic energy is properly initialized in the halo's.
610 
611  if (.not. corrections .and. equations == ransequations) then
612  call applyallturbbc(secondhalo)
613  end if
614 
615  ! Apply all boundary conditions of the mean flow.
616 
617  call applyallbc(secondhalo)
618 
619  ! If case this routine is called in full mg mode call the mean
620  ! flow boundary conditions again such that the normal momentum
621  ! boundary condition is treated correctly.
622 
623  if (.not. corrections) call applyallbc(secondhalo)
624 
625  ! Exchange the solution. Either whalo1 or whalo2
626  ! must be called.
627 
628  if (secondhalo) then
629  call whalo2(currentlevel, 1_inttype, nvarint, .true., &
630  .true., .true.)
631  else
632  call whalo1(currentlevel, 1_inttype, nvarint, .true., &
633  .true., .true.)
634  end if
635 
636  ! For full multigrid mode the bleeds must be determined, the
637  ! boundary conditions must be applied one more time and the
638  ! solution must be exchanged again.
639 
640  if (.not. corrections) then
641  call applyallbc(secondhalo)
642 
643  if (secondhalo) then
644  call whalo2(currentlevel, 1_inttype, nvarint, .true., &
645  .true., .true.)
646  else
647  call whalo1(currentlevel, 1_inttype, nvarint, .true., &
648  .true., .true.)
649  end if
650  end if
651 
652  end subroutine transfertofinegrid
653 
654  ! ==================================================================
655 
657  !
658  ! extrapolateSolution sets the solution of the cell halos by a
659  ! constant extrapolation. This routine is called after the
660  ! solution has been interpolated to the next finer grid and this
661  ! routine makes sure that the halo's are initialized.
662  ! Only the block to which the pointers in blockPointers
663  ! currently point is treated.
664  !
665  use blockpointers
666  use flowvarrefstate
667  implicit none
668  !
669  ! Local variables.
670  !
671  integer(kind=intType) :: i, j, k, l
672 
673  ! Constant extrapolation in i-direction.
674 
675  do k = 2, kl
676  do j = 2, jl
677 
678  do l = 1, nw
679  w(0, j, k, l) = w(2, j, k, l)
680  w(1, j, k, l) = w(2, j, k, l)
681  w(ie, j, k, l) = w(il, j, k, l)
682  w(ib, j, k, l) = w(il, j, k, l)
683  end do
684 
685  p(0, j, k) = p(2, j, k)
686  p(1, j, k) = p(2, j, k)
687  p(ie, j, k) = p(il, j, k)
688  p(ib, j, k) = p(il, j, k)
689 
690  end do
691  end do
692 
693  ! Constant extrapolation in the j-direction. Take the just
694  ! interpolated values in i-direction into account.
695 
696  do k = 2, kl
697  do i = 0, ib
698 
699  do l = 1, nw
700  w(i, 0, k, l) = w(i, 2, k, l)
701  w(i, 1, k, l) = w(i, 2, k, l)
702  w(i, je, k, l) = w(i, jl, k, l)
703  w(i, jb, k, l) = w(i, jl, k, l)
704  end do
705 
706  p(i, 0, k) = p(i, 2, k)
707  p(i, 1, k) = p(i, 2, k)
708  p(i, je, k) = p(i, jl, k)
709  p(i, jb, k) = p(i, jl, k)
710 
711  end do
712  end do
713 
714  ! Constant extrapolation in the k-direction. Take the just
715  ! interpolated values in i- and j-direction into account.
716 
717  do j = 0, jb
718  do i = 0, ib
719 
720  do l = 1, nw
721  w(i, j, 0, l) = w(i, j, 2, l)
722  w(i, j, 1, l) = w(i, j, 2, l)
723  w(i, j, ke, l) = w(i, j, kl, l)
724  w(i, j, kb, l) = w(i, j, kl, l)
725  end do
726 
727  p(i, j, 0) = p(i, j, 2)
728  p(i, j, 1) = p(i, j, 2)
729  p(i, j, ke) = p(i, j, kl)
730  p(i, j, kb) = p(i, j, kl)
731 
732  end do
733  end do
734 
735  end subroutine extrapolatesolution
736 
737  ! ==================================================================
738 
740  !
741  ! extrapolateViscosities sets the laminar and eddy viscosities
742  ! of the cell halos by a constant extrapolation. This routine is
743  ! called after the solution has been interpolated to the next
744  ! finer grid and this routine makes sure that the halo's are
745  ! initialized.
746  ! Only the block to which the pointers in blockPointers
747  ! currently point is treated and only for a viscous problem.
748  !
749  use blockpointers
750  use flowvarrefstate
751  implicit none
752  !
753  ! Local variables.
754  !
755  integer(kind=intType) :: i, j, k
756 
757  ! Return immediately if this is not a viscous problem.
758 
759  if (.not. viscous) return
760 
761  ! Constant extrapolation in i-direction.
762 
763  do k = 2, kl
764  do j = 2, jl
765 
766  rlv(0, j, k) = rlv(2, j, k)
767  rlv(1, j, k) = rlv(2, j, k)
768  rlv(ie, j, k) = rlv(il, j, k)
769  rlv(ib, j, k) = rlv(il, j, k)
770 
771  if (eddymodel) then
772  rev(0, j, k) = rev(2, j, k)
773  rev(1, j, k) = rev(2, j, k)
774  rev(ie, j, k) = rev(il, j, k)
775  rev(ib, j, k) = rev(il, j, k)
776  end if
777 
778  end do
779  end do
780 
781  ! Constant extrapolation in the j-direction. Take the just
782  ! interpolated values in i-direction into account.
783 
784  do k = 2, kl
785  do i = 0, ib
786 
787  rlv(i, 0, k) = rlv(i, 2, k)
788  rlv(i, 1, k) = rlv(i, 2, k)
789  rlv(i, je, k) = rlv(i, jl, k)
790  rlv(i, jb, k) = rlv(i, jl, k)
791 
792  if (eddymodel) then
793  rev(i, 0, k) = rev(i, 2, k)
794  rev(i, 1, k) = rev(i, 2, k)
795  rev(i, je, k) = rev(i, jl, k)
796  rev(i, jb, k) = rev(i, jl, k)
797  end if
798 
799  end do
800  end do
801 
802  ! Constant extrapolation in the k-direction. Take the just
803  ! interpolated values in i- and j-direction into account.
804 
805  do j = 0, jb
806  do i = 0, ib
807 
808  rlv(i, j, 0) = rlv(i, j, 2)
809  rlv(i, j, 1) = rlv(i, j, 2)
810  rlv(i, j, ke) = rlv(i, j, kl)
811  rlv(i, j, kb) = rlv(i, j, kl)
812 
813  if (eddymodel) then
814  rev(i, j, 0) = rev(i, j, 2)
815  rev(i, j, 1) = rev(i, j, 2)
816  rev(i, j, ke) = rev(i, j, kl)
817  rev(i, j, kb) = rev(i, j, kl)
818  end if
819 
820  end do
821  end do
822 
823  end subroutine extrapolateviscosities
824 
825  subroutine executemgcycle
826  !
827  ! executeMGCycle performs a multigrid cycle defined by
828  ! cycling, see the module iteration.
829  !
830  use flowvarrefstate
831  use iteration
832  use inputiteration
833  use inputphysics
834  use utils, only: terminate
835  use turbapi, only: turbsolveddadi
836  use solverutils, only: timestep, computeutau
839  implicit none
840  !
841  ! Local variables.
842  !
843  integer(kind=intType) :: nn
844 
845  ! Initialize currentLevel to groundLevel, the ground level
846  ! of this multigrid cycle.
847 
849 
850  ! Loop over the number of steps in cycling.
851 
852  mgloop: do nn = 1, nstepscycling
853 
854  ! Determine what must be done.
855 
856  select case (cycling(nn))
857 
858  case (-1_inttype)
859 
860  ! Set the new currentLevel and and prolongate the
861  ! the corrections to this grid level.
862 
864  call transfertofinegrid(.true.)
865 
866  case (0_inttype)
867 
868  ! Perform a smoothing iteration on this grid level.
869  ! First determine the current situation. If this is the
870  ! first entry in cycling the residual already contains the
871  ! correct values and therefore it needs not to be computed.
872 
873  if (nn > 1) then
874 
875  ! Compute the residual if the previous action was not a
876  ! restriction. In that case the residual already contains
877  ! the correct values.
878 
879  if (cycling(nn - 1) /= 1_inttype) then
880 
881  ! Initialize and compute the residual.
882 
883  rkstage = 0
884  call timestep(.false.)
885 
886  call initres(1_inttype, nwf)
887  call sourceterms()
888  call residual
889 
890  end if
891  end if
892 
893  ! Perform a smoothing step. Determine the smoother to
894  ! be used and call the appropriate routine.
895 
896  select case (smoother)
897  case (rungekutta)
898  call rungekuttasmoother
899  itertype = " RK"
900  case (dadi)
901  call dadismoother
902  itertype = " DADI"
903  case (nllusgs)
904  call terminate("executeMGCycle", &
905  "nlLusgs smoother not implemented yet")
906  case (nllusgsline)
907  call terminate("executeMGCycle", &
908  "nlLusgsLine smoother not implemented &
909  &yet")
910  end select
911 
912  case (1_inttype)
913 
914  ! Restrict the solution and residual to the next coarser
915  ! grid level. Inside transferToCoarseGrid currentLevel
916  ! is updated.
917 
919 
920  end select
921 
922  end do mgloop
923 
924  ! Reset the values of rkStage and currentLevel, such that
925  ! they correspond to a new iteration.
926 
927  rkstage = 0
929 
930  ! Compute the latest values of the skin friction velocity.
931  ! The currently stored values are of the previous iteration.
932 
933  call computeutau
934 
935  ! Apply an iteration to the turbulent transport equations in
936  ! case these must be solved separately.
937 
938  if (equations == ransequations) then
939  call turbsolveddadi
940  end if
941 
942  ! Compute the time step.
943 
944  call timestep(.false.)
945 
946  ! Compute the residual of the new solution on the ground level.
947 
948  call initres(1_inttype, nwf)
949  call sourceterms()
950  call residual
951 
952  ! Set some information for monitoring purposes
954 
955  end subroutine executemgcycle
956 
957  subroutine setcyclestrategy
958  !
959  ! setCycleStrategy sets the multigrid cycling strategy for the
960  ! multigrid level groundLevel. It is cycle strategy for the
961  ! fine grid cut off at the current grid level. If the grid level
962  ! is not in the range of the fine grid cycle strategy, cycling
963  ! will be set to a single grid strategy.
964  !
965  use constants
968  use utils, only: returnfail
969  implicit none
970  !
971  ! Local variables.
972  !
973  integer(kind=intType) :: i
974  integer(kind=intType) :: thisLevel, maxLevel
975 
976  ! Initialize thisLevel and maxLevel to 1, i.e. the finest grid.
977 
978  thislevel = 1
979  maxlevel = 1
980 
981  ! Determine the cycling strategy for groundLevel by looping over
982  ! the fine grid cycling strategy and picking the correct entries.
983 
984  nstepscycling = 0
985  do i = 1, nmgsteps
986  thislevel = thislevel + cyclestrategy(i)
987  maxlevel = max(maxlevel, thislevel)
988 
989  ! Store this entry in cycling if a) we are on a coarser grid
990  ! than groundLevel or b) if we are on groundLevel and
991  ! cycleStrategy(i) does not correspond to a restriction,
992  ! i.e. 1.
993 
994  if ((thislevel == groundlevel .and. cyclestrategy(i) /= 1) .or. &
995  thislevel > groundlevel) then
998  end if
999 
1000  ! Break the loop if a cycle on the current grid level has
1001  ! been completed.
1002 
1003  if (thislevel == groundlevel .and. cyclestrategy(i) == -1) exit
1004 
1005  end do
1006 
1007  ! Take care of the case that groundLevel >= maxLevel.
1008  ! In this case a single grid strategy is used.
1009 
1010  if (groundlevel >= maxlevel) then
1011  nstepscycling = 1
1012  cycling(1) = 0
1013  end if
1014 
1015  ! Check in debug mode if the multigrid strategy created is
1016  ! a valid one.
1017 
1018  if (debug) then
1019 
1020  thislevel = 0
1021  do i = 1, nstepscycling
1022  thislevel = thislevel + cycling(i)
1023  end do
1024 
1025  if (thislevel /= 0) &
1026  call returnfail("setCyleStrategy", "Invalid strategy created")
1027 
1028  end if
1029 
1030  end subroutine setcyclestrategy
1031 
1032  subroutine setcornerrowhalos(nVar)
1033  !
1034  ! setCornerRowHalos initializes the halo's next to corner row
1035  ! halo's, such that it contains some values. Otherwise it may
1036  ! be uninitialized or cause a floating point exception, as this
1037  ! memory is also used to compute the mg corrections.
1038  ! It is assumed that the pointers in blockPointers already
1039  ! point to the correct block.
1040  !
1041  use constants
1042  use blockpointers, only: w, p, rlv, rev, nx, ny, nz, &
1043  il, ie, jl, je, kl, ke
1044  use flowvarrefstate, only: eddymodel, viscous
1045  implicit none
1046  !
1047  ! Subroutine arguments
1048  !
1049  integer(kind=intType), intent(in) :: nVar
1050  !
1051  ! Local variables.
1052  !
1053  integer(kind=intType) :: i, j, k, l, mm, ll
1054 
1055  ! Halo's on the i=iMin and i=iMax plane.
1056  !
1057  ! K-rows.
1058 
1059  mm = min(3_inttype, jl)
1060  ll = max(2_inttype, ny)
1061 
1062  do k = 2, kl
1063  do l = 1, nvar
1064  w(1, 2, k, l) = w(2, 2, k, l)
1065  w(1, mm, k, l) = w(2, mm, k, l)
1066  w(1, jl, k, l) = w(2, jl, k, l)
1067  w(1, ll, k, l) = w(2, ll, k, l)
1068  w(ie, 2, k, l) = w(il, 2, k, l)
1069  w(ie, mm, k, l) = w(il, mm, k, l)
1070  w(ie, jl, k, l) = w(il, jl, k, l)
1071  w(ie, ll, k, l) = w(il, ll, k, l)
1072  end do
1073 
1074  p(1, 2, k) = p(2, 2, k)
1075  p(1, mm, k) = p(2, mm, k)
1076  p(1, jl, k) = p(2, jl, k)
1077  p(1, ll, k) = p(2, ll, k)
1078  p(ie, 2, k) = p(il, 2, k)
1079  p(ie, mm, k) = p(il, mm, k)
1080  p(ie, jl, k) = p(il, jl, k)
1081  p(ie, ll, k) = p(il, ll, k)
1082 
1083  if (viscous) then
1084  rlv(1, 2, k) = rlv(2, 2, k)
1085  rlv(1, mm, k) = rlv(2, mm, k)
1086  rlv(1, jl, k) = rlv(2, jl, k)
1087  rlv(1, ll, k) = rlv(2, ll, k)
1088  rlv(ie, 2, k) = rlv(il, 2, k)
1089  rlv(ie, mm, k) = rlv(il, mm, k)
1090  rlv(ie, jl, k) = rlv(il, jl, k)
1091  rlv(ie, ll, k) = rlv(il, ll, k)
1092  end if
1093 
1094  if (eddymodel) then
1095  rev(1, 2, k) = rev(2, 2, k)
1096  rev(1, mm, k) = rev(2, mm, k)
1097  rev(1, jl, k) = rev(2, jl, k)
1098  rev(1, ll, k) = rev(2, ll, k)
1099  rev(ie, 2, k) = rev(il, 2, k)
1100  rev(ie, mm, k) = rev(il, mm, k)
1101  rev(ie, jl, k) = rev(il, jl, k)
1102  rev(ie, ll, k) = rev(il, ll, k)
1103  end if
1104  end do
1105 
1106  ! J-rows; no need to include the corners. These have been set in
1107  ! the previous k-loop.
1108 
1109  mm = min(3_inttype, kl)
1110  ll = max(2_inttype, nz)
1111 
1112  do j = 3, ny
1113  do l = 1, nvar
1114  w(1, j, 2, l) = w(2, j, 2, l)
1115  w(1, j, mm, l) = w(2, j, mm, l)
1116  w(1, j, kl, l) = w(2, j, kl, l)
1117  w(1, j, ll, l) = w(2, j, ll, l)
1118  w(ie, j, 2, l) = w(il, j, 2, l)
1119  w(ie, j, mm, l) = w(il, j, mm, l)
1120  w(ie, j, kl, l) = w(il, j, kl, l)
1121  w(ie, j, ll, l) = w(il, j, ll, l)
1122  end do
1123 
1124  p(1, j, 2) = p(2, j, 2)
1125  p(1, j, mm) = p(2, j, mm)
1126  p(1, j, kl) = p(2, j, kl)
1127  p(1, j, ll) = p(2, j, ll)
1128  p(ie, j, 2) = p(il, j, 2)
1129  p(ie, j, mm) = p(il, j, mm)
1130  p(ie, j, kl) = p(il, j, kl)
1131  p(ie, j, ll) = p(il, j, ll)
1132 
1133  if (viscous) then
1134  rlv(1, j, 2) = rlv(2, j, 2)
1135  rlv(1, j, mm) = rlv(2, j, mm)
1136  rlv(1, j, kl) = rlv(2, j, kl)
1137  rlv(1, j, ll) = rlv(2, j, ll)
1138  rlv(ie, j, 2) = rlv(il, j, 2)
1139  rlv(ie, j, mm) = rlv(il, j, mm)
1140  rlv(ie, j, kl) = rlv(il, j, kl)
1141  rlv(ie, j, ll) = rlv(il, j, ll)
1142  end if
1143 
1144  if (eddymodel) then
1145  rev(1, j, 2) = rev(2, j, 2)
1146  rev(1, j, mm) = rev(2, j, mm)
1147  rev(1, j, kl) = rev(2, j, kl)
1148  rev(1, j, ll) = rev(2, j, ll)
1149  rev(ie, j, 2) = rev(il, j, 2)
1150  rev(ie, j, mm) = rev(il, j, mm)
1151  rev(ie, j, kl) = rev(il, j, kl)
1152  rev(ie, j, ll) = rev(il, j, ll)
1153  end if
1154  end do
1155  !
1156  ! Halo's on the j=jMin and j=jMax plane.
1157  !
1158  ! K-rows; no need to include the corners; this is done in the
1159  ! next i-loop.
1160 
1161  mm = min(3_inttype, il)
1162  ll = max(2_inttype, nx)
1163 
1164  do k = 3, nz
1165  do l = 1, nvar
1166  w(2, 1, k, l) = w(2, 2, k, l)
1167  w(mm, 1, k, l) = w(mm, 2, k, l)
1168  w(il, 1, k, l) = w(il, 2, k, l)
1169  w(ll, 1, k, l) = w(ll, 2, k, l)
1170  w(2, je, k, l) = w(2, jl, k, l)
1171  w(mm, je, k, l) = w(mm, jl, k, l)
1172  w(il, je, k, l) = w(il, jl, k, l)
1173  w(ll, je, k, l) = w(ll, jl, k, l)
1174  end do
1175 
1176  p(2, 1, k) = p(2, 2, k)
1177  p(mm, 1, k) = p(mm, 2, k)
1178  p(il, 1, k) = p(il, 2, k)
1179  p(ll, 1, k) = p(ll, 2, k)
1180  p(2, je, k) = p(2, jl, k)
1181  p(mm, je, k) = p(mm, jl, k)
1182  p(il, je, k) = p(il, jl, k)
1183  p(ll, je, k) = p(ll, jl, k)
1184 
1185  if (viscous) then
1186  rlv(2, 1, k) = rlv(2, 2, k)
1187  rlv(mm, 1, k) = rlv(mm, 2, k)
1188  rlv(il, 1, k) = rlv(il, 2, k)
1189  rlv(ll, 1, k) = rlv(ll, 2, k)
1190  rlv(2, je, k) = rlv(2, jl, k)
1191  rlv(mm, je, k) = rlv(mm, jl, k)
1192  rlv(il, je, k) = rlv(il, jl, k)
1193  rlv(ll, je, k) = rlv(ll, jl, k)
1194  end if
1195 
1196  if (eddymodel) then
1197  rev(2, 1, k) = rev(2, 2, k)
1198  rev(mm, 1, k) = rev(mm, 2, k)
1199  rev(il, 1, k) = rev(il, 2, k)
1200  rev(ll, 1, k) = rev(ll, 2, k)
1201  rev(2, je, k) = rev(2, jl, k)
1202  rev(mm, je, k) = rev(mm, jl, k)
1203  rev(il, je, k) = rev(il, jl, k)
1204  rev(ll, je, k) = rev(ll, jl, k)
1205  end if
1206  end do
1207 
1208  ! I-rows, including halo's set on the iMin and iMax plane.
1209 
1210  mm = min(3_inttype, kl)
1211  ll = max(2_inttype, nz)
1212 
1213  do i = 1, ie
1214  do l = 1, nvar
1215  w(i, 1, 2, l) = w(i, 2, 2, l)
1216  w(i, 1, mm, l) = w(i, 2, mm, l)
1217  w(i, 1, kl, l) = w(i, 2, kl, l)
1218  w(i, 1, ll, l) = w(i, 2, ll, l)
1219  w(i, je, 2, l) = w(i, jl, 2, l)
1220  w(i, je, mm, l) = w(i, jl, mm, l)
1221  w(i, je, kl, l) = w(i, jl, kl, l)
1222  w(i, je, ll, l) = w(i, jl, ll, l)
1223  end do
1224 
1225  p(i, 1, 2) = p(i, 2, 2)
1226  p(i, 1, mm) = p(i, 2, mm)
1227  p(i, 1, kl) = p(i, 2, kl)
1228  p(i, 1, ll) = p(i, 2, ll)
1229  p(i, je, 2) = p(i, jl, 2)
1230  p(i, je, mm) = p(i, jl, mm)
1231  p(i, je, kl) = p(i, jl, kl)
1232  p(i, je, ll) = p(i, jl, ll)
1233 
1234  if (viscous) then
1235  rlv(i, 1, 2) = rlv(i, 2, 2)
1236  rlv(i, 1, mm) = rlv(i, 2, mm)
1237  rlv(i, 1, kl) = rlv(i, 2, kl)
1238  rlv(i, 1, ll) = rlv(i, 2, ll)
1239  rlv(i, je, 2) = rlv(i, jl, 2)
1240  rlv(i, je, mm) = rlv(i, jl, mm)
1241  rlv(i, je, kl) = rlv(i, jl, kl)
1242  rlv(i, je, ll) = rlv(i, jl, ll)
1243  end if
1244 
1245  if (eddymodel) then
1246  rev(i, 1, 2) = rev(i, 2, 2)
1247  rev(i, 1, mm) = rev(i, 2, mm)
1248  rev(i, 1, kl) = rev(i, 2, kl)
1249  rev(i, 1, ll) = rev(i, 2, ll)
1250  rev(i, je, 2) = rev(i, jl, 2)
1251  rev(i, je, mm) = rev(i, jl, mm)
1252  rev(i, je, kl) = rev(i, jl, kl)
1253  rev(i, je, ll) = rev(i, jl, ll)
1254  end if
1255  end do
1256  !
1257  ! Halo's on the k=kMin and k=kMax plane.
1258  !
1259  ! J-rows, including halo's set on the jMin and jMax plane.
1260 
1261  mm = min(3_inttype, il)
1262  ll = max(2_inttype, nx)
1263 
1264  do j = 1, je
1265  do l = 1, nvar
1266  w(2, j, 1, l) = w(2, j, 2, l)
1267  w(mm, j, 1, l) = w(mm, j, 2, l)
1268  w(il, j, 1, l) = w(il, j, 2, l)
1269  w(ll, j, 1, l) = w(ll, j, 2, l)
1270  w(2, j, ke, l) = w(2, j, kl, l)
1271  w(mm, j, ke, l) = w(mm, j, kl, l)
1272  w(il, j, ke, l) = w(il, j, kl, l)
1273  w(ll, j, ke, l) = w(ll, j, kl, l)
1274  end do
1275 
1276  p(2, j, 1) = p(2, j, 2)
1277  p(mm, j, 1) = p(mm, j, 2)
1278  p(il, j, 1) = p(il, j, 2)
1279  p(ll, j, 1) = p(ll, j, 2)
1280  p(2, j, ke) = p(2, j, kl)
1281  p(mm, j, ke) = p(mm, j, kl)
1282  p(il, j, ke) = p(il, j, kl)
1283  p(ll, j, ke) = p(ll, j, kl)
1284 
1285  if (viscous) then
1286  rlv(2, j, 1) = rlv(2, j, 2)
1287  rlv(mm, j, 1) = rlv(mm, j, 2)
1288  rlv(il, j, 1) = rlv(il, j, 2)
1289  rlv(ll, j, 1) = rlv(ll, j, 2)
1290  rlv(2, j, ke) = rlv(2, j, kl)
1291  rlv(mm, j, ke) = rlv(mm, j, kl)
1292  rlv(il, j, ke) = rlv(il, j, kl)
1293  rlv(ll, j, ke) = rlv(ll, j, kl)
1294  end if
1295 
1296  if (eddymodel) then
1297  rev(2, j, 1) = rev(2, j, 2)
1298  rev(mm, j, 1) = rev(mm, j, 2)
1299  rev(il, j, 1) = rev(il, j, 2)
1300  rev(ll, j, 1) = rev(ll, j, 2)
1301  rev(2, j, ke) = rev(2, j, kl)
1302  rev(mm, j, ke) = rev(mm, j, kl)
1303  rev(il, j, ke) = rev(il, j, kl)
1304  rev(ll, j, ke) = rev(ll, j, kl)
1305  end if
1306  end do
1307 
1308  ! I-rows, including halo's set on the iMin and iMax plane.
1309 
1310  mm = min(3_inttype, jl)
1311  ll = max(2_inttype, ny)
1312 
1313  do i = 1, ie
1314  do l = 1, nvar
1315  w(i, 2, 1, l) = w(i, 2, 2, l)
1316  w(i, mm, 1, l) = w(i, mm, 2, l)
1317  w(i, jl, 1, l) = w(i, jl, 2, l)
1318  w(i, ll, 1, l) = w(i, ll, 2, l)
1319  w(i, 2, ke, l) = w(i, 2, kl, l)
1320  w(i, mm, ke, l) = w(i, mm, kl, l)
1321  w(i, jl, ke, l) = w(i, jl, kl, l)
1322  w(i, ll, ke, l) = w(i, ll, kl, l)
1323  end do
1324 
1325  p(i, 2, 1) = p(i, 2, 2)
1326  p(i, mm, 1) = p(i, mm, 2)
1327  p(i, jl, 1) = p(i, jl, 2)
1328  p(i, ll, 1) = p(i, ll, 2)
1329  p(i, 2, ke) = p(i, 2, kl)
1330  p(i, mm, ke) = p(i, mm, kl)
1331  p(i, jl, ke) = p(i, jl, kl)
1332  p(i, ll, ke) = p(i, ll, kl)
1333 
1334  if (viscous) then
1335  rlv(i, 2, 1) = rlv(i, 2, 2)
1336  rlv(i, mm, 1) = rlv(i, mm, 2)
1337  rlv(i, jl, 1) = rlv(i, jl, 2)
1338  rlv(i, ll, 1) = rlv(i, ll, 2)
1339  rlv(i, 2, ke) = rlv(i, 2, kl)
1340  rlv(i, mm, ke) = rlv(i, mm, kl)
1341  rlv(i, jl, ke) = rlv(i, jl, kl)
1342  rlv(i, ll, ke) = rlv(i, ll, kl)
1343  end if
1344 
1345  if (eddymodel) then
1346  rev(i, 2, 1) = rev(i, 2, 2)
1347  rev(i, mm, 1) = rev(i, mm, 2)
1348  rev(i, jl, 1) = rev(i, jl, 2)
1349  rev(i, ll, 1) = rev(i, ll, 2)
1350  rev(i, 2, ke) = rev(i, 2, kl)
1351  rev(i, mm, ke) = rev(i, mm, kl)
1352  rev(i, jl, ke) = rev(i, jl, kl)
1353  rev(i, ll, ke) = rev(i, ll, kl)
1354  end if
1355  end do
1356 
1357  end subroutine setcornerrowhalos
1358 
1359  subroutine setcorrectionscoarsehalos(sps, nn, coarseLevel, &
1360  fact, nVarInt)
1361  !
1362  ! setCorrectionsCoarseHalos sets the values of the coarse
1363  ! grid boundary halo corrections. For all boundaries, either a
1364  ! homogeneous Dirichlet condition (fact = 0.0) or a Neumann
1365  ! condition (fact = 1.0) is used. Exception are symmetry planes,
1366  ! where a mirroring takes place.
1367  !
1368  use constants
1369  use block, only: bcdatatype, flowdoms
1370  use flowvarrefstate, only: nt1
1371  implicit none
1372  !
1373  ! Subroutine arguments.
1374  !
1375  integer(kind=intType), intent(in) :: sps, nn, coarseLevel
1376  integer(kind=intType), intent(in) :: nVarInt
1377  real(kind=realtype), intent(in) :: fact
1378  !
1379  ! Local variables.
1380  !
1381  integer(kind=intType) :: i, j, l, mm
1382  integer(kind=intType) :: il, jl, kl, ie, je, ke
1383 
1384  real(kind=realtype) :: nnx, nny, nnz, vn
1385 
1386  real(kind=realtype), dimension(:, :, :, :), pointer :: ww
1387  real(kind=realtype), dimension(:, :, :), pointer :: ww1, ww2
1388 
1389  type(bcdatatype), dimension(:), pointer :: bcdata
1390 
1391  ! Set the pointer ww to the coarse grid variables. At the moment
1392  ! when this routine is called, these contain the corrections in a
1393  ! normal grid cycle and the true variables when used to
1394  ! interpolate the solution to the next finer mesh level in full
1395  ! multigrid mode. Also set the pointer for BCData, such that the
1396  ! unit normals are accessed easier.
1397 
1398  ww => flowdoms(nn, coarselevel, sps)%w
1399  bcdata => flowdoms(nn, coarselevel, sps)%BCData
1400 
1401  ! Easier storage of the upper coarse block range.
1402 
1403  il = flowdoms(nn, coarselevel, sps)%il
1404  jl = flowdoms(nn, coarselevel, sps)%jl
1405  kl = flowdoms(nn, coarselevel, sps)%kl
1406 
1407  ie = flowdoms(nn, coarselevel, sps)%ie
1408  je = flowdoms(nn, coarselevel, sps)%je
1409  ke = flowdoms(nn, coarselevel, sps)%ke
1410 
1411  ! Loop over the number of boundary subfaces to correct the
1412  ! boundary halo values.
1413 
1414  subfacescoarse: do mm = 1, flowdoms(nn, coarselevel, sps)%nBocos
1415 
1416  ! Set the pointers for ww1 and ww2, depending on the block face
1417  ! on which this subface is located. Note that bcFaceID is the
1418  ! same for all spectral modes and only the 1st is allocated.
1419  ! Therefore the value of the 1st spectral mode is used here.
1420 
1421  select case (flowdoms(nn, coarselevel, 1)%BCFaceID(mm))
1422 
1423  case (imin)
1424  ww1 => ww(1, 1:, 1:, :); ww2 => ww(2, 1:, 1:, :)
1425  case (imax)
1426  ww1 => ww(ie, 1:, 1:, :); ww2 => ww(il, 1:, 1:, :)
1427  case (jmin)
1428  ww1 => ww(1:, 1, 1:, :); ww2 => ww(1:, 2, 1:, :)
1429  case (jmax)
1430  ww1 => ww(1:, je, 1:, :); ww2 => ww(1:, jl, 1:, :)
1431  case (kmin)
1432  ww1 => ww(1:, 1:, 1, :); ww2 => ww(1:, 1:, 2, :)
1433  case (kmax)
1434  ww1 => ww(1:, 1:, ke, :); ww2 => ww(1:, 1:, kl, :)
1435 
1436  end select
1437 
1438  ! Choose what to do based on the BC type. Note that BCType is
1439  ! the same for all spectral modes and only the 1st is allocated.
1440  ! Therefore the value of the 1st spectral mode is used here.
1441 
1442  select case (flowdoms(nn, coarselevel, 1)%BCType(mm))
1443 
1448 
1449  ! None of these are physical boundary conditions and thus
1450  ! nothing needs to be done. The halos already contain the
1451  ! corrections or solution.
1452 
1453  case (symm)
1454 
1455  ! This is a symmetry plane. Loop over the faces of this
1456  ! subface.
1457 
1458  do j = bcdata(mm)%jcBeg, bcdata(mm)%jcEnd
1459  do i = bcdata(mm)%icBeg, bcdata(mm)%icEnd
1460 
1461  ! Compute twice the normal velocity component of the
1462  ! internal cell.
1463 
1464  nnx = bcdata(mm)%norm(i, j, 1)
1465  nny = bcdata(mm)%norm(i, j, 2)
1466  nnz = bcdata(mm)%norm(i, j, 3)
1467 
1468  vn = two * (ww2(i, j, ivx) * nnx + ww2(i, j, ivy) * nny &
1469  + ww2(i, j, ivz) * nnz)
1470 
1471  ! Compute the halo state. Make sure that the average
1472  ! normal velocity component is zero.
1473 
1474  ww1(i, j, irho) = ww2(i, j, irho)
1475  ww1(i, j, ivx) = ww2(i, j, ivx) - vn * nnx
1476  ww1(i, j, ivy) = ww2(i, j, ivy) - vn * nny
1477  ww1(i, j, ivz) = ww2(i, j, ivz) - vn * nnz
1478  ww1(i, j, irhoe) = ww2(i, j, irhoe)
1479 
1480  do l = nt1, nvarint
1481  ww1(i, j, l) = ww2(i, j, l)
1482  end do
1483 
1484  end do
1485  end do
1486 
1487  case default
1488 
1489  ! Other type of boundary subface. Set the boundary halo's
1490  ! as fact times the internal cell value.
1491 
1492  do l = 1, nvarint
1493  do j = bcdata(mm)%jcBeg, bcdata(mm)%jcEnd
1494  do i = bcdata(mm)%icBeg, bcdata(mm)%icEnd
1495  ww1(i, j, l) = fact * ww2(i, j, l)
1496  end do
1497  end do
1498  end do
1499 
1500  end select
1501  end do subfacescoarse
1502 
1503  end subroutine setcorrectionscoarsehalos
1504 
1505 end module multigrid
Definition: BCData.F90:1
subroutine applyallbc(secondHalo)
Definition: BCRoutines.F90:16
Definition: block.F90:1
type(blocktype), dimension(:, :, :), allocatable, target flowdoms
Definition: block.F90:771
real(kind=realtype), dimension(:, :, :, :), pointer w1
integer(kind=inttype), dimension(:, :), pointer mgjcoarse
integer(kind=inttype) jl
integer(kind=inttype), dimension(:, :), pointer mgkcoarse
real(kind=realtype), dimension(:, :, :, :), pointer wr
integer(kind=inttype), dimension(:, :), pointer mgifine
integer(kind=inttype) nx
real(kind=realtype), dimension(:, :, :), pointer p
integer(kind=inttype) ny
integer(kind=inttype) ie
real(kind=realtype), dimension(:, :, :, :), pointer w
real(kind=realtype), dimension(:, :, :), pointer p1
integer(kind=inttype), dimension(:, :), pointer mgjfine
integer(kind=inttype), dimension(:, :, :), pointer iblank
integer(kind=inttype) jb
integer(kind=inttype), dimension(:, :), pointer mgicoarse
integer(kind=inttype) kb
real(kind=realtype), dimension(:, :, :), pointer rlv
integer(kind=inttype), dimension(:, :), pointer mgkfine
real(kind=realtype), dimension(:, :, :), pointer rev
real(kind=realtype), dimension(:, :, :, :), pointer dw
real(kind=realtype), dimension(:), pointer mgkweight
integer(kind=inttype) ib
real(kind=realtype), dimension(:), pointer mgiweight
integer(kind=inttype) nz
integer(kind=inttype) je
integer(kind=inttype) ke
real(kind=realtype), dimension(:), pointer mgjweight
integer(kind=inttype) kl
integer(kind=inttype) il
integer(kind=inttype), parameter domaininterfacep
Definition: constants.F90:279
integer(kind=inttype), parameter slidinginterface
Definition: constants.F90:275
integer(kind=inttype), parameter oversetouterbound
Definition: constants.F90:276
real(kind=realtype), parameter zero
Definition: constants.F90:71
integer(kind=inttype), parameter domaininterfacerhouvw
Definition: constants.F90:278
integer(kind=inttype), parameter domaininterfacerho
Definition: constants.F90:280
integer(kind=inttype), parameter imax
Definition: constants.F90:293
integer(kind=inttype), parameter kmin
Definition: constants.F90:296
integer(kind=inttype), parameter jmax
Definition: constants.F90:295
integer, parameter irho
Definition: constants.F90:34
integer, parameter imx
Definition: constants.F90:65
integer(kind=inttype), parameter symm
Definition: constants.F90:258
integer, parameter ivx
Definition: constants.F90:35
integer(kind=inttype), parameter bcdirichlet0
Definition: constants.F90:214
integer, parameter irhoe
Definition: constants.F90:38
real(kind=realtype), parameter one
Definition: constants.F90:72
integer(kind=inttype), parameter imin
Definition: constants.F90:292
integer(kind=inttype), parameter domaininterfacetotal
Definition: constants.F90:281
integer, parameter ivz
Definition: constants.F90:37
real(kind=realtype), parameter two
Definition: constants.F90:73
integer, parameter imz
Definition: constants.F90:67
integer(kind=inttype), parameter domaininterfaceall
Definition: constants.F90:277
integer, parameter imy
Definition: constants.F90:66
integer(kind=inttype), parameter kmax
Definition: constants.F90:297
integer, parameter ivy
Definition: constants.F90:36
integer(kind=inttype), parameter ransequations
Definition: constants.F90:110
integer(kind=inttype), parameter jmin
Definition: constants.F90:294
subroutine computelamviscosity(includeHalos)
Definition: flowUtils.F90:1202
subroutine computeetotblock(iStart, iEnd, jStart, jEnd, kStart, kEnd, correctForK)
Definition: flowUtils.F90:553
integer(kind=inttype) nt1
real(kind=realtype) pinfcorr
integer(kind=inttype) nwf
integer(kind=inttype) nw
real(kind=realtype) rhoinf
subroutine whalo2(level, start, end, commPressure, commGamma, commViscous)
subroutine whalo1(level, start, end, commPressure, commGamma, commViscous)
Definition: haloExchange.F90:7
integer(kind=inttype) smoother
Definition: inputParam.F90:264
integer(kind=inttype) nmgsteps
Definition: inputParam.F90:271
integer(kind=inttype), dimension(:), allocatable cyclestrategy
Definition: inputParam.F90:273
integer(kind=inttype) mgboundcorr
Definition: inputParam.F90:270
real(kind=realtype) fcoll
Definition: inputParam.F90:275
integer(kind=inttype) equations
Definition: inputParam.F90:583
integer(kind=inttype) ntimeintervalsspectral
Definition: inputParam.F90:645
integer(kind=inttype) currentlevel
Definition: iteration.f90:18
character(len=maxitertypelen) itertype
Definition: iteration.f90:84
integer(kind=inttype), dimension(:), allocatable cycling
Definition: iteration.f90:26
integer(kind=inttype) groundlevel
Definition: iteration.f90:18
integer(kind=inttype) rkstage
Definition: iteration.f90:19
logical exchangepressureearly
Definition: iteration.f90:53
integer(kind=inttype) approxtotalits
Definition: iteration.f90:93
integer(kind=inttype) nstepscycling
Definition: iteration.f90:25
subroutine extrapolatesolution
Definition: multiGrid.F90:657
subroutine transfertocoarsegrid
Definition: multiGrid.F90:6
subroutine setcorrectionscoarsehalos(sps, nn, coarseLevel, fact, nVarInt)
Definition: multiGrid.F90:1361
subroutine executemgcycle
Definition: multiGrid.F90:826
subroutine setcornerrowhalos(nVar)
Definition: multiGrid.F90:1033
subroutine extrapolateviscosities
Definition: multiGrid.F90:740
subroutine setcyclestrategy
Definition: multiGrid.F90:958
subroutine transfertofinegrid(corrections)
Definition: multiGrid.F90:327
subroutine sourceterms
Definition: residuals.F90:1004
subroutine residual
Definition: residuals.F90:1029
subroutine initres(varStart, varEnd)
Definition: residuals.F90:965
subroutine rungekuttasmoother
Definition: smoothers.F90:5
subroutine dadismoother
Definition: smoothers.F90:384
subroutine computeutau
subroutine timestep(onlyRadii)
Definition: solverUtils.F90:5
subroutine turbsolveddadi
Definition: turbAPI.F90:5
subroutine applyallturbbc(secondHalo)
subroutine computeeddyviscosity(includeHalos)
Definition: turbUtils.F90:581
Definition: utils.F90:1
subroutine returnfail(routineName, errorMessage)
Definition: utils.F90:5606
logical function getcorrectfork()
Definition: utils.F90:487
subroutine setpointers(nn, mm, ll)
Definition: utils.F90:3237
subroutine terminate(routineName, errorMessage)
Definition: utils.F90:502