ADflow  v1.0
ADflow is a finite volume RANS solver tailored for gradient-based aerodynamic design optimization.
oversetUtilities.F90
Go to the documentation of this file.
2 contains
3 #ifndef USE_TAPENADE
4 
5  subroutine tic(index)
6  use constants
7  use oversetdata, only: tstart
8  implicit none
9  integer(kind=intType), intent(in) :: index
10  tstart(index) = mpi_wtime()
11 
12  end subroutine tic
13 
14  subroutine toc(index)
15  use constants
16  use oversetdata, only: tstart, oversettimes
17  implicit none
18  integer(kind=intType), intent(in) :: index
19  oversettimes(index) = oversettimes(index) + mpi_wtime() - tstart(index)
20  end subroutine toc
21 
22  subroutine unwindindex(index, il, jl, kl, i, j, k)
23  ! Unwind a 1-based index based on the double halo size of 0:ib,
24  ! 0:jb, 0:kb
25  use constants
26  implicit none
27  integer(kind=intType), intent(in) :: index, il, jl, kl
28  integer(kind=intType), intent(out) :: i, j, k
29  integer(kind=intType) :: ID, isize, jsize, ksize
30  id = index - 1
31  isize = il + 3
32  jsize = jl + 3
33  ksize = kl + 3
34  i = mod(id, isize)
35  j = mod(id / isize, jsize)
36  k = id / (isize * jsize)
37 
38  end subroutine unwindindex
39 
40  function windindex(i, j, k, il, jl, kl)
41 
42  use constants
43  implicit none
44  integer(kind=intType), intent(in) :: i, j, k, il, jl, kl
45  integer(kind=intType) :: isize, jsize, ksize, windindex
46 
47  isize = il + 3
48  jsize = jl + 3
49  ksize = kl + 3
50 
51  windindex = k * isize * jsize + j * isize + i + 1
52 
53  end function windindex
54 
55  subroutine printoverlapmatrix(overlap)
56 
57  ! This is a debugging routine to print out the overlap matrix.
58  use constants
59  use communication, only: myid
60  use oversetdata, only: csrmatrix
61  implicit none
62 
63  ! Input/output
64  type(csrmatrix), intent(in) :: overlap
65 
66  ! Working
67  integer(kind=intType) :: i, jj
68 
69  if (myid == 0) then
70  ! Now dump out who owns what:
71  do i = 1, overlap%nrow
72  write (*, "(a,I4, a)", advance='no') 'Row:', i, " "
73  do jj = overlap%rowPtr(i), overlap%rowPtr(i + 1) - 1
74  write (*, "(a,I2, a, es10.5)", advance='no') "(", overlap%colInd(jj), ")", overlap%data(jj)
75  end do
76  write (*, *) " "
77  end do
78 
79  print *, '--------------------------------------'
80  ! Now dump out who owns what:
81  do i = 1, overlap%nRow
82  write (*, "(a,I4, a)", advance='no') 'Row:', i, " "
83  do jj = overlap%rowPtr(i), overlap%rowPtr(i + 1) - 1
84  write (*, "(a,I2, a, I8)", advance='no') "(", overlap%colInd(jj), ")", int(overlap%assignedProc(jj))
85  end do
86  write (*, *) " "
87  end do
88  end if
89  end subroutine printoverlapmatrix
90 
91  subroutine getcumulativeform(sizeArray, n, cumArray)
92 
93  use constants
94  implicit none
95 
96  ! Input/Output
97  integer(kind=intType), intent(in) :: n
98  integer(kind=intType), dimension(n), intent(in) :: sizeArray
99  integer(kind=intType), dimension(0:n), intent(out) :: cumArray
100 
101  ! Working
102  integer(kind=intType) :: i
103 
104  cumarray(0) = 0
105  do i = 1, n
106  cumarray(i) = cumarray(i - 1) + sizearray(i)
107  end do
108 
109  end subroutine getcumulativeform
110 
111  subroutine transposeoverlap(A, B)
112 
113  ! Create the matrix Create the matrix transpose.
114  ! Inspired by: https://people.sc.fsu.edu/~jburkardt/f_src/sparsekit/sparsekit.f90
115  use constants
116  use oversetdata, only: csrmatrix
117  implicit none
118 
119  ! Input/Output
120  type(csrmatrix), intent(in) :: A
121  type(csrmatrix), intent(inout) :: B
122 
123  ! Working
124  integer(kind=intType) :: col, colp1, i, k, next
125 
126  ! A CSR matrix is the same as a CSC matrix of the transpose. So
127  ! essentially the algorithm is convert A as a CSC matrix to B
128  ! (a CSR matrix)
129 
130  ! Allocate space for everything in B
131  b%nnz = a%nnz
132  b%nRow = a%nCol
133  b%nCol = a%nRow
134  allocate (b%data(b%nnz), b%colInd(b%nnz), &
135  b%assignedProc(b%nnz), b%rowPtr(b%nRow + 1))
136  b%allocated = .true.
137  ! Compute lengths of rows of B (ie the columns of A)
138 
139  b%rowPtr = 0
140 
141  do i = 1, a%nRow
142  do k = a%rowPTr(i), a%rowPtr(i + 1) - 1
143  colp1 = a%colInd(k) + 1
144  b%rowPtr(colp1) = b%rowPtr(colp1) + 1
145 
146  end do
147  end do
148  !
149  ! Compute pointers from lengths.
150  !
151  b%rowPtr(1) = 1
152  do i = 1, a%nRow
153  b%rowPtr(i + 1) = b%rowPtr(i) + b%rowPtr(i + 1)
154  end do
155  !
156  ! Do the actual copying.
157  !
158  do i = 1, a%nRow
159  do k = a%rowPtr(i), a%rowPtr(i + 1) - 1
160  col = a%colInd(k)
161  next = b%rowPtr(col)
162 
163  b%data(next) = a%data(k)
164  b%assignedProc(next) = a%assignedProc(k)
165 
166  b%colInd(next) = i
167  b%rowPtr(col) = next + 1
168  end do
169  end do
170 
171  ! Reshift B%rowPtr
172  do i = a%nRow, 1, -1
173  b%rowPtr(i + 1) = b%rowPtr(i)
174  end do
175  b%rowPtr(1) = 1
176 
177  end subroutine transposeoverlap
178 
179  subroutine deallocatecsrmatrix(mat1)
180 
181  use constants
182  use oversetdata, only: csrmatrix
183  implicit none
184 
185  type(csrmatrix), intent(inout) :: mat1
186 
187  if (mat1%allocated) then
188  deallocate ( &
189  mat1%data, &
190  mat1%colInd, &
191  mat1%rowPtr, &
192  mat1%assignedProc)
193  end if
194 
195  end subroutine deallocatecsrmatrix
196 
197  subroutine computefringeprocarray(fringes, n, fringeProc, cumFringeProc, nFringeProc)
198  ! Compute the breakpoints "cumFringeProc" for a list of sorted n
199  ! fringes "fringes". nFringeProc is the total number of unique
200  ! processors. fringeProc is the processor number for each section.
201  use constants
202  use block, only: fringetype
203  use oversetdata, only: csrmatrix
204  use communication, only: nproc
205 
206  implicit none
207 
208  ! Input/Output
209  integer(kind=intType), intent(in) :: n
210  type(fringetype), intent(in), dimension(n) :: fringes
211  integer(kind=intType), intent(out) :: nFringeProc
212  integer(kind=intType), intent(out) :: fringeProc(nProc), cumFringeProc(1:nProc + 1)
213 
214  ! Working
215  integer(kind=intType) :: i, currentProc
216 
217  fringeproc = -1
218  nfringeproc = 0
219  cumfringeproc(1) = 1
220  currentproc = -1
221 
222  do i = 1, n
223  if (currentproc /= fringes(i)%donorProc) then
224  nfringeproc = nfringeproc + 1
225  cumfringeproc(nfringeproc) = i
226  fringeproc(nfringeproc) = fringes(i)%donorProc
227  currentproc = fringes(i)%donorProc
228  end if
229  end do
230 
231  ! Finally, the nFringeProc+1 entry is always n+1
232  cumfringeproc(nfringeproc + 1) = n + 1
233 
234  end subroutine computefringeprocarray
235 
236  subroutine deallocateoblocks(oBlocks, n)
237 
238  ! This subroutine deallocates all data stores in a list of oBlocks
239  use constants
240  use adtbuild, only: destroyserialhex
241  use oversetdata, only: oversetblock
242  implicit none
243 
244  ! Input Params
245  integer(kind=intType) :: n
246  type(oversetblock), dimension(n), intent(inout) :: oBLocks
247 
248  ! Working Parameters
249  integer(kind=intType) :: i
250 
251  do i = 1, n
252 
253  ! oBlock:
254  if (oblocks(i)%allocated) then
255  deallocate ( &
256  oblocks(i)%hexaConn, &
257  oblocks(i)%globalCell, &
258  oblocks(i)%nearWall, &
259  oblocks(i)%invalidDonor, &
260  oblocks(i)%qualDonor, &
261  oblocks(i)%xADT)
262  if (allocated(oblocks(i)%rbuffer)) then
263  deallocate (oblocks(i)%rBuffer, &
264  oblocks(i)%iBuffer)
265  end if
266  call destroyserialhex(oblocks(i)%ADT)
267  end if
268  end do
269  end subroutine deallocateoblocks
270 
271  subroutine deallocateofringes(oFringes, n)
272 
273  ! This subroutine deallocates all data stores in a list of oFringes
274  use constants
275  use oversetdata, only: oversetfringe
276  implicit none
277 
278  ! Input Params
279  integer(kind=intType) :: n
280  type(oversetfringe), dimension(n), intent(inout) :: oFringes
281 
282  ! Working Parameters
283  integer(kind=intType) :: i
284 
285  do i = 1, n
286  if (allocated(ofringes(i)%x)) &
287  deallocate (ofringes(i)%x)
288 
289  if (allocated(ofringes(i)%isWall)) &
290  deallocate (ofringes(i)%isWall)
291 
292  if (allocated(ofringes(i)%xSeed)) &
293  deallocate (ofringes(i)%xSeed)
294 
295  if (allocated(ofringes(i)%wallInd)) &
296  deallocate (ofringes(i)%wallInd)
297 
298  if (allocated(ofringes(i)%rbuffer)) &
299  deallocate (ofringes(i)%rBuffer)
300 
301  if (allocated(ofringes(i)%ibuffer)) &
302  deallocate (ofringes(i)%iBuffer)
303 
304  if (associated(ofringes(i)%fringeIntBuffer)) &
305  deallocate (ofringes(i)%fringeIntBuffer)
306 
307  if (associated(ofringes(i)%fringeRealBuffer)) &
308  deallocate (ofringes(i)%fringeRealBuffer)
309 
310  ofringes(i)%allocated = .false.
311  end do
312  end subroutine deallocateofringes
313 
314  subroutine deallocateosurfs(oSurfs, n)
315 
316  ! This subroutine deallocates all data stores in a list of oSurfs
317 
318  use constants
319  use adtbuild, only: destroyserialquad
320  use oversetdata, only: oversetwall
321  use kdtree2_module, only: kdtree2destroy
322  implicit none
323 
324  ! Input Params
325  integer(kind=intType) :: n
326  type(oversetwall), dimension(n), intent(inout) :: oSurfs
327 
328  ! Working Parameters
329  integer(kind=intType) :: i
330 
331  do i = 1, n
332  if (osurfs(i)%allocated) then
333  deallocate ( &
334  osurfs(i)%x, &
335  osurfs(i)%conn, &
336  osurfs(i)%iblank, &
337  osurfs(i)%cellPtr)
338  call destroyserialquad(osurfs(i)%ADT)
339  if (osurfs(i)%nNodes > 0) then
340  call kdtree2destroy(osurfs(i)%tree)
341  end if
342  end if
343  osurfs(i)%allocated = .false.
344  end do
345  end subroutine deallocateosurfs
346 
347  subroutine wallsonblock(wallsPresent)
348 
349  use constants
350  use blockpointers, only: nbkglobal
351  use cgnsgrid, only: cgnsdoms
352  implicit none
353 
354  logical, intent(out) :: wallsPresent
355  integer(kind=intType) :: mm
356  wallspresent = .false.
357  ! Check THE ORIGINAL CGNS blocks for BCs, because the block may have
358  ! been split.
359  do mm = 1, cgnsdoms(nbkglobal)%nBocos
360  if (cgnsdoms(nbkglobal)%bocoInfo(mm)%BCType == nswalladiabatic .or. &
361  cgnsdoms(nbkglobal)%bocoInfo(mm)%BCType == nswallisothermal .or. &
362  cgnsdoms(nbkglobal)%bocoInfo(mm)%BCType == eulerwall) then
363  wallspresent = .true.
364  end if
365  end do
366  end subroutine wallsonblock
367 
368  subroutine flagforcedrecv
369 
370  use constants
371  use blockpointers, only: nx, ny, nz, ie, je, ke, bcdata, bcfaceid, nbocos, bctype, &
372  forcedrecv, flowdoms, ndom, il, jl, kl, iblank, status
373  use utils, only: setpointers
374  use communication
376  use stencils
377  implicit none
378 
379  ! This is generic routine for filling up a 3D array of 1st level halos
380  ! cells (1:ie, 1:je, 1:ke) indicating cells that are forced
381  ! receivers. BlockPointers must have already been set.
382 
383  integer(kind=intType) :: nn, i, j, k, mm, iStart, iEnd, jStart, jEnd, kStart, kEnd
384  integer(kind=intType) :: ii, jj, kk, i_stencil
385  logical :: floodOrBlank, floodOrBlank2
386  do nn = 1, ndom
387  call setpointers(nn, 1, 1)
388  forcedrecv = 0
389  do mm = 1, nbocos
390  ! Just record the ranges necessarvy and we'll add in a generic
391  ! loop. Why is it the first three? Well, the first level of halos
392  ! off of an overset outer bound is completely
393  ! meaningless. Essentially we ignore those. So the outer two
394  ! layers of cells are indices 2 and 3. Therefore the first 3 on
395  ! either side need to be flagged as invalid.
396 
397  select case (bcfaceid(mm))
398  case (imin)
399  istart = 1; iend = 3;
400  jstart = bcdata(mm)%inBeg + 1; jend = bcdata(mm)%inEnd
401  kstart = bcdata(mm)%jnBeg + 1; kend = bcdata(mm)%jnEnd
402  case (imax)
403  istart = nx; iend = ie;
404  jstart = bcdata(mm)%inBeg + 1; jend = bcdata(mm)%inEnd
405  kstart = bcdata(mm)%jnBeg + 1; kend = bcdata(mm)%jnEnd
406  case (jmin)
407  istart = bcdata(mm)%inBeg + 1; iend = bcdata(mm)%inEnd
408  jstart = 1; jend = 3;
409  kstart = bcdata(mm)%jnBeg + 1; kend = bcdata(mm)%jnEnd
410  case (jmax)
411  istart = bcdata(mm)%inBeg + 1; iend = bcdata(mm)%inEnd
412  jstart = ny; jend = je;
413  kstart = bcdata(mm)%jnBeg + 1; kend = bcdata(mm)%jnEnd
414  case (kmin)
415  istart = bcdata(mm)%inBeg + 1; iend = bcdata(mm)%inEnd
416  jstart = bcdata(mm)%jnBeg + 1; jend = bcdata(mm)%jnEnd
417  kstart = 1; kend = 3;
418  case (kmax)
419  istart = bcdata(mm)%inBeg + 1; iend = bcdata(mm)%inEnd
420  jstart = bcdata(mm)%jnBeg + 1; jend = bcdata(mm)%jnEnd
421  kstart = nz; kend = ke;
422  end select
423 
424  if (bctype(mm) == oversetouterbound) then
425  do k = kstart, kend
426  do j = jstart, jend
427  do i = istart, iend
428  forcedrecv(i, j, k) = 1
429  end do
430  end do
431  end do
432  end if
433  end do
434 
435  ! Add to the invalid donor list if it got flooded with iblank of -2 or -3:
436  do k = 2, kl
437  do j = 2, jl
438  do i = 2, il
439  ! Flooded or explictly blanked cell
440  floodorblank = isflooded(status(i, j, k)) .or. &
441  isfloodseed(status(i, j, k)) .or. &
442  iblank(i, j, k) == -4
443  if (floodorblank) then
444  stencilloop: do i_stencil = 1, n_visc_drdw
445  ii = visc_drdw_stencil(i_stencil, 1) + i
446  jj = visc_drdw_stencil(i_stencil, 2) + j
447  kk = visc_drdw_stencil(i_stencil, 3) + k
448  ! Flag as a forced reciver if it *isn't* flooded
449  ! or explictly blanked
450 
451  floodorblank2 = isflooded(status(ii, jj, kk)) .or. &
452  isfloodseed(status(ii, jj, kk)) .or. &
453  iblank(ii, jj, kk) == -4
454 
455  if (.not. floodorblank2) then
456  forcedrecv(ii, jj, kk) = 1
457  end if
458  end do stencilloop
459  end if
460  end do
461  end do
462  end do
463  end do
464 
465  ! Update the info across block boundaries
466  domainloop: do nn = 1, ndom
467  flowdoms(nn, 1, 1)%intCommVars(1)%var => &
468  flowdoms(nn, 1, 1)%forcedRecv(:, :, :)
469  end do domainloop
470 
471  ! Run the reverse halo exchange first. This is necessary if there
472  ! is 1 cell wide block next to a overset outer bound like the following:
473  !
474  ! Blk1 Blk2
475  ! ----+-----+------++-----+
476  ! | | || | <= this face has overset outer bound BC
477  ! ----+-----+------++-----+
478  ! | | || |
479  ! ----+-----+------++-----+
480  ! | | || |
481  ! ----+-----+------++-----+
482  ! ^block boundary
483  !
484  ! So what happens, is blk2 (1 cell wide) sets the two layers of
485  ! cells off of the BC as forced receivers. However, the second of
486  ! those layers is a halo cell. Blk1 then never gets this
487  ! information. as it clearly should. So what we have to do is a
488  ! reverse halo exchange that takes halo information and combines
489  ! it with real cell information. Essentially we will accumulate
490  ! forcedRecv from the halo to the real cell. For this we run the
491  ! generic reverse halo exchange.
492 
494 
495  ! Finally we now need to run the forward halo exchange to make
496  ! sure any halos on other procs are set correctly that may be part of a stencil
498 
499  end subroutine flagforcedrecv
500 
501  ! Utility function for unpacking/accessing the status variable
502 
503  function isdonor(i)
504  use constants
505  implicit none
507  integer(kind=intType), intent(in) :: i
509  end function isdonor
510 
511  function ishole(i)
512  use constants
513  implicit none
515  integer(kind=intType), intent(in) :: i
517  end function ishole
518 
519  function iscompute(i)
520  use constants
521  implicit none
523  integer(kind=intType), intent(in) :: i
525  end function iscompute
526 
527  function isfloodseed(i)
528  use constants
529  implicit none
531  integer(kind=intType), intent(in) :: i
533  end function isfloodseed
534 
535  function isflooded(i)
536  use constants
537  implicit none
539  integer(kind=intType), intent(in) :: i
541  end function isflooded
542 
543  function iswalldonor(i)
544  use constants
545  implicit none
547  integer(kind=intType), intent(in) :: i
549  end function iswalldonor
550 
551  function isreceiver(i)
552  use constants
553  implicit none
555  integer(kind=intType), intent(in) :: i
557  end function isreceiver
558 
559  subroutine setisdonor(i, flag)
560  use constants
561  implicit none
562  integer(kind=intType), intent(inout) :: i
563  logical :: isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver, flag
564  call getstatus(i, isdonor, ishole, iscompute, isfloodseed, isflooded, iswalldonor, isreceiver)
565  call setstatus(i, flag, ishole, iscompute, isfloodseed, isflooded, iswalldonor, isreceiver)
566  end subroutine setisdonor
567 
568  subroutine setishole(i, flag)
569  use constants
570  implicit none
571  integer(kind=intType), intent(inout) :: i
572  logical :: isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver, flag
573  call getstatus(i, isdonor, ishole, iscompute, isfloodseed, isflooded, iswalldonor, isreceiver)
574  call setstatus(i, isdonor, flag, iscompute, isfloodseed, isflooded, iswalldonor, isreceiver)
575  end subroutine setishole
576 
577  subroutine setiscompute(i, flag)
578  use constants
579  implicit none
580  integer(kind=intType), intent(inout) :: i
581  logical :: isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver, flag
582  call getstatus(i, isdonor, ishole, iscompute, isfloodseed, isflooded, iswalldonor, isreceiver)
583  call setstatus(i, isdonor, ishole, flag, isfloodseed, isflooded, iswalldonor, isreceiver)
584  end subroutine setiscompute
585 
586  subroutine setisfloodseed(i, flag)
587  use constants
588  implicit none
589  integer(kind=intType), intent(inout) :: i
590  logical :: isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver, flag
591  call getstatus(i, isdonor, ishole, iscompute, isfloodseed, isflooded, iswalldonor, isreceiver)
592  call setstatus(i, isdonor, ishole, iscompute, flag, isflooded, iswalldonor, isreceiver)
593  end subroutine setisfloodseed
594 
595  subroutine setisflooded(i, flag)
596  use constants
597  implicit none
598  integer(kind=intType), intent(inout) :: i
599  logical :: isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver, flag
600  call getstatus(i, isdonor, ishole, iscompute, isfloodseed, isflooded, iswalldonor, isreceiver)
601  call setstatus(i, isdonor, ishole, iscompute, isfloodseed, flag, iswalldonor, isreceiver)
602  end subroutine setisflooded
603 
604  subroutine setiswalldonor(i, flag)
605  use constants
606  implicit none
607  integer(kind=intType), intent(inout) :: i
608  logical :: isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver, flag
609  call getstatus(i, isdonor, ishole, iscompute, isfloodseed, isflooded, iswalldonor, isreceiver)
610  call setstatus(i, isdonor, ishole, iscompute, isfloodseed, isflooded, flag, isreceiver)
611  end subroutine setiswalldonor
612 
613  subroutine setisreceiver(i, flag)
614  use constants
615  implicit none
616  integer(kind=intType), intent(inout) :: i
617  logical :: isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver, flag
618  call getstatus(i, isdonor, ishole, iscompute, isfloodseed, isflooded, iswalldonor, isreceiver)
619  call setstatus(i, isdonor, ishole, iscompute, isfloodseed, isflooded, iswalldonor, flag)
620  end subroutine setisreceiver
621 
622  subroutine setstatus(i, isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver)
623 
624  use constants
625  implicit none
626  integer(kind=intType), intent(out) :: i
627  logical :: isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver
628  i = 0
629 
630  if (isdonor) i = i + 1
631  if (ishole) i = i + 2
632  if (iscompute) i = i + 4
633  if (isfloodseed) i = i + 8
634  if (isflooded) i = i + 16
635  if (iswalldonor) i = i + 32
636  if (isreceiver) i = i + 64
637  end subroutine setstatus
638 
639  subroutine getstatus(i, isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver)
640 
641  use constants
642  implicit none
643  logical :: isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver
644  integer(kind=intType) :: i, j
645  j = i
646 
647  isdonor = .false.
648  ishole = .false.
649  iscompute = .false.
650  isfloodseed = .false.
651  isflooded = .false.
652  iswalldonor = .false.
653  isreceiver = .false.
654 
655  if (j / 64 > 0) then
656  isreceiver = .true.
657  j = j - 64
658  end if
659 
660  if (j / 32 > 0) then
661  iswalldonor = .true.
662  j = j - 32
663  end if
664 
665  if (j / 16 > 0) then
666  isflooded = .true.
667  j = j - 16
668  end if
669 
670  if (j / 8 > 0) then
671  isfloodseed = .true.
672  j = j - 8
673  end if
674 
675  if (j / 4 > 0) then
676  iscompute = .true.
677  j = j - 4
678  end if
679 
680  if (j / 2 > 0) then
681  ishole = .true.
682  j = j - 2
683  end if
684 
685  if (j / 1 > 0) then
686  isdonor = .true.
687  j = j - 1
688  end if
689  end subroutine getstatus
690 
691  !
692  subroutine binsearchnodes(arr, searchNode, nn, searchInd)
693 
694  ! binSearchNodes does binary search for a node 'searchNode'
695  ! in arr(1:nn) and returns index 'searchInd' where
696  ! 'searchNode' lies in arr. searchInd = -1 if not found.
697 
698  use constants
699  implicit none
700 
701  ! Input parameters
702  integer(kind=intType), intent(in) :: nn, searchNode
703  integer(kind=intType), intent(out) :: searchInd
704  integer(kind=intType), intent(in) :: arr(nn)
705 
706  ! Local variables
707  integer(kind=intType) :: first, last, middle
708 
709  first = 1
710  last = nn
711 
712  middle = (first + last) / 2
713 
714  do while (first <= last)
715  if (arr(middle) < searchnode) then
716  first = middle + 1
717  else if (arr(middle) == searchnode) then
718  searchind = middle
719  exit
720  else
721  last = middle - 1
722  end if
723 
724  middle = (first + last) / 2
725  end do !while
726 
727  if (first > last) then
728  searchind = -1
729  print *, ' binSearchNode fails for searchNode ', searchnode
730  stop
731  end if
732  end subroutine binsearchnodes
733 
734  subroutine binsearchpocketedgetype(arr, search, nn, searchInd)
735 
736  ! binSearchPocketEdgeType does binary searche for
737  ! pocketEdgeType 'search' edge and returns index 'searchInd'
738  ! where 'search' lies in arr.
739 
740  use constants
741  use oversetdata ! cannot use only becuase of <= operator
742  implicit none
743 
744  ! Input parameters
745  integer(kind=intType), intent(in) :: nn
746  integer(kind=intType), intent(out) :: searchInd
747 
748  type(pocketedge), intent(in) :: search
749  type(pocketedge), dimension(*), intent(in) :: arr
750 
751  ! Local variables
752  integer(kind=intType) :: first, last, middle
753 
754  first = 1
755  last = nn
756 
757  middle = (first + last) / 2
758 
759  do while (first <= last)
760  if (arr(middle) < search) then
761  first = middle + 1
762  else if (arr(middle) == search) then
763  searchind = middle
764  exit
765  else
766  last = middle - 1
767  end if
768 
769  middle = (first + last) / 2
770  end do !while
771 
772  if (first > last) then
773  print *, ' binSearchPocketEdgeType fails for Edge with nodes ', &
774  search%n1, search%n2
775  stop
776  end if
777  end subroutine binsearchpocketedgetype
778 
779  !
780  subroutine qsortedgetype(arr, nn)
781  !
782  ! qsortEdgeType sorts the given number of oversetString master
783  ! Edges in increasing order based on the <= operator for this
784  ! derived data type.
785  ! (Generously copied from qsortFringeType.F90)
786  !
787  use constants
788  use oversetdata ! cannot use only becuase of <= operator
789  use utils, only: terminate
790  implicit none
791  !
792  ! Subroutine arguments.
793  !
794  integer(kind=intType), intent(in) :: nn
795 
796  type(oversetedge), dimension(*), intent(inout) :: arr
797  !
798  ! Local variables.
799  !
800  integer(kind=intType), parameter :: m = 7
801 
802  integer(kind=intType) :: nStack
803  integer(kind=intType) :: i, j, k, r, l, jStack, ii
804 
805  integer :: ierr
806 
807  type(oversetedge) :: a, tmp
808 
809  integer(kind=intType), allocatable, dimension(:) :: stack
810  integer(kind=intType), allocatable, dimension(:) :: tmpStack
811 
812  ! Allocate the memory for stack.
813 
814  nstack = 100
815  allocate (stack(nstack), stat=ierr)
816  if (ierr /= 0) &
817  call terminate("qsortEdgeType", &
818  "Memory allocation failure for stack")
819 
820  ! Initialize the variables that control the sorting.
821 
822  jstack = 0
823  l = 1
824  r = nn
825 
826  ! Start of the algorithm
827 
828  do
829 
830  ! Check for the size of the subarray.
831 
832  if ((r - l) < m) then
833 
834  ! Perform insertion sort
835 
836  do j = l + 1, r
837  a = arr(j)
838  do i = (j - 1), l, -1
839  if (arr(i) <= a) exit
840  arr(i + 1) = arr(i)
841  end do
842  arr(i + 1) = a
843  end do
844 
845  ! In case there are no more elements on the stack, exit from
846  ! the outermost do-loop. Algorithm has finished.
847 
848  if (jstack == 0) exit
849 
850  ! Pop stack and begin a new round of partitioning.
851 
852  r = stack(jstack)
853  l = stack(jstack - 1)
854  jstack = jstack - 2
855 
856  else
857 
858  ! Subarray is larger than the threshold for a linear sort.
859  ! Choose median of left, center and right elements as
860  ! partitioning element a.
861  ! Also rearrange so that (l) <= (l+1) <= (r).
862 
863  k = (l + r) / 2
864  tmp = arr(k) ! Swap the elements
865  arr(k) = arr(l + 1) ! k and l+1.
866  arr(l + 1) = tmp
867 
868  if (arr(r) < arr(l)) then
869  tmp = arr(l) ! Swap the elements
870  arr(l) = arr(r) ! r and l.
871  arr(r) = tmp
872  end if
873 
874  if (arr(r) < arr(l + 1)) then
875  tmp = arr(l + 1) ! Swap the elements
876  arr(l + 1) = arr(r) ! r and l+1.
877  arr(r) = tmp
878  end if
879 
880  if (arr(l + 1) < arr(l)) then
881  tmp = arr(l + 1) ! Swap the elements
882  arr(l + 1) = arr(l) ! l and l+1.
883  arr(l) = tmp
884  end if
885 
886  ! Initialize the pointers for partitioning.
887 
888  i = l + 1
889  j = r
890  a = arr(l + 1)
891 
892  ! The innermost loop
893 
894  do
895 
896  ! Scan up to find element >= a.
897  do
898  i = i + 1
899  if (a <= arr(i)) exit
900  end do
901 
902  ! Scan down to find element <= a.
903  do
904  j = j - 1
905  if (arr(j) <= a) exit
906  end do
907 
908  ! Exit the loop in case the pointers i and j crossed.
909 
910  if (j < i) exit
911 
912  ! Swap the element i and j.
913 
914  tmp = arr(i)
915  arr(i) = arr(j)
916  arr(j) = tmp
917  end do
918 
919  ! Swap the entries j and l+1. Remember that a equals
920  ! arr(l+1).
921 
922  arr(l + 1) = arr(j)
923  arr(j) = a
924 
925  ! Push pointers to larger subarray on stack,
926  ! process smaller subarray immediately.
927 
928  jstack = jstack + 2
929  if (jstack > nstack) then
930 
931  ! Storage of the stack is too small. Reallocate.
932 
933  allocate (tmpstack(nstack), stat=ierr)
934  if (ierr /= 0) &
935  call terminate("qsortEdgeType", &
936  "Memory allocation error for tmpStack")
937  tmpstack = stack
938 
939  ! Free the memory of stack, store the old value of nStack
940  ! in tmp and increase nStack.
941 
942  deallocate (stack, stat=ierr)
943  if (ierr /= 0) &
944  call terminate("qsortEdgeType", &
945  "Deallocation error for stack")
946  ii = nstack
947  nstack = nstack + 100
948 
949  ! Allocate the memory for stack and copy the old values
950  ! from tmpStack.
951 
952  allocate (stack(nstack), stat=ierr)
953  if (ierr /= 0) &
954  call terminate("qsortEdgeType", &
955  "Memory reallocation error for stack")
956  stack(1:ii) = tmpstack(1:ii)
957 
958  ! And finally release the memory of tmpStack.
959 
960  deallocate (tmpstack, stat=ierr)
961  if (ierr /= 0) &
962  call terminate("qsortEdgeType", &
963  "Deallocation error for tmpStack")
964  end if
965 
966  if ((r - i + 1) >= (j - l)) then
967  stack(jstack) = r
968  r = j - 1
969  stack(jstack - 1) = j
970  else
971  stack(jstack) = j - 1
972  stack(jstack - 1) = l
973  l = j
974  end if
975 
976  end if
977  end do
978 
979  ! Release the memory of stack.
980 
981  deallocate (stack, stat=ierr)
982  if (ierr /= 0) &
983  call terminate("qsortEdgeType", &
984  "Deallocation error for stack")
985 
986  ! Check in debug mode whether the array is really sorted.
987 
988  if (debug) then
989  do i = 1, (nn - 1)
990  if (arr(i + 1) < arr(i)) &
991  call terminate("qsortEdgeType", &
992  "Array is not sorted correctly")
993  end do
994  end if
995 
996  end subroutine qsortedgetype
997 
998  subroutine qsortfringetype(arr, nn, sortType)
999  !
1000  ! qsortFringeListTy sorts the given number of fringes
1001  ! increasing order based on the <= operator for this derived
1002  ! data type.
1003  !
1004  use constants
1005  use block ! Cannot use-only becuase of <= operator
1006  use utils, only: terminate
1007  implicit none
1008  !
1009  ! Subroutine arguments.
1010  !
1011  integer(kind=intType), intent(in) :: nn, sortType
1012 
1013  type(fringetype), dimension(*), intent(inout) :: arr
1014  !
1015  ! Local variables.
1016  !
1017  integer(kind=intType), parameter :: m = 7
1018 
1019  integer(kind=intType) :: nStack
1020  integer(kind=intType) :: i, j, k, r, l, jStack, ii
1021 
1022  integer :: ierr
1023 
1024  type(fringetype) :: a, tmp
1025 
1026  integer(kind=intType), allocatable, dimension(:) :: stack
1027  integer(kind=intType), allocatable, dimension(:) :: tmpStack
1028 
1029  if (sorttype == sortbydonor) then
1031  else if (sorttype == sortbyreceiver) then
1033  else
1034  call terminate("qsortfringeType", &
1035  "Uuknown sort type")
1036  end if
1037 
1038  ! Allocate the memory for stack.
1039 
1040  nstack = 100
1041  allocate (stack(nstack), stat=ierr)
1042  if (ierr /= 0) &
1043  call terminate("qsortfringeType", &
1044  "Memory allocation failure for stack")
1045 
1046  ! Initialize the variables that control the sorting.
1047 
1048  jstack = 0
1049  l = 1
1050  r = nn
1051 
1052  ! Start of the algorithm
1053 
1054  do
1055 
1056  ! Check for the size of the subarray.
1057 
1058  if ((r - l) < m) then
1059 
1060  ! Perform insertion sort
1061 
1062  do j = l + 1, r
1063  a = arr(j)
1064  do i = (j - 1), l, -1
1065  if (arr(i) <= a) exit
1066  arr(i + 1) = arr(i)
1067  end do
1068  arr(i + 1) = a
1069  end do
1070 
1071  ! In case there are no more elements on the stack, exit from
1072  ! the outermost do-loop. Algorithm has finished.
1073 
1074  if (jstack == 0) exit
1075 
1076  ! Pop stack and begin a new round of partitioning.
1077 
1078  r = stack(jstack)
1079  l = stack(jstack - 1)
1080  jstack = jstack - 2
1081 
1082  else
1083 
1084  ! Subarray is larger than the threshold for a linear sort.
1085  ! Choose median of left, center and right elements as
1086  ! partitioning element a.
1087  ! Also rearrange so that (l) <= (l+1) <= (r).
1088 
1089  k = (l + r) / 2
1090  tmp = arr(k) ! Swap the elements
1091  arr(k) = arr(l + 1) ! k and l+1.
1092  arr(l + 1) = tmp
1093 
1094  if (arr(r) < arr(l)) then
1095  tmp = arr(l) ! Swap the elements
1096  arr(l) = arr(r) ! r and l.
1097  arr(r) = tmp
1098  end if
1099 
1100  if (arr(r) < arr(l + 1)) then
1101  tmp = arr(l + 1) ! Swap the elements
1102  arr(l + 1) = arr(r) ! r and l+1.
1103  arr(r) = tmp
1104  end if
1105 
1106  if (arr(l + 1) < arr(l)) then
1107  tmp = arr(l + 1) ! Swap the elements
1108  arr(l + 1) = arr(l) ! l and l+1.
1109  arr(l) = tmp
1110  end if
1111 
1112  ! Initialize the pointers for partitioning.
1113 
1114  i = l + 1
1115  j = r
1116  a = arr(l + 1)
1117 
1118  ! The innermost loop
1119 
1120  do
1121 
1122  ! Scan up to find element >= a.
1123  do
1124  i = i + 1
1125  if (a <= arr(i)) exit
1126  end do
1127 
1128  ! Scan down to find element <= a.
1129  do
1130  j = j - 1
1131  if (arr(j) <= a) exit
1132  end do
1133 
1134  ! Exit the loop in case the pointers i and j crossed.
1135 
1136  if (j < i) exit
1137 
1138  ! Swap the element i and j.
1139 
1140  tmp = arr(i)
1141  arr(i) = arr(j)
1142  arr(j) = tmp
1143  end do
1144 
1145  ! Swap the entries j and l+1. Remember that a equals
1146  ! arr(l+1).
1147 
1148  arr(l + 1) = arr(j)
1149  arr(j) = a
1150 
1151  ! Push pointers to larger subarray on stack,
1152  ! process smaller subarray immediately.
1153 
1154  jstack = jstack + 2
1155  if (jstack > nstack) then
1156 
1157  ! Storage of the stack is too small. Reallocate.
1158 
1159  allocate (tmpstack(nstack), stat=ierr)
1160  if (ierr /= 0) &
1161  call terminate("qsortfringeType", &
1162  "Memory allocation error for tmpStack")
1163  tmpstack = stack
1164 
1165  ! Free the memory of stack, store the old value of nStack
1166  ! in tmp and increase nStack.
1167 
1168  deallocate (stack, stat=ierr)
1169  if (ierr /= 0) &
1170  call terminate("qsortfringeType", &
1171  "Deallocation error for stack")
1172  ii = nstack
1173  nstack = nstack + 100
1174 
1175  ! Allocate the memory for stack and copy the old values
1176  ! from tmpStack.
1177 
1178  allocate (stack(nstack), stat=ierr)
1179  if (ierr /= 0) &
1180  call terminate("qsortfringeType", &
1181  "Memory reallocation error for stack")
1182  stack(1:ii) = tmpstack(1:ii)
1183 
1184  ! And finally release the memory of tmpStack.
1185 
1186  deallocate (tmpstack, stat=ierr)
1187  if (ierr /= 0) &
1188  call terminate("qsortfringeType", &
1189  "Deallocation error for tmpStack")
1190  end if
1191 
1192  if ((r - i + 1) >= (j - l)) then
1193  stack(jstack) = r
1194  r = j - 1
1195  stack(jstack - 1) = j
1196  else
1197  stack(jstack) = j - 1
1198  stack(jstack - 1) = l
1199  l = j
1200  end if
1201 
1202  end if
1203  end do
1204 
1205  ! Release the memory of stack.
1206 
1207  deallocate (stack, stat=ierr)
1208  if (ierr /= 0) &
1209  call terminate("qsortfringeType", &
1210  "Deallocation error for stack")
1211 
1212  ! Check in debug mode whether the array is really sorted.
1213 
1214  if (debug) then
1215  do i = 1, (nn - 1)
1216  if (arr(i + 1) < arr(i)) &
1217  call terminate("qsortfringeType", &
1218  "Array is not sorted correctly")
1219  end do
1220  end if
1221 
1222  end subroutine qsortfringetype
1223 
1224  subroutine addtofringelist(fringeList, n, fringe)
1225 
1226  ! Generic subroutine to add to a fringe "List". This isn't
1227  ! actually a list but rather an allocatable (pointer) array that
1228  ! is periodically resized as necessary. n is the current size
1229  ! which is automatically incremented by this routine. This
1230  ! operation occurs multiple times throughout the overset code.
1231 
1232  use constants
1233  use block, only: fringetype
1234 
1235  implicit none
1236 
1237  ! Input Params
1238  type(fringetype), dimension(:), pointer :: fringeList
1239  type(fringetype) :: fringe
1240  integer(kind=intType), intent(inout) :: n
1241 
1242  ! Working Paramters
1243  integer(kind=intType) :: fSize
1244  type(fringetype), dimension(:), pointer :: tmpFringePtr
1245  fsize = size(fringelist)
1246 
1247  ! Increment n for next item
1248  n = n + 1
1249 
1250  if (n > fsize) then
1251 
1252  ! Pointer to existing data:
1253  tmpfringeptr => fringelist
1254 
1255  ! Allocate new space
1256  allocate (fringelist(int(1.5 * fsize)))
1257 
1258  ! Copy exsitng values
1259  fringelist(1:fsize) = tmpfringeptr(1:fsize)
1260 
1261  ! Free original memory
1262  deallocate (tmpfringeptr)
1263 
1264  end if
1265 
1266  fringelist(n) = fringe
1267 
1268  end subroutine addtofringelist
1269 
1270  subroutine addtofringebuffer(intBuffer, realBuffer, n, fringe)
1271 
1272  ! Generic subroutine to add to a fringe "List". It isn't actually
1273  ! a list of fringe types but rather a real array and an int array.
1274 
1275  use constants
1276  use block, only: fringetype
1277 
1278  implicit none
1279 
1280  ! Input Params
1281  integer(kind=intType), dimension(:, :), pointer :: intBuffer
1282  real(kind=realtype), dimension(:, :), pointer :: realbuffer
1283  type(fringetype) :: fringe
1284  integer(kind=intType), intent(inout) :: n
1285 
1286  ! Working Paramters
1287  integer(kind=intType) :: fsize
1288  integer(kind=intType), dimension(:, :), pointer :: tmpint
1289  real(kind=realtype), dimension(:, :), pointer :: tmpreal
1290  fsize = size(intbuffer, 2)
1291 
1292  ! Increment n for next item
1293  n = n + 1
1294 
1295  if (n > fsize) then
1296 
1297  ! Pointers to existing data:
1298  tmpint => intbuffer
1299  tmpreal => realbuffer
1300 
1301  ! Allocate new space
1302  allocate (intbuffer(5, int(1.5 * fsize)))
1303  allocate (realbuffer(4, int(1.5 * fsize)))
1304 
1305  ! Copy exsitng values
1306  intbuffer(:, 1:fsize) = tmpint(:, 1:fsize)
1307  realbuffer(:, 1:fsize) = tmpreal(:, 1:fsize)
1308 
1309  ! Free original memory
1310  deallocate (tmpint, tmpreal)
1311 
1312  end if
1313 
1314  ! Now we can safely add the information:
1315  intbuffer(1, n) = fringe%donorProc
1316  intbuffer(2, n) = fringe%donorBlock
1317  intbuffer(3, n) = fringe%dIndex
1318  intbuffer(4, n) = fringe%myBlock
1319  intbuffer(5, n) = fringe%myIndex
1320 
1321  realbuffer(1:3, n) = fringe%donorFrac
1322  realbuffer(4, n) = fringe%quality
1323 
1324  end subroutine addtofringebuffer
1325 
1326  subroutine qsortpocketedgetype(arr, nn)
1327  !
1328  ! qsortPocketEdgeType sorts the given number of oversetString
1329  ! master Edges in increasing order based on the <= operator for
1330  ! this derived data type.
1331  ! (Generously copied from qsortFringeType.F90)
1332  !
1333  use constants
1334  use oversetdata ! Cannot use-only becuase of <= operator
1335  use utils, onlY: terminate
1336  implicit none
1337  !
1338  ! Subroutine arguments.
1339  !
1340  integer(kind=intType), intent(in) :: nn
1341 
1342  type(pocketedge), dimension(*), intent(inout) :: arr
1343  !
1344  ! Local variables.
1345  !
1346  integer(kind=intType), parameter :: m = 7
1347 
1348  integer(kind=intType) :: nStack
1349  integer(kind=intType) :: i, j, k, r, l, jStack, ii
1350 
1351  integer :: ierr
1352 
1353  type(pocketedge) :: a, tmp
1354 
1355  integer(kind=intType), allocatable, dimension(:) :: stack
1356  integer(kind=intType), allocatable, dimension(:) :: tmpStack
1357 
1358  ! Allocate the memory for stack.
1359 
1360  nstack = 100
1361  allocate (stack(nstack), stat=ierr)
1362  if (ierr /= 0) &
1363  call terminate("qsortEdgeType", &
1364  "Memory allocation failure for stack")
1365 
1366  ! Initialize the variables that control the sorting.
1367 
1368  jstack = 0
1369  l = 1
1370  r = nn
1371 
1372  ! Start of the algorithm
1373 
1374  do
1375 
1376  ! Check for the size of the subarray.
1377 
1378  if ((r - l) < m) then
1379 
1380  ! Perform insertion sort
1381 
1382  do j = l + 1, r
1383  a = arr(j)
1384  do i = (j - 1), l, -1
1385  if (arr(i) <= a) exit
1386  arr(i + 1) = arr(i)
1387  end do
1388  arr(i + 1) = a
1389  end do
1390 
1391  ! In case there are no more elements on the stack, exit from
1392  ! the outermost do-loop. Algorithm has finished.
1393 
1394  if (jstack == 0) exit
1395 
1396  ! Pop stack and begin a new round of partitioning.
1397 
1398  r = stack(jstack)
1399  l = stack(jstack - 1)
1400  jstack = jstack - 2
1401 
1402  else
1403 
1404  ! Subarray is larger than the threshold for a linear sort.
1405  ! Choose median of left, center and right elements as
1406  ! partitioning element a.
1407  ! Also rearrange so that (l) <= (l+1) <= (r).
1408 
1409  k = (l + r) / 2
1410  tmp = arr(k) ! Swap the elements
1411  arr(k) = arr(l + 1) ! k and l+1.
1412  arr(l + 1) = tmp
1413 
1414  if (arr(r) < arr(l)) then
1415  tmp = arr(l) ! Swap the elements
1416  arr(l) = arr(r) ! r and l.
1417  arr(r) = tmp
1418  end if
1419 
1420  if (arr(r) < arr(l + 1)) then
1421  tmp = arr(l + 1) ! Swap the elements
1422  arr(l + 1) = arr(r) ! r and l+1.
1423  arr(r) = tmp
1424  end if
1425 
1426  if (arr(l + 1) < arr(l)) then
1427  tmp = arr(l + 1) ! Swap the elements
1428  arr(l + 1) = arr(l) ! l and l+1.
1429  arr(l) = tmp
1430  end if
1431 
1432  ! Initialize the pointers for partitioning.
1433 
1434  i = l + 1
1435  j = r
1436  a = arr(l + 1)
1437 
1438  ! The innermost loop
1439 
1440  do
1441 
1442  ! Scan up to find element >= a.
1443  do
1444  i = i + 1
1445  if (a <= arr(i)) exit
1446  end do
1447 
1448  ! Scan down to find element <= a.
1449  do
1450  j = j - 1
1451  if (arr(j) <= a) exit
1452  end do
1453 
1454  ! Exit the loop in case the pointers i and j crossed.
1455 
1456  if (j < i) exit
1457 
1458  ! Swap the element i and j.
1459 
1460  tmp = arr(i)
1461  arr(i) = arr(j)
1462  arr(j) = tmp
1463  end do
1464 
1465  ! Swap the entries j and l+1. Remember that a equals
1466  ! arr(l+1).
1467 
1468  arr(l + 1) = arr(j)
1469  arr(j) = a
1470 
1471  ! Push pointers to larger subarray on stack,
1472  ! process smaller subarray immediately.
1473 
1474  jstack = jstack + 2
1475  if (jstack > nstack) then
1476 
1477  ! Storage of the stack is too small. Reallocate.
1478 
1479  allocate (tmpstack(nstack), stat=ierr)
1480  if (ierr /= 0) &
1481  call terminate("qsortEdgeType", &
1482  "Memory allocation error for tmpStack")
1483  tmpstack = stack
1484 
1485  ! Free the memory of stack, store the old value of nStack
1486  ! in tmp and increase nStack.
1487 
1488  deallocate (stack, stat=ierr)
1489  if (ierr /= 0) &
1490  call terminate("qsortEdgeType", &
1491  "Deallocation error for stack")
1492  ii = nstack
1493  nstack = nstack + 100
1494 
1495  ! Allocate the memory for stack and copy the old values
1496  ! from tmpStack.
1497 
1498  allocate (stack(nstack), stat=ierr)
1499  if (ierr /= 0) &
1500  call terminate("qsortEdgeType", &
1501  "Memory reallocation error for stack")
1502  stack(1:ii) = tmpstack(1:ii)
1503 
1504  ! And finally release the memory of tmpStack.
1505 
1506  deallocate (tmpstack, stat=ierr)
1507  if (ierr /= 0) &
1508  call terminate("qsortEdgeType", &
1509  "Deallocation error for tmpStack")
1510  end if
1511 
1512  if ((r - i + 1) >= (j - l)) then
1513  stack(jstack) = r
1514  r = j - 1
1515  stack(jstack - 1) = j
1516  else
1517  stack(jstack) = j - 1
1518  stack(jstack - 1) = l
1519  l = j
1520  end if
1521 
1522  end if
1523  end do
1524 
1525  ! Release the memory of stack.
1526 
1527  deallocate (stack, stat=ierr)
1528  if (ierr /= 0) &
1529  call terminate("qsortEdgeType", &
1530  "Deallocation error for stack")
1531 
1532  ! Check in debug mode whether the array is really sorted.
1533 
1534  if (debug) then
1535  do i = 1, (nn - 1)
1536  if (arr(i + 1) < arr(i)) &
1537  call terminate("qsortEdgeType", &
1538  "Array is not sorted correctly")
1539  end do
1540  end if
1541 
1542  end subroutine qsortpocketedgetype
1543 
1544  subroutine checkoverset(level, sps, totalOrphans, lastCall)
1545 
1546  !
1547  ! CheckOverset checks the integrity of the overset connectivity
1548  ! and holes. For every comptue cell (iblank = 1) it checks that
1549  ! every cell in its stencil are not blanked. If even 1 cell is
1550  ! * found with an incomplete stencil it is a fatal error.
1551  use constants
1552  use blockpointers, only: il, jl, kl, iblank, flowdoms, ndom, orphans, &
1556  use utils, only: setpointers, echk
1557  use inputoverset, only: oversetdebugprint
1558  implicit none
1559 
1560  ! Input/Output
1561  integer(kind=intType), intent(in) :: level, sps
1562  integer(kind=intType), intent(out) :: totalOrphans
1563  logical, intent(in) :: lastCall
1564 
1565  ! Working
1566  integer(kind=intType) :: i, j, k, nn, ii, jj, kk, n, ierr
1567  integer(kind=intType) :: magic, localOrphans, i_stencil
1568  logical :: badCell
1569 
1570  ! This pass just lets the user know where the bad cells are.
1571  do nn = 1, ndom
1572  call setpointers(nn, level, sps)
1573 
1574  ! On the first pass count up the total number of orphans for this block
1575  n = 0
1576  do k = 2, kl
1577  do j = 2, jl
1578  do i = 2, il
1579  if (iblank(i, j, k) == 1) then
1580  badcell = .false.
1581 
1582  stencilloop: do i_stencil = 1, n_visc_drdw
1583  ii = visc_drdw_stencil(i_stencil, 1) + i
1584  jj = visc_drdw_stencil(i_stencil, 2) + j
1585  kk = visc_drdw_stencil(i_stencil, 3) + k
1586 
1587  if (.not. (iblank(ii, jj, kk) == 1 .or. iblank(ii, jj, kk) == -1)) then
1588  badcell = .true.
1589  end if
1590  end do stencilloop
1591  if (badcell .and. lastcall .and. oversetdebugprint) then
1592  print *, 'Error in connectivity at :', nbkglobal, i + ibegor, j + jbegor, k + kbegor
1593  end if
1594  end if
1595  end do
1596  end do
1597  end do
1598  end do
1599 
1600  magic = 33
1601  localorphans = 0
1602  do nn = 1, ndom
1603  call setpointers(nn, level, sps)
1604 
1605  ! On the first pass count up the total number of orphans for this block
1606  n = 0
1607  do k = 2, kl
1608  do j = 2, jl
1609  do i = 2, il
1610  if (iblank(i, j, k) == 0 .or. iblank(i, j, k) == -2 .or. &
1611  iblank(i, j, k) == -3 .or. iblank(i, j, k) == -4) then
1612 
1613  stencilloop2: do i_stencil = 1, n_visc_drdw
1614  ii = visc_drdw_stencil(i_stencil, 1) + i
1615  jj = visc_drdw_stencil(i_stencil, 2) + j
1616  kk = visc_drdw_stencil(i_stencil, 3) + k
1617 
1618  if (ii >= 2 .and. jj >= 2 .and. kk >= 2 .and. &
1619  ii <= il .and. jj <= jl .and. kk <= kl) then
1620 
1621  if (iblank(ii, jj, kk) == 1) then
1622  ! This cell is an orphan:
1623  n = n + 1
1624  end if
1625  end if
1626  end do stencilloop2
1627  end if
1628  end do
1629  end do
1630  end do
1631 
1632  localorphans = localorphans + n
1633 
1634  ! Remove any existing orphans
1635  if (associated(flowdoms(nn, level, sps)%orphans)) then
1636  deallocate (flowdoms(nn, level, sps)%orphans)
1637  end if
1638  allocate (flowdoms(nn, level, sps)%orphans(3, n))
1639 
1640  ! Save the total number of orphans on this block
1641  flowdoms(nn, level, sps)%nOrphans = n
1642 
1643  ! Manual set information from blockPointers that would be set
1644  ! with setPointers()
1645  orphans => flowdoms(nn, level, sps)%orphans
1646  norphans = n
1647 
1648  ! On the first pass count up the total number of orphans for this block
1649  n = 0
1650  do k = 2, kl
1651  do j = 2, jl
1652  do i = 2, il
1653  if (iblank(i, j, k) == 0 .or. iblank(i, j, k) == -2 .or. &
1654  iblank(i, j, k) == -3 .or. iblank(i, j, k) == -4) then
1655 
1656  stencilloop3: do i_stencil = 1, n_visc_drdw
1657  ii = visc_drdw_stencil(i_stencil, 1) + i
1658  jj = visc_drdw_stencil(i_stencil, 2) + j
1659  kk = visc_drdw_stencil(i_stencil, 3) + k
1660 
1661  if (ii >= 2 .and. jj >= 2 .and. kk >= 2 .and. &
1662  ii <= il .and. jj <= jl .and. kk <= kl) then
1663 
1664  if (iblank(ii, jj, kk) == 1) then
1665  ! This cell is an orphan:
1666  n = n + 1
1667  orphans(:, n) = (/ii, jj, kk/)
1668  if (lastcall) then
1669  ! we can modify iBlankLast because this is the last checkOverset call.
1670  ! we set iBlankLast to -5 to mark orphan cells, this value will then
1671  ! be moved to iBlank after we are done with other loops.
1672  flowdoms(nn, level, sps)%iBlankLast(ii, jj, kk) = -5
1673  end if
1674  end if
1675  end if
1676  end do stencilloop3
1677  end if
1678  end do
1679  end do
1680  end do
1681  end do
1682 
1683  ! Determine the total number of overset orphans
1684  call mpi_allreduce(localorphans, totalorphans, 1, adflow_integer, mpi_sum, &
1685  adflow_comm_world, ierr)
1686  call echk(ierr, __file__, __line__)
1687 
1688  if (myid == 0) then
1689  print *, 'Total number of orphans:', totalorphans
1690  end if
1691 
1692  ! if this is the last checkOverset call with lastCall = .True., then
1693  ! we can move the orphan information to iBlank because we have done all
1694  ! the checking required.
1695  if (lastcall .and. (totalorphans .gt. 0)) then
1696  ! loop over the cells and write the orphan information to iBlank
1697  do nn = 1, ndom
1698  call setpointers(nn, level, sps)
1699  do k = 2, kl
1700  do j = 2, jl
1701  do i = 2, il
1702  if (flowdoms(nn, level, sps)%iblankLast(i, j, k) == -5) iblank(i, j, k) = -5
1703  end do
1704  end do
1705  end do
1706  end do
1707  end if
1708 
1709  end subroutine checkoverset
1710 
1711  !
1712  ! Finds quadratic uvw weights [-1:1] for interpolant point
1713  ! xSearch by solving for its co-ord in donor element defined by
1714  ! xElem using newton-raphson iteration.
1715  ! Fractions uvwQuadratic come with initial guess from ADT search
1716  ! used for linear interpolation.
1717 
1718  subroutine computequadraticweights(xSearch, xElem, uvwQuadratic)
1719 
1720  use constants
1721 
1722  implicit none
1723 
1724  ! Input variables
1725  real(kind=realtype), intent(in) :: xsearch(3), xelem(3, -1:1, -1:1, -1:1)
1726  real(kind=realtype), intent(inout) :: uvwquadratic(3)
1727 
1728  ! Working variables
1729  ! -----------------------------------------------------------------
1730  ! newton related
1731  integer(kind=intType) :: n, niter
1732  real(kind=realtype) :: resid, residtol
1733  real(kind=realtype) :: b(3, 4)
1734 
1735  ! others
1736  integer(kind=intType) :: j, l, iii, jjj, kkk
1737  real(kind=realtype) :: ff(27), shp(3, 3), psi(3)
1738  real(kind=realtype) :: dff(27, 3), dshp(3, 3, 3) !-> differentials wrt 3 psi dirs
1739  logical :: ok_flag
1740  ! -----------------------------------------------------------------
1741 
1742  ! Initialize newton parameters
1743  niter = 0
1744  resid = 1.0e10
1745  residtol = 1.0e-15
1746 
1747  ! Begin newton iterations to solve for uvw weights wrt quadratic element
1748 
1749  newton_loop: do while (niter < 10 .and. resid > residtol)
1750 
1751  !step 1: find weights
1752  !--------------------
1753 
1754  ! Initialize weights
1755  psi(1:3) = uvwquadratic(1:3)
1756 
1757  ! Precopute the FE shape functions for each j-direction
1758  do j = 1, 3
1759  shp(1, j) = half * psi(j) * (psi(j) - one)
1760  shp(2, j) = -(psi(j)**2 - 1)
1761  shp(3, j) = half * psi(j) * (psi(j) + one)
1762  end do
1763 
1764  ! These are the 27 quadratic weights
1765  ff(1) = shp(1, 1) * shp(1, 2) * shp(1, 3)
1766  ff(2) = shp(2, 1) * shp(1, 2) * shp(1, 3)
1767  ff(3) = shp(3, 1) * shp(1, 2) * shp(1, 3)
1768 
1769  ff(4) = shp(1, 1) * shp(2, 2) * shp(1, 3)
1770  ff(5) = shp(2, 1) * shp(2, 2) * shp(1, 3)
1771  ff(6) = shp(3, 1) * shp(2, 2) * shp(1, 3)
1772 
1773  ff(7) = shp(1, 1) * shp(3, 2) * shp(1, 3)
1774  ff(8) = shp(2, 1) * shp(3, 2) * shp(1, 3)
1775  ff(9) = shp(3, 1) * shp(3, 2) * shp(1, 3)
1776 
1777  ff(10) = shp(1, 1) * shp(1, 2) * shp(2, 3)
1778  ff(11) = shp(2, 1) * shp(1, 2) * shp(2, 3)
1779  ff(12) = shp(3, 1) * shp(1, 2) * shp(2, 3)
1780 
1781  ff(13) = shp(1, 1) * shp(2, 2) * shp(2, 3)
1782  ff(14) = shp(2, 1) * shp(2, 2) * shp(2, 3)
1783  ff(15) = shp(3, 1) * shp(2, 2) * shp(2, 3)
1784 
1785  ff(16) = shp(1, 1) * shp(3, 2) * shp(2, 3)
1786  ff(17) = shp(2, 1) * shp(3, 2) * shp(2, 3)
1787  ff(18) = shp(3, 1) * shp(3, 2) * shp(2, 3)
1788 
1789  ff(19) = shp(1, 1) * shp(1, 2) * shp(3, 3)
1790  ff(20) = shp(2, 1) * shp(1, 2) * shp(3, 3)
1791  ff(21) = shp(3, 1) * shp(1, 2) * shp(3, 3)
1792 
1793  ff(22) = shp(1, 1) * shp(2, 2) * shp(3, 3)
1794  ff(23) = shp(2, 1) * shp(2, 2) * shp(3, 3)
1795  ff(24) = shp(3, 1) * shp(2, 2) * shp(3, 3)
1796 
1797  ff(25) = shp(1, 1) * shp(3, 2) * shp(3, 3)
1798  ff(26) = shp(2, 1) * shp(3, 2) * shp(3, 3)
1799  ff(27) = shp(3, 1) * shp(3, 2) * shp(3, 3)
1800 
1801  !step 2: find differentials of weights
1802  !-------------------------------------
1803 
1804  ! Linearize the FE shape functions wrt each psi(j) direction
1805  ! Note: only derivatives wrt psi(j) for any j are non-zero, rest are zero
1806 
1807  dshp(:, :, :) = 0.d0
1808  do j = 1, 3
1809  dshp(1, j, j) = half * (psi(j) - one) + half * psi(j)
1810  dshp(2, j, j) = -2.d0 * psi(j)
1811  dshp(3, j, j) = half * (psi(j) + one) + half * psi(j)
1812  end do
1813 
1814  ! Linearize 27 quadratic weights wrt each psi(j) dir, build from dshp
1815 
1816  loop_psi_j: do j = 1, 3
1817  dff(1, j) = dshp(1, 1, j) * shp(1, 2) * shp(1, 3) &
1818  + shp(1, 1) * dshp(1, 2, j) * shp(1, 3) &
1819  + shp(1, 1) * shp(1, 2) * dshp(1, 3, j)
1820 
1821  dff(2, j) = dshp(2, 1, j) * shp(1, 2) * shp(1, 3) &
1822  + shp(2, 1) * dshp(1, 2, j) * shp(1, 3) &
1823  + shp(2, 1) * shp(1, 2) * dshp(1, 3, j)
1824 
1825  dff(3, j) = dshp(3, 1, j) * shp(1, 2) * shp(1, 3) &
1826  + shp(3, 1) * dshp(1, 2, j) * shp(1, 3) &
1827  + shp(3, 1) * shp(1, 2) * dshp(1, 3, j)
1828 
1829  dff(4, j) = dshp(1, 1, j) * shp(2, 2) * shp(1, 3) &
1830  + shp(1, 1) * dshp(2, 2, j) * shp(1, 3) &
1831  + shp(1, 1) * shp(2, 2) * dshp(1, 3, j)
1832 
1833  dff(5, j) = dshp(2, 1, j) * shp(2, 2) * shp(1, 3) &
1834  + shp(2, 1) * dshp(2, 2, j) * shp(1, 3) &
1835  + shp(2, 1) * shp(2, 2) * dshp(1, 3, j)
1836 
1837  dff(6, j) = dshp(3, 1, j) * shp(2, 2) * shp(1, 3) &
1838  + shp(3, 1) * dshp(2, 2, j) * shp(1, 3) &
1839  + shp(3, 1) * shp(2, 2) * dshp(1, 3, j)
1840 
1841  dff(7, j) = dshp(1, 1, j) * shp(3, 2) * shp(1, 3) &
1842  + shp(1, 1) * dshp(3, 2, j) * shp(1, 3) &
1843  + shp(1, 1) * shp(3, 2) * dshp(1, 3, j)
1844 
1845  dff(8, j) = dshp(2, 1, j) * shp(3, 2) * shp(1, 3) &
1846  + shp(2, 1) * dshp(3, 2, j) * shp(1, 3) &
1847  + shp(2, 1) * shp(3, 2) * dshp(1, 3, j)
1848 
1849  dff(9, j) = dshp(3, 1, j) * shp(3, 2) * shp(1, 3) &
1850  + shp(3, 1) * dshp(3, 2, j) * shp(1, 3) &
1851  + shp(3, 1) * shp(3, 2) * dshp(1, 3, j)
1852 
1853  dff(10, j) = dshp(1, 1, j) * shp(1, 2) * shp(2, 3) &
1854  + shp(1, 1) * dshp(1, 2, j) * shp(2, 3) &
1855  + shp(1, 1) * shp(1, 2) * dshp(2, 3, j)
1856 
1857  dff(11, j) = dshp(2, 1, j) * shp(1, 2) * shp(2, 3) &
1858  + shp(2, 1) * dshp(1, 2, j) * shp(2, 3) &
1859  + shp(2, 1) * shp(1, 2) * dshp(2, 3, j)
1860 
1861  dff(12, j) = dshp(3, 1, j) * shp(1, 2) * shp(2, 3) &
1862  + shp(3, 1) * dshp(1, 2, j) * shp(2, 3) &
1863  + shp(3, 1) * shp(1, 2) * dshp(2, 3, j)
1864 
1865  dff(13, j) = dshp(1, 1, j) * shp(2, 2) * shp(2, 3) &
1866  + shp(1, 1) * dshp(2, 2, j) * shp(2, 3) &
1867  + shp(1, 1) * shp(2, 2) * dshp(2, 3, j)
1868 
1869  dff(14, j) = dshp(2, 1, j) * shp(2, 2) * shp(2, 3) &
1870  + shp(2, 1) * dshp(2, 2, j) * shp(2, 3) &
1871  + shp(2, 1) * shp(2, 2) * dshp(2, 3, j)
1872 
1873  dff(15, j) = dshp(3, 1, j) * shp(2, 2) * shp(2, 3) &
1874  + shp(3, 1) * dshp(2, 2, j) * shp(2, 3) &
1875  + shp(3, 1) * shp(2, 2) * dshp(2, 3, j)
1876 
1877  dff(16, j) = dshp(1, 1, j) * shp(3, 2) * shp(2, 3) &
1878  + shp(1, 1) * dshp(3, 2, j) * shp(2, 3) &
1879  + shp(1, 1) * shp(3, 2) * dshp(2, 3, j)
1880 
1881  dff(17, j) = dshp(2, 1, j) * shp(3, 2) * shp(2, 3) &
1882  + shp(2, 1) * dshp(3, 2, j) * shp(2, 3) &
1883  + shp(2, 1) * shp(3, 2) * dshp(2, 3, j)
1884 
1885  dff(18, j) = dshp(3, 1, j) * shp(3, 2) * shp(2, 3) &
1886  + shp(3, 1) * dshp(3, 2, j) * shp(2, 3) &
1887  + shp(3, 1) * shp(3, 2) * dshp(2, 3, j)
1888 
1889  dff(19, j) = dshp(1, 1, j) * shp(1, 2) * shp(3, 3) &
1890  + shp(1, 1) * dshp(1, 2, j) * shp(3, 3) &
1891  + shp(1, 1) * shp(1, 2) * dshp(3, 3, j)
1892 
1893  dff(20, j) = dshp(2, 1, j) * shp(1, 2) * shp(3, 3) &
1894  + shp(2, 1) * dshp(1, 2, j) * shp(3, 3) &
1895  + shp(2, 1) * shp(1, 2) * dshp(3, 3, j)
1896 
1897  dff(21, j) = dshp(3, 1, j) * shp(1, 2) * shp(3, 3) &
1898  + shp(3, 1) * dshp(1, 2, j) * shp(3, 3) &
1899  + shp(3, 1) * shp(1, 2) * dshp(3, 3, j)
1900 
1901  dff(22, j) = dshp(1, 1, j) * shp(2, 2) * shp(3, 3) &
1902  + shp(1, 1) * dshp(2, 2, j) * shp(3, 3) &
1903  + shp(1, 1) * shp(2, 2) * dshp(3, 3, j)
1904 
1905  dff(23, j) = dshp(2, 1, j) * shp(2, 2) * shp(3, 3) &
1906  + shp(2, 1) * dshp(2, 2, j) * shp(3, 3) &
1907  + shp(2, 1) * shp(2, 2) * dshp(3, 3, j)
1908 
1909  dff(24, j) = dshp(3, 1, j) * shp(2, 2) * shp(3, 3) &
1910  + shp(3, 1) * dshp(2, 2, j) * shp(3, 3) &
1911  + shp(3, 1) * shp(2, 2) * dshp(3, 3, j)
1912 
1913  dff(25, j) = dshp(1, 1, j) * shp(3, 2) * shp(3, 3) &
1914  + shp(1, 1) * dshp(3, 2, j) * shp(3, 3) &
1915  + shp(1, 1) * shp(3, 2) * dshp(3, 3, j)
1916 
1917  dff(26, j) = dshp(2, 1, j) * shp(3, 2) * shp(3, 3) &
1918  + shp(2, 1) * dshp(3, 2, j) * shp(3, 3) &
1919  + shp(2, 1) * shp(3, 2) * dshp(3, 3, j)
1920 
1921  dff(27, j) = dshp(3, 1, j) * shp(3, 2) * shp(3, 3) &
1922  + shp(3, 1) * dshp(3, 2, j) * shp(3, 3) &
1923  + shp(3, 1) * shp(3, 2) * dshp(3, 3, j)
1924 
1925  end do loop_psi_j
1926 
1927  ! Step 3: construct Jacobian d(R(psi(:))/d(psi(:)) and residue R(psi(:))
1928  ! ----------------------------------------------------------------------
1929 
1930  ! loop over x,y,z dirs, stored row-wise
1931  loop_xyz: do n = 1, 3
1932 
1933  ! construct LHS -d(R(psi(:))/d(psi(:))
1934 
1935  ! loop over each psi dir j
1936  do j = 1, 3
1937 
1938  ! loop over nodes
1939  l = 0
1940  b(n, j) = 0.d0
1941 
1942  do kkk = -1, 1
1943  do jjj = -1, 1
1944  do iii = -1, 1
1945  l = l + 1
1946  b(n, j) = b(n, j) + dff(l, j) * xelem(n, iii, jjj, kkk)
1947  end do
1948  end do
1949  end do
1950  end do !j
1951 
1952  ! construct RHS (Xp - sum_i(ff_i * X_i), i =1,27) for nth row (x,y or z)
1953  l = 0
1954  b(n, 4) = xsearch(n)
1955 
1956  ! loop over nodes
1957  do kkk = -1, 1
1958  do jjj = -1, 1
1959  do iii = -1, 1
1960  l = l + 1
1961  b(n, 4) = b(n, 4) - ff(l) * xelem(n, iii, jjj, kkk)
1962  end do
1963  end do
1964  end do
1965 
1966  end do loop_xyz
1967 
1968  ! Get d(uvwQuadratic) weights
1969  ! invert 3x3 matrix returns solution in b(:,4)
1970  call matrixinv3by3(b, ok_flag)
1971  if (.not. ok_flag) stop 'Can not invert B in computeQuadraticWeights'
1972 
1973  ! update uvwQuadratic weights
1974  do n = 1, 3
1975  uvwquadratic(n) = uvwquadratic(n) + b(n, 4)
1976 
1977  ! sanity check: if weights lie outside [-1:1] reset to 0.5
1978  if ((uvwquadratic(n) - 1) * (uvwquadratic(n) + 1) > 0.d0) uvwquadratic(n) = half
1979  end do
1980 
1981  ! L2-norm of residue
1982  resid = 0.d0
1983  do n = 1, 3
1984  resid = resid + b(n, 4)**2
1985  end do
1986 
1987  niter = niter + 1
1988 
1989  end do newton_loop
1990  end subroutine computequadraticweights
1991  !
1992  ! Plain invert of A to solve Ax=B
1993  ! a(3,3) --- matrix to be inverted
1994  ! a(:,4) --- contains the right hand side vector, also stores
1995  ! the final solution
1996 
1997  subroutine matrixinv3by3(a, ok_flag)
1998 
1999  use constants
2000  implicit none
2001 
2002  ! Input variables
2003  real(kind=realtype), intent(inout) :: a(3, 4)
2004  logical, intent(out) :: ok_flag
2005 
2006  ! Working variables
2007  integer(kind=intType) :: n
2008  real(kind=realtype) :: det, cofactor(3, 3), ainv(3, 3), rin(3, 1), rout(3, 1), myeps
2009 
2010  myeps = 1.0e-10
2011  ainv = 0.d0
2012 
2013  det = a(1, 1) * a(2, 2) * a(3, 3) &
2014  - a(1, 1) * a(2, 3) * a(3, 2) &
2015  - a(1, 2) * a(2, 1) * a(3, 3) &
2016  + a(1, 2) * a(2, 3) * a(3, 1) &
2017  + a(1, 3) * a(2, 1) * a(3, 2) &
2018  - a(1, 3) * a(2, 2) * a(3, 1)
2019 
2020  if (abs(det) <= myeps) then
2021  ainv = 0.0d0
2022  ok_flag = .false.
2023  return
2024  end if
2025 
2026  cofactor(1, 1) = +(a(2, 2) * a(3, 3) - a(2, 3) * a(3, 2))
2027  cofactor(1, 2) = -(a(2, 1) * a(3, 3) - a(2, 3) * a(3, 1))
2028  cofactor(1, 3) = +(a(2, 1) * a(3, 2) - a(2, 2) * a(3, 1))
2029  cofactor(2, 1) = -(a(1, 2) * a(3, 3) - a(1, 3) * a(3, 2))
2030  cofactor(2, 2) = +(a(1, 1) * a(3, 3) - a(1, 3) * a(3, 1))
2031  cofactor(2, 3) = -(a(1, 1) * a(3, 2) - a(1, 2) * a(3, 1))
2032  cofactor(3, 1) = +(a(1, 2) * a(2, 3) - a(1, 3) * a(2, 2))
2033  cofactor(3, 2) = -(a(1, 1) * a(2, 3) - a(1, 3) * a(2, 1))
2034  cofactor(3, 3) = +(a(1, 1) * a(2, 2) - a(1, 2) * a(2, 1))
2035 
2036  ainv = transpose(cofactor) / det
2037 
2038  ok_flag = .true.
2039 
2040  do n = 1, 3
2041  rin(n, 1) = a(n, 4)
2042  end do
2043 
2044  !save solution on a(:,4)
2045  rout = matmul(ainv, rin)
2046 
2047  do n = 1, 3
2048  a(n, 4) = rout(n, 1)
2049  end do
2050 
2051  end subroutine matrixinv3by3
2052 
2053  subroutine fringereduction(level, sps)
2054 
2055  use constants
2056  use blockpointers, only: ndom, il, jl, kl, status, fringeptr
2058  use utils, only: setpointers
2059  implicit none
2060 
2061  ! Input/Output
2062  integer(kind=intType), intent(in) :: level, sps
2063 
2064  ! Working
2065  integer(kind=intType) :: i, j, k, nn, ii, jj, kk, i_stencil
2066  logical :: computeCellFound
2067 
2068  do nn = 1, ndom
2069  call setpointers(nn, level, sps)
2070 
2071  do k = 2, kl
2072  do j = 2, jl
2073  do i = 2, il
2074 
2075  ! Check if this cell is a fringe:
2076  if (isreceiver(status(i, j, k))) then
2077 
2078  computecellfound = .false.
2079 
2080  stencilloop2: do i_stencil = 1, n_visc_drdw
2081  ii = visc_drdw_stencil(i_stencil, 1) + i
2082  jj = visc_drdw_stencil(i_stencil, 2) + j
2083  kk = visc_drdw_stencil(i_stencil, 3) + k
2084 
2085  if (iscompute(status(ii, jj, kk))) then
2086  ! This is a compute cell
2087  computecellfound = .true.
2088  end if
2089  end do stencilloop2
2090 
2091  if (.not. computecellfound) then
2092  ! This cell is a hole no compute cell
2093  ! surrounding a fringe, we can hard iblank it.
2094  call setishole(status(i, j, k), .true.)
2095  call setiscompute(status(i, j, k), .false.)
2096  call setisreceiver(status(i, j, k), .false.)
2097  fringeptr(1, i, j, k) = 0
2098 
2099  end if
2100  end if
2101  end do
2102  end do
2103  end do
2104  end do
2105 
2106  end subroutine fringereduction
2107 
2108  subroutine irregularcellcorrection(level, sps)
2109 
2110  use constants
2111  use blockpointers, only: ndom, il, jl, kl, status, ie, je, ke, forcedrecv
2112  use utils, only: setpointers
2113  implicit none
2114 
2115  ! Input/Output
2116  integer(kind=intType), intent(in) :: level, sps
2117 
2118  ! Working
2119  integer(kind=intType) :: i, j, k, nn
2120 
2121  do nn = 1, ndom
2122  call setpointers(nn, level, sps)
2123 
2124  do k = 2, kl
2125  do j = 2, jl
2126  do i = 2, il
2127  if (isdonor(status(i, j, k)) .and. &
2128  isreceiver(status(i, j, k))) then
2129 
2130  ! Clear the fringe
2131  call setisdonor(status(i, j, k), .false.)
2132  call setisreceiver(status(i, j, k), .false.)
2133  call setiscompute(status(i, j, k), .true.)
2134  end if
2135  end do
2136  end do
2137  end do
2138  end do
2139 
2140  end subroutine irregularcellcorrection
2141 
2143 
2144  ! This routine determines if there are any overset boundaries
2145  ! present in the mesh.
2146 
2147  use constants
2148  use blockpointers, only: ndom, nbocos, bctype
2149  use communication, only: adflow_comm_world
2150  use utils, only: setpointers, echk
2151  implicit none
2152 
2153  ! Function
2154  logical :: checkoversetpresent, local
2155 
2156  ! Working
2157  integer(Kind=intType) :: nn, mm, ierr
2158 
2159  local = .false.
2160  do nn = 1, ndom
2161  call setpointers(nn, 1_inttype, 1_inttype)
2162 
2163  do mm = 1, nbocos
2164  if (bctype(mm) == oversetouterbound) then
2165  local = .true.
2166  end if
2167  end do
2168  end do
2169 
2170  call mpi_allreduce(local, checkoversetpresent, 1, mpi_logical, mpi_lor, adflow_comm_world, ierr)
2171  call echk(ierr, __file__, __line__)
2172 
2173  end function checkoversetpresent
2174 
2175  subroutine setiblankarray(level, sps)
2176 
2177  use constants
2178  use block
2179  use blockpointers, only: ndom, il, jl, kl, status, iblank, flowdoms, ie, je, ke, forcedrecv
2182  use utils, only: setpointers, echk
2184  implicit none
2185 
2186  ! Input/Output
2187  integer(kind=intType), intent(in) :: level, sps
2188 
2189  ! Working
2190  integer(kind=intType) :: i, j, k, nn
2191  integer(kind=intType) :: nCompute, nFringe, nBlank, nFloodSeed, nFlooded, nExplicitBlanked
2192  integer(kind=intType) :: counts(6), ierr
2193  type(fringetype) :: fringe
2194  ncompute = 0
2195  nfringe = 0
2196  nblank = 0
2197  nfloodseed = 0
2198  nflooded = 0
2199  nexplicitblanked = 0
2200 
2201  do nn = 1, ndom
2202  call setpointers(nn, level, sps)
2203 
2204  do k = 2, kl
2205  do j = 2, jl
2206  do i = 2, il
2207 
2208  if (iblank(i, j, k) == -4) then
2209  nexplicitblanked = nexplicitblanked + 1
2210 
2211  else if (isreceiver(status(i, j, k))) then
2212  iblank(i, j, k) = -1
2213  nfringe = nfringe + 1
2214 
2215  else if (isfloodseed(status(i, j, k))) then
2216  iblank(i, j, k) = -3
2217  nfloodseed = nfloodseed + 1
2218 
2219  else if (isflooded(status(i, j, k))) then
2220  iblank(i, j, k) = -2
2221  nflooded = nflooded + 1
2222 
2223  else if (ishole(status(i, j, k))) then
2224  iblank(i, j, k) = 0
2225  nblank = nblank + 1
2226 
2227  else
2228  ! We need to explictly make sure forced receivers
2229  ! *NEVER EVER EVER EVER* get set as compute cells.
2230  if (forcedrecv(i, j, k) .ne. 0) then
2231  ! This is REALLY Bad. This cell must be a forced
2232  ! receiver but never found a donor.
2233  iblank(i, j, k) = 0
2234  nblank = nblank + 1
2235  else
2236  ! Compute cell
2237  ncompute = ncompute + 1
2238  iblank(i, j, k) = 1
2239  end if
2240  end if
2241  end do
2242  end do
2243  end do
2244  end do
2245 
2246  ! Update the iblank info.
2247  domainloop: do nn = 1, ndom
2248  flowdoms(nn, level, sps)%intCommVars(1)%var => &
2249  flowdoms(nn, level, sps)%iblank(:, :, :)
2250  end do domainloop
2251 
2252  ! Run the generic integer exchange
2254 
2255  call mpi_reduce((/ncompute, nfringe, nblank, nflooded, nfloodseed, nexplicitblanked/), &
2256  counts, 6, adflow_integer, mpi_sum, 0, adflow_comm_world, ierr)
2257  call echk(ierr, __file__, __line__)
2258 
2259  if (myid == 0) then
2260  print *, '+--------------------------------+'
2261  print *, '| Compute Cells :', counts(1)
2262  print *, '| Fringe Cells :', counts(2)
2263  print *, '| Blanked Cells :', counts(3)
2264  print *, '| Explicitly Blanked Cells:', counts(6)
2265  print *, '| Flooded Cells :', counts(4)
2266  print *, '| FloodSeed Cells :', counts(5)
2267  print *, '+--------------------------------+'
2268  end if
2269  end subroutine setiblankarray
2270 
2271  subroutine dumpiblank(level, sps)
2272 
2273  use constants
2274  use blockpointers, only: il, jl, kl, x, ndom, iblank
2275  use communication, only: myid
2276  use utils, only: setpointers
2277  implicit none
2278 
2279  ! Input/Output
2280  integer(kind=intType), intent(in) :: level, sps
2281 
2282  ! Working
2283  integer(kind=intType) :: i, j, k, nn
2284  real(kind=realtype) :: xp(3)
2285  character(80) :: fileName
2286 
2287  write (filename, "(a,I2.2,a)") "proc_", myid, ".dat"
2288  open (unit=19, file=trim(filename), form='formatted')
2289 
2290  do nn = 1, ndom
2291  call setpointers(nn, level, sps)
2292  do k = 2, kl
2293  do j = 2, jl
2294  do i = 2, il
2295 
2296  ! Compute the cell center:
2297  xp = eighth * ( &
2298  x(i - 1, j - 1, k - 1, :) + &
2299  x(i, j - 1, k - 1, :) + &
2300  x(i - 1, j, k - 1, :) + &
2301  x(i, j, k - 1, :) + &
2302  x(i - 1, j - 1, k, :) + &
2303  x(i, j - 1, k, :) + &
2304  x(i - 1, j, k, :) + &
2305  x(i, j, k, :))
2306 
2307  write (19, "(ES18.10, ES18.10, ES18.10, I3)") xp(1), xp(2), xp(3), iblank(i, j, k)
2308  end do
2309  end do
2310  end do
2311  end do
2312 
2313  close (19)
2314 
2315  end subroutine dumpiblank
2316 
2317  subroutine getworkarray(overlap, work)
2318 
2319  use constants
2320  use communication, only: myid
2321  use oversetdata, only: csrmatrix, ndomtotal
2322  implicit none
2323 
2324  ! Input/Output
2325  type(csrmatrix), intent(in) :: overlap
2326  integer(kind=intType), dimension(:, :), allocatable :: work
2327 
2328  ! Local variables
2329  integer(kind=intType) :: nWork, jj, iDom, jDom
2330 
2331  nwork = 0
2332  do jj = 1, overlap%nnz
2333  if (overlap%assignedProc(jj) == myid) then
2334  nwork = nwork + 1
2335  end if
2336  end do
2337  allocate (work(4, nwork))
2338 
2339  nwork = 0
2340  do idom = 1, ndomtotal
2341  do jj = overlap%rowPtr(idom), overlap%rowPtr(idom + 1) - 1
2342  jdom = overlap%colInd(jj)
2343  if (overlap%assignedProc(jj) == myid) then
2344  nwork = nwork + 1
2345  work(1, nwork) = idom
2346  work(2, nwork) = jdom
2347  work(3, nwork) = jj
2348  work(4, nwork) = 0
2349  end if
2350  end do
2351  end do
2352  end subroutine getworkarray
2353 
2354  subroutine writeoversetwall(oWall, fName)
2355 
2356  ! debug routine to dumb an owall to a file
2357  use constants
2358  use oversetdata
2359  implicit none
2360  type(oversetwall) :: oWall
2361  character(len=*), intent(in) :: fName
2362 
2363  integer(kind=intType) :: i, iDim
2364  open (unit=19, file=trim(fname), form='formatted')
2365  write (19, *) 'Variables = "CoordinateX" "CoordianteY" "CoordinateZ"'
2366  write (19, *) "Zone"
2367  write (19, *) "Nodes = ", owall%nNodes, " Elements= ", owall%nCells, " ZONETYPE=FEQUADRILATERAL"
2368  write (19, *) "DATAPACKING=BLOCK"
2369 
2370  do idim = 1, 3
2371  do i = 1, owall%nNodes
2372  write (19, *) owall%x(idim, i)
2373  end do
2374  end do
2375 
2376  do i = 1, owall%nCells
2377  write (19, *) owall%conn(1, i), owall%conn(2, i), owall%conn(3, i), owall%conn(4, i)
2378  end do
2379  close (19)
2380  end subroutine writeoversetwall
2381 
2382  subroutine getoversetiblank(blkList, n)
2383 
2384  ! This routine gathers a list of the iblank status of every
2385  ! compute cell in the original CGNS ordering. It then returns the
2386  ! full list on the root processor. Therefore, this routine is not
2387  ! memory or computation scalable. It is only meant to be used a
2388  ! debugging tool to ensure that the overset connectivity as
2389  ! computed with given parallel decomposition is the same as a
2390  ! different parallel decomposition.
2391 
2392  use constants
2393  use blockpointers, only: ndom, il, jl, kl, ibegor, jbegor, kbegor, &
2394  nbkglobal, iblank
2395  use cgnsgrid, only: cgnsdoms, cgnsndom
2398  use utils, only: setpointers, echk, terminate
2399 #include <petsc/finclude/petsc.h>
2400  use petsc
2401  implicit none
2402 
2403  ! Input/Output
2404  integer(kind=intType), intent(in) :: n
2405  integer(kind=intType), dimension(n), intent(out) :: blkList
2406 
2407  ! Working
2408 
2409  ! Working parameters
2410  integer(kind=intType) :: i, j, k, ierr, l, nx_cg, ny_cg, nz_cg
2411  integer(kind=intType) :: ii, indx, indy, indz, nn, cgnsInd
2412  integer(kind=intType), allocatable, dimension(:) :: cellOffset
2413  real(kind=realtype), dimension(:), pointer :: localptr
2414  real(kind=realtype) :: vals(5)
2415  vec cgnsvec
2416 
2417  ! This routine cannot be used in timespectral mode
2418  if (ntimeintervalsspectral > 1) then
2419  call terminate('getOversetIBlank', 'This routine can only be used '&
2420  &'with 1 spectral instance')
2421  end if
2422 
2423  allocate (celloffset(cgnsndom + 1))
2424  celloffset(1) = 0
2425  do nn = 1, cgnsndom
2426  celloffset(nn + 1) = celloffset(nn) + &
2427  cgnsdoms(nn)%nx * cgnsdoms(nn)%ny * cgnsdoms(nn)%nz
2428  end do
2429 
2430  ! Create the CGNSVector
2431  if (myid == 0) then
2432  call veccreatempi(adflow_comm_world, celloffset(cgnsndom + 1) * 5, &
2433  petsc_determine, cgnsvec, ierr)
2434  call echk(ierr, __file__, __line__)
2435 
2436  else
2437  call veccreatempi(adflow_comm_world, 0, petsc_determine, cgnsvec, ierr)
2438  call echk(ierr, __file__, __line__)
2439  end if
2440 
2441  call vecsetblocksize(cgnsvec, 5, ierr)
2442  call echk(ierr, __file__, __line__)
2443  ii = 0
2444  do nn = 1, ndom
2445  call setpointers(nn, 1, 1)
2446  do k = 2, kl
2447  do j = 2, jl
2448  do i = 2, il
2449 
2450  nx_cg = cgnsdoms(nbkglobal)%nx
2451  ny_cg = cgnsdoms(nbkglobal)%ny
2452  nz_cg = cgnsdoms(nbkglobal)%nz
2453 
2454  indx = ibegor + i - 2
2455  indy = jbegor + j - 2
2456  indz = kbegor + k - 2
2457 
2458  ! cgnsInd is zero-based
2459  cgnsind = celloffset(nbkglobal) + &
2460  (indz - 1) * ny_cg * nx_cg + &
2461  (indy - 1) * nx_cg + &
2462  (indx - 1)
2463  vals(1) = real(iblank(i, j, k))
2464  if (vals(1) <= -2) then
2465  vals(1) = 0
2466  end if
2467  vals(2) = real(nbkglobal)
2468  vals(3) = real(indx)
2469  vals(4) = real(indy)
2470  vals(5) = real(indz)
2471  call vecsetvaluesblocked(cgnsvec, 1, (/cgnsind/), vals, insert_values, ierr)
2472  call echk(ierr, __file__, __line__)
2473  end do
2474  end do
2475  end do
2476  end do
2477 
2478  call vecassemblybegin(cgnsvec, ierr)
2479  call echk(ierr, __file__, __line__)
2480 
2481  call vecassemblyend(cgnsvec, ierr)
2482  call echk(ierr, __file__, __line__)
2483 
2484  ! Get the local vector pointer. Only the root proc actually has
2485  ! values.
2486  call vecgetarrayf90(cgnsvec, localptr, ierr)
2487  call echk(ierr, __file__, __line__)
2488 
2489  ! Convert back to integer.
2490  do i = 1, size(localptr)
2491  blklist(i) = int(localptr(i))
2492  end do
2493 
2494  call vecrestorearrayf90(cgnsvec, localptr, ierr)
2495  call echk(ierr, __file__, __line__)
2496 
2497  end subroutine getoversetiblank
2498 
2499 #endif
2500 
2501  ! --------------------------------------------------
2502  ! Tapenade Routine BELOW this point
2503  ! --------------------------------------------------
2504 
2505  subroutine fractoweights(frac, weights)
2506  use constants
2507  implicit none
2508  real(kind=realtype), intent(in), dimension(3) :: frac
2509  real(kind=realtype), intent(out), dimension(8) :: weights
2510 
2511  weights(1) = (one - frac(1)) * (one - frac(2)) * (one - frac(3))
2512  weights(2) = (frac(1)) * (one - frac(2)) * (one - frac(3))
2513  weights(3) = (one - frac(1)) * (frac(2)) * (one - frac(3))
2514  weights(4) = (frac(1)) * (frac(2)) * (one - frac(3))
2515  weights(5) = (one - frac(1)) * (one - frac(2)) * (frac(3))
2516  weights(6) = (frac(1)) * (one - frac(2)) * (frac(3))
2517  weights(7) = (one - frac(1)) * (frac(2)) * (frac(3))
2518  weights(8) = (frac(1)) * (frac(2)) * (frac(3))
2519  end subroutine fractoweights
2520 
2521  subroutine fractoweights2(frac, weights)
2522  use constants
2523  implicit none
2524  real(kind=realtype), intent(in), dimension(3) :: frac
2525  real(kind=realtype), intent(out), dimension(8) :: weights
2526 
2527  weights(1) = (one - frac(1)) * (one - frac(2)) * (one - frac(3))
2528  weights(2) = (frac(1)) * (one - frac(2)) * (one - frac(3))
2529  weights(3) = (frac(1)) * (frac(2)) * (one - frac(3))
2530  weights(4) = (one - frac(1)) * (frac(2)) * (one - frac(3))
2531 
2532  weights(5) = (one - frac(1)) * (one - frac(2)) * (frac(3))
2533  weights(6) = (frac(1)) * (one - frac(2)) * (frac(3))
2534  weights(7) = (frac(1)) * (frac(2)) * (frac(3))
2535  weights(8) = (one - frac(1)) * (frac(2)) * (frac(3))
2536 
2537  end subroutine fractoweights2
2538 
2539  subroutine newtonupdate(xCen, blk, frac0, frac)
2540 
2541  ! This routine performs the newton update to recompute the new
2542  ! "frac" (u,v,w) for the point xCen. The actual search is performed
2543  ! on the the dual cell formed by the cell centers of the 3x3x3 block
2544  ! of primal nodes. This routine is AD'd with tapenade in both
2545  ! forward and reverse.
2546 
2547  use constants
2548  implicit none
2549 
2550  ! Input
2551  real(kind=realtype), dimension(3), intent(in) :: xcen
2552  real(kind=realtype), dimension(3, 3, 3, 3), intent(in) :: blk
2553  real(kind=realtype), dimension(3), intent(in) :: frac0
2554  ! Output
2555  real(kind=realtype), dimension(3), intent(out) :: frac
2556 
2557  ! Working
2558  real(kind=realtype), dimension(3, 1:8) :: xn
2559  real(kind=realtype) :: u, v, w, uv, uw, vw, wvu, du, dv, dw
2560  real(kind=realtype) :: a11, a12, a13, a21, a22, a23, a31, a32, a33, val
2561  real(kind=realtype) :: f(3), x(3)
2562  integer(kind=intType), dimension(8), parameter :: indices = [1, 2, 4, 3, 5, 6, 8, 7]
2563  integer(kind=intType) :: i, j, k, ii, ll
2564  real(kind=realtype), parameter :: adteps = 1.e-25_realtype
2565  real(kind=realtype), parameter :: thresconv = 1.e-10_realtype
2566 
2567  ! Compute the cell center locations for the 8 nodes describing the
2568  ! dual cell. Note that this must be counter-clockwise ordering.
2569 
2570  ii = 0
2571  do k = 1, 2
2572  do j = 1, 2
2573  do i = 1, 2
2574  ii = ii + 1
2575  xn(:, indices(ii)) = eighth * ( &
2576  blk(i, j, k, :) + &
2577  blk(i + 1, j, k, :) + &
2578  blk(i, j + 1, k, :) + &
2579  blk(i + 1, j + 1, k, :) + &
2580  blk(i, j, k + 1, :) + &
2581  blk(i + 1, j, k + 1, :) + &
2582  blk(i, j + 1, k + 1, :) + &
2583  blk(i + 1, j + 1, k + 1, :))
2584  end do
2585  end do
2586  end do
2587 
2588  ! Compute the coordinates relative to node 1.
2589 
2590  do i = 2, 8
2591  xn(:, i) = xn(:, i) - xn(:, 1)
2592  end do
2593 
2594  ! Compute the location of our seach point relative to the first node.
2595  x = xcen - xn(:, 1)
2596 
2597  ! Modify the coordinates of node 3, 6, 8 and 7 such that
2598  ! they correspond to the weights of the u*v, u*w, v*w and
2599  ! u*v*w term in the transformation respectively.
2600 
2601  xn(1, 7) = xn(1, 7) + xn(1, 2) + xn(1, 4) + xn(1, 5) &
2602  - xn(1, 3) - xn(1, 6) - xn(1, 8)
2603  xn(2, 7) = xn(2, 7) + xn(2, 2) + xn(2, 4) + xn(2, 5) &
2604  - xn(2, 3) - xn(2, 6) - xn(2, 8)
2605  xn(3, 7) = xn(3, 7) + xn(3, 2) + xn(3, 4) + xn(3, 5) &
2606  - xn(3, 3) - xn(3, 6) - xn(3, 8)
2607 
2608  xn(1, 3) = xn(1, 3) - xn(1, 2) - xn(1, 4)
2609  xn(2, 3) = xn(2, 3) - xn(2, 2) - xn(2, 4)
2610  xn(3, 3) = xn(3, 3) - xn(3, 2) - xn(3, 4)
2611 
2612  xn(1, 6) = xn(1, 6) - xn(1, 2) - xn(1, 5)
2613  xn(2, 6) = xn(2, 6) - xn(2, 2) - xn(2, 5)
2614  xn(3, 6) = xn(3, 6) - xn(3, 2) - xn(3, 5)
2615 
2616  xn(1, 8) = xn(1, 8) - xn(1, 4) - xn(1, 5)
2617  xn(2, 8) = xn(2, 8) - xn(2, 4) - xn(2, 5)
2618  xn(3, 8) = xn(3, 8) - xn(3, 4) - xn(3, 5)
2619 
2620  ! Set the starting values of u, v and w based on our previous values
2621 
2622  u = frac0(1); v = frac0(2); w = frac0(3);
2623  ! The Newton algorithm to determine the parametric
2624  ! weights u, v and w for the given coordinate.
2625 
2626  newtonhexa: do ll = 1, 15
2627 
2628  ! Compute the RHS.
2629 
2630  uv = u * v; uw = u * w; vw = v * w; wvu = u * v * w
2631 
2632  f(1) = xn(1, 2) * u + xn(1, 4) * v + xn(1, 5) * w &
2633  + xn(1, 3) * uv + xn(1, 6) * uw + xn(1, 8) * vw &
2634  + xn(1, 7) * wvu - x(1)
2635  f(2) = xn(2, 2) * u + xn(2, 4) * v + xn(2, 5) * w &
2636  + xn(2, 3) * uv + xn(2, 6) * uw + xn(2, 8) * vw &
2637  + xn(2, 7) * wvu - x(2)
2638  f(3) = xn(3, 2) * u + xn(3, 4) * v + xn(3, 5) * w &
2639  + xn(3, 3) * uv + xn(3, 6) * uw + xn(3, 8) * vw &
2640  + xn(3, 7) * wvu - x(3)
2641 
2642  ! Compute the Jacobian.
2643 
2644  a11 = xn(1, 2) + xn(1, 3) * v + xn(1, 6) * w + xn(1, 7) * vw
2645  a12 = xn(1, 4) + xn(1, 3) * u + xn(1, 8) * w + xn(1, 7) * uw
2646  a13 = xn(1, 5) + xn(1, 6) * u + xn(1, 8) * v + xn(1, 7) * uv
2647 
2648  a21 = xn(2, 2) + xn(2, 3) * v + xn(2, 6) * w + xn(2, 7) * vw
2649  a22 = xn(2, 4) + xn(2, 3) * u + xn(2, 8) * w + xn(2, 7) * uw
2650  a23 = xn(2, 5) + xn(2, 6) * u + xn(2, 8) * v + xn(2, 7) * uv
2651 
2652  a31 = xn(3, 2) + xn(3, 3) * v + xn(3, 6) * w + xn(3, 7) * vw
2653  a32 = xn(3, 4) + xn(3, 3) * u + xn(3, 8) * w + xn(3, 7) * uw
2654  a33 = xn(3, 5) + xn(3, 6) * u + xn(3, 8) * v + xn(3, 7) * uv
2655 
2656  ! Compute the determinant. Make sure that it is not zero
2657  ! and invert the value. The cut off is needed to be able
2658  ! to handle exceptional cases for degenerate elements.
2659 
2660  val = a11 * (a22 * a33 - a32 * a23) + a21 * (a13 * a32 - a12 * a33) &
2661  + a31 * (a12 * a23 - a13 * a22)
2662  val = sign(one, val) / max(abs(val), adteps)
2663 
2664  ! Compute the new values of u, v and w.
2665 
2666  du = val * ((a22 * a33 - a23 * a32) * f(1) &
2667  + (a13 * a32 - a12 * a33) * f(2) &
2668  + (a12 * a23 - a13 * a22) * f(3))
2669  dv = val * ((a23 * a31 - a21 * a33) * f(1) &
2670  + (a11 * a33 - a13 * a31) * f(2) &
2671  + (a13 * a21 - a11 * a23) * f(3))
2672  dw = val * ((a21 * a32 - a22 * a31) * f(1) &
2673  + (a12 * a31 - a11 * a32) * f(2) &
2674  + (a11 * a22 - a12 * a21) * f(3))
2675 
2676  u = u - du; v = v - dv; w = w - dw
2677 
2678  ! Exit the loop if the update of the parametric
2679  ! weights is below the threshold
2680 
2681  val = sqrt(du * du + dv * dv + dw * dw)
2682  if (val <= thresconv) then
2683  exit newtonhexa
2684  end if
2685 
2686  end do newtonhexa
2687 
2688  ! We would *like* that all solutions fall inside the hexa, but we
2689  ! can't be picky here since we are not changing the donors. So
2690  ! whatever the u,v,w is we have to accept. Even if it is greater than
2691  ! 1 or less than zero, it shouldn't be by much.
2692 
2693  frac(1) = u
2694  frac(2) = v
2695  frac(3) = w
2696 
2697  end subroutine newtonupdate
2698 
2699 end module oversetutilities
subroutine destroyserialquad(ADT)
Definition: adtBuild.F90:1404
subroutine destroyserialhex(ADT)
Definition: adtBuild.F90:1266
Definition: BCData.F90:1
Definition: block.F90:1
integer(kind=inttype) ndom
Definition: block.F90:761
integer(kind=inttype) fringesorttype
Definition: block.F90:764
type(blocktype), dimension(:, :, :), allocatable, target flowdoms
Definition: block.F90:771
integer(kind=inttype), dimension(:, :), pointer orphans
integer(kind=inttype) jl
integer(kind=inttype) norphans
integer(kind=inttype) kbegor
integer(kind=inttype) nx
integer(kind=inttype) ny
integer(kind=inttype), dimension(:, :, :, :), pointer fringeptr
integer(kind=inttype) ie
integer(kind=inttype), dimension(:, :, :), pointer iblank
integer(kind=inttype) nbkglobal
integer(kind=inttype), dimension(:), pointer bcfaceid
integer(kind=inttype) ibegor
integer(kind=inttype) nbocos
integer(kind=inttype), dimension(:, :, :), pointer status
integer(kind=inttype) jbegor
integer(kind=inttype), dimension(:), pointer bctype
integer(kind=inttype) nz
integer(kind=inttype), dimension(:, :, :), pointer forcedrecv
integer(kind=inttype) je
integer(kind=inttype) ke
real(kind=realtype), dimension(:, :, :, :), pointer x
integer(kind=inttype) kl
integer(kind=inttype) il
type(cgnsblockinfotype), dimension(:), allocatable cgnsdoms
Definition: cgnsGrid.F90:495
integer(kind=inttype) cgnsndom
Definition: cgnsGrid.F90:491
type(internalcommtype), dimension(:), allocatable internalcell_2nd
type(commtype), dimension(:), allocatable commpatterncell_2nd
integer adflow_comm_world
integer(kind=inttype), parameter eulerwall
Definition: constants.F90:262
integer(kind=inttype), parameter oversetouterbound
Definition: constants.F90:276
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
real(kind=realtype), parameter eighth
Definition: constants.F90:84
integer(kind=inttype), parameter nswalladiabatic
Definition: constants.F90:260
integer(kind=inttype), parameter sortbyreceiver
Definition: constants.F90:325
real(kind=realtype), parameter one
Definition: constants.F90:72
real(kind=realtype), parameter half
Definition: constants.F90:80
integer(kind=inttype), parameter imin
Definition: constants.F90:292
integer(kind=inttype), parameter sortbydonor
Definition: constants.F90:324
integer(kind=inttype), parameter nswallisothermal
Definition: constants.F90:261
integer(kind=inttype), parameter kmax
Definition: constants.F90:297
integer(kind=inttype), parameter jmin
Definition: constants.F90:294
subroutine whalo1to1intgeneric_b(nVar, level, sps, commPattern, internal)
subroutine whalo1to1intgeneric(nVar, level, sps, commPattern, internal)
logical oversetdebugprint
Definition: inputParam.F90:895
integer(kind=inttype) ntimeintervalsspectral
Definition: inputParam.F90:645
subroutine, public kdtree2destroy(tp)
Definition: kd_tree.f90:979
real(kind=realtype), dimension(itotal) oversettimes
Definition: overset.F90:380
integer(kind=inttype) ndomtotal
Definition: overset.F90:365
real(kind=realtype), dimension(itotal) tstart
Definition: overset.F90:379
subroutine wallsonblock(wallsPresent)
subroutine irregularcellcorrection(level, sps)
subroutine getoversetiblank(blkList, n)
subroutine setisdonor(i, flag)
subroutine writeoversetwall(oWall, fName)
subroutine deallocateofringes(oFringes, n)
subroutine fractoweights(frac, weights)
logical function ishole(i)
subroutine binsearchnodes(arr, searchNode, nn, searchInd)
logical function isfloodseed(i)
subroutine qsortpocketedgetype(arr, nn)
subroutine unwindindex(index, il, jl, kl, i, j, k)
subroutine addtofringelist(fringeList, n, fringe)
subroutine qsortedgetype(arr, nn)
subroutine tic(index)
subroutine qsortfringetype(arr, nn, sortType)
logical function iswalldonor(i)
subroutine newtonupdate(xCen, blk, frac0, frac)
subroutine toc(index)
logical function checkoversetpresent()
subroutine setiblankarray(level, sps)
subroutine getcumulativeform(sizeArray, n, cumArray)
logical function isdonor(i)
subroutine setisfloodseed(i, flag)
subroutine computefringeprocarray(fringes, n, fringeProc, cumFringeProc, nFringeProc)
subroutine deallocatecsrmatrix(mat1)
logical function isreceiver(i)
subroutine setiswalldonor(i, flag)
subroutine getstatus(i, isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver)
subroutine addtofringebuffer(intBuffer, realBuffer, n, fringe)
subroutine computequadraticweights(xSearch, xElem, uvwQuadratic)
subroutine checkoverset(level, sps, totalOrphans, lastCall)
logical function iscompute(i)
subroutine fractoweights2(frac, weights)
subroutine deallocateosurfs(oSurfs, n)
subroutine getworkarray(overlap, work)
integer(kind=inttype) function windindex(i, j, k, il, jl, kl)
subroutine printoverlapmatrix(overlap)
logical function isflooded(i)
subroutine transposeoverlap(A, B)
subroutine setiscompute(i, flag)
subroutine setstatus(i, isDonor, isHole, isCompute, isFloodSeed, isFlooded, isWallDonor, isReceiver)
subroutine setishole(i, flag)
subroutine fringereduction(level, sps)
subroutine deallocateoblocks(oBlocks, n)
subroutine dumpiblank(level, sps)
subroutine matrixinv3by3(a, ok_flag)
subroutine setisflooded(i, flag)
subroutine binsearchpocketedgetype(arr, search, nn, searchInd)
subroutine setisreceiver(i, flag)
integer(kind=inttype), parameter n_visc_drdw
Definition: stencils.f90:19
integer(kind=inttype), dimension(33, 3), target visc_drdw_stencil
Definition: stencils.f90:22
Definition: utils.F90:1
subroutine echk(errorcode, file, line)
Definition: utils.F90:5722
subroutine setpointers(nn, mm, ll)
Definition: utils.F90:3237
subroutine terminate(routineName, errorMessage)
Definition: utils.F90:502