Neko  0.8.99
A portable framework for high-order spectral element flow simulations
map_1d.f90
Go to the documentation of this file.
1 
3 module 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 logger, only: neko_log, log_size
12  use utils, only: neko_error, neko_warning
13  use math, only: glmax, glmin, glimax, glimin, relcmp
14  use neko_mpi_types
15  use, intrinsic :: iso_c_binding
16  implicit none
17  private
21  type, public :: map_1d_t
23  integer, allocatable :: dir_el(:)
25  integer, allocatable :: el_lvl(:)
27  integer, allocatable :: pt_lvl(:,:,:,:)
29  integer :: n_el_lvls
31  type(dofmap_t), pointer :: dof => null()
33  type(mesh_t), pointer :: msh => null()
35  integer :: dir
37  real(kind=rp) :: tol = 1e-7
38  contains
40  procedure, pass(this) :: init => map_1d_init
42  procedure, pass(this) :: free => map_1d_free
43  end type map_1d_t
44 
45 
46 contains
47 
48  subroutine map_1d_init(this, dof, gs, dir, tol)
49  class(map_1d_t) :: this
50  type(dofmap_t), target, intent(in) :: dof
51  type(gs_t), intent(inout) :: gs
52  integer, intent(in) :: dir
53  real(kind=rp), intent(in) :: tol
54  integer :: nelv, lx, n, i, e, lvl
55  real(kind=rp), contiguous, pointer :: line(:,:,:,:)
56  real(kind=rp), allocatable :: min_vals(:,:,:,:)
57  type(c_ptr) :: min_vals_d = c_null_ptr
58  real(kind=rp) :: el_dim(3,3), glb_min, glb_max, el_min
59  call this%free()
60 
61  if (neko_bcknd_device .eq. 1) then
62  if (pe_rank .eq. 0) then
63  call neko_warning('map_1d does not copy indices to device, but ok if used on cpu')
64  end if
65  end if
66 
67  this%dir = dir
68  this%dof => dof
69  this%msh => dof%msh
70  nelv = this%msh%nelv
71  lx = this%dof%Xh%lx
72  n = dof%size()
73 
74  if (dir .eq. 1) then
75  line => dof%x
76  else if (dir .eq. 2) then
77  line => dof%y
78  else if(dir .eq. 3) then
79  line => dof%z
80  else
81  call neko_error('Invalid dir for geopmetric comm')
82  end if
83 
84  allocate(this%dir_el(nelv))
85  allocate(this%el_lvl(nelv))
86  allocate(min_vals(lx, lx, lx, nelv))
87  allocate(this%pt_lvl(lx, lx, lx, nelv))
88  if (neko_bcknd_device .eq. 1) then
89  call device_map(min_vals,min_vals_d,n)
90  end if
91 
92  do i = 1, nelv
93  !store which direction r,s,t corresponds to speciifed direction, x,y,z
94  !we assume elements are stacked on each other...
95  ! Check which one of the normalized vectors are closest to dir
96  ! If we want to incorporate other directions, we should look here
97  el_dim(1,:) = abs(this%msh%elements(i)%e%pts(1)%p%x - this%msh%elements(i)%e%pts(2)%p%x)
98  el_dim(1,:) = el_dim(1,:)/norm2(el_dim(1,:))
99  el_dim(2,:) = abs(this%msh%elements(i)%e%pts(1)%p%x - this%msh%elements(i)%e%pts(3)%p%x)
100  el_dim(2,:) = el_dim(2,:)/norm2(el_dim(2,:))
101  el_dim(3,:) = abs(this%msh%elements(i)%e%pts(1)%p%x - this%msh%elements(i)%e%pts(5)%p%x)
102  el_dim(3,:) = el_dim(3,:)/norm2(el_dim(3,:))
103  ! Checks which directions in rst the xyz corresponds to
104  ! 1 corresponds to r, 2 to s, 3 to t and are stored in dir_el
105  this%dir_el(i) = maxloc(el_dim(:,this%dir),dim=1)
106  end do
107  glb_min = glmin(line,n)
108  glb_max = glmax(line,n)
109 
110  i = 1
111  this%el_lvl = -1
112  ! Check what the mimum value in each element and put in min_vals
113  do e = 1, nelv
114  el_min = minval(line(:,:,:,e))
115  min_vals(:,:,:,e) = el_min
116  ! Check if this element is on the bottom, in this case assign el_lvl = i = 1
117  if (relcmp(el_min, glb_min, this%tol)) then
118  if(this%el_lvl(e) .eq. -1) this%el_lvl(e) = i
119  end if
120  end do
121  ! While loop where at each iteation the global maximum value propagates down one level.
122  ! When the minumum value has propagated to the highest level this stops.
123  ! Only works when the bottom plate of the domain is flat.
124  do while (.not. relcmp(glmax(min_vals,n), glb_min, this%tol))
125  i = i + 1
126  do e = 1, nelv
127  !Sets the value at the bottom of each element to glb_max
128  if (this%dir_el(e) .eq. 1) then
129  if (line(1,1,1,e) .gt. line(lx,1,1,e)) then
130  min_vals(lx,:,:,e) = glb_max
131  else
132  min_vals(1,:,:,e) = glb_max
133  end if
134  end if
135  if (this%dir_el(e) .eq. 2) then
136  if (line(1,1,1,e) .gt. line(1,lx,1,e)) then
137  min_vals(:,lx,:,e) = glb_max
138  else
139  min_vals(:,1,:,e) = glb_max
140  end if
141  end if
142  if (this%dir_el(e) .eq. 3) then
143  if (line(1,1,1,e) .gt. line(1,1,lx,e)) then
144  min_vals(:,:,lx,e) = glb_max
145  else
146  min_vals(:,:,1,e) = glb_max
147  end if
148  end if
149  end do
150  if (neko_bcknd_device .eq. 1) &
151  call device_memcpy(min_vals, min_vals_d, n,&
152  host_to_device, sync=.false.)
153  !Propagates the minumum value along the element boundary.
154  call gs%op(min_vals,n,gs_op_min)
155  if (neko_bcknd_device .eq. 1) &
156  call device_memcpy(min_vals, min_vals_d, n,&
157  device_to_host, sync=.true.)
158  !Checks the new minimum value on each element
159  !Assign this value to all points in this element in min_val
160  !If the element has not already been assinged a level,
161  !and it has obtained the minval, set el_lvl = i
162  do e = 1, nelv
163  el_min = minval(min_vals(:,:,:,e))
164  min_vals(:,:,:,e) = el_min
165  if (relcmp(el_min, glb_min, this%tol)) then
166  if (this%el_lvl(e) .eq. -1) this%el_lvl(e) = i
167  end if
168  end do
169  end do
170  this%n_el_lvls = glimax(this%el_lvl,nelv)
171  if ( pe_rank .eq. 0) then
172  write(*,*) 'Number of element levels', this%n_el_lvls
173  end if
174  !Numbers the points in each element based on the element level
175  !and its orientation
176  do e = 1, nelv
177  do i = 1, lx
178  lvl = lx * (this%el_lvl(e) - 1) + i
179  if (this%dir_el(e) .eq. 1) then
180  if (line(1,1,1,e) .gt. line(lx,1,1,e)) then
181  this%pt_lvl(lx-i+1,:,:,e) = lvl
182  else
183  this%pt_lvl(i,:,:,e) = lvl
184  end if
185  end if
186  if (this%dir_el(e) .eq. 2) then
187  if (line(1,1,1,e) .gt. line(1,lx,1,e)) then
188  this%pt_lvl(:,lx-i+1,:,e) = lvl
189  else
190  this%pt_lvl(:,i,:,e) = lvl
191  end if
192  end if
193  if (this%dir_el(e) .eq. 3) then
194  if (line(1,1,1,e) .gt. line(1,1,lx,e)) then
195  this%pt_lvl(:,:,lx-i+1,e) = lvl
196  else
197  this%pt_lvl(:,:,i,e) = lvl
198  end if
199  end if
200  end do
201  end do
202  call device_deassociate(min_vals)
203  call device_free(min_vals_d)
204  deallocate(min_vals)
205  end subroutine map_1d_init
206 
207  subroutine map_1d_free(this)
208  class(map_1d_t) :: this
209 
210  if(allocated(this%dir_el)) deallocate(this%dir_el)
211  if(allocated(this%el_lvl)) deallocate(this%el_lvl)
212  if(allocated(this%pt_lvl)) deallocate(this%pt_lvl)
213  if(associated(this%dof)) nullify(this%dof)
214  if(associated(this%msh)) nullify(this%msh)
215  this%dir = 0
216  this%n_el_lvls = 0
217 
218  end subroutine map_1d_free
219 
220 end module map_1d
Deassociate a Fortran array from a device pointer.
Definition: device.F90:75
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
Definition: comm.F90:1
integer pe_rank
MPI rank.
Definition: comm.F90:26
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:61
integer, parameter, public log_size
Definition: log.f90:40
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_free(this)
Definition: map_1d.f90:208
subroutine map_1d_init(this, dof, gs, dir, tol)
Definition: map_1d.f90:49
Definition: math.f90:60
integer function, public glimin(a, n)
Min of an integer vector of length n.
Definition: math.f90:383
real(kind=rp) function, public glmax(a, n)
Max of a vector of length n.
Definition: math.f90:341
integer function, public glimax(a, n)
Max of an integer vector of length n.
Definition: math.f90:355
real(kind=rp) function, public glmin(a, n)
Min of a vector of length n.
Definition: math.f90:369
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)
Definition: utils.f90:198
Type that encapsulates a mapping from each gll point in the mesh to its corresponding (global) GLL po...
Definition: map_1d.f90:21
The function space for the SEM solution fields.
Definition: space.f90:62