Neko-TOP
A portable framework for high-order spectral element flow toplogy optimization.
Loading...
Searching...
No Matches
normal_vec_bcs.f90
Go to the documentation of this file.
1
35module normal_vec_bcs
36 use num_types, only : rp
37 use neko_config, only : neko_bcknd_device
38 use vector, only : vector_t
39 use coefs, only : coef_t
40 use bc, only : bc_t, bc_dirichlet
41 use utils, only : neko_error, nonlinear_index
42 use json_module, only : json_file
43 use, intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr, c_associated
44 use htable, only : htable_i4_t
45 use device, only : device_map, device_memcpy, device_unmap, &
46 host_to_device
47 use time_state, only : time_state_t
48 implicit none
49 private
50
52 type, public, extends(bc_t) :: normal_vec_bcs_t
53 integer, allocatable :: unique_mask(:)
54 type(c_ptr) :: unique_mask_d = c_null_ptr
55 type(vector_t) :: nx, ny, nz, work
56 contains
57 procedure, pass(this) :: apply_scalar => normal_vec_bcs_apply_scalar
58 procedure, pass(this) :: apply_scalar_dev => &
59 normal_vec_bcs_apply_scalar_dev
60 procedure, pass(this) :: apply_vector => normal_vec_bcs_apply_vector
61 procedure, pass(this) :: apply_vector_dev => &
62 normal_vec_bcs_apply_vector_dev
63 procedure, pass(this) :: apply_n_dot => normal_vec_bcs_apply_n_dot
64 procedure, pass(this) :: apply_n_cross => normal_vec_bcs_apply_n_cross
66 procedure, pass(this) :: init => normal_vec_bcs_init
68 procedure, pass(this) :: init_from_components => &
69 normal_vec_bcs_init_from_components
71 procedure, pass(this) :: free => normal_vec_bcs_free
73 procedure, pass(this) :: finalize => normal_vec_bcs_finalize
74 end type normal_vec_bcs_t
75
76contains
77
82 subroutine normal_vec_bcs_init(this, coef, json)
83 class(normal_vec_bcs_t), intent(inout), target :: this
84 type(coef_t), target, intent(in) :: coef
85 type(json_file), intent(inout) ::json
86
87 call this%init_from_components(coef)
88 end subroutine normal_vec_bcs_init
89
93 subroutine normal_vec_bcs_init_from_components(this, coef)
94 class(normal_vec_bcs_t), intent(inout), target :: this
95 type(coef_t), target, intent(in) :: coef
96
97 call this%init_base(coef)
98 this%bc_type = bc_dirichlet
99 end subroutine normal_vec_bcs_init_from_components
100
107 subroutine normal_vec_bcs_apply_scalar(this, x, n, time, strong)
108 class(normal_vec_bcs_t), intent(inout) :: this
109 integer, intent(in) :: n
110 real(kind=rp), intent(inout), dimension(n) :: x
111 type(time_state_t), intent(in), optional :: time
112 logical, intent(in), optional :: strong
113 end subroutine normal_vec_bcs_apply_scalar
114
121 subroutine normal_vec_bcs_apply_scalar_dev(this, x_d, time, strong, strm)
122 class(normal_vec_bcs_t), intent(inout), target :: this
123 type(c_ptr),intent(inout) :: x_d
124 type(time_state_t), intent(in), optional :: time
125 logical, intent(in), optional :: strong
126 type(c_ptr), intent(inout) :: strm
127
128 end subroutine normal_vec_bcs_apply_scalar_dev
129
138 subroutine normal_vec_bcs_apply_vector_dev(this, x_d, y_d, z_d, time, &
139 strong, strm)
140 class(normal_vec_bcs_t), intent(inout), target :: this
141 type(c_ptr), intent(inout) :: x_d
142 type(c_ptr), intent(inout) :: y_d
143 type(c_ptr), intent(inout) :: z_d
144 type(time_state_t), intent(in), optional :: time
145 logical, intent(in), optional :: strong
146 type(c_ptr), intent(inout) :: strm
147
148 end subroutine normal_vec_bcs_apply_vector_dev
149
158 subroutine normal_vec_bcs_apply_vector(this, x, y, z, n, time, strong)
159 class(normal_vec_bcs_t), intent(inout) :: this
160 integer, intent(in) :: n
161 real(kind=rp), intent(inout), dimension(n) :: x
162 real(kind=rp), intent(inout), dimension(n) :: y
163 real(kind=rp), intent(inout), dimension(n) :: z
164 type(time_state_t), intent(in), optional :: time
165 logical, intent(in), optional :: strong
166 end subroutine normal_vec_bcs_apply_vector
167
176 subroutine normal_vec_bcs_apply_n_dot(this, f, u, v, w, n, time)
177 class(normal_vec_bcs_t), intent(in) :: this
178 integer, intent(in) :: n
179 real(kind=rp), intent(inout), dimension(n) :: f
180 real(kind=rp), intent(inout), dimension(n) :: u
181 real(kind=rp), intent(inout), dimension(n) :: v
182 real(kind=rp), intent(inout), dimension(n) :: w
183 type(time_state_t), intent(in), optional :: time
184 integer :: i, m, k
185
186 m = this%unique_mask(0)
187
188 ! This should be implemented n dot u weighted by the 2D mass matrix, which
189 ! I believe is the area, and it appears that n is weighted by the area.
190 do i = 1, m
191 k = this%unique_mask(i)
192 f(k) = u(k) * this%nx%x(i) + v(k) * this%ny%x(i) + w(k) * this%nz%x(i)
193 end do
194
195 end subroutine normal_vec_bcs_apply_n_dot
196
207 subroutine normal_vec_bcs_apply_n_cross(this, x, y, z, u, v, w, n, time)
208 class(normal_vec_bcs_t), intent(in) :: this
209 integer, intent(in) :: n
210 real(kind=rp), intent(inout), dimension(n) :: x
211 real(kind=rp), intent(inout), dimension(n) :: y
212 real(kind=rp), intent(inout), dimension(n) :: z
213 real(kind=rp), intent(inout), dimension(n) :: u
214 real(kind=rp), intent(inout), dimension(n) :: v
215 real(kind=rp), intent(inout), dimension(n) :: w
216 type(time_state_t), intent(in), optional :: time
217 integer :: i, m, k
218
219 m = this%unique_mask(0)
220
221 do i = 1, m
222 k = this%unique_mask(i)
223 x(k) = this%ny%x(i) * w(k) - this%nz%x(i) * v(k)
224 y(k) = this%nz%x(i) * u(k) - this%nx%x(i) * w(k)
225 z(k) = this%nx%x(i) * v(k) - this%ny%x(i) * u(k)
226 end do
227
228 end subroutine normal_vec_bcs_apply_n_cross
229
232 subroutine normal_vec_bcs_free(this)
233 class(normal_vec_bcs_t), target, intent(inout) :: this
234
235 call this%free_base()
236 if (allocated(this%unique_mask)) then
237 if (c_associated(this%unique_mask_d)) then
238 call device_unmap(this%unique_mask, this%unique_mask_d)
239 end if
240 deallocate(this%unique_mask)
241 end if
242
243 call this%nx%free()
244 call this%ny%free()
245 call this%nz%free()
246 call this%work%free()
247
248 end subroutine normal_vec_bcs_free
249
252 subroutine normal_vec_bcs_finalize(this)
253 class(normal_vec_bcs_t), target, intent(inout) :: this
254 type(htable_i4_t) :: unique_point_idx
255 integer :: htable_data, rcode, i, j, idx(4), facet
256 real(kind=rp) :: area, normal(3)
257
258 call this%finalize_base()
259 ! This part is purely needed to ensure that contributions
260 ! for all faces a point is on is properly summed up.
261 ! If one simply uses the original mask, if a point is on a corner
262 ! where both faces are on the boundary
263 ! one will only get the contribution from one face, not both
264 ! We solve this by adding up the normals of both faces for these points
265 ! and storing this sum in this%nx, this%ny, this%nz.
266 ! As both contrbutions are added already,
267 ! we also ensure that we only visit each point once
268 ! and create a new mask with only unique points (this%unique_mask).
269 if (allocated(this%unique_mask)) then
270 if (c_associated(this%unique_mask_d)) then
271 call device_unmap(this%unique_mask, this%unique_mask_d)
272 end if
273 deallocate(this%unique_mask)
274 end if
275
276 call unique_point_idx%init(this%facet_node_msk(0), htable_data)
277 j = 0
278 do i = 1, this%facet_node_msk(0)
279 if (unique_point_idx%get(this%facet_node_msk(i), htable_data) .ne. 0) then
280 j = j + 1
281 htable_data = j
282 call unique_point_idx%set(this%facet_node_msk(i), j)
283 end if
284 end do
285
286 ! Only allocate work vectors if size is non-zero
287 if (unique_point_idx%num_entries() .gt. 0 ) then
288 call this%nx%init(unique_point_idx%num_entries())
289 call this%ny%init(unique_point_idx%num_entries())
290 call this%nz%init(unique_point_idx%num_entries())
291 call this%work%init(unique_point_idx%num_entries())
292 end if
293 allocate(this%unique_mask(0:unique_point_idx%num_entries()))
294
295 this%unique_mask(0) = unique_point_idx%num_entries()
296 do i = 1, this%unique_mask(0)
297 this%unique_mask(i) = 0
298 end do
299
300
301 do i = 1, this%facet_node_msk(0)
302 rcode = unique_point_idx%get(this%facet_node_msk(i), htable_data)
303 if (rcode .ne. 0) call neko_error("Facet normal: htable get failed.")
304 this%unique_mask(htable_data) = this%facet_node_msk(i)
305 facet = this%facet(i)
306
307 idx = nonlinear_index(this%facet_node_msk(i), this%Xh%lx, this%Xh%lx, &
308 this%Xh%lx)
309 normal = this%coef%get_normal(idx(1), idx(2), idx(3), idx(4), facet)
310 area = this%coef%get_area(idx(1), idx(2), idx(3), idx(4), facet)
311 normal = normal * area !Scale normal by area
312 this%nx%x(htable_data) = this%nx%x(htable_data) + normal(1)
313 this%ny%x(htable_data) = this%ny%x(htable_data) + normal(2)
314 this%nz%x(htable_data) = this%nz%x(htable_data) + normal(3)
315 end do
316
317 if (neko_bcknd_device .eq. 1 .and. &
318 (unique_point_idx%num_entries() .gt. 0 )) then
319 call device_map(this%unique_mask, this%unique_mask_d, &
320 size(this%unique_mask))
321 call device_memcpy(this%unique_mask, this%unique_mask_d, &
322 size(this%unique_mask), host_to_device, sync = .true.)
323 call device_memcpy(this%nx%x, this%nx%x_d, &
324 this%nx%size(), host_to_device, sync = .true.)
325 call device_memcpy(this%ny%x, this%ny%x_d, &
326 this%ny%size(), host_to_device, sync = .true.)
327 call device_memcpy(this%nz%x, this%nz%x_d, &
328 this%nz%size(), host_to_device, sync = .true.)
329 end if
330
331 call unique_point_idx%free()
332
333 end subroutine normal_vec_bcs_finalize
334
335end module normal_vec_bcs
Dirichlet condition in facet normal direction.