Neko 1.99.9
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, bc_dirichlet
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 this%bc_type = bc_dirichlet
126
127 if (len_trim(str) .eq. 0) then
128 call neko_error("An expression boundary condition needs a non-empty " &
129 // "expression under the value keyword")
130 end if
131
132 call this%expr%init(str)
133
135
138 class(expression_dirichlet_t), target, intent(inout) :: this
139
140 call this%free_base()
141 call this%expr%free()
142
143 if (allocated(this%g)) then
144 if (neko_bcknd_device .eq. 1) then
145 call device_unmap(this%g, this%g_d)
146 end if
147 deallocate(this%g)
148 end if
149
150 if (allocated(this%xm)) deallocate(this%xm)
151 if (allocated(this%ym)) deallocate(this%ym)
152 if (allocated(this%zm)) deallocate(this%zm)
153
154 end subroutine expression_dirichlet_free
155
161 class(expression_dirichlet_t), target, intent(inout) :: this
162 integer :: m
163
164 call this%finalize_base()
165
166 m = this%msk(0)
167 if (m .eq. 0) return
168
169 allocate(this%xm(m), this%ym(m), this%zm(m), this%g(m))
170 call expression_mask_coords(this, this%xm, this%ym, this%zm)
171 this%g = 0.0_rp
172
173 if (neko_bcknd_device .eq. 1) then
174 call device_map(this%g, this%g_d, m)
175 end if
176
177 if (.not. this%expr%time_dependent) then
178 call this%expr%eval(this%g, m, this%xm, this%ym, this%zm)
179 call expression_check_finite(this%expr%src, this%g, m, &
180 "boundary condition")
181 if (neko_bcknd_device .eq. 1) then
182 call device_memcpy(this%g, this%g_d, m, host_to_device, &
183 sync = .true.)
184 end if
185 end if
186
187 end subroutine expression_dirichlet_finalize
188
194 subroutine expression_dirichlet_update(this, time, strm)
195 class(expression_dirichlet_t), intent(inout) :: this
196 type(time_state_t), intent(in), optional :: time
197 type(c_ptr), intent(inout), optional :: strm
198 integer :: m
199
200 if (.not. this%expr%time_dependent) return
201 if (this%updated) return
202
203 if (.not. present(time)) then
204 call neko_error("The boundary condition expression '" // &
205 this%expr%src // "' depends on time, but the solver did not " // &
206 "provide a time state")
207 end if
208
209 m = this%msk(0)
210 call this%expr%eval(this%g, m, this%xm, this%ym, this%zm, time%t, time%dt)
211 call expression_check_finite(this%expr%src, this%g, m, &
212 "boundary condition")
213
214 if (neko_bcknd_device .eq. 1) then
215 ! Synchronous on purpose: the host buffer is reused every timestep,
216 ! and the copy is only as large as the mask.
217 call device_memcpy(this%g, this%g_d, m, host_to_device, &
218 sync = .true., strm = strm)
219 end if
220
221 this%updated = .true.
222
223 end subroutine expression_dirichlet_update
224
230 subroutine expression_dirichlet_apply_scalar(this, x, n, time, strong)
231 class(expression_dirichlet_t), intent(inout) :: this
232 integer, intent(in) :: n
233 real(kind=rp), intent(inout), dimension(n) :: x
234 type(time_state_t), intent(in), optional :: time
235 logical, intent(in), optional :: strong
236 integer :: i, m
237 logical :: strong_
238
239 if (present(strong)) then
240 strong_ = strong
241 else
242 strong_ = .true.
243 end if
244
245 m = this%msk(0)
246 if (.not. strong_ .or. m .eq. 0) return
247
248 ! The bc list applies the host conditions from inside an OpenMP parallel
249 ! region, and evaluating an expression mutates the shared evaluation stack
250 ! of `expr`, so only one thread may run the update. The implicit barrier of
251 ! `single` also makes `g` visible to every thread before the loop below.
252 !$omp single
253 call this%update(time)
254 !$omp end single
255
256 !$omp do
257 do i = 1, m
258 x(this%msk(i)) = this%g(i)
259 end do
260 !$omp end do
261
263
271 subroutine expression_dirichlet_apply_vector(this, x, y, z, n, time, strong)
272 class(expression_dirichlet_t), intent(inout) :: this
273 integer, intent(in) :: n
274 real(kind=rp), intent(inout), dimension(n) :: x
275 real(kind=rp), intent(inout), dimension(n) :: y
276 real(kind=rp), intent(inout), dimension(n) :: z
277 type(time_state_t), intent(in), optional :: time
278 logical, intent(in), optional :: strong
280
286 subroutine expression_dirichlet_apply_scalar_dev(this, x_d, time, strong, &
287 strm)
288 class(expression_dirichlet_t), intent(inout), target :: this
289 type(c_ptr), intent(inout) :: x_d
290 type(time_state_t), intent(in), optional :: time
291 logical, intent(in), optional :: strong
292 type(c_ptr), intent(inout) :: strm
293 integer :: m
294 logical :: strong_
295
296 if (present(strong)) then
297 strong_ = strong
298 else
299 strong_ = .true.
300 end if
301
302 m = this%msk(0)
303 if (.not. strong_ .or. m .eq. 0) return
304
305 call this%update(time, strm)
306
307 call device_inhom_dirichlet_apply_scalar(this%msk_d, x_d, this%g_d, m, strm)
308
310
318 subroutine expression_dirichlet_apply_vector_dev(this, x_d, y_d, z_d, &
319 time, strong, strm)
320 class(expression_dirichlet_t), intent(inout), target :: this
321 type(c_ptr), intent(inout) :: x_d
322 type(c_ptr), intent(inout) :: y_d
323 type(c_ptr), intent(inout) :: z_d
324 type(time_state_t), intent(in), optional :: time
325 logical, intent(in), optional :: strong
326 type(c_ptr), intent(inout) :: strm
328
335 subroutine expression_mask_coords(bc, xm, ym, zm)
336 class(bc_t), intent(in) :: bc
337 real(kind=rp), intent(inout) :: xm(:)
338 real(kind=rp), intent(inout) :: ym(:)
339 real(kind=rp), intent(inout) :: zm(:)
340
341 call gather_coords(bc%msk, bc%msk(0), bc%dof%x%x, bc%dof%y%x, bc%dof%z%x, &
342 bc%dof%size(), xm, ym, zm)
343
344 end subroutine expression_mask_coords
345
358 subroutine gather_coords(msk, m, x, y, z, n, xm, ym, zm)
359 integer, intent(in) :: m
360 integer, intent(in) :: n
361 integer, intent(in) :: msk(0:m)
362 real(kind=rp), intent(in) :: x(n)
363 real(kind=rp), intent(in) :: y(n)
364 real(kind=rp), intent(in) :: z(n)
365 real(kind=rp), intent(inout) :: xm(m)
366 real(kind=rp), intent(inout) :: ym(m)
367 real(kind=rp), intent(inout) :: zm(m)
368 integer :: i, k
369
370 do i = 1, m
371 k = msk(i)
372 xm(i) = x(k)
373 ym(i) = y(k)
374 zm(i) = z(k)
375 end do
376
377 end subroutine gather_coords
378
379end 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
integer, parameter, public bc_dirichlet
Supported boundary condition types. The values are set in order of precedence for global resolution....
Definition bc.f90:67
Coefficients.
Definition coef.f90:34
Device backend wrappers for inhomogeneous Dirichlet boundary conditions.
subroutine device_inhom_dirichlet_apply_scalar(msk, x, bla_x, m, strm)
Apply an inhomogeneous Dirichlet condition to a scalar field on the device.
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, 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.
subroutine expression_dirichlet_finalize(this)
Finalize.
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:14
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
Base type for a boundary condition.
Definition bc.f90:73
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:135
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.