36 use json_module,
only : json_file
47 use space,
only :
operator(.ne.)
55 use mpi_f08,
only : mpi_allreduce, mpi_integer, mpi_sum
64 type(
coef_t),
pointer :: coef => null()
68 integer,
allocatable :: zone_indices(:)
70 character(len=:),
allocatable :: field_name
72 character(len=16),
allocatable :: operations(:)
74 logical :: compute_integral = .false.
76 logical :: compute_average = .false.
78 logical :: compute_min = .false.
80 logical :: compute_max = .false.
82 logical :: log = .true.
84 logical :: csv_output_enabled = .false.
94 real(kind=
rp) :: integral = 0.0_rp
96 real(kind=
rp) :: average = 0.0_rp
98 real(kind=
rp) :: minimum = huge(0.0_rp)
100 real(kind=
rp) :: maximum = -huge(0.0_rp)
105 generic :: init_from_components => &
106 init_from_controllers, init_from_controllers_properties
108 procedure, pass(this) :: init_from_controllers => &
111 procedure, pass(this) :: init_from_controllers_properties => &
114 procedure,
private, pass(this) :: init_common => &
129 type(json_file),
intent(inout) :: json
130 class(
case_t),
intent(inout),
target :: case
131 character(len=:),
allocatable :: name
132 integer,
allocatable :: zone_indices(:)
133 character(len=:),
allocatable :: field_name
134 character(len=16),
allocatable :: operations(:)
136 character(len=:),
allocatable :: output_filename
142 call this%init_base(json,
case)
144 call json_get(json,
"zone_indices", zone_indices)
145 call json_get(json,
"field_name", field_name)
146 call json_get(json,
"operations", operations)
148 if (json%valid_path(
"output_filename"))
then
149 call json_get(json,
"output_filename", output_filename)
150 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
151 operations, log, output_filename)
153 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
167 field_name, operations, log, output_filename)
169 character(len=*),
intent(in) :: name
170 type(
coef_t),
intent(inout),
target :: coef
171 integer,
intent(in) :: zone_indices(:)
172 character(len=*),
intent(in) :: field_name
173 character(len=*),
intent(in) :: operations(:)
174 logical,
intent(in) :: log
175 character(len=*),
intent(in),
optional :: output_filename
176 character(len=:),
allocatable :: csv_header
177 character(len=LOG_SIZE) :: log_buf
179 integer :: n_pts, glb_n_pts, ierr
183 this%compute_integral = .false.
184 this%compute_average = .false.
185 this%compute_min = .false.
186 this%compute_max = .false.
187 this%csv_output_enabled = .false.
188 this%integral = 0.0_rp
189 this%average = 0.0_rp
190 this%minimum = huge(0.0_rp)
191 this%maximum = -huge(0.0_rp)
196 if (
size(zone_indices) .eq. 0)
then
197 call neko_error(
"boundary_operation requires at least one zone index")
200 if (
size(operations) .eq. 0)
then
201 call neko_error(
"boundary_operation requires at least one operation")
204 allocate(this%zone_indices(
size(zone_indices)))
205 this%zone_indices = zone_indices
206 this%field_name = field_name
207 allocate(
character(len=16) :: this%operations(size(operations)))
208 this%operations = operations
210 do i = 1,
size(this%operations)
211 select case (trim(this%operations(i)))
213 this%compute_integral = .true.
215 this%compute_average = .true.
217 this%compute_min = .true.
219 this%compute_max = .true.
221 call neko_error(
"boundary_operation supports only operations = " // &
222 "[integral, average, min, max]")
226 call this%bc%init_from_components(this%coef, 0.0_rp)
227 this%bc%zone_indices = this%zone_indices
228 do i = 1,
size(this%zone_indices)
229 call this%bc%mark_zone(this%bc%msh%labeled_zones(this%zone_indices(i)))
231 call this%bc%finalize()
233 n_pts = this%bc%facet_node_msk(0)
234 call mpi_allreduce(n_pts, glb_n_pts, 1, mpi_integer, mpi_sum,
neko_comm, &
236 if (n_pts .gt. 0)
then
237 call this%areas%init(n_pts)
238 call this%surface_values%init(n_pts)
240 this%bc%facet_node_msk, this%bc%facet, this%coef%Xh%lx, &
241 this%coef%Xh%ly, this%coef%Xh%lz, n_pts)
244 if (
present(output_filename))
then
245 csv_header =
"tstep,time"
246 do i = 1,
size(this%operations)
247 csv_header = trim(csv_header) //
"," // trim(this%operations(i))
249 call this%csv_output%init(trim(output_filename), header = &
250 trim(csv_header), overwrite = .true.)
251 call this%csv_row%init(2 +
size(this%operations))
252 this%csv_output_enabled = .true.
255 call neko_log%section(
"Boundary operation")
256 write(log_buf,
'(A,A)')
"Name: ", trim(this%name)
258 write(log_buf,
'(A,A)')
"Field: ", trim(this%field_name)
260 call neko_log%message(
"Operations:")
261 do i = 1,
size(this%operations)
262 write(log_buf,
'(A,A)')
" ", trim(this%operations(i))
265 write(log_buf,
'(A,*(I0,:,", "))')
"Zone indices: ", this%zone_indices
267 write(log_buf,
'(A,I0)')
"Marked boundary quadrature points: ", glb_n_pts
285 preprocess_controller, compute_controller, output_controller, &
286 zone_indices, field_name, operations, log, output_filename)
288 character(len=*),
intent(in) :: name
289 class(
case_t),
intent(inout),
target :: case
290 integer,
intent(in) :: order
294 integer,
intent(in) :: zone_indices(:)
295 character(len=*),
intent(in) :: field_name
296 character(len=*),
intent(in) :: operations(:)
297 logical,
intent(in),
optional :: log
298 character(len=*),
intent(in),
optional :: output_filename
299 logical :: log_enabled
304 if (
present(log)) log_enabled = log
306 call this%init_base_from_components(
case, order, preprocess_controller, &
309 if (
present(output_filename))
then
310 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
311 operations, log_enabled, output_filename)
313 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
314 operations, log_enabled)
334 case, order, preprocess_control, preprocess_value, compute_control, &
335 compute_value, output_control, output_value, zone_indices, field_name, &
336 operations, log, output_filename)
338 character(len=*),
intent(in) :: name
339 class(
case_t),
intent(inout),
target :: case
340 integer,
intent(in) :: order
341 character(len=*),
intent(in) :: preprocess_control
342 real(kind=
dp),
intent(in) :: preprocess_value
343 character(len=*),
intent(in) :: compute_control
344 real(kind=
dp),
intent(in) :: compute_value
345 character(len=*),
intent(in) :: output_control
346 real(kind=
dp),
intent(in) :: output_value
347 integer,
intent(in) :: zone_indices(:)
348 character(len=*),
intent(in) :: field_name
349 character(len=*),
intent(in) :: operations(:)
350 logical,
intent(in),
optional :: log
351 character(len=*),
intent(in),
optional :: output_filename
352 logical :: log_enabled
357 if (
present(log)) log_enabled = log
359 call this%init_base_from_components(
case, order, preprocess_control, &
360 preprocess_value, compute_control, compute_value, output_control, &
363 if (
present(output_filename))
then
364 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
365 operations, log_enabled, output_filename)
367 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
368 operations, log_enabled)
377 call this%csv_output%free()
378 call this%csv_row%free()
379 call this%areas%free()
380 call this%surface_values%free()
381 if (
allocated(this%zone_indices))
deallocate(this%zone_indices)
382 if (
allocated(this%field_name))
deallocate(this%field_name)
383 if (
allocated(this%operations))
deallocate(this%operations)
388 call this%free_base()
398 real(kind=
rp) :: area
399 character(len=18) :: value_buf
400 character(len=12) :: step_str
401 character(len=:),
allocatable :: section_title, header_line, value_line
402 integer :: output_col
404 n_pts = this%bc%facet_node_msk(0)
406 this%integral = 0.0_rp
407 this%average = 0.0_rp
408 this%minimum = huge(0.0_rp)
409 this%maximum = -huge(0.0_rp)
413 this%field%x, this%bc%facet_node_msk, this%field%size(), n_pts)
415 if (this%compute_integral .or. this%compute_average)
then
416 this%integral =
vector_glsc2(this%surface_values, this%areas, n_pts)
419 if (this%compute_average)
then
421 if (area .gt. 0.0_rp)
then
422 this%average = this%integral / area
424 this%average = 0.0_rp
428 if (this%compute_min)
then
432 if (this%compute_max)
then
437 section_title = trim(this%name)
438 call neko_log%section(section_title)
440 header_line = repeat(
' ', 12) //
' |'
441 write(step_str,
'(I12)') time%tstep
442 step_str = adjustl(step_str)
443 value_line = step_str //
' |'
445 do i = 1,
size(this%operations)
446 select case (trim(this%operations(i)))
448 header_line = header_line //
left_pad(
'Integral:', 18)
449 write(value_buf,
'(ES18.9)') this%integral
450 value_line = value_line // value_buf
452 header_line = header_line //
left_pad(
'Average:', 18)
453 write(value_buf,
'(ES18.9)') this%average
454 value_line = value_line // value_buf
456 header_line = header_line //
left_pad(
'Min:', 18)
457 write(value_buf,
'(ES18.9)') this%minimum
458 value_line = value_line // value_buf
460 header_line = header_line //
left_pad(
'Max:', 18)
461 write(value_buf,
'(ES18.9)') this%maximum
462 value_line = value_line // value_buf
471 if (this%csv_output_enabled)
then
472 if (this%output_controller%check(time))
then
473 this%csv_row%x(1) =
real(time%tstep,
rp)
474 this%csv_row%x(2) = time%t
476 do i = 1,
size(this%operations)
477 select case (trim(this%operations(i)))
479 this%csv_row%x(output_col) = this%integral
481 this%csv_row%x(output_col) = this%average
483 this%csv_row%x(output_col) = this%minimum
485 this%csv_row%x(output_col) = this%maximum
487 output_col = output_col + 1
489 call this%csv_output%write(this%csv_row)
490 call this%output_controller%register_execution(time)
499 character(len=*),
intent(in) :: text
500 integer,
intent(in) :: width
501 character(len=:),
allocatable :: padded
504 pad_width =
max(0, width - len_trim(text))
505 padded = repeat(
' ', pad_width) // trim(text)
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 boundary condition.
Implements boundary_operation_t.
subroutine boundary_operation_free(this)
Free all resources owned by the component.
subroutine boundary_operation_init_from_controllers_properties(this, name, case, order, preprocess_control, preprocess_value, compute_control, compute_value, output_control, output_value, zone_indices, field_name, operations, log, output_filename)
Construct from time-based controller properties.
subroutine boundary_operation_init_from_controllers(this, name, case, order, preprocess_controller, compute_controller, output_controller, zone_indices, field_name, operations, log, output_filename)
Construct from explicit time-based controllers.
subroutine boundary_operation_init_common(this, name, coef, zone_indices, field_name, operations, log, output_filename)
Common constructor shared by all public constructors.
pure character(len=:) function, allocatable left_pad(text, width)
Left-pad a string to a fixed width.
subroutine boundary_operation_init_from_json(this, json, case)
Construct from JSON.
subroutine boundary_operation_compute(this, time)
Compute and optionally output the requested boundary operations.
Defines a simulation case.
type(mpi_comm), public neko_comm
MPI communicator.
Module for file I/O operations.
Utilities for retrieving parameters from the case files.
type(log_t), public neko_log
Global log stream.
integer, parameter, public log_size
Defines a Neumann boundary condition.
integer, parameter, public dp
integer, parameter, public rp
Global precision used in computations.
Implements output_controller_t
Defines a registry for storing solution fields.
type(registry_t), target, public neko_registry
Global field 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.
Contains the time_based_controller_t type.
Module with things related to the simulation time.
subroutine, public vector_masked_gather_copy_0(a, b, mask, n, n_mask)
Gather a vector to reduced contigous array .
real(kind=rp) function, public vector_glmin(a, n)
Global minimum of all elements in a vector .
subroutine, public vector_face_masked_gather_copy_0(a, b, mask, facet, lx, ly, lz, n_mask)
Gather a face-local SEM field to a reduced contiguous vector.
real(kind=rp) function, public vector_glsum(a, n)
real(kind=rp) function, public vector_glsc2(a, b, n)
real(kind=rp) function, public vector_glmax(a, n)
Global maximum of all elements in a vector .
A simulation component for boundary reductions on labelled zones.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
A wrapper around a polymorphic generic_file_t that handles its init. This is essentially a factory fo...
A Neumann boundary condition. Sets the flux of the field to the chosen values.
Base abstract class for simulation components.
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.