Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
source_term_handler.f90
Go to the documentation of this file.
1
2! Copyright (c) 2023, The Neko Authors
3! All rights reserved.
4!
5! Redistribution and use in source and binary forms, with or without
6! modification, are permitted provided that the following conditions
7! are met:
8!
9! * Redistributions of source code must retain the above copyright
10! notice, this list of conditions and the following disclaimer.
11!
12! * Redistributions in binary form must reproduce the above
13! copyright notice, this list of conditions and the following
14! disclaimer in the documentation and/or other materials provided
15! with the distribution.
16!
17! * Neither the name of the authors nor the names of its
18! contributors may be used to endorse or promote products derived
19! from this software without specific prior written permission.
20!
21! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32! POSSIBILITY OF SUCH DAMAGE.
33!
37 use num_types, only: rp
39 source_term_factory
40 use field, only: field_t
41 use field_list, only: field_list_t
43 use json_module, only: json_file
44 use coefs, only: coef_t
45 use user_intf, only: user_t
47 use math, only : col2
48 use device_math, only : device_col2
49 use time_state, only : time_state_t
51 implicit none
52 private
53
64 type, abstract, public :: source_term_handler_t
66 class(source_term_wrapper_t), allocatable :: source_terms(:)
68 type(field_list_t) :: rhs_fields
70 type(coef_t), pointer :: coef
72 type(user_t), pointer :: user
74 character(len=:), allocatable :: scheme_name
77 integer :: n_unextrapolated = 0
78
79 contains
81 procedure, pass(this) :: init_base => source_term_handler_init_base
83 procedure, pass(this) :: free => source_term_handler_free
85 procedure, pass(this) :: compute => source_term_handler_compute
87 generic :: add => add_source_term, add_json_source_terms
89 procedure, pass(this) :: add_source_term => &
92 procedure, pass(this) :: add_json_source_terms => &
96 nopass, deferred :: init_user_source
98
99 abstract interface
100 subroutine source_term_handler_init_user_source(source_term, rhs_fields, &
101 coef, user, scheme_name)
103 class(source_term_t), allocatable, intent(inout) :: source_term
104 type(field_list_t) :: rhs_fields
105 type(coef_t), intent(in) :: coef
106 type(user_t), intent(in) :: user
107 character(len=*), intent(in) :: scheme_name
109 end interface
110
111contains
112
114 subroutine source_term_handler_init_base(this, rhs_fields, coef, user, &
115 scheme_name)
116 class(source_term_handler_t), intent(inout) :: this
117 type(field_list_t), intent(in) :: rhs_fields
118 type(coef_t), target, intent(in) :: coef
119 type(user_t), target, intent(in) :: user
120 character(len=*), intent(in) :: scheme_name
121
122 call this%free()
123
124 ! We package the fields for the source term to operate on in a field list.
125 this%rhs_fields = rhs_fields
126 this%coef => coef
127 this%user => user
128 this%scheme_name = trim(scheme_name)
129
130 end subroutine source_term_handler_init_base
131
132
135 class(source_term_handler_t), intent(inout) :: this
136 integer :: i
137
138 call this%rhs_fields%free()
139
140 if (allocated(this%source_terms)) then
141 do i = 1, size(this%source_terms)
142 call this%source_terms(i)%free()
143 end do
144 deallocate(this%source_terms)
145 end if
146 this%n_unextrapolated = 0
147
148 nullify(this%coef)
149 nullify(this%user)
150
151 if (allocated(this%scheme_name)) then
152 deallocate(this%scheme_name)
153 end if
154
155 end subroutine source_term_handler_free
156
168 subroutine source_term_handler_compute(this, time, extrapolate, scale)
169 class(source_term_handler_t), intent(inout) :: this
170 type(time_state_t), intent(in) :: time
171 logical, intent(in) :: extrapolate
172 type(field_t), intent(in), optional :: scale
173 type(field_list_t) :: stash
174 type(field_t), pointer :: f, s
175 integer, allocatable :: stash_idx(:)
176 integer :: i, n_rhs
177
178 n_rhs = this%rhs_fields%size()
179
180 ! The terms that are not extrapolated are added on top of the
181 ! right-hand side, which is stashed in scratch fields meanwhile.
182 if (.not. extrapolate) then
183 if (this%n_unextrapolated .eq. 0) return
184 call stash%init(n_rhs)
185 allocate(stash_idx(n_rhs))
186 do i = 1, n_rhs
187 f => this%rhs_fields%get(i)
188 call neko_scratch_registry%request_field(s, stash_idx(i), .false.)
189 call field_copy(s, f)
190 call stash%assign(i, s)
191 end do
192 end if
193
194 do i = 1, n_rhs
195 f => this%rhs_fields%get(i)
196 call field_rzero(f)
197 end do
198
199 ! Add contribution from the selected source terms. If time permits.
200 if (allocated(this%source_terms)) then
201
202 do i = 1, size(this%source_terms)
203 if (this%source_terms(i)%source_term%extrapolate .neqv. &
204 extrapolate) cycle
205 call this%source_terms(i)%source_term%compute(time)
206 end do
207
208 ! Multiply by mass matrix and scale
209 do i = 1, n_rhs
210 f => this%rhs_fields%get(i)
211 if (neko_bcknd_device .eq. 1) then
212 call device_col2(f%x_d, this%coef%B_d, f%size())
213 else
214 call col2(f%x, this%coef%B, f%size())
215 end if
216 if (present(scale)) call field_col2(f, scale)
217 end do
218
219 end if
220
221 ! Add back the stashed right-hand side
222 if (.not. extrapolate) then
223 do i = 1, n_rhs
224 f => this%rhs_fields%get(i)
225 s => stash%get(i)
226 call field_add2(f, s)
227 end do
228 call neko_scratch_registry%relinquish_field(stash_idx)
229 call stash%free()
230 deallocate(stash_idx)
231 end if
232
233 end subroutine source_term_handler_compute
234
237 class(source_term_handler_t), intent(inout) :: this
238 integer :: i
239
240 this%n_unextrapolated = 0
241 if (.not. allocated(this%source_terms)) return
242
243 do i = 1, size(this%source_terms)
244 if (.not. this%source_terms(i)%source_term%extrapolate) then
245 this%n_unextrapolated = this%n_unextrapolated + 1
246 end if
247 end do
248
250
252 subroutine source_term_handler_add_json_source_terms(this, json, name)
253 class(source_term_handler_t), intent(inout) :: this
254 type(json_file), intent(inout) :: json
255 character(len=*), intent(in) :: name
256
257 class(source_term_wrapper_t), dimension(:), allocatable :: temp
258
259 ! A single source term as its own json_file.
260 type(json_file) :: source_subdict
261 character(len=:), allocatable :: type
262 integer :: n_sources, i, i0
263
264 if (json%valid_path(name)) then
265 ! Get the number of source terms.
266 call json%info(name, n_children = n_sources)
267
268 if (allocated(this%source_terms)) then
269 i0 = size(this%source_terms)
270 call move_alloc(this%source_terms, temp)
271 allocate(this%source_terms(i0 + n_sources))
272 if (allocated(temp)) then
273 do i = 1, i0
274 call move_alloc(temp(i)%source_term, &
275 this%source_terms(i)%source_term)
276 end do
277 end if
278 else
279 i0 = 0
280 allocate(this%source_terms(n_sources))
281 end if
282
283 do i = 1, n_sources
284 ! Create a new json containing just the subdict for this source.
285 call json_extract_item(json, name, i, source_subdict)
286 call json_get(source_subdict, "type", type)
287
288 ! The user source is treated separately
289 if (trim(type) .eq. "user") then
290
291 call this%init_user_source(this%source_terms(i+ i0)%source_term, &
292 this%rhs_fields, this%coef, this%user, this%scheme_name)
293
294 call json_get_or_default(source_subdict, "start_time", &
295 this%source_terms(i + i0)%source_term%start_time, 0.0_rp)
296 call json_get_or_default(source_subdict, "end_time", &
297 this%source_terms(i + i0)%source_term%end_time, huge(0.0_rp))
298 else
299 call source_term_factory(this%source_terms(i + i0)%source_term, &
300 source_subdict, this%rhs_fields, this%coef, &
301 this%scheme_name)
302 end if
303 end do
304
306 end if
307
309
312 subroutine source_term_handler_add_source_term(this, source_term)
313 class(source_term_handler_t), intent(inout) :: this
314 class(source_term_t), intent(in) :: source_term
315 class(source_term_wrapper_t), dimension(:), allocatable :: temp
316
317 integer :: n_sources, i
318
319 if (allocated(this%source_terms)) then
320 n_sources = size(this%source_terms)
321 else
322 n_sources = 0
323 end if
324
325 call move_alloc(this%source_terms, temp)
326 allocate(this%source_terms(n_sources + 1))
327
328 if (allocated(temp)) then
329 do i = 1, n_sources
330 call move_alloc(temp(i)%source_term, &
331 this%source_terms(i)%source_term)
332 end do
333 end if
334
335 this%source_terms(n_sources + 1)%source_term = source_term
336
338
340end module source_term_handler
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Retrieves a parameter by name or throws an error.
Coefficients.
Definition coef.f90:34
subroutine, public device_col2(a_d, b_d, n, strm)
Vector multiplication .
subroutine, public field_col2(a, b, n)
Vector multiplication .
subroutine, public field_rzero(a, n)
Zero a real vector.
subroutine, public field_add2(a, b, n)
Vector addition .
subroutine, public field_copy(a, b, n)
Copy a vector .
Defines a field.
Definition field.f90:34
Utilities for retrieving parameters from the case files.
Definition math.f90:60
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:1085
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines a registry for storing and requesting temporary objects This can be used when you have a func...
type(scratch_registry_t), target, public neko_scratch_registry
Global scratch registry.
Implements the source_term_handler_t type.
subroutine source_term_handler_free(this)
Destructor.
subroutine source_term_handler_init_base(this, rhs_fields, coef, user, scheme_name)
Constructor.
subroutine source_term_handler_compute(this, time, extrapolate, scale)
Add source terms to the right-hand side fields.
subroutine source_term_handler_add_json_source_terms(this, json, name)
Read from the json file and initialize the source terms.
subroutine source_term_handler_count_unextrapolated(this)
Count the source terms that are not extrapolated in time.
subroutine source_term_handler_add_source_term(this, source_term)
Add new source term to the list.
Implements the source_term_t type and a wrapper source_term_wrapper_t.
Module with things related to the simulation time.
Interfaces for user interaction with NEKO.
Definition user_intf.f90:34
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:136
field_list_t, To be able to group fields together
Base abstract type for source terms.
A helper type that is needed to have an array of polymorphic objects.
Abstract class for handling source terms.
A struct that contains all info about the time, expand as needed.
A type collecting all the overridable user routines and flag to suppress type injection from custom m...