36 use json_module,
only : json_file
47 use space,
only :
operator(.ne.)
62 type(
coef_t),
pointer :: coef => null()
66 integer,
allocatable :: zone_indices(:)
68 character(len=:),
allocatable :: field_name
70 character(len=16),
allocatable :: operations(:)
72 logical :: compute_integral = .false.
74 logical :: compute_average = .false.
76 logical :: compute_min = .false.
78 logical :: compute_max = .false.
80 logical :: log = .true.
82 logical :: csv_output_enabled = .false.
92 real(kind=
rp) :: integral = 0.0_rp
94 real(kind=
rp) :: average = 0.0_rp
96 real(kind=
rp) :: minimum = huge(0.0_rp)
98 real(kind=
rp) :: maximum = -huge(0.0_rp)
103 generic :: init_from_components => &
104 init_from_controllers, init_from_controllers_properties
106 procedure, pass(this) :: init_from_controllers => &
109 procedure, pass(this) :: init_from_controllers_properties => &
112 procedure,
private, pass(this) :: init_common => &
127 type(json_file),
intent(inout) :: json
128 class(
case_t),
intent(inout),
target :: case
129 character(len=:),
allocatable :: name
130 integer,
allocatable :: zone_indices(:)
131 character(len=:),
allocatable :: field_name
132 character(len=16),
allocatable :: operations(:)
134 character(len=:),
allocatable :: output_filename
140 call this%init_base(json,
case)
142 call json_get(json,
"zone_indices", zone_indices)
143 call json_get(json,
"field_name", field_name)
144 call json_get(json,
"operations", operations)
146 if (json%valid_path(
"output_filename"))
then
147 call json_get(json,
"output_filename", output_filename)
148 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
149 operations, log, output_filename)
151 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
165 field_name, operations, log, output_filename)
167 character(len=*),
intent(in) :: name
168 type(
coef_t),
intent(inout),
target :: coef
169 integer,
intent(in) :: zone_indices(:)
170 character(len=*),
intent(in) :: field_name
171 character(len=*),
intent(in) :: operations(:)
172 logical,
intent(in) :: log
173 character(len=*),
intent(in),
optional :: output_filename
174 character(len=:),
allocatable :: csv_header
175 character(len=LOG_SIZE) :: log_buf
181 this%compute_integral = .false.
182 this%compute_average = .false.
183 this%compute_min = .false.
184 this%compute_max = .false.
185 this%csv_output_enabled = .false.
186 this%integral = 0.0_rp
187 this%average = 0.0_rp
188 this%minimum = huge(0.0_rp)
189 this%maximum = -huge(0.0_rp)
194 if (
size(zone_indices) .eq. 0)
then
195 call neko_error(
"boundary_operation requires at least one zone index")
198 if (
size(operations) .eq. 0)
then
199 call neko_error(
"boundary_operation requires at least one operation")
202 allocate(this%zone_indices(
size(zone_indices)))
203 this%zone_indices = zone_indices
204 this%field_name = field_name
205 allocate(
character(len=16) :: this%operations(size(operations)))
206 this%operations = operations
208 do i = 1,
size(this%operations)
209 select case (trim(this%operations(i)))
211 this%compute_integral = .true.
213 this%compute_average = .true.
215 this%compute_min = .true.
217 this%compute_max = .true.
219 call neko_error(
"boundary_operation supports only operations = " // &
220 "[integral, average, min, max]")
224 call this%bc%init_from_components(this%coef, 0.0_rp)
225 this%bc%zone_indices = this%zone_indices
226 do i = 1,
size(this%zone_indices)
227 call this%bc%mark_zone(this%bc%msh%labeled_zones(this%zone_indices(i)))
229 call this%bc%finalize()
231 n_pts = this%bc%msk(0)
232 if (n_pts .gt. 0)
then
233 call this%areas%init(n_pts)
234 call this%surface_values%init(n_pts)
236 this%bc%msk, this%bc%facet, this%coef%Xh%lx, this%coef%Xh%ly, &
237 this%coef%Xh%lz, n_pts)
240 if (
present(output_filename))
then
241 csv_header =
"tstep,time"
242 do i = 1,
size(this%operations)
243 csv_header = trim(csv_header) //
"," // trim(this%operations(i))
245 call this%csv_output%init(trim(output_filename), header = &
246 trim(csv_header), overwrite = .true.)
247 call this%csv_row%init(2 +
size(this%operations))
248 this%csv_output_enabled = .true.
251 call neko_log%section(
"Boundary operation")
252 write(log_buf,
'(A,A)')
"Name: ", trim(this%name)
254 write(log_buf,
'(A,A)')
"Field: ", trim(this%field_name)
256 call neko_log%message(
"Operations:")
257 do i = 1,
size(this%operations)
258 write(log_buf,
'(A,A)')
" ", trim(this%operations(i))
261 write(log_buf,
'(A,*(I0,:,", "))')
"Zone indices: ", this%zone_indices
263 write(log_buf,
'(A,I0)')
"Marked boundary quadrature points: ", &
282 preprocess_controller, compute_controller, output_controller, &
283 zone_indices, field_name, operations, log, output_filename)
285 character(len=*),
intent(in) :: name
286 class(
case_t),
intent(inout),
target :: case
287 integer,
intent(in) :: order
291 integer,
intent(in) :: zone_indices(:)
292 character(len=*),
intent(in) :: field_name
293 character(len=*),
intent(in) :: operations(:)
294 logical,
intent(in),
optional :: log
295 character(len=*),
intent(in),
optional :: output_filename
296 logical :: log_enabled
301 if (
present(log)) log_enabled = log
303 call this%init_base_from_components(
case, order, preprocess_controller, &
306 if (
present(output_filename))
then
307 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
308 operations, log_enabled, output_filename)
310 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
311 operations, log_enabled)
331 case, order, preprocess_control, preprocess_value, compute_control, &
332 compute_value, output_control, output_value, zone_indices, field_name, &
333 operations, log, output_filename)
335 character(len=*),
intent(in) :: name
336 class(
case_t),
intent(inout),
target :: case
337 integer,
intent(in) :: order
338 character(len=*),
intent(in) :: preprocess_control
339 real(kind=
rp),
intent(in) :: preprocess_value
340 character(len=*),
intent(in) :: compute_control
341 real(kind=
rp),
intent(in) :: compute_value
342 character(len=*),
intent(in) :: output_control
343 real(kind=
rp),
intent(in) :: output_value
344 integer,
intent(in) :: zone_indices(:)
345 character(len=*),
intent(in) :: field_name
346 character(len=*),
intent(in) :: operations(:)
347 logical,
intent(in),
optional :: log
348 character(len=*),
intent(in),
optional :: output_filename
349 logical :: log_enabled
354 if (
present(log)) log_enabled = log
356 call this%init_base_from_components(
case, order, preprocess_control, &
357 preprocess_value, compute_control, compute_value, output_control, &
360 if (
present(output_filename))
then
361 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
362 operations, log_enabled, output_filename)
364 call this%init_common(name,
case%fluid%c_Xh, zone_indices, field_name, &
365 operations, log_enabled)
374 call this%csv_output%free()
375 call this%csv_row%free()
376 call this%areas%free()
377 call this%surface_values%free()
378 if (
allocated(this%zone_indices))
deallocate(this%zone_indices)
379 if (
allocated(this%field_name))
deallocate(this%field_name)
380 if (
allocated(this%operations))
deallocate(this%operations)
385 call this%free_base()
395 real(kind=
rp) :: area
396 character(len=18) :: value_buf
397 character(len=12) :: step_str
398 character(len=:),
allocatable :: section_title, header_line, value_line
399 integer :: output_col
401 n_pts = this%bc%msk(0)
403 this%integral = 0.0_rp
404 this%average = 0.0_rp
405 this%minimum = huge(0.0_rp)
406 this%maximum = -huge(0.0_rp)
410 this%field%x, this%bc%msk, this%field%size(), n_pts)
412 if (this%compute_integral .or. this%compute_average)
then
413 this%integral =
vector_glsc2(this%surface_values, this%areas, n_pts)
416 if (this%compute_average)
then
418 if (area .gt. 0.0_rp)
then
419 this%average = this%integral / area
421 this%average = 0.0_rp
425 if (this%compute_min)
then
429 if (this%compute_max)
then
434 section_title = trim(this%name)
435 call neko_log%section(section_title)
437 header_line = repeat(
' ', 12) //
' |'
438 write(step_str,
'(I12)') time%tstep
439 step_str = adjustl(step_str)
440 value_line = step_str //
' |'
442 do i = 1,
size(this%operations)
443 select case (trim(this%operations(i)))
445 header_line = header_line //
left_pad(
'Integral:', 18)
446 write(value_buf,
'(ES18.9)') this%integral
447 value_line = value_line // value_buf
449 header_line = header_line //
left_pad(
'Average:', 18)
450 write(value_buf,
'(ES18.9)') this%average
451 value_line = value_line // value_buf
453 header_line = header_line //
left_pad(
'Min:', 18)
454 write(value_buf,
'(ES18.9)') this%minimum
455 value_line = value_line // value_buf
457 header_line = header_line //
left_pad(
'Max:', 18)
458 write(value_buf,
'(ES18.9)') this%maximum
459 value_line = value_line // value_buf
468 if (this%csv_output_enabled)
then
469 if (this%output_controller%check(time))
then
470 this%csv_row%x(1) =
real(time%tstep,
rp)
471 this%csv_row%x(2) = time%t
473 do i = 1,
size(this%operations)
474 select case (trim(this%operations(i)))
476 this%csv_row%x(output_col) = this%integral
478 this%csv_row%x(output_col) = this%average
480 this%csv_row%x(output_col) = this%minimum
482 this%csv_row%x(output_col) = this%maximum
484 output_col = output_col + 1
486 call this%csv_output%write(this%csv_row)
487 call this%output_controller%register_execution()
496 character(len=*),
intent(in) :: text
497 integer,
intent(in) :: width
498 character(len=:),
allocatable :: padded
501 pad_width =
max(0, width - len_trim(text))
502 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.
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 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.