Neko 1.99.9
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, bc_neumann
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%bc_type = bc_neumann
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 real(kind=rp) :: area
182 logical :: strong_
183
184 if (present(strong)) then
185 strong_ = strong
186 else
187 strong_ = .true.
188 end if
189
190 if (.not. strong_) then
191
192 !$omp single
193 if (.not. this%updated) then
194 call this%update(this%field_list, this, time)
195 call this%gather_flux()
196 this%updated = .true.
197 end if
198 !$omp end single
199
200 m = this%facet_node_msk(0)
201 !$omp do
202 do i = 1, m
203 k = this%facet_node_msk(i)
204 facet = this%facet(i)
205 idx = nonlinear_index(k, this%coef%Xh%lx, this%coef%Xh%lx, &
206 this%coef%Xh%lx)
207 area = 0.0_rp
208 select case (facet)
209 case (1,2)
210 area = this%coef%area(idx(2), idx(3), facet, idx(4))
211 case (3,4)
212 area = this%coef%area(idx(1), idx(3), facet, idx(4))
213 case (5,6)
214 area = this%coef%area(idx(1), idx(2), facet, idx(4))
215 end select
216 !$omp atomic
217 x(k) = x(k) + this%flux%x(i) * area
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 !$omp single
244 if (.not. this%updated) then
245 call this%update(this%field_list, this, time)
246 call this%gather_flux()
247 this%updated = .true.
248 end if
249 !$omp end single
250
251 if (this%facet_node_msk(0) .gt. 0) then
252 call device_neumann_apply_scalar(this%facet_node_msk_d, &
253 this%facet_d, x_d, &
254 this%flux%x_d, this%coef%area_d, this%coef%Xh%lx, &
255 size(this%facet_node_msk), strm)
256 end if
257 end if
258
259 end subroutine field_neumann_apply_scalar_dev
260
262 subroutine field_neumann_apply_vector(this, x, y, z, n, time, strong)
263 class(field_neumann_t), intent(inout) :: this
264 integer, intent(in) :: n
265 real(kind=rp), intent(inout), dimension(n) :: x
266 real(kind=rp), intent(inout), dimension(n) :: y
267 real(kind=rp), intent(inout), dimension(n) :: z
268 type(time_state_t), intent(in), optional :: time
269 logical, intent(in), optional :: strong
270
271 call neko_error("field_neumann cannot apply vector BCs.")
272
273 end subroutine field_neumann_apply_vector
274
276 subroutine field_neumann_apply_vector_dev(this, x_d, y_d, z_d, time, &
277 strong, strm)
278 class(field_neumann_t), intent(inout), target :: this
279 type(c_ptr), intent(inout) :: x_d
280 type(c_ptr), intent(inout) :: y_d
281 type(c_ptr), intent(inout) :: z_d
282 type(time_state_t), intent(in), optional :: time
283 logical, intent(in), optional :: strong
284 type(c_ptr), intent(inout) :: strm
285
286 call neko_error("field_neumann cannot apply vector BCs.")
287
288 end subroutine field_neumann_apply_vector_dev
289
291 subroutine field_neumann_finalize(this)
292 class(field_neumann_t), target, intent(inout) :: this
293
294 call this%finalize_base()
295 call this%flux%init(this%msk(0))
296
297 end subroutine field_neumann_finalize
298
299end 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
integer, parameter, public bc_neumann
Definition bc.f90:70
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_apply_scalar_dev(this, x_d, time, strong, strm)
Apply scalar (device).
subroutine field_neumann_finalize(this)
Finalize.
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:364
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
Defines a vector.
Definition vector.f90:34
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
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.