Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
fdm.F90
Go to the documentation of this file.
1! Copyright (c) 2008-2020, UCHICAGO ARGONNE, LLC.
2!
3! The UChicago Argonne, LLC as Operator of Argonne National
4! Laboratory holds copyright in the Software. The copyright holder
5! reserves all rights except those expressly granted to licensees,
6! and U.S. Government license rights.
7!
8! Redistribution and use in source and binary forms, with or without
9! modification, are permitted provided that the following conditions
10! are met:
11!
12! 1. Redistributions of source code must retain the above copyright
13! notice, this list of conditions and the disclaimer below.
14!
15! 2. Redistributions in binary form must reproduce the above copyright
16! notice, this list of conditions and the disclaimer (as noted below)
17! in the documentation and/or other materials provided with the
18! distribution.
19!
20! 3. Neither the name of ANL nor the names of its contributors
21! may be used to endorse or promote products derived from this software
22! without specific prior written permission.
23!
24! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28! UCHICAGO ARGONNE, LLC, THE U.S. DEPARTMENT OF
29! ENERGY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
31! TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32! DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33! THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34! (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35! OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36!
37! Additional BSD Notice
38! ---------------------
39! 1. This notice is required to be provided under our contract with
40! the U.S. Department of Energy (DOE). This work was produced at
41! Argonne National Laboratory under Contract
42! No. DE-AC02-06CH11357 with the DOE.
43!
44! 2. Neither the United States Government nor UCHICAGO ARGONNE,
45! LLC nor any of their employees, makes any warranty,
46! express or implied, or assumes any liability or responsibility for the
47! accuracy, completeness, or usefulness of any information, apparatus,
48! product, or process disclosed, or represents that its use would not
49! infringe privately-owned rights.
50!
51! 3. Also, reference herein to any specific commercial products, process,
52! or services by trade name, trademark, manufacturer or otherwise does
53! not necessarily constitute or imply its endorsement, recommendation,
54! or favoring by the United States Government or UCHICAGO ARGONNE LLC.
55! The views and opinions of authors expressed
56! herein do not necessarily state or reflect those of the United States
57! Government or UCHICAGO ARGONNE, LLC, and shall
58! not be used for advertising or product endorsement purposes.
59!
61module fdm
63 use num_types, only : rp, sp, dp, qp
64 use mesh, only : mesh_t
65 use space, only : space_t
66 use dofmap, only : dofmap_t
67 use gather_scatter, only : gs_t, gs_op_add
68 use fdm_cpu, only : fdm_do_fast_cpu
70 use fdm_sx, only : fdm_do_fast_sx
71 use fdm_xsmm, only : fdm_do_fast_xsmm
72 use utils, only : neko_error, neko_warning
73 use comm, only : pe_rank
74 use math, only : vlmax
77 use fast3d, only : semhat
78 use tensor, only : trsp
79 use math, only : rzero, row_zero
80 use, intrinsic :: iso_c_binding
81 implicit none
82 private
83
84 type, public :: fdm_t
85 real(kind=rp), allocatable :: s(:,:,:,:)
86 real(kind=rp), allocatable :: d(:,:)
87 type(c_ptr) :: s_d = c_null_ptr
88 type(c_ptr) :: d_d = c_null_ptr
89 real(kind=rp), allocatable :: len_lr(:), len_ls(:), len_lt(:)
90 real(kind=rp), allocatable :: len_mr(:), len_ms(:), len_mt(:)
91 real(kind=rp), allocatable :: len_rr(:), len_rs(:), len_rt(:)
92 real(kind=rp), allocatable :: swplen(:,:,:,:)
93 type(c_ptr) :: swplen_d = c_null_ptr
94 type(space_t), pointer :: xh => null()
95 type(dofmap_t), pointer :: dof => null()
96 type(gs_t), pointer :: gs_h => null()
97 type(mesh_t), pointer :: msh => null()
98 contains
99 procedure, pass(this) :: init => fdm_init
100 procedure, pass(this) :: free => fdm_free
101 procedure, pass(this) :: compute => fdm_compute
102 end type fdm_t
103
104 interface sygv
105 module procedure sp_sygv, dp_sygv
106#ifdef HAVE_REAL128
107 module procedure qp_sygv
108#endif
109 end interface sygv
110
111contains
112
113 subroutine fdm_init(this, Xh, dof, gs_h)
114 class(fdm_t), intent(inout) :: this
115 type(space_t), target, intent(inout) :: Xh
116 type(dofmap_t), target, intent(in) :: dof
117 type(gs_t), target, intent(inout) :: gs_h
118 !We only really use ah, bh
119 real(kind=rp), dimension((Xh%lx)**2) :: ah, bh, ch, dh, zh
120 real(kind=rp), dimension((Xh%lx)**2) :: dph, jph, bgl, zglhat, dgl, jgl, wh
121 integer :: nl, n, nelv
122
123 n = xh%lx - 1 !Polynomnial degree
124 nl = xh%lx + 2 !Schwarz!
125 nelv = dof%msh%nelv
126 call fdm_free(this)
127 allocate(this%s(nl*nl, 2, dof%msh%gdim, dof%msh%nelv))
128 allocate(this%d(nl**3, dof%msh%nelv))
129 allocate(this%swplen(xh%lx, xh%lx, xh%lx, dof%msh%nelv))
130 allocate(this%len_lr(nelv), this%len_ls(nelv), this%len_lt(nelv))
131 allocate(this%len_mr(nelv), this%len_ms(nelv), this%len_mt(nelv))
132 allocate(this%len_rr(nelv), this%len_rs(nelv), this%len_rt(nelv))
133
134 ! Zeroing here enables easier debugging since then
135 ! MPI messages in GS are deterministic
136 call rzero(this%swplen, xh%lxyz * dof%msh%nelv)
137
138 if (neko_bcknd_device .eq. 1) then
139 call device_map(this%s, this%s_d, nl*nl*2*dof%msh%gdim*dof%msh%nelv)
140 call device_map(this%d, this%d_d, nl**dof%msh%gdim*dof%msh%nelv)
141 call device_map(this%swplen, this%swplen_d, xh%lxyz*dof%msh%nelv)
142 end if
143
144 call semhat(ah, bh, ch, dh, zh, dph, jph, bgl, zglhat, dgl, jgl, n, wh)
145 this%Xh => xh
146 this%dof => dof
147 this%gs_h => gs_h
148 this%msh => dof%msh
149
150 call swap_lengths(this, dof%x%x, dof%y%x, dof%z%x, dof%msh%nelv, dof%msh%gdim)
151
152 call fdm_setup_fast(this, ah, bh, nl, n)
153
154 if (neko_bcknd_device .eq. 1) then
155 call device_memcpy(this%s, this%s_d, &
156 nl*nl*2*dof%msh%gdim*dof%msh%nelv, host_to_device, sync = .false.)
157 call device_memcpy(this%d, this%d_d, &
158 nl**dof%msh%gdim*dof%msh%nelv, host_to_device, sync = .false.)
159 call device_memcpy(this%swplen, this%swplen_d, &
160 xh%lxyz*dof%msh%nelv, host_to_device, sync = .false.)
161 end if
162 end subroutine fdm_init
163
164 subroutine swap_lengths(this, x, y, z, nelv, gdim)
165 type(fdm_t), intent(inout) :: this
166 integer, intent(in) :: gdim, nelv
167 real(kind=rp), dimension(this%Xh%lxyz, nelv), intent(in) :: x, y, z
168 integer :: j, k, e, n2, nz0, nzn, nx, lx1, n
169
170 associate(l => this%swplen, xh => this%Xh, &
171 llr => this%len_lr, lls => this%len_ls, llt => this%len_lt, &
172 lmr => this%len_mr, lms => this%len_ms, lmt => this%len_mt, &
173 lrr => this%len_rr, lrs => this%len_rs, lrt => this%len_rt)
174 lx1 = this%Xh%lx
175 n2 = lx1 - 1
176 nz0 = 1
177 nzn = 1
178 nx = lx1 - 2
179 if (gdim .eq. 3) then
180 nz0 = 0
181 nzn = n2
182 end if
183 call plane_space(lmr, lms, lmt, 0, n2, xh%wx, x, y, z, &
184 nx, n2, nz0, nzn, nelv, gdim)
185 n = n2 + 1
186 if (gdim .eq. 3) then
187 do e = 1, nelv
188 do j = 2, n2
189 do k = 2, n2
190 l(1, k, j, e) = lmr(e)
191 l(n, k, j, e) = lmr(e)
192 l(k, 1, j, e) = lms(e)
193 l(k, n, j, e) = lms(e)
194 l(k, j, 1, e) = lmt(e)
195 l(k, j, n, e) = lmt(e)
196 end do
197 end do
198 end do
199 if (neko_bcknd_device .eq. 1) then
200 call device_memcpy(l, this%swplen_d, this%dof%size(), &
201 host_to_device, sync = .false.)
202 call this%gs_h%op(l, this%dof%size(), gs_op_add)
203 call device_memcpy(l, this%swplen_d, this%dof%size(), &
204 device_to_host, sync = .true.)
205 else
206 call this%gs_h%op(l, this%dof%size(), gs_op_add)
207 end if
208
209 do e = 1, nelv
210 llr(e) = l(1, 2, 2, e) - lmr(e)
211 lrr(e) = l(n, 2, 2, e) - lmr(e)
212 lls(e) = l(2, 1, 2, e) - lms(e)
213 lrs(e) = l(2, n, 2, e) - lms(e)
214 llt(e) = l(2, 2, 1, e) - lmt(e)
215 lrt(e) = l(2, 2, n, e) - lmt(e)
216 end do
217 else
218 do e = 1, nelv
219 do j = 2, n2
220 l(1, j, 1, e) = lmr(e)
221 l(n, j, 1, e) = lmr(e)
222 l(j, 1, 1, e) = lms(e)
223 l(j, n, 1, e) = lms(e)
224 end do
225 end do
226
227 if (neko_bcknd_device .eq. 1) then
228 call device_memcpy(l, this%swplen_d, this%dof%size(), &
229 host_to_device, sync = .false.)
230 call this%gs_h%op(l, this%dof%size(), gs_op_add)
231 call device_memcpy(l, this%swplen_d, this%dof%size(), &
232 device_to_host, sync = .true.)
233 else
234 call this%gs_h%op(l, this%dof%size(), gs_op_add)
235 end if
236
237 do e = 1, nelv
238 llr(e) = l(1, 2, 1, e) - lmr(e)
239 lrr(e) = l(n, 2, 1, e) - lmr(e)
240 lls(e) = l(2, 1, 1, e) - lms(e)
241 lrs(e) = l(2, n, 1, e) - lms(e)
242 end do
243 end if
244 end associate
245 end subroutine swap_lengths
246
250 subroutine plane_space(lr, ls, lt, i1, i2, w, x, y, z, &
251 nx, nxn, nz0, nzn, nelv, gdim)
252 integer, intent(in) :: nxn, nzn, i1, i2, nelv, gdim, nx, nz0
253 real(kind=rp), intent(inout) :: lr(nelv), ls(nelv), lt(nelv)
254 real(kind=rp), intent(inout) :: w(nx)
255 real(kind=rp), intent(in) :: x(0:nxn, 0:nxn, nz0:nzn, nelv)
256 real(kind=rp), intent(in) :: y(0:nxn, 0:nxn, nz0:nzn, nelv)
257 real(kind=rp), intent(in) :: z(0:nxn, 0:nxn, nz0:nzn, nelv)
258 real(kind=rp) :: lr2, ls2, lt2, weight, wsum
259 integer :: ny, nz, j1, k1, j2, k2, i, j, k, ie
260 ny = nx
261 nz = nx
262 j1 = i1
263 k1 = i1
264 j2 = i2
265 k2 = i2
266 ! Now, for each element, compute lr,ls,lt between specified planes
267 do ie = 1, nelv
268 if (gdim .eq. 3) then
269 lr2 = 0d0
270 wsum = 0d0
271 do k = 1, nz
272 do j = 1, ny
273 weight = w(j)*w(k)
274 lr2 = lr2 + weight /&
275 ( (x(i2, j, k, ie) - x(i1, j, k, ie))**2&
276 + (y(i2, j, k, ie) - y(i1, j, k, ie))**2&
277 + (z(i2, j, k, ie) - z(i1, j, k, ie))**2 )
278 wsum = wsum + weight
279 end do
280 end do
281 lr2 = lr2/wsum
282 lr(ie) = 1d0/sqrt(lr2)
283 ls2 = 0d0
284 wsum = 0d0
285 do k = 1, nz
286 do i = 1, nx
287 weight = w(i)*w(k)
288 ls2 = ls2 + weight / &
289 ( (x(i, j2, k, ie) - x(i, j1, k, ie))**2 &
290 + (y(i, j2, k, ie) - y(i, j1, k, ie))**2 &
291 + (z(i, j2, k, ie) - z(i, j1, k, ie))**2 )
292 wsum = wsum + weight
293 end do
294 end do
295 ls2 = ls2/wsum
296 ls(ie) = 1d0/sqrt(ls2)
297 lt2 = 0d0
298 wsum = 0d0
299 do j = 1, ny
300 do i = 1, nx
301 weight = w(i)*w(j)
302 lt2 = lt2 + weight / &
303 ( (x(i, j, k2, ie) - x(i, j, k1, ie))**2 &
304 + (y(i, j, k2, ie) - y(i, j, k1, ie))**2 &
305 + (z(i, j, k2, ie) - z(i, j, k1, ie))**2 )
306 wsum = wsum + weight
307 end do
308 end do
309 lt2 = lt2/wsum
310 lt(ie) = 1d0/sqrt(lt2)
311 else ! 2D
312 lr2 = 0d0
313 wsum = 0d0
314 do j = 1, ny
315 weight = w(j)
316 lr2 = lr2 + weight / &
317 ( (x(i2, j, 1, ie) - x(i1, j, 1, ie))**2 &
318 + (y(i2, j, 1, ie) - y(i1, j, 1, ie))**2 )
319 wsum = wsum + weight
320 end do
321 lr2 = lr2/wsum
322 lr(ie) = 1d0/sqrt(lr2)
323 ls2 = 0d0
324 wsum = 0d0
325 do i = 1, nx
326 weight = w(i)
327 ls2 = ls2 + weight / &
328 ( (x(i, j2, 1, ie) - x(i, j1, 1, ie))**2 &
329 + (y(i, j2, 1, ie) - y(i, j1, 1, ie))**2 )
330 wsum = wsum + weight
331 end do
332 ls2 = ls2/wsum
333 ls(ie) = 1d0/sqrt(ls2)
334 end if
335 end do
336 ie = 1014
337 end subroutine plane_space
338
340 subroutine fdm_setup_fast(this, ah, bh, nl, n)
341 integer, intent(in) :: nl, n
342 type(fdm_t), intent(inout) :: this
343 real(kind=rp), intent(inout) :: ah(n+1, n+1), bh(n+1)
344 real(kind=rp), dimension(2*this%Xh%lx + 4) :: lr, ls, lt
345 integer :: i, j, k
346 integer :: ie, il, nr, ns, nt
347 integer :: lbr, rbr, lbs, rbs, lbt, rbt
348 real(kind=rp) :: eps, diag
349
350 associate(s => this%s, d => this%d, &
351 llr => this%len_lr, lls => this%len_ls, llt => this%len_lt, &
352 lmr => this%len_mr, lms => this%len_ms, lmt => this%len_mt, &
353 lrr => this%len_rr, lrs => this%len_rs, lrt => this%len_rt)
354 do ie = 1, this%dof%msh%nelv
355 lbr = this%dof%msh%facet_type(1, ie)
356 rbr = this%dof%msh%facet_type(2, ie)
357 lbs = this%dof%msh%facet_type(3, ie)
358 rbs = this%dof%msh%facet_type(4, ie)
359 lbt = this%dof%msh%facet_type(5, ie)
360 rbt = this%dof%msh%facet_type(6, ie)
361
362 nr = nl
363 ns = nl
364 nt = nl
365 call fdm_setup_fast1d(s(1, 1, 1, ie), lr, nr, lbr, rbr, &
366 llr(ie), lmr(ie), lrr(ie), ah, bh, n)
367 call fdm_setup_fast1d(s(1, 1, 2, ie), ls, ns, lbs, rbs, &
368 lls(ie), lms(ie), lrs(ie), ah, bh, n)
369 if (this%dof%msh%gdim .eq. 3) then
370 call fdm_setup_fast1d(s(1, 1, 3, ie), lt, nt, lbt, rbt, &
371 llt(ie), lmt(ie), lrt(ie), ah, bh, n)
372 end if
373
374 il = 1
375 if (.not. this%dof%msh%gdim .eq. 3) then
376 eps = 1d-5 * (vlmax(lr(2), nr - 2) + vlmax(ls(2), ns - 2))
377 do j = 1, ns
378 do i = 1, nr
379 diag = lr(i) + ls(j)
380 if (diag .gt. eps) then
381 d(il, ie) = 1.0_rp / diag
382 else
383 d(il, ie) = 0.0_rp
384 end if
385 il = il + 1
386 end do
387 end do
388 else
389 eps = 1d-5 * (vlmax(lr(2), nr - 2) + &
390 vlmax(ls(2), ns - 2) + vlmax(lt(2), nt - 2))
391 do k = 1, nt
392 do j = 1, ns
393 do i = 1, nr
394 diag = lr(i) + ls(j) + lt(k)
395 if (diag .gt. eps) then
396 d(il, ie) = 1.0_rp / diag
397 else
398 d(il, ie) = 0.0_rp
399 end if
400 il = il + 1
401 end do
402 end do
403 end do
404 end if
405 end do
406 end associate
407
408 end subroutine fdm_setup_fast
409
410 subroutine fdm_setup_fast1d(s, lam, nl, lbc, rbc, ll, lm, lr, ah, bh, n)
411 integer, intent(in) :: nl, lbc, rbc, n
412 real(kind=rp), intent(inout) :: s(nl, nl, 2), lam(nl), ll, lm, lr
413 real(kind=rp), intent(inout) :: ah(0:n, 0:n), bh(0:n)
414 integer :: lx1, lxm
415 real(kind=rp) :: b(2*(n+3)**2)
416
417 lx1 = n + 1
418 lxm = lx1 + 2
419
420 call fdm_setup_fast1d_a(s, lbc, rbc, ll, lm, lr, ah, n)
421 call fdm_setup_fast1d_b(b, lbc, rbc, ll, lm, lr, bh, n)
422 call generalev(s, b, lam, nl, lx1)
423 if (lbc .gt. 0) call row_zero(s, nl, nl, 1)
424 if (lbc .eq. 1) call row_zero(s, nl, nl, 2)
425 if (rbc .gt. 0) call row_zero(s, nl, nl, nl)
426 if (rbc .eq. 1) call row_zero(s, nl, nl, nl-1)
427
428 call trsp(s(1, 1, 2), nl, s, nl)
429
430 end subroutine fdm_setup_fast1d
431
435 subroutine generalev(a, b, lam, n, lx)
436 integer, intent(in) :: n, lx
437 real(kind=rp), intent(inout) :: a(n, n), b(n, n), lam(n)
438 integer :: lbw, lw
439 real(kind=rp) :: bw(4*(lx+2)**3)
440
441 lbw = 4*(lx+2)**3
442 lw = n*n
443 call sygv(a, b, lam, n, lx, bw, lbw)
444
445 end subroutine generalev
446
447 subroutine sp_sygv(a, b, lam, n, lx, bw, lbw)
448 integer, intent(in) :: n, lx, lbw
449 real(kind=sp), intent(inout) :: a(n, n), b(n, n), lam(n)
450 real(kind=sp) :: bw(4*(lx+2)**3)
451 integer :: info = 0
452 call ssygv(1, 'V', 'U', n, a, n, b, n, lam, bw, lbw, info)
453 end subroutine sp_sygv
454
455 subroutine dp_sygv(a, b, lam, n, lx, bw, lbw)
456 integer, intent(in) :: n, lx, lbw
457 real(kind=dp), intent(inout) :: a(n, n), b(n, n), lam(n)
458 real(kind=dp) :: bw(4*(lx+2)**3)
459 integer :: info = 0
460 call dsygv(1, 'V', 'U', n, a, n, b, n, lam, bw, lbw, info)
461 end subroutine dp_sygv
462
463#ifdef HAVE_REAL128
464 subroutine qp_sygv(a, b, lam, n, lx, bw, lbw)
465 integer, intent(in) :: n, lx, lbw
466 real(kind=qp), intent(inout) :: a(n, n), b(n, n), lam(n)
467 real(kind=dp) :: a2(n, n), b2(n, n), lam2(n)
468 real(kind=qp) :: bw(4*(lx+2)**3)
469 real(kind=dp) :: bw2(4*(lx+2)**3)
470 integer :: info = 0
471
472 a2 = real(a, dp)
473 b2 = real(b, dp)
474 lam2 = real(lam, dp)
475 call dsygv(1, 'V', 'U', n, a2, n, b2, n, lam2, bw2, lbw, info)
476 a = real(a2, qp)
477 b = real(b2, qp)
478 lam = real(lam2, qp)
479 if (pe_rank .eq. 0) then
480 call neko_warning('Real precision choice not supported for fdm, ' // &
481 'treating it as double')
482 end if
483
484 end subroutine qp_sygv
485#endif
486
487 subroutine fdm_setup_fast1d_a(a, lbc, rbc, ll, lm, lr, ah, n)
488 integer, intent(in) ::lbc, rbc, n
489 real(kind=rp), intent(inout) :: a(0:n+2, 0:n+2), ll, lm, lr
490 real(kind=rp), intent(inout) :: ah(0:n, 0:n)
491 real(kind=rp) :: fac
492 integer :: i, j, i0, i1
493
494 i0 = 0
495 if (lbc .eq. 1) i0 = 1
496 i1 = n
497 if (rbc .eq. 1) i1 = n - 1
498
499 call rzero(a, (n+3) * (n+3))
500
501 fac = 2.0_rp / lm
502 a(1, 1) = 1.0_rp
503 a(n+1, n+1) = 1.0_rp
504
505 do j = i0, i1
506 do i = i0, i1
507 a(i+1, j+1) = fac * ah(i, j)
508 end do
509 end do
510
511 if (lbc .eq. 0) then
512 fac = 2.0_rp / ll
513 a(0, 0) = fac * ah(n-1, n-1)
514 a(1, 0) = fac * ah(n, n-1)
515 a(0, 1) = fac * ah(n-1, n)
516 a(1, 1) = a(1, 1) + fac * ah(n, n)
517 else
518 a(0, 0) = 1.0_rp
519 end if
520
521 if (rbc .eq. 0) then
522 fac = 2.0_rp / lr
523 a(n+1, n+1) = a(n+1, n+1) + fac * ah(0, 0)
524 a(n+2, n+1) = fac * ah(1, 0)
525 a(n+1, n+2) = fac * ah(0, 1)
526 a(n+2, n+2) = fac * ah(1, 1)
527 else
528 a(n+2, n+2) = 1.0_rp
529 end if
530
531 end subroutine fdm_setup_fast1d_a
532
533 subroutine fdm_setup_fast1d_b(b, lbc, rbc, ll, lm, lr, bh, n)
534 integer, intent(in) :: lbc, rbc, n
535 real(kind=rp), intent(inout) :: b(0:n+2, 0:n+2), ll, lm, lr
536 real(kind=rp), intent(inout) :: bh(0:n)
537 real(kind=rp) :: fac
538 integer :: i, i0, i1
539
540 i0 = 0
541 if (lbc .eq. 1) i0 = 1
542 i1 = n
543 if (rbc .eq. 1) i1 = n - 1
544
545 call rzero(b, (n + 3) * (n + 3))
546
547 fac = 0.5_rp * lm
548 b(1, 1) = 1.0_rp
549 b(n+1, n+1) = 1.0_rp
550
551 do i = i0, i1
552 b(i+1, i+1) = fac * bh(i)
553 end do
554
555 if (lbc .eq. 0) then
556 fac = 0.5_rp * ll
557 b(0, 0) = fac * bh(n-1)
558 b(1, 1) = b(1, 1) + fac * bh(n)
559 else
560 b(0, 0) = 1.0_rp
561 end if
562
563 if (rbc .eq. 0) then
564 fac = 0.5_rp * lr
565 b(n+1, n+1) = b(n+1, n+1) + fac * bh(0)
566 b(n+2, n+2) = fac * bh(1)
567 else
568 b(n+2, n+2) = 1.0_rp
569 end if
570
571 end subroutine fdm_setup_fast1d_b
572
573 subroutine fdm_free(this)
574 class(fdm_t), intent(inout) :: this
575
576 if (allocated(this%s)) then
577 if (neko_bcknd_device .eq. 1) then
578 call device_unmap(this%s, this%s_d)
579 end if
580 deallocate(this%s)
581 end if
582
583 if (allocated(this%d)) then
584 if (neko_bcknd_device .eq. 1) then
585 call device_unmap(this%d, this%d_d)
586 end if
587 deallocate(this%d)
588 end if
589
590 if (allocated(this%len_lr)) then
591 deallocate(this%len_lr)
592 end if
593
594 if (allocated(this%len_ls)) then
595 deallocate(this%len_ls)
596 end if
597
598 if (allocated(this%len_lt)) then
599 deallocate(this%len_lt)
600 end if
601
602 if (allocated(this%len_mr)) then
603 deallocate(this%len_mr)
604 end if
605
606 if (allocated(this%len_ms)) then
607 deallocate(this%len_ms)
608 end if
609
610 if (allocated(this%len_mt)) then
611 deallocate(this%len_mt)
612 end if
613
614 if (allocated(this%len_rr)) then
615 deallocate(this%len_rr)
616 end if
617
618 if (allocated(this%len_rs)) then
619 deallocate(this%len_rs)
620 end if
621
622 if (allocated(this%len_rt)) then
623 deallocate(this%len_rt)
624 end if
625
626 if (allocated(this%swplen)) then
627 if (neko_bcknd_device .eq. 1) then
628 call device_unmap(this%swplen, this%swplen_d)
629 end if
630 deallocate(this%swplen)
631 end if
632
633 nullify(this%Xh)
634 nullify(this%dof)
635 nullify(this%gs_h)
636 nullify(this%msh)
637
638 end subroutine fdm_free
639
640 subroutine fdm_compute(this, e, r, stream)
641 class(fdm_t), intent(inout) :: this
642 real(kind=rp), dimension((this%Xh%lx + 2)**3, this%msh%nelv), &
643 intent(inout) :: e, r
644 type(c_ptr), optional :: stream
645 type(c_ptr) :: strm
646
647 if (present(stream)) then
648 strm = stream
649 else
650 strm = glb_cmd_queue
651 end if
652
653 if (neko_bcknd_sx .eq. 1) then
654 call fdm_do_fast_sx(e, r, this%s, this%d, &
655 this%Xh%lx+2, this%msh%gdim, this%msh%nelv)
656 else if (neko_bcknd_xsmm .eq. 1) then
657 call fdm_do_fast_xsmm(e, r, this%s, this%d, &
658 this%Xh%lx+2, this%msh%gdim, this%msh%nelv)
659 else if (neko_bcknd_device .eq. 1) then
660 call fdm_do_fast_device(e, r, this%s, this%d, &
661 this%Xh%lx+2, this%msh%gdim, this%msh%nelv, strm)
662 else
663 call fdm_do_fast_cpu(e, r, this%s, this%d, &
664 this%Xh%lx+2, this%msh%gdim, this%msh%nelv)
665 end if
666
667 end subroutine fdm_compute
668
669
670end module fdm
double real
Map a Fortran array to a device (allocate and associate)
Definition device.F90:83
Copy data between host and device (or device and device)
Definition device.F90:72
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:89
Definition comm.F90:1
integer, public pe_rank
MPI rank.
Definition comm.F90:59
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
integer, parameter, public device_to_host
Definition device.F90:48
type(c_ptr), bind(C), public glb_cmd_queue
Global command queue.
Definition device.F90:52
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Fast diagonalization methods from NEKTON.
Definition fast3d.f90:61
subroutine, public semhat(a, b, c, d, z, dgll, jgll, bgl, zgl, dgl, jgl, n, w)
Generate matrices for single element, 1D operators: a = Laplacian b = diagonal mass matrix c = convec...
Definition fast3d.f90:170
Fast Diagonalization.
Definition fdm_cpu.f90:2
subroutine, public fdm_do_fast_cpu(e, r, s, d, nl, ldim, nelv)
Definition fdm_cpu.f90:13
subroutine, public fdm_do_fast_device(e, r, s, d, nl, ldim, nelv, stream)
Fast Diagonalization SX-Aurora backend.
Definition fdm_sx.f90:34
subroutine, public fdm_do_fast_sx(e, r, s, d, nl, ldim, nelv)
Definition fdm_sx.f90:45
Fast Diagonalization libxsmm backend.
Definition fdm_xsmm.f90:2
subroutine fdm_do_fast_xsmm(e, r, s, d, nl, ldim, nelv)
Definition fdm_xsmm.f90:10
Type for the Fast Diagonalization connected with the schwarz overlapping solves.
Definition fdm.F90:61
subroutine swap_lengths(this, x, y, z, nelv, gdim)
Definition fdm.F90:165
subroutine fdm_setup_fast(this, ah, bh, nl, n)
Setup the arrays s, d needed for the fast evaluation of the system.
Definition fdm.F90:341
subroutine fdm_init(this, xh, dof, gs_h)
Definition fdm.F90:114
subroutine fdm_compute(this, e, r, stream)
Definition fdm.F90:641
subroutine fdm_free(this)
Definition fdm.F90:574
subroutine dp_sygv(a, b, lam, n, lx, bw, lbw)
Definition fdm.F90:456
subroutine generalev(a, b, lam, n, lx)
Solve the generalized eigenvalue problem /$ A x = lam B x/$ A – symm. B – symm., pos....
Definition fdm.F90:436
subroutine fdm_setup_fast1d(s, lam, nl, lbc, rbc, ll, lm, lr, ah, bh, n)
Definition fdm.F90:411
subroutine fdm_setup_fast1d_b(b, lbc, rbc, ll, lm, lr, bh, n)
Definition fdm.F90:534
subroutine plane_space(lr, ls, lt, i1, i2, w, x, y, z, nx, nxn, nz0, nzn, nelv, gdim)
Here, spacing is based on harmonic mean. pff 2/10/07 We no longer base this on the finest grid,...
Definition fdm.F90:252
subroutine fdm_setup_fast1d_a(a, lbc, rbc, ll, lm, lr, ah, n)
Definition fdm.F90:488
subroutine sp_sygv(a, b, lam, n, lx, bw, lbw)
Definition fdm.F90:448
Gather-scatter.
Definition math.F90:60
subroutine, public row_zero(a, m, n, e)
Sets row e to 0 in matrix a.
Definition math.F90:277
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.F90:249
real(kind=rp) function, public vlmax(vec, n)
maximum value of a vector of length n
Definition math.F90:789
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_sx
integer, parameter neko_bcknd_device
integer, parameter neko_bcknd_xsmm
integer, parameter, public qp
Definition num_types.f90:12
integer, parameter, public dp
Definition num_types.f90:10
integer, parameter, public sp
Definition num_types.f90:8
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines a function space.
Definition space.f90:34
Tensor operations.
Definition tensor.f90:61
subroutine, public trsp(a, lda, b, ldb)
Transpose of a rectangular tensor .
Definition tensor.f90:124
Utilities.
Definition utils.f90:35
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:454
Gather-scatter kernel.
The function space for the SEM solution fields.
Definition space.f90:64