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_free, &
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 deallocate(this%unique_mask)
237 end if
238 if (c_associated(this%unique_mask_d)) then
239 call device_free(this%unique_mask_d)
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
252 subroutine normal_vec_bcs_finalize(this, only_facets)
253 class(normal_vec_bcs_t), target, intent(inout) :: this
254 logical, optional, intent(in) :: only_facets
255 type(htable_i4_t) :: unique_point_idx
256 integer :: htable_data, rcode, i, j, idx(4), facet
257 real(kind=rp) :: area, normal(3)
258
259 if (present(only_facets)) then
260 if (only_facets .eqv. .false.) then
261 call neko_error("For normal_vec_bcs_t, only_facets has to be true.")
262 end if
263 end if
264
265 call this%finalize_base(.true.)
266 ! This part is purely needed to ensure that contributions
267 ! for all faces a point is on is properly summed up.
268 ! If one simply uses the original mask, if a point is on a corner
269 ! where both faces are on the boundary
270 ! one will only get the contribution from one face, not both
271 ! We solve this by adding up the normals of both faces for these points
272 ! and storing this sum in this%nx, this%ny, this%nz.
273 ! As both contrbutions are added already,
274 ! we also ensure that we only visit each point once
275 ! and create a new mask with only unique points (this%unique_mask).
276 if (allocated(this%unique_mask)) then
277 deallocate(this%unique_mask)
278 end if
279 if (c_associated(this%unique_mask_d)) then
280 call device_free(this%unique_mask_d)
281 end if
282
283 call unique_point_idx%init(this%msk(0), htable_data)
284 j = 0
285 do i = 1, this%msk(0)
286 if (unique_point_idx%get(this%msk(i),htable_data) .ne. 0) then
287 j = j + 1
288 htable_data = j
289 call unique_point_idx%set(this%msk(i), j)
290 end if
291 end do
292
293 ! Only allocate work vectors if size is non-zero
294 if (unique_point_idx%num_entries() .gt. 0 ) then
295 call this%nx%init(unique_point_idx%num_entries())
296 call this%ny%init(unique_point_idx%num_entries())
297 call this%nz%init(unique_point_idx%num_entries())
298 call this%work%init(unique_point_idx%num_entries())
299 end if
300 allocate(this%unique_mask(0:unique_point_idx%num_entries()))
301
302 this%unique_mask(0) = unique_point_idx%num_entries()
303 do i = 1, this%unique_mask(0)
304 this%unique_mask(i) = 0
305 end do
306
307
308 do i = 1, this%msk(0)
309 rcode = unique_point_idx%get(this%msk(i), htable_data)
310 if (rcode .ne. 0) call neko_error("Facet normal: htable get failed.")
311 this%unique_mask(htable_data) = this%msk(i)
312 facet = this%facet(i)
313
314 idx = nonlinear_index(this%msk(i), this%Xh%lx, this%Xh%lx, this%Xh%lx)
315 normal = this%coef%get_normal(idx(1), idx(2), idx(3), idx(4), facet)
316 area = this%coef%get_area(idx(1), idx(2), idx(3), idx(4), facet)
317 normal = normal * area !Scale normal by area
318 this%nx%x(htable_data) = this%nx%x(htable_data) + normal(1)
319 this%ny%x(htable_data) = this%ny%x(htable_data) + normal(2)
320 this%nz%x(htable_data) = this%nz%x(htable_data) + normal(3)
321 end do
322
323 if (neko_bcknd_device .eq. 1 .and. &
324 (unique_point_idx%num_entries() .gt. 0 )) then
325 call device_map(this%unique_mask, this%unique_mask_d, &
326 size(this%unique_mask))
327 call device_memcpy(this%unique_mask, this%unique_mask_d, &
328 size(this%unique_mask), host_to_device, sync = .true.)
329 call device_memcpy(this%nx%x, this%nx%x_d, &
330 this%nx%size(), host_to_device, sync = .true.)
331 call device_memcpy(this%ny%x, this%ny%x_d, &
332 this%ny%size(), host_to_device, sync = .true.)
333 call device_memcpy(this%nz%x, this%nz%x_d, &
334 this%nz%size(), host_to_device, sync = .true.)
335 end if
336
337 call unique_point_idx%free()
338
339 end subroutine normal_vec_bcs_finalize
340
341end module normal_vec_bcs
Dirichlet condition in facet normal direction.