150 type(
coef_t),
intent(inout),
target :: coef
151 integer,
intent(in) :: dir
152 real(kind=
rp),
intent(in) :: tol
153 integer :: nelv, lx, n, i, e, lvl, ierr
154 real(kind=
rp),
contiguous,
pointer :: line(:, :, :, :)
155 real(kind=
rp),
allocatable :: min_vals(:, :, :, :)
156 real(kind=
rp),
allocatable :: min_temp(:, :, :, :)
157 type(c_ptr) :: min_vals_d = c_null_ptr
158 real(kind=
rp) :: el_dim(3, 3), glb_min, glb_max, el_min, abs_tol
164 call neko_warning(
'map_1d does not copy indices to device, ' // &
165 ' but ok if used on cpu and for io')
180 else if (dir .eq. 2)
then
182 else if (dir .eq. 3)
then
185 call neko_error(
'Invalid dir for geopmetric comm')
187 allocate(this%dir_el(nelv))
188 allocate(this%el_lvl(nelv))
189 allocate(this%pt_lvl(lx, lx, lx, nelv))
190 allocate(min_vals(lx, lx, lx, nelv))
191 allocate(min_temp(lx, lx, lx, nelv))
206 el_dim(1, :) = abs(this%msh%elements(i)%e%pts(1)%p%x - &
207 this%msh%elements(i)%e%pts(2)%p%x)
208 el_dim(1, :) = el_dim(1, :)/norm2(el_dim(1, :))
209 el_dim(2, :) = abs(this%msh%elements(i)%e%pts(1)%p%x - &
210 this%msh%elements(i)%e%pts(3)%p%x)
211 el_dim(2, :) = el_dim(2, :)/norm2(el_dim(2, :))
212 el_dim(3, :) = abs(this%msh%elements(i)%e%pts(1)%p%x - &
213 this%msh%elements(i)%e%pts(5)%p%x)
214 el_dim(3, :) = el_dim(3, :)/norm2(el_dim(3, :))
217 this%dir_el(i) = maxloc(el_dim(:, this%dir), dim = 1)
220 glb_min =
glmin(line, n)
221 glb_max =
glmax(line, n)
234 abs_tol =
max(this%tol * (glb_max - glb_min), &
235 8.0_rp * epsilon(1.0_rp) *
max(abs(glb_min), abs(glb_max)))
241 el_min = minval(line(:, :, :, e))
244 if (abs(el_min - glb_min) .le. abs_tol)
then
246 if (this%el_lvl(e) .eq. -1) this%el_lvl(e) = i
248 min_vals(:, :, :, e) = el_min
255 do while (abs(
glmax(min_vals, n) - glb_min) .gt. abs_tol)
262 if (i .gt. this%msh%glb_nelv)
exit
266 if (this%dir_el(e) .eq. 1)
then
267 if (line(1, 1, 1, e) .gt. line(lx, 1, 1, e))
then
268 min_vals(lx, :, :, e) = glb_max
270 min_vals(1, :, :, e) = glb_max
273 if (this%dir_el(e) .eq. 2)
then
274 if (line(1, 1, 1, e) .gt. line(1, lx, 1, e))
then
275 min_vals(:, lx, :, e) = glb_max
277 min_vals(:, 1, :, e) = glb_max
280 if (this%dir_el(e) .eq. 3)
then
281 if (line(1, 1, 1, e) .gt. line(1, 1, lx, e))
then
282 min_vals(:, :, lx, e) = glb_max
284 min_vals(:, :, 1, e) = glb_max
298 call coef%gs_h%op(min_vals, n, gs_op_add)
306 call col2(min_vals, coef%mult, n)
307 call cmult(min_temp, -1.0_rp, n)
308 call add2s1(min_vals, min_temp, 2.0_rp, n)
315 el_min = minval(min_vals(:, :, :, e))
316 if (abs(el_min - glb_min) .le. abs_tol)
then
320 if (this%el_lvl(e) .eq. -1) this%el_lvl(e) = i
322 min_vals(:, :, :, e) = el_min
326 if (
allocated(min_vals))
then
327 if (c_associated(min_vals_d))
call device_unmap(min_vals, min_vals_d)
331 if (
allocated(min_temp))
deallocate(min_temp)
337 if (
glimin(this%el_lvl, nelv) .lt. 1)
then
338 call neko_error(
'map_1d: some elements were not assigned a level, ' // &
339 'check that the mesh is layered in the requested direction')
342 this%n_el_lvls =
glimax(this%el_lvl, nelv)
343 this%n_gll_lvls = this%n_el_lvls*lx
349 lvl = lx * (this%el_lvl(e) - 1) + i
350 if (this%dir_el(e) .eq. 1)
then
351 if (line(1, 1, 1, e) .gt. line(lx, 1, 1, e))
then
352 this%pt_lvl(lx-i+1, :, :, e) = lvl
354 this%pt_lvl(i, :, :, e) = lvl
357 if (this%dir_el(e) .eq. 2)
then
358 if (line(1, 1, 1, e) .gt. line(1, lx, 1, e))
then
359 this%pt_lvl(:, lx-i+1, :, e) = lvl
361 this%pt_lvl(:, i, :, e) = lvl
364 if (this%dir_el(e) .eq. 3)
then
365 if (line(1, 1, 1, e) .gt. line(1, 1, lx, e))
then
366 this%pt_lvl(:, :, lx-i+1, e) = lvl
368 this%pt_lvl(:, :, i, e) = lvl
374 allocate(this%volume_per_gll_lvl(this%n_gll_lvls))
376 this%volume_per_gll_lvl = 0.0_rp
379 this%volume_per_gll_lvl(this%pt_lvl(i, 1, 1, 1)) = &
380 this%volume_per_gll_lvl(this%pt_lvl(i, 1, 1, 1)) + &
384 call mpi_allreduce(mpi_in_place, this%volume_per_gll_lvl, this%n_gll_lvls, &
434 class(
map_1d_t),
intent(inout) :: this
436 type(
matrix_t),
intent(inout) :: avg_planes
437 integer :: n, ierr, j, i
438 real(kind=
rp) :: coord
439 call avg_planes%free()
440 call avg_planes%init(this%n_gll_lvls,
field_list%size() + 1)
445 if (this%dir .eq. 1) coord = this%dof%x%x(i,1,1,1)
446 if (this%dir .eq. 2) coord = this%dof%y%x(i,1,1,1)
447 if (this%dir .eq. 3) coord = this%dof%z%x(i,1,1,1)
448 avg_planes%x(this%pt_lvl(i,1,1,1), 1) = &
449 avg_planes%x(this%pt_lvl(i,1,1,1), 1) + &
450 coord * this%coef%B(i,1,1,1) / &
451 this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1))
455 avg_planes%x(this%pt_lvl(i,1,1,1), j) = &
456 avg_planes%x(this%pt_lvl(i,1,1,1), j) + &
457 field_list%items(j-1)%ptr%x(i,1,1,1) * this%coef%B(i,1,1,1) &
458 /this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1))
462 call mpi_allreduce(mpi_in_place, avg_planes%x, &
475 class(
map_1d_t),
intent(inout) :: this
478 type(
matrix_t),
intent(inout) :: avg_planes
479 integer :: n, ierr, j, i
480 real(kind=
rp) :: coord
482 call avg_planes%free()
483 call avg_planes%init(this%n_gll_lvls,
size(vector_ptr) + 1)
489 if (this%dir .eq. 1) coord = this%dof%x%x(i,1,1,1)
490 if (this%dir .eq. 2) coord = this%dof%y%x(i,1,1,1)
491 if (this%dir .eq. 3) coord = this%dof%z%x(i,1,1,1)
492 avg_planes%x(this%pt_lvl(i,1,1,1), 1) = &
493 avg_planes%x(this%pt_lvl(i,1,1,1), 1) + &
494 coord * this%coef%B(i,1,1,1) / &
495 this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1))
497 do j = 2,
size(vector_ptr) + 1
499 avg_planes%x(this%pt_lvl(i,1,1,1), j) = &
500 avg_planes%x(this%pt_lvl(i,1,1,1), j) + &
501 vector_ptr(j-1)%ptr%x(i)*this%coef%B(i,1,1,1) &
502 /this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1))
505 call mpi_allreduce(mpi_in_place, avg_planes%x, &