Neko 1.99.3
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
109 contains
111 procedure, pass(this) :: init => simulation_component_wrapper_init
113 procedure, pass(this) :: free => simulation_component_wrapper_free
116 procedure, pass(this) :: move_from => &
119 procedure, pass(this) :: is_allocated => &
122
123 abstract interface
124
127 subroutine simulation_component_init(this, json, case)
128 import simulation_component_t, json_file, case_t
129 class(simulation_component_t), intent(inout), target :: this
130 type(json_file), intent(inout) :: json
131 class(case_t), intent(inout), target :: case
132 end subroutine simulation_component_init
133 end interface
134
135 abstract interface
136
139 class(simulation_component_t), intent(inout) :: this
140 end subroutine simulation_component_free
141 end interface
142
143 interface
144
149 module subroutine simulation_component_factory(object, json, case)
150 class(simulation_component_t), allocatable, intent(inout) :: object
151 type(json_file), intent(inout) :: json
152 class(case_t), intent(inout), target :: case
153 end subroutine simulation_component_factory
154 end interface
155
156 interface
157
160 module subroutine simulation_component_allocator(object, type_name)
161 class(simulation_component_t), allocatable, intent(inout) :: object
162 character(len=*), intent(in):: type_name
163 end subroutine simulation_component_allocator
164 end interface
165
166 !
167 ! Machinery for injecting user-defined types
168 !
169
173 abstract interface
174 subroutine simulation_component_allocate(obj)
175 import simulation_component_t
176 class(simulation_component_t), allocatable, intent(inout) :: obj
177 end subroutine simulation_component_allocate
178 end interface
179
180 interface
181
182 module subroutine register_simulation_component(type_name, allocator)
183 character(len=*), intent(in) :: type_name
184 procedure(simulation_component_allocate), pointer, intent(in) :: &
185 allocator
186 end subroutine register_simulation_component
187 end interface
188
189 ! A name-allocator pair for user-defined types. A helper type to define a
190 ! registry of custom allocators.
191 type allocator_entry
192 character(len=20) :: type_name
193 procedure(simulation_component_allocate), pointer, nopass :: allocator
194 end type allocator_entry
195
197 type(allocator_entry), allocatable :: simcomp_registry(:)
198
200 integer :: simcomp_registry_size = 0
201
202 public :: simulation_component_factory, simulation_component_allocator, &
203 register_simulation_component, simulation_component_allocate
204
205
206contains
208 subroutine simulation_component_init_base(this, json, case)
209 class(simulation_component_t), intent(inout) :: this
210 type(json_file), intent(inout) :: json
211 class(case_t), intent(inout), target :: case
212 character(len=:), allocatable :: preprocess_control, compute_control, &
213 output_control
214 real(kind=rp) :: preprocess_value, compute_value, output_value
215 integer :: order
216
217 call this%parse_json(json, case%params, preprocess_control, &
218 preprocess_value, compute_control, compute_value, output_control, &
219 output_value)
220
221 call json_get_or_default(json, "order", order, -1)
222
223 call this%init_base_from_components(case, order, &
224 preprocess_control, preprocess_value, compute_control, compute_value, &
225 output_control, output_value)
226
227 end subroutine simulation_component_init_base
228
239 subroutine simulation_component_init_base_from_controllers_properties(this, &
240 case, order, preprocess_control, preprocess_value, compute_control, &
241 compute_value, output_control, output_value)
242 class(simulation_component_t), intent(inout) :: this
243 class(case_t), intent(inout), target :: case
244 integer :: order
245 character(len=*), intent(in) :: preprocess_control
246 real(kind=rp), intent(in) :: preprocess_value
247 character(len=*), intent(in) :: compute_control
248 real(kind=rp), intent(in) :: compute_value
249 character(len=*), intent(in) :: output_control
250 real(kind=rp), intent(in) :: output_value
251
252 this%case => case
253 this%order = order
254
255 call this%preprocess_controller%init(case%time%start_time, &
256 case%time%end_time, preprocess_control, preprocess_value)
257 call this%compute_controller%init(case%time%start_time, case%time%end_time,&
258 compute_control, compute_value)
259 call this%output_controller%init(case%time%start_time, case%time%end_time, &
260 output_control, output_value)
261
262 end subroutine simulation_component_init_base_from_controllers_properties
263
270 subroutine simulation_component_init_base_from_controllers(this, case, order,&
271 preprocess_controller, compute_controller, output_controller)
272 class(simulation_component_t), intent(inout) :: this
273 class(case_t), intent(inout), target :: case
274 integer :: order
275 type(time_based_controller_t), intent(in) :: preprocess_controller
276 type(time_based_controller_t), intent(in) :: compute_controller
277 type(time_based_controller_t), intent(in) :: output_controller
278
279 this%case => case
280 this%order = order
281 this%preprocess_controller = preprocess_controller
282 this%compute_controller = compute_controller
283 this%output_controller = output_controller
284 end subroutine simulation_component_init_base_from_controllers
285
295 subroutine simulation_component_parse_json(this, json, case_params, &
296 preprocess_control, preprocess_value, compute_control, compute_value, &
297 output_control, output_value)
298 class(simulation_component_t), intent(inout) :: this
299 type(json_file), intent(inout) :: json
300 type(json_file), intent(inout) :: case_params
301 character(len=:), allocatable, intent(inout) :: preprocess_control
302 real(kind=rp), intent(out) :: preprocess_value
303 character(len=:), allocatable, intent(inout) :: compute_control
304 real(kind=rp), intent(out) :: compute_value
305 character(len=:), allocatable, intent(inout) :: output_control
306 real(kind=rp), intent(out) :: output_value
307 integer :: preprocess_value_int, compute_value_int, output_value_int
308 character(len=:), allocatable :: json_path
309 type(json_file) :: json_object
310
311 !
312 ! Preprocess
313 !
314
315 ! Get the preprocess control, defaulting to tsteps, pin to fluid if
316 ! requested
317 call json_get_or_default(json, "preprocess_control", preprocess_control, &
318 "tsteps")
319
320 json_path = "preprocess_value"
321 json_object = json
322 if (preprocess_control .eq. "fluid_output") then
323 call json_get(case_params, 'case.fluid.output_control', &
324 preprocess_control)
325 json_path = "case.fluid.output_value"
326 json_object = case_params
327 end if
328
329 ! Read preprocess value based on control type
330 if ((preprocess_control .eq. "tsteps") .or. &
331 (preprocess_control .eq. "nsamples")) then
332 ! Read it is an interger, and convert to real
333 call json_get_or_lookup_or_default(json_object, json_path, &
334 preprocess_value_int, 1)
335 preprocess_value = real(preprocess_value_int, kind=rp)
336 else if (preprocess_control .eq. "simulationtime") then
337 ! Read as real
338 call json_get_or_lookup_or_default(json_object, json_path, &
339 preprocess_value, 1.0_rp)
340 else if (preprocess_control .eq. "never") then
341 ! Dummy value
342 preprocess_value = 0.0_rp
343 end if
344
345 !
346 ! Compute
347 !
348
349 ! Get the compute control, defaulting to tsteps, pin to fluid if
350 ! requested
351 call json_get_or_default(json, "compute_control", compute_control, &
352 "tsteps")
353
354 json_path = "compute_value"
355 json_object = json
356 if (compute_control .eq. "fluid_output") then
357 call json_get(case_params, 'case.fluid.output_control', &
358 compute_control)
359 json_path = "case.fluid.output_value"
360 json_object = case_params
361 end if
362
363 ! Read compute value based on control type
364 if ((compute_control .eq. "tsteps") .or. &
365 (compute_control .eq. "nsamples")) then
366 ! Read it is an interger, and convert to real
367 call json_get_or_lookup_or_default(json_object, json_path, &
368 compute_value_int, 1)
369 compute_value = real(compute_value_int, kind=rp)
370 else if (compute_control .eq. "simulationtime") then
371 ! Read as real
372 call json_get_or_lookup_or_default(json_object, json_path, &
373 compute_value, 1.0_rp)
374 compute_value_int = int(compute_value)
375 else if (compute_control .eq. "never") then
376 ! Dummy value
377 compute_value = 0.0_rp
378 compute_value_int = 0
379 end if
380
381 !
382 ! Output
383 !
384
385 ! We default to output whenever we execute, pin to fluid if requested
386 call json_get_or_default(json, "output_control", output_control, &
387 compute_control)
388
389 json_path = "output_value"
390 json_object = json
391 if (output_control .eq. "global") then
392 call json_get(case_params, 'case.fluid.output_control', &
393 output_control)
394 json_path = "case.fluid.output_value"
395 json_object = case_params
396 end if
397
398
399 ! Read output value based on control type. We default to compute_value
400 if ((output_control .eq. "tsteps") .or. &
401 (output_control .eq. "nsamples")) then
402 ! Read it is an interger, and convert to real
403 call json_get_or_lookup_or_default(json_object, json_path, &
404 output_value_int, compute_value_int)
405 output_value = real(output_value_int, kind=rp)
406 else if (output_control .eq. "simulationtime") then
407 ! Read as real
408 call json_get_or_lookup_or_default(json_object, json_path, &
409 output_value, compute_value)
410 else if (output_control .eq. "never") then
411 ! Dummy value
412 output_value = 0.0_rp
413 end if
414
415 deallocate(json_path)
416 end subroutine simulation_component_parse_json
417
419 subroutine simulation_component_free_base(this)
420 class(simulation_component_t), intent(inout) :: this
421
422 nullify(this%case)
423
424 if (allocated(this%name)) then
425 deallocate(this%name)
426 end if
427
428 call this%preprocess_controller%free()
429 call this%compute_controller%free()
430 call this%output_controller%free()
431 end subroutine simulation_component_free_base
432
436 subroutine simulation_component_preprocess_wrapper(this, time)
437 class(simulation_component_t), intent(inout) :: this
438 type(time_state_t), intent(in) :: time
439
440 if (this%preprocess_controller%check(time)) then
441 call this%preprocess_(time)
442 call this%preprocess_controller%register_execution()
443 end if
444 end subroutine simulation_component_preprocess_wrapper
445
449 subroutine simulation_component_compute_wrapper(this, time)
450 class(simulation_component_t), intent(inout) :: this
451 type(time_state_t), intent(in) :: time
452
453 if (this%compute_controller%check(time)) then
454 call this%compute_(time)
455 call this%compute_controller%register_execution()
456 end if
457 end subroutine simulation_component_compute_wrapper
458
461 subroutine simulation_component_restart_wrapper(this, time)
462 class(simulation_component_t), intent(inout) :: this
463 type(time_state_t), intent(in) :: time
464
465 call this%compute_controller%set_counter(time)
466 call this%output_controller%set_counter(time)
467 call this%restart_(time)
468
469 end subroutine simulation_component_restart_wrapper
470
473 subroutine restart_(this, time)
474 class(simulation_component_t), intent(inout) :: this
475 type(time_state_t), intent(in) :: time
476
477 ! Do nothing
478 end subroutine restart_
479
482 subroutine preprocess_(this, time)
483 class(simulation_component_t), intent(inout) :: this
484 type(time_state_t), intent(in) :: time
485
486 ! Do nothing
487 end subroutine preprocess_
488
491 subroutine compute_(this, time)
492 class(simulation_component_t), intent(inout) :: this
493 type(time_state_t), intent(in) :: time
494
495 ! Do nothing
496 end subroutine compute_
497
498 ! ========================================================================== !
499 ! Simulation component wrapper type methods
500
502 subroutine simulation_component_wrapper_init(this, json, case)
503 class(simulation_component_wrapper_t), intent(inout) :: this
504 type(json_file), intent(inout) :: json
505 class(case_t), intent(inout), target :: case
506
507 call this%free()
508 call simulation_component_factory(this%simcomp, json, case)
509
510 end subroutine simulation_component_wrapper_init
511
513 subroutine simulation_component_wrapper_free(this)
514 class(simulation_component_wrapper_t), intent(inout) :: this
515
516 if (allocated(this%simcomp)) then
517 call this%simcomp%free()
518 deallocate(this%simcomp)
519 end if
520
521 end subroutine simulation_component_wrapper_free
522
527 subroutine simulation_component_wrapper_move_from(this, other)
528 class(simulation_component_wrapper_t), intent(inout) :: this
529 class(simulation_component_wrapper_t), intent(inout) :: other
530
531 ! Move the pointer
532 call move_alloc(other%simcomp, this%simcomp)
533
534 end subroutine simulation_component_wrapper_move_from
535
538 function simulation_component_wrapper_is_allocated(this) result(is_alloc)
539 class(simulation_component_wrapper_t), intent(in) :: this
540 logical :: is_alloc
541 is_alloc = allocated(this%simcomp)
542 end function simulation_component_wrapper_is_allocated
543
544end 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 simulation_component_wrapper_free(this)
Destructor. Just deallocates the pointer.
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_wrapper_init(this, json, case)
Constructor. Initializes the object.
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_wrapper_move_from(this, other)
Move assignment operator for the wrapper, needed for storing simcomps in lists and arrays.
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...
logical function simulation_component_wrapper_is_allocated(this)
Return allocation status.
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.