Neko 1.99.5
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
field_neumann.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 coefs, only : coef_t
37 use bc, only : bc_t
38 use field, only : field_t
39 use field_list, only : field_list_t
40 use vector, only : vector_t
42 use json_module, only : json_file
43 use json_utils, only : json_get
44 use math, only : masked_gather_copy_0
48 use, intrinsic :: iso_c_binding, only : c_ptr
49 use time_state, only : time_state_t
50 implicit none
51 private
52
59 type, public, extends(bc_t) :: field_neumann_t
61 type(field_t) :: field_bc
65 type(vector_t) :: flux
67 procedure(field_neumann_update), nopass, pointer :: update => null()
68 contains
70 procedure, pass(this) :: init => field_neumann_init
72 procedure, pass(this) :: init_from_components => &
75 procedure, pass(this) :: free => field_neumann_free
77 procedure, pass(this) :: finalize => field_neumann_finalize
79 procedure, pass(this) :: apply_scalar => field_neumann_apply_scalar
81 procedure, pass(this) :: apply_vector => field_neumann_apply_vector
83 procedure, pass(this) :: apply_vector_dev => field_neumann_apply_vector_dev
85 procedure, pass(this) :: apply_scalar_dev => field_neumann_apply_scalar_dev
87 procedure, pass(this), private :: gather_flux => field_neumann_gather_flux
88
89 end type field_neumann_t
90
92 abstract interface
93 subroutine field_neumann_update(fields, bc, time)
95 type(field_list_t), intent(inout) :: fields
96 type(field_neumann_t), intent(in) :: bc
97 type(time_state_t), intent(in) :: time
98 end subroutine field_neumann_update
99 end interface
100
101 public :: field_neumann_update
102
103contains
107 subroutine field_neumann_init(this, coef, json)
108 class(field_neumann_t), intent(inout), target :: this
109 type(coef_t), target, intent(in) :: coef
110 type(json_file), intent(inout) :: json
111 character(len=:), allocatable :: field_name
112
113 call json_get(json, "field_name", field_name)
114 call this%init_from_components(coef, field_name)
115 if (allocated(field_name)) then
116 deallocate(field_name)
117 end if
118
119 end subroutine field_neumann_init
120
124 subroutine field_neumann_init_from_components(this, coef, field_name)
125 class(field_neumann_t), intent(inout), target :: this
126 type(coef_t), intent(in) :: coef
127 character(len=*), intent(in) :: field_name
128
129 call this%init_base(coef)
130 this%strong = .false.
131
132 call this%field_bc%init(this%dof, field_name)
133 call this%field_list%init(1)
134 call this%field_list%assign_to_field(1, this%field_bc)
135
137
139 subroutine field_neumann_free(this)
140 class(field_neumann_t), target, intent(inout) :: this
141
142 call this%free_base
143 call this%field_bc%free()
144 call this%field_list%free()
145 call this%flux%free()
146
147 if (associated(this%update)) then
148 this%update => null()
149 end if
150
151 end subroutine field_neumann_free
152
155 class(field_neumann_t), intent(inout) :: this
156
157 if (this%msk(0) .gt. 0) then
158 if (neko_bcknd_device .eq. 1) then
159 call device_masked_gather_copy_0(this%flux%x_d, this%field_bc%x_d, &
160 this%msk_d, this%field_bc%dof%size(), this%msk(0))
161 else
162 call masked_gather_copy_0(this%flux%x, this%field_bc%x, &
163 this%msk, this%field_bc%dof%size(), this%msk(0))
164 end if
165 end if
166
167 end subroutine field_neumann_gather_flux
168
173 subroutine field_neumann_apply_scalar(this, x, n, time, strong)
174 class(field_neumann_t), intent(inout) :: this
175 integer, intent(in) :: n
176 real(kind=rp), intent(inout), dimension(n) :: x
177 type(time_state_t), intent(in), optional :: time
178 logical, intent(in), optional :: strong
179 integer :: i, m, k, facet
180 integer :: idx(4)
181 logical :: strong_
182
183 if (present(strong)) then
184 strong_ = strong
185 else
186 strong_ = .true.
187 end if
188
189 if (.not. strong_) then
190
191 if (.not. this%updated) then
192 call this%update(this%field_list, this, time)
193 call this%gather_flux()
194 this%updated = .true.
195 end if
196
197 m = this%msk(0)
198 !$omp do
199 do i = 1, m
200 k = this%msk(i)
201 facet = this%facet(i)
202 idx = nonlinear_index(k, this%coef%Xh%lx, this%coef%Xh%lx, &
203 this%coef%Xh%lx)
204 select case (facet)
205 case (1,2)
206 x(k) = x(k) + &
207 this%flux%x(i) * &
208 this%coef%area(idx(2), idx(3), facet, idx(4))
209 case (3,4)
210 x(k) = x(k) + &
211 this%flux%x(i) * &
212 this%coef%area(idx(1), idx(3), facet, idx(4))
213 case (5,6)
214 x(k) = x(k) + &
215 this%flux%x(i) * &
216 this%coef%area(idx(1), idx(2), facet, idx(4))
217 end select
218 end do
219 !$omp end do
220 end if
221
222 end subroutine field_neumann_apply_scalar
223
228 subroutine field_neumann_apply_scalar_dev(this, x_d, time, strong, strm)
229 class(field_neumann_t), intent(inout), target :: this
230 type(c_ptr), intent(inout) :: x_d
231 type(time_state_t), intent(in), optional :: time
232 logical, intent(in), optional :: strong
233 type(c_ptr), intent(inout) :: strm
234 logical :: strong_
235
236 if (present(strong)) then
237 strong_ = strong
238 else
239 strong_ = .true.
240 end if
241
242 if (.not. strong_) then
243 if (.not. this%updated) then
244 call this%update(this%field_list, this, time)
245 call this%gather_flux()
246 this%updated = .true.
247 end if
248
249 if (this%msk(0) .gt. 0) then
250 call device_neumann_apply_scalar(this%msk_d, this%facet_d, x_d, &
251 this%flux%x_d, this%coef%area_d, this%coef%Xh%lx, &
252 size(this%msk), strm)
253 end if
254 end if
255
256 end subroutine field_neumann_apply_scalar_dev
257
259 subroutine field_neumann_apply_vector(this, x, y, z, n, time, strong)
260 class(field_neumann_t), intent(inout) :: this
261 integer, intent(in) :: n
262 real(kind=rp), intent(inout), dimension(n) :: x
263 real(kind=rp), intent(inout), dimension(n) :: y
264 real(kind=rp), intent(inout), dimension(n) :: z
265 type(time_state_t), intent(in), optional :: time
266 logical, intent(in), optional :: strong
267
268 call neko_error("field_neumann cannot apply vector BCs.")
269
270 end subroutine field_neumann_apply_vector
271
273 subroutine field_neumann_apply_vector_dev(this, x_d, y_d, z_d, time, &
274 strong, strm)
275 class(field_neumann_t), intent(inout), target :: this
276 type(c_ptr), intent(inout) :: x_d
277 type(c_ptr), intent(inout) :: y_d
278 type(c_ptr), intent(inout) :: z_d
279 type(time_state_t), intent(in), optional :: time
280 logical, intent(in), optional :: strong
281 type(c_ptr), intent(inout) :: strm
282
283 call neko_error("field_neumann cannot apply vector BCs.")
284
285 end subroutine field_neumann_apply_vector_dev
286
288 subroutine field_neumann_finalize(this, only_facets)
289 class(field_neumann_t), target, intent(inout) :: this
290 logical, optional, intent(in) :: only_facets
291
292 if (present(only_facets)) then
293 if (.not. only_facets) then
294 call neko_error("For field_neumann_t, only_facets has to be true.")
295 end if
296 end if
297
298 call this%finalize_base(.true.)
299 call this%flux%init(this%msk(0))
300
301 end subroutine field_neumann_finalize
302
303end module field_neumann
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
Definition bc_utils.h:44
Abstract interface defining a neumann condition on a list of fields.
Retrieves a parameter by name or throws an error.
Defines a boundary condition.
Definition bc.f90:34
Coefficients.
Definition coef.f90:34
subroutine, public device_masked_gather_copy_0(a_d, b_d, mask_d, n, n_mask, strm)
Gather a masked vector .
subroutine, public device_neumann_apply_scalar(msk, facet, x, flux, area, lx, m, strm)
Defines user neumann condition for a scalar field.
subroutine field_neumann_gather_flux(this)
Gather field-defined values into compact boundary flux storage.
subroutine field_neumann_apply_vector_dev(this, x_d, y_d, z_d, time, strong, strm)
(No-op) Apply vector (device).
subroutine field_neumann_free(this)
Destructor.
subroutine field_neumann_finalize(this, only_facets)
Finalize.
subroutine field_neumann_apply_scalar_dev(this, x_d, time, strong, strm)
Apply scalar (device).
subroutine field_neumann_apply_vector(this, x, y, z, n, time, strong)
(No-op) Apply vector.
subroutine field_neumann_init(this, coef, json)
Constructor.
subroutine field_neumann_apply_scalar(this, x, n, time, strong)
Apply scalar by adding weak neumann contribution.
subroutine field_neumann_init_from_components(this, coef, field_name)
Constructor from components.
Defines a field.
Definition field.f90:34
Utilities for retrieving parameters from the case files.
Definition math.f90:60
subroutine, public masked_gather_copy_0(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
Definition math.f90:360
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
Defines a vector.
Definition vector.f90:34
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:62
field_list_t, To be able to group fields together
User defined neumann condition, for which the user can work with an entire field. The type stores a s...
A struct that contains all info about the time, expand as needed.