Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
dofmap.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!
35module dofmap
37 use mesh, only : mesh_t
38 use mask, only : mask_t
39 use space, only : space_t, gll
40 use tuple, only : tuple4_i4_t
41 use num_types, only : i4, i8, rp, xp
42 use utils, only : neko_error, neko_warning
43 use fast3d, only : fd_weights_full
44 use tensor, only : tensr3, tnsr2d_el, trsp, addtnsr
49 use element, only : element_t
50 use quad, only : quad_t
51 use hex, only : hex_t
53 use, intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr, c_associated
54 implicit none
55 private
56
57 type, public :: dofmap_t
58 integer(kind=i8), allocatable :: dof(:,:,:,:)
59 logical, allocatable :: shared_dof(:,:,:,:)
60 real(kind=rp), allocatable :: x(:,:,:,:)
61 real(kind=rp), allocatable :: y(:,:,:,:)
62 real(kind=rp), allocatable :: z(:,:,:,:)
63 integer, private :: ntot
64
65 type(mesh_t), pointer :: msh
66 type(mesh_t), allocatable :: msh_subset
67 type(space_t), pointer :: xh
68
69 !
70 ! Device pointers (if present)
71 !
72 type(c_ptr) :: x_d = c_null_ptr
73 type(c_ptr) :: y_d = c_null_ptr
74 type(c_ptr) :: z_d = c_null_ptr
75
76 contains
78 procedure, pass(this) :: init_from_mesh => dofmap_init
79 procedure, pass(this) :: init_from_dof => dofmap_init_and_map
80 generic :: init => init_from_mesh, init_from_dof
82 procedure, pass(this) :: free => dofmap_free
84 procedure, pass(this) :: size => dofmap_size
86 procedure, pass(this) :: subset_by_mask => dofmap_subset_by_mask
88 procedure, pass(this) :: global_size => dofmap_global_size
89 end type dofmap_t
90
91contains
92
96 subroutine dofmap_init(this, msh, Xh)
97 class(dofmap_t) :: this
98 type(mesh_t), target, intent(inout) :: msh
99 type(space_t), target, intent(inout) :: Xh
100
101 if ((msh%gdim .eq. 3 .and. xh%lz .eq. 1) .or. &
102 (msh%gdim .eq. 2 .and. xh%lz .gt. 1)) then
103 call neko_error("Invalid dimension of function space for the given mesh")
104 end if
105
106 call this%free()
107
108 this%msh => msh
109 this%Xh => xh
110
111 this%ntot = xh%lx* xh%ly * xh%lz * msh%nelv
112
113 !
114 ! Assign a unique id for all dofs
115 !
116
117 allocate(this%dof(xh%lx, xh%ly, xh%lz, msh%nelv))
118 allocate(this%shared_dof(xh%lx, xh%ly, xh%lz, msh%nelv))
119
120 this%dof = 0
121 this%shared_dof = .false.
122
124 if (msh%gdim .eq. 3) then
125 call dofmap_number_points(this)
126 call dofmap_number_edges(this)
127 call dofmap_number_faces(this)
128 else
129 call dofmap_number_points(this)
130 call dofmap_number_edges(this)
131 end if
132
133 !
134 ! Generate x,y,z-coordinates for all dofs
135 !
136
137 allocate(this%x(xh%lx, xh%ly, xh%lz, msh%nelv))
138 allocate(this%y(xh%lx, xh%ly, xh%lz, msh%nelv))
139 allocate(this%z(xh%lx, xh%ly, xh%lz, msh%nelv))
140
141 this%x = 0d0
142 this%y = 0d0
143 this%z = 0d0
145
146 call dofmap_generate_xyz(this)
147
148 if (neko_bcknd_device .eq. 1) then
149 call device_map(this%x, this%x_d, this%ntot)
150 call device_map(this%y, this%y_d, this%ntot)
151 call device_map(this%z, this%z_d, this%ntot)
152
153 call device_memcpy(this%x, this%x_d, this%ntot, &
154 host_to_device, sync = .false.)
155 call device_memcpy(this%y, this%y_d, this%ntot, &
156 host_to_device, sync = .false.)
157 call device_memcpy(this%z, this%z_d, this%ntot, &
158 host_to_device, sync = .false.)
159 end if
160
161 end subroutine dofmap_init
162
166 subroutine dofmap_init_and_map(this, dof, Xh)
167 class(dofmap_t) :: this
168 type(dofmap_t), target, intent(inout) :: dof
169 type(space_t), target, intent(inout) :: Xh
170 type(interpolator_t) :: interpolator
171
172 ! Initialize as usual
173 call this%init_from_mesh(dof%msh, xh)
174
175 ! Interpolate if needed
176 if (dof%Xh%lxyz .ne. this%Xh%lxyz) then
177 call interpolator%init(this%Xh, dof%Xh)
178
179 call interpolator%map(this%x, &
180 dof%x, &
181 this%msh%nelv, this%Xh)
182 call interpolator%map(this%y, &
183 dof%y, &
184 this%msh%nelv, this%Xh)
185 call interpolator%map(this%z, &
186 dof%z, &
187 this%msh%nelv, this%Xh)
188
189 call interpolator%free()
190
191 else
192 if (neko_bcknd_device .eq. 1) then
193 call device_copy(this%x_d, dof%x_d, this%ntot)
194 call device_copy(this%y_d, dof%y_d, this%ntot)
195 call device_copy(this%z_d, dof%z_d, this%ntot)
196 else
197 call copy(this%x, dof%x, this%ntot)
198 call copy(this%y, dof%y, this%ntot)
199 call copy(this%z, dof%z, this%ntot)
200 end if
201
202 end if
203
204 end subroutine dofmap_init_and_map
205
207 subroutine dofmap_free(this)
208 class(dofmap_t), intent(inout) :: this
209
210 if (allocated(this%dof)) then
211 deallocate(this%dof)
212 end if
213
214 if (allocated(this%shared_dof)) then
215 deallocate(this%shared_dof)
216 end if
217
218 if (allocated(this%x)) then
219 if (neko_bcknd_device .eq. 1) then
220 call device_unmap(this%x, this%x_d)
221 end if
222 deallocate(this%x)
223 end if
224
225 if (allocated(this%y)) then
226 if (neko_bcknd_device .eq. 1) then
227 call device_unmap(this%y, this%y_d)
228 end if
229 deallocate(this%y)
230 end if
231
232 if (allocated(this%z)) then
233 if (neko_bcknd_device .eq. 1) then
234 call device_unmap(this%z, this%z_d)
235 end if
236 deallocate(this%z)
237 end if
238
239 nullify(this%msh)
240 nullify(this%Xh)
241
242 if (allocated(this%msh_subset)) then
243 call this%msh_subset%free()
244 deallocate(this%msh_subset)
245 end if
246
247 end subroutine dofmap_free
248
250 pure function dofmap_size(this) result(res)
251 class(dofmap_t), intent(in) :: this
252 integer :: res
253 res = this%ntot
254 end function dofmap_size
255
257 pure function dofmap_global_size(this) result(res)
258 class(dofmap_t), intent(in) :: this
259 integer :: res
260 res = this%Xh%lx * this%Xh%ly * this%Xh%lz * this%msh%glb_nelv
261 end function dofmap_global_size
262
264 subroutine dofmap_number_points(this)
265 type(dofmap_t), target :: this
266 integer :: il, jl, ix, iy, iz
267 type(mesh_t), pointer :: msh
268 type(space_t), pointer :: Xh
269
270 msh => this%msh
271 xh => this%Xh
272 !$omp parallel do private(il,jl,ix,iy,iz)
273 do il = 1, msh%nelv
274 do jl = 1, msh%npts
275 ix = mod(jl - 1, 2) * (xh%lx - 1) + 1
276 iy = (mod(jl - 1, 4)/2) * (xh%ly - 1) + 1
277 iz = ((jl - 1)/4) * (xh%lz - 1) + 1
278 this%dof(ix, iy, iz, il) = int(msh%elements(il)%e%pts(jl)%p%id(), i8)
279 this%shared_dof(ix, iy, iz, il) = msh%is_shared_point(il, jl)
280 end do
281 end do
282 !$omp end parallel do
283 end subroutine dofmap_number_points
284
286 subroutine dofmap_number_edges(this)
287 type(dofmap_t), target :: this
288 type(mesh_t), pointer :: msh
289 type(space_t), pointer :: Xh
290 integer :: i,j,k
291 integer :: global_id
292 integer(kind=i8) :: num_dofs_edges(3) ! #dofs for each dir (r, s, t)
293 integer(kind=i8) :: edge_id, edge_offset
294 logical :: shared_dof
295
296 msh => this%msh
297 xh => this%Xh
298
299 ! Number of dofs on an edge excluding end-points
300 num_dofs_edges(1) = int(xh%lx - 2, i8)
301 num_dofs_edges(2) = int(xh%ly - 2, i8)
302 num_dofs_edges(3) = int(xh%lz - 2, i8)
303 edge_offset = int(msh%glb_mpts, i8) + int(1, i8)
304
305 !$omp parallel do private(i,j,k,global_id,edge_id,shared_dof)
306 do i = 1, msh%nelv
307
308 select type (ep => msh%elements(i)%e)
309 type is (hex_t)
310 !
311 ! Number edges in r-direction
312 !
313 shared_dof = msh%is_shared_edge(i, 1)
314 global_id = msh%get_global_edge(i, 1)
315 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(1)
316 !Reverse order of tranversal if edge is reversed
317 if (this%dof(1,1,1,i) .gt. this%dof(xh%lx, 1, 1, i)) then
318 do concurrent(j = 2:xh%lx - 1)
319 k = xh%lx+1-j
320 this%dof(k, 1, 1, i) = edge_id + (j-2)
321 this%shared_dof(k, 1, 1, i) = shared_dof
322 end do
323 else
324 do concurrent(j = 2:xh%lx - 1)
325 k = j
326 this%dof(k, 1, 1, i) = edge_id + (j-2)
327 this%shared_dof(k, 1, 1, i) = shared_dof
328 end do
329 end if
330
331 shared_dof = msh%is_shared_edge(i, 3)
332 global_id = msh%get_global_edge(i, 3)
333 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(1)
334 if (this%dof(1, 1, xh%lz, i) .gt. this%dof(xh%lx, 1, xh%lz, i)) then
335 do concurrent(j = 2:xh%lx - 1)
336 k = xh%lx+1-j
337 this%dof(k, 1, xh%lz, i) = edge_id + (j-2)
338 this%shared_dof(k, 1, xh%lz, i) = shared_dof
339 end do
340 else
341 do concurrent(j = 2:xh%lx - 1)
342 k = j
343 this%dof(k, 1, xh%lz, i) = edge_id + (j-2)
344 this%shared_dof(k, 1, xh%lz, i) = shared_dof
345 end do
346 end if
347
348 shared_dof = msh%is_shared_edge(i, 2)
349 global_id = msh%get_global_edge(i, 2)
350 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(1)
351 if (this%dof(1, xh%ly, 1, i) .gt. this%dof(xh%lx, xh%ly, 1, i)) then
352 do concurrent(j = 2:xh%lx - 1)
353 k = xh%lx+1-j
354 this%dof(k, xh%ly, 1, i) = edge_id + (j-2)
355 this%shared_dof(k, xh%ly, 1, i) = shared_dof
356 end do
357 else
358 do concurrent(j = 2:xh%lx - 1)
359 k = j
360 this%dof(k, xh%ly, 1, i) = edge_id + (j-2)
361 this%shared_dof(k, xh%ly, 1, i) = shared_dof
362 end do
363 end if
364
365 shared_dof = msh%is_shared_edge(i, 4)
366 global_id = msh%get_global_edge(i, 4)
367 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(1)
368 if (this%dof(1, xh%ly, xh%lz, i) .gt. &
369 this%dof(xh%lx, xh%ly, xh%lz, i)) then
370 do concurrent(j = 2:xh%lx - 1)
371 k = xh%lx+1-j
372 this%dof(k, xh%ly, xh%lz, i) = edge_id + (j-2)
373 this%shared_dof(k, xh%ly, xh%lz, i) = shared_dof
374 end do
375 else
376 do concurrent(j = 2:xh%lx - 1)
377 k = j
378 this%dof(k, xh%ly, xh%lz, i) = edge_id + (j-2)
379 this%shared_dof(k, xh%ly, xh%lz, i) = shared_dof
380 end do
381 end if
382
383
384 !
385 ! Number edges in s-direction
386 !
387 shared_dof = msh%is_shared_edge(i, 5)
388 global_id = msh%get_global_edge(i, 5)
389 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(2)
390 if (this%dof(1,1,1,i) .gt. this%dof(1, xh%ly, 1, i)) then
391 do concurrent(j = 2:xh%ly - 1)
392 k = xh%ly+1-j
393 this%dof(1, k, 1, i) = edge_id + (j-2)
394 this%shared_dof(1, k, 1, i) = shared_dof
395 end do
396 else
397 do concurrent(j = 2:xh%ly - 1)
398 k = j
399 this%dof(1, k, 1, i) = edge_id + (j-2)
400 this%shared_dof(1, k, 1, i) = shared_dof
401 end do
402 end if
403
404 shared_dof = msh%is_shared_edge(i, 7)
405 global_id = msh%get_global_edge(i, 7)
406 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(2)
407 if (this%dof(1, 1, xh%lz, i) .gt. this%dof(1, xh%ly, xh%lz, i)) then
408 do concurrent(j = 2:xh%ly - 1)
409 k = xh%ly+1-j
410 this%dof(1, k, xh%lz, i) = edge_id + (j-2)
411 this%shared_dof(1, k, xh%lz, i) = shared_dof
412 end do
413 else
414 do concurrent(j = 2:xh%ly - 1)
415 k = j
416 this%dof(1, k, xh%lz, i) = edge_id + (j-2)
417 this%shared_dof(1, k, xh%lz, i) = shared_dof
418 end do
419 end if
420
421 shared_dof = msh%is_shared_edge(i, 6)
422 global_id = msh%get_global_edge(i, 6)
423 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(2)
424 if (this%dof(xh%lx, 1, 1, i) .gt. this%dof(xh%lx, xh%ly, 1, i)) then
425 do concurrent(j = 2:xh%ly - 1)
426 k = xh%ly+1-j
427 this%dof(xh%lx, k, 1, i) = edge_id + (j-2)
428 this%shared_dof(xh%lx, k, 1, i) = shared_dof
429 end do
430 else
431 do concurrent(j = 2:xh%ly - 1)
432 k = j
433 this%dof(xh%lx, k, 1, i) = edge_id + (j-2)
434 this%shared_dof(xh%lx, k, 1, i) = shared_dof
435 end do
436 end if
437
438 shared_dof = msh%is_shared_edge(i, 8)
439 global_id = msh%get_global_edge(i, 8)
440 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(2)
441 if (this%dof(xh%lx, 1, xh%lz, i) .gt. &
442 this%dof(xh%lx, xh%ly, xh%lz, i)) then
443 do concurrent(j = 2:xh%ly - 1)
444 k = xh%lz+1-j
445 this%dof(xh%lx, k, xh%lz, i) = edge_id + (j-2)
446 this%shared_dof(xh%lx, k, xh%lz, i) = shared_dof
447 end do
448 else
449 do concurrent(j = 2:xh%ly - 1)
450 k = j
451 this%dof(xh%lx, k, xh%lz, i) = edge_id + (j-2)
452 this%shared_dof(xh%lx, k, xh%lz, i) = shared_dof
453 end do
454 end if
455
456 !
457 ! Number edges in t-direction
458 !
459 shared_dof = msh%is_shared_edge(i, 9)
460 global_id = msh%get_global_edge(i, 9)
461 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(3)
462 if (this%dof(1,1,1,i) .gt. this%dof(1, 1, xh%lz, i)) then
463 do concurrent(j = 2:xh%lz - 1)
464 k = xh%lz+1-j
465 this%dof(1, 1, k, i) = edge_id + (j-2)
466 this%shared_dof(1, 1, k, i) = shared_dof
467 end do
468 else
469 do concurrent(j = 2:xh%lz - 1)
470 k = j
471 this%dof(1, 1, k, i) = edge_id + (j-2)
472 this%shared_dof(1, 1, k, i) = shared_dof
473 end do
474 end if
475
476 shared_dof = msh%is_shared_edge(i, 10)
477 global_id = msh%get_global_edge(i, 10)
478 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(3)
479 if (this%dof(xh%lx,1,1,i) .gt. this%dof(xh%lx, 1, xh%lz, i)) then
480 do concurrent(j = 2:xh%lz - 1)
481 k = xh%lz+1-j
482 this%dof(xh%lx, 1, k, i) = edge_id + (j-2)
483 this%shared_dof(xh%lx, 1, k, i) = shared_dof
484 end do
485 else
486 do concurrent(j = 2:xh%lz - 1)
487 k = j
488 this%dof(xh%lx, 1, k, i) = edge_id + (j-2)
489 this%shared_dof(xh%lx, 1, k, i) = shared_dof
490 end do
491 end if
492
493 shared_dof = msh%is_shared_edge(i, 11)
494 global_id = msh%get_global_edge(i, 11)
495 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(3)
496 if (this%dof(1, xh%ly, 1, i) .gt. this%dof(1, xh%ly, xh%lz, i)) then
497 do concurrent(j = 2:xh%lz - 1)
498 k = xh%lz+1-j
499 this%dof(1, xh%ly, k, i) = edge_id + (j-2)
500 this%shared_dof(1, xh%ly, k, i) = shared_dof
501 end do
502 else
503 do concurrent(j = 2:xh%lz - 1)
504 k = j
505 this%dof(1, xh%ly, k, i) = edge_id + (j-2)
506 this%shared_dof(1, xh%ly, k, i) = shared_dof
507 end do
508 end if
509
510 shared_dof = msh%is_shared_edge(i, 12)
511 global_id = msh%get_global_edge(i, 12)
512 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(3)
513 if (this%dof(xh%lx, xh%ly, 1, i) .gt. &
514 this%dof(xh%lx, xh%ly, xh%lz, i)) then
515 do concurrent(j = 2:xh%lz - 1)
516 k = xh%lz+1-j
517 this%dof(xh%lx, xh%ly, k, i) = edge_id + (j-2)
518 this%shared_dof(xh%lx, xh%ly, k, i) = shared_dof
519 end do
520 else
521 do concurrent(j = 2:xh%lz - 1)
522 k = j
523 this%dof(xh%lx, xh%ly, k, i) = edge_id + (j-2)
524 this%shared_dof(xh%lx, xh%ly, k, i) = shared_dof
525 end do
526 end if
527 type is (quad_t)
528 !
529 ! Number edges in r-direction
530 !
531 shared_dof = msh%is_shared_edge(i, 3)
532 global_id = msh%get_global_edge(i, 3)
533 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(1)
534 !Reverse order of tranversal if edge is reversed
535 if (this%dof(1,1,1,i) .gt. this%dof(xh%lx, 1, 1, i)) then
536 do concurrent(j = 2:xh%lx - 1)
537 k = xh%lx+1-j
538 this%dof(k, 1, 1, i) = edge_id + (j-2)
539 this%shared_dof(k, 1, 1, i) = shared_dof
540 end do
541 else
542 do concurrent(j = 2:xh%lx - 1)
543 k = j
544 this%dof(k, 1, 1, i) = edge_id + (j-2)
545 this%shared_dof(k, 1, 1, i) = shared_dof
546 end do
547 end if
548
549 shared_dof = msh%is_shared_edge(i, 4)
550 global_id = msh%get_global_edge(i, 4)
551 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(1)
552 if (this%dof(1, xh%ly, 1, i) .gt. this%dof(xh%lx, xh%ly, 1, i)) then
553 do concurrent(j = 2:xh%lx - 1)
554 k = xh%lx+1-j
555 this%dof(k, xh%ly, 1, i) = edge_id + (j-2)
556 this%shared_dof(k, xh%ly, 1, i) = shared_dof
557 end do
558 else
559 do concurrent(j = 2:xh%lx - 1)
560 k = j
561 this%dof(k, xh%ly, 1, i) = edge_id + (j-2)
562 this%shared_dof(k, xh%ly, 1, i) = shared_dof
563 end do
564 end if
565
566 !
567 ! Number edges in s-direction
568 !
569 shared_dof = msh%is_shared_edge(i, 1)
570 global_id = msh%get_global_edge(i, 1)
571 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(2)
572 if (this%dof(1,1,1,i) .gt. this%dof(1, xh%ly, 1, i)) then
573 do concurrent(j = 2:xh%ly - 1)
574 k = xh%ly+1-j
575 this%dof(1, k, 1, i) = edge_id + (j-2)
576 this%shared_dof(1, k, 1, i) = shared_dof
577 end do
578 else
579 do concurrent(j = 2:xh%ly - 1)
580 k = j
581 this%dof(1, k, 1, i) = edge_id + (j-2)
582 this%shared_dof(1, k, 1, i) = shared_dof
583 end do
584 end if
585
586 shared_dof = msh%is_shared_edge(i, 2)
587 global_id = msh%get_global_edge(i, 2)
588 edge_id = edge_offset + int((global_id - 1), i8) * num_dofs_edges(2)
589 if (this%dof(xh%lx,1,1,i) .gt. this%dof(xh%lx, xh%ly, 1, i)) then
590 do concurrent(j = 2:xh%ly - 1)
591 k = xh%ly+1-j
592 this%dof(xh%lx, k, 1, i) = edge_id + (j-2)
593 this%shared_dof(xh%lx, k, 1, i) = shared_dof
594 end do
595 else
596 do concurrent(j = 2:xh%ly - 1)
597 k = j
598 this%dof(xh%lx, k, 1, i) = edge_id + (j-2)
599 this%shared_dof(xh%lx, k, 1, i) = shared_dof
600 end do
601 end if
602 end select
603
604 end do
605 !$omp end parallel do
606 end subroutine dofmap_number_edges
607
609 subroutine dofmap_number_faces(this)
610 type(dofmap_t), target :: this
611 type(mesh_t), pointer :: msh
612 type(space_t), pointer :: Xh
613 integer :: i,j,k
614 integer :: global_id
615 type(tuple4_i4_t) :: face, face_order
616 integer(kind=i8) :: num_dofs_faces(3) ! #dofs for each dir (r, s, t)
617 integer(kind=i8) :: facet_offset, facet_id
618 logical :: shared_dof
619
620 msh => this%msh
621 xh => this%Xh
622
624 facet_offset = int(msh%glb_mpts, i8) + &
625 int(msh%glb_meds, i8) * int(xh%lx-2, i8) + int(1, i8)
626
627 ! Number of dofs on an face excluding end-points
628 num_dofs_faces(1) = int((xh%ly - 2) * (xh%lz - 2), i8)
629 num_dofs_faces(2) = int((xh%lx - 2) * (xh%lz - 2), i8)
630 num_dofs_faces(3) = int((xh%lx - 2) * (xh%ly - 2), i8)
631
632 !$omp parallel do private(i,j,k,global_id,face,face_order,facet_id, shared_dof)
633 do i = 1, msh%nelv
634
635 !
636 ! Number facets in r-direction (s, t)-plane
637 !
638 call msh%elements(i)%e%facet_id(face, 1)
639 call msh%elements(i)%e%facet_order(face_order, 1)
640 shared_dof = msh%is_shared_facet(i, 1)
641 global_id = msh%get_global_facet(i, 1)
642 facet_id = facet_offset + int((global_id - 1), i8) * num_dofs_faces(1)
643 do k = 2, xh%lz - 1
644 do j = 2, xh%ly - 1
645 this%dof(1, j, k, i) = dofmap_facetidx(face_order, face, &
646 facet_id, j, k, xh%lz, xh%ly)
647 this%shared_dof(1, j, k, i) = shared_dof
648 end do
649 end do
650
651 call msh%elements(i)%e%facet_id(face, 2)
652 call msh%elements(i)%e%facet_order(face_order, 2)
653 shared_dof = msh%is_shared_facet(i, 2)
654 global_id = msh%get_global_facet(i, 2)
655 facet_id = facet_offset + int((global_id - 1), i8) * num_dofs_faces(1)
656 do k = 2, xh%lz - 1
657 do j = 2, xh%ly - 1
658 this%dof(xh%lx, j, k, i) = dofmap_facetidx(face_order, face, &
659 facet_id, j, k, xh%lz, xh%ly)
660 this%shared_dof(xh%lx, j, k, i) = shared_dof
661 end do
662 end do
663
664
665 !
666 ! Number facets in s-direction (r, t)-plane
667 !
668 call msh%elements(i)%e%facet_id(face, 3)
669 call msh%elements(i)%e%facet_order(face_order, 3)
670 shared_dof = msh%is_shared_facet(i, 3)
671 global_id = msh%get_global_facet(i, 3)
672 facet_id = facet_offset + int((global_id - 1), i8) * num_dofs_faces(2)
673 do k = 2, xh%lz - 1
674 do j = 2, xh%lx - 1
675 this%dof(j, 1, k, i) = dofmap_facetidx(face_order, face, &
676 facet_id, k, j, xh%lz, xh%lx)
677 this%shared_dof(j, 1, k, i) = shared_dof
678 end do
679 end do
680
681 call msh%elements(i)%e%facet_id(face, 4)
682 call msh%elements(i)%e%facet_order(face_order, 4)
683 shared_dof = msh%is_shared_facet(i, 4)
684 global_id = msh%get_global_facet(i, 4)
685 facet_id = facet_offset + int((global_id - 1), i8) * num_dofs_faces(2)
686 do k = 2, xh%lz - 1
687 do j = 2, xh%lx - 1
688 this%dof(j, xh%ly, k, i) = dofmap_facetidx(face_order, face, &
689 facet_id, k, j, xh%lz, xh%lx)
690 this%shared_dof(j, xh%ly, k, i) = shared_dof
691 end do
692 end do
693
694
695 !
696 ! Number facets in t-direction (r, s)-plane
697 !
698 call msh%elements(i)%e%facet_id(face, 5)
699 call msh%elements(i)%e%facet_order(face_order, 5)
700 shared_dof = msh%is_shared_facet(i, 5)
701 global_id = msh%get_global_facet(i, 5)
702 facet_id = facet_offset + int((global_id - 1), i8) * num_dofs_faces(3)
703 do k = 2, xh%ly - 1
704 do j = 2, xh%lx - 1
705 this%dof(j, k, 1, i) = dofmap_facetidx(face_order, face, &
706 facet_id, k, j, xh%ly, xh%lx)
707 this%shared_dof(j, k, 1, i) = shared_dof
708 end do
709 end do
710
711 call msh%elements(i)%e%facet_id(face, 6)
712 call msh%elements(i)%e%facet_order(face_order, 6)
713 shared_dof = msh%is_shared_facet(i, 6)
714 global_id = msh%get_global_facet(i, 6)
715 facet_id = facet_offset + int((global_id - 1), i8) * num_dofs_faces(3)
716 do k = 2, xh%ly - 1
717 do j = 2, xh%lx - 1
718 this%dof(j, k, xh%lz, i) = dofmap_facetidx(face_order, face, &
719 facet_id, k, j, xh%lz, xh%lx)
720 this%shared_dof(j, k, xh%lz, i) = shared_dof
721 end do
722 end do
723 end do
724 !$omp end parallel do
725
726 end subroutine dofmap_number_faces
727
729 pure function dofmap_facetidx(face_order, face, facet_id, k1, j1, lk1, &
730 lj1) result(facet_idx)
731 type(tuple4_i4_t), intent(in) :: face_order, face
732 integer(kind=i8), intent(in) :: facet_id
733 integer(kind=i8) :: facet_idx
734 integer, intent(in) :: k1, j1, lk1, lj1
735 integer :: k, j, lk, lj
736
737 k = k1 - 2
738 j = j1 - 2
739 lk = lk1 - 2
740 lj = lj1 - 2
741
742 ! Given the indexes k,j for a GLL point on the inner part of the
743 ! face, we assign a unique number to it that depends on the
744 ! corner with the lowest id and its neighbour with the lowest
745 ! id. The id is assigned in this way to be consistent regardless
746 ! of how the faces are rotated or mirrored.
747 !
748 ! 4 -------- 3
749 ! | | k
750 ! |----->| ^
751 ! |----->| |
752 ! |----->| |
753 ! 1 -------- 2 0--->j
754
755
756 if (face_order%x(1) .eq. face%x(1)) then
757 if (face_order%x(2) .lt. face_order%x(4)) then
758 facet_idx = facet_id + j + k*lj
759 else
760 facet_idx = facet_id + j*lk + k
761 end if
762 else if (face_order%x(2) .eq. face%x(1)) then
763 if (face_order%x(3) .lt. face_order%x(1)) then
764 facet_idx = facet_id + lk*(lj-1-j) + k
765 else
766 facet_idx = facet_id + (lj-1-j) + k*lj
767 end if
768 else if (face_order%x(3) .eq. face%x(1)) then
769 if (face_order%x(4) .lt. face_order%x(2)) then
770 facet_idx = facet_id + (lj-1-j) + lj*(lk-1-k)
771 else
772 facet_idx = facet_id + lk*(lj-1-j) + (lk-1-k)
773 end if
774 else if (face_order%x(4) .eq. face%x(1)) then
775 if (face_order%x(1) .lt. face_order%x(3)) then
776 facet_idx = facet_id + lk*j + (lk-1-k)
777 else
778 facet_idx = facet_id + j + lj*(lk-1-k)
779 end if
780 end if
781
782 end function dofmap_facetidx
783
786 subroutine dofmap_generate_xyz(this)
787 type(dofmap_t), target :: this
788 integer :: i, j, el_idx
789 type(mesh_t), pointer :: msh
790 type(space_t), pointer :: Xh
791 real(kind=rp) :: rp_curve_data(5), curve_data_tot(5,12)
792 logical :: midpoint
793 integer :: n_edge, curve_type(12)
794
795 msh => this%msh
796 xh => this%Xh
797
798 if (msh%gdim .eq. 3) then
799 n_edge = 12
800 else
801 n_edge = 4
802 end if
803
804 !$omp parallel do
805 do i = 1, msh%nelv
806 call dofmap_xyzlin(xh, msh, msh%elements(i)%e, this%x(1,1,1,i), &
807 this%y(1,1,1,i), this%z(1,1,1,i))
808 end do
809 !$omp end parallel do
810
811 do i = 1, msh%curve%size
812 midpoint = .false.
813 el_idx = msh%curve%curve_el(i)%el_idx
814 curve_type = msh%curve%curve_el(i)%curve_type
815 curve_data_tot = msh%curve%curve_el(i)%curve_data
816 do j = 1, n_edge
817 if (curve_type(j) .eq. 4) then
818 midpoint = .true.
819 end if
820 end do
821 if (midpoint .and. xh%lx .gt. 2) then
822 call dofmap_xyzquad(xh, msh, msh%elements(el_idx)%e, &
823 this%x(1, 1, 1, el_idx), this%y(1, 1, 1, el_idx), &
824 this%z(1 ,1, 1, el_idx), curve_type, curve_data_tot)
825 end if
826 end do
827 do i = 1, msh%curve%size
828 el_idx = msh%curve%curve_el(i)%el_idx
829 do j = 1, 8
830 if (msh%curve%curve_el(i)%curve_type(j) .eq. 3) then
831 rp_curve_data = msh%curve%curve_el(i)%curve_data(1:5,j)
832 call arc_surface(j, rp_curve_data, &
833 this%x(1, 1, 1, el_idx), &
834 this%y(1, 1, 1, el_idx), &
835 this%z(1, 1, 1, el_idx), &
836 xh, msh%elements(el_idx)%e, msh%gdim)
837 end if
838 end do
839 end do
840 if (associated(msh%apply_deform)) then
841 call msh%apply_deform(this%x, this%y, this%z, xh%lx, xh%ly, xh%lz)
842 end if
843 end subroutine dofmap_generate_xyz
844
853 subroutine dofmap_xyzlin(Xh, msh, element, x, y, z)
854 type(mesh_t), pointer, intent(in) :: msh
855 type(space_t), intent(in) :: Xh
856 class(element_t), intent(in) :: element
857 real(kind=rp), intent(inout) :: x(xh%lx, xh%ly, xh%lz), &
858 y(xh%lx, xh%ly, xh%lz), &
859 z(xh%lx, xh%ly, xh%lz)
860 real(kind=rp) :: xyzb(2,2,2,3), zgml(xh%lx, 3)
861 real(kind=rp) :: jx(xh%lx*2)
862 real(kind=rp) :: jxt(xh%lx*2), jyt(xh%lx*2), jzt(xh%lx*2)
863 real(kind=rp) :: w(4*xh%lx**3), tmp(xh%lx, xh%lx, xh%lx)
864 real(kind=rp), dimension(2), parameter :: zlin = [-1d0, 1d0]
865
866 integer :: j, k
867
868 zgml = 0d0
869 xyzb = 0d0
870
871 w = 0d0
872 call copy(zgml(1,1), xh%zg(1,1), xh%lx)
873 call copy(zgml(1,2), xh%zg(1,2), xh%ly)
874 if (msh%gdim .gt. 2) then
875 call copy(zgml(1,3), xh%zg(1,3), xh%lz)
876 end if
877
878 k = 1
879 do j = 1, xh%lx
880 call fd_weights_full(zgml(j,1), zlin, 1, 0, jxt(k))
881 call fd_weights_full(zgml(j,2), zlin, 1, 0, jyt(k))
882 if (msh%gdim .gt. 2) then
883 call fd_weights_full(zgml(j,3), zlin, 1, 0, jzt(k))
884 end if
885 k = k + 2
886 end do
887 call trsp(jx, xh%lx, jxt, 2)
888
889 if (msh%gdim .eq. 2) then
890 jzt = 1d0
891 end if
892
893 if (msh%gdim .gt. 2) then
894 do concurrent(j = 1:msh%gdim)
895 xyzb(1,1,1,j) = element%pts(1)%p%x(j)
896 xyzb(2,1,1,j) = element%pts(2)%p%x(j)
897 xyzb(1,2,1,j) = element%pts(3)%p%x(j)
898 xyzb(2,2,1,j) = element%pts(4)%p%x(j)
899
900 xyzb(1,1,2,j) = element%pts(5)%p%x(j)
901 xyzb(2,1,2,j) = element%pts(6)%p%x(j)
902 xyzb(1,2,2,j) = element%pts(7)%p%x(j)
903 xyzb(2,2,2,j) = element%pts(8)%p%x(j)
904 end do
905 else
906 do concurrent(j = 1:msh%gdim)
907 xyzb(1,1,1,j) = element%pts(1)%p%x(j)
908 xyzb(2,1,1,j) = element%pts(2)%p%x(j)
909 xyzb(1,2,1,j) = element%pts(3)%p%x(j)
910 xyzb(2,2,1,j) = element%pts(4)%p%x(j)
911 end do
912 end if
913 if (msh%gdim .eq. 3) then
914 call tensr3(tmp, xh%lx, xyzb(1,1,1,1), 2, jx, jyt, jzt, w)
915 call copy(x, tmp, xh%lx*xh%ly*xh%lz)
916 call tensr3(tmp, xh%ly, xyzb(1,1,1,2), 2, jx, jyt, jzt, w)
917 call copy(y, tmp, xh%lx*xh%ly*xh%lz)
918 call tensr3(tmp, xh%lz, xyzb(1,1,1,3), 2, jx, jyt, jzt, w)
919 call copy(z, tmp, xh%lx*xh%ly*xh%lz)
920 else
921 call tnsr2d_el(tmp, xh%lx, xyzb(1,1,1,1), 2, jx, jyt)
922 call copy(x, tmp, xh%lx*xh%ly*xh%lz)
923 call tnsr2d_el(tmp, xh%ly, xyzb(1,1,1,2), 2, jx, jyt)
924 call copy(y, tmp, xh%lx*xh%ly*xh%lz)
925 end if
926 end subroutine dofmap_xyzlin
927
928 !OCL SERIAL
929 subroutine dofmap_xyzquad(Xh, msh, element, x, y, z, curve_type, curve_data)
930 type(mesh_t), pointer, intent(in) :: msh
931 type(space_t), intent(in) :: Xh
932 class(element_t), intent(in) :: element
933 real(kind=rp), dimension(Xh%lx, Xh%ly, Xh%lz), intent(inout) :: x, y, z
934 integer :: curve_type(12), eindx(12)
935 real(kind=rp) :: curve_data(5,12), x3(3,3,3), y3(3,3,3), z3(3,3,3)
936 type(space_t), target :: xh3
937 real(kind=rp), dimension(3), parameter :: zquad = [-1d0, 0d0,1d0]
938 real(kind=rp) :: zg(3)
939 real(kind=rp), dimension(Xh%lx, Xh%lx, Xh%lx) :: tmp
940 real(kind=rp) :: jx(xh%lx*3)
941 real(kind=rp) :: jxt(xh%lx*3), jyt(xh%lx*3), jzt(xh%lx*3)
942 real(kind=rp) :: w(4*xh%lxyz,2)
943 integer :: j, k, n_edges
944 eindx = [2 , 6 , 8 , 4, &
945 20 , 24 , 26 , 22, &
946 10 , 12 , 18 , 16]
947
948 w = 0d0
949 if (msh%gdim .eq. 3) then
950 n_edges = 12
951 call xh3%init(gll, 3, 3, 3)
952 else
953 n_edges = 4
954 call xh3%init(gll, 3, 3)
955 end if
956 call dofmap_xyzlin(xh3, msh, element, x3, y3, z3)
957
958 do k = 1, n_edges
959 if (curve_type(k) .eq. 4) then
960 x3(eindx(k),1,1) = curve_data(1,k)
961 y3(eindx(k),1,1) = curve_data(2,k)
962 z3(eindx(k),1,1) = curve_data(3,k)
963 end if
964 end do
965 zg(1) = -1
966 zg(2) = 0
967 zg(3) = 1
968 if (msh%gdim .eq. 3) then
969 call gh_face_extend_3d(x3, zg, 3, 2, w(1,1), w(1,2)) ! 2 --> edge extend
970 call gh_face_extend_3d(y3, zg, 3, 2, w(1,1), w(1,2))
971 call gh_face_extend_3d(z3, zg, 3, 2, w(1,1), w(1,2))
972 else
973 call neko_warning(' m deformation not supported for 2d yet')
974 call gh_face_extend_2d(x3, zg, 3, 2, w(1,1), w(1,2)) ! 2 --> edge extend
975 call gh_face_extend_2d(y3, zg, 3, 2, w(1,1), w(1,2))
976 end if
977 k = 1
978 do j = 1, xh%lx
979 call fd_weights_full(xh%zg(j,1), zquad, 2, 0, jxt(k))
980 call fd_weights_full(xh%zg(j,2), zquad, 2, 0, jyt(k))
981 if (msh%gdim .gt. 2) then
982 call fd_weights_full(xh%zg(j,3), zquad, 2, 0, jzt(k))
983 end if
984 k = k + 3
985 end do
986 call trsp(jx, xh%lx, jxt, 3)
987 if (msh%gdim .eq. 3) then
988 call tensr3(tmp, xh%lx, x3, 3, jx, jyt, jzt, w)
989 call copy(x, tmp, xh%lx*xh%ly*xh%lz)
990 call tensr3(tmp, xh%ly, y3, 3, jx, jyt, jzt, w)
991 call copy(y, tmp, xh%lx*xh%ly*xh%lz)
992 call tensr3(tmp, xh%lz, z3, 3, jx, jyt, jzt, w)
993 call copy(z, tmp, xh%lx*xh%ly*xh%lz)
994 else
995 call tnsr2d_el(tmp, xh%lx, x3, 3, jx, jyt)
996 call copy(x, tmp, xh%lx*xh%ly*xh%lz)
997 call tnsr2d_el(tmp, xh%ly, y3, 3, jx, jyt)
998 call copy(y, tmp, xh%lx*xh%ly*xh%lz)
999 end if
1000
1001 call xh3%free()
1002 end subroutine dofmap_xyzquad
1003
1004
1005 !OCL SERIAL
1011 subroutine gh_face_extend_3d(x, zg, n, gh_type, e, v)
1012 integer, intent(in) :: n
1013 real(kind=rp), intent(inout) :: x(n, n, n)
1014 real(kind=rp), intent(in) :: zg(n)
1015 real(kind=rp), intent(inout) :: e(n, n, n)
1016 real(kind=rp), intent(inout) :: v(n, n, n)
1017 integer :: gh_type, ntot, kk, jj, ii, k, j, i
1018 real(kind=xp) :: si, sj, sk, hi, hj, hk
1019
1020 !
1021 ! Build vertex interpolant
1022 !
1023 ntot = n**3
1024 do concurrent(i = 1:ntot)
1025 v(i,1,1) = 0.0_rp
1026 end do
1027
1028 do concurrent(i = 1:n, j = 1:n, k = 1:n, &
1029 ii = 1:n:n-1, jj = 1:n:n-1, kk = 1:n:n-1)
1030 si = 0.5_xp*((n-ii)*(1-zg(i))+(ii-1)*(1+zg(i)))/(n-1)
1031 sj = 0.5_xp*((n-jj)*(1-zg(j))+(jj-1)*(1+zg(j)))/(n-1)
1032 sk = 0.5_xp*((n-kk)*(1-zg(k))+(kk-1)*(1+zg(k)))/(n-1)
1033 v(i,j,k) = v(i,j,k) + si * sj* sk * x(ii, jj, kk)
1034 end do
1035
1036 if (gh_type .eq. 1) then
1037 do concurrent(i = 1:ntot)
1038 x(i,1,1) = v(i,1,1)
1039 end do
1040 return
1041 end if
1042 !
1043 !
1044 ! Extend 12 edges
1045 do concurrent(i = 1:ntot)
1046 e(i,1,1) = 0.0_rp
1047 end do
1048 !
1049 ! x-edges
1050 !
1051 do concurrent(i = 1:n, j = 1:n, k = 1:n, jj = 1:n:n-1, kk = 1:n:n-1)
1052 hj = 0.5_xp*((n-jj)*(1-zg(j))+(jj-1)*(1+zg(j)))/(n-1)
1053 hk = 0.5_xp*((n-kk)*(1-zg(k))+(kk-1)*(1+zg(k)))/(n-1)
1054 e(i,j,k) = e(i,j,k) + hj*hk*(x(i, jj, kk) - v(i, jj, kk))
1055 end do
1056 !
1057 ! y-edges
1058 !
1059 do concurrent(i = 1:n, j = 1:n, k = 1:n, ii = 1:n:n-1, kk = 1:n:n-1)
1060 hi = 0.5_xp*((n-ii)*(1-zg(i))+(ii-1)*(1+zg(i)))/(n-1)
1061 hk = 0.5_xp*((n-kk)*(1-zg(k))+(kk-1)*(1+zg(k)))/(n-1)
1062 e(i,j,k) = e(i,j,k) + hi*hk*(x(ii, j, kk) - v(ii, j, kk))
1063 end do
1064 !
1065 ! z-edges
1066 !
1067 do concurrent(i = 1:n, j = 1:n, k = 1:n, ii = 1:n:n-1, jj = 1:n:n-1)
1068 hi = 0.5_xp*((n-ii)*(1-zg(i))+(ii-1)*(1+zg(i)))/(n-1)
1069 hj = 0.5_xp*((n-jj)*(1-zg(j))+(jj-1)*(1+zg(j)))/(n-1)
1070 e(i,j,k) = e(i,j,k) + hi*hj*(x(ii, jj, k) - v(ii, jj, k))
1071 end do
1072
1073 do concurrent(i = 1:ntot)
1074 e(i,1,1) = e(i,1,1) + v(i,1,1)
1075 end do
1076
1077 if (gh_type .eq. 2) then
1078 do concurrent(i = 1:ntot)
1079 x(i,1,1) = e(i,1,1)
1080 end do
1081 return
1082 end if
1083 !
1084 ! Extend faces
1085 !
1086 do concurrent(i = 1:ntot)
1087 v(i,1,1) = 0.0_rp
1088 end do
1089 !
1090 ! x-edges
1091 !
1092 do concurrent(i = 1:n, j = 1:n, k = 1:n, ii = 1:n:n-1)
1093 hi = 0.5_xp*((n-ii)*(1-zg(i))+(ii-1)*(1+zg(i)))/(n-1)
1094 v(i,j,k) = v(i,j,k) + hi*(x(ii,j,k)-e(ii,j,k))
1095 end do
1096
1097 !
1098 ! y-edges
1099 !
1100 do concurrent(i = 1:n, j = 1:n, k = 1:n, jj = 1:n:n-1)
1101 hj = 0.5_xp*((n-jj)*(1-zg(j))+(jj-1)*(1+zg(j)))/(n-1)
1102 v(i,j,k) = v(i,j,k) + hj*(x(i, jj, k) - e(i, jj, k))
1103 end do
1104
1105 !
1106 ! z-edges
1107 !
1108 do concurrent(i = 1:n, j = 1:n, k = 1:n, kk = 1:n:n-1)
1109 hk = 0.5_xp*((n-kk)*(1-zg(k))+(kk-1)*(1+zg(k)))/(n-1)
1110 v(i,j,k) = v(i,j,k) + hk*(x(i, j, kk) - e(i, j, kk))
1111 end do
1112
1113 do concurrent(i = 1:ntot)
1114 v(i,1,1) = v(i,1,1) + e(i,1,1)
1115 x(i,1,1) = v(i,1,1)
1116 end do
1117
1118 end subroutine gh_face_extend_3d
1119
1120 !OCL SERIAL
1124 subroutine gh_face_extend_2d(x, zg, n, gh_type, e, v)
1125 integer, intent(in) :: n
1126 real(kind=rp), intent(inout) :: x(n, n)
1127 real(kind=rp), intent(in) :: zg(n)
1128 real(kind=rp), intent(inout) :: e(n, n)
1129 real(kind=rp), intent(inout) :: v(n, n)
1130 integer, intent(in) :: gh_type
1131 integer :: i,j , jj, ii, ntot
1132 real(kind=rp) :: si, sj, hi, hj
1133
1134 !Build vertex interpolant
1135
1136 ntot = n*n
1137 call rzero(v, ntot)
1138 do jj = 1, n, n-1
1139 do ii = 1, n, n-1
1140 do j = 1, n
1141 do i = 1, n
1142 si = 0.5_xp*((n-ii)*(1-zg(i))+(ii-1)*(1+zg(i)))/(n-1)
1143 sj = 0.5_xp*((n-jj)*(1-zg(j))+(jj-1)*(1+zg(j)))/(n-1)
1144 v(i,j) = v(i,j) + si*sj*x(ii, jj)
1145 end do
1146 end do
1147 end do
1148 end do
1149 if (gh_type .eq. 1) then
1150 call copy(x, v, ntot)
1151 return
1152 end if
1153
1154 !Extend 4 edges
1155 call rzero(e, ntot)
1156
1157 !x-edges
1158
1159 do jj = 1, n, n-1
1160 do j = 1, n
1161 do i = 1, n
1162 hj = 0.5_xp*((n-jj)*(1-zg(j))+(jj-1)*(1+zg(j)))/(n-1)
1163 e(i,j) = e(i,j) + hj*(x(i, jj) - v(i, jj))
1164 end do
1165 end do
1166 end do
1167
1168 !y-edges
1169
1170 do ii = 1, n, n-1
1171 do j = 1, n
1172 do i = 1, n
1173 hi = 0.5_xp*((n-ii)*(1-zg(i))+(ii-1)*(1+zg(i)))/(n-1)
1174 e(i,j) = e(i,j) + hi*(x(ii,j)-v(ii,j))
1175 end do
1176 end do
1177 end do
1178
1179 call add3(x, e, v, ntot)
1180
1181 end subroutine gh_face_extend_2d
1182
1183
1184
1185 subroutine arc_surface(isid, curve_data, x, y, z, Xh, element, gdim)
1186 integer, intent(in) :: isid, gdim
1187 type(space_t), intent(in) :: Xh
1188 class(element_t) :: element
1189 real(kind=rp), dimension(5), intent(in) :: curve_data
1190 real(kind=rp), dimension(Xh%lx, Xh%ly, Xh%lz), intent(inout) :: x, y, z
1191 real(kind=rp) :: pt1x, pt1y, pt2x, pt2y, pt12x, pt12y
1192 real(kind=rp) :: radius, dtheta, r, xys
1193 real(kind=rp) :: theta0, xcenn, ycenn, h(xh%lx, 3, 2)
1194 real(kind=rp) :: xcrved(xh%lx), ycrved(xh%lx), xs, ys
1195 integer :: isid1, ixt, iyt, izt, ix, itmp
1196 ! Cyclic to symmetric face mapping
1197 integer(i4), dimension(6), parameter :: fcyc_to_sym = [3, 2, 4, 1, 5, 6]
1198 ! Cyclic to symmetric edge mapping
1199 integer(i4), dimension(12), parameter :: ecyc_to_sym = [1, 6, 2, 5, 3, 8, &
1200 4, 7, 9, 10, 12, 11]
1201 ! Symmetric edge to vertex mapping
1202 integer, parameter, dimension(2, 12) :: edge_nodes = reshape([1, 2, 3, 4, &
1203 5, 6, 7, 8, 1, 3, 2, 4, 5, 7, 6, 8, 1, 5, 2, 6, 3, 7, 4, 8], &
1204 [2,12])
1205 ! copy from hex as this has private attribute there
1206
1207 ! this subroutine is a mess of symmetric and cyclic edge/face numberring and
1208 ! cannot be cleaned without changing an input format (isid seems to be
1209 ! a cyclic edge number)
1210 ! following according to cyclic edge numbering and orientation
1211 itmp = ecyc_to_sym(isid)
1212 select case (isid)
1213 case (1:2,5:6)
1214 pt1x = element%pts(edge_nodes(1, itmp))%p%x(1)
1215 pt1y = element%pts(edge_nodes(1, itmp))%p%x(2)
1216 pt2x = element%pts(edge_nodes(2, itmp))%p%x(1)
1217 pt2y = element%pts(edge_nodes(2, itmp))%p%x(2)
1218 case (3:4,7:8)
1219 pt1x = element%pts(edge_nodes(2, itmp))%p%x(1)
1220 pt1y = element%pts(edge_nodes(2, itmp))%p%x(2)
1221 pt2x = element%pts(edge_nodes(1, itmp))%p%x(1)
1222 pt2y = element%pts(edge_nodes(1, itmp))%p%x(2)
1223 end select
1224 ! find slope of perpendicular
1225 radius = curve_data(1)
1226 xs = pt2y-pt1y
1227 ys = pt1x-pt2x
1228 ! make length radius
1229 xys = sqrt(xs**2 + ys**2)
1230 ! sanity check
1231 if (abs(2.0 * radius) <= xys * 1.00001) &
1232 & call neko_error('Radius to small for arced element surface')
1233 ! find center
1234 dtheta = abs(asin(0.5_xp*xys/radius))
1235 pt12x = (pt1x + pt2x)/2.0
1236 pt12y = (pt1y + pt2y)/2.0
1237 xcenn = pt12x - xs/xys * radius*cos(dtheta)
1238 ycenn = pt12y - ys/xys * radius*cos(dtheta)
1239 theta0 = atan2((pt12y-ycenn), (pt12x-xcenn))
1240 ! compute perturbation of geometry
1241 isid1 = mod(isid+4-1, 4)+1
1242 call compute_h(h, xh%zg, gdim, xh%lx)
1243 if (radius < 0.0) dtheta = -dtheta
1244 do ix = 1, xh%lx
1245 ixt = ix
1246 if (isid1 .gt. 2) ixt = xh%lx+1-ix
1247 r = xh%zg(ix,1)
1248 xcrved(ixt) = xcenn + abs(radius) * cos(theta0 + r*dtheta) &
1249 - ( h(ix,1,1)*pt1x + h(ix,1,2)*pt2x )
1250 ycrved(ixt) = ycenn + abs(radius) * sin(theta0 + r*dtheta) &
1251 - ( h(ix,1,1)*pt1y + h(ix,1,2)*pt2y )
1252 end do
1253 ! points all set, add perturbation to current mesh.
1254 ! LEGACY WARNING
1255 ! I dont want to dive in this again, Martin Karp 2/3 - 2021
1256 isid1 = fcyc_to_sym(isid1)
1257 izt = (isid-1)/4+1
1258 iyt = isid1-2
1259 ixt = isid1
1260 if (isid1 .le. 2) then
1261 call addtnsr(x, h(1, 1, ixt), xcrved, h(1, 3, izt), &
1262 xh%lx, xh%ly, xh%lz)
1263 call addtnsr(y, h(1, 1, ixt), ycrved, h(1, 3, izt), &
1264 xh%lx, xh%ly, xh%lz)
1265 else
1266 call addtnsr(x, xcrved, h(1, 2, iyt), h(1, 3, izt), &
1267 xh%lx, xh%ly, xh%lz)
1268 call addtnsr(y, ycrved, h(1, 2, iyt), h(1, 3, izt), &
1269 xh%lx, xh%ly, xh%lz)
1270 end if
1271 end subroutine arc_surface
1272
1273 !OCL SERIAL
1274 subroutine compute_h(h, zgml, gdim, lx)
1275 integer, intent(in) :: lx, gdim
1276 real(kind=rp), intent(inout) :: h(lx, 3, 2)
1277 real(kind=rp), intent(in) :: zgml(lx, 3)
1278 integer :: ix, iy, iz
1279
1280 do ix = 1, lx
1281 h(ix,1,1) = (1.0_rp - zgml(ix, 1)) * 0.5_rp
1282 h(ix,1,2) = (1.0_rp + zgml(ix, 1)) * 0.5_rp
1283 end do
1284
1285 do iy = 1, lx
1286 h(iy,2,1) = (1.0_rp - zgml(iy, 2)) * 0.5_rp
1287 h(iy,2,2) = (1.0_rp + zgml(iy, 2)) * 0.5_rp
1288 end do
1289
1290 if (gdim .eq. 3) then
1291 do iz = 1, lx
1292 h(iz,3,1) = (1.0_rp - zgml(iz, 3)) * 0.5_rp
1293 h(iz,3,2) = (1.0_rp + zgml(iz, 3)) * 0.5_rp
1294 end do
1295 else
1296 call rone(h(1,3,1), lx)
1297 call rone(h(1,3,2), lx)
1298 end if
1299
1300 end subroutine compute_h
1301
1306 subroutine dofmap_subset_by_mask(this, other, mask)
1307 class(dofmap_t), intent(inout) :: this
1308 class(dofmap_t), intent(inout) :: other
1309 type(mask_t), intent(in) :: mask
1310 integer :: i
1311
1312 ! Initialize the mesh subset_mesh in this
1313 ! Deallocate any previously allocated mesh subset
1314 if (allocated(this%msh_subset)) then
1315 call this%msh_subset%free()
1316 deallocate(this%msh_subset)
1317 end if
1318
1319 allocate(this%msh_subset)
1320 call this%msh%subset_by_mask(this%msh_subset, mask, &
1321 this%Xh%lx, this%Xh%ly, this%Xh%lz)
1322
1323 ! Initialize the other dofmap
1324 call other%init(this%msh_subset, this%Xh)
1325
1326 ! Overwrite dofmap in case it has been updated and
1327 ! the mesh has not.
1328 if (neko_bcknd_device .eq. 1) then
1329 call device_masked_gather_copy_aligned(other%x_d, &
1330 this%x_d, mask%get_d(), &
1331 this%size(), mask%size())
1332 call device_masked_gather_copy_aligned(other%y_d, &
1333 this%y_d, mask%get_d(), &
1334 this%size(), mask%size())
1335 call device_masked_gather_copy_aligned(other%z_d, &
1336 this%z_d, mask%get_d(), &
1337 this%size(), mask%size())
1338
1339 ! Sync with host
1340 call device_memcpy(other%x, other%x_d, other%ntot, &
1341 device_to_host, sync = .false.)
1342 call device_memcpy(other%y, other%y_d, other%ntot, &
1343 device_to_host, sync = .false.)
1344 call device_memcpy(other%z, other%z_d, other%ntot, &
1345 device_to_host, sync = .true.)
1346
1347 else
1348 call masked_gather_copy(other%x, this%x, mask%get(), &
1349 this%size(), mask%size())
1350 call masked_gather_copy(other%y, this%y, mask%get(), &
1351 this%size(), mask%size())
1352 call masked_gather_copy(other%z, this%z, mask%get(), &
1353 this%size(), mask%size())
1354 end if
1355
1356 end subroutine dofmap_subset_by_mask
1357
1358end module dofmap
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
subroutine, public device_copy(a_d, b_d, n, strm)
Copy a vector .
subroutine, public device_masked_gather_copy_aligned(a_d, b_d, mask_d, n, n_mask, strm)
Gather a masked 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
pure integer function dofmap_global_size(this)
Return the global number of dofs in the dofmap, lx*ly*lz*glb_nelv.
Definition dofmap.f90:258
subroutine gh_face_extend_2d(x, zg, n, gh_type, e, v)
Extend 2D faces into interior via gordon hall gh_type: 1 - vertex only 2 - vertex and faces.
Definition dofmap.f90:1125
subroutine dofmap_init_and_map(this, dof, xh)
Constructor.
Definition dofmap.f90:167
subroutine dofmap_generate_xyz(this)
Generate x,y,z-coordinates for all dofs.
Definition dofmap.f90:787
subroutine arc_surface(isid, curve_data, x, y, z, xh, element, gdim)
Definition dofmap.f90:1186
subroutine compute_h(h, zgml, gdim, lx)
Definition dofmap.f90:1275
subroutine dofmap_subset_by_mask(this, other, mask)
Generate/Initialize a new dofmap object based on a mask.
Definition dofmap.f90:1307
subroutine dofmap_xyzlin(xh, msh, element, x, y, z)
Generate the x, y, z coordinates of the dofs in a signle element, assuming linear element edges.
Definition dofmap.f90:854
subroutine dofmap_free(this)
Destructor.
Definition dofmap.f90:208
subroutine dofmap_number_edges(this)
Assing numbers to dofs on edges.
Definition dofmap.f90:287
subroutine dofmap_init(this, msh, xh)
Constructor.
Definition dofmap.f90:97
subroutine dofmap_number_points(this)
Assign numbers to each dofs on points.
Definition dofmap.f90:265
pure integer function dofmap_size(this)
Return the local number of dofs in the dofmap, lx*ly*lz*nelv.
Definition dofmap.f90:251
subroutine dofmap_xyzquad(xh, msh, element, x, y, z, curve_type, curve_data)
Definition dofmap.f90:930
subroutine dofmap_number_faces(this)
Assign numbers to dofs on faces.
Definition dofmap.f90:610
subroutine gh_face_extend_3d(x, zg, n, gh_type, e, v)
Extend faces into interior via gordon hall gh_type: 1 - vertex only 2 - vertex and edges 3 - vertex,...
Definition dofmap.f90:1012
pure integer(kind=i8) function dofmap_facetidx(face_order, face, facet_id, k1, j1, lk1, lj1)
Get idx for GLL point on face depending on face ordering k and j.
Definition dofmap.f90:731
Fast diagonalization methods from NEKTON.
Definition fast3d.f90:61
subroutine, public fd_weights_full(xi, x, n, m, c)
Compute finite-difference stencil weights for evaluating derivatives up to order at a point.
Definition fast3d.f90:106
Defines a hexahedron element.
Definition hex.f90:34
Routines to interpolate between different spaces.
Object for handling masks in Neko.
Definition mask.f90:34
Definition math.f90:60
subroutine, public rone(a, n)
Set all elements to one.
Definition math.f90:280
subroutine, public masked_gather_copy(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
Definition math.f90:423
subroutine, public add3(a, b, c, n)
Vector addition .
Definition math.f90:918
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:294
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:238
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public i8
Definition num_types.f90:7
integer, parameter, public i4
Definition num_types.f90:6
integer, parameter, public xp
Definition num_types.f90:16
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines a quadrilateral element.
Definition quad.f90:34
Defines a function space.
Definition space.f90:34
integer, parameter, public gll
Definition space.f90:50
Tensor operations.
Definition tensor.f90:61
subroutine, public addtnsr(s, h1, h2, h3, nx, ny, nz)
Maps and adds to S a tensor product form of the three functions H1,H2,H3. This is a single element ro...
Definition tensor.f90:280
subroutine, public trsp(a, lda, b, ldb)
Transpose of a rectangular tensor .
Definition tensor.f90:124
subroutine, public tensr3(v, nv, u, nu, a, bt, ct, w)
Tensor product .
Definition tensor.f90:94
subroutine, public tnsr2d_el(v, nv, u, nu, a, bt)
Computes .
Definition tensor.f90:157
Implements a n-tuple.
Definition tuple.f90:41
Utilities.
Definition utils.f90:35
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:398
Base type for an element.
Definition element.f90:44
Hexahedron element.
Definition hex.f90:63
Interpolation between two space::space_t.
Type for consistently handling masks in Neko. This type encapsulates the mask array and its associate...
Definition mask.f90:51
Quadrilateral element.
Definition quad.f90:58
The function space for the SEM solution fields.
Definition space.f90:64
Integer based 4-tuple.
Definition tuple.f90:76