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
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 class(expression_dirichlet_t), target, intent(inout) :: this
161 integer :: m
162
163 call this%finalize_base()
164
165 m = this%msk(0)
166 if (m .eq. 0) return
167
168 allocate(this%xm(m), this%ym(m), this%zm(m), this%g(m))
169 call expression_mask_coords(this, this%xm, this%ym, this%zm)
170 this%g = 0.0_rp
171
172 if (neko_bcknd_device .eq. 1) then
173 call device_map(this%g, this%g_d, m)
174 end if
175
176 if (.not. this%expr%time_dependent) then
177 call this%expr%eval(this%g, m, this%xm, this%ym, this%zm)
178 call expression_check_finite(this%expr%src, this%g, m, &
179 "boundary condition")
180 if (neko_bcknd_device .eq. 1) then
181 call device_memcpy(this%g, this%g_d, m, host_to_device, &
182 sync = .true.)
183 end if
184 end if
185
186 end subroutine expression_dirichlet_finalize
187
193 subroutine expression_dirichlet_update(this, time, strm)
194 class(expression_dirichlet_t), intent(inout) :: this
195 type(time_state_t), intent(in), optional :: time
196 type(c_ptr), intent(inout), optional :: strm
197 integer :: m
198
199 if (.not. this%expr%time_dependent) return
200 if (this%updated) return
201
202 if (.not. present(time)) then
203 call neko_error("The boundary condition expression '" // &
204 this%expr%src // "' depends on time, but the solver did not " // &
205 "provide a time state")
206 end if
207
208 m = this%msk(0)
209 call this%expr%eval(this%g, m, this%xm, this%ym, this%zm, time%t, time%dt)
210 call expression_check_finite(this%expr%src, this%g, m, &
211 "boundary condition")
212
213 if (neko_bcknd_device .eq. 1) then
214 ! Synchronous on purpose: the host buffer is reused every timestep,
215 ! and the copy is only as large as the mask.
216 call device_memcpy(this%g, this%g_d, m, host_to_device, &
217 sync = .true., strm = strm)
218 end if
219
220 this%updated = .true.
221
222 end subroutine expression_dirichlet_update
223
229 subroutine expression_dirichlet_apply_scalar(this, x, n, time, strong)
230 class(expression_dirichlet_t), intent(inout) :: this
231 integer, intent(in) :: n
232 real(kind=rp), intent(inout), dimension(n) :: x
233 type(time_state_t), intent(in), optional :: time
234 logical, intent(in), optional :: strong
235 integer :: i, m
236 logical :: strong_
237
238 if (present(strong)) then
239 strong_ = strong
240 else
241 strong_ = .true.
242 end if
243
244 m = this%msk(0)
245 if (.not. strong_ .or. m .eq. 0) return
246
247 ! The bc list applies the host conditions from inside an OpenMP parallel
248 ! region, and evaluating an expression mutates the shared evaluation stack
249 ! of `expr`, so only one thread may run the update. The implicit barrier of
250 ! `single` also makes `g` visible to every thread before the loop below.
251 !$omp single
252 call this%update(time)
253 !$omp end single
254
255 !$omp do
256 do i = 1, m
257 x(this%msk(i)) = this%g(i)
258 end do
259 !$omp end do
260
262
270 subroutine expression_dirichlet_apply_vector(this, x, y, z, n, time, strong)
271 class(expression_dirichlet_t), intent(inout) :: this
272 integer, intent(in) :: n
273 real(kind=rp), intent(inout), dimension(n) :: x
274 real(kind=rp), intent(inout), dimension(n) :: y
275 real(kind=rp), intent(inout), dimension(n) :: z
276 type(time_state_t), intent(in), optional :: time
277 logical, intent(in), optional :: strong
279
285 subroutine expression_dirichlet_apply_scalar_dev(this, x_d, time, strong, &
286 strm)
287 class(expression_dirichlet_t), intent(inout), target :: this
288 type(c_ptr), intent(inout) :: x_d
289 type(time_state_t), intent(in), optional :: time
290 logical, intent(in), optional :: strong
291 type(c_ptr), intent(inout) :: strm
292 integer :: m
293 logical :: strong_
294
295 if (present(strong)) then
296 strong_ = strong
297 else
298 strong_ = .true.
299 end if
300
301 m = this%msk(0)
302 if (.not. strong_ .or. m .eq. 0) return
303
304 call this%update(time, strm)
305
306 call device_inhom_dirichlet_apply_scalar(this%msk_d, x_d, this%g_d, m, strm)
307
309
317 subroutine expression_dirichlet_apply_vector_dev(this, x_d, y_d, z_d, &
318 time, strong, strm)
319 class(expression_dirichlet_t), intent(inout), target :: this
320 type(c_ptr), intent(inout) :: x_d
321 type(c_ptr), intent(inout) :: y_d
322 type(c_ptr), intent(inout) :: z_d
323 type(time_state_t), intent(in), optional :: time
324 logical, intent(in), optional :: strong
325 type(c_ptr), intent(inout) :: strm
327
334 subroutine expression_mask_coords(bc, xm, ym, zm)
335 class(bc_t), intent(in) :: bc
336 real(kind=rp), intent(inout) :: xm(:)
337 real(kind=rp), intent(inout) :: ym(:)
338 real(kind=rp), intent(inout) :: zm(:)
339
340 call gather_coords(bc%msk, bc%msk(0), bc%dof%x, bc%dof%y, bc%dof%z, &
341 size(bc%dof%x), xm, ym, zm)
342
343 end subroutine expression_mask_coords
344
357 subroutine gather_coords(msk, m, x, y, z, n, xm, ym, zm)
358 integer, intent(in) :: m
359 integer, intent(in) :: n
360 integer, intent(in) :: msk(0:m)
361 real(kind=rp), intent(in) :: x(n)
362 real(kind=rp), intent(in) :: y(n)
363 real(kind=rp), intent(in) :: z(n)
364 real(kind=rp), intent(inout) :: xm(m)
365 real(kind=rp), intent(inout) :: ym(m)
366 real(kind=rp), intent(inout) :: zm(m)
367 integer :: i, k
368
369 do i = 1, m
370 k = msk(i)
371 xm(i) = x(k)
372 ym(i) = y(k)
373 zm(i) = z(k)
374 end do
375
376 end subroutine gather_coords
377
378end 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
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:72
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:93
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.