Neko 1.99.2
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
map_2d.f90
Go to the documentation of this file.
1
2
3module map_2d
5 use num_types, only: rp
6 use dofmap, only: dofmap_t
7 use map_1d, only : map_1d_t
8 use gather_scatter, only : gs_t, gs_op_add
9 use mesh, only: mesh_t
10 use field_list, only : field_list_t
11 use coefs, only: coef_t
12 use vector, only: vector_ptr_t
13 use utils, only: neko_error, linear_index
14 use math, only: cmult, col2, copy, rzero
15 use field, only : field_t
16 use, intrinsic :: iso_c_binding
18 use comm, only : neko_comm
20 use mpi_f08, only : mpi_allreduce, mpi_integer, mpi_sum, mpi_exscan
22 implicit none
23 private
24
25 type, public :: map_2d_t
26 integer :: nelv_2d = 0
27 integer :: glb_nelv_2d = 0
28 integer :: offset_el_2d = 0
29 integer :: lxy = 0
30 integer :: n_2d = 0
31 integer, allocatable :: idx_2d(:)
32 integer, allocatable :: el_idx_2d(:)
34 type(mesh_t), pointer :: msh
35 type(dofmap_t), pointer :: dof => null()
36 type(coef_t), pointer :: coef => null()
37 type(field_t) :: u
38 type(field_t) :: old_u
39 type(field_t) :: avg_u
40 type(field_t) :: el_heights
41 integer :: dir
42 real(kind=rp) :: domain_height
43 contains
44 procedure, pass(this) :: init_int => map_2d_init
45 procedure, pass(this) :: init_char => map_2d_init_char
46 procedure, pass(this) :: free => map_2d_free
47 generic :: init => init_int, init_char
48 procedure, pass(this) :: average_file => map_2d_average
49 procedure, pass(this) :: average_list => map_2d_average_field_list
50 generic :: average => average_list, average_file
51 end type map_2d_t
52
53contains
54
55 subroutine map_2d_init(this, coef, dir, tol)
56 class(map_2d_t), intent(inout) :: this
57 type(coef_t), intent(inout), target :: coef
58 integer, intent(in) :: dir
59 real(kind=rp), intent(in) :: tol
60 real(kind=rp) :: el_dim(3,3), el_h
61 integer :: i, e, j, ierr, k, lx, lxy, n
62 call this%map_1d%init(coef,dir,tol)
63 this%msh => coef%msh
64 this%coef => coef
65 this%dof => coef%dof
66
67 call this%u%init(this%dof)
68 call this%old_u%init(this%dof)
69 call this%avg_u%init(this%dof)
70 call this%el_heights%init(this%dof)
71 this%dir = dir
72
73 n = this%dof%size()
74 lx = this%dof%Xh%lx
75 lxy = this%dof%Xh%lxy
76 this%nelv_2d = 0
77 do i = 1, this%msh%nelv
78 if (this%map_1d%el_lvl(i) .eq. 1) then
79 this%nelv_2d = this%nelv_2d + 1
80 end if
81 end do
82 this%glb_nelv_2d = 0
83 call mpi_allreduce(this%nelv_2d, this%glb_nelv_2d, 1, &
84 mpi_integer, mpi_sum, neko_comm, ierr)
85
86 this%offset_el_2d = 0
87 call mpi_exscan(this%nelv_2d, this%offset_el_2d, 1, &
88 mpi_integer, mpi_sum, neko_comm, ierr)
89 allocate(this%el_idx_2d(this%nelv_2d))
90 do i = 1, this%nelv_2d
91 this%el_idx_2d(i) = this%offset_el_2d + i
92 end do
93 this%n_2d = this%nelv_2d*lxy
94 allocate(this%idx_2d(this%n_2d))
95
96 j = 0
97 do e = 1, this%msh%nelv
98 if (this%map_1d%el_lvl(e) .eq. 1) then
99 if (this%map_1d%dir_el(e) .eq. 1) then
100 do i = 1, lxy
101 this%idx_2d(j*lxy+i) = linear_index(1,i,1,e,lx,lx,lx)
102 end do
103 end if
104 if (this%map_1d%dir_el(e) .eq. 2) then
105 do i = 1, lx
106 do k = 1, lx
107 this%idx_2d(j*lxy+k+lx*(i-1)) = linear_index(k,1,i,e,lx,lx,lx)
108 end do
109 end do
110 end if
111 if (this%map_1d%dir_el(e) .eq. 3) then
112 do i = 1, lxy
113 this%idx_2d(j*lxy+i) = linear_index(i,1,1,e,lx,lx,lx)
114 end do
115 end if
116 j = j +1
117 end if
118 end do
119 do i = 1, this%msh%nelv
120 !find height in hom-dir
121 !direction in local coords (r,s,t) that is hom is stored in map_1d%dir_el
122 !set element to height
123 !we assume elements are stacked on eachother...
124 el_dim(1,:) = abs(this%msh%elements(i)%e%pts(1)%p%x-&
125 this%msh%elements(i)%e%pts(2)%p%x)
126 el_dim(2,:) = abs(this%msh%elements(i)%e%pts(1)%p%x-&
127 this%msh%elements(i)%e%pts(3)%p%x)
128 el_dim(3,:) = abs(this%msh%elements(i)%e%pts(1)%p%x-&
129 this%msh%elements(i)%e%pts(5)%p%x)
130 ! 1 corresponds to x, 2 to y, 3 to z
131 el_h = el_dim(this%map_1d%dir_el(i),dir)
132 this%el_heights%x(:,:,:,i) = el_h
133 end do
134 !Need to compute mapping for 3d to 2d
135 !Does order matter? Think its ok as long as values written in same order
136
137 call copy(this%u%x,this%el_heights%x,n)
138 call copy(this%old_u%x,this%el_heights%x,n)
139 call copy(this%avg_u%x,this%el_heights%x,n)
140 call perform_global_summation(this%u, this%avg_u, this%old_u, &
141 this%map_1d%n_el_lvls, &
142 this%map_1d%dir_el,this%coef%gs_h, this%coef%mult, this%msh%nelv, lx)
143 this%domain_height = this%u%x(1,1,1,1)
144
145 end subroutine map_2d_init
146
147 subroutine map_2d_init_char(this, coef, dir, tol)
148 class(map_2d_t) :: this
149 type(coef_t), intent(inout), target :: coef
150 character(len=*), intent(in) :: dir
151 real(kind=rp), intent(in) :: tol
152 integer :: idir
153
154 if (trim(dir) .eq. 'x') then
155 idir = 1
156 else if (trim(dir) .eq. 'y') then
157 idir = 2
158 else if (trim(dir) .eq. 'z') then
159 idir = 3
160 else
161 call neko_error('Direction not supported, map_2d')
162 end if
163
164 call this%init(coef,idir,tol)
165
166 end subroutine map_2d_init_char
167
168 subroutine map_2d_free(this)
169 class(map_2d_t), intent(inout) :: this
170
171 if (allocated(this%idx_2d)) then
172 deallocate(this%idx_2d)
173 end if
174
175 if (allocated(this%el_idx_2d)) then
176 deallocate(this%el_idx_2d)
177 end if
178
179 nullify(this%msh)
180 nullify(this%dof)
181 nullify(this%coef)
182 end subroutine map_2d_free
183
184
189 subroutine map_2d_average_field_list(this, fld_data2D, fld_data3D)
190 class(map_2d_t), intent(inout) :: this
191 type(fld_file_data_t), intent(inout) :: fld_data2D
192 type(field_list_t), intent(inout) :: fld_data3D
193 real(kind=rp), pointer, contiguous, dimension(:,:,:,:) :: x_ptr, y_ptr
194
195 type(vector_ptr_t), allocatable :: fields2d(:)
196 integer :: n_2d, n
197 integer :: i, j, lx, lxy
198
199 call fld_data2d%init(this%nelv_2d, this%offset_el_2d)
200 fld_data2d%gdim = 2
201 fld_data2d%lx = this%dof%Xh%lx
202 fld_data2d%ly = this%dof%Xh%ly
203 fld_data2d%lz = 1
204 lx = this%dof%Xh%lx
205 fld_data2d%glb_nelv = this%glb_nelv_2d
206 lxy = fld_data2d%lx*fld_data2d%ly
207 n_2d = lxy*this%nelv_2d
208 n = this%dof%size()
209 call fld_data2d%x%init(n_2d)
210 call fld_data2d%y%init(n_2d)
211 allocate(fld_data2d%idx(this%nelv_2d))
212
213 if (this%dir .eq. 1) then
214 x_ptr => this%dof%z
215 y_ptr => this%dof%y
216 end if
217 if (this%dir .eq. 2) then
218 x_ptr => this%dof%x
219 y_ptr => this%dof%z
220 end if
221 if (this%dir .eq. 3) then
222 x_ptr => this%dof%x
223 y_ptr => this%dof%y
224 end if
225 do j = 1, this%nelv_2d
226 fld_data2d%idx(j) = this%el_idx_2d(j)
227 end do
228 do j = 1, n_2d
229 fld_data2d%x%x(j) = x_ptr(this%idx_2d(j),1,1,1)
230 fld_data2d%y%x(j) = y_ptr(this%idx_2d(j),1,1,1)
231 end do
232 allocate(fields2d(fld_data3d%size()))
233
234 call fld_data2d%init_n_fields(fld_data3d%size(), n_2d)
235 this%u = 0.0_rp
236 this%old_u = 0.0_rp
237 this%avg_u = 0.0_rp
238 do i = 1, fld_data3d%size()
239 call copy(this%old_u%x, fld_data3d%items(i)%ptr%x, n)
240 call perform_local_summation(this%u, this%old_u, &
241 this%el_heights, this%domain_height, &
242 this%map_1d%dir_el, this%coef, this%msh%nelv, lx)
243 call copy(this%old_u%x, this%u%x, n)
244 call copy(this%avg_u%x, this%u%x, n)
245 call perform_global_summation(this%u, this%avg_u, &
246 this%old_u, this%map_1d%n_el_lvls, &
247 this%map_1d%dir_el,this%coef%gs_h, this%coef%mult, &
248 this%msh%nelv, lx)
249 call copy(fld_data3d%items(i)%ptr%x, this%u%x, n)
250 end do
251 call fld_data2d%get_list(fields2d, fld_data2d%size())
252 do i = 1, fld_data3d%size()
253 do j = 1, n_2d
254 fields2d(i)%ptr%x(j) = fld_data3d%items(i)%ptr%x(this%idx_2d(j),1,1,1)
255 end do
256 end do
257
258 end subroutine map_2d_average_field_list
259
260
265 subroutine map_2d_average(this, fld_data2D, fld_data3D)
266 class(map_2d_t), intent(inout) :: this
267 type(fld_file_data_t), intent(inout) :: fld_data2D
268 type(fld_file_data_t), intent(inout) :: fld_data3D
269 real(kind=rp), pointer, dimension(:,:,:,:) :: x_ptr, y_ptr
270
271 type(vector_ptr_t), allocatable :: fields3d(:), fields2d(:)
272 integer :: n_2d, n
273 integer :: i, j, lx, lxy
274
275 call fld_data2d%init(this%nelv_2d, this%offset_el_2d)
276 fld_data2d%gdim = 2
277 fld_data2d%lx = this%dof%Xh%lx
278 fld_data2d%ly = this%dof%Xh%ly
279 fld_data2d%lz = 1
280 lx = this%dof%Xh%lx
281 fld_data2d%glb_nelv = this%glb_nelv_2d
282 lxy = fld_data2d%lx*fld_data2d%ly
283 n_2d = lxy*this%nelv_2d
284 n = this%dof%size()
285 call fld_data2d%x%init(n_2d)
286 call fld_data2d%y%init(n_2d)
287 allocate(fld_data2d%idx(n_2d))
288
289 if (this%dir .eq. 1) then
290 x_ptr => this%dof%z
291 y_ptr => this%dof%y
292 end if
293 if (this%dir .eq. 2) then
294 x_ptr => this%dof%x
295 y_ptr => this%dof%z
296 end if
297 if (this%dir .eq. 3) then
298 x_ptr => this%dof%x
299 y_ptr => this%dof%y
300 end if
301 do j = 1, n_2d
302 fld_data2d%idx(j) = this%idx_2d(j)
303 fld_data2d%x%x(j) = x_ptr(this%idx_2d(j),1,1,1)
304 fld_data2d%y%x(j) = y_ptr(this%idx_2d(j),1,1,1)
305 end do
306 allocate(fields3d(fld_data3d%size()))
307 allocate(fields2d(fld_data3d%size()))
308
309 call fld_data2d%init_n_fields(fld_data3d%size(), n_2d)
310 call fld_data3d%get_list(fields3d,fld_data3d%size())
311
312 this%u = 0.0_rp
313 this%old_u = 0.0_rp
314 this%avg_u = 0.0_rp
315 do i = 1, fld_data3d%size()
316 call copy(this%old_u%x, fields3d(i)%ptr%x, n)
317 call perform_local_summation(this%u,this%old_u,&
318 this%el_heights, this%domain_height, &
319 this%map_1d%dir_el, this%coef, this%msh%nelv, lx)
320 call copy(this%old_u%x, this%u%x,n)
321 call copy(this%avg_u%x, this%u%x,n)
322 call perform_global_summation(this%u, this%avg_u, &
323 this%old_u, this%map_1d%n_el_lvls, &
324 this%map_1d%dir_el, this%coef%gs_h,&
325 this%coef%mult, this%msh%nelv, lx)
326 call copy(fields3d(i)%ptr%x, this%u%x, n)
327 end do
328 call fld_data2d%get_list(fields2d, fld_data2d%size())
329 do i = 1, fld_data3d%size()
330 do j = 1, n_2d
331 fields2d(i)%ptr%x(j) = fields3d(i)%ptr%x(this%idx_2d(j))
332 end do
333 end do
334 end subroutine map_2d_average
335
336 subroutine perform_global_summation(u, avg_u, old_u, n_levels, &
337 hom_dir_el, gs_h, mult, nelv, lx)
338 type(field_t), intent(inout) :: u, avg_u, old_u
339 type(gs_t), intent(inout) :: gs_h
340 integer, intent(in) :: n_levels, nelv, lx
341 integer, intent(in) :: hom_dir_el(nelv)
342 real(kind=rp), intent(in) :: mult(nelv*lx**3)
343 real(kind=rp) :: temp_el(lx,lx,lx)
344 integer :: n, i, j, e
345
346 n = u%dof%size()
347
348 do i = 1, n_levels-1
349 !compute average
350 if (neko_bcknd_device .eq. 1) &
351 call device_memcpy(u%x, u%x_d, n, &
352 host_to_device, sync=.true.)
353 call gs_h%op(u,gs_op_add)
354 if (neko_bcknd_device .eq. 1) &
355 call device_memcpy(u%x, u%x_d, n, device_to_host, sync=.true.)
356 call col2(u%x,mult,n)
357 !Assumes sugarcube I think
358 do e = 1, nelv
359 temp_el = 2.0*u%x(:,:,:,e)-old_u%x(:,:,:,e)
360 if (hom_dir_el(e) .eq. 1) then
361 u%x(1,:,:,e) = temp_el(lx,:,:)
362 avg_u%x(1,:,:,e) = avg_u%x(1,:,:,e)+temp_el(1,:,:)
363 u%x(lx,:,:,e) = temp_el(1,:,:)
364 else if (hom_dir_el(e) .eq. 2) then
365 u%x(:,1,:,e) = temp_el(:,lx,:)
366 avg_u%x(:,1,:,e) = avg_u%x(:,1,:,e)+temp_el(:,1,:)
367 u%x(:,lx,:,e) = temp_el(:,1,:)
368 else if (hom_dir_el(e) .eq. 3) then
369 u%x(:,:,1,e) = temp_el(:,:,lx)
370 avg_u%x(:,:,1,e) = avg_u%x(:,:,1,e)+temp_el(:,:,1)
371 u%x(:,:,lx,e) = temp_el(:,:,1)
372 end if
373 old_u%x(:,:,:,e) = u%x(:,:,:,e)
374 end do
375 end do
376 do e = 1, nelv
377 do i = 1,lx
378 do j = 1, lx
379 if (hom_dir_el(e) .eq. 1) then
380 u%x(:,i,j,e) = avg_u%x(1,i,j,e)
381 else if (hom_dir_el(e) .eq. 2) then
382 u%x(i,:,j,e) = avg_u%x(i,1,j,e)
383 else if (hom_dir_el(e) .eq. 3) then
384 u%x(i,j,:,e) = avg_u%x(i,j,1,e)
385 end if
386 end do
387 end do
388 end do
389 end subroutine perform_global_summation
390
391 subroutine perform_local_summation(u_out, u, el_heights, domain_height,&
392 hom_dir_el, coef, nelv, lx)
393 type(field_t), intent(inout) :: u, u_out, el_heights
394 type(coef_t), intent(inout) :: coef
395 integer, intent(in) :: nelv, lx
396 integer, intent(in) :: hom_dir_el(nelv)
397 real(kind=rp), intent(in) :: domain_height
398 real(kind=rp) :: wt
399 integer :: n, i, j, e, k
400
401 n = nelv*lx**3
402
403 call col2(u%x,el_heights%x,n)
404 call cmult(u%x, 1.0_rp/(2.0*domain_height),n)
405 call rzero(u_out%x,n)
406
407
408 do e = 1, nelv
409 do i = 1,lx
410 do j = 1, lx
411 do k = 1, lx
412 wt = coef%Xh%wx(k)
413 if (hom_dir_el(e) .eq. 1) then
414 u_out%x(1,i,j,e) = u_out%x(1,i,j,e)+wt*u%x(k,i,j,e)
415 else if (hom_dir_el(e) .eq. 2) then
416 u_out%x(i,1,j,e) = u_out%x(i,1,j,e)+wt*u%x(i,k,j,e)
417 else if (hom_dir_el(e) .eq. 3) then
418 u_out%x(i,j,1,e) = u_out%x(i,j,1,e)+wt*u%x(i,j,k,e)
419 end if
420 end do
421 end do
422 end do
423 end do
424
425 do e = 1, nelv
426 do i = 1,lx
427 do j = 1, lx
428 if (hom_dir_el(e) .eq. 1) then
429 u_out%x(:,i,j,e) = u_out%x(1,i,j,e)
430 else if (hom_dir_el(e) .eq. 2) then
431 u_out%x(i,:,j,e) = u_out%x(i,1,j,e)
432 else if (hom_dir_el(e) .eq. 3) then
433 u_out%x(i,j,:,e) = u_out%x(i,j,1,e)
434 end if
435 end do
436 end do
437 end do
438 end subroutine perform_local_summation
439
440end module map_2d
Copy data between host and device (or device and device)
Definition device.F90:71
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:43
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:47
integer, parameter, public device_to_host
Definition device.F90:47
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Defines a field.
Definition field.f90:34
Simple module to handle fld file series. Provides an interface to the different fields sotred in a fl...
Gather-scatter.
Creates a 1d GLL point map along a specified direction based on the connectivity in the mesh.
Definition map_1d.f90:3
Maps a 3D dofmap to a 2D spectral element grid.
Definition map_2d.f90:3
subroutine map_2d_free(this)
Definition map_2d.f90:169
subroutine perform_local_summation(u_out, u, el_heights, domain_height, hom_dir_el, coef, nelv, lx)
Definition map_2d.f90:393
subroutine perform_global_summation(u, avg_u, old_u, n_levels, hom_dir_el, gs_h, mult, nelv, lx)
Definition map_2d.f90:338
subroutine map_2d_init(this, coef, dir, tol)
Definition map_2d.f90:56
subroutine map_2d_init_char(this, coef, dir, tol)
Definition map_2d.f90:148
subroutine map_2d_average_field_list(this, fld_data2d, fld_data3d)
Computes average if field list in one direction and outputs 2D field with averaged values.
Definition map_2d.f90:190
subroutine map_2d_average(this, fld_data2d, fld_data3d)
Computes average if field list in one direction and outputs 2D field with averaged values.
Definition map_2d.f90:266
Definition math.f90:60
subroutine, public cmult(a, c, n)
Multiplication by constant c .
Definition math.f90:411
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:854
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.f90:249
subroutine, public rzero(a, n)
Zero a real vector.
Definition math.f90:205
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Utilities.
Definition utils.f90:35
pure integer function, public linear_index(i, j, k, l, lx, ly, lz)
Compute the address of a (i,j,k,l) array with sizes (1:lx, 1:ly, 1:lz, :)
Definition utils.f90:237
Defines a vector.
Definition vector.f90:34
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:56
field_list_t, To be able to group fields together
Type that encapsulates a mapping from each gll point in the mesh to its corresponding (global) GLL po...
Definition map_1d.f90:27