Neko 1.99.7
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
expression_dirichlet.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 bc, only : bc_t
37 use coefs, only : coef_t
42 use json_module, only : json_file
43 use json_utils, only : json_get
44 use time_state, only : time_state_t
45 use utils, only : neko_error
46 use, intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr
47 implicit none
48 private
49
61 type, public, extends(bc_t) :: expression_dirichlet_t
63 type(expression_t) :: expr
65 real(kind=rp), allocatable :: g(:)
67 real(kind=rp), allocatable :: xm(:)
68 real(kind=rp), allocatable :: ym(:)
69 real(kind=rp), allocatable :: zm(:)
71 type(c_ptr) :: g_d = c_null_ptr
72 contains
74 procedure, pass(this) :: init => expression_dirichlet_init
76 procedure, pass(this) :: init_from_components => &
79 procedure, pass(this) :: free => expression_dirichlet_free
81 procedure, pass(this) :: finalize => expression_dirichlet_finalize
83 procedure, pass(this) :: apply_scalar => expression_dirichlet_apply_scalar
85 procedure, pass(this) :: apply_vector => expression_dirichlet_apply_vector
87 procedure, pass(this) :: apply_scalar_dev => &
90 procedure, pass(this) :: apply_vector_dev => &
93 procedure, pass(this) :: update => expression_dirichlet_update
95
97
98contains
99
103 subroutine expression_dirichlet_init(this, coef, json)
104 class(expression_dirichlet_t), intent(inout), target :: this
105 type(coef_t), target, intent(in) :: coef
106 type(json_file), intent(inout) :: json
107 character(len=:), allocatable :: str
108
109 call json_get(json, "value", str)
110 call this%init_from_components(coef, str)
111 if (allocated(str)) deallocate(str)
112
113 end subroutine expression_dirichlet_init
114
119 class(expression_dirichlet_t), intent(inout), target :: this
120 type(coef_t), target, intent(in) :: coef
121 character(len=*), intent(in) :: str
122
123 call this%free()
124 call this%init_base(coef)
125
126 if (len_trim(str) .eq. 0) then
127 call neko_error("An expression boundary condition needs a non-empty " &
128 // "expression under the value keyword")
129 end if
130
131 call this%expr%init(str)
132
134
137 class(expression_dirichlet_t), target, intent(inout) :: this
138
139 call this%free_base()
140 call this%expr%free()
141
142 if (allocated(this%g)) then
143 if (neko_bcknd_device .eq. 1) then
144 call device_unmap(this%g, this%g_d)
145 end if
146 deallocate(this%g)
147 end if
148
149 if (allocated(this%xm)) deallocate(this%xm)
150 if (allocated(this%ym)) deallocate(this%ym)
151 if (allocated(this%zm)) deallocate(this%zm)
152
153 end subroutine expression_dirichlet_free
154
160 subroutine expression_dirichlet_finalize(this, only_facets)
161 class(expression_dirichlet_t), target, intent(inout) :: this
162 logical, optional, intent(in) :: only_facets
163 logical :: only_facets_
164 integer :: m
165
166 if (present(only_facets)) then
167 only_facets_ = only_facets
168 else
169 only_facets_ = .false.
170 end if
171
172 call this%finalize_base(only_facets_)
173
174 m = this%msk(0)
175 if (m .eq. 0) return
176
177 allocate(this%xm(m), this%ym(m), this%zm(m), this%g(m))
178 call expression_mask_coords(this, this%xm, this%ym, this%zm)
179 this%g = 0.0_rp
180
181 if (neko_bcknd_device .eq. 1) then
182 call device_map(this%g, this%g_d, m)
183 end if
184
185 if (.not. this%expr%time_dependent) then
186 call this%expr%eval(this%g, m, this%xm, this%ym, this%zm)
187 call expression_check_finite(this%expr%src, this%g, m, &
188 "boundary condition")
189 if (neko_bcknd_device .eq. 1) then
190 call device_memcpy(this%g, this%g_d, m, host_to_device, &
191 sync = .true.)
192 end if
193 end if
194
195 end subroutine expression_dirichlet_finalize
196
202 subroutine expression_dirichlet_update(this, time, strm)
203 class(expression_dirichlet_t), intent(inout) :: this
204 type(time_state_t), intent(in), optional :: time
205 type(c_ptr), intent(inout), optional :: strm
206 integer :: m
207
208 if (.not. this%expr%time_dependent) return
209 if (this%updated) return
210
211 if (.not. present(time)) then
212 call neko_error("The boundary condition expression '" // &
213 this%expr%src // "' depends on time, but the solver did not " // &
214 "provide a time state")
215 end if
216
217 m = this%msk(0)
218 call this%expr%eval(this%g, m, this%xm, this%ym, this%zm, time%t, time%dt)
219 call expression_check_finite(this%expr%src, this%g, m, &
220 "boundary condition")
221
222 if (neko_bcknd_device .eq. 1) then
223 ! Synchronous on purpose: the host buffer is reused every timestep,
224 ! and the copy is only as large as the mask.
225 call device_memcpy(this%g, this%g_d, m, host_to_device, &
226 sync = .true., strm = strm)
227 end if
228
229 this%updated = .true.
230
231 end subroutine expression_dirichlet_update
232
238 subroutine expression_dirichlet_apply_scalar(this, x, n, time, strong)
239 class(expression_dirichlet_t), intent(inout) :: this
240 integer, intent(in) :: n
241 real(kind=rp), intent(inout), dimension(n) :: x
242 type(time_state_t), intent(in), optional :: time
243 logical, intent(in), optional :: strong
244 integer :: i, m
245 logical :: strong_
246
247 if (present(strong)) then
248 strong_ = strong
249 else
250 strong_ = .true.
251 end if
252
253 m = this%msk(0)
254 if (.not. strong_ .or. m .eq. 0) return
255
256 ! The bc list applies the host conditions from inside an OpenMP parallel
257 ! region, and evaluating an expression mutates the shared evaluation stack
258 ! of `expr`, so only one thread may run the update. The implicit barrier of
259 ! `single` also makes `g` visible to every thread before the loop below.
260 !$omp single
261 call this%update(time)
262 !$omp end single
263
264 !$omp do
265 do i = 1, m
266 x(this%msk(i)) = this%g(i)
267 end do
268 !$omp end do
269
271
279 subroutine expression_dirichlet_apply_vector(this, x, y, z, n, time, strong)
280 class(expression_dirichlet_t), intent(inout) :: this
281 integer, intent(in) :: n
282 real(kind=rp), intent(inout), dimension(n) :: x
283 real(kind=rp), intent(inout), dimension(n) :: y
284 real(kind=rp), intent(inout), dimension(n) :: z
285 type(time_state_t), intent(in), optional :: time
286 logical, intent(in), optional :: strong
288
294 subroutine expression_dirichlet_apply_scalar_dev(this, x_d, time, strong, &
295 strm)
296 class(expression_dirichlet_t), intent(inout), target :: this
297 type(c_ptr), intent(inout) :: x_d
298 type(time_state_t), intent(in), optional :: time
299 logical, intent(in), optional :: strong
300 type(c_ptr), intent(inout) :: strm
301 integer :: m
302 logical :: strong_
303
304 if (present(strong)) then
305 strong_ = strong
306 else
307 strong_ = .true.
308 end if
309
310 m = this%msk(0)
311 if (.not. strong_ .or. m .eq. 0) return
312
313 call this%update(time, strm)
314
315 call device_inhom_dirichlet_apply_scalar(this%msk_d, x_d, this%g_d, m, strm)
316
318
326 subroutine expression_dirichlet_apply_vector_dev(this, x_d, y_d, z_d, &
327 time, strong, strm)
328 class(expression_dirichlet_t), intent(inout), target :: this
329 type(c_ptr), intent(inout) :: x_d
330 type(c_ptr), intent(inout) :: y_d
331 type(c_ptr), intent(inout) :: z_d
332 type(time_state_t), intent(in), optional :: time
333 logical, intent(in), optional :: strong
334 type(c_ptr), intent(inout) :: strm
336
343 subroutine expression_mask_coords(bc, xm, ym, zm)
344 class(bc_t), intent(in) :: bc
345 real(kind=rp), intent(inout) :: xm(:)
346 real(kind=rp), intent(inout) :: ym(:)
347 real(kind=rp), intent(inout) :: zm(:)
348
349 call gather_coords(bc%msk, bc%msk(0), bc%dof%x, bc%dof%y, bc%dof%z, &
350 size(bc%dof%x), xm, ym, zm)
351
352 end subroutine expression_mask_coords
353
366 subroutine gather_coords(msk, m, x, y, z, n, xm, ym, zm)
367 integer, intent(in) :: m
368 integer, intent(in) :: n
369 integer, intent(in) :: msk(0:m)
370 real(kind=rp), intent(in) :: x(n)
371 real(kind=rp), intent(in) :: y(n)
372 real(kind=rp), intent(in) :: z(n)
373 real(kind=rp), intent(inout) :: xm(m)
374 real(kind=rp), intent(inout) :: ym(m)
375 real(kind=rp), intent(inout) :: zm(m)
376 integer :: i, k
377
378 do i = 1, m
379 k = msk(i)
380 xm(i) = x(k)
381 ym(i) = y(k)
382 zm(i) = z(k)
383 end do
384
385 end subroutine gather_coords
386
387end module expression_dirichlet
Map a Fortran array to a device (allocate and associate)
Definition device.F90:83
Copy data between host and device (or device and device)
Definition device.F90:72
Unmap a Fortran array from a device (deassociate and free)
Definition device.F90:89
Retrieves a parameter by name or throws an error.
Defines a boundary condition.
Definition bc.f90:34
Coefficients.
Definition coef.f90:34
subroutine device_inhom_dirichlet_apply_scalar(msk, x, bla_x, m, strm)
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
Defines a Dirichlet condition prescribed by a mathematical expression.
subroutine expression_dirichlet_init(this, coef, json)
Constructor from JSON.
subroutine expression_dirichlet_update(this, time, strm)
Bring g up to date with the current time.
subroutine gather_coords(msk, m, x, y, z, n, xm, ym, zm)
Gather the coordinates of the masked points into contiguous arrays.
subroutine expression_dirichlet_apply_vector_dev(this, x_d, y_d, z_d, time, strong, strm)
(No-op) Apply vector (device version).
subroutine expression_dirichlet_apply_scalar(this, x, n, time, strong)
Apply the condition to a scalar field.
subroutine expression_dirichlet_apply_scalar_dev(this, x_d, time, strong, strm)
Apply the condition to a scalar field (device version).
subroutine expression_dirichlet_init_from_components(this, coef, str)
Constructor from components.
subroutine expression_dirichlet_finalize(this, only_facets)
Finalize.
subroutine, public expression_mask_coords(bc, xm, ym, zm)
Tabulate the coordinates of the points of the mask of a boundary condition.
subroutine expression_dirichlet_apply_vector(this, x, y, z, n, time, strong)
(No-op) Apply vector.
subroutine expression_dirichlet_free(this)
Destructor.
Evaluation of mathematical expressions given as strings in the case file.
subroutine, public expression_check_finite(str, res, n, usage)
Abort if an expression did not evaluate to a finite value everywhere.
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:12
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
Base type for a boundary condition.
Definition bc.f90:62
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:63
A compiled mathematical expression.
Dirichlet condition on , where is a mathematical expression given in the case file.
A struct that contains all info about the time, expand as needed.