Neko 1.99.2
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
simulation_component.f90
Go to the documentation of this file.
1! Copyright (c) 2023, 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!
33!
39 use num_types, only : rp
40 use json_module, only : json_file
41 use case, only : case_t
45 use time_state, only : time_state_t
46 implicit none
47 private
48
50 type, abstract, public :: simulation_component_t
52 type(case_t), pointer :: case
54 type(time_based_controller_t) :: preprocess_controller
56 type(time_based_controller_t) :: compute_controller
60 integer :: order
62 character(:), allocatable :: name
63 contains
65 procedure, pass(this) :: init_base => simulation_component_init_base
67 generic :: init_base_from_components => &
68 init_base_from_controllers_properties, &
69 init_base_from_controllers
73 procedure, pass(this) :: init_base_from_controllers => &
78 procedure, pass(this) :: init_base_from_controllers_properties => &
81 procedure, pass(this) :: free_base => simulation_component_free_base
84 procedure, pass(this) :: restart => simulation_component_restart_wrapper
87 procedure, pass(this) :: preprocess => &
91 procedure, pass(this) :: compute => simulation_component_compute_wrapper
93 procedure(simulation_component_init), pass(this), deferred :: init
95 procedure(simulation_component_free), pass(this), deferred :: free
97 procedure, pass(this) :: preprocess_
99 procedure, pass(this) :: compute_
101 procedure, pass(this) :: restart_
103 procedure, pass(this) :: parse_json => simulation_component_parse_json
105
108 class(simulation_component_t), allocatable :: simcomp
110
111
112 abstract interface
113
116 subroutine simulation_component_init(this, json, case)
117 import simulation_component_t, json_file, case_t
118 class(simulation_component_t), intent(inout), target :: this
119 type(json_file), intent(inout) :: json
120 class(case_t), intent(inout), target :: case
121 end subroutine simulation_component_init
122 end interface
123
124 abstract interface
125
128 class(simulation_component_t), intent(inout) :: this
129 end subroutine simulation_component_free
130 end interface
131
132 interface
133
138 module subroutine simulation_component_factory(object, json, case)
139 class(simulation_component_t), allocatable, intent(inout) :: object
140 type(json_file), intent(inout) :: json
141 class(case_t), intent(inout), target :: case
142 end subroutine simulation_component_factory
143 end interface
144
145 interface
146
149 module subroutine simulation_component_allocator(object, type_name)
150 class(simulation_component_t), allocatable, intent(inout) :: object
151 character(len=*), intent(in):: type_name
152 end subroutine simulation_component_allocator
153 end interface
154
155 !
156 ! Machinery for injecting user-defined types
157 !
158
162 abstract interface
163 subroutine simulation_component_allocate(obj)
164 import simulation_component_t
165 class(simulation_component_t), allocatable, intent(inout) :: obj
166 end subroutine simulation_component_allocate
167 end interface
168
169 interface
170
171 module subroutine register_simulation_component(type_name, allocator)
172 character(len=*), intent(in) :: type_name
173 procedure(simulation_component_allocate), pointer, intent(in) :: &
174 allocator
175 end subroutine register_simulation_component
176 end interface
177
178 ! A name-allocator pair for user-defined types. A helper type to define a
179 ! registry of custom allocators.
180 type allocator_entry
181 character(len=20) :: type_name
182 procedure(simulation_component_allocate), pointer, nopass :: allocator
183 end type allocator_entry
184
186 type(allocator_entry), allocatable :: simcomp_registry(:)
187
189 integer :: simcomp_registry_size = 0
190
191 public :: simulation_component_factory, simulation_component_allocator, &
192 register_simulation_component, simulation_component_allocate
193
194
195contains
197 subroutine simulation_component_init_base(this, json, case)
198 class(simulation_component_t), intent(inout) :: this
199 type(json_file), intent(inout) :: json
200 class(case_t), intent(inout), target :: case
201 character(len=:), allocatable :: preprocess_control, compute_control, &
202 output_control
203 real(kind=rp) :: preprocess_value, compute_value, output_value
204 integer :: order
205
206 call this%parse_json(json, case%params, preprocess_control, &
207 preprocess_value, compute_control, compute_value, output_control, &
208 output_value)
209
210 call json_get_or_default(json, "order", order, -1)
211
212 call this%init_base_from_components(case, order, &
213 preprocess_control, preprocess_value, compute_control, compute_value, &
214 output_control, output_value)
215
216 end subroutine simulation_component_init_base
217
228 subroutine simulation_component_init_base_from_controllers_properties(this, &
229 case, order, preprocess_control, preprocess_value, compute_control, &
230 compute_value, output_control, output_value)
231 class(simulation_component_t), intent(inout) :: this
232 class(case_t), intent(inout), target :: case
233 integer :: order
234 character(len=*), intent(in) :: preprocess_control
235 real(kind=rp), intent(in) :: preprocess_value
236 character(len=*), intent(in) :: compute_control
237 real(kind=rp), intent(in) :: compute_value
238 character(len=*), intent(in) :: output_control
239 real(kind=rp), intent(in) :: output_value
240
241 this%case => case
242 this%order = order
243
244 call this%preprocess_controller%init(case%time%start_time, &
245 case%time%end_time, preprocess_control, preprocess_value)
246 call this%compute_controller%init(case%time%start_time, case%time%end_time,&
247 compute_control, compute_value)
248 call this%output_controller%init(case%time%start_time, case%time%end_time, &
249 output_control, output_value)
250
251 end subroutine simulation_component_init_base_from_controllers_properties
252
259 subroutine simulation_component_init_base_from_controllers(this, case, order,&
260 preprocess_controller, compute_controller, output_controller)
261 class(simulation_component_t), intent(inout) :: this
262 class(case_t), intent(inout), target :: case
263 integer :: order
264 type(time_based_controller_t), intent(in) :: preprocess_controller
265 type(time_based_controller_t), intent(in) :: compute_controller
266 type(time_based_controller_t), intent(in) :: output_controller
267
268 this%case => case
269 this%order = order
270 this%preprocess_controller = preprocess_controller
271 this%compute_controller = compute_controller
272 this%output_controller = output_controller
273 end subroutine simulation_component_init_base_from_controllers
274
284 subroutine simulation_component_parse_json(this, json, case_params, &
285 preprocess_control, preprocess_value, compute_control, compute_value, &
286 output_control, output_value)
287 class(simulation_component_t), intent(inout) :: this
288 type(json_file), intent(inout) :: json
289 type(json_file), intent(inout) :: case_params
290 character(len=:), allocatable, intent(inout) :: preprocess_control
291 real(kind=rp), intent(out) :: preprocess_value
292 character(len=:), allocatable, intent(inout) :: compute_control
293 real(kind=rp), intent(out) :: compute_value
294 character(len=:), allocatable, intent(inout) :: output_control
295 real(kind=rp), intent(out) :: output_value
296 integer :: preprocess_value_int, compute_value_int, output_value_int
297 character(len=:), allocatable :: json_path
298 type(json_file) :: json_object
299
300 !
301 ! Preprocess
302 !
303
304 ! Get the preprocess control, defaulting to tsteps, pin to fluid if
305 ! requested
306 call json_get_or_default(json, "preprocess_control", preprocess_control, &
307 "tsteps")
308
309 json_path = "preprocess_value"
310 json_object = json
311 if (preprocess_control .eq. "fluid_output") then
312 call json_get(case_params, 'case.fluid.output_control', &
313 preprocess_control)
314 json_path = "case.fluid.output_value"
315 json_object = case_params
316 end if
317
318 ! Read preprocess value based on control type
319 if ((preprocess_control .eq. "tsteps") .or. &
320 (preprocess_control .eq. "nsamples")) then
321 ! Read it is an interger, and convert to real
322 call json_get_or_lookup_or_default(json_object, json_path, &
323 preprocess_value_int, 1)
324 preprocess_value = real(preprocess_value_int, kind=rp)
325 else if (preprocess_control .eq. "simulationtime") then
326 ! Read as real
327 call json_get_or_lookup_or_default(json_object, json_path, &
328 preprocess_value, 1.0_rp)
329 else if (preprocess_control .eq. "never") then
330 ! Dummy value
331 preprocess_value = 0.0_rp
332 end if
333
334 !
335 ! Compute
336 !
337
338 ! Get the compute control, defaulting to tsteps, pin to fluid if
339 ! requested
340 call json_get_or_default(json, "compute_control", compute_control, &
341 "tsteps")
342
343 json_path = "compute_value"
344 json_object = json
345 if (compute_control .eq. "fluid_output") then
346 call json_get(case_params, 'case.fluid.output_control', &
347 compute_control)
348 json_path = "case.fluid.output_value"
349 json_object = case_params
350 end if
351
352 ! Read compute value based on control type
353 if ((compute_control .eq. "tsteps") .or. &
354 (compute_control .eq. "nsamples")) then
355 ! Read it is an interger, and convert to real
356 call json_get_or_lookup_or_default(json_object, json_path, &
357 compute_value_int, 1)
358 compute_value = real(compute_value_int, kind=rp)
359 else if (compute_control .eq. "simulationtime") then
360 ! Read as real
361 call json_get_or_lookup_or_default(json_object, json_path, &
362 compute_value, 1.0_rp)
363 compute_value_int = int(compute_value)
364 else if (compute_control .eq. "never") then
365 ! Dummy value
366 compute_value = 0.0_rp
367 compute_value_int = 0
368 end if
369
370 !
371 ! Output
372 !
373
374 ! We default to output whenever we execute, pin to fluid if requested
375 call json_get_or_default(json, "output_control", output_control, &
376 compute_control)
377
378 json_path = "output_value"
379 json_object = json
380 if (output_control .eq. "global") then
381 call json_get(case_params, 'case.fluid.output_control', &
382 output_control)
383 json_path = "case.fluid.output_value"
384 json_object = case_params
385 end if
386
387
388 ! Read output value based on control type. We default to compute_value
389 if ((output_control .eq. "tsteps") .or. &
390 (output_control .eq. "nsamples")) then
391 ! Read it is an interger, and convert to real
392 call json_get_or_lookup_or_default(json_object, json_path, &
393 output_value_int, compute_value_int)
394 output_value = real(output_value_int, kind=rp)
395 else if (output_control .eq. "simulationtime") then
396 ! Read as real
397 call json_get_or_lookup_or_default(json_object, json_path, &
398 output_value, compute_value)
399 else if (output_control .eq. "never") then
400 ! Dummy value
401 output_value = 0.0_rp
402 end if
403
404 deallocate(json_path)
405 end subroutine simulation_component_parse_json
406
408 subroutine simulation_component_free_base(this)
409 class(simulation_component_t), intent(inout) :: this
410
411 nullify(this%case)
412
413 if (allocated(this%name)) then
414 deallocate(this%name)
415 end if
416
417 call this%preprocess_controller%free()
418 call this%compute_controller%free()
419 call this%output_controller%free()
420 end subroutine simulation_component_free_base
421
425 subroutine simulation_component_preprocess_wrapper(this, time)
426 class(simulation_component_t), intent(inout) :: this
427 type(time_state_t), intent(in) :: time
428
429 if (this%preprocess_controller%check(time)) then
430 call this%preprocess_(time)
431 call this%preprocess_controller%register_execution()
432 end if
433 end subroutine simulation_component_preprocess_wrapper
434
438 subroutine simulation_component_compute_wrapper(this, time)
439 class(simulation_component_t), intent(inout) :: this
440 type(time_state_t), intent(in) :: time
441
442 if (this%compute_controller%check(time)) then
443 call this%compute_(time)
444 call this%compute_controller%register_execution()
445 end if
446 end subroutine simulation_component_compute_wrapper
447
450 subroutine simulation_component_restart_wrapper(this, time)
451 class(simulation_component_t), intent(inout) :: this
452 type(time_state_t), intent(in) :: time
453
454 call this%compute_controller%set_counter(time)
455 call this%output_controller%set_counter(time)
456 call this%restart_(time)
457
458 end subroutine simulation_component_restart_wrapper
459
462 subroutine restart_(this, time)
463 class(simulation_component_t), intent(inout) :: this
464 type(time_state_t), intent(in) :: time
465
466 ! Do nothing
467 end subroutine restart_
468
471 subroutine preprocess_(this, time)
472 class(simulation_component_t), intent(inout) :: this
473 type(time_state_t), intent(in) :: time
474
475 ! Do nothing
476 end subroutine preprocess_
477
480 subroutine compute_(this, time)
481 class(simulation_component_t), intent(inout) :: this
482 type(time_state_t), intent(in) :: time
483
484 ! Do nothing
485 end subroutine compute_
486end module simulation_component
double real
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.
The common constructor using a JSON dictionary.
Defines a simulation case.
Definition case.f90:34
Utilities for retrieving parameters from the case files.
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Implements output_controller_t
Simulation components are objects that encapsulate functionality that can be fit to a particular comp...
subroutine simulation_component_free_base(this)
Destructor for the simulation_component_t (base) class.
subroutine restart_(this, time)
Dummy restart function.
subroutine simulation_component_restart_wrapper(this, time)
Wrapper for calling set_counter_ based for the controllers.
subroutine simulation_component_init_base_from_controllers(this, case, order, preprocess_controller, compute_controller, output_controller)
Constructor for the simulation_component_t (base) class from components.
subroutine preprocess_(this, time)
Dummy preprocessing function.
subroutine simulation_component_init_base_from_controllers_properties(this, case, order, preprocess_control, preprocess_value, compute_control, compute_value, output_control, output_value)
Constructor for the simulation_component_t (base) class via the properties of the time_based_controll...
subroutine simulation_component_init_base(this, json, case)
Constructor for the simulation_component_t (base) class.
subroutine compute_(this, time)
Dummy compute function.
subroutine simulation_component_preprocess_wrapper(this, time)
Wrapper for calling preprocess_ based on the preprocess_controller. Serves as the public interface.
subroutine simulation_component_parse_json(this, json, case_params, preprocess_control, preprocess_value, compute_control, compute_value, output_control, output_value)
Parse JSON to determine the properties of the time_based_controllers.
subroutine simulation_component_compute_wrapper(this, time)
Wrapper for calling compute_ based on the compute_controller. Serves as the public interface.
Contains the time_based_controller_t type.
Module with things related to the simulation time.
Base abstract class for simulation components.
A helper type that is needed to have an array of polymorphic objects.
A utility type for determining whether an action should be executed based on the current time value....
A struct that contains all info about the time, expand as needed.