Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
wall_gll_sampler.f90
Go to the documentation of this file.
1! Copyright (c) 2026, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
35 use num_types, only : rp
36 use field, only : field_t
37 use coefs, only : coef_t
38 use vector, only : vector_t
39 use json_module, only : json_file
42 use user_intf, only : user_t
43 use mask, only : mask_t
46 use math, only : masked_gather_copy
48 use device, only : host_to_device
49 implicit none
50 private
51
53 type, public, extends(wall_sampler_t) :: wall_gll_sampler_t
55 integer, allocatable :: indices(:)
57 type(mask_t) :: sample_idx
58 contains
60 procedure, pass(this) :: init => wall_gll_sampler_init
62 procedure, pass(this) :: init_from_indices => &
65 procedure, private, pass(this) :: init_from_user => &
68 procedure, pass(this) :: init_from_components => &
71 procedure, pass(this) :: finalize => wall_gll_sampler_finalize
73 procedure, pass(this) :: sample => wall_gll_sampler_sample
75 procedure, pass(this) :: free => wall_gll_sampler_free
76 end type wall_gll_sampler_t
77
78contains
79
82 subroutine wall_gll_sampler_init(this, json)
83 class(wall_gll_sampler_t), intent(inout) :: this
84 type(json_file), intent(inout) :: json
85 integer, allocatable :: indices(:)
86 integer :: index, n_samples, var_type
87 logical :: found, output_h
88 character(len=:), allocatable :: value
89
90 call json_get_or_default(json, 'output_h', output_h, .true.)
91
92 call json%info('value', found = found, var_type = var_type)
93 if (.not. found) then
94 call neko_error('Wall GLL sampler requires a value')
95 end if
96
97 select case (var_type)
98 case (3) ! json_array
99 call json_get(json, 'value', indices)
100 call this%init_from_indices(indices, output_h)
101 case (5) ! json_integer
102 call json_get(json, 'value', index)
103 call this%init_from_indices([index], output_h)
104 case (7) ! json_string
105 call json_get(json, 'value', value)
106 if (trim(value) /= 'user') then
107 call neko_error('Wall GLL sampler value must be an integer, ' // &
108 'array, or user')
109 end if
110 call json_get(json, 'n_samples', n_samples)
111 call this%init_from_user(n_samples, output_h)
112 case default
113 call neko_error('Wall GLL sampler value must be an integer, ' // &
114 'array, or user')
115 end select
116 end subroutine wall_gll_sampler_init
117
122 subroutine wall_gll_sampler_init_from_indices(this, indices, output_h)
123 class(wall_gll_sampler_t), intent(inout) :: this
124 integer, intent(in) :: indices(:)
125 logical, intent(in) :: output_h
126
127 if (any(indices < 1)) then
128 call neko_error('Wall GLL sampler indices must be positive')
129 end if
130
131 this%indices = indices
132 this%n_samples = size(indices)
133 this%user_values = .false.
134 this%output_h_enabled = output_h
136
140 subroutine wall_gll_sampler_init_from_user(this, n_samples, output_h)
141 class(wall_gll_sampler_t), intent(inout) :: this
142 integer, intent(in) :: n_samples
143 logical, intent(in) :: output_h
144
145 if (n_samples < 1) then
146 call neko_error('Wall GLL sampler n_samples must be positive')
147 end if
148
149 this%n_samples = n_samples
150 this%user_values = .true.
151 this%output_h_enabled = output_h
153
161 subroutine wall_gll_sampler_init_from_components(this, indices, sample_idx, &
162 h, output_h)
163 class(wall_gll_sampler_t), intent(inout) :: this
164 integer, intent(in) :: indices(:)
165 integer, intent(in) :: sample_idx(:)
166 type(vector_t), intent(in) :: h
167 logical, intent(in) :: output_h
168 integer :: n_nodes
169
170 if (size(indices) < 1 .or. any(indices < 1)) then
171 call neko_error('Wall GLL sampler indices must be positive')
172 end if
173 if (size(sample_idx) < 1 .or. any(sample_idx < 1)) then
174 call neko_error('Wall GLL sampler sample indices must be positive')
175 end if
176 if (mod(size(sample_idx), size(indices)) /= 0) then
177 call neko_error('Wall GLL sampler sample indices have an invalid size')
178 end if
179
180 n_nodes = size(sample_idx) / size(indices)
181 call this%free()
182 call this%init_base(n_nodes, size(indices), h, output_h)
183 this%indices = indices
184 call this%sample_idx%init(sample_idx, size(sample_idx))
186
197 subroutine wall_gll_sampler_finalize(this, coef, msk, facet, n_x, n_y, &
198 n_z, bc_name, user)
199 class(wall_gll_sampler_t), intent(inout) :: this
200 type(coef_t), intent(in) :: coef
201 integer, intent(in) :: msk(0:)
202 integer, intent(in) :: facet(0:)
203 type(vector_t), intent(in) :: n_x, n_y, n_z
204 character(len=*), optional, intent(in) :: bc_name
205 type(user_t), target, optional, intent(in) :: user
206 integer :: i, j, p, fid, idx(4), sample(4), lx, ly, lz, offwall
207 real(kind=rp) :: xw, yw, zw, dx, dy, dz
208 integer, allocatable :: user_indices(:,:), sample_idx(:)
209
210 if (.not. this%user_values .and. .not. allocated(this%indices)) then
211 call neko_error('Wall GLL sampler has not been initialized')
212 end if
213
214 call this%h%free()
215 this%n_nodes = msk(0)
216 if (.not. this%user_values) this%n_samples = size(this%indices)
217
218 if (this%user_values) then
219 if (.not. present(bc_name) .or. .not. present(user)) then
220 call neko_error('Wall GLL user sampler has no configured callback')
221 end if
222
223 allocate(user_indices(this%n_samples, this%n_nodes))
224
225 call user%wall_sampling_gll(bc_name, msk(1:this%n_nodes), user_indices)
226
227 if (any(user_indices < 1)) then
228 call neko_error('Wall GLL sampler indices must be positive')
229 end if
230 end if
231
232 allocate(sample_idx(this%n_nodes * this%n_samples))
233 call this%h%init(size(sample_idx))
234
235 lx = coef%Xh%lx
236 ly = coef%Xh%ly
237 lz = coef%Xh%lz
238 do i = 1, this%n_nodes
239 idx = nonlinear_index(msk(i), lx, ly, lz)
240 xw = coef%dof%x(idx(1), idx(2), idx(3), idx(4))
241 yw = coef%dof%y(idx(1), idx(2), idx(3), idx(4))
242 zw = coef%dof%z(idx(1), idx(2), idx(3), idx(4))
243 fid = facet(i)
244 do j = 1, this%n_samples
245 p = (i - 1) * this%n_samples + j
246 if (this%user_values) then
247 offwall = user_indices(j,i)
248 else
249 offwall = this%indices(j)
250 end if
251 sample = idx
252 select case (fid)
253 case (1)
254 sample(1) = sample(1) + offwall
255 case (2)
256 sample(1) = sample(1) - offwall
257 case (3)
258 sample(2) = sample(2) + offwall
259 case (4)
260 sample(2) = sample(2) - offwall
261 case (5)
262 sample(3) = sample(3) + offwall
263 case (6)
264 sample(3) = sample(3) - offwall
265 case default
266 call neko_error('Invalid facet in wall GLL sampler')
267 end select
268
269 if (sample(1) < 1 .or. sample(1) > lx .or. &
270 sample(2) < 1 .or. sample(2) > ly .or. &
271 sample(3) < 1 .or. sample(3) > lz) then
272 call neko_error('Wall GLL sampling index lies outside element')
273 end if
274
275 sample_idx(p) = linear_index(sample(1), sample(2), sample(3), &
276 sample(4), lx, ly, lz)
277
278 dx = coef%dof%x(sample(1), sample(2), sample(3), sample(4)) - xw
279 dy = coef%dof%y(sample(1), sample(2), sample(3), sample(4)) - yw
280 dz = coef%dof%z(sample(1), sample(2), sample(3), sample(4)) - zw
281 this%h%x(p) = -(dx*n_x%x(i) + dy*n_y%x(i) + dz*n_z%x(i))
282 end do
283 end do
284
285 call this%sample_idx%init(sample_idx, size(sample_idx))
286 if (neko_bcknd_device .eq. 1) &
287 call this%h%copy_from(host_to_device, sync = .true.)
288
289 if (this%output_h_enabled .and. present(bc_name)) then
290 call this%output_h(coef, msk, bc_name)
291 end if
292 end subroutine wall_gll_sampler_finalize
293
297 subroutine wall_gll_sampler_sample(this, field, values)
298 class(wall_gll_sampler_t), intent(inout) :: this
299 type(field_t), intent(inout) :: field
300 type(vector_t), intent(inout) :: values
301 integer :: n
302
303 n = this%n_nodes * this%n_samples
304
305 if (values%size() .ne. n) then
306 call neko_error('Wall sampler destination has an invalid size')
307 end if
308
309 if (neko_bcknd_device .eq. 1) then
310 call device_masked_gather_copy_aligned(values%x_d, field%x_d, &
311 this%sample_idx%get_d(), field%size(), n)
312 else
313 call masked_gather_copy(values%x, field%x, this%sample_idx%get(), &
314 field%size(), n)
315 end if
316 end subroutine wall_gll_sampler_sample
317
319 subroutine wall_gll_sampler_free(this)
320 class(wall_gll_sampler_t), intent(inout) :: this
321
322 call this%sample_idx%free()
323
324 if (allocated(this%indices)) deallocate(this%indices)
325
326 call this%h%free()
327
328 this%n_nodes = 0
329 this%n_samples = 0
330 this%user_values = .false.
331 this%output_h_enabled = .true.
332 end subroutine wall_gll_sampler_free
333
334end module wall_gll_sampler
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
Definition bc_utils.h:44
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Retrieves a parameter by name or throws an error.
Coefficients.
Definition coef.f90:34
subroutine, public device_masked_gather_copy_aligned(a_d, b_d, mask_d, n, n_mask, strm)
Gather a masked vector .
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
Defines a field.
Definition field.f90:34
Utilities for retrieving parameters from the case files.
Object for handling masks in Neko.
Definition mask.f90:34
Definition math.f90:60
subroutine, public masked_gather_copy(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
Definition math.f90:423
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Interfaces for user interaction with NEKO.
Definition user_intf.f90:34
Utilities.
Definition utils.f90:35
pure integer function, public linear_index(i, j, k, l, lx, ly, lz)
Compute the address of a (i,j,k,l) array with sizes (1:lx, 1:ly, 1:lz, :)
Definition utils.f90:289
Defines a vector.
Definition vector.f90:34
Implements sampling from GLL nodes at prescribed off-wall indices.
subroutine wall_gll_sampler_init(this, json)
Partial constructor from JSON.
subroutine wall_gll_sampler_init_from_components(this, indices, sample_idx, h, output_h)
Fully construct a GLL sampler from its resolved components.
subroutine wall_gll_sampler_finalize(this, coef, msk, facet, n_x, n_y, n_z, bc_name, user)
Construct field indices and wall-normal distances for sampling. Completes initialization.
subroutine wall_gll_sampler_free(this)
Destructor.
subroutine wall_gll_sampler_init_from_user(this, n_samples, output_h)
Partial constructor for user-provided GLL sampling indices.
subroutine wall_gll_sampler_sample(this, field, values)
Sample the solution field at the sampling points.
subroutine wall_gll_sampler_init_from_indices(this, indices, output_h)
Partial constructor from off-wall GLL indices.
Defines the abstract interface for wall-model field samplers.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:93
Type for consistently handling masks in Neko. This type encapsulates the mask array and its associate...
Definition mask.f90:51
A type collecting all the overridable user routines and flag to suppress type injection from custom m...
Wall sampler implementation for GLL nodes at prescribed off-wall indices.
Base type for sampling solution fields at points associated with wall nodes. Samples belonging to one...