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