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