Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
wall_distance_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 copyright
12! notice, this list of conditions and the following disclaimer in
13! the documentation and/or other materials provided with the
14! 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
45 use utils, only : neko_error
46 use device, only : host_to_device
47 implicit none
48 private
49
51 type, public, extends(wall_sampler_t) :: wall_distance_sampler_t
53 real(kind=rp), allocatable :: distances(:)
55 real(kind=rp), allocatable :: xyz(:,:)
57 type(global_interpolation_t) :: interpolator
58 contains
60 procedure, pass(this) :: init => wall_distance_sampler_init
62 procedure, pass(this) :: init_from_distances => &
65 procedure, private, pass(this) :: init_from_user => &
68 procedure, pass(this) :: init_from_components => &
72 procedure, pass(this) :: finalize => wall_distance_sampler_finalize
74 procedure, pass(this) :: sample => wall_distance_sampler_sample
76 procedure, pass(this) :: free => wall_distance_sampler_free
78
79contains
80
83 subroutine wall_distance_sampler_init(this, json)
84 class(wall_distance_sampler_t), intent(inout) :: this
85 type(json_file), intent(inout) :: json
86 real(kind=rp), allocatable :: distances(:)
87 real(kind=rp) :: distance
88 integer :: n_samples, var_type
89 logical :: found, output_h
90 character(len=:), allocatable :: value
91
92 call json_get_or_default(json, 'output_h', output_h, .true.)
93
94 call json%info('value', found = found, var_type = var_type)
95 if (.not. found) then
96 call neko_error('Wall distance sampler requires a value')
97 end if
98
99 select case (var_type)
100 case (3) ! json_array
101 call json_get(json, 'value', distances)
102 call this%init_from_distances(distances, output_h)
103 case (5, 6) ! json_integer, json_real
104 call json_get(json, 'value', distance)
105 call this%init_from_distances([distance], output_h)
106 case (7) ! json_string
107 call json_get(json, 'value', value)
108 if (trim(value) /= 'user') then
109 call neko_error('Wall distance sampler value must be a real,' // &
110 ' array, or user')
111 end if
112 call json_get(json, 'n_samples', n_samples)
113 call this%init_from_user(n_samples, output_h)
114 case default
115 call neko_error('Wall distance sampler value must be a real, array,' // &
116 ' or user')
117 end select
118 end subroutine wall_distance_sampler_init
119
124 subroutine wall_distance_sampler_init_from_distances(this, distances, &
125 output_h)
126 class(wall_distance_sampler_t), intent(inout) :: this
127 real(kind=rp), intent(in) :: distances(:)
128 logical, intent(in) :: output_h
129
130 if (size(distances) < 1 .or. any(distances <= 0.0_rp)) then
131 call neko_error('Wall sampling distances must be positive')
132 end if
133 this%distances = distances
134 this%n_samples = size(distances)
135 this%user_values = .false.
136 this%output_h_enabled = output_h
138
142 subroutine wall_distance_sampler_init_from_user(this, n_samples, output_h)
143 class(wall_distance_sampler_t), intent(inout) :: this
144 integer, intent(in) :: n_samples
145 logical, intent(in) :: output_h
146
147 if (n_samples < 1) then
148 call neko_error('Wall distance sampler n_samples must be positive')
149 end if
150
151 this%n_samples = n_samples
152 this%user_values = .true.
153 this%output_h_enabled = output_h
155
164 subroutine wall_distance_sampler_init_from_components(this, coef, distances, &
165 xyz, h, output_h)
166 class(wall_distance_sampler_t), intent(inout) :: this
167 type(coef_t), intent(in) :: coef
168 real(kind=rp), intent(in) :: distances(:)
169 real(kind=rp), intent(in) :: xyz(:,:)
170 type(vector_t), intent(in) :: h
171 logical, intent(in) :: output_h
172 integer :: n_nodes, n_points
173
174 if (size(distances) < 1 .or. any(distances <= 0.0_rp)) then
175 call neko_error('Wall sampling distances must be positive')
176 end if
177 if (size(xyz, 1) /= 3) then
178 call neko_error('Wall sampler coordinates must have three components')
179 end if
180
181 n_points = size(xyz, 2)
182 if (n_points < 1 .or. mod(n_points, size(distances)) /= 0) then
183 call neko_error('Wall sampler coordinates have an invalid size')
184 end if
185
186 n_nodes = n_points / size(distances)
187 call this%free()
188 call this%init_base(n_nodes, size(distances), h, output_h)
189 this%distances = distances
190 this%xyz = xyz
191 call this%interpolator%init(coef%dof)
192 call this%interpolator%find_points(this%xyz, n_points)
194
204 subroutine wall_distance_sampler_finalize(this, coef, msk, facet, &
205 n_x, n_y, n_z, bc_name, user)
206 class(wall_distance_sampler_t), intent(inout) :: this
207 type(coef_t), intent(in) :: coef
208 integer, intent(in) :: msk(0:)
209 integer, intent(in) :: facet(0:)
210 type(vector_t), intent(in) :: n_x, n_y, n_z
211 character(len=*), optional, intent(in) :: bc_name
212 type(user_t), target, optional, intent(in) :: user
213 integer :: i, j, p, linear
214 real(kind=rp) :: distance
215 real(kind=rp), allocatable :: user_distances(:,:)
216
217 if (.not. this%user_values .and. .not. allocated(this%distances)) then
218 call neko_error('Wall distance sampler has not been initialized')
219 end if
220
221 call this%h%free()
222 call this%interpolator%free()
223
224 if (allocated(this%xyz)) deallocate(this%xyz)
225
226 this%n_nodes = msk(0)
227 if (.not. this%user_values) this%n_samples = size(this%distances)
228
229 if (this%user_values) then
230 if (.not. present(bc_name) .or. .not. present(user)) then
231 call neko_error('Wall distance user sampler has no ' // &
232 'configured callback')
233 end if
234
235 allocate(user_distances(this%n_samples, this%n_nodes))
236 call user%wall_sampling_distance(bc_name, msk(1:this%n_nodes), &
237 user_distances)
238 if (any(user_distances <= 0.0_rp)) then
239 call neko_error('Wall sampling distances must be positive')
240 end if
241 end if
242 allocate(this%xyz(3, this%n_nodes * this%n_samples))
243 call this%h%init(this%n_nodes * this%n_samples)
244
245 do i = 1, this%n_nodes
246 linear = msk(i)
247 do j = 1, this%n_samples
248 p = (i - 1) * this%n_samples + j
249 if (this%user_values) then
250 distance = user_distances(j,i)
251 else
252 distance = this%distances(j)
253 end if
254 this%xyz(1,p) = coef%dof%x(linear,1,1,1) - &
255 distance * n_x%x(i)
256 this%xyz(2,p) = coef%dof%y(linear,1,1,1) - &
257 distance * n_y%x(i)
258 this%xyz(3,p) = coef%dof%z(linear,1,1,1) - &
259 distance * n_z%x(i)
260 this%h%x(p) = distance
261 end do
262 end do
263
264 call this%interpolator%init(coef%dof)
265 call this%interpolator%find_points(this%xyz, &
266 this%n_nodes * this%n_samples)
267
268 if (neko_bcknd_device .eq. 1) then
269 call this%h%copy_from(host_to_device, sync = .true.)
270 end if
271
272 if (this%output_h_enabled .and. present(bc_name)) then
273 call this%output_h(coef, msk, bc_name)
274 end if
275 end subroutine wall_distance_sampler_finalize
276
280 subroutine wall_distance_sampler_sample(this, field, values)
281 class(wall_distance_sampler_t), intent(inout) :: this
282 type(field_t), intent(inout) :: field
283 type(vector_t), intent(inout) :: values
284 integer :: n
285
286 n = this%n_nodes * this%n_samples
287 if (values%size() /= n) then
288 call neko_error('Wall sampler destination has an invalid size')
289 end if
290
291 call this%interpolator%evaluate(values%x, field%x, &
292 neko_bcknd_device .eq. 0)
293 end subroutine wall_distance_sampler_sample
294
297 class(wall_distance_sampler_t), intent(inout) :: this
298
299 call this%interpolator%free()
300 call this%h%free()
301 if (allocated(this%distances)) deallocate(this%distances)
302 if (allocated(this%xyz)) deallocate(this%xyz)
303 this%n_nodes = 0
304 this%n_samples = 0
305 this%user_values = .false.
306 this%output_h_enabled = .true.
307 end subroutine wall_distance_sampler_free
308
309end module wall_distance_sampler
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
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
Implements global_interpolation given a dofmap.
Utilities for retrieving parameters from the case files.
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
Defines a vector.
Definition vector.f90:34
Implements wall_distance_sampler_t.
subroutine wall_distance_sampler_init_from_components(this, coef, distances, xyz, h, output_h)
Fully construct a distance sampler from its resolved components.
subroutine wall_distance_sampler_init_from_distances(this, distances, output_h)
Partial constructor from physical wall-normal distances.
subroutine wall_distance_sampler_finalize(this, coef, msk, facet, n_x, n_y, n_z, bc_name, user)
Construct sampling locations and initialise global interpolation.
subroutine wall_distance_sampler_sample(this, field, values)
Sample a field at the configured physical locations.
subroutine wall_distance_sampler_init_from_user(this, n_samples, output_h)
Partial constructor for user-provided sampling distances.
subroutine wall_distance_sampler_free(this)
Release sampler resources.
subroutine wall_distance_sampler_init(this, json)
Partial constructor from JSON.
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
Implements global interpolation for arbitrary points in the domain.
A type collecting all the overridable user routines and flag to suppress type injection from custom m...
Implements wall-normal sampling at prescribed physical distances.
Base type for sampling solution fields at points associated with wall nodes. Samples belonging to one...