Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
coef.f90
Go to the documentation of this file.
1! Copyright (c) 2020-2026, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
34module coefs
35 use gather_scatter, only : gs_t
36 use gs_ops, only : gs_op_add
38 use num_types, only : rp, sp, dp
39 use dofmap, only : dofmap_t
40 use space, only : space_t
41 use math, only : rone, invcol1, addcol3, subcol3, copy, &
44 use logger, only : neko_log, log_size
45 use mesh, only : mesh_t
51 use mxm_wrapper, only : mxm
56 use comm, only : neko_comm
58 use mpi_f08, only : mpi_allreduce, mpi_integer, mpi_sum
59 use, intrinsic :: iso_c_binding
60 implicit none
61 private
62
71 real(kind=rp), public, parameter :: neko_metric_cond_sp = 1.0e4_rp
72
76 integer, public, parameter :: coef_full = 0
89 integer, public, parameter :: coef_operator = 1
90
93 type, public :: coef_t
95 real(kind=rp), allocatable :: g11(:,:,:,:)
97 real(kind=rp), allocatable :: g22(:,:,:,:)
99 real(kind=rp), allocatable :: g33(:,:,:,:)
101 real(kind=rp), allocatable :: g12(:,:,:,:)
103 real(kind=rp), allocatable :: g13(:,:,:,:)
105 real(kind=rp), allocatable :: g23(:,:,:,:)
106
109 real(kind=rp) :: metric_cond = 0.0_rp
112 integer :: metric_degenerate = 0
119 logical :: metric_sp_safe = .false.
121 real(kind=rp), allocatable :: g11_compressed(:,:,:,:)
123 real(kind=rp), allocatable :: g22_compressed(:,:,:,:)
125 real(kind=rp), allocatable :: g33_compressed(:,:,:,:)
127 real(kind=rp), allocatable :: g12_compressed(:,:,:,:)
129 real(kind=rp), allocatable :: g13_compressed(:,:,:,:)
131 real(kind=rp), allocatable :: g23_compressed(:,:,:,:)
133 integer, allocatable :: compression_inds(:)
134
135 real(kind=rp), allocatable :: mult(:,:,:,:)
140 real(kind=rp), allocatable :: dxdr(:,:,:,:), dydr(:,:,:,:), dzdr(:,:,:,:)
141 real(kind=rp), allocatable :: dxds(:,:,:,:), dyds(:,:,:,:), dzds(:,:,:,:)
142 real(kind=rp), allocatable :: dxdt(:,:,:,:), dydt(:,:,:,:), dzdt(:,:,:,:)
146 real(kind=rp), allocatable :: drdx(:,:,:,:), drdy(:,:,:,:), drdz(:,:,:,:)
147 real(kind=rp), allocatable :: dsdx(:,:,:,:), dsdy(:,:,:,:), dsdz(:,:,:,:)
148 real(kind=rp), allocatable :: dtdx(:,:,:,:), dtdy(:,:,:,:), dtdz(:,:,:,:)
149
150 real(kind=rp), allocatable :: h1(:,:,:,:)
151 real(kind=rp), allocatable :: h2(:,:,:,:)
152 logical :: ifh2
153
154 real(kind=rp), allocatable :: jac(:,:,:,:)
155 real(kind=rp), allocatable :: jacinv(:,:,:,:)
156 real(kind=rp), allocatable :: b(:,:,:,:)
157 real(kind=rp), allocatable :: binv(:,:,:,:)
158 real(kind=rp), pointer :: blag(:,:,:,:) => null()
159 real(kind=rp), pointer :: blaglag(:,:,:,:) => null()
160 real(kind=rp), allocatable :: area(:,:,:,:)
161 real(kind=rp), allocatable :: nx(:,:,:,:)
162 real(kind=rp), allocatable :: ny(:,:,:,:)
163 real(kind=rp), allocatable :: nz(:,:,:,:)
164 logical :: cyclic = .false.
165 integer, allocatable :: cyc_msk(:)
166 real(kind=rp), allocatable :: r11(:)
167 real(kind=rp), allocatable :: r12(:)
168
169 !! True if geometric metrics have been initialized
170 logical, private :: coef_metrics_initialized = .false.
171
174 integer :: scope = coef_full
175
177
178 real(kind=rp) :: volume = 0.0_rp
179
180 type(space_t), pointer :: xh => null()
181 type(mesh_t), pointer :: msh => null()
182 type(dofmap_t), pointer :: dof => null()
183 type(gs_t), pointer :: gs_h=> null()
184
185 !
186 ! Device pointers (if present)
187 !
188
189 type(c_ptr) :: g11_d = c_null_ptr
190 type(c_ptr) :: g22_d = c_null_ptr
191 type(c_ptr) :: g33_d = c_null_ptr
192 type(c_ptr) :: g12_d = c_null_ptr
193 type(c_ptr) :: g13_d = c_null_ptr
194 type(c_ptr) :: g23_d = c_null_ptr
195 type(c_ptr) :: dxdr_d = c_null_ptr
196 type(c_ptr) :: dydr_d = c_null_ptr
197 type(c_ptr) :: dzdr_d = c_null_ptr
198 type(c_ptr) :: dxds_d = c_null_ptr
199 type(c_ptr) :: dyds_d = c_null_ptr
200 type(c_ptr) :: dzds_d = c_null_ptr
201 type(c_ptr) :: dxdt_d = c_null_ptr
202 type(c_ptr) :: dydt_d = c_null_ptr
203 type(c_ptr) :: dzdt_d = c_null_ptr
204 type(c_ptr) :: drdx_d = c_null_ptr
205 type(c_ptr) :: drdy_d = c_null_ptr
206 type(c_ptr) :: drdz_d = c_null_ptr
207 type(c_ptr) :: dsdx_d = c_null_ptr
208 type(c_ptr) :: dsdy_d = c_null_ptr
209 type(c_ptr) :: dsdz_d = c_null_ptr
210 type(c_ptr) :: dtdx_d = c_null_ptr
211 type(c_ptr) :: dtdy_d = c_null_ptr
212 type(c_ptr) :: dtdz_d = c_null_ptr
213 type(c_ptr) :: mult_d = c_null_ptr
214 type(c_ptr) :: h1_d = c_null_ptr
215 type(c_ptr) :: h2_d = c_null_ptr
216 type(c_ptr) :: jac_d = c_null_ptr
217 type(c_ptr) :: jacinv_d = c_null_ptr
218 type(c_ptr) :: b_d = c_null_ptr
219 type(c_ptr) :: blag_d = c_null_ptr
220 type(c_ptr) :: blaglag_d = c_null_ptr
221 type(c_ptr) :: binv_d = c_null_ptr
222 type(c_ptr) :: area_d = c_null_ptr
223 type(c_ptr) :: nx_d = c_null_ptr
224 type(c_ptr) :: ny_d = c_null_ptr
225 type(c_ptr) :: nz_d = c_null_ptr
226 type(c_ptr) :: cyc_msk_d = c_null_ptr
227 type(c_ptr) :: r11_d = c_null_ptr
228 type(c_ptr) :: r12_d = c_null_ptr
229
231 integer :: metrics_version = 0
232
233 contains
234 procedure, private, pass(this) :: init_empty => coef_init_empty
235 procedure, private, pass(this) :: init_all => coef_init_all
236 procedure, pass(this) :: free => coef_free
237 procedure, pass(this) :: get_normal => coef_get_normal
238 procedure, pass(this) :: get_area => coef_get_area
239 procedure, pass(this) :: require_facets => coef_require_facets
240 procedure, pass(this) :: generate_cyclic_bc => coef_generate_cyclic_bc
241 procedure, pass(this) :: recompute_metrics => coef_recompute_metrics
242 procedure, pass(this) :: metric_condition => coef_metric_condition
243 procedure, pass(this) :: enable_b_history => coef_enable_lagged_mass
244 procedure, pass(this) :: update_b_history => coef_update_lagged_mass
245 generic :: init => init_empty, init_all
246 end type coef_t
247
248contains
249
251 subroutine coef_init_empty(this, Xh, msh)
252 class(coef_t), intent(inout) :: this
253 type(space_t), intent(inout), target :: Xh
254 type(mesh_t), intent(inout), target :: msh
255 integer :: n
256 call this%free()
257 this%msh => msh
258 this%Xh => xh
259
260 allocate(this%drdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
261 allocate(this%dsdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
262 allocate(this%dtdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
263
264 allocate(this%drdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
265 allocate(this%dsdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
266 allocate(this%dtdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
267
268 allocate(this%drdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
269 allocate(this%dsdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
270 allocate(this%dtdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
271
272
273 !
274 ! Setup device memory (if present)
275 !
276
277 n = this%Xh%lx * this%Xh%ly * this%Xh%lz * this%msh%nelv
278 if (neko_bcknd_device .eq. 1) then
279
280 call device_map(this%drdx, this%drdx_d, n)
281 call device_map(this%drdy, this%drdy_d, n)
282 call device_map(this%drdz, this%drdz_d, n)
283
284 call device_map(this%dsdx, this%dsdx_d, n)
285 call device_map(this%dsdy, this%dsdy_d, n)
286 call device_map(this%dsdz, this%dsdz_d, n)
287
288 call device_map(this%dtdx, this%dtdx_d, n)
289 call device_map(this%dtdy, this%dtdy_d, n)
290 call device_map(this%dtdz, this%dtdz_d, n)
291
292 end if
293
294 end subroutine coef_init_empty
295
300 subroutine coef_init_all(this, gs_h, scope)
301 class(coef_t), intent(inout), target :: this
302 type(gs_t), intent(inout), target :: gs_h
303 integer, intent(in), optional :: scope
304 integer :: n, m, ncyc
305
306 call this%free()
307
308 ! After free(), so that it survives into the initialized state
309 if (present(scope)) then
310 if (scope .ne. coef_full .and. scope .ne. coef_operator) then
311 call neko_error('Unknown coefficient scope')
312 end if
313 this%scope = scope
314 end if
315
316 call neko_log%section('Coefficients')
317
318 this%msh => gs_h%dofmap%msh
319 this%Xh => gs_h%dofmap%Xh
320 this%dof => gs_h%dofmap
321 this%gs_h => gs_h
322
323 !
324 ! Allocate arrays for geometric data
325 !
327 allocate(this%G11(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
328 allocate(this%G22(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
329 allocate(this%G33(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
330 allocate(this%G12(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
331 allocate(this%G13(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
332 allocate(this%G23(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
333
334 allocate(this%dxdr(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
335 allocate(this%dxds(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
336 allocate(this%dxdt(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
337
338 allocate(this%dydr(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
339 allocate(this%dyds(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
340 allocate(this%dydt(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
341
342 allocate(this%dzdr(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
343 allocate(this%dzds(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
344 allocate(this%dzdt(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
345
346 allocate(this%drdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
347 allocate(this%dsdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
348 allocate(this%dtdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
349
350 allocate(this%drdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
351 allocate(this%dsdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
352 allocate(this%dtdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
353
354 allocate(this%drdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
355 allocate(this%dsdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
356 allocate(this%dtdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
357
358 allocate(this%jac(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
359 allocate(this%jacinv(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
360
361 if (this%scope .eq. coef_full) then
362 allocate(this%area(this%Xh%lx, this%Xh%ly, 6, this%msh%nelv))
363 allocate(this%nx(this%Xh%lx, this%Xh%ly, 6, this%msh%nelv))
364 allocate(this%ny(this%Xh%lx, this%Xh%ly, 6, this%msh%nelv))
365 allocate(this%nz(this%Xh%lx, this%Xh%ly, 6, this%msh%nelv))
366 end if
367
368 allocate(this%B(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
369 allocate(this%Binv(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
370
371 ! We do this so in a static simulation we don't allocate extra memory
372 this%Blag => this%B
373 this%Blaglag => this%B
374
375 allocate(this%h1(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
376 allocate(this%h2(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
377
378 allocate(this%mult(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
379
380
381 !
382 ! Setup device memory (if present)
383 !
384
385 n = this%Xh%lx * this%Xh%ly * this%Xh%lz * this%msh%nelv
386 if (neko_bcknd_device .eq. 1) then
387 call device_map(this%G11, this%G11_d, n)
388 call device_map(this%G22, this%G22_d, n)
389 call device_map(this%G33, this%G33_d, n)
390 call device_map(this%G12, this%G12_d, n)
391 call device_map(this%G13, this%G13_d, n)
392 call device_map(this%G23, this%G23_d, n)
393
394 call device_map(this%dxdr, this%dxdr_d, n)
395 call device_map(this%dydr, this%dydr_d, n)
396 call device_map(this%dzdr, this%dzdr_d, n)
397
398 call device_map(this%dxds, this%dxds_d, n)
399 call device_map(this%dyds, this%dyds_d, n)
400 call device_map(this%dzds, this%dzds_d, n)
401
402 call device_map(this%dxdt, this%dxdt_d, n)
403 call device_map(this%dydt, this%dydt_d, n)
404 call device_map(this%dzdt, this%dzdt_d, n)
405
406 call device_map(this%drdx, this%drdx_d, n)
407 call device_map(this%drdy, this%drdy_d, n)
408 call device_map(this%drdz, this%drdz_d, n)
409
410 call device_map(this%dsdx, this%dsdx_d, n)
411 call device_map(this%dsdy, this%dsdy_d, n)
412 call device_map(this%dsdz, this%dsdz_d, n)
413
414 call device_map(this%dtdx, this%dtdx_d, n)
415 call device_map(this%dtdy, this%dtdy_d, n)
416 call device_map(this%dtdz, this%dtdz_d, n)
417
418 call device_map(this%mult, this%mult_d, n)
419 call device_map(this%h1, this%h1_d, n)
420 call device_map(this%h2, this%h2_d, n)
421
422 call device_map(this%jac, this%jac_d, n)
423 call device_map(this%jacinv, this%jacinv_d, n)
424 call device_map(this%B, this%B_d, n)
425 call device_map(this%Binv, this%Binv_d, n)
426
427 this%Blag_d = this%B_d
428 this%Blaglag_d = this%B_d
429
430 if (this%scope .eq. coef_full) then
431 m = this%Xh%lx * this%Xh%ly * 6 * this%msh%nelv
432
433 call device_map(this%area, this%area_d, m)
434 call device_map(this%nx, this%nx_d, m)
435 call device_map(this%ny, this%ny_d, m)
436 call device_map(this%nz, this%nz_d, m)
437 end if
438
439 end if
440
441 call coef_generate_dxyzdrst(this)
442
443 call coef_generate_geo(this)
444
445 ! call coef_generate_geo_compressed(this)
446
447 ! Both are dead weight under COEF_OPERATOR: nothing reads the facet
448 ! metrics, and the condition estimate is a per-point eigenvalue solve
449 ! plus two reductions spent on a diagnostic no one consumes.
450 if (this%scope .eq. coef_full) then
451 call coef_metric_condition(this)
452
454 end if
455
456 call coef_generate_mass(this)
457
458 this%coef_metrics_initialized = .true.
459
460
461 ! This is a placeholder, just for now
462 ! We can probably find a prettier solution
463 if (neko_bcknd_device .eq. 1) then
464 call device_rone(this%h1_d, n)
465 call device_rone(this%h2_d, n)
466 call device_memcpy(this%h1, this%h1_d, n, &
467 device_to_host, sync = .false.)
468 call device_memcpy(this%h2, this%h2_d, n, &
469 device_to_host, sync = .false.)
470 else
471 call rone(this%h1,n)
472 call rone(this%h2,n)
473 end if
474
475 this%ifh2 = .false.
476
477 !
478 ! Set up multiplicity
479 !
480 if (neko_bcknd_device .eq. 1) then
481 call device_rone(this%mult_d, n)
482 else
483 call rone(this%mult, n)
484 end if
485
486 call gs_h%op(this%mult, n, gs_op_add)
487
488 if (neko_bcknd_device .eq. 1) then
489 call device_invcol1(this%mult_d, n)
490 call device_memcpy(this%mult, this%mult_d, n, &
491 device_to_host, sync = .true.)
492 else
493 call invcol1(this%mult, n)
494 end if
495
496 ncyc = this%msh%periodic%size * this%Xh%lx * this%Xh%lx
497 allocate(this%cyc_msk(0:ncyc))
498 this%cyc_msk(0) = ncyc + 1
499 if (ncyc .gt. 0) then
500 allocate(this%R11(ncyc))
501 allocate(this%R12(ncyc))
502
504 call rone(this%R11, ncyc)
505 call rzero(this%R12, ncyc)
506
507 if (neko_bcknd_device .eq. 1) then
508 call device_map(this%cyc_msk, this%cyc_msk_d, ncyc+1)
509 call device_map(this%R11, this%R11_d, ncyc)
510 call device_map(this%R12, this%R12_d, ncyc)
511
512 call device_memcpy(this%cyc_msk, this%cyc_msk_d, ncyc+1, &
513 host_to_device, sync = .false.)
514 call device_memcpy(this%R11, this%R11_d, ncyc, &
515 host_to_device, sync = .false.)
516 call device_memcpy(this%R12, this%R12_d, ncyc, &
517 host_to_device, sync = .false.)
518 end if
519
520 end if
521
522 call coef_release_scratch(this)
523
524 call neko_log%end_section()
525
526 end subroutine coef_init_all
527
529 subroutine coef_free(this)
530 class(coef_t), intent(inout), target :: this
531
532 if (allocated(this%G11)) then
533 if (neko_bcknd_device .eq. 1) call device_unmap(this%G11, this%G11_d)
534 deallocate(this%G11)
535 end if
536
537 if (allocated(this%G22)) then
538 if (neko_bcknd_device .eq. 1) call device_unmap(this%G22, this%G22_d)
539 deallocate(this%G22)
540 end if
541
542 if (allocated(this%G33)) then
543 if (neko_bcknd_device .eq. 1) call device_unmap(this%G33, this%G33_d)
544 deallocate(this%G33)
545 end if
546
547 if (allocated(this%G12)) then
548 if (neko_bcknd_device .eq. 1) call device_unmap(this%G12, this%G12_d)
549 deallocate(this%G12)
550 end if
551
552 if (allocated(this%G13)) then
553 if (neko_bcknd_device .eq. 1) call device_unmap(this%G13, this%G13_d)
554 deallocate(this%G13)
555 end if
556
557 if (allocated(this%G23)) then
558 if (neko_bcknd_device .eq. 1) call device_unmap(this%G23, this%G23_d)
559 deallocate(this%G23)
560 end if
561
562 if (allocated(this%G11_compressed)) then
563 deallocate(this%G11_compressed)
564 end if
565
566 if (allocated(this%compression_inds)) then
567 deallocate(this%compression_inds)
568 end if
569
570 if (allocated(this%G22_compressed)) then
571 deallocate(this%G22_compressed)
572 end if
573
574 if (allocated(this%G33_compressed)) then
575 deallocate(this%G33_compressed)
576 end if
577
578 if (allocated(this%G12_compressed)) then
579 deallocate(this%G12_compressed)
580 end if
581
582 if (allocated(this%G13_compressed)) then
583 deallocate(this%G13_compressed)
584 end if
585
586 if (allocated(this%G23_compressed)) then
587 deallocate(this%G23_compressed)
588 end if
589
590 if (allocated(this%mult)) then
591 if (neko_bcknd_device .eq. 1) call device_unmap(this%mult, this%mult_d)
592 deallocate(this%mult)
593 end if
594
595 if (associated(this%Blag) .and. &
596 .not. associated(this%Blag, this%B)) then
597 if (c_associated(this%Blag_d) .and. &
598 .not. c_associated(this%Blag_d, this%B_d)) then
599 call device_unmap(this%Blag, this%Blag_d)
600 end if
601 deallocate(this%Blag)
602 end if
603 nullify(this%Blag)
604
605 if (associated(this%Blaglag) .and. &
606 .not. associated(this%Blaglag, this%B)) then
607 if (c_associated(this%Blaglag_d) .and. &
608 .not. c_associated(this%Blaglag_d, this%B_d)) then
609 call device_unmap(this%Blaglag, this%Blaglag_d)
610 end if
611 deallocate(this%Blaglag)
612 end if
613 nullify(this%Blaglag)
614
615 if (c_associated(this%Blag_d) .and. &
616 .not. c_associated(this%Blag_d, this%B_d)) then
617 this%Blag_d = c_null_ptr
618 end if
619 this%Blag_d = c_null_ptr
620
621 if (c_associated(this%Blaglag_d) .and. &
622 .not. c_associated(this%Blaglag_d, this%B_d)) then
623 this%Blaglag_d = c_null_ptr
624 end if
625 this%Blaglag_d = c_null_ptr
626
627 if (allocated(this%B)) then
628 if (neko_bcknd_device .eq. 1) call device_unmap(this%B, this%B_d)
629 deallocate(this%B)
630 end if
631
632 if (allocated(this%Binv)) then
633 if (neko_bcknd_device .eq. 1) call device_unmap(this%Binv, this%Binv_d)
634 deallocate(this%Binv)
635 end if
636
637 if (allocated(this%dxdr)) then
638 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxdr, this%dxdr_d)
639 deallocate(this%dxdr)
640 end if
641
642 if (allocated(this%dxds)) then
643 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxds, this%dxds_d)
644 deallocate(this%dxds)
645 end if
646
647 if (allocated(this%dxdt)) then
648 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxdt, this%dxdt_d)
649 deallocate(this%dxdt)
650 end if
651
652 if (allocated(this%dydr)) then
653 if (neko_bcknd_device .eq. 1) call device_unmap(this%dydr, this%dydr_d)
654 deallocate(this%dydr)
655 end if
656
657 if (allocated(this%dyds)) then
658 if (neko_bcknd_device .eq. 1) call device_unmap(this%dyds, this%dyds_d)
659 deallocate(this%dyds)
660 end if
661
662 if (allocated(this%dydt)) then
663 if (neko_bcknd_device .eq. 1) call device_unmap(this%dydt, this%dydt_d)
664 deallocate(this%dydt)
665 end if
666
667 if (allocated(this%dzdr)) then
668 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzdr, this%dzdr_d)
669 deallocate(this%dzdr)
670 end if
671
672 if (allocated(this%dzds)) then
673 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzds, this%dzds_d)
674 deallocate(this%dzds)
675 end if
676
677 if (allocated(this%dzdt)) then
678 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzdt, this%dzdt_d)
679 deallocate(this%dzdt)
680 end if
681
682 if (allocated(this%drdx)) then
683 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdx, this%drdx_d)
684 deallocate(this%drdx)
685 end if
686
687 if (allocated(this%dsdx)) then
688 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdx, this%dsdx_d)
689 deallocate(this%dsdx)
690 end if
691
692 if (allocated(this%dtdx)) then
693 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdx, this%dtdx_d)
694 deallocate(this%dtdx)
695 end if
696
697 if (allocated(this%drdy)) then
698 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdy, this%drdy_d)
699 deallocate(this%drdy)
700 end if
701
702 if (allocated(this%dsdy)) then
703 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdy, this%dsdy_d)
704 deallocate(this%dsdy)
705 end if
706
707 if (allocated(this%dtdy)) then
708 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdy, this%dtdy_d)
709 deallocate(this%dtdy)
710 end if
711
712 if (allocated(this%drdz)) then
713 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdz, this%drdz_d)
714 deallocate(this%drdz)
715 end if
716
717 if (allocated(this%dsdz)) then
718 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdz, this%dsdz_d)
719 deallocate(this%dsdz)
720 end if
721
722 if (allocated(this%dtdz)) then
723 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdz, this%dtdz_d)
724 deallocate(this%dtdz)
725 end if
726
727 if (allocated(this%jac)) then
728 if (neko_bcknd_device .eq. 1) call device_unmap(this%jac, this%jac_d)
729 deallocate(this%jac)
730 end if
731
732 if (allocated(this%jacinv)) then
733 if (neko_bcknd_device .eq. 1) then
734 call device_unmap(this%jacinv, this%jacinv_d)
735 end if
736 deallocate(this%jacinv)
737 end if
738
739 if (allocated(this%h1)) then
740 if (neko_bcknd_device .eq. 1) call device_unmap(this%h1, this%h1_d)
741 deallocate(this%h1)
742 end if
743
744 if (allocated(this%h2)) then
745 if (neko_bcknd_device .eq. 1) call device_unmap(this%h2, this%h2_d)
746 deallocate(this%h2)
747 end if
748
749 if (allocated(this%area)) then
750 if (neko_bcknd_device .eq. 1) call device_unmap(this%area, this%area_d)
751 deallocate(this%area)
752 end if
753
754 if (allocated(this%nx)) then
755 if (neko_bcknd_device .eq. 1) call device_unmap(this%nx, this%nx_d)
756 deallocate(this%nx)
757 end if
758
759 if (allocated(this%ny)) then
760 if (neko_bcknd_device .eq. 1) call device_unmap(this%ny, this%ny_d)
761 deallocate(this%ny)
762 end if
763
764 if (allocated(this%nz)) then
765 if (neko_bcknd_device .eq. 1) call device_unmap(this%nz, this%nz_d)
766 deallocate(this%nz)
767 end if
768
769 if (allocated(this%cyc_msk)) then
770 if (neko_bcknd_device .eq. 1) then
771 call device_unmap(this%cyc_msk, this%cyc_msk_d)
772 end if
773 deallocate(this%cyc_msk)
774 end if
775
776 if (allocated(this%R11)) then
777 if (neko_bcknd_device .eq. 1) call device_unmap(this%R11, this%R11_d)
778 deallocate(this%R11)
779 end if
780
781 if (allocated(this%R12)) then
782 if (neko_bcknd_device .eq. 1) call device_unmap(this%R12, this%R12_d)
783 deallocate(this%R12)
784 end if
785
786
787 nullify(this%msh)
788 nullify(this%Xh)
789 nullify(this%dof)
790 nullify(this%gs_h)
791
792 this%coef_metrics_initialized = .false.
793 this%scope = coef_full
794
795 end subroutine coef_free
796
807 subroutine coef_release_scratch(this)
808 class(coef_t), intent(inout), target :: this
809
810 if (this%scope .eq. coef_full) return
811
812 if (allocated(this%dxdr)) then
813 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxdr, this%dxdr_d)
814 deallocate(this%dxdr)
815 end if
816
817 if (allocated(this%dxds)) then
818 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxds, this%dxds_d)
819 deallocate(this%dxds)
820 end if
821
822 if (allocated(this%dxdt)) then
823 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxdt, this%dxdt_d)
824 deallocate(this%dxdt)
825 end if
826
827 if (allocated(this%dydr)) then
828 if (neko_bcknd_device .eq. 1) call device_unmap(this%dydr, this%dydr_d)
829 deallocate(this%dydr)
830 end if
831
832 if (allocated(this%dyds)) then
833 if (neko_bcknd_device .eq. 1) call device_unmap(this%dyds, this%dyds_d)
834 deallocate(this%dyds)
835 end if
836
837 if (allocated(this%dydt)) then
838 if (neko_bcknd_device .eq. 1) call device_unmap(this%dydt, this%dydt_d)
839 deallocate(this%dydt)
840 end if
841
842 if (allocated(this%dzdr)) then
843 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzdr, this%dzdr_d)
844 deallocate(this%dzdr)
845 end if
846
847 if (allocated(this%dzds)) then
848 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzds, this%dzds_d)
849 deallocate(this%dzds)
850 end if
851
852 if (allocated(this%dzdt)) then
853 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzdt, this%dzdt_d)
854 deallocate(this%dzdt)
855 end if
856
857 if (allocated(this%drdx)) then
858 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdx, this%drdx_d)
859 deallocate(this%drdx)
860 end if
861
862 if (allocated(this%drdy)) then
863 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdy, this%drdy_d)
864 deallocate(this%drdy)
865 end if
866
867 if (allocated(this%drdz)) then
868 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdz, this%drdz_d)
869 deallocate(this%drdz)
870 end if
871
872 if (allocated(this%dsdx)) then
873 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdx, this%dsdx_d)
874 deallocate(this%dsdx)
875 end if
876
877 if (allocated(this%dsdy)) then
878 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdy, this%dsdy_d)
879 deallocate(this%dsdy)
880 end if
881
882 if (allocated(this%dsdz)) then
883 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdz, this%dsdz_d)
884 deallocate(this%dsdz)
885 end if
886
887 if (allocated(this%dtdx)) then
888 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdx, this%dtdx_d)
889 deallocate(this%dtdx)
890 end if
891
892 if (allocated(this%dtdy)) then
893 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdy, this%dtdy_d)
894 deallocate(this%dtdy)
895 end if
896
897 if (allocated(this%dtdz)) then
898 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdz, this%dtdz_d)
899 deallocate(this%dtdz)
900 end if
901
902 if (allocated(this%jac)) then
903 if (neko_bcknd_device .eq. 1) call device_unmap(this%jac, this%jac_d)
904 deallocate(this%jac)
905 end if
906
907 if (allocated(this%jacinv)) then
908 if (neko_bcknd_device .eq. 1) then
909 call device_unmap(this%jacinv, this%jacinv_d)
910 end if
911 deallocate(this%jacinv)
912 end if
913
914 if (allocated(this%Binv)) then
915 if (neko_bcknd_device .eq. 1) call device_unmap(this%Binv, this%Binv_d)
916 deallocate(this%Binv)
917 end if
918
919 if (allocated(this%area)) then
920 if (neko_bcknd_device .eq. 1) call device_unmap(this%area, this%area_d)
921 deallocate(this%area)
922 end if
923
924 if (allocated(this%nx)) then
925 if (neko_bcknd_device .eq. 1) call device_unmap(this%nx, this%nx_d)
926 deallocate(this%nx)
927 end if
928
929 if (allocated(this%ny)) then
930 if (neko_bcknd_device .eq. 1) call device_unmap(this%ny, this%ny_d)
931 deallocate(this%ny)
932 end if
933
934 if (allocated(this%nz)) then
935 if (neko_bcknd_device .eq. 1) call device_unmap(this%nz, this%nz_d)
936 deallocate(this%nz)
937 end if
938
939 end subroutine coef_release_scratch
940
942 type(coef_t), intent(inout) :: c
943 integer :: e, i, lxy, lyz, ntot
944
945 lxy = c%Xh%lx*c%Xh%ly
946 lyz = c%Xh%ly*c%Xh%lz
947 ntot = c%dof%size()
948
949 associate(drdx => c%drdx, drdy => c%drdy, drdz => c%drdz, &
950 dsdx => c%dsdx, dsdy => c%dsdy, dsdz => c%dsdz, &
951 dtdx => c%dtdx, dtdy => c%dtdy, dtdz => c%dtdz, &
952 dxdr => c%dxdr, dydr => c%dydr, dzdr => c%dzdr, &
953 dxds => c%dxds, dyds => c%dyds, dzds => c%dzds, &
954 dxdt => c%dxdt, dydt => c%dydt, dzdt => c%dzdt, &
955 dx => c%Xh%dx, dy => c%Xh%dy, dz => c%Xh%dz, &
956 x => c%dof%x, y => c%dof%y, z => c%dof%z, &
957 lx => c%Xh%lx, ly => c%Xh%ly, lz => c%Xh%lz, &
958 dyt => c%Xh%dyt, dzt => c%Xh%dzt, &
959 jacinv => c%jacinv, jac => c%jac)
960
961 if (neko_bcknd_device .eq. 1) then
962
963 call device_coef_generate_dxydrst(c%drdx_d, c%drdy_d, c%drdz_d, &
964 c%dsdx_d, c%dsdy_d, c%dsdz_d, c%dtdx_d, c%dtdy_d, c%dtdz_d, &
965 c%dxdr_d, c%dydr_d, c%dzdr_d, c%dxds_d, c%dyds_d, c%dzds_d, &
966 c%dxdt_d, c%dydt_d, c%dzdt_d, c%Xh%dx_d, c%Xh%dy_d, c%Xh%dz_d, &
967 c%dof%x_d, c%dof%y_d, c%dof%z_d, c%jacinv_d, c%jac_d, &
968 c%Xh%lx, c%msh%nelv)
969
970 ! copy to host only at initialization.
971 if (.not. c%coef_metrics_initialized) then
972 call device_memcpy(dxdr, c%dxdr_d, ntot, device_to_host, &
973 sync = .false.)
974 call device_memcpy(dydr, c%dydr_d, ntot, device_to_host, &
975 sync = .false.)
976 call device_memcpy(dzdr, c%dzdr_d, ntot, device_to_host, &
977 sync = .false.)
978 call device_memcpy(dxds, c%dxds_d, ntot, device_to_host, &
979 sync = .false.)
980 call device_memcpy(dyds, c%dyds_d, ntot, device_to_host, &
981 sync = .false.)
982 call device_memcpy(dzds, c%dzds_d, ntot, device_to_host, &
983 sync = .false.)
984 call device_memcpy(dxdt, c%dxdt_d, ntot, device_to_host, &
985 sync = .false.)
986 call device_memcpy(dydt, c%dydt_d, ntot, device_to_host, &
987 sync = .false.)
988 call device_memcpy(dzdt, c%dzdt_d, ntot, device_to_host, &
989 sync = .false.)
990 call device_memcpy(drdx, c%drdx_d, ntot, device_to_host, &
991 sync = .false.)
992 call device_memcpy(drdy, c%drdy_d, ntot, device_to_host, &
993 sync = .false.)
994 call device_memcpy(drdz, c%drdz_d, ntot, device_to_host, &
995 sync = .false.)
996 call device_memcpy(dsdx, c%dsdx_d, ntot, device_to_host, &
997 sync = .false.)
998 call device_memcpy(dsdy, c%dsdy_d, ntot, device_to_host, &
999 sync = .false.)
1000 call device_memcpy(dsdz, c%dsdz_d, ntot, device_to_host, &
1001 sync = .false.)
1002 call device_memcpy(dtdx, c%dtdx_d, ntot, device_to_host, &
1003 sync = .false.)
1004 call device_memcpy(dtdy, c%dtdy_d, ntot, device_to_host, &
1005 sync = .false.)
1006 call device_memcpy(dtdz, c%dtdz_d, ntot, device_to_host, &
1007 sync = .false.)
1008 call device_memcpy(jac, c%jac_d, ntot, device_to_host, &
1009 sync = .false.)
1010 call device_memcpy(jacinv, c%jacinv_d, ntot, device_to_host, &
1011 sync = .true.)
1012 end if
1013
1014 else
1015 !$omp parallel do private(i)
1016 do e = 1, c%msh%nelv
1017 call mxm(dx, lx, x(1,1,1,e), lx, dxdr(1,1,1,e), lyz)
1018 call mxm(dx, lx, y(1,1,1,e), lx, dydr(1,1,1,e), lyz)
1019 call mxm(dx, lx, z(1,1,1,e), lx, dzdr(1,1,1,e), lyz)
1020
1021 do i = 1, lz
1022 call mxm(x(1,1,i,e), lx, dyt, ly, dxds(1,1,i,e), ly)
1023 call mxm(y(1,1,i,e), lx, dyt, ly, dyds(1,1,i,e), ly)
1024 call mxm(z(1,1,i,e), lx, dyt, ly, dzds(1,1,i,e), ly)
1025 end do
1026
1027 ! We actually take 2d into account, wow, need to do that for the rest.
1028 if (c%msh%gdim .eq. 3) then
1029 call mxm(x(1,1,1,e), lxy, dzt, lz, dxdt(1,1,1,e), lz)
1030 call mxm(y(1,1,1,e), lxy, dzt, lz, dydt(1,1,1,e), lz)
1031 call mxm(z(1,1,1,e), lxy, dzt, lz, dzdt(1,1,1,e), lz)
1032 else
1033 call rzero(dxdt(1,1,1,e), lxy)
1034 call rzero(dydt(1,1,1,e), lxy)
1035 call rone(dzdt(1,1,1,e), lxy)
1036 end if
1037 end do
1038 !$omp end parallel do
1039
1040 if (c%msh%gdim .eq. 2) then
1041 call rzero (jac, ntot)
1042 call addcol3 (jac, dxdr, dyds, ntot)
1043 call subcol3 (jac, dxds, dydr, ntot)
1044 call copy (drdx, dyds, ntot)
1045 call copy (drdy, dxds, ntot)
1046 call chsign (drdy, ntot)
1047 call copy (dsdx, dydr, ntot)
1048 call chsign (dsdx, ntot)
1049 call copy (dsdy, dxdr, ntot)
1050 call rzero (drdz, ntot)
1051 call rzero (dsdz, ntot)
1052 call rone (dtdz, ntot)
1053 else
1054 !$omp parallel private(i)
1055 !$omp do simd
1056 do i = 1, ntot
1057 c%jac(i, 1, 1, 1) = 0.0_rp
1058 end do
1059 !$omp end do simd
1060 !$omp do simd
1061 do i = 1, ntot
1062 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) + ( c%dxdr(i, 1, 1, 1) &
1063 * c%dyds(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1) )
1064
1065 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) + ( c%dxdt(i, 1, 1, 1) &
1066 * c%dydr(i, 1, 1, 1) * c%dzds(i, 1, 1, 1) )
1067
1068 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) + ( c%dxds(i, 1, 1, 1) &
1069 * c%dydt(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1) )
1070 end do
1071 !$omp end do simd
1072 !$omp do simd
1073 do i = 1, ntot
1074 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) - ( c%dxdr(i, 1, 1, 1) &
1075 * c%dydt(i, 1, 1, 1) * c%dzds(i, 1, 1, 1) )
1076
1077 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) - ( c%dxds(i, 1, 1, 1) &
1078 * c%dydr(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1) )
1079
1080 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) - ( c%dxdt(i, 1, 1, 1) &
1081 * c%dyds(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1) )
1082 end do
1083 !$omp end do simd
1084 !$omp do simd
1085 do i = 1, ntot
1086 c%drdx(i, 1, 1, 1) = c%dyds(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1) &
1087 - c%dydt(i, 1, 1, 1) * c%dzds(i, 1, 1, 1)
1088
1089 c%drdy(i, 1, 1, 1) = c%dxdt(i, 1, 1, 1) * c%dzds(i, 1, 1, 1) &
1090 - c%dxds(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1)
1091
1092 c%drdz(i, 1, 1, 1) = c%dxds(i, 1, 1, 1) * c%dydt(i, 1, 1, 1) &
1093 - c%dxdt(i, 1, 1, 1) * c%dyds(i, 1, 1, 1)
1094 end do
1095 !$omp end do simd
1096 !$omp do simd
1097 do i = 1, ntot
1098 c%dsdx(i, 1, 1, 1) = c%dydt(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1) &
1099 - c%dydr(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1)
1100
1101 c%dsdy(i, 1, 1, 1) = c%dxdr(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1) &
1102 - c%dxdt(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1)
1103
1104 c%dsdz(i, 1, 1, 1) = c%dxdt(i, 1, 1, 1) * c%dydr(i, 1, 1, 1) &
1105 - c%dxdr(i, 1, 1, 1) * c%dydt(i, 1, 1, 1)
1106 end do
1107 !$omp end do simd
1108 !$omp do simd
1109 do i = 1, ntot
1110 c%dtdx(i, 1, 1, 1) = c%dydr(i, 1, 1, 1) * c%dzds(i, 1, 1, 1) &
1111 - c%dyds(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1)
1112
1113 c%dtdy(i, 1, 1, 1) = c%dxds(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1) &
1114 - c%dxdr(i, 1, 1, 1) * c%dzds(i, 1, 1, 1)
1115
1116 c%dtdz(i, 1, 1, 1) = c%dxdr(i, 1, 1, 1) * c%dyds(i, 1, 1, 1) &
1117 - c%dxds(i, 1, 1, 1) * c%dydr(i, 1, 1, 1)
1118 end do
1119 !$omp end do simd
1120 !$omp end parallel
1121 end if
1122 call invers2(jacinv, jac, ntot)
1123 end if
1124 end associate
1125
1126 end subroutine coef_generate_dxyzdrst
1127
1130 subroutine coef_generate_geo(c)
1131 type(coef_t), intent(inout) :: c
1132 integer :: e, i, lxyz, ntot
1133
1134 lxyz = c%Xh%lx * c%Xh%ly * c%Xh%lz
1135 ntot = c%dof%size()
1136
1137 if (neko_bcknd_device .eq. 1) then
1138
1139 call device_coef_generate_geo(c%G11_d, c%G12_d, c%G13_d, &
1140 c%G22_d, c%G23_d, c%G33_d, &
1141 c%drdx_d, c%drdy_d, c%drdz_d, &
1142 c%dsdx_d, c%dsdy_d, c%dsdz_d, &
1143 c%dtdx_d, c%dtdy_d, c%dtdz_d, &
1144 c%jacinv_d, c%Xh%w3_d, c%msh%nelv, &
1145 c%Xh%lx, c%msh%gdim)
1146
1147 ! copy to host only at initialization.
1148 if (.not. c%coef_metrics_initialized) then
1149 call device_memcpy(c%G11, c%G11_d, ntot, device_to_host, &
1150 sync = .false.)
1151 call device_memcpy(c%G22, c%G22_d, ntot, device_to_host, &
1152 sync = .false.)
1153 call device_memcpy(c%G33, c%G33_d, ntot, device_to_host, &
1154 sync = .false.)
1155 call device_memcpy(c%G12, c%G12_d, ntot, device_to_host, &
1156 sync = .false.)
1157 call device_memcpy(c%G13, c%G13_d, ntot, device_to_host, &
1158 sync = .false.)
1159 call device_memcpy(c%G23, c%G23_d, ntot, device_to_host, &
1160 sync = .true.)
1161 end if
1162
1163 else
1164 if (c%msh%gdim .eq. 2) then
1165
1166 do i = 1, ntot
1167 c%G11(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%drdx(i, 1, 1, 1) &
1168 + c%drdy(i, 1, 1, 1) * c%drdy(i, 1, 1, 1)
1169
1170 c%G22(i, 1, 1, 1) = c%dsdx(i, 1, 1, 1) * c%dsdx(i, 1, 1, 1) &
1171 + c%dsdy(i, 1, 1, 1) * c%dsdy(i, 1, 1, 1)
1172
1173 c%G12(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%dsdx(i, 1, 1, 1) &
1174 + c%drdy(i, 1, 1, 1) * c%dsdy(i, 1, 1, 1)
1175 end do
1176
1177 do i = 1, ntot
1178 c%G11(i, 1, 1, 1) = c%G11(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1179 c%G22(i, 1, 1, 1) = c%G22(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1180 c%G12(i, 1, 1, 1) = c%G12(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1181 c%G33(i, 1, 1, 1) = 0.0_rp
1182 c%G13(i, 1, 1, 1) = 0.0_rp
1183 c%G23(i, 1, 1, 1) = 0.0_rp
1184 end do
1185
1186 do concurrent(e = 1:c%msh%nelv)
1187 do concurrent(i = 1:lxyz)
1188 c%G11(i,1,1,e) = c%G11(i,1,1,e) * c%Xh%w3(i,1,1)
1189 c%G22(i,1,1,e) = c%G22(i,1,1,e) * c%Xh%w3(i,1,1)
1190 c%G12(i,1,1,e) = c%G12(i,1,1,e) * c%Xh%w3(i,1,1)
1191 end do
1192 end do
1193
1194 else
1195 !$omp parallel private(i)
1196 !$omp do
1197 do i = 1, ntot
1198 c%G11(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%drdx(i, 1, 1, 1) &
1199 + c%drdy(i, 1, 1, 1) * c%drdy(i, 1, 1, 1) &
1200 + c%drdz(i, 1, 1, 1) * c%drdz(i, 1, 1, 1)
1201
1202 c%G22(i, 1, 1, 1) = c%dsdx(i, 1, 1, 1) * c%dsdx(i, 1, 1, 1) &
1203 + c%dsdy(i, 1, 1, 1) * c%dsdy(i, 1, 1, 1) &
1204 + c%dsdz(i, 1, 1, 1) * c%dsdz(i, 1, 1, 1)
1205
1206 c%G33(i, 1, 1, 1) = c%dtdx(i, 1, 1, 1) * c%dtdx(i, 1, 1, 1) &
1207 + c%dtdy(i, 1, 1, 1) * c%dtdy(i, 1, 1, 1) &
1208 + c%dtdz(i, 1, 1, 1) * c%dtdz(i, 1, 1, 1)
1209 end do
1210 !$omp end do
1211 !$omp do
1212 do i = 1, ntot
1213 c%G11(i, 1, 1, 1) = c%G11(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1214 c%G22(i, 1, 1, 1) = c%G22(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1215 c%G33(i, 1, 1, 1) = c%G33(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1216 end do
1217 !$omp end do
1218 !$omp do
1219 do i = 1, ntot
1220 c%G12(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%dsdx(i, 1, 1, 1) &
1221 + c%drdy(i, 1, 1, 1) * c%dsdy(i, 1, 1, 1) &
1222 + c%drdz(i, 1, 1, 1) * c%dsdz(i, 1, 1, 1)
1223
1224 c%G13(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%dtdx(i, 1, 1, 1) &
1225 + c%drdy(i, 1, 1, 1) * c%dtdy(i, 1, 1, 1) &
1226 + c%drdz(i, 1, 1, 1) * c%dtdz(i, 1, 1, 1)
1227
1228 c%G23(i, 1, 1, 1) = c%dsdx(i, 1, 1, 1) * c%dtdx(i, 1, 1, 1) &
1229 + c%dsdy(i, 1, 1, 1) * c%dtdy(i, 1, 1, 1) &
1230 + c%dsdz(i, 1, 1, 1) * c%dtdz(i, 1, 1, 1)
1231 end do
1232 !$omp end do
1233 !$omp do
1234 do i = 1, ntot
1235 c%G12(i, 1, 1, 1) = c%G12(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1236 c%G13(i, 1, 1, 1) = c%G13(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1237 c%G23(i, 1, 1, 1) = c%G23(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1238 end do
1239 !$omp end do
1240 !$omp do
1241 do e = 1, c%msh%nelv
1242 do concurrent(i = 1:lxyz)
1243 c%G11(i,1,1,e) = c%G11(i,1,1,e) * c%Xh%w3(i,1,1)
1244 c%G22(i,1,1,e) = c%G22(i,1,1,e) * c%Xh%w3(i,1,1)
1245 c%G12(i,1,1,e) = c%G12(i,1,1,e) * c%Xh%w3(i,1,1)
1246
1247 c%G33(i,1,1,e) = c%G33(i,1,1,e) * c%Xh%w3(i,1,1)
1248 c%G13(i,1,1,e) = c%G13(i,1,1,e) * c%Xh%w3(i,1,1)
1249 c%G23(i,1,1,e) = c%G23(i,1,1,e) * c%Xh%w3(i,1,1)
1250 end do
1251 end do
1252 !$omp end do
1253 !$omp end parallel
1254 end if
1255 end if
1256
1257 end subroutine coef_generate_geo
1258
1288 subroutine coef_metric_condition(this)
1289 class(coef_t), intent(inout) :: this
1290 real(kind=dp) :: e1, e2, e3, scal
1291 real(kind=rp) :: kmax, tmp(1)
1292 integer :: i, j, k, e, n, ndeg, ndeg_glb, ierr
1293 character(len=LOG_SIZE) :: log_buf
1294
1295 n = this%dof%size()
1296
1297 ! Post-initialization the host copy is stale on device builds
1298 if (neko_bcknd_device .eq. 1 .and. this%coef_metrics_initialized) then
1299 call device_memcpy(this%G11, this%G11_d, n, device_to_host, &
1300 sync = .false.)
1301 call device_memcpy(this%G22, this%G22_d, n, device_to_host, &
1302 sync = .false.)
1303 call device_memcpy(this%G33, this%G33_d, n, device_to_host, &
1304 sync = .false.)
1305 call device_memcpy(this%G12, this%G12_d, n, device_to_host, &
1306 sync = .false.)
1307 call device_memcpy(this%G13, this%G13_d, n, device_to_host, &
1308 sync = .false.)
1309 call device_memcpy(this%G23, this%G23_d, n, device_to_host, &
1310 sync = .true.)
1311 end if
1312
1313 kmax = 0.0_rp
1314 ndeg = 0
1315
1316 do e = 1, this%msh%nelv
1317 do k = 1, this%Xh%lz
1318 do j = 1, this%Xh%ly
1319 do i = 1, this%Xh%lx
1320
1321 ! Scale out the magnitude before the eigenvalue solve; the
1322 ! condition number is invariant under it and w3*J spans a
1323 ! wide range within an element
1324 scal = max(abs(real(this%G11(i,j,k,e), dp)), &
1325 abs(real(this%G22(i,j,k,e), dp)))
1326 scal = max(scal, abs(real(this%G33(i,j,k,e), dp)))
1327 scal = max(scal, abs(real(this%G12(i,j,k,e), dp)))
1328 scal = max(scal, abs(real(this%G13(i,j,k,e), dp)))
1329 scal = max(scal, abs(real(this%G23(i,j,k,e), dp)))
1330
1331 if (scal .le. 0.0_dp) then
1332 ndeg = ndeg + 1
1333 cycle
1334 end if
1335
1336 if (this%msh%gdim .eq. 2) then
1337 call eig_sym2(real(this%G11(i,j,k,e), dp) / scal, &
1338 real(this%G22(i,j,k,e), dp) / scal, &
1339 real(this%G12(i,j,k,e), dp) / scal, e1, e3)
1340 else
1341 call eig_sym3(real(this%G11(i,j,k,e), dp) / scal, &
1342 real(this%G22(i,j,k,e), dp) / scal, &
1343 real(this%G33(i,j,k,e), dp) / scal, &
1344 real(this%G12(i,j,k,e), dp) / scal, &
1345 real(this%G13(i,j,k,e), dp) / scal, &
1346 real(this%G23(i,j,k,e), dp) / scal, e1, e2, e3)
1347 end if
1348
1349 if (e3 .le. 0.0_dp) then
1350 ndeg = ndeg + 1
1351 else
1352 kmax = max(kmax, real(e1 / e3, rp))
1353 end if
1354
1355 end do
1356 end do
1357 end do
1358 end do
1359
1360 tmp(1) = kmax
1361 this%metric_cond = glmax(tmp, 1)
1362
1363 call mpi_allreduce(ndeg, ndeg_glb, 1, mpi_integer, mpi_sum, &
1364 neko_comm, ierr)
1365 this%metric_degenerate = ndeg_glb
1366
1367 this%metric_sp_safe = (this%metric_degenerate .eq. 0) .and. &
1368 (this%metric_cond .le. neko_metric_cond_sp)
1369
1370 write(log_buf, '(A,ES12.5)') 'Metric condition : ', this%metric_cond
1371 call neko_log%message(log_buf)
1372
1373 ! G_ij is stored in rp, so the limit only bites on a single precision
1374 ! build. Reported rather than fatal: the threshold keeps three
1375 ! orders of margin below 1/eps_sp, so crossing it makes the loss of
1376 ! positive definiteness possible, not certain, and the run may well be
1377 ! fine. On a double precision build there is nothing at risk yet, and a
1378 ! warning on every wall resolved mesh would be pure noise.
1379 if (rp .eq. sp .and. this%metric_cond .gt. neko_metric_cond_sp) then
1380 write(log_buf, '(A,ES12.5)') &
1381 'Metric too ill conditioned for single precision, limit ', &
1383 call neko_log%warning(log_buf)
1384 call neko_log%message('Geometric factors may lose positive ' // &
1385 'definiteness, consider a double precision build')
1386 end if
1387
1388 ! A metric that is not positive definite is a degenerate or inverted
1389 ! element, which is a mesh problem in any precision. Reported rather than
1390 ! fatal, since this is a diagnostic and the rest of the setup may still
1391 ! want to run
1392 if (this%metric_degenerate .gt. 0) then
1393 write(log_buf, '(A,I0)') &
1394 'Non positive definite metric at points: ', this%metric_degenerate
1395 call neko_log%error(log_buf)
1396 end if
1397
1398 end subroutine coef_metric_condition
1399
1403 type(coef_t), intent(inout) :: c
1404 integer :: e, m, i, lxyz, m_max
1405 integer, allocatable :: c_inds_rev(:) ! reverse compression indices map
1406 real(kind=rp) :: ctol = 1.0e-7_rp
1407 real(kind=rp) :: diff = 0.0_rp
1408
1409 ! First step, allocate full-size lookup structure for entire mesh
1410 allocate(c%compression_inds(c%msh%nelv))
1411 allocate(c_inds_rev(c%msh%nelv))
1412
1413 ! Second step, loop over all elements, compute compression mapping
1414 ! First entry must be itself to get started
1415 m_max = 1
1416 c%compression_inds(1) = 1
1417 c_inds_rev = 0
1418 c_inds_rev(1) = 1
1419
1420 ! Loop over elements, but skip first
1421 lxyz = c%Xh%lx * c%Xh%ly * c%Xh%lz
1422 do e = 2, c%msh%nelv
1423 ! Loop over possible compression candidates
1424 do m = 1, m_max
1425 diff = 0.0_rp
1426 ! Loop over quadrature points
1427 do i = 1, lxyz
1428 ! diff += abs( \| G(i,:,:,e) - G(i,:,:,reverse(m)) \|_l1 )
1429 diff = diff + abs(c%G11(i,1,1,e) - c%G11(i,1,1,c_inds_rev(m))) &
1430 + 2.0*abs(c%G12(i,1,1,e) - c%G12(i,1,1,c_inds_rev(m))) &
1431 + 2.0*abs(c%G13(i,1,1,e) - c%G13(i,1,1,c_inds_rev(m))) &
1432 + abs(c%G22(i,1,1,e) - c%G22(i,1,1,c_inds_rev(m))) &
1433 + 2.0*abs(c%G23(i,1,1,e) - c%G23(i,1,1,c_inds_rev(m))) &
1434 + abs(c%G33(i,1,1,e) - c%G33(i,1,1,c_inds_rev(m)))
1435 end do
1436
1437 ! match is found; mapping(e) is redundant
1438 if ( diff .le. ctol ) then
1439 c%compression_inds(e) = m
1440 exit
1441 end if
1442 end do
1443
1444 ! never found a match
1445 if ( diff .gt. ctol ) then
1446 m_max = m_max + 1
1447 c%compression_inds(e) = m_max
1448 c_inds_rev(m_max) = e
1449 end if
1450 end do
1451
1452 write(*,*)
1453 write(*,*) '------Mapping Compression-----'
1454 write(*,*) 'Compressed from ', c%msh%nelv, ' to ', m_max
1455
1456 ! Third step, allocate and fill Gij_compressed objects
1457 allocate(c%G11_compressed(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1458 allocate(c%G22_compressed(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1459 allocate(c%G33_compressed(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1460 allocate(c%G12_compressed(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1461 allocate(c%G13_compressed(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1462 allocate(c%G23_compressed(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1463 do m = 1, m_max
1464 do i = 1, lxyz
1465 c%G11_compressed(i,1,1,m) = c%G11(i,1,1,c_inds_rev(m))
1466 c%G22_compressed(i,1,1,m) = c%G22(i,1,1,c_inds_rev(m))
1467 c%G33_compressed(i,1,1,m) = c%G33(i,1,1,c_inds_rev(m))
1468 c%G12_compressed(i,1,1,m) = c%G12(i,1,1,c_inds_rev(m))
1469 c%G13_compressed(i,1,1,m) = c%G13(i,1,1,c_inds_rev(m))
1470 c%G23_compressed(i,1,1,m) = c%G23(i,1,1,c_inds_rev(m))
1471 end do
1472 end do
1473
1474 deallocate(c_inds_rev)
1475
1476 end subroutine coef_generate_geo_compressed
1477
1481 type(coef_t), intent(inout) :: c
1482 integer :: e, i, lxyz, ntot
1483
1484 lxyz = c%Xh%lx * c%Xh%ly * c%Xh%lz
1485 ntot = c%dof%size()
1486
1487 if (neko_bcknd_device .eq. 1) then
1488 call device_coef_generate_mass(c%B_d, c%Binv_d, c%jac_d, c%Xh%w3_d, &
1489 lxyz, c%msh%nelv)
1490 ! copy to host only at initialization.
1491 if (.not. c%coef_metrics_initialized) then
1492 ! Under COEF_OPERATOR the Binv transfer below is skipped, so this
1493 ! becomes the last one of the routine and has to synchronise.
1494 call device_memcpy(c%B, c%B_d, ntot, device_to_host, &
1495 sync = (c%scope .eq. coef_operator))
1496 end if
1497 else
1498 !$omp parallel do private(e, i)
1499 do e = 1, c%msh%nelv
1500 ! Here we need to handle things differently for axis symmetric elements
1501 do i = 1, lxyz
1502 c%B(i,1,1,e) = c%jac(i,1,1,e) * c%Xh%w3(i,1,1)
1503 c%Binv(i,1,1,e) = c%B(i,1,1,e)
1504 end do
1505 end do
1506 !$omp end parallel do
1507 end if
1508
1509 ! Neither Binv nor the volume is read when only applying an operator,
1510 ! and assembling Binv costs a gather-scatter round on top of that.
1511 if (c%scope .ne. coef_full) return
1512
1513 call c%gs_h%op(c%Binv, ntot, gs_op_add)
1514
1515 if (neko_bcknd_device .eq. 1) then
1516 call device_invcol1(c%Binv_d, ntot)
1517 ! copy to host only at initialization.
1518 if (.not. c%coef_metrics_initialized) then
1519 call device_memcpy(c%Binv, c%Binv_d, ntot, &
1520 device_to_host, sync = .true.)
1521 end if
1522 else
1523 call invcol1(c%Binv, ntot)
1524 end if
1525
1527 if (neko_bcknd_device .eq. 1) then
1528 c%volume = device_glsum(c%B_d, ntot)
1529 else
1530 c%volume = glsum(c%B, ntot)
1531 end if
1532
1533 end subroutine coef_generate_mass
1534
1544 subroutine coef_require_facets(this, who)
1545 class(coef_t), intent(in) :: this
1546 character(len=*), intent(in) :: who
1547
1548 if (this%scope .ne. coef_full) then
1549 call neko_error(who // ' needs the facet areas and normals, which ' // &
1550 'a COEF_OPERATOR coef does not build')
1551 end if
1552
1553 end subroutine coef_require_facets
1554
1559 pure function coef_get_normal(this, i, j, k, e, facet) result(normal)
1560 class(coef_t), intent(in) :: this
1561 integer, intent(in) :: i, j, k, e, facet
1562 real(kind=rp) :: normal(3)
1563
1564 select case (facet)
1565 case (1, 2)
1566 normal(1) = this%nx(j, k, facet, e)
1567 normal(2) = this%ny(j, k, facet, e)
1568 normal(3) = this%nz(j, k, facet, e)
1569 case (3, 4)
1570 normal(1) = this%nx(i, k, facet, e)
1571 normal(2) = this%ny(i, k, facet, e)
1572 normal(3) = this%nz(i, k, facet, e)
1573 case (5, 6)
1574 normal(1) = this%nx(i, j, facet, e)
1575 normal(2) = this%ny(i, j, facet, e)
1576 normal(3) = this%nz(i, j, facet, e)
1577 end select
1578 end function coef_get_normal
1579
1583 pure function coef_get_area(this, i, j, k, e, facet) result(area)
1584 class(coef_t), intent(in) :: this
1585 integer, intent(in) :: i, j, k, e, facet
1586 real(kind=rp) :: area
1587
1588 select case (facet)
1589 case (1, 2)
1590 area = this%area(j, k, facet, e)
1591 case (3, 4)
1592 area = this%area(i, k, facet, e)
1593 case (5, 6)
1594 area = this%area(i, j, facet, e)
1595 end select
1596 end function coef_get_area
1597
1598
1601 type(coef_t), intent(inout) :: coef
1602 real(kind=rp), allocatable :: a(:,:,:,:)
1603 real(kind=rp), allocatable :: b(:,:,:,:)
1604 real(kind=rp), allocatable :: c(:,:,:,:)
1605 real(kind=rp), allocatable :: dot(:,:,:,:)
1606 integer :: n, m, e, i, j, k, lx
1607 real(kind=rp) :: weight, len
1608 n = coef%dof%size()
1609 lx = coef%Xh%lx
1610
1611 if (neko_bcknd_device .eq. 1) then
1612
1613 call device_coef_generate_area_and_normal( &
1614 coef%area_d, coef%nx_d, coef%ny_d, coef%nz_d, &
1615 coef%dxdr_d, coef%dydr_d, coef%dzdr_d, &
1616 coef%dxds_d, coef%dyds_d, coef%dzds_d, &
1617 coef%dxdt_d, coef%dydt_d, coef%dzdt_d, &
1618 coef%Xh%wx_d, coef%Xh%wy_d, coef%Xh%wz_d, &
1619 lx, coef%msh%nelv, neko_eps)
1620
1621 ! Here, we always copy back to host.
1622 m = size(coef%area)
1623 call device_memcpy(coef%area, coef%area_d, m, &
1624 device_to_host, sync = .false.)
1625 call device_memcpy(coef%nx, coef%nx_d, m, &
1626 device_to_host, sync = .false.)
1627 call device_memcpy(coef%ny, coef%ny_d, m, &
1628 device_to_host, sync = .false.)
1629 call device_memcpy(coef%nz, coef%nz_d, &
1630 m, device_to_host, sync = .true.)
1631
1632 else
1633
1634 allocate(a(coef%Xh%lx, coef%Xh%lx, coef%Xh%lx, coef%msh%nelv))
1635 allocate(b(coef%Xh%lx, coef%Xh%lx, coef%Xh%lx, coef%msh%nelv))
1636 allocate(c(coef%Xh%lx, coef%Xh%lx, coef%Xh%lx, coef%msh%nelv))
1637 allocate(dot(coef%Xh%lx, coef%Xh%lx, coef%Xh%lx, coef%msh%nelv))
1638
1639 !$omp parallel private (e, i, j, k, weight, len)
1640
1641 ! ds x dt
1642 !$omp do simd
1643 do i = 1, n
1644 a(i, 1, 1, 1) = coef%dyds(i, 1, 1, 1) * coef%dzdt(i, 1, 1, 1) &
1645 - coef%dzds(i, 1, 1, 1) * coef%dydt(i, 1, 1, 1)
1646
1647 b(i, 1, 1, 1) = coef%dzds(i, 1, 1, 1) * coef%dxdt(i, 1, 1, 1) &
1648 - coef%dxds(i, 1, 1, 1) * coef%dzdt(i, 1, 1, 1)
1649
1650 c(i, 1, 1, 1) = coef%dxds(i, 1, 1, 1) * coef%dydt(i, 1, 1, 1) &
1651 - coef%dyds(i, 1, 1, 1) * coef%dxdt(i, 1, 1, 1)
1652 end do
1653 !$omp end do simd
1654 !$omp do simd
1655 do i = 1, n
1656 dot(i, 1, 1, 1) = a(i, 1, 1, 1) * a(i, 1, 1, 1) &
1657 + b(i, 1, 1, 1) * b(i, 1, 1, 1) &
1658 + c(i, 1, 1, 1) * c(i, 1, 1, 1)
1659 end do
1660 !$omp end do simd
1661 !$omp do
1662 do e = 1, coef%msh%nelv
1663 do concurrent(k = 1:coef%Xh%lx)
1664 do concurrent(j = 1:coef%Xh%lx)
1665 weight = coef%Xh%wy(j) * coef%Xh%wz(k)
1666 coef%area(j, k, 2, e) = sqrt(dot(lx, j, k, e)) * weight
1667 coef%area(j, k, 1, e) = sqrt(dot(1, j, k, e)) * weight
1668 coef%nx(j,k, 1, e) = -a(1, j, k, e)
1669 coef%nx(j,k, 2, e) = a(lx, j, k, e)
1670 coef%ny(j,k, 1, e) = -b(1, j, k, e)
1671 coef%ny(j,k, 2, e) = b(lx, j, k, e)
1672 coef%nz(j,k, 1, e) = -c(1, j, k, e)
1673 coef%nz(j,k, 2, e) = c(lx, j, k, e)
1674 end do
1675 end do
1676 end do
1677 !$omp end do
1678
1679 ! dr x dt
1680 !$omp do simd
1681 do i = 1, n
1682 a(i, 1, 1, 1) = coef%dydr(i, 1, 1, 1) * coef%dzdt(i, 1, 1, 1) &
1683 - coef%dzdr(i, 1, 1, 1) * coef%dydt(i, 1, 1, 1)
1684
1685 b(i, 1, 1, 1) = coef%dzdr(i, 1, 1, 1) * coef%dxdt(i, 1, 1, 1) &
1686 - coef%dxdr(i, 1, 1, 1) * coef%dzdt(i, 1, 1, 1)
1687
1688 c(i, 1, 1, 1) = coef%dxdr(i, 1, 1, 1) * coef%dydt(i, 1, 1, 1) &
1689 - coef%dydr(i, 1, 1, 1) * coef%dxdt(i, 1, 1, 1)
1690 end do
1691 !$omp end do simd
1692 !$omp do simd
1693 do i = 1, n
1694 dot(i, 1, 1, 1) = a(i, 1, 1, 1) * a(i, 1, 1, 1) &
1695 + b(i, 1, 1, 1) * b(i, 1, 1, 1) &
1696 + c(i, 1, 1, 1) * c(i, 1, 1, 1)
1697 end do
1698 !$omp end do simd
1699 !$omp do
1700 do e = 1, coef%msh%nelv
1701 do concurrent(k = 1:coef%Xh%lx)
1702 do concurrent(j = 1:coef%Xh%lx)
1703 weight = coef%Xh%wx(j) * coef%Xh%wz(k)
1704 coef%area(j, k, 3, e) = sqrt(dot(j, 1, k, e)) * weight
1705 coef%area(j, k, 4, e) = sqrt(dot(j, lx, k, e)) * weight
1706 coef%nx(j,k, 3, e) = a(j, 1, k, e)
1707 coef%nx(j,k, 4, e) = -a(j, lx, k, e)
1708 coef%ny(j,k, 3, e) = b(j, 1, k, e)
1709 coef%ny(j,k, 4, e) = -b(j, lx, k, e)
1710 coef%nz(j,k, 3, e) = c(j, 1, k, e)
1711 coef%nz(j,k, 4, e) = -c(j, lx, k, e)
1712 end do
1713 end do
1714 end do
1715 !$omp end do
1716 ! dr x ds
1717 !$omp do simd
1718 do i = 1, n
1719 a(i, 1, 1, 1) = coef%dydr(i, 1, 1, 1) * coef%dzds(i, 1, 1, 1) &
1720 - coef%dzdr(i, 1, 1, 1) * coef%dyds(i, 1, 1, 1)
1721
1722 b(i, 1, 1, 1) = coef%dzdr(i, 1, 1, 1) * coef%dxds(i, 1, 1, 1) &
1723 - coef%dxdr(i, 1, 1, 1) * coef%dzds(i, 1, 1, 1)
1724
1725 c(i, 1, 1, 1) = coef%dxdr(i, 1, 1, 1) * coef%dyds(i, 1, 1, 1) &
1726 - coef%dydr(i, 1, 1, 1) * coef%dxds(i, 1, 1, 1)
1727 end do
1728 !$omp end do simd
1729 !$omp do simd
1730 do i = 1, n
1731 dot(i, 1, 1, 1) = a(i, 1, 1, 1) * a(i, 1, 1, 1) &
1732 + b(i, 1, 1, 1) * b(i, 1, 1, 1) &
1733 + c(i, 1, 1, 1) * c(i, 1, 1, 1)
1734 end do
1735 !$omp end do simd
1736 !$omp do
1737 do e = 1, coef%msh%nelv
1738 do concurrent(k = 1:coef%Xh%lx)
1739 do concurrent(j = 1:coef%Xh%lx)
1740 weight = coef%Xh%wx(j) * coef%Xh%wy(k)
1741 coef%area(j, k, 5, e) = sqrt(dot(j, k, 1, e)) * weight
1742 coef%area(j, k, 6, e) = sqrt(dot(j, k, lx, e)) * weight
1743 coef%nx(j,k, 5, e) = -a(j, k, 1, e)
1744 coef%nx(j,k, 6, e) = a(j, k, lx, e)
1745 coef%ny(j,k, 5, e) = -b(j, k, 1, e)
1746 coef%ny(j,k, 6, e) = b(j, k, lx, e)
1747 coef%nz(j,k, 5, e) = -c(j, k, 1, e)
1748 coef%nz(j,k, 6, e) = c(j, k, lx, e)
1749 end do
1750 end do
1751 end do
1752 !$omp end do
1753 ! Normalize
1754 !$omp do
1755 do j = 1, size(coef%nz)
1756 len = sqrt(coef%nx(j,1,1,1)**2 + &
1757 coef%ny(j,1,1,1)**2 + coef%nz(j,1,1,1)**2)
1758 if (len .gt. neko_eps) then
1759 coef%nx(j,1,1,1) = coef%nx(j,1,1,1) / len
1760 coef%ny(j,1,1,1) = coef%ny(j,1,1,1) / len
1761 coef%nz(j,1,1,1) = coef%nz(j,1,1,1) / len
1762 end if
1763 end do
1764 !$omp end do
1765 !$omp end parallel
1766
1767 deallocate(dot)
1768 deallocate(c)
1769 deallocate(b)
1770 deallocate(a)
1771
1772 end if
1773
1774 end subroutine coef_generate_area_and_normal
1775
1777 class(coef_t), intent(inout) :: this
1778 real(kind=rp) :: un(3), len, d
1779 integer :: lx, ly, lz, np, np_glb, ierr
1780 integer :: i, j, k, pf, pe, n, nc, ncyc
1781
1782 if (.not. this%cyclic) return
1783
1784 ! Builds the rotation matrices from get_normal()
1785 if (this%scope .ne. coef_full) then
1786 call neko_error('Cyclic boundaries need the facet normals, ' // &
1787 'which COEF_OPERATOR does not build')
1788 end if
1789
1790 np = this%msh%periodic%size
1791 call mpi_allreduce(np, np_glb, 1, &
1792 mpi_integer, mpi_sum, neko_comm, ierr)
1793
1794 if (np_glb .eq. 0) then
1795 call neko_error("There are no periodic boundaries. " // &
1796 "Switch cyclic off in the case file.")
1797 end if
1798
1799 if (np .eq. 0) return
1800
1801 lx = this%Xh%lx
1802 ly = this%Xh%ly
1803 lz = this%Xh%lz
1804 ncyc = this%cyc_msk(0) - 1
1805 nc = 1
1806 do n = 1, np
1807 pf = this%msh%periodic%facet_el(n)%x(1)
1808 pe = this%msh%periodic%facet_el(n)%x(2)
1809 do k = 1, lz
1810 do j = 1, ly
1811 do i = 1, lx
1812 if (index_is_on_facet(i, j, k, lx, ly, lz, pf)) then
1813 un = this%get_normal(i, j, k, pe, pf)
1814 len = sqrt(un(1) * un(1) + un(2) * un(2))
1815 if (len .gt. neko_eps) then
1816 d = this%dof%y(i, j, k, pe) * un(1) &
1817 - this%dof%x(i, j, k, pe) * un(2)
1818
1819 this%cyc_msk(nc) = linear_index(i, j, k, pe, lx, ly, lz)
1820 this%R11(nc) = un(1) / len * sign(1.0_rp, d)
1821 this%R12(nc) = un(2) / len * sign(1.0_rp, d)
1822 nc = nc + 1
1823 else
1824 call neko_error("x and y components of surface " // &
1825 "normals are zero. Cyclic rotations must be " // &
1826 "around z-axis.")
1827 end if
1828 end if
1829 end do
1830 end do
1831 end do
1832 end do
1833
1834 if (nc - 1 /= ncyc) then
1835 call neko_error("The number of cyclic GLL points were " // &
1836 "not estimated correctly.")
1837 end if
1838
1839 if (neko_bcknd_device .eq. 1) then
1840 call device_memcpy(this%cyc_msk, this%cyc_msk_d, ncyc+1, &
1841 host_to_device, sync = .false.)
1842 call device_memcpy(this%R11, this%R11_d, ncyc, &
1843 host_to_device, sync = .false.)
1844 call device_memcpy(this%R12, this%R12_d, ncyc, &
1845 host_to_device, sync = .false.)
1846 end if
1847
1848 end subroutine coef_generate_cyclic_bc
1849
1850
1852 subroutine coef_recompute_metrics(this)
1853 class(coef_t), intent(inout) :: this
1854
1855 if (this%scope .ne. coef_full) then
1856 call neko_error('Rebuilding the geometry needs the derivative ' // &
1857 'arrays, which COEF_OPERATOR releases')
1858 end if
1859
1860 call coef_generate_dxyzdrst(this)
1861 call coef_generate_geo(this)
1863 call coef_generate_mass(this)
1864 if (this%cyclic) then
1865 call coef_generate_cyclic_bc(this)
1866 end if
1867 this%metrics_version = this%metrics_version + 1
1868 end subroutine coef_recompute_metrics
1869
1870
1874 class(coef_t), intent(inout), target :: this
1875 integer :: n
1876
1877 ! Return if already allocated distinctly
1878 if (.not. associated(this%Blag, this%B)) return
1879
1880 n = this%Xh%lx * this%Xh%ly * this%Xh%lz * this%msh%nelv
1881
1882
1883 nullify(this%Blag)
1884 nullify(this%Blaglag)
1885
1886 allocate(this%Blag(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
1887 allocate(this%Blaglag(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
1888
1889 this%Blag = this%B
1890 this%Blaglag = this%B
1891
1892 if (neko_bcknd_device .eq. 1) then
1893
1894 this%Blag_d = c_null_ptr
1895 this%Blaglag_d = c_null_ptr
1896
1897 call device_map(this%Blag, this%Blag_d, n)
1898 call device_map(this%Blaglag, this%Blaglag_d, n)
1899
1900 call device_memcpy(this%Blag, this%Blag_d, n, &
1901 host_to_device, sync = .false.)
1902 call device_memcpy(this%Blaglag, this%Blaglag_d, n, &
1903 host_to_device, sync = .true.)
1904 end if
1905
1906 end subroutine coef_enable_lagged_mass
1907
1908
1911 class(coef_t), intent(inout), target :: this
1912 integer :: n
1913
1914 ! If this%Blag does not have separate memory, we don't need to update it.
1915 if (associated(this%Blag, this%B)) return
1916 n = this%Xh%lx * this%Xh%ly * this%Xh%lz * this%msh%nelv
1917 if (neko_bcknd_device .eq. 1) then
1918 call device_copy(this%Blaglag_d, this%Blag_d, n)
1919 call device_copy(this%Blag_d, this%B_d, n)
1920 else
1921 this%Blaglag = this%Blag
1922 this%Blag = this%B
1923 end if
1924
1925 end subroutine coef_update_lagged_mass
1926
1927end module coefs
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
Coefficients.
Definition coef.f90:34
integer, parameter, public coef_full
Retain every coefficient. The default, and the only scope that supports recompute_metrics(),...
Definition coef.f90:76
subroutine coef_generate_geo(c)
Generate geometric data for the given mesh.
Definition coef.f90:1131
subroutine coef_free(this)
Deallocate coefficients.
Definition coef.f90:530
subroutine coef_release_scratch(this)
Release the coefficients that COEF_OPERATOR does not retain.
Definition coef.f90:808
integer, parameter, public coef_operator
Retain only what applying a discrete operator needs: , h1, h2, B and mult.
Definition coef.f90:89
subroutine coef_recompute_metrics(this)
Recompute and update geometric factors (ALE)
Definition coef.f90:1853
pure real(kind=rp) function coef_get_area(this, i, j, k, e, facet)
Facet area at a point.
Definition coef.f90:1584
pure real(kind=rp) function, dimension(3) coef_get_normal(this, i, j, k, e, facet)
Facet normal at a point.
Definition coef.f90:1560
subroutine coef_init_all(this, gs_h, scope)
Initialize coefficients.
Definition coef.f90:301
subroutine coef_update_lagged_mass(this)
Update history: Blaglag = Blag, Blag = B.
Definition coef.f90:1911
subroutine coef_generate_dxyzdrst(c)
Definition coef.f90:942
subroutine coef_generate_area_and_normal(coef)
Generate facet area and surface normals.
Definition coef.f90:1601
subroutine coef_init_empty(this, xh, msh)
Initialize empty coefs for a space and a mesh.
Definition coef.f90:252
subroutine coef_metric_condition(this)
Compute the largest condition number of the metric tensor over the mesh.
Definition coef.f90:1289
subroutine coef_enable_lagged_mass(this)
Enable separate memory for lagged B matrices if needed. For eg. when mesh moves.
Definition coef.f90:1874
subroutine coef_require_facets(this, who)
Abort unless this coef holds the facet areas and normals.
Definition coef.f90:1545
real(kind=rp), parameter, public neko_metric_cond_sp
Largest metric condition number for which single precision storage of the geometric factors is consi...
Definition coef.f90:71
subroutine coef_generate_geo_compressed(c)
Compute processor-local compressed versions of mappings Gij.
Definition coef.f90:1403
subroutine coef_generate_cyclic_bc(this)
Definition coef.f90:1777
subroutine coef_generate_mass(c)
Generate mass matrix B for the given mesh and space.
Definition coef.f90:1481
Definition comm.F90:1
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
subroutine, public device_coef_generate_area_and_normal(area_d, nx_d, ny_d, nz_d, dxdr_d, dydr_d, dzdr_d, dxds_d, dyds_d, dzds_d, dxdt_d, dydt_d, dzdt_d, wx_d, wy_d, wz_d, lx, nel, eps)
subroutine, public device_coef_generate_dxydrst(drdx_d, drdy_d, drdz_d, dsdx_d, dsdy_d, dsdz_d, dtdx_d, dtdy_d, dtdz_d, dxdr_d, dydr_d, dzdr_d, dxds_d, dyds_d, dzds_d, dxdt_d, dydt_d, dzdt_d, dx_d, dy_d, dz_d, x_d, y_d, z_d, jacinv_d, jac_d, lx, nel)
subroutine, public device_coef_generate_mass(b, binv, jac, w3, lxyz, nel)
subroutine, public device_coef_generate_geo(g11_d, g12_d, g13_d, g22_d, g23_d, g33_d, drdx_d, drdy_d, drdz_d, dsdx_d, dsdy_d, dsdz_d, dtdx_d, dtdy_d, dtdz_d, jacinv_d, w3_d, nel, lx, gdim)
real(kind=rp) function, public device_glsum(a_d, n, strm)
Sum a vector of length n.
subroutine, public device_invcol1(a_d, n, strm)
Invert a vector .
subroutine, public device_rone(a_d, n, strm)
Set all elements to one.
subroutine, public device_copy(a_d, b_d, n, strm)
Copy a vector .
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
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Gather-scatter.
Defines Gather-scatter operations.
Definition gs_ops.f90:34
integer, parameter, public gs_op_add
Definition gs_ops.f90:36
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:80
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
pure subroutine, public eig_sym3(a11, a22, a33, a12, a13, a23, e1, e2, e3)
Eigenvalues of a symmetric 3x3 matrix, descending.
Definition math.f90:1946
subroutine, public invers2(a, b, n)
Compute inverted vector .
Definition math.f90:803
pure subroutine, public eig_sym2(a11, a22, a12, e1, e2)
Eigenvalues of a symmetric 2x2 matrix, descending.
Definition math.f90:1911
subroutine, public subcol3(a, b, c, n)
Returns .
Definition math.f90:1080
subroutine, public rone(a, n)
Set all elements to one.
Definition math.f90:280
real(kind=rp) function, public glsum(a, n)
Sum a vector of length n.
Definition math.f90:632
subroutine, public addcol3(a, b, c, n)
Returns .
Definition math.f90:1167
subroutine, public invcol1(a, n)
Invert a vector .
Definition math.f90:774
subroutine, public chsign(a, n)
Change sign of vector .
Definition math.f90:729
real(kind=rp) function, public glmax(a, n)
Max of a vector of length n.
Definition math.f90:653
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:294
real(kind=rp), parameter, public neko_eps
Machine epsilon .
Definition math.f90:70
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:238
Defines a mesh.
Definition mesh.f90:34
Wrapper for all matrix-matrix product implementations.
subroutine, public mxm(a, n1, b, n2, c, n3)
Compute matrix-matrix product for contiguously packed matrices A,B, and C.
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter neko_bcknd_opencl
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
Utilities.
Definition utils.f90:35
pure logical function, public index_is_on_facet(i, j, k, lx, ly, lz, facet)
Definition utils.f90:314
pure integer function, public linear_index(i, j, k, l, lx, ly, lz)
Compute the address of a (i,j,k,l) array with sizes (1:lx, 1:ly, 1:lz, :)
Definition utils.f90:289
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:93
Gather-scatter kernel.
The function space for the SEM solution fields.
Definition space.f90:64
#define max(a, b)
Definition tensor.cu:40