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
39 use num_types, only : rp, sp, dp
40 use dofmap, only : dofmap_t
41 use space, only : space_t
42 use math, only : rone, invcol1, addcol3, subcol3, copy, &
45 use logger, only : neko_log, log_size
46 use mesh, only : mesh_t
52 use mxm_wrapper, only : mxm
57 use comm, only : neko_comm
59 use mpi_f08, only : mpi_allreduce, mpi_integer, mpi_sum
60 use, intrinsic :: iso_c_binding
61 implicit none
62 private
63
80 real(kind=rp), public, parameter :: neko_metric_cond_sp = 1.0e4_rp
81
114 real(kind=rp), public, parameter :: neko_metric_perturb_max = 1.0e-5_rp
115
119 integer, public, parameter :: coef_full = 0
132 integer, public, parameter :: coef_operator = 1
133
136 type, public :: coef_t
138 real(kind=rp), allocatable :: g11(:,:,:,:)
140 real(kind=rp), allocatable :: g22(:,:,:,:)
142 real(kind=rp), allocatable :: g33(:,:,:,:)
144 real(kind=rp), allocatable :: g12(:,:,:,:)
146 real(kind=rp), allocatable :: g13(:,:,:,:)
148 real(kind=rp), allocatable :: g23(:,:,:,:)
149
153 real(kind=rp) :: metric_cond = 0.0_rp
160 real(kind=rp) :: metric_scaled_cond = 0.0_rp
163 integer :: metric_degenerate = 0
169 real(kind=rp) :: metric_perturb = 0.0_rp
180 logical :: metric_sp_safe = .false.
182 real(kind=rp), allocatable :: g11_compr(:,:,:,:)
184 real(kind=rp), allocatable :: g22_compr(:,:,:,:)
186 real(kind=rp), allocatable :: g33_compr(:,:,:,:)
188 real(kind=rp), allocatable :: g12_compr(:,:,:,:)
190 real(kind=rp), allocatable :: g13_compr(:,:,:,:)
192 real(kind=rp), allocatable :: g23_compr(:,:,:,:)
194 integer, allocatable :: compression_inds(:)
197 logical :: geo_compression = .false.
200 real(kind=rp) :: geo_compression_tol = 0.0_rp
201
202 real(kind=rp), allocatable :: mult(:,:,:,:)
207 real(kind=rp), allocatable :: dxdr(:,:,:,:), dydr(:,:,:,:), dzdr(:,:,:,:)
208 real(kind=rp), allocatable :: dxds(:,:,:,:), dyds(:,:,:,:), dzds(:,:,:,:)
209 real(kind=rp), allocatable :: dxdt(:,:,:,:), dydt(:,:,:,:), dzdt(:,:,:,:)
213 real(kind=rp), allocatable :: drdx(:,:,:,:), drdy(:,:,:,:), drdz(:,:,:,:)
214 real(kind=rp), allocatable :: dsdx(:,:,:,:), dsdy(:,:,:,:), dsdz(:,:,:,:)
215 real(kind=rp), allocatable :: dtdx(:,:,:,:), dtdy(:,:,:,:), dtdz(:,:,:,:)
216
217 real(kind=rp), allocatable :: h1(:,:,:,:)
218 real(kind=rp), allocatable :: h2(:,:,:,:)
219 logical :: ifh2
220
221 real(kind=rp), allocatable :: jac(:,:,:,:)
222 real(kind=rp), allocatable :: jacinv(:,:,:,:)
223 real(kind=rp), allocatable :: b(:,:,:,:)
224 real(kind=rp), allocatable :: binv(:,:,:,:)
225 real(kind=rp), pointer :: blag(:,:,:,:) => null()
226 real(kind=rp), pointer :: blaglag(:,:,:,:) => null()
227 real(kind=rp), allocatable :: area(:,:,:,:)
228 real(kind=rp), allocatable :: nx(:,:,:,:)
229 real(kind=rp), allocatable :: ny(:,:,:,:)
230 real(kind=rp), allocatable :: nz(:,:,:,:)
231 logical :: cyclic = .false.
232 integer, allocatable :: cyc_msk(:)
233 real(kind=rp), allocatable :: r11(:)
234 real(kind=rp), allocatable :: r12(:)
235
236 !! True if geometric metrics have been initialized
237 logical, private :: coef_metrics_initialized = .false.
238
241 integer :: scope = coef_full
242
244
245 real(kind=rp) :: volume = 0.0_rp
246
247 type(space_t), pointer :: xh => null()
248 type(mesh_t), pointer :: msh => null()
249 type(dofmap_t), pointer :: dof => null()
250 type(gs_t), pointer :: gs_h=> null()
251
252 !
253 ! Device pointers (if present)
254 !
255
256 type(c_ptr) :: g11_d = c_null_ptr
257 type(c_ptr) :: g22_d = c_null_ptr
258 type(c_ptr) :: g33_d = c_null_ptr
259 type(c_ptr) :: g12_d = c_null_ptr
260 type(c_ptr) :: g13_d = c_null_ptr
261 type(c_ptr) :: g23_d = c_null_ptr
262 type(c_ptr) :: g11_compr_d = c_null_ptr
263 type(c_ptr) :: g22_compr_d = c_null_ptr
264 type(c_ptr) :: g33_compr_d = c_null_ptr
265 type(c_ptr) :: g12_compr_d = c_null_ptr
266 type(c_ptr) :: g13_compr_d = c_null_ptr
267 type(c_ptr) :: g23_compr_d = c_null_ptr
268 type(c_ptr) :: compression_inds_d = c_null_ptr
269 type(c_ptr) :: dxdr_d = c_null_ptr
270 type(c_ptr) :: dydr_d = c_null_ptr
271 type(c_ptr) :: dzdr_d = c_null_ptr
272 type(c_ptr) :: dxds_d = c_null_ptr
273 type(c_ptr) :: dyds_d = c_null_ptr
274 type(c_ptr) :: dzds_d = c_null_ptr
275 type(c_ptr) :: dxdt_d = c_null_ptr
276 type(c_ptr) :: dydt_d = c_null_ptr
277 type(c_ptr) :: dzdt_d = c_null_ptr
278 type(c_ptr) :: drdx_d = c_null_ptr
279 type(c_ptr) :: drdy_d = c_null_ptr
280 type(c_ptr) :: drdz_d = c_null_ptr
281 type(c_ptr) :: dsdx_d = c_null_ptr
282 type(c_ptr) :: dsdy_d = c_null_ptr
283 type(c_ptr) :: dsdz_d = c_null_ptr
284 type(c_ptr) :: dtdx_d = c_null_ptr
285 type(c_ptr) :: dtdy_d = c_null_ptr
286 type(c_ptr) :: dtdz_d = c_null_ptr
287 type(c_ptr) :: mult_d = c_null_ptr
288 type(c_ptr) :: h1_d = c_null_ptr
289 type(c_ptr) :: h2_d = c_null_ptr
290 type(c_ptr) :: jac_d = c_null_ptr
291 type(c_ptr) :: jacinv_d = c_null_ptr
292 type(c_ptr) :: b_d = c_null_ptr
293 type(c_ptr) :: blag_d = c_null_ptr
294 type(c_ptr) :: blaglag_d = c_null_ptr
295 type(c_ptr) :: binv_d = c_null_ptr
296 type(c_ptr) :: area_d = c_null_ptr
297 type(c_ptr) :: nx_d = c_null_ptr
298 type(c_ptr) :: ny_d = c_null_ptr
299 type(c_ptr) :: nz_d = c_null_ptr
300 type(c_ptr) :: cyc_msk_d = c_null_ptr
301 type(c_ptr) :: r11_d = c_null_ptr
302 type(c_ptr) :: r12_d = c_null_ptr
303
305 integer :: metrics_version = 0
306
307 contains
308 procedure, private, pass(this) :: init_empty => coef_init_empty
309 procedure, private, pass(this) :: init_all => coef_init_all
310 procedure, pass(this) :: free => coef_free
311 procedure, pass(this) :: get_normal => coef_get_normal
312 procedure, pass(this) :: get_area => coef_get_area
313 procedure, pass(this) :: require_facets => coef_require_facets
314 procedure, pass(this) :: generate_cyclic_bc => coef_generate_cyclic_bc
315 procedure, pass(this) :: recompute_metrics => coef_recompute_metrics
316 procedure, pass(this) :: metric_condition => coef_metric_condition
317 procedure, pass(this) :: enable_geo_compression => &
319 procedure, pass(this) :: enable_b_history => coef_enable_lagged_mass
320 procedure, pass(this) :: update_b_history => coef_update_lagged_mass
321 generic :: init => init_empty, init_all
322 end type coef_t
323
324contains
325
327 subroutine coef_init_empty(this, Xh, msh)
328 class(coef_t), intent(inout) :: this
329 type(space_t), intent(inout), target :: Xh
330 type(mesh_t), intent(inout), target :: msh
331 integer :: n
332 call this%free()
333 this%msh => msh
334 this%Xh => xh
335
336 allocate(this%drdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
337 allocate(this%dsdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
338 allocate(this%dtdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
339
340 allocate(this%drdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
341 allocate(this%dsdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
342 allocate(this%dtdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
343
344 allocate(this%drdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
345 allocate(this%dsdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
346 allocate(this%dtdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
347
348
349 !
350 ! Setup device memory (if present)
351 !
352
353 n = this%Xh%lx * this%Xh%ly * this%Xh%lz * this%msh%nelv
354 if (neko_bcknd_device .eq. 1) then
355
356 call device_map(this%drdx, this%drdx_d, n)
357 call device_map(this%drdy, this%drdy_d, n)
358 call device_map(this%drdz, this%drdz_d, n)
359
360 call device_map(this%dsdx, this%dsdx_d, n)
361 call device_map(this%dsdy, this%dsdy_d, n)
362 call device_map(this%dsdz, this%dsdz_d, n)
363
364 call device_map(this%dtdx, this%dtdx_d, n)
365 call device_map(this%dtdy, this%dtdy_d, n)
366 call device_map(this%dtdz, this%dtdz_d, n)
367
368 end if
369
370 end subroutine coef_init_empty
371
376 subroutine coef_init_all(this, gs_h, scope)
377 class(coef_t), intent(inout), target :: this
378 type(gs_t), intent(inout), target :: gs_h
379 integer, intent(in), optional :: scope
380 integer :: n, m, ncyc
381
382 call this%free()
383
384 ! After free(), so that it survives into the initialized state
385 if (present(scope)) then
386 if (scope .ne. coef_full .and. scope .ne. coef_operator) then
387 call neko_error('Unknown coefficient scope')
388 end if
389 this%scope = scope
390 end if
391
392 call neko_log%section('Coefficients')
393
394 this%msh => gs_h%dofmap%msh
395 this%Xh => gs_h%dofmap%Xh
396 this%dof => gs_h%dofmap
397 this%gs_h => gs_h
398
399 !
400 ! Allocate arrays for geometric data
401 !
403 allocate(this%G11(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
404 allocate(this%G22(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
405 allocate(this%G33(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
406 allocate(this%G12(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
407 allocate(this%G13(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
408 allocate(this%G23(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
409
410 allocate(this%dxdr(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
411 allocate(this%dxds(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
412 allocate(this%dxdt(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
413
414 allocate(this%dydr(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
415 allocate(this%dyds(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
416 allocate(this%dydt(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
417
418 allocate(this%dzdr(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
419 allocate(this%dzds(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
420 allocate(this%dzdt(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
421
422 allocate(this%drdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
423 allocate(this%dsdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
424 allocate(this%dtdx(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
425
426 allocate(this%drdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
427 allocate(this%dsdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
428 allocate(this%dtdy(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
429
430 allocate(this%drdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
431 allocate(this%dsdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
432 allocate(this%dtdz(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
433
434 allocate(this%jac(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
435 allocate(this%jacinv(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
436
437 if (this%scope .eq. coef_full) then
438 allocate(this%area(this%Xh%lx, this%Xh%ly, 6, this%msh%nelv))
439 allocate(this%nx(this%Xh%lx, this%Xh%ly, 6, this%msh%nelv))
440 allocate(this%ny(this%Xh%lx, this%Xh%ly, 6, this%msh%nelv))
441 allocate(this%nz(this%Xh%lx, this%Xh%ly, 6, this%msh%nelv))
442 end if
443
444 allocate(this%B(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
445 allocate(this%Binv(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
446
447 ! We do this so in a static simulation we don't allocate extra memory
448 this%Blag => this%B
449 this%Blaglag => this%B
450
451 allocate(this%h1(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
452 allocate(this%h2(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
453
454 allocate(this%mult(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
455
456
457 !
458 ! Setup device memory (if present)
459 !
460
461 n = this%Xh%lx * this%Xh%ly * this%Xh%lz * this%msh%nelv
462 if (neko_bcknd_device .eq. 1) then
463 call device_map(this%G11, this%G11_d, n)
464 call device_map(this%G22, this%G22_d, n)
465 call device_map(this%G33, this%G33_d, n)
466 call device_map(this%G12, this%G12_d, n)
467 call device_map(this%G13, this%G13_d, n)
468 call device_map(this%G23, this%G23_d, n)
469
470 call device_map(this%dxdr, this%dxdr_d, n)
471 call device_map(this%dydr, this%dydr_d, n)
472 call device_map(this%dzdr, this%dzdr_d, n)
473
474 call device_map(this%dxds, this%dxds_d, n)
475 call device_map(this%dyds, this%dyds_d, n)
476 call device_map(this%dzds, this%dzds_d, n)
477
478 call device_map(this%dxdt, this%dxdt_d, n)
479 call device_map(this%dydt, this%dydt_d, n)
480 call device_map(this%dzdt, this%dzdt_d, n)
481
482 call device_map(this%drdx, this%drdx_d, n)
483 call device_map(this%drdy, this%drdy_d, n)
484 call device_map(this%drdz, this%drdz_d, n)
485
486 call device_map(this%dsdx, this%dsdx_d, n)
487 call device_map(this%dsdy, this%dsdy_d, n)
488 call device_map(this%dsdz, this%dsdz_d, n)
489
490 call device_map(this%dtdx, this%dtdx_d, n)
491 call device_map(this%dtdy, this%dtdy_d, n)
492 call device_map(this%dtdz, this%dtdz_d, n)
493
494 call device_map(this%mult, this%mult_d, n)
495 call device_map(this%h1, this%h1_d, n)
496 call device_map(this%h2, this%h2_d, n)
497
498 call device_map(this%jac, this%jac_d, n)
499 call device_map(this%jacinv, this%jacinv_d, n)
500 call device_map(this%B, this%B_d, n)
501 call device_map(this%Binv, this%Binv_d, n)
502
503 this%Blag_d = this%B_d
504 this%Blaglag_d = this%B_d
505
506 if (this%scope .eq. coef_full) then
507 m = this%Xh%lx * this%Xh%ly * 6 * this%msh%nelv
508
509 call device_map(this%area, this%area_d, m)
510 call device_map(this%nx, this%nx_d, m)
511 call device_map(this%ny, this%ny_d, m)
512 call device_map(this%nz, this%nz_d, m)
513 end if
514
515 end if
516
517 call coef_generate_dxyzdrst(this)
518
519 call coef_generate_geo(this)
520
521 ! Both are dead weight under COEF_OPERATOR: nothing reads the facet
522 ! metrics, and the conditioning diagnostic is two per-point eigenvalue
523 ! solves plus three reductions spent on something no one consumes yet.
524 if (this%scope .eq. coef_full) then
525 call coef_metric_condition(this)
526
528 end if
529
530 call coef_generate_mass(this)
531
532 this%coef_metrics_initialized = .true.
533
534
535 ! This is a placeholder, just for now
536 ! We can probably find a prettier solution
537 if (neko_bcknd_device .eq. 1) then
538 call device_rone(this%h1_d, n)
539 call device_rone(this%h2_d, n)
540 call device_memcpy(this%h1, this%h1_d, n, &
541 device_to_host, sync = .false.)
542 call device_memcpy(this%h2, this%h2_d, n, &
543 device_to_host, sync = .false.)
544 else
545 call rone(this%h1,n)
546 call rone(this%h2,n)
547 end if
548
549 this%ifh2 = .false.
550
551 !
552 ! Set up multiplicity
553 !
554 if (neko_bcknd_device .eq. 1) then
555 call device_rone(this%mult_d, n)
556 else
557 call rone(this%mult, n)
558 end if
559
560 call gs_h%op(this%mult, n, gs_op_add)
561
562 if (neko_bcknd_device .eq. 1) then
563 call device_invcol1(this%mult_d, n)
564 call device_memcpy(this%mult, this%mult_d, n, &
565 device_to_host, sync = .true.)
566 else
567 call invcol1(this%mult, n)
568 end if
569
570 ncyc = this%msh%periodic%size * this%Xh%lx * this%Xh%lx
571 allocate(this%cyc_msk(0:ncyc))
572 this%cyc_msk(0) = ncyc + 1
573 if (ncyc .gt. 0) then
574 allocate(this%R11(ncyc))
575 allocate(this%R12(ncyc))
576
578 call rone(this%R11, ncyc)
579 call rzero(this%R12, ncyc)
580
581 if (neko_bcknd_device .eq. 1) then
582 call device_map(this%cyc_msk, this%cyc_msk_d, ncyc+1)
583 call device_map(this%R11, this%R11_d, ncyc)
584 call device_map(this%R12, this%R12_d, ncyc)
585
586 call device_memcpy(this%cyc_msk, this%cyc_msk_d, ncyc+1, &
587 host_to_device, sync = .false.)
588 call device_memcpy(this%R11, this%R11_d, ncyc, &
589 host_to_device, sync = .false.)
590 call device_memcpy(this%R12, this%R12_d, ncyc, &
591 host_to_device, sync = .false.)
592 end if
593
594 end if
595
596 call coef_release_scratch(this)
597
598 call neko_log%end_section()
599
600 end subroutine coef_init_all
601
603 subroutine coef_free(this)
604 class(coef_t), intent(inout), target :: this
605
606 if (allocated(this%G11)) then
607 if (neko_bcknd_device .eq. 1) call device_unmap(this%G11, this%G11_d)
608 deallocate(this%G11)
609 end if
610
611 if (allocated(this%G22)) then
612 if (neko_bcknd_device .eq. 1) call device_unmap(this%G22, this%G22_d)
613 deallocate(this%G22)
614 end if
615
616 if (allocated(this%G33)) then
617 if (neko_bcknd_device .eq. 1) call device_unmap(this%G33, this%G33_d)
618 deallocate(this%G33)
619 end if
620
621 if (allocated(this%G12)) then
622 if (neko_bcknd_device .eq. 1) call device_unmap(this%G12, this%G12_d)
623 deallocate(this%G12)
624 end if
625
626 if (allocated(this%G13)) then
627 if (neko_bcknd_device .eq. 1) call device_unmap(this%G13, this%G13_d)
628 deallocate(this%G13)
629 end if
630
631 if (allocated(this%G23)) then
632 if (neko_bcknd_device .eq. 1) call device_unmap(this%G23, this%G23_d)
633 deallocate(this%G23)
634 end if
635
636 call coef_free_geo_compr(this)
637 this%geo_compression = .false.
638 this%geo_compression_tol = 0.0_rp
639
640 if (allocated(this%mult)) then
641 if (neko_bcknd_device .eq. 1) call device_unmap(this%mult, this%mult_d)
642 deallocate(this%mult)
643 end if
644
645 if (associated(this%Blag) .and. &
646 .not. associated(this%Blag, this%B)) then
647 if (c_associated(this%Blag_d) .and. &
648 .not. c_associated(this%Blag_d, this%B_d)) then
649 call device_unmap(this%Blag, this%Blag_d)
650 end if
651 deallocate(this%Blag)
652 end if
653 nullify(this%Blag)
654
655 if (associated(this%Blaglag) .and. &
656 .not. associated(this%Blaglag, this%B)) then
657 if (c_associated(this%Blaglag_d) .and. &
658 .not. c_associated(this%Blaglag_d, this%B_d)) then
659 call device_unmap(this%Blaglag, this%Blaglag_d)
660 end if
661 deallocate(this%Blaglag)
662 end if
663 nullify(this%Blaglag)
664
665 if (c_associated(this%Blag_d) .and. &
666 .not. c_associated(this%Blag_d, this%B_d)) then
667 this%Blag_d = c_null_ptr
668 end if
669 this%Blag_d = c_null_ptr
670
671 if (c_associated(this%Blaglag_d) .and. &
672 .not. c_associated(this%Blaglag_d, this%B_d)) then
673 this%Blaglag_d = c_null_ptr
674 end if
675 this%Blaglag_d = c_null_ptr
676
677 if (allocated(this%B)) then
678 if (neko_bcknd_device .eq. 1) call device_unmap(this%B, this%B_d)
679 deallocate(this%B)
680 end if
681
682 if (allocated(this%Binv)) then
683 if (neko_bcknd_device .eq. 1) call device_unmap(this%Binv, this%Binv_d)
684 deallocate(this%Binv)
685 end if
686
687 if (allocated(this%dxdr)) then
688 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxdr, this%dxdr_d)
689 deallocate(this%dxdr)
690 end if
691
692 if (allocated(this%dxds)) then
693 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxds, this%dxds_d)
694 deallocate(this%dxds)
695 end if
696
697 if (allocated(this%dxdt)) then
698 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxdt, this%dxdt_d)
699 deallocate(this%dxdt)
700 end if
701
702 if (allocated(this%dydr)) then
703 if (neko_bcknd_device .eq. 1) call device_unmap(this%dydr, this%dydr_d)
704 deallocate(this%dydr)
705 end if
706
707 if (allocated(this%dyds)) then
708 if (neko_bcknd_device .eq. 1) call device_unmap(this%dyds, this%dyds_d)
709 deallocate(this%dyds)
710 end if
711
712 if (allocated(this%dydt)) then
713 if (neko_bcknd_device .eq. 1) call device_unmap(this%dydt, this%dydt_d)
714 deallocate(this%dydt)
715 end if
716
717 if (allocated(this%dzdr)) then
718 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzdr, this%dzdr_d)
719 deallocate(this%dzdr)
720 end if
721
722 if (allocated(this%dzds)) then
723 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzds, this%dzds_d)
724 deallocate(this%dzds)
725 end if
726
727 if (allocated(this%dzdt)) then
728 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzdt, this%dzdt_d)
729 deallocate(this%dzdt)
730 end if
731
732 if (allocated(this%drdx)) then
733 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdx, this%drdx_d)
734 deallocate(this%drdx)
735 end if
736
737 if (allocated(this%dsdx)) then
738 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdx, this%dsdx_d)
739 deallocate(this%dsdx)
740 end if
741
742 if (allocated(this%dtdx)) then
743 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdx, this%dtdx_d)
744 deallocate(this%dtdx)
745 end if
746
747 if (allocated(this%drdy)) then
748 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdy, this%drdy_d)
749 deallocate(this%drdy)
750 end if
751
752 if (allocated(this%dsdy)) then
753 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdy, this%dsdy_d)
754 deallocate(this%dsdy)
755 end if
756
757 if (allocated(this%dtdy)) then
758 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdy, this%dtdy_d)
759 deallocate(this%dtdy)
760 end if
761
762 if (allocated(this%drdz)) then
763 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdz, this%drdz_d)
764 deallocate(this%drdz)
765 end if
766
767 if (allocated(this%dsdz)) then
768 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdz, this%dsdz_d)
769 deallocate(this%dsdz)
770 end if
771
772 if (allocated(this%dtdz)) then
773 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdz, this%dtdz_d)
774 deallocate(this%dtdz)
775 end if
776
777 if (allocated(this%jac)) then
778 if (neko_bcknd_device .eq. 1) call device_unmap(this%jac, this%jac_d)
779 deallocate(this%jac)
780 end if
781
782 if (allocated(this%jacinv)) then
783 if (neko_bcknd_device .eq. 1) then
784 call device_unmap(this%jacinv, this%jacinv_d)
785 end if
786 deallocate(this%jacinv)
787 end if
788
789 if (allocated(this%h1)) then
790 if (neko_bcknd_device .eq. 1) call device_unmap(this%h1, this%h1_d)
791 deallocate(this%h1)
792 end if
793
794 if (allocated(this%h2)) then
795 if (neko_bcknd_device .eq. 1) call device_unmap(this%h2, this%h2_d)
796 deallocate(this%h2)
797 end if
798
799 if (allocated(this%area)) then
800 if (neko_bcknd_device .eq. 1) call device_unmap(this%area, this%area_d)
801 deallocate(this%area)
802 end if
803
804 if (allocated(this%nx)) then
805 if (neko_bcknd_device .eq. 1) call device_unmap(this%nx, this%nx_d)
806 deallocate(this%nx)
807 end if
808
809 if (allocated(this%ny)) then
810 if (neko_bcknd_device .eq. 1) call device_unmap(this%ny, this%ny_d)
811 deallocate(this%ny)
812 end if
813
814 if (allocated(this%nz)) then
815 if (neko_bcknd_device .eq. 1) call device_unmap(this%nz, this%nz_d)
816 deallocate(this%nz)
817 end if
818
819 if (allocated(this%cyc_msk)) then
820 if (neko_bcknd_device .eq. 1) then
821 call device_unmap(this%cyc_msk, this%cyc_msk_d)
822 end if
823 deallocate(this%cyc_msk)
824 end if
825
826 if (allocated(this%R11)) then
827 if (neko_bcknd_device .eq. 1) call device_unmap(this%R11, this%R11_d)
828 deallocate(this%R11)
829 end if
830
831 if (allocated(this%R12)) then
832 if (neko_bcknd_device .eq. 1) call device_unmap(this%R12, this%R12_d)
833 deallocate(this%R12)
834 end if
835
836
837 nullify(this%msh)
838 nullify(this%Xh)
839 nullify(this%dof)
840 nullify(this%gs_h)
841
842 this%coef_metrics_initialized = .false.
843 this%scope = coef_full
844
845 end subroutine coef_free
846
857 subroutine coef_release_scratch(this)
858 class(coef_t), intent(inout), target :: this
859
860 if (this%scope .eq. coef_full) return
861
862 if (allocated(this%dxdr)) then
863 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxdr, this%dxdr_d)
864 deallocate(this%dxdr)
865 end if
866
867 if (allocated(this%dxds)) then
868 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxds, this%dxds_d)
869 deallocate(this%dxds)
870 end if
871
872 if (allocated(this%dxdt)) then
873 if (neko_bcknd_device .eq. 1) call device_unmap(this%dxdt, this%dxdt_d)
874 deallocate(this%dxdt)
875 end if
876
877 if (allocated(this%dydr)) then
878 if (neko_bcknd_device .eq. 1) call device_unmap(this%dydr, this%dydr_d)
879 deallocate(this%dydr)
880 end if
881
882 if (allocated(this%dyds)) then
883 if (neko_bcknd_device .eq. 1) call device_unmap(this%dyds, this%dyds_d)
884 deallocate(this%dyds)
885 end if
886
887 if (allocated(this%dydt)) then
888 if (neko_bcknd_device .eq. 1) call device_unmap(this%dydt, this%dydt_d)
889 deallocate(this%dydt)
890 end if
891
892 if (allocated(this%dzdr)) then
893 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzdr, this%dzdr_d)
894 deallocate(this%dzdr)
895 end if
896
897 if (allocated(this%dzds)) then
898 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzds, this%dzds_d)
899 deallocate(this%dzds)
900 end if
901
902 if (allocated(this%dzdt)) then
903 if (neko_bcknd_device .eq. 1) call device_unmap(this%dzdt, this%dzdt_d)
904 deallocate(this%dzdt)
905 end if
906
907 if (allocated(this%drdx)) then
908 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdx, this%drdx_d)
909 deallocate(this%drdx)
910 end if
911
912 if (allocated(this%drdy)) then
913 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdy, this%drdy_d)
914 deallocate(this%drdy)
915 end if
916
917 if (allocated(this%drdz)) then
918 if (neko_bcknd_device .eq. 1) call device_unmap(this%drdz, this%drdz_d)
919 deallocate(this%drdz)
920 end if
921
922 if (allocated(this%dsdx)) then
923 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdx, this%dsdx_d)
924 deallocate(this%dsdx)
925 end if
926
927 if (allocated(this%dsdy)) then
928 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdy, this%dsdy_d)
929 deallocate(this%dsdy)
930 end if
931
932 if (allocated(this%dsdz)) then
933 if (neko_bcknd_device .eq. 1) call device_unmap(this%dsdz, this%dsdz_d)
934 deallocate(this%dsdz)
935 end if
936
937 if (allocated(this%dtdx)) then
938 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdx, this%dtdx_d)
939 deallocate(this%dtdx)
940 end if
941
942 if (allocated(this%dtdy)) then
943 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdy, this%dtdy_d)
944 deallocate(this%dtdy)
945 end if
946
947 if (allocated(this%dtdz)) then
948 if (neko_bcknd_device .eq. 1) call device_unmap(this%dtdz, this%dtdz_d)
949 deallocate(this%dtdz)
950 end if
951
952 if (allocated(this%jac)) then
953 if (neko_bcknd_device .eq. 1) call device_unmap(this%jac, this%jac_d)
954 deallocate(this%jac)
955 end if
956
957 if (allocated(this%jacinv)) then
958 if (neko_bcknd_device .eq. 1) then
959 call device_unmap(this%jacinv, this%jacinv_d)
960 end if
961 deallocate(this%jacinv)
962 end if
963
964 if (allocated(this%Binv)) then
965 if (neko_bcknd_device .eq. 1) call device_unmap(this%Binv, this%Binv_d)
966 deallocate(this%Binv)
967 end if
968
969 if (allocated(this%area)) then
970 if (neko_bcknd_device .eq. 1) call device_unmap(this%area, this%area_d)
971 deallocate(this%area)
972 end if
973
974 if (allocated(this%nx)) then
975 if (neko_bcknd_device .eq. 1) call device_unmap(this%nx, this%nx_d)
976 deallocate(this%nx)
977 end if
978
979 if (allocated(this%ny)) then
980 if (neko_bcknd_device .eq. 1) call device_unmap(this%ny, this%ny_d)
981 deallocate(this%ny)
982 end if
983
984 if (allocated(this%nz)) then
985 if (neko_bcknd_device .eq. 1) call device_unmap(this%nz, this%nz_d)
986 deallocate(this%nz)
987 end if
988
989 end subroutine coef_release_scratch
990
992 type(coef_t), intent(inout) :: c
993 integer :: e, i, lxy, lyz, ntot
994
995 lxy = c%Xh%lx*c%Xh%ly
996 lyz = c%Xh%ly*c%Xh%lz
997 ntot = c%dof%size()
998
999 associate(drdx => c%drdx, drdy => c%drdy, drdz => c%drdz, &
1000 dsdx => c%dsdx, dsdy => c%dsdy, dsdz => c%dsdz, &
1001 dtdx => c%dtdx, dtdy => c%dtdy, dtdz => c%dtdz, &
1002 dxdr => c%dxdr, dydr => c%dydr, dzdr => c%dzdr, &
1003 dxds => c%dxds, dyds => c%dyds, dzds => c%dzds, &
1004 dxdt => c%dxdt, dydt => c%dydt, dzdt => c%dzdt, &
1005 dx => c%Xh%dx, dy => c%Xh%dy, dz => c%Xh%dz, &
1006 x => c%dof%x%x, y => c%dof%y%x, z => c%dof%z%x, &
1007 lx => c%Xh%lx, ly => c%Xh%ly, lz => c%Xh%lz, &
1008 dyt => c%Xh%dyt, dzt => c%Xh%dzt, &
1009 jacinv => c%jacinv, jac => c%jac)
1010
1011 if (neko_bcknd_device .eq. 1) then
1012
1013 call device_coef_generate_dxydrst(c%drdx_d, c%drdy_d, c%drdz_d, &
1014 c%dsdx_d, c%dsdy_d, c%dsdz_d, c%dtdx_d, c%dtdy_d, c%dtdz_d, &
1015 c%dxdr_d, c%dydr_d, c%dzdr_d, c%dxds_d, c%dyds_d, c%dzds_d, &
1016 c%dxdt_d, c%dydt_d, c%dzdt_d, c%Xh%dx_d, c%Xh%dy_d, c%Xh%dz_d, &
1017 c%dof%x%x_d, c%dof%y%x_d, c%dof%z%x_d, c%jacinv_d, c%jac_d, &
1018 c%Xh%lx, c%msh%nelv)
1019
1020 ! copy to host only at initialization.
1021 if (.not. c%coef_metrics_initialized) then
1022 call device_memcpy(dxdr, c%dxdr_d, ntot, device_to_host, &
1023 sync = .false.)
1024 call device_memcpy(dydr, c%dydr_d, ntot, device_to_host, &
1025 sync = .false.)
1026 call device_memcpy(dzdr, c%dzdr_d, ntot, device_to_host, &
1027 sync = .false.)
1028 call device_memcpy(dxds, c%dxds_d, ntot, device_to_host, &
1029 sync = .false.)
1030 call device_memcpy(dyds, c%dyds_d, ntot, device_to_host, &
1031 sync = .false.)
1032 call device_memcpy(dzds, c%dzds_d, ntot, device_to_host, &
1033 sync = .false.)
1034 call device_memcpy(dxdt, c%dxdt_d, ntot, device_to_host, &
1035 sync = .false.)
1036 call device_memcpy(dydt, c%dydt_d, ntot, device_to_host, &
1037 sync = .false.)
1038 call device_memcpy(dzdt, c%dzdt_d, ntot, device_to_host, &
1039 sync = .false.)
1040 call device_memcpy(drdx, c%drdx_d, ntot, device_to_host, &
1041 sync = .false.)
1042 call device_memcpy(drdy, c%drdy_d, ntot, device_to_host, &
1043 sync = .false.)
1044 call device_memcpy(drdz, c%drdz_d, ntot, device_to_host, &
1045 sync = .false.)
1046 call device_memcpy(dsdx, c%dsdx_d, ntot, device_to_host, &
1047 sync = .false.)
1048 call device_memcpy(dsdy, c%dsdy_d, ntot, device_to_host, &
1049 sync = .false.)
1050 call device_memcpy(dsdz, c%dsdz_d, ntot, device_to_host, &
1051 sync = .false.)
1052 call device_memcpy(dtdx, c%dtdx_d, ntot, device_to_host, &
1053 sync = .false.)
1054 call device_memcpy(dtdy, c%dtdy_d, ntot, device_to_host, &
1055 sync = .false.)
1056 call device_memcpy(dtdz, c%dtdz_d, ntot, device_to_host, &
1057 sync = .false.)
1058 call device_memcpy(jac, c%jac_d, ntot, device_to_host, &
1059 sync = .false.)
1060 call device_memcpy(jacinv, c%jacinv_d, ntot, device_to_host, &
1061 sync = .true.)
1062 end if
1063
1064 else
1065 !$omp parallel do private(i)
1066 do e = 1, c%msh%nelv
1067 call mxm(dx, lx, x(1,1,1,e), lx, dxdr(1,1,1,e), lyz)
1068 call mxm(dx, lx, y(1,1,1,e), lx, dydr(1,1,1,e), lyz)
1069 call mxm(dx, lx, z(1,1,1,e), lx, dzdr(1,1,1,e), lyz)
1070
1071 do i = 1, lz
1072 call mxm(x(1,1,i,e), lx, dyt, ly, dxds(1,1,i,e), ly)
1073 call mxm(y(1,1,i,e), lx, dyt, ly, dyds(1,1,i,e), ly)
1074 call mxm(z(1,1,i,e), lx, dyt, ly, dzds(1,1,i,e), ly)
1075 end do
1076
1077 ! We actually take 2d into account, wow, need to do that for the rest.
1078 if (c%msh%gdim .eq. 3) then
1079 call mxm(x(1,1,1,e), lxy, dzt, lz, dxdt(1,1,1,e), lz)
1080 call mxm(y(1,1,1,e), lxy, dzt, lz, dydt(1,1,1,e), lz)
1081 call mxm(z(1,1,1,e), lxy, dzt, lz, dzdt(1,1,1,e), lz)
1082 else
1083 call rzero(dxdt(1,1,1,e), lxy)
1084 call rzero(dydt(1,1,1,e), lxy)
1085 call rone(dzdt(1,1,1,e), lxy)
1086 end if
1087 end do
1088 !$omp end parallel do
1089
1090 if (c%msh%gdim .eq. 2) then
1091 call rzero (jac, ntot)
1092 call addcol3 (jac, dxdr, dyds, ntot)
1093 call subcol3 (jac, dxds, dydr, ntot)
1094 call copy (drdx, dyds, ntot)
1095 call copy (drdy, dxds, ntot)
1096 call chsign (drdy, ntot)
1097 call copy (dsdx, dydr, ntot)
1098 call chsign (dsdx, ntot)
1099 call copy (dsdy, dxdr, ntot)
1100 call rzero (drdz, ntot)
1101 call rzero (dsdz, ntot)
1102 call rone (dtdz, ntot)
1103 else
1104 !$omp parallel private(i)
1105 !$omp do simd
1106 do i = 1, ntot
1107 c%jac(i, 1, 1, 1) = 0.0_rp
1108 end do
1109 !$omp end do simd
1110 !$omp do simd
1111 do i = 1, ntot
1112 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) + ( c%dxdr(i, 1, 1, 1) &
1113 * c%dyds(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1) )
1114
1115 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) + ( c%dxdt(i, 1, 1, 1) &
1116 * c%dydr(i, 1, 1, 1) * c%dzds(i, 1, 1, 1) )
1117
1118 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) + ( c%dxds(i, 1, 1, 1) &
1119 * c%dydt(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1) )
1120 end do
1121 !$omp end do simd
1122 !$omp do simd
1123 do i = 1, ntot
1124 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) - ( c%dxdr(i, 1, 1, 1) &
1125 * c%dydt(i, 1, 1, 1) * c%dzds(i, 1, 1, 1) )
1126
1127 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) - ( c%dxds(i, 1, 1, 1) &
1128 * c%dydr(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1) )
1129
1130 c%jac(i, 1, 1, 1) = c%jac(i, 1, 1, 1) - ( c%dxdt(i, 1, 1, 1) &
1131 * c%dyds(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1) )
1132 end do
1133 !$omp end do simd
1134 !$omp do simd
1135 do i = 1, ntot
1136 c%drdx(i, 1, 1, 1) = c%dyds(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1) &
1137 - c%dydt(i, 1, 1, 1) * c%dzds(i, 1, 1, 1)
1138
1139 c%drdy(i, 1, 1, 1) = c%dxdt(i, 1, 1, 1) * c%dzds(i, 1, 1, 1) &
1140 - c%dxds(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1)
1141
1142 c%drdz(i, 1, 1, 1) = c%dxds(i, 1, 1, 1) * c%dydt(i, 1, 1, 1) &
1143 - c%dxdt(i, 1, 1, 1) * c%dyds(i, 1, 1, 1)
1144 end do
1145 !$omp end do simd
1146 !$omp do simd
1147 do i = 1, ntot
1148 c%dsdx(i, 1, 1, 1) = c%dydt(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1) &
1149 - c%dydr(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1)
1150
1151 c%dsdy(i, 1, 1, 1) = c%dxdr(i, 1, 1, 1) * c%dzdt(i, 1, 1, 1) &
1152 - c%dxdt(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1)
1153
1154 c%dsdz(i, 1, 1, 1) = c%dxdt(i, 1, 1, 1) * c%dydr(i, 1, 1, 1) &
1155 - c%dxdr(i, 1, 1, 1) * c%dydt(i, 1, 1, 1)
1156 end do
1157 !$omp end do simd
1158 !$omp do simd
1159 do i = 1, ntot
1160 c%dtdx(i, 1, 1, 1) = c%dydr(i, 1, 1, 1) * c%dzds(i, 1, 1, 1) &
1161 - c%dyds(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1)
1162
1163 c%dtdy(i, 1, 1, 1) = c%dxds(i, 1, 1, 1) * c%dzdr(i, 1, 1, 1) &
1164 - c%dxdr(i, 1, 1, 1) * c%dzds(i, 1, 1, 1)
1165
1166 c%dtdz(i, 1, 1, 1) = c%dxdr(i, 1, 1, 1) * c%dyds(i, 1, 1, 1) &
1167 - c%dxds(i, 1, 1, 1) * c%dydr(i, 1, 1, 1)
1168 end do
1169 !$omp end do simd
1170 !$omp end parallel
1171 end if
1172 call invers2(jacinv, jac, ntot)
1173 end if
1174 end associate
1175
1176 end subroutine coef_generate_dxyzdrst
1177
1180 subroutine coef_generate_geo(c)
1181 type(coef_t), intent(inout) :: c
1182 integer :: e, i, lxyz, ntot
1183
1184 lxyz = c%Xh%lx * c%Xh%ly * c%Xh%lz
1185 ntot = c%dof%size()
1186
1187 if (neko_bcknd_device .eq. 1) then
1188
1189 call device_coef_generate_geo(c%G11_d, c%G12_d, c%G13_d, &
1190 c%G22_d, c%G23_d, c%G33_d, &
1191 c%drdx_d, c%drdy_d, c%drdz_d, &
1192 c%dsdx_d, c%dsdy_d, c%dsdz_d, &
1193 c%dtdx_d, c%dtdy_d, c%dtdz_d, &
1194 c%jacinv_d, c%Xh%w3_d, c%msh%nelv, &
1195 c%Xh%lx, c%msh%gdim)
1196
1197 ! copy to host only at initialization.
1198 if (.not. c%coef_metrics_initialized) then
1199 call device_memcpy(c%G11, c%G11_d, ntot, device_to_host, &
1200 sync = .false.)
1201 call device_memcpy(c%G22, c%G22_d, ntot, device_to_host, &
1202 sync = .false.)
1203 call device_memcpy(c%G33, c%G33_d, ntot, device_to_host, &
1204 sync = .false.)
1205 call device_memcpy(c%G12, c%G12_d, ntot, device_to_host, &
1206 sync = .false.)
1207 call device_memcpy(c%G13, c%G13_d, ntot, device_to_host, &
1208 sync = .false.)
1209 call device_memcpy(c%G23, c%G23_d, ntot, device_to_host, &
1210 sync = .true.)
1211 end if
1212
1213 else
1214 if (c%msh%gdim .eq. 2) then
1215
1216 do i = 1, ntot
1217 c%G11(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%drdx(i, 1, 1, 1) &
1218 + c%drdy(i, 1, 1, 1) * c%drdy(i, 1, 1, 1)
1219
1220 c%G22(i, 1, 1, 1) = c%dsdx(i, 1, 1, 1) * c%dsdx(i, 1, 1, 1) &
1221 + c%dsdy(i, 1, 1, 1) * c%dsdy(i, 1, 1, 1)
1222
1223 c%G12(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%dsdx(i, 1, 1, 1) &
1224 + c%drdy(i, 1, 1, 1) * c%dsdy(i, 1, 1, 1)
1225 end do
1226
1227 do i = 1, ntot
1228 c%G11(i, 1, 1, 1) = c%G11(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1229 c%G22(i, 1, 1, 1) = c%G22(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1230 c%G12(i, 1, 1, 1) = c%G12(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1231 c%G33(i, 1, 1, 1) = 0.0_rp
1232 c%G13(i, 1, 1, 1) = 0.0_rp
1233 c%G23(i, 1, 1, 1) = 0.0_rp
1234 end do
1235
1236 do concurrent(e = 1:c%msh%nelv)
1237 do concurrent(i = 1:lxyz)
1238 c%G11(i,1,1,e) = c%G11(i,1,1,e) * c%Xh%w3(i,1,1)
1239 c%G22(i,1,1,e) = c%G22(i,1,1,e) * c%Xh%w3(i,1,1)
1240 c%G12(i,1,1,e) = c%G12(i,1,1,e) * c%Xh%w3(i,1,1)
1241 end do
1242 end do
1243
1244 else
1245 !$omp parallel private(i)
1246 !$omp do
1247 do i = 1, ntot
1248 c%G11(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%drdx(i, 1, 1, 1) &
1249 + c%drdy(i, 1, 1, 1) * c%drdy(i, 1, 1, 1) &
1250 + c%drdz(i, 1, 1, 1) * c%drdz(i, 1, 1, 1)
1251
1252 c%G22(i, 1, 1, 1) = c%dsdx(i, 1, 1, 1) * c%dsdx(i, 1, 1, 1) &
1253 + c%dsdy(i, 1, 1, 1) * c%dsdy(i, 1, 1, 1) &
1254 + c%dsdz(i, 1, 1, 1) * c%dsdz(i, 1, 1, 1)
1255
1256 c%G33(i, 1, 1, 1) = c%dtdx(i, 1, 1, 1) * c%dtdx(i, 1, 1, 1) &
1257 + c%dtdy(i, 1, 1, 1) * c%dtdy(i, 1, 1, 1) &
1258 + c%dtdz(i, 1, 1, 1) * c%dtdz(i, 1, 1, 1)
1259 end do
1260 !$omp end do
1261 !$omp do
1262 do i = 1, ntot
1263 c%G11(i, 1, 1, 1) = c%G11(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1264 c%G22(i, 1, 1, 1) = c%G22(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1265 c%G33(i, 1, 1, 1) = c%G33(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1266 end do
1267 !$omp end do
1268 !$omp do
1269 do i = 1, ntot
1270 c%G12(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%dsdx(i, 1, 1, 1) &
1271 + c%drdy(i, 1, 1, 1) * c%dsdy(i, 1, 1, 1) &
1272 + c%drdz(i, 1, 1, 1) * c%dsdz(i, 1, 1, 1)
1273
1274 c%G13(i, 1, 1, 1) = c%drdx(i, 1, 1, 1) * c%dtdx(i, 1, 1, 1) &
1275 + c%drdy(i, 1, 1, 1) * c%dtdy(i, 1, 1, 1) &
1276 + c%drdz(i, 1, 1, 1) * c%dtdz(i, 1, 1, 1)
1277
1278 c%G23(i, 1, 1, 1) = c%dsdx(i, 1, 1, 1) * c%dtdx(i, 1, 1, 1) &
1279 + c%dsdy(i, 1, 1, 1) * c%dtdy(i, 1, 1, 1) &
1280 + c%dsdz(i, 1, 1, 1) * c%dtdz(i, 1, 1, 1)
1281 end do
1282 !$omp end do
1283 !$omp do
1284 do i = 1, ntot
1285 c%G12(i, 1, 1, 1) = c%G12(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1286 c%G13(i, 1, 1, 1) = c%G13(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1287 c%G23(i, 1, 1, 1) = c%G23(i, 1, 1, 1) * c%jacinv(i, 1, 1, 1)
1288 end do
1289 !$omp end do
1290 !$omp do
1291 do e = 1, c%msh%nelv
1292 do concurrent(i = 1:lxyz)
1293 c%G11(i,1,1,e) = c%G11(i,1,1,e) * c%Xh%w3(i,1,1)
1294 c%G22(i,1,1,e) = c%G22(i,1,1,e) * c%Xh%w3(i,1,1)
1295 c%G12(i,1,1,e) = c%G12(i,1,1,e) * c%Xh%w3(i,1,1)
1296
1297 c%G33(i,1,1,e) = c%G33(i,1,1,e) * c%Xh%w3(i,1,1)
1298 c%G13(i,1,1,e) = c%G13(i,1,1,e) * c%Xh%w3(i,1,1)
1299 c%G23(i,1,1,e) = c%G23(i,1,1,e) * c%Xh%w3(i,1,1)
1300 end do
1301 end do
1302 !$omp end do
1303 !$omp end parallel
1304 end if
1305 end if
1306
1307 end subroutine coef_generate_geo
1308
1367 subroutine coef_metric_condition(this)
1368 class(coef_t), intent(inout) :: this
1369 real(kind=dp) :: e1, e2, e3, scal
1370 real(kind=dp) :: c1, c2, c3, c12, c13, c23
1371 real(kind=rp) :: kmax, kcmax, tmp(1)
1372 integer :: i, j, k, e, n, ndeg, ndeg_glb, ierr
1373 character(len=LOG_SIZE) :: log_buf
1374
1375 n = this%dof%size()
1376
1377 ! Post-initialization the host copy is stale on device builds
1378 if (neko_bcknd_device .eq. 1 .and. this%coef_metrics_initialized) then
1379 call device_memcpy(this%G11, this%G11_d, n, device_to_host, &
1380 sync = .false.)
1381 call device_memcpy(this%G22, this%G22_d, n, device_to_host, &
1382 sync = .false.)
1383 call device_memcpy(this%G33, this%G33_d, n, device_to_host, &
1384 sync = .false.)
1385 call device_memcpy(this%G12, this%G12_d, n, device_to_host, &
1386 sync = .false.)
1387 call device_memcpy(this%G13, this%G13_d, n, device_to_host, &
1388 sync = .false.)
1389 call device_memcpy(this%G23, this%G23_d, n, device_to_host, &
1390 sync = .true.)
1391 end if
1392
1393 kmax = 0.0_rp
1394 kcmax = 0.0_rp
1395 ndeg = 0
1396
1397 do e = 1, this%msh%nelv
1398 do k = 1, this%Xh%lz
1399 do j = 1, this%Xh%ly
1400 do i = 1, this%Xh%lx
1401
1402 ! Scale out the magnitude before the eigenvalue solve; the
1403 ! condition number is invariant under it and w3*J spans a
1404 ! wide range within an element
1405 scal = max(abs(real(this%G11(i,j,k,e), dp)), &
1406 abs(real(this%G22(i,j,k,e), dp)))
1407 scal = max(scal, abs(real(this%G33(i,j,k,e), dp)))
1408 scal = max(scal, abs(real(this%G12(i,j,k,e), dp)))
1409 scal = max(scal, abs(real(this%G13(i,j,k,e), dp)))
1410 scal = max(scal, abs(real(this%G23(i,j,k,e), dp)))
1411
1412 if (scal .le. 0.0_dp) then
1413 ndeg = ndeg + 1
1414 cycle
1415 end if
1416
1417 if (this%msh%gdim .eq. 2) then
1418 call eig_sym2(real(this%G11(i,j,k,e), dp) / scal, &
1419 real(this%G22(i,j,k,e), dp) / scal, &
1420 real(this%G12(i,j,k,e), dp) / scal, e1, e3)
1421 else
1422 call eig_sym3(real(this%G11(i,j,k,e), dp) / scal, &
1423 real(this%G22(i,j,k,e), dp) / scal, &
1424 real(this%G33(i,j,k,e), dp) / scal, &
1425 real(this%G12(i,j,k,e), dp) / scal, &
1426 real(this%G13(i,j,k,e), dp) / scal, &
1427 real(this%G23(i,j,k,e), dp) / scal, e1, e2, e3)
1428 end if
1429
1430 if (e3 .le. 0.0_dp) then
1431 ndeg = ndeg + 1
1432 else
1433 kmax = max(kmax, real(e1 / e3, rp))
1434
1435 ! Jacobi scale the metric: C_ij = G_ij/sqrt(G_ii G_jj).
1436 ! kappa(C) is what bounds the effect of rounding G to a
1437 ! lower precision, and unlike kappa(G) it is independent
1438 ! of the element aspect ratio. The point is positive
1439 ! definite here, so the diagonal is strictly positive and
1440 ! the square roots are safe. An orthogonal element gives
1441 ! the identity, which eig_sym3 returns exactly through
1442 ! its isotropic branch.
1443 c12 = real(this%G12(i,j,k,e), dp) &
1444 / sqrt(real(this%G11(i,j,k,e), dp) &
1445 * real(this%G22(i,j,k,e), dp))
1446
1447 if (this%msh%gdim .eq. 2) then
1448 call eig_sym2(1.0_dp, 1.0_dp, c12, c1, c3)
1449 else
1450 c13 = real(this%G13(i,j,k,e), dp) &
1451 / sqrt(real(this%G11(i,j,k,e), dp) &
1452 * real(this%G33(i,j,k,e), dp))
1453 c23 = real(this%G23(i,j,k,e), dp) &
1454 / sqrt(real(this%G22(i,j,k,e), dp) &
1455 * real(this%G33(i,j,k,e), dp))
1456 call eig_sym3(1.0_dp, 1.0_dp, 1.0_dp, &
1457 c12, c13, c23, c1, c2, c3)
1458 end if
1459
1460 if (c3 .gt. 0.0_dp) then
1461 kcmax = max(kcmax, real(c1 / c3, rp))
1462 else
1463 ! C is a positive diagonal congruence of a metric
1464 ! already found definite, so this is unreachable
1465 ! analytically. Fail safe rather than underreport.
1466 kcmax = huge(0.0_rp)
1467 end if
1468 end if
1469
1470 end do
1471 end do
1472 end do
1473 end do
1474
1475 tmp(1) = kmax
1476 this%metric_cond = glmax(tmp, 1)
1477
1478 tmp(1) = kcmax
1479 this%metric_scaled_cond = glmax(tmp, 1)
1480
1481 call mpi_allreduce(ndeg, ndeg_glb, 1, mpi_integer, mpi_sum, &
1482 neko_comm, ierr)
1483 this%metric_degenerate = ndeg_glb
1484
1485 ! The two condition numbers enter through different unit roundoffs, so
1486 ! the estimate is additive: storage rounding of G contributes
1487 ! eps_sp*kappa(C) and accumulation in rp contributes eps_rp*kappa(G).
1488 ! On a double build the second term all but vanishes and skew decides; on
1489 ! an rp = sp build it dominates and aspect ratio decides. No test on the
1490 ! build is needed, which is the point of writing it this way.
1491 this%metric_perturb = real(neko_eps_sp, rp) * this%metric_scaled_cond &
1492 + neko_eps * this%metric_cond
1493
1494 this%metric_sp_safe = (this%metric_degenerate .eq. 0) .and. &
1495 (this%metric_perturb .le. neko_metric_perturb_max)
1496
1497 write(log_buf, '(A,ES12.5)') 'Metric condition : ', this%metric_cond
1498 call neko_log%message(log_buf)
1499 write(log_buf, '(A,ES12.5)') 'Metric skew cond : ', &
1500 this%metric_scaled_cond
1501 call neko_log%message(log_buf)
1502 write(log_buf, '(A,ES12.5)') 'Metric perturb : ', this%metric_perturb
1503 call neko_log%message(log_buf)
1504 write(log_buf, '(A,L1)') 'Metric fp32 safe : ', this%metric_sp_safe
1505 call neko_log%message(log_buf)
1506
1507 ! Three independent questions, reported independently: can the solve
1508 ! break down, how far wrong is the operator, and is the mesh valid at
1509 ! all. They are not grades of one thing, so none suppresses another -- a
1510 ! wall resolved boundary layer in a single precision build trips the
1511 ! first two at once, and both are worth saying, because the definiteness
1512 ! limit is a possibility while the perturbation is a certainty.
1513
1514 ! Past the arithmetic limit the local operator can lose positive
1515 ! definiteness and a Krylov solve can break down rather than degrade,
1516 ! which is only reachable when rp is sp. Reported rather than fatal: the
1517 ! threshold keeps three orders of margin below 1/eps_sp, so crossing it
1518 ! makes breakdown possible, not certain, and the run may well be fine.
1519 if (rp .eq. sp .and. this%metric_cond .gt. neko_metric_cond_sp) then
1520 write(log_buf, '(A,ES12.5)') &
1521 'Metric too ill conditioned for single precision, limit ', &
1523 call neko_log%warning(log_buf)
1524 call neko_log%message('Geometric factors may lose positive ' // &
1525 'definiteness, consider a double precision build')
1526 end if
1527
1528 ! How much the single precision factors actually perturb the operator,
1529 ! regardless of whether the definiteness limit above was also crossed.
1530 ! On a single precision build that error is being incurred now, so it
1531 ! warrants a warning; on a double precision build it describes a storage
1532 ! path that may not be in use, so it is recorded without one. Which of
1533 ! the two terms dominates is the actionable part: skew is a meshing
1534 ! problem, aspect ratio is a precision problem, and they have different
1535 ! remedies.
1536 if (this%metric_perturb .gt. neko_metric_perturb_max) then
1537 if (rp .eq. sp) then
1538 write(log_buf, '(A,ES12.5,A,ES12.5)') &
1539 'Single precision metric error ', this%metric_perturb, &
1540 ', tolerance ', neko_metric_perturb_max
1541 call neko_log%warning(log_buf)
1542 else
1543 call neko_log%message('Single precision storage of the ' // &
1544 'geometric factors would exceed the error tolerance')
1545 end if
1546
1547 if (real(neko_eps_sp, rp) * this%metric_scaled_cond .ge. &
1548 neko_eps * this%metric_cond) then
1549 call neko_log%message('Dominated by element skew')
1550 else
1551 call neko_log%message('Dominated by element aspect ratio')
1552 end if
1553 end if
1554
1555 ! A metric that is not positive definite is a degenerate or inverted
1556 ! element, which is a mesh problem in any precision. Reported rather than
1557 ! fatal, since this is a diagnostic and the rest of the setup may still
1558 ! want to run
1559 if (this%metric_degenerate .gt. 0) then
1560 write(log_buf, '(A,I0)') &
1561 'Non positive definite metric at points: ', this%metric_degenerate
1562 call neko_log%error(log_buf)
1563 end if
1564
1565 end subroutine coef_metric_condition
1566
1577 subroutine coef_enable_geo_compression(this, tol)
1578 class(coef_t), intent(inout) :: this
1579 real(kind=rp), intent(in), optional :: tol
1580
1581 if (.not. this%coef_metrics_initialized) then
1582 call neko_error('Geometric factors must be generated before they ' // &
1583 'are compressed')
1584 end if
1585
1586 if (present(tol)) then
1587 if (tol .lt. 0.0_rp) then
1588 call neko_error('Geometric factor compression tolerance must ' // &
1589 'be non-negative')
1590 end if
1591 end if
1592
1593 if (neko_bcknd_xsmm .eq. 1) then
1594 if (this%scope .eq. coef_full) then
1595 call neko_log%section('Compressed G')
1596 call neko_log%message('Not built for the XSMM backend')
1597 call neko_log%end_section()
1598 end if
1599 return
1600 end if
1601
1602 this%geo_compression_tol = 1.0e-7_rp
1603 if (present(tol)) then
1604 this%geo_compression_tol = tol
1605 end if
1606
1607 this%geo_compression = .true.
1608 call coef_generate_geo_compr(this, this%scope .eq. coef_full)
1609
1610 end subroutine coef_enable_geo_compression
1611
1621 subroutine coef_generate_geo_compr(c, verbose)
1622 type(coef_t), intent(inout) :: c
1623 logical, intent(in) :: verbose
1624 integer :: e, m, i, lxyz, m_max, ierr, n
1625 integer, allocatable :: c_inds_rev(:) ! reverse compression indices map
1626 integer :: stats(2), glb_stats(2)
1627 real(kind=rp) :: ctol, diff
1628 character(len=LOG_SIZE) :: log_buf
1629
1630 call coef_free_geo_compr(c)
1631
1632 ! On a device backend the host factors are only current after
1633 ! initialization, while recompute_metrics() updates the device ones
1634 if (neko_bcknd_device .eq. 1) then
1635 n = c%dof%size()
1636 call device_memcpy(c%G11, c%G11_d, n, device_to_host, sync = .false.)
1637 call device_memcpy(c%G22, c%G22_d, n, device_to_host, sync = .false.)
1638 call device_memcpy(c%G33, c%G33_d, n, device_to_host, sync = .false.)
1639 call device_memcpy(c%G12, c%G12_d, n, device_to_host, sync = .false.)
1640 call device_memcpy(c%G13, c%G13_d, n, device_to_host, sync = .false.)
1641 call device_memcpy(c%G23, c%G23_d, n, device_to_host, sync = .true.)
1642 end if
1643
1644 ctol = c%geo_compression_tol
1645 diff = 0.0_rp
1646
1647 ! First step, allocate full-size lookup structure for entire mesh
1648 allocate(c%compression_inds(c%msh%nelv))
1649 allocate(c_inds_rev(c%msh%nelv))
1650
1651 ! Second step, loop over all elements, compute compression mapping
1652 ! First entry must be itself to get started
1653 m_max = 0
1654 if (c%msh%nelv .gt. 0) then
1655 m_max = 1
1656 c%compression_inds(1) = 1
1657 c_inds_rev = 0
1658 c_inds_rev(1) = 1
1659 end if
1660
1661 ! Loop over elements, but skip first
1662 lxyz = c%Xh%lx * c%Xh%ly * c%Xh%lz
1663 do e = 2, c%msh%nelv
1664 ! Loop over possible compression candidates
1665 do m = 1, m_max
1666 diff = 0.0_rp
1667 ! Loop over quadrature points
1668 do i = 1, lxyz
1669 ! diff += abs( \| G(i,:,:,e) - G(i,:,:,reverse(m)) \|_l1 )
1670 diff = diff + abs(c%G11(i,1,1,e) - c%G11(i,1,1,c_inds_rev(m))) &
1671 + 2.0_rp*abs(c%G12(i,1,1,e) - c%G12(i,1,1,c_inds_rev(m))) &
1672 + 2.0_rp*abs(c%G13(i,1,1,e) - c%G13(i,1,1,c_inds_rev(m))) &
1673 + abs(c%G22(i,1,1,e) - c%G22(i,1,1,c_inds_rev(m))) &
1674 + 2.0_rp*abs(c%G23(i,1,1,e) - c%G23(i,1,1,c_inds_rev(m))) &
1675 + abs(c%G33(i,1,1,e) - c%G33(i,1,1,c_inds_rev(m)))
1676 end do
1677
1678 ! match is found; mapping(e) is redundant
1679 if ( diff .le. ctol ) then
1680 c%compression_inds(e) = m
1681 exit
1682 end if
1683 end do
1684
1685 ! never found a match, written so that a NaN never matches either
1686 if (.not. (diff .le. ctol)) then
1687 m_max = m_max + 1
1688 c%compression_inds(e) = m_max
1689 c_inds_rev(m_max) = e
1690 end if
1691 end do
1692
1693 ! Third step, allocate and fill Gij_compr objects
1694 allocate(c%G11_compr(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1695 allocate(c%G22_compr(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1696 allocate(c%G33_compr(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1697 allocate(c%G12_compr(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1698 allocate(c%G13_compr(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1699 allocate(c%G23_compr(c%Xh%lx, c%Xh%ly, c%Xh%lz, m_max))
1700 do m = 1, m_max
1701 do i = 1, lxyz
1702 c%G11_compr(i,1,1,m) = c%G11(i,1,1,c_inds_rev(m))
1703 c%G22_compr(i,1,1,m) = c%G22(i,1,1,c_inds_rev(m))
1704 c%G33_compr(i,1,1,m) = c%G33(i,1,1,c_inds_rev(m))
1705 c%G12_compr(i,1,1,m) = c%G12(i,1,1,c_inds_rev(m))
1706 c%G13_compr(i,1,1,m) = c%G13(i,1,1,c_inds_rev(m))
1707 c%G23_compr(i,1,1,m) = c%G23(i,1,1,c_inds_rev(m))
1708 end do
1709 end do
1710
1711 deallocate(c_inds_rev)
1712
1713 if (neko_bcknd_device .eq. 1) then
1714 n = lxyz * m_max
1715 call device_map(c%G11_compr, c%G11_compr_d, n)
1716 call device_map(c%G22_compr, c%G22_compr_d, n)
1717 call device_map(c%G33_compr, c%G33_compr_d, n)
1718 call device_map(c%G12_compr, c%G12_compr_d, n)
1719 call device_map(c%G13_compr, c%G13_compr_d, n)
1720 call device_map(c%G23_compr, c%G23_compr_d, n)
1721 call device_map(c%compression_inds, c%compression_inds_d, c%msh%nelv)
1722 call device_memcpy(c%G11_compr, c%G11_compr_d, n, host_to_device, &
1723 sync = .false.)
1724 call device_memcpy(c%G22_compr, c%G22_compr_d, n, host_to_device, &
1725 sync = .false.)
1726 call device_memcpy(c%G33_compr, c%G33_compr_d, n, host_to_device, &
1727 sync = .false.)
1728 call device_memcpy(c%G12_compr, c%G12_compr_d, n, host_to_device, &
1729 sync = .false.)
1730 call device_memcpy(c%G13_compr, c%G13_compr_d, n, host_to_device, &
1731 sync = .false.)
1732 call device_memcpy(c%G23_compr, c%G23_compr_d, n, host_to_device, &
1733 sync = .false.)
1734 call device_memcpy(c%compression_inds, c%compression_inds_d, &
1735 c%msh%nelv, host_to_device, sync = .true.)
1736 end if
1737
1738 if (verbose) then
1739 stats(1) = c%msh%nelv
1740 stats(2) = m_max
1741 call mpi_allreduce(stats, glb_stats, 2, mpi_integer, mpi_sum, &
1742 neko_comm, ierr)
1743
1744 call neko_log%section('Compressed G')
1745 write(log_buf, '(A,I0)') 'Copies : ', glb_stats(2)
1746 call neko_log%message(log_buf)
1747 write(log_buf, '(A,I0)') 'Elements : ', glb_stats(1)
1748 call neko_log%message(log_buf)
1749 write(log_buf, '(A,ES12.5)') 'Tolerance : ', ctol
1750 call neko_log%message(log_buf)
1751 call neko_log%end_section()
1752 end if
1753
1754 end subroutine coef_generate_geo_compr
1755
1758 type(coef_t), intent(inout) :: c
1759
1760 if (allocated(c%compression_inds)) then
1761 if (neko_bcknd_device .eq. 1) then
1762 call device_unmap(c%compression_inds, c%compression_inds_d)
1763 end if
1764 deallocate(c%compression_inds)
1765 end if
1766
1767 if (allocated(c%G11_compr)) then
1768 if (neko_bcknd_device .eq. 1) then
1769 call device_unmap(c%G11_compr, c%G11_compr_d)
1770 end if
1771 deallocate(c%G11_compr)
1772 end if
1773
1774 if (allocated(c%G22_compr)) then
1775 if (neko_bcknd_device .eq. 1) then
1776 call device_unmap(c%G22_compr, c%G22_compr_d)
1777 end if
1778 deallocate(c%G22_compr)
1779 end if
1780
1781 if (allocated(c%G33_compr)) then
1782 if (neko_bcknd_device .eq. 1) then
1783 call device_unmap(c%G33_compr, c%G33_compr_d)
1784 end if
1785 deallocate(c%G33_compr)
1786 end if
1787
1788 if (allocated(c%G12_compr)) then
1789 if (neko_bcknd_device .eq. 1) then
1790 call device_unmap(c%G12_compr, c%G12_compr_d)
1791 end if
1792 deallocate(c%G12_compr)
1793 end if
1794
1795 if (allocated(c%G13_compr)) then
1796 if (neko_bcknd_device .eq. 1) then
1797 call device_unmap(c%G13_compr, c%G13_compr_d)
1798 end if
1799 deallocate(c%G13_compr)
1800 end if
1801
1802 if (allocated(c%G23_compr)) then
1803 if (neko_bcknd_device .eq. 1) then
1804 call device_unmap(c%G23_compr, c%G23_compr_d)
1805 end if
1806 deallocate(c%G23_compr)
1807 end if
1808
1809
1810 end subroutine coef_free_geo_compr
1811
1815 type(coef_t), intent(inout) :: c
1816 integer :: e, i, lxyz, ntot
1817
1818 lxyz = c%Xh%lx * c%Xh%ly * c%Xh%lz
1819 ntot = c%dof%size()
1820
1821 if (neko_bcknd_device .eq. 1) then
1822 call device_coef_generate_mass(c%B_d, c%Binv_d, c%jac_d, c%Xh%w3_d, &
1823 lxyz, c%msh%nelv)
1824 ! copy to host only at initialization.
1825 if (.not. c%coef_metrics_initialized) then
1826 ! Under COEF_OPERATOR the Binv transfer below is skipped, so this
1827 ! becomes the last one of the routine and has to synchronise.
1828 call device_memcpy(c%B, c%B_d, ntot, device_to_host, &
1829 sync = (c%scope .eq. coef_operator))
1830 end if
1831 else
1832 !$omp parallel do private(e, i)
1833 do e = 1, c%msh%nelv
1834 ! Here we need to handle things differently for axis symmetric elements
1835 do i = 1, lxyz
1836 c%B(i,1,1,e) = c%jac(i,1,1,e) * c%Xh%w3(i,1,1)
1837 c%Binv(i,1,1,e) = c%B(i,1,1,e)
1838 end do
1839 end do
1840 !$omp end parallel do
1841 end if
1842
1843 ! Neither Binv nor the volume is read when only applying an operator,
1844 ! and assembling Binv costs a gather-scatter round on top of that.
1845 if (c%scope .ne. coef_full) return
1846
1847 call c%gs_h%op(c%Binv, ntot, gs_op_add)
1848
1849 if (neko_bcknd_device .eq. 1) then
1850 call device_invcol1(c%Binv_d, ntot)
1851 ! copy to host only at initialization.
1852 if (.not. c%coef_metrics_initialized) then
1853 call device_memcpy(c%Binv, c%Binv_d, ntot, &
1854 device_to_host, sync = .true.)
1855 end if
1856 else
1857 call invcol1(c%Binv, ntot)
1858 end if
1859
1861 if (neko_bcknd_device .eq. 1) then
1862 c%volume = device_glsum(c%B_d, ntot)
1863 else
1864 c%volume = glsum(c%B, ntot)
1865 end if
1866
1867 end subroutine coef_generate_mass
1868
1878 subroutine coef_require_facets(this, who)
1879 class(coef_t), intent(in) :: this
1880 character(len=*), intent(in) :: who
1881
1882 if (this%scope .ne. coef_full) then
1883 call neko_error(who // ' needs the facet areas and normals, which ' // &
1884 'a COEF_OPERATOR coef does not build')
1885 end if
1886
1887 end subroutine coef_require_facets
1888
1893 pure function coef_get_normal(this, i, j, k, e, facet) result(normal)
1894 class(coef_t), intent(in) :: this
1895 integer, intent(in) :: i, j, k, e, facet
1896 real(kind=rp) :: normal(3)
1897
1898 select case (facet)
1899 case (1, 2)
1900 normal(1) = this%nx(j, k, facet, e)
1901 normal(2) = this%ny(j, k, facet, e)
1902 normal(3) = this%nz(j, k, facet, e)
1903 case (3, 4)
1904 normal(1) = this%nx(i, k, facet, e)
1905 normal(2) = this%ny(i, k, facet, e)
1906 normal(3) = this%nz(i, k, facet, e)
1907 case (5, 6)
1908 normal(1) = this%nx(i, j, facet, e)
1909 normal(2) = this%ny(i, j, facet, e)
1910 normal(3) = this%nz(i, j, facet, e)
1911 end select
1912 end function coef_get_normal
1913
1917 pure function coef_get_area(this, i, j, k, e, facet) result(area)
1918 class(coef_t), intent(in) :: this
1919 integer, intent(in) :: i, j, k, e, facet
1920 real(kind=rp) :: area
1921
1922 select case (facet)
1923 case (1, 2)
1924 area = this%area(j, k, facet, e)
1925 case (3, 4)
1926 area = this%area(i, k, facet, e)
1927 case (5, 6)
1928 area = this%area(i, j, facet, e)
1929 end select
1930 end function coef_get_area
1931
1932
1935 type(coef_t), intent(inout) :: coef
1936 real(kind=rp), allocatable :: a(:,:,:,:)
1937 real(kind=rp), allocatable :: b(:,:,:,:)
1938 real(kind=rp), allocatable :: c(:,:,:,:)
1939 real(kind=rp), allocatable :: dot(:,:,:,:)
1940 integer :: n, m, e, i, j, k, lx
1941 real(kind=rp) :: weight, len
1942 n = coef%dof%size()
1943 lx = coef%Xh%lx
1944
1945 if (neko_bcknd_device .eq. 1) then
1946
1947 call device_coef_generate_area_and_normal( &
1948 coef%area_d, coef%nx_d, coef%ny_d, coef%nz_d, &
1949 coef%dxdr_d, coef%dydr_d, coef%dzdr_d, &
1950 coef%dxds_d, coef%dyds_d, coef%dzds_d, &
1951 coef%dxdt_d, coef%dydt_d, coef%dzdt_d, &
1952 coef%Xh%wx_d, coef%Xh%wy_d, coef%Xh%wz_d, &
1953 lx, coef%msh%nelv, neko_eps)
1954
1955 ! Here, we always copy back to host.
1956 m = size(coef%area)
1957 call device_memcpy(coef%area, coef%area_d, m, &
1958 device_to_host, sync = .false.)
1959 call device_memcpy(coef%nx, coef%nx_d, m, &
1960 device_to_host, sync = .false.)
1961 call device_memcpy(coef%ny, coef%ny_d, m, &
1962 device_to_host, sync = .false.)
1963 call device_memcpy(coef%nz, coef%nz_d, &
1964 m, device_to_host, sync = .true.)
1965
1966 else
1967
1968 allocate(a(coef%Xh%lx, coef%Xh%lx, coef%Xh%lx, coef%msh%nelv))
1969 allocate(b(coef%Xh%lx, coef%Xh%lx, coef%Xh%lx, coef%msh%nelv))
1970 allocate(c(coef%Xh%lx, coef%Xh%lx, coef%Xh%lx, coef%msh%nelv))
1971 allocate(dot(coef%Xh%lx, coef%Xh%lx, coef%Xh%lx, coef%msh%nelv))
1972
1973 !$omp parallel private (e, i, j, k, weight, len)
1974
1975 ! ds x dt
1976 !$omp do simd
1977 do i = 1, n
1978 a(i, 1, 1, 1) = coef%dyds(i, 1, 1, 1) * coef%dzdt(i, 1, 1, 1) &
1979 - coef%dzds(i, 1, 1, 1) * coef%dydt(i, 1, 1, 1)
1980
1981 b(i, 1, 1, 1) = coef%dzds(i, 1, 1, 1) * coef%dxdt(i, 1, 1, 1) &
1982 - coef%dxds(i, 1, 1, 1) * coef%dzdt(i, 1, 1, 1)
1983
1984 c(i, 1, 1, 1) = coef%dxds(i, 1, 1, 1) * coef%dydt(i, 1, 1, 1) &
1985 - coef%dyds(i, 1, 1, 1) * coef%dxdt(i, 1, 1, 1)
1986 end do
1987 !$omp end do simd
1988 !$omp do simd
1989 do i = 1, n
1990 dot(i, 1, 1, 1) = a(i, 1, 1, 1) * a(i, 1, 1, 1) &
1991 + b(i, 1, 1, 1) * b(i, 1, 1, 1) &
1992 + c(i, 1, 1, 1) * c(i, 1, 1, 1)
1993 end do
1994 !$omp end do simd
1995 !$omp do
1996 do e = 1, coef%msh%nelv
1997 do concurrent(k = 1:coef%Xh%lx)
1998 do concurrent(j = 1:coef%Xh%lx)
1999 weight = coef%Xh%wy(j) * coef%Xh%wz(k)
2000 coef%area(j, k, 2, e) = sqrt(dot(lx, j, k, e)) * weight
2001 coef%area(j, k, 1, e) = sqrt(dot(1, j, k, e)) * weight
2002 coef%nx(j,k, 1, e) = -a(1, j, k, e)
2003 coef%nx(j,k, 2, e) = a(lx, j, k, e)
2004 coef%ny(j,k, 1, e) = -b(1, j, k, e)
2005 coef%ny(j,k, 2, e) = b(lx, j, k, e)
2006 coef%nz(j,k, 1, e) = -c(1, j, k, e)
2007 coef%nz(j,k, 2, e) = c(lx, j, k, e)
2008 end do
2009 end do
2010 end do
2011 !$omp end do
2012
2013 ! dr x dt
2014 !$omp do simd
2015 do i = 1, n
2016 a(i, 1, 1, 1) = coef%dydr(i, 1, 1, 1) * coef%dzdt(i, 1, 1, 1) &
2017 - coef%dzdr(i, 1, 1, 1) * coef%dydt(i, 1, 1, 1)
2018
2019 b(i, 1, 1, 1) = coef%dzdr(i, 1, 1, 1) * coef%dxdt(i, 1, 1, 1) &
2020 - coef%dxdr(i, 1, 1, 1) * coef%dzdt(i, 1, 1, 1)
2021
2022 c(i, 1, 1, 1) = coef%dxdr(i, 1, 1, 1) * coef%dydt(i, 1, 1, 1) &
2023 - coef%dydr(i, 1, 1, 1) * coef%dxdt(i, 1, 1, 1)
2024 end do
2025 !$omp end do simd
2026 !$omp do simd
2027 do i = 1, n
2028 dot(i, 1, 1, 1) = a(i, 1, 1, 1) * a(i, 1, 1, 1) &
2029 + b(i, 1, 1, 1) * b(i, 1, 1, 1) &
2030 + c(i, 1, 1, 1) * c(i, 1, 1, 1)
2031 end do
2032 !$omp end do simd
2033 !$omp do
2034 do e = 1, coef%msh%nelv
2035 do concurrent(k = 1:coef%Xh%lx)
2036 do concurrent(j = 1:coef%Xh%lx)
2037 weight = coef%Xh%wx(j) * coef%Xh%wz(k)
2038 coef%area(j, k, 3, e) = sqrt(dot(j, 1, k, e)) * weight
2039 coef%area(j, k, 4, e) = sqrt(dot(j, lx, k, e)) * weight
2040 coef%nx(j,k, 3, e) = a(j, 1, k, e)
2041 coef%nx(j,k, 4, e) = -a(j, lx, k, e)
2042 coef%ny(j,k, 3, e) = b(j, 1, k, e)
2043 coef%ny(j,k, 4, e) = -b(j, lx, k, e)
2044 coef%nz(j,k, 3, e) = c(j, 1, k, e)
2045 coef%nz(j,k, 4, e) = -c(j, lx, k, e)
2046 end do
2047 end do
2048 end do
2049 !$omp end do
2050 ! dr x ds
2051 !$omp do simd
2052 do i = 1, n
2053 a(i, 1, 1, 1) = coef%dydr(i, 1, 1, 1) * coef%dzds(i, 1, 1, 1) &
2054 - coef%dzdr(i, 1, 1, 1) * coef%dyds(i, 1, 1, 1)
2055
2056 b(i, 1, 1, 1) = coef%dzdr(i, 1, 1, 1) * coef%dxds(i, 1, 1, 1) &
2057 - coef%dxdr(i, 1, 1, 1) * coef%dzds(i, 1, 1, 1)
2058
2059 c(i, 1, 1, 1) = coef%dxdr(i, 1, 1, 1) * coef%dyds(i, 1, 1, 1) &
2060 - coef%dydr(i, 1, 1, 1) * coef%dxds(i, 1, 1, 1)
2061 end do
2062 !$omp end do simd
2063 !$omp do simd
2064 do i = 1, n
2065 dot(i, 1, 1, 1) = a(i, 1, 1, 1) * a(i, 1, 1, 1) &
2066 + b(i, 1, 1, 1) * b(i, 1, 1, 1) &
2067 + c(i, 1, 1, 1) * c(i, 1, 1, 1)
2068 end do
2069 !$omp end do simd
2070 !$omp do
2071 do e = 1, coef%msh%nelv
2072 do concurrent(k = 1:coef%Xh%lx)
2073 do concurrent(j = 1:coef%Xh%lx)
2074 weight = coef%Xh%wx(j) * coef%Xh%wy(k)
2075 coef%area(j, k, 5, e) = sqrt(dot(j, k, 1, e)) * weight
2076 coef%area(j, k, 6, e) = sqrt(dot(j, k, lx, e)) * weight
2077 coef%nx(j,k, 5, e) = -a(j, k, 1, e)
2078 coef%nx(j,k, 6, e) = a(j, k, lx, e)
2079 coef%ny(j,k, 5, e) = -b(j, k, 1, e)
2080 coef%ny(j,k, 6, e) = b(j, k, lx, e)
2081 coef%nz(j,k, 5, e) = -c(j, k, 1, e)
2082 coef%nz(j,k, 6, e) = c(j, k, lx, e)
2083 end do
2084 end do
2085 end do
2086 !$omp end do
2087 ! Normalize
2088 !$omp do
2089 do j = 1, size(coef%nz)
2090 len = sqrt(coef%nx(j,1,1,1)**2 + &
2091 coef%ny(j,1,1,1)**2 + coef%nz(j,1,1,1)**2)
2092 if (len .gt. neko_eps) then
2093 coef%nx(j,1,1,1) = coef%nx(j,1,1,1) / len
2094 coef%ny(j,1,1,1) = coef%ny(j,1,1,1) / len
2095 coef%nz(j,1,1,1) = coef%nz(j,1,1,1) / len
2096 end if
2097 end do
2098 !$omp end do
2099 !$omp end parallel
2100
2101 deallocate(dot)
2102 deallocate(c)
2103 deallocate(b)
2104 deallocate(a)
2105
2106 end if
2107
2108 end subroutine coef_generate_area_and_normal
2109
2111 class(coef_t), intent(inout) :: this
2112 real(kind=rp) :: un(3), len, d
2113 integer :: lx, ly, lz, np, np_glb, ierr
2114 integer :: i, j, k, pf, pe, n, nc, ncyc
2115
2116 if (.not. this%cyclic) return
2117
2118 ! Builds the rotation matrices from get_normal()
2119 if (this%scope .ne. coef_full) then
2120 call neko_error('Cyclic boundaries need the facet normals, ' // &
2121 'which COEF_OPERATOR does not build')
2122 end if
2123
2124 np = this%msh%periodic%size
2125 call mpi_allreduce(np, np_glb, 1, &
2126 mpi_integer, mpi_sum, neko_comm, ierr)
2127
2128 if (np_glb .eq. 0) then
2129 call neko_error("There are no periodic boundaries. " // &
2130 "Switch cyclic off in the case file.")
2131 end if
2132
2133 if (np .eq. 0) return
2134
2135 lx = this%Xh%lx
2136 ly = this%Xh%ly
2137 lz = this%Xh%lz
2138 ncyc = this%cyc_msk(0) - 1
2139 nc = 1
2140 do n = 1, np
2141 pf = this%msh%periodic%facet_el(n)%x(1)
2142 pe = this%msh%periodic%facet_el(n)%x(2)
2143 do k = 1, lz
2144 do j = 1, ly
2145 do i = 1, lx
2146 if (index_is_on_facet(i, j, k, lx, ly, lz, pf)) then
2147 un = this%get_normal(i, j, k, pe, pf)
2148 len = sqrt(un(1) * un(1) + un(2) * un(2))
2149 if (len .gt. neko_eps) then
2150 d = this%dof%y%x(i, j, k, pe) * un(1) &
2151 - this%dof%x%x(i, j, k, pe) * un(2)
2152
2153 this%cyc_msk(nc) = linear_index(i, j, k, pe, lx, ly, lz)
2154 this%R11(nc) = un(1) / len * sign(1.0_rp, d)
2155 this%R12(nc) = un(2) / len * sign(1.0_rp, d)
2156 nc = nc + 1
2157 else
2158 call neko_error("x and y components of surface " // &
2159 "normals are zero. Cyclic rotations must be " // &
2160 "around z-axis.")
2161 end if
2162 end if
2163 end do
2164 end do
2165 end do
2166 end do
2167
2168 if (nc - 1 /= ncyc) then
2169 call neko_error("The number of cyclic GLL points were " // &
2170 "not estimated correctly.")
2171 end if
2172
2173 if (neko_bcknd_device .eq. 1) then
2174 call device_memcpy(this%cyc_msk, this%cyc_msk_d, ncyc+1, &
2175 host_to_device, sync = .false.)
2176 call device_memcpy(this%R11, this%R11_d, ncyc, &
2177 host_to_device, sync = .false.)
2178 call device_memcpy(this%R12, this%R12_d, ncyc, &
2179 host_to_device, sync = .false.)
2180 end if
2181
2182 end subroutine coef_generate_cyclic_bc
2183
2184
2186 subroutine coef_recompute_metrics(this)
2187 class(coef_t), intent(inout) :: this
2188
2189 if (this%scope .ne. coef_full) then
2190 call neko_error('Rebuilding the geometry needs the derivative ' // &
2191 'arrays, which COEF_OPERATOR releases')
2192 end if
2193
2194 call coef_generate_dxyzdrst(this)
2195 call coef_generate_geo(this)
2196 if (this%geo_compression) then
2197 call coef_generate_geo_compr(this, .false.)
2198 end if
2200 call coef_generate_mass(this)
2201 if (this%cyclic) then
2202 call coef_generate_cyclic_bc(this)
2203 end if
2204 this%metrics_version = this%metrics_version + 1
2205 end subroutine coef_recompute_metrics
2206
2207
2211 class(coef_t), intent(inout), target :: this
2212 integer :: n
2213
2214 ! Return if already allocated distinctly
2215 if (.not. associated(this%Blag, this%B)) return
2216
2217 n = this%Xh%lx * this%Xh%ly * this%Xh%lz * this%msh%nelv
2218
2219
2220 nullify(this%Blag)
2221 nullify(this%Blaglag)
2222
2223 allocate(this%Blag(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
2224 allocate(this%Blaglag(this%Xh%lx, this%Xh%ly, this%Xh%lz, this%msh%nelv))
2225
2226 this%Blag = this%B
2227 this%Blaglag = this%B
2228
2229 if (neko_bcknd_device .eq. 1) then
2230
2231 this%Blag_d = c_null_ptr
2232 this%Blaglag_d = c_null_ptr
2233
2234 call device_map(this%Blag, this%Blag_d, n)
2235 call device_map(this%Blaglag, this%Blaglag_d, n)
2236
2237 call device_memcpy(this%Blag, this%Blag_d, n, &
2238 host_to_device, sync = .false.)
2239 call device_memcpy(this%Blaglag, this%Blaglag_d, n, &
2240 host_to_device, sync = .true.)
2241 end if
2242
2243 end subroutine coef_enable_lagged_mass
2244
2245
2248 class(coef_t), intent(inout), target :: this
2249 integer :: n
2250
2251 ! If this%Blag does not have separate memory, we don't need to update it.
2252 if (associated(this%Blag, this%B)) return
2253 n = this%Xh%lx * this%Xh%ly * this%Xh%lz * this%msh%nelv
2254 if (neko_bcknd_device .eq. 1) then
2255 call device_copy(this%Blaglag_d, this%Blag_d, n)
2256 call device_copy(this%Blag_d, this%B_d, n)
2257 else
2258 this%Blaglag = this%Blag
2259 this%Blag = this%B
2260 end if
2261
2262 end subroutine coef_update_lagged_mass
2263
2264end 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:119
subroutine coef_generate_geo(c)
Generate geometric data for the given mesh.
Definition coef.f90:1181
subroutine coef_free_geo_compr(c)
Release the compressed geometric factors.
Definition coef.f90:1758
subroutine coef_free(this)
Deallocate coefficients.
Definition coef.f90:604
subroutine coef_generate_geo_compr(c, verbose)
Compute processor-local compressed versions of mappings Gij.
Definition coef.f90:1622
subroutine coef_release_scratch(this)
Release the coefficients that COEF_OPERATOR does not retain.
Definition coef.f90:858
integer, parameter, public coef_operator
Retain only what applying a discrete operator needs: , h1, h2, B and mult.
Definition coef.f90:132
subroutine coef_recompute_metrics(this)
Recompute and update geometric factors (ALE)
Definition coef.f90:2187
pure real(kind=rp) function coef_get_area(this, i, j, k, e, facet)
Facet area at a point.
Definition coef.f90:1918
subroutine coef_enable_geo_compression(this, tol)
Enable compressed geometric factors.
Definition coef.f90:1578
pure real(kind=rp) function, dimension(3) coef_get_normal(this, i, j, k, e, facet)
Facet normal at a point.
Definition coef.f90:1894
subroutine coef_init_all(this, gs_h, scope)
Initialize coefficients.
Definition coef.f90:377
subroutine coef_update_lagged_mass(this)
Update history: Blaglag = Blag, Blag = B.
Definition coef.f90:2248
subroutine coef_generate_dxyzdrst(c)
Definition coef.f90:992
subroutine coef_generate_area_and_normal(coef)
Generate facet area and surface normals.
Definition coef.f90:1935
subroutine coef_init_empty(this, xh, msh)
Initialize empty coefs for a space and a mesh.
Definition coef.f90:328
real(kind=rp), parameter, public neko_metric_perturb_max
Largest predicted relative perturbation of the element Helmholtz operator, in its own energy norm,...
Definition coef.f90:114
subroutine coef_metric_condition(this)
Compute the metric tensor condition numbers over the mesh.
Definition coef.f90:1368
subroutine coef_enable_lagged_mass(this)
Enable separate memory for lagged B matrices if needed. For eg. when mesh moves.
Definition coef.f90:2211
subroutine coef_require_facets(this, who)
Abort unless this coef holds the facet areas and normals.
Definition coef.f90:1879
real(kind=rp), parameter, public neko_metric_cond_sp
Largest metric condition number for which single precision arithmetic on the geometric factors is co...
Definition coef.f90:80
subroutine coef_generate_cyclic_bc(this)
Definition coef.f90:2111
subroutine coef_generate_mass(c)
Generate mass matrix B for the given mesh and space.
Definition coef.f90:1815
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:92
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:2003
subroutine, public invers2(a, b, n)
Compute inverted vector .
Definition math.f90:839
pure subroutine, public eig_sym2(a11, a22, a12, e1, e2)
Eigenvalues of a symmetric 2x2 matrix, descending.
Definition math.f90:1952
subroutine, public subcol3(a, b, c, n)
Returns .
Definition math.f90:1116
subroutine, public rone(a, n)
Set all elements to one.
Definition math.f90:281
real(kind=rp) function, public glsum(a, n)
Sum a vector of length n.
Definition math.f90:633
subroutine, public addcol3(a, b, c, n)
Returns .
Definition math.f90:1203
subroutine, public invcol1(a, n)
Invert a vector .
Definition math.f90:810
subroutine, public chsign(a, n)
Change sign of vector .
Definition math.f90:750
real(kind=rp) function, public glmax(a, n)
Max of a vector of length n.
Definition math.f90:654
real(kind=sp), parameter, public neko_eps_sp
Definition math.f90:72
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:295
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:239
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_sx
integer, parameter neko_bcknd_device
integer, parameter neko_bcknd_opencl
integer, parameter neko_bcknd_xsmm
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
Defines a container for all statistics.
Utilities.
Definition utils.f90:35
pure logical function, public index_is_on_facet(i, j, k, lx, ly, lz, facet)
Definition utils.f90:353
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:328
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:136
Gather-scatter kernel.
The function space for the SEM solution fields.
Definition space.f90:64
#define max(a, b)
Definition tensor.cu:40