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
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 end subroutine normal_vec_bcs_init_from_components
99
106 subroutine normal_vec_bcs_apply_scalar(this, x, n, time, strong)
107 class(normal_vec_bcs_t), intent(inout) :: this
108 integer, intent(in) :: n
109 real(kind=rp), intent(inout), dimension(n) :: x
110 type(time_state_t), intent(in), optional :: time
111 logical, intent(in), optional :: strong
112 end subroutine normal_vec_bcs_apply_scalar
113
120 subroutine normal_vec_bcs_apply_scalar_dev(this, x_d, time, strong, strm)
121 class(normal_vec_bcs_t), intent(inout), target :: this
122 type(c_ptr),intent(inout) :: x_d
123 type(time_state_t), intent(in), optional :: time
124 logical, intent(in), optional :: strong
125 type(c_ptr), intent(inout) :: strm
126
127 end subroutine normal_vec_bcs_apply_scalar_dev
128
137 subroutine normal_vec_bcs_apply_vector_dev(this, x_d, y_d, z_d, time, &
138 strong, strm)
139 class(normal_vec_bcs_t), intent(inout), target :: this
140 type(c_ptr), intent(inout) :: x_d
141 type(c_ptr), intent(inout) :: y_d
142 type(c_ptr), intent(inout) :: z_d
143 type(time_state_t), intent(in), optional :: time
144 logical, intent(in), optional :: strong
145 type(c_ptr), intent(inout) :: strm
146
147 end subroutine normal_vec_bcs_apply_vector_dev
148
157 subroutine normal_vec_bcs_apply_vector(this, x, y, z, n, time, strong)
158 class(normal_vec_bcs_t), intent(inout) :: this
159 integer, intent(in) :: n
160 real(kind=rp), intent(inout), dimension(n) :: x
161 real(kind=rp), intent(inout), dimension(n) :: y
162 real(kind=rp), intent(inout), dimension(n) :: z
163 type(time_state_t), intent(in), optional :: time
164 logical, intent(in), optional :: strong
165 end subroutine normal_vec_bcs_apply_vector
166
175 subroutine normal_vec_bcs_apply_n_dot(this, f, u, v, w, n, time)
176 class(normal_vec_bcs_t), intent(in) :: this
177 integer, intent(in) :: n
178 real(kind=rp), intent(inout), dimension(n) :: f
179 real(kind=rp), intent(inout), dimension(n) :: u
180 real(kind=rp), intent(inout), dimension(n) :: v
181 real(kind=rp), intent(inout), dimension(n) :: w
182 type(time_state_t), intent(in), optional :: time
183 integer :: i, m, k
184
185 m = this%unique_mask(0)
186
187 ! This should be implemented n dot u weighted by the 2D mass matrix, which
188 ! I believe is the area, and it appears that n is weighted by the area.
189 do i = 1, m
190 k = this%unique_mask(i)
191 f(k) = u(k) * this%nx%x(i) + v(k) * this%ny%x(i) + w(k) * this%nz%x(i)
192 end do
193
194 end subroutine normal_vec_bcs_apply_n_dot
195
206 subroutine normal_vec_bcs_apply_n_cross(this, x, y, z, u, v, w, n, time)
207 class(normal_vec_bcs_t), intent(in) :: this
208 integer, intent(in) :: n
209 real(kind=rp), intent(inout), dimension(n) :: x
210 real(kind=rp), intent(inout), dimension(n) :: y
211 real(kind=rp), intent(inout), dimension(n) :: z
212 real(kind=rp), intent(inout), dimension(n) :: u
213 real(kind=rp), intent(inout), dimension(n) :: v
214 real(kind=rp), intent(inout), dimension(n) :: w
215 type(time_state_t), intent(in), optional :: time
216 integer :: i, m, k
217
218 m = this%unique_mask(0)
219
220 do i = 1, m
221 k = this%unique_mask(i)
222 x(k) = this%ny%x(i) * w(k) - this%nz%x(i) * v(k)
223 y(k) = this%nz%x(i) * u(k) - this%nx%x(i) * w(k)
224 z(k) = this%nx%x(i) * v(k) - this%ny%x(i) * u(k)
225 end do
226
227 end subroutine normal_vec_bcs_apply_n_cross
228
231 subroutine normal_vec_bcs_free(this)
232 class(normal_vec_bcs_t), target, intent(inout) :: this
233
234 call this%free_base()
235 if (allocated(this%unique_mask)) then
236 if (c_associated(this%unique_mask_d)) then
237 call device_unmap(this%unique_mask, this%unique_mask_d)
238 end if
239 deallocate(this%unique_mask)
240 end if
241
242 call this%nx%free()
243 call this%ny%free()
244 call this%nz%free()
245 call this%work%free()
246
247 end subroutine normal_vec_bcs_free
248
251 subroutine normal_vec_bcs_finalize(this)
252 class(normal_vec_bcs_t), target, intent(inout) :: this
253 type(htable_i4_t) :: unique_point_idx
254 integer :: htable_data, rcode, i, j, idx(4), facet
255 real(kind=rp) :: area, normal(3)
256
257 call this%finalize_base()
258 ! This part is purely needed to ensure that contributions
259 ! for all faces a point is on is properly summed up.
260 ! If one simply uses the original mask, if a point is on a corner
261 ! where both faces are on the boundary
262 ! one will only get the contribution from one face, not both
263 ! We solve this by adding up the normals of both faces for these points
264 ! and storing this sum in this%nx, this%ny, this%nz.
265 ! As both contrbutions are added already,
266 ! we also ensure that we only visit each point once
267 ! and create a new mask with only unique points (this%unique_mask).
268 if (allocated(this%unique_mask)) then
269 if (c_associated(this%unique_mask_d)) then
270 call device_unmap(this%unique_mask, this%unique_mask_d)
271 end if
272 deallocate(this%unique_mask)
273 end if
274
275 call unique_point_idx%init(this%facet_node_msk(0), htable_data)
276 j = 0
277 do i = 1, this%facet_node_msk(0)
278 if (unique_point_idx%get(this%facet_node_msk(i), htable_data) .ne. 0) then
279 j = j + 1
280 htable_data = j
281 call unique_point_idx%set(this%facet_node_msk(i), j)
282 end if
283 end do
284
285 ! Only allocate work vectors if size is non-zero
286 if (unique_point_idx%num_entries() .gt. 0 ) then
287 call this%nx%init(unique_point_idx%num_entries())
288 call this%ny%init(unique_point_idx%num_entries())
289 call this%nz%init(unique_point_idx%num_entries())
290 call this%work%init(unique_point_idx%num_entries())
291 end if
292 allocate(this%unique_mask(0:unique_point_idx%num_entries()))
293
294 this%unique_mask(0) = unique_point_idx%num_entries()
295 do i = 1, this%unique_mask(0)
296 this%unique_mask(i) = 0
297 end do
298
299
300 do i = 1, this%facet_node_msk(0)
301 rcode = unique_point_idx%get(this%facet_node_msk(i), htable_data)
302 if (rcode .ne. 0) call neko_error("Facet normal: htable get failed.")
303 this%unique_mask(htable_data) = this%facet_node_msk(i)
304 facet = this%facet(i)
305
306 idx = nonlinear_index(this%facet_node_msk(i), this%Xh%lx, this%Xh%lx, &
307 this%Xh%lx)
308 normal = this%coef%get_normal(idx(1), idx(2), idx(3), idx(4), facet)
309 area = this%coef%get_area(idx(1), idx(2), idx(3), idx(4), facet)
310 normal = normal * area !Scale normal by area
311 this%nx%x(htable_data) = this%nx%x(htable_data) + normal(1)
312 this%ny%x(htable_data) = this%ny%x(htable_data) + normal(2)
313 this%nz%x(htable_data) = this%nz%x(htable_data) + normal(3)
314 end do
315
316 if (neko_bcknd_device .eq. 1 .and. &
317 (unique_point_idx%num_entries() .gt. 0 )) then
318 call device_map(this%unique_mask, this%unique_mask_d, &
319 size(this%unique_mask))
320 call device_memcpy(this%unique_mask, this%unique_mask_d, &
321 size(this%unique_mask), host_to_device, sync = .true.)
322 call device_memcpy(this%nx%x, this%nx%x_d, &
323 this%nx%size(), host_to_device, sync = .true.)
324 call device_memcpy(this%ny%x, this%ny%x_d, &
325 this%ny%size(), host_to_device, sync = .true.)
326 call device_memcpy(this%nz%x, this%nz%x_d, &
327 this%nz%size(), host_to_device, sync = .true.)
328 end if
329
330 call unique_point_idx%free()
331
332 end subroutine normal_vec_bcs_finalize
333
334end module normal_vec_bcs
Dirichlet condition in facet normal direction.