Neko 0.9.99
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
map_1d.f90
Go to the documentation of this file.
1
3module map_1d
4 use num_types, only: rp
5 use space, only: space_t
6 use dofmap, only: dofmap_t
8 use mesh, only: mesh_t
9 use device
10 use comm
11 use coefs, only: coef_t
12 use field_list, only: field_list_t
13 use matrix, only: matrix_t
14 use vector, only: vector_ptr_t
15 use utils, only: neko_error, neko_warning
16 use math, only: glmax, glmin, glimax, relcmp, cmult, add2s1, col2
18 use, intrinsic :: iso_c_binding
19 implicit none
20 private
25 type, public :: map_1d_t
28 integer, allocatable :: dir_el(:)
30 integer, allocatable :: el_lvl(:)
32 integer, allocatable :: pt_lvl(:,:,:,:)
34 integer :: n_el_lvls
36 integer :: n_gll_lvls
39 type(dofmap_t), pointer :: dof => null()
41 type(coef_t), pointer :: coef => null()
43 type(mesh_t), pointer :: msh => null()
45 integer :: dir
47 real(kind=rp) :: tol = 1e-7
49 real(kind=rp), allocatable :: volume_per_gll_lvl(:)
50 contains
52 procedure, pass(this) :: init_int => map_1d_init
53
54 procedure, pass(this) :: init_char => map_1d_init_char
55 generic :: init => init_int, init_char
57 procedure, pass(this) :: free => map_1d_free
59 procedure, pass(this) :: average_planes_fld_lst => map_1d_average_field_list
60
61 procedure, pass(this) :: average_planes_vec_ptr => map_1d_average_vector_ptr
62 generic :: average_planes => average_planes_fld_lst, average_planes_vec_ptr
63 end type map_1d_t
64
65
66contains
67
68 subroutine map_1d_init(this, coef, dir, tol)
69 class(map_1d_t) :: this
70 type(coef_t), intent(inout), target :: coef
71 integer, intent(in) :: dir
72 real(kind=rp), intent(in) :: tol
73 integer :: nelv, lx, n, i, e, lvl, ierr
74 real(kind=rp), contiguous, pointer :: line(:,:,:,:)
75 real(kind=rp), allocatable :: min_vals(:,:,:,:)
76 real(kind=rp), allocatable :: min_temp(:,:,:,:)
77 type(c_ptr) :: min_vals_d = c_null_ptr
78 real(kind=rp) :: el_dim(3,3), glb_min, glb_max, el_min
79
80 call this%free()
81
82 if (neko_bcknd_device .eq. 1) then
83 if (pe_rank .eq. 0) then
84 call neko_warning('map_1d does not copy indices to device,'// &
85 ' but ok if used on cpu and for io')
86 end if
87 end if
88
89 this%dir = dir
90 this%dof => coef%dof
91 this%coef => coef
92 this%msh => coef%msh
93 nelv = this%msh%nelv
94 lx = this%dof%Xh%lx
95 n = this%dof%size()
96
97 if (dir .eq. 1) then
98 line => this%dof%x
99 else if (dir .eq. 2) then
100 line => this%dof%y
101 else if(dir .eq. 3) then
102 line => this%dof%z
103 else
104 call neko_error('Invalid dir for geopmetric comm')
105 end if
106 allocate(this%dir_el(nelv))
107 allocate(this%el_lvl(nelv))
108 allocate(this%pt_lvl(lx, lx, lx, nelv))
109 allocate(min_vals(lx, lx, lx, nelv))
110 allocate(min_temp(lx, lx, lx, nelv))
111 call mpi_barrier(neko_comm)
112 if (neko_bcknd_device .eq. 1) then
113
114 call device_map(min_vals,min_vals_d,n)
115 end if
116 call mpi_barrier(neko_comm)
117
118 do i = 1, nelv
119 !store which direction r,s,t corresponds to speciifed direction, x,y,z
120 !we assume elements are stacked on each other...
121 ! Check which one of the normalized vectors are closest to dir
122 ! If we want to incorporate other directions, we should look here
123 el_dim(1,:) = abs(this%msh%elements(i)%e%pts(1)%p%x - &
124 this%msh%elements(i)%e%pts(2)%p%x)
125 el_dim(1,:) = el_dim(1,:)/norm2(el_dim(1,:))
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(2,:) = el_dim(2,:)/norm2(el_dim(2,:))
129 el_dim(3,:) = abs(this%msh%elements(i)%e%pts(1)%p%x - &
130 this%msh%elements(i)%e%pts(5)%p%x)
131 el_dim(3,:) = el_dim(3,:)/norm2(el_dim(3,:))
132 ! Checks which directions in rst the xyz corresponds to
133 ! 1 corresponds to r, 2 to s, 3 to t and are stored in dir_el
134 this%dir_el(i) = maxloc(el_dim(:,this%dir),dim=1)
135 end do
136 glb_min = glmin(line,n)
137 glb_max = glmax(line,n)
138
139 i = 1
140 this%el_lvl = -1
141 ! Check what the mimum value in each element and put in min_vals
142 do e = 1, nelv
143 el_min = minval(line(:,:,:,e))
144 min_vals(:,:,:,e) = el_min
145 ! Check if this element is on the bottom, in this case assign el_lvl = i = 1
146 if (relcmp(el_min, glb_min, this%tol)) then
147 if(this%el_lvl(e) .eq. -1) this%el_lvl(e) = i
148 end if
149 end do
150 ! While loop where at each iteation the global maximum value
151 ! propagates down one level.
152 ! When the minumum value has propagated to the highest level this stops.
153 ! Only works when the bottom plate of the domain is flat.
154 do while (.not. relcmp(glmax(min_vals,n), glb_min, this%tol))
155 i = i + 1
156 do e = 1, nelv
157 !Sets the value at the bottom of each element to glb_max
158 if (this%dir_el(e) .eq. 1) then
159 if (line(1,1,1,e) .gt. line(lx,1,1,e)) then
160 min_vals(lx,:,:,e) = glb_max
161 else
162 min_vals(1,:,:,e) = glb_max
163 end if
164 end if
165 if (this%dir_el(e) .eq. 2) then
166 if (line(1,1,1,e) .gt. line(1,lx,1,e)) then
167 min_vals(:,lx,:,e) = glb_max
168 else
169 min_vals(:,1,:,e) = glb_max
170 end if
171 end if
172 if (this%dir_el(e) .eq. 3) then
173 if (line(1,1,1,e) .gt. line(1,1,lx,e)) then
174 min_vals(:,:,lx,e) = glb_max
175 else
176 min_vals(:,:,1,e) = glb_max
177 end if
178 end if
179 end do
180 !Make sketchy min as GS_OP_MIN is not supported with device mpi
181 min_temp = min_vals
182 if (neko_bcknd_device .eq. 1) &
183 call device_memcpy(min_vals, min_vals_d, n,&
184 host_to_device, sync=.false.)
185 !Propagates the minumum value along the element boundary.
186 call coef%gs_h%op(min_vals, n, gs_op_add)
187 if (neko_bcknd_device .eq. 1) &
188 call device_memcpy(min_vals, min_vals_d, n,&
189 device_to_host, sync=.true.)
190 !Obtain average along boundary
191
192 call col2(min_vals, coef%mult, n)
193 call cmult(min_temp, -1.0_rp, n)
194 call add2s1(min_vals, min_temp, 2.0_rp, n)
195
196
197 !Checks the new minimum value on each element
198 !Assign this value to all points in this element in min_val
199 !If the element has not already been assinged a level,
200 !and it has obtained the minval, set el_lvl = i
201 do e = 1, nelv
202 el_min = minval(min_vals(:,:,:,e))
203 min_vals(:,:,:,e) = el_min
204 if (relcmp(el_min, glb_min, this%tol)) then
205 if (this%el_lvl(e) .eq. -1) this%el_lvl(e) = i
206 end if
207 end do
208 end do
209 this%n_el_lvls = glimax(this%el_lvl,nelv)
210 this%n_gll_lvls = this%n_el_lvls*lx
211 !Numbers the points in each element based on the element level
212 !and its orientation
213 do e = 1, nelv
214 do i = 1, lx
215 lvl = lx * (this%el_lvl(e) - 1) + i
216 if (this%dir_el(e) .eq. 1) then
217 if (line(1,1,1,e) .gt. line(lx,1,1,e)) then
218 this%pt_lvl(lx-i+1,:,:,e) = lvl
219 else
220 this%pt_lvl(i,:,:,e) = lvl
221 end if
222 end if
223 if (this%dir_el(e) .eq. 2) then
224 if (line(1,1,1,e) .gt. line(1,lx,1,e)) then
225 this%pt_lvl(:,lx-i+1,:,e) = lvl
226 else
227 this%pt_lvl(:,i,:,e) = lvl
228 end if
229 end if
230 if (this%dir_el(e) .eq. 3) then
231 if (line(1,1,1,e) .gt. line(1,1,lx,e)) then
232 this%pt_lvl(:,:,lx-i+1,e) = lvl
233 else
234 this%pt_lvl(:,:,i,e) = lvl
235 end if
236 end if
237 end do
238 end do
239 if(allocated(min_vals)) deallocate(min_vals)
240 if(c_associated(min_vals_d)) call device_free(min_vals_d)
241 if(allocated(min_temp)) deallocate(min_temp)
242 allocate(this%volume_per_gll_lvl(this%n_gll_lvls))
243 this%volume_per_gll_lvl =0.0_rp
244 do i = 1, n
245 this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1)) = &
246 this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1)) + coef%B(i,1,1,1)
247 end do
248 call mpi_allreduce(mpi_in_place,this%volume_per_gll_lvl, this%n_gll_lvls, &
249 mpi_real_precision, mpi_sum, neko_comm, ierr)
250
251 end subroutine map_1d_init
252
253 subroutine map_1d_init_char(this, coef, dir, tol)
254 class(map_1d_t) :: this
255 type(coef_t), intent(inout), target :: coef
256 character(len=*), intent(in) :: dir
257 real(kind=rp), intent(in) :: tol
258 integer :: idir
259
260 if (trim(dir) .eq. 'yz' .or. trim(dir) .eq. 'zy') then
261 idir = 1
262 else if (trim(dir) .eq. 'xz' .or. trim(dir) .eq. 'zx') then
263 idir = 2
264 else if (trim(dir) .eq. 'xy' .or. trim(dir) .eq. 'yx') then
265 idir = 3
266 else
267 call neko_error('homogenous direction not supported')
268 end if
269
270 call this%init(coef,idir,tol)
271
272 end subroutine map_1d_init_char
273
274 subroutine map_1d_free(this)
275 class(map_1d_t) :: this
276
277 if(allocated(this%dir_el)) deallocate(this%dir_el)
278 if(allocated(this%el_lvl)) deallocate(this%el_lvl)
279 if(allocated(this%pt_lvl)) deallocate(this%pt_lvl)
280 if(associated(this%dof)) nullify(this%dof)
281 if(associated(this%msh)) nullify(this%msh)
282 if(associated(this%coef)) nullify(this%coef)
283 if(allocated(this%volume_per_gll_lvl)) deallocate(this%volume_per_gll_lvl)
284 this%dir = 0
285 this%n_el_lvls = 0
286 this%n_gll_lvls = 0
287
288 end subroutine map_1d_free
289
290
296 subroutine map_1d_average_field_list(this, avg_planes, field_list)
297 class(map_1d_t), intent(inout) :: this
298 type(field_list_t), intent(inout) :: field_list
299 type(matrix_t), intent(inout) :: avg_planes
300 integer :: n, ierr, j, i
301 real(kind=rp) :: coord
302 call avg_planes%free()
303 call avg_planes%init(this%n_gll_lvls, field_list%size()+1)
304 avg_planes = 0.0_rp
305 !ugly way of getting coordinates, computes average
306 n = this%dof%size()
307 do i = 1, n
308 if (this%dir .eq. 1) coord = this%dof%x(i,1,1,1)
309 if (this%dir .eq. 2) coord = this%dof%y(i,1,1,1)
310 if (this%dir .eq. 3) coord = this%dof%z(i,1,1,1)
311 avg_planes%x(this%pt_lvl(i,1,1,1),1) = &
312 avg_planes%x(this%pt_lvl(i,1,1,1),1) + coord*this%coef%B(i,1,1,1) &
313 /this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1))
314 end do
315 do j = 2, field_list%size() + 1
316 do i = 1, n
317 avg_planes%x(this%pt_lvl(i,1,1,1),j) = &
318 avg_planes%x(this%pt_lvl(i,1,1,1),j) + &
319 field_list%items(j-1)%ptr%x(i,1,1,1)*this%coef%B(i,1,1,1) &
320 /this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1))
321 end do
322 end do
323 if (pe_size .gt. 1) then
324 call mpi_allreduce(mpi_in_place, avg_planes%x, (field_list%size()+1)*this%n_gll_lvls, &
325 mpi_real_precision, mpi_sum, neko_comm, ierr)
326 end if
327
328
329 end subroutine map_1d_average_field_list
330
336 subroutine map_1d_average_vector_ptr(this, avg_planes, vector_ptr)
337 class(map_1d_t), intent(inout) :: this
338 !Observe is an array...
339 type(vector_ptr_t), intent(inout) :: vector_ptr(:)
340 type(matrix_t), intent(inout) :: avg_planes
341 integer :: n, ierr, j, i
342 real(kind=rp) :: coord
343
344 call avg_planes%free()
345 call avg_planes%init(this%n_gll_lvls,size(vector_ptr)+1)
346 !ugly way of getting coordinates, computes average
347 avg_planes = 0.0_rp
348
349 n = this%dof%size()
350 do i = 1, n
351 if (this%dir .eq. 1) coord = this%dof%x(i,1,1,1)
352 if (this%dir .eq. 2) coord = this%dof%y(i,1,1,1)
353 if (this%dir .eq. 3) coord = this%dof%z(i,1,1,1)
354 avg_planes%x(this%pt_lvl(i,1,1,1),1) = &
355 avg_planes%x(this%pt_lvl(i,1,1,1),1) + coord*this%coef%B(i,1,1,1) &
356 /this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1))
357 end do
358 do j = 2, size(vector_ptr)+1
359 do i = 1, n
360 avg_planes%x(this%pt_lvl(i,1,1,1),j) = &
361 avg_planes%x(this%pt_lvl(i,1,1,1),j) + &
362 vector_ptr(j-1)%ptr%x(i)*this%coef%B(i,1,1,1) &
363 /this%volume_per_gll_lvl(this%pt_lvl(i,1,1,1))
364 end do
365 end do
366 call mpi_allreduce(mpi_in_place,avg_planes%x, (size(vector_ptr)+1)*this%n_gll_lvls, &
367 mpi_real_precision, mpi_sum, neko_comm, ierr)
368
369
370 end subroutine map_1d_average_vector_ptr
371
372end module map_1d
Map a Fortran array to a device (allocate and associate)
Definition device.F90:57
Copy data between host and device (or device and device)
Definition device.F90:51
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
integer pe_rank
MPI rank.
Definition comm.F90:28
type(mpi_comm) neko_comm
MPI communicator.
Definition comm.F90:16
type(mpi_datatype) mpi_real_precision
MPI type for working precision of REAL types.
Definition comm.F90:23
integer pe_size
MPI size of communicator.
Definition comm.F90:31
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:47
subroutine, public device_free(x_d)
Deallocate memory on the device.
Definition device.F90:185
integer, parameter, public device_to_host
Definition device.F90:47
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Gather-scatter.
Creates a 1d GLL point map along a specified direction based on the connectivity in the mesh.
Definition map_1d.f90:3
subroutine map_1d_init(this, coef, dir, tol)
Definition map_1d.f90:69
subroutine map_1d_free(this)
Definition map_1d.f90:275
subroutine map_1d_average_field_list(this, avg_planes, field_list)
Computes average if field list in two directions and outputs matrix with averaged values avg_planes c...
Definition map_1d.f90:297
subroutine map_1d_init_char(this, coef, dir, tol)
Definition map_1d.f90:254
subroutine map_1d_average_vector_ptr(this, avg_planes, vector_ptr)
Computes average if vector_pt in two directions and outputs matrix with averaged values avg_planes co...
Definition map_1d.f90:337
Definition math.f90:60
subroutine, public cmult(a, c, n)
Multiplication by constant c .
Definition math.f90:310
subroutine, public add2s1(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on first argument)
Definition math.f90:657
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:728
real(kind=rp) function, public glmax(a, n)
Max of a vector of length n.
Definition math.f90:376
integer function, public glimax(a, n)
Max of an integer vector of length n.
Definition math.f90:391
real(kind=rp) function, public glmin(a, n)
Min of a vector of length n.
Definition math.f90:406
Defines a matrix.
Definition matrix.f90:34
Defines a mesh.
Definition mesh.f90:34
MPI derived types.
Definition mpi_types.f90:34
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Defines a function space.
Definition space.f90:34
Utilities.
Definition utils.f90:35
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:266
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:55
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:25
The function space for the SEM solution fields.
Definition space.f90:62