45 use mpi_f08,
only : mpi_allreduce, mpi_in_place, mpi_sum, mpi_integer
48 use json_module,
only : json_file
64 use,
intrinsic :: iso_c_binding
79 character(len=80),
allocatable :: field_names(:)
81 integer :: n_fields = 0
99 type(
mesh_t),
pointer :: msh => null()
101 logical :: internal_mesh = .false.
117 logical :: internal_space = .false.
121 logical :: checked = .false.
127 procedure, pass(this) :: init_common => &
134 generic :: init_from_components => &
135 init_from_controllers, init_from_controllers_properties
137 procedure, pass(this) :: init_from_controllers => &
141 procedure, pass(this) :: init_from_controllers_properties => &
169 if (this%internal_mesh)
then
172 is_valid = (
associated(this%point_zone) .and. &
173 this%point_zone%mask%is_set())
174 if (.not. is_valid)
call neko_error(
"The point zone is missing " // &
175 " or has not been set up properly")
177 n = this%point_zone%size
178 call mpi_allreduce(mpi_in_place, n, 1, mpi_integer, mpi_sum, &
182 if (.not. is_valid)
call neko_warning(
"Point zone is empty")
187 if (this%internal_space)
then
188 is_valid = this%lx .gt. 0
189 if (.not. is_valid)
call neko_error(
"lx has not been set up properly")
191 is_valid =
allocated(this%interpolator%Xh_to_Yh)
192 if (.not. is_valid)
call neko_error(
"The interpolator has not been " // &
193 "initialized properly")
197 is_valid = (this%dof%global_size() .gt. 0 .and.
allocated(this%dof%x))
198 if (.not. is_valid)
call neko_error(
"Dofmap not initialized or empty")
203 is_valid = (this%fields%size() .gt. 0 .and.
allocated(this%fields%items))
204 if (.not. is_valid)
call neko_error(
"Internal field_list not initialized")
207 is_valid =
associated(this%compute_impl)
208 if (.not. is_valid)
call neko_error(
"compute_impl not associated")
210 this%checked = .true.
220 if (.not. this%checked)
call this%check()
221 call this%compute_impl(time)
230 call neko_error(
"field_subsampler must be initialized first!")
237 type(json_file),
intent(inout) :: json
238 class(
case_t),
intent(inout),
target :: case
240 character(len=:),
allocatable :: name
241 character(len=80),
allocatable :: which_fields(:)
244 logical :: do_space_interp, do_point_zone_masking
246 character(len=:),
allocatable :: pz_name
250 call this%init_base(json,
case)
253 call json_get(json,
"source_fields", which_fields)
258 do_space_interp = json%valid_path(
'polynomial_order')
259 if (do_space_interp)
then
261 case%fluid%Xh%lx - 1)
268 do_point_zone_masking = json%valid_path(
'point_zone')
269 if (do_point_zone_masking)
then
270 call json_get(json,
"point_zone", pz_name)
276 if (do_space_interp .and. do_point_zone_masking)
then
279 else if (do_space_interp .and. .not. do_point_zone_masking)
then
282 else if (.not. do_space_interp .and. do_point_zone_masking)
then
286 call neko_error(
"Invalid configuration: please pass either " // &
287 "a point zone or a valid polynomial order.")
295 character(len=1024) :: new_field_names(this%n_fields)
298 do i = 1, this%n_fields
299 new_field_names(i) = trim(this%fields%name(i))
303 call json%add(
"fields", new_field_names)
306 if (json%valid_path(
"point_zone"))
call json%remove(
"point_zone")
311 if (.not. json%valid_path(
"output_filename"))
then
312 call json%add(
"output_filename", this%name)
315 call this%writer%init(json,
case)
318 if (
associated(this%point_zone))
call json%add(
"point_zone", &
319 trim(this%point_zone%name))
333 character(len=*),
intent(in) :: name
334 character(len=*),
intent(in) :: which_fields(:)
335 integer,
intent(in),
optional :: lx
336 class(point_zone_t),
pointer,
intent(in),
optional :: point_zone
339 this%field_names = which_fields
340 this%n_fields =
size(which_fields)
345 if (.not.
present(lx) .and. .not.
present(
point_zone))
then
346 call neko_error(
"Invalid configuration: please pass either " // &
347 "a point zone or a polynomial order.")
352 if (
present(lx))
then
353 if (lx .eq. this%case%fluid%Xh%lx .and. .not.
present(
point_zone))
then
354 call neko_error(
"Invalid configuration: no change in " // &
355 "polynomial order and no point zone provided.")
362 this%internal_space = .false.
363 if (
present(lx))
then
366 if (this%lx .eq. this%case%fluid%Xh%lx)
then
367 call neko_warning(
"No change in polynomial order " // &
368 "Space-to-space interpolation disabled.")
374 call this%Xh%init(gll, this%lx, this%lx, this%lx)
375 this%internal_space = .true.
377 call this%interpolator%init(this%Xh, this%case%fluid%Xh)
384 if (.not. this%internal_space)
then
385 this%lx = this%case%fluid%Xh%lx
386 this%Xh => this%case%fluid%Xh
395 if (.not.
point_zone%full_elements)
call neko_error(
"full_elements" // &
396 "must be enabled when sampling a point zone")
400 call this%case%fluid%msh%subset_by_mask(this%msh, &
402 this%case%fluid%Xh%lx, &
403 this%case%fluid%Xh%ly, &
404 this%case%fluid%Xh%lz)
405 this%internal_mesh = .true.
408 this%msh => this%case%fluid%msh
409 this%internal_mesh = .false.
413 call this%dof%init(this%msh, this%Xh)
420 character(len=2048) :: field_name
422 call this%fields%init(this%n_fields)
423 call this%source_fields%init(this%n_fields)
425 do i = 1, this%n_fields
428 field_name = this%name //
"/" // this%field_names(i)
429 call neko_registry%add_field(this%dof, field_name)
430 this%fields%items(i)%ptr => neko_registry%get_field(trim(field_name))
433 this%source_fields%items(i)%ptr => &
434 neko_registry%get_field(this%field_names(i))
442 if (this%internal_space .and. .not. this%internal_mesh)
then
444 else if (.not. this%internal_space .and. this%internal_mesh)
then
446 else if (this%internal_space .and. this%internal_mesh)
then
449 call neko_error(
"Invalid configuration")
461 if (
allocated(this%field_names))
deallocate(this%field_names)
462 nullify(this%point_zone)
464 if (this%internal_space)
then
467 this%internal_space = .false.
470 if (this%internal_mesh)
then
473 this%internal_mesh = .false.
477 call this%interpolator%free()
482 call this%source_fields%free()
483 call this%fields%free()
484 call this%writer%free()
486 call this%free_base()
496 type(time_state_t),
intent(in) :: time
498 integer :: i, n, n_mask
500 n = this%source_fields%items(1)%ptr%dof%size()
501 n_mask = this%point_zone%mask%size()
503 do i = 1, this%n_fields
505 if (neko_bcknd_device .eq. 1)
then
506 call device_masked_gather_copy_aligned(this%fields%x_d(i), &
507 this%source_fields%x_d(i), &
508 this%point_zone%mask%get_d(), n, n_mask)
510 call masked_gather_copy(this%fields%x(i), &
511 this%source_fields%x(i), &
512 this%point_zone%mask%get(), n, n_mask)
523 type(time_state_t),
intent(in) :: time
527 do i = 1, this%n_fields
528 call this%interpolator%map(this%fields%x(i), &
529 this%source_fields%x(i), &
530 this%msh%nelv, this%Xh)
541 type(time_state_t),
intent(in) :: time
543 type(field_t),
pointer :: wk
544 integer :: i, n, n_mask, tmp_index
546 n = this%source_fields%items(1)%ptr%dof%size()
547 n_mask = this%point_zone%mask%size()
549 call neko_scratch_registry%request_field(wk, tmp_index, .false.)
551 do i = 1, this%n_fields
555 if (neko_bcknd_device .eq. 1)
then
556 call device_masked_gather_copy_aligned(wk%x_d, &
557 this%source_fields%x_d(i), &
558 this%point_zone%mask%get_d(), n, n_mask)
560 call masked_gather_copy(wk%x, &
561 this%source_fields%x(i), &
562 this%point_zone%mask%get(), n, n_mask)
566 call this%interpolator%map(this%fields%x(i), wk%x, &
567 this%msh%nelv, this%Xh)
571 call neko_scratch_registry%relinquish_field(tmp_index)
587 preprocess_controller, compute_controller, output_controller, &
588 which_fields, lx, point_zone)
590 character(len=*),
intent(in) :: name
591 class(case_t),
intent(inout),
target :: case
593 type(time_based_controller_t),
intent(in) :: preprocess_controller
594 type(time_based_controller_t),
intent(in) :: compute_controller
595 type(time_based_controller_t),
intent(in) :: output_controller
596 character(len=*),
intent(in) :: which_fields(:)
597 integer,
intent(in) :: lx
598 class(point_zone_t),
intent(in),
pointer,
optional :: point_zone
600 call this%init_base_from_components(
case, order, preprocess_controller, &
603 call this%init_common(name, which_fields, lx = lx, &
624 case, order, preprocess_control, preprocess_value, compute_control, &
625 compute_value, output_control, output_value, which_fields, lx, &
628 character(len=*),
intent(in) :: name
629 class(case_t),
intent(inout),
target :: case
631 character(len=*),
intent(in) :: preprocess_control
632 real(kind=rp),
intent(in) :: preprocess_value
633 character(len=*),
intent(in) :: compute_control
634 real(kind=rp),
intent(in) :: compute_value
635 character(len=*),
intent(in) :: output_control
636 real(kind=rp),
intent(in) :: output_value
637 character(len=*),
intent(in) :: which_fields(:)
638 integer,
intent(in),
optional :: lx
639 class(point_zone_t),
pointer,
intent(in),
optional :: point_zone
641 call this%init_base_from_components(
case, order, preprocess_control, &
642 preprocess_value, compute_control, compute_value, output_control, &
645 call this%init_common(name, which_fields, lx = lx, &
Copy data between host and device (or device and device)
Abstract interface for the compute() subroutine, which will be assigned at runtime depending on the s...
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.
Defines a simulation case.
integer, public pe_rank
MPI rank.
type(mpi_comm), public neko_comm
MPI communicator.
subroutine, public device_masked_gather_copy_aligned(a_d, b_d, mask_d, n, n_mask, strm)
Gather a masked vector .
Device abstraction, common interface for various accelerators.
integer, parameter, public host_to_device
integer, parameter, public device_to_host
Defines a mapping of the degrees of freedom.
Implements type field_subsampler_t.
subroutine dummy_compute(this, time)
Dummy subroutine assigned by default to compute_impl.
subroutine field_subsampler_compute_pz(this, time)
Subsample the fields based only on a point zone, no space-to-space interpolation.
subroutine field_subsampler_compute_pz_xh(this, time)
Subsample the fields based a point zone, and with space-to-space interpolation enabled.
subroutine field_subsampler_init_from_controllers(this, name, case, order, preprocess_controller, compute_controller, output_controller, which_fields, lx, point_zone)
Constructor from components, passing controllers.
subroutine field_subsampler_compute_xh(this, time)
Subsample fields wihout any point zone, only space-to-space interpolation is enabled.
subroutine field_subsampler_init_common(this, name, which_fields, lx, point_zone)
Actual constructor.
subroutine compute_wrapper(this, time)
Wrapper for the run-time-assigned subroutine compute_impl, which will be assigned at runtime to the c...
subroutine field_subsampler_init_json(this, json, case)
Constructor.
subroutine field_subsampler_free(this)
Destructor.
subroutine field_subsampler_init_from_controllers_properties(this, name, case, order, preprocess_control, preprocess_value, compute_control, compute_value, output_control, output_value, which_fields, lx, point_zone)
Constructor from components, passing properties to the time_based_controller` components in the base ...
subroutine field_subsampler_check(this)
Checks the validity of the setup before calling compute()
Implements the field_writer_t type.
Routines to interpolate between different spaces.
Utilities for retrieving parameters from the case files.
integer, parameter, public neko_log_debug
Debug log level.
type(log_t), public neko_log
Global log stream.
subroutine, public masked_gather_copy(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
real(kind=rp) function, public glsum(a, n)
Sum a vector of length n.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Implements output_controller_t
type(point_zone_registry_t), target, public neko_point_zone_registry
Global point_zone registry.
Defines a registry for storing solution fields.
type(registry_t), target, public neko_registry
Global field registry.
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.
Simulation components are objects that encapsulate functionality that can be fit to a particular comp...
subroutine compute_(this, time)
Dummy compute function.
Defines a function space.
integer, parameter, public gll
Contains the time_based_controller_t type.
Module with things related to the simulation time.
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
field_list_t, To be able to group fields together
Implements the field_subsampler_t simulation components, which allows for masking regions of the doma...
A simulation component that writes a 3d field to a file.
Interpolation between two space::space_t.
Base abstract type for point zones.
Base abstract class for simulation components.
The function space for the SEM solution fields.
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.