Neko 1.99.7
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
wall_shear_stress_simcomp.f90
Go to the documentation of this file.
1! Copyright (c) 2026, 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!
35 use num_types, only : rp
36 use json_module, only : json_file
40 use time_state, only : time_state_t
41 use case, only : case_t
42 use field, only : field_t
43 use registry, only : neko_registry
45 use coefs, only : coef_t
46 use vector, only : vector_t
48 use operators, only : strain_rate
50 use math, only : vdot3, sqrt_inplace
53 use ale_manager, only : neko_ale
54 use logger, only : neko_log, log_size
56 implicit none
57 private
58
65 type(field_t), pointer :: u => null()
67 type(field_t), pointer :: v => null()
69 type(field_t), pointer :: w => null()
71 type(field_t), pointer :: p => null()
73 type(field_t), pointer :: mu => null()
75 type(field_t), pointer :: tau_x => null()
77 type(field_t), pointer :: tau_y => null()
79 type(field_t), pointer :: tau_z => null()
81 type(field_t), pointer :: tau_mag => null()
83 type(coef_t), pointer :: coef => null()
86 type(boundary_data_t) :: bdata
88 integer, allocatable :: zone_indices(:)
90 logical :: want_x = .true.
91 logical :: want_y = .true.
92 logical :: want_z = .true.
93 logical :: want_mag = .true.
95 logical :: mesh_has_changed = .false.
97 character(len=:), allocatable :: computed_field
98 contains
100 procedure, pass(this) :: init => wall_shear_stress_init_from_json
101 generic :: init_from_components => &
102 init_from_controllers, init_from_controllers_properties
103 procedure, pass(this) :: init_from_controllers => &
105 procedure, pass(this) :: init_from_controllers_properties => &
107 procedure, private, pass(this) :: init_common => &
110 procedure, pass(this) :: free => wall_shear_stress_free
112 procedure, pass(this) :: compute_ => wall_shear_stress_compute
113 end type wall_shear_stress_t
114
115contains
116
120 subroutine wall_shear_stress_init_from_json(this, json, case)
121 class(wall_shear_stress_t), intent(inout), target :: this
122 type(json_file), intent(inout) :: json
123 class(case_t), intent(inout), target :: case
124 character(len=:), allocatable :: name, computed_field, fluid_name
125 character(len=:), allocatable :: viscosity_field
126 integer, allocatable :: zone_indices(:)
127 character(len=NEKO_VARNAME_LEN), allocatable :: components(:)
128
129 call this%free()
130
131 call json_get_or_default(json, "name", name, "wall_shear_stress")
132 call json_get_or_default(json, "computed_field", computed_field, "tau")
133 call json_get_or_default(json, "fluid_name", fluid_name, "fluid")
134 call json_get_or_default(json, "viscosity_field", viscosity_field, &
135 trim(fluid_name) // "_mu_tot")
136 call json_get(json, "zone_indices", zone_indices)
137
138 ! Defaults to all four components.
139 if (json%valid_path("components")) then
140 call json_get(json, "components", components)
141 else
142 allocate(components(1))
143 components(1) = "all"
144 end if
145
146 call this%init_base(json, case)
147
148 call this%init_common(name, computed_field, viscosity_field, &
149 zone_indices, components, case%fluid%c_Xh)
150
152
160 subroutine wall_shear_stress_parse_components(components, &
161 want_x, want_y, want_z, want_mag)
162 character(len=*), intent(in) :: components(:)
163 logical, intent(out) :: want_x, want_y, want_z, want_mag
164 integer :: i
165 character(len=:), allocatable :: c
166
167 want_x = .false.
168 want_y = .false.
169 want_z = .false.
170 want_mag = .false.
171
172 if (size(components) .eq. 0) then
173 call neko_error("wall_shear_stress: 'components' must not be empty")
174 end if
175
176 do i = 1, size(components)
177 c = trim(components(i))
178 select case (c)
179 case ("all")
180 want_x = .true.
181 want_y = .true.
182 want_z = .true.
183 want_mag = .true.
184 case ("x")
185 want_x = .true.
186 case ("y")
187 want_y = .true.
188 case ("z")
189 want_z = .true.
190 case ("mag")
191 want_mag = .true.
192 case default
193 call neko_error("wall_shear_stress: unknown component '" // c // &
194 "'. Use x, y, z, mag, or all.")
195 end select
196 end do
197
198 if (.not. (want_x .or. want_y .or. want_z .or. want_mag)) then
199 call neko_error("wall_shear_stress: no components selected")
200 end if
201
203
211 subroutine wall_shear_stress_build_field_list(computed_field, want_x, &
212 want_y, want_z, want_mag, fields)
213 character(len=*), intent(in) :: computed_field
214 logical, intent(in) :: want_x, want_y, want_z, want_mag
215 character(len=NEKO_VARNAME_LEN), allocatable, intent(out) :: fields(:)
216 integer :: n, k
217
218 n = 0
219 if (want_x) n = n + 1
220 if (want_y) n = n + 1
221 if (want_z) n = n + 1
222 if (want_mag) n = n + 1
223
224 allocate(fields(n))
225 k = 0
226 if (want_x) then
227 k = k + 1
228 fields(k) = trim(computed_field) // "_x"
229 end if
230 if (want_y) then
231 k = k + 1
232 fields(k) = trim(computed_field) // "_y"
233 end if
234 if (want_z) then
235 k = k + 1
236 fields(k) = trim(computed_field) // "_z"
237 end if
238 if (want_mag) then
239 k = k + 1
240 fields(k) = trim(computed_field) // "_mag"
241 end if
242
244
257 subroutine wall_shear_stress_init_from_controllers(this, name, case, order, &
258 preprocess_controller, compute_controller, output_controller, &
259 computed_field, viscosity_field, zone_indices, components, coef)
260 class(wall_shear_stress_t), intent(inout) :: this
261 character(len=*), intent(in) :: name
262 class(case_t), intent(inout), target :: case
263 integer, intent(in) :: 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 character(len=*), intent(in) :: computed_field
268 character(len=*), intent(in) :: viscosity_field
269 integer, intent(in) :: zone_indices(:)
270 character(len=*), intent(in) :: components(:)
271 type(coef_t), intent(inout), target :: coef
272
273 call this%free()
274
275 call this%init_base_from_components(case, order, preprocess_controller, &
276 compute_controller, output_controller)
277
278 call this%init_common(name, computed_field, viscosity_field, &
279 zone_indices, components, coef)
280
282
300 case, order, preprocess_control, preprocess_value, compute_control, &
301 compute_value, output_control, output_value, computed_field, &
302 viscosity_field, zone_indices, components, coef)
303 class(wall_shear_stress_t), intent(inout) :: this
304 character(len=*), intent(in) :: name
305 class(case_t), intent(inout), target :: case
306 integer, intent(in) :: order
307 character(len=*), intent(in) :: preprocess_control
308 real(kind=rp), intent(in) :: preprocess_value
309 character(len=*), intent(in) :: compute_control
310 real(kind=rp), intent(in) :: compute_value
311 character(len=*), intent(in) :: output_control
312 real(kind=rp), intent(in) :: output_value
313 character(len=*), intent(in) :: computed_field
314 character(len=*), intent(in) :: viscosity_field
315 integer, intent(in) :: zone_indices(:)
316 character(len=*), intent(in) :: components(:)
317 type(coef_t), intent(inout), target :: coef
318
319 call this%free()
320
321 call this%init_base_from_components(case, order, preprocess_control, &
322 preprocess_value, compute_control, compute_value, output_control, &
323 output_value)
324
325 call this%init_common(name, computed_field, viscosity_field, &
326 zone_indices, components, coef)
327
329
337 subroutine wall_shear_stress_init_common(this, name, computed_field, &
338 viscosity_field, zone_indices, components, coef)
339 class(wall_shear_stress_t), intent(inout) :: this
340 character(len=*), intent(in) :: name
341 character(len=*), intent(in) :: computed_field
342 character(len=*), intent(in) :: viscosity_field
343 integer, intent(in) :: zone_indices(:)
344 character(len=*), intent(in) :: components(:)
345 type(coef_t), intent(inout), target :: coef
346 character(len=NEKO_VARNAME_LEN), allocatable :: fields(:)
347 character(len=LOG_SIZE) :: log_buf
348 integer :: i, glb_n_pts
349 logical :: ale_enabled
350
351 this%name = name
352 this%coef => coef
353 this%computed_field = computed_field
354
355 call wall_shear_stress_parse_components(components, this%want_x, &
356 this%want_y, this%want_z, this%want_mag)
357
358 call wall_shear_stress_build_field_list(computed_field, this%want_x, &
359 this%want_y, this%want_z, this%want_mag, fields)
360
361 ! Register the selected fields so they are available in the registry.
362 do i = 1, size(fields)
363 call neko_registry%add_field(coef%dof, trim(fields(i)), &
364 ignore_existing = .false.)
365 end do
366
367 allocate(this%zone_indices(size(zone_indices)))
368 this%zone_indices = zone_indices
369
370 ale_enabled = .false.
371 if (associated(neko_ale)) then
372 if (neko_ale%active) ale_enabled = .true.
373 end if
374
375 ! Whether the mesh geometry varies during the run.
376 this%mesh_has_changed = .false.
377 if (ale_enabled) then
378 this%mesh_has_changed = .true.
379 end if
380
381 this%u => neko_registry%get_field_by_name("u")
382 this%v => neko_registry%get_field_by_name("v")
383 this%w => neko_registry%get_field_by_name("w")
384 this%p => neko_registry%get_field_by_name("p")
385
386 if (.not. neko_registry%field_exists(trim(viscosity_field))) then
387 call neko_error("wall_shear_stress: the viscosity field '" // &
388 trim(viscosity_field) // "' is not in the registry")
389 end if
390 this%mu => neko_registry%get_field_by_name(trim(viscosity_field))
391
392 if (this%want_x) this%tau_x => &
393 neko_registry%get_field_by_name(trim(computed_field) // "_x")
394 if (this%want_y) this%tau_y => &
395 neko_registry%get_field_by_name(trim(computed_field) // "_y")
396 if (this%want_z) this%tau_z => &
397 neko_registry%get_field_by_name(trim(computed_field) // "_z")
398 if (this%want_mag) this%tau_mag => &
399 neko_registry%get_field_by_name(trim(computed_field) // "_mag")
400
401 ! only_facets = .true.
402 ! The normals are requested in the `coef` convention, pointing out of the
403 ! fluid domain, because that is what `calc_force_array` expects. The
404 ! outward convention would flip the sign of the computed traction.
405 call this%bdata%init(this%coef, this%zone_indices, &
406 outward_normals = .false.)
407
408 glb_n_pts = this%bdata%n_global
409
410 call neko_log%section("Wall shear stress")
411 write(log_buf, '(A,A)') "Name: ", trim(this%name)
412 call neko_log%message(log_buf)
413 write(log_buf, '(A,*(I0,:,", "))') "Zone indices: ", this%zone_indices
414 call neko_log%message(log_buf)
415 write(log_buf, '(A,I0)') "Global number of masked points: ", glb_n_pts
416 call neko_log%message(log_buf)
417 write(log_buf, '(A,A)') "Viscosity field: ", trim(viscosity_field)
418 call neko_log%message(log_buf)
419 log_buf = "Registered fields: "
420 if (this%want_x) log_buf = trim(log_buf) // " " // &
421 trim(computed_field) // "_x"
422 if (this%want_y) log_buf = trim(log_buf) // " " // &
423 trim(computed_field) // "_y"
424 if (this%want_z) log_buf = trim(log_buf) // " " // &
425 trim(computed_field) // "_z"
426 if (this%want_mag) log_buf = trim(log_buf) // " " // &
427 trim(computed_field) // "_mag"
428 call neko_log%message(log_buf)
429 write(log_buf, '(A,L1)') "Moving mesh: ", this%mesh_has_changed
430 call neko_log%message(log_buf)
431 call neko_log%end_section()
432
433 end subroutine wall_shear_stress_init_common
434
436 subroutine wall_shear_stress_free(this)
437 class(wall_shear_stress_t), intent(inout) :: this
438
439 call this%bdata%free()
440
441 if (allocated(this%zone_indices)) deallocate(this%zone_indices)
442 if (allocated(this%computed_field)) deallocate(this%computed_field)
443
444 nullify(this%u)
445 nullify(this%v)
446 nullify(this%w)
447 nullify(this%p)
448 nullify(this%mu)
449 nullify(this%tau_x)
450 nullify(this%tau_y)
451 nullify(this%tau_z)
452 nullify(this%tau_mag)
453 nullify(this%coef)
454
455 call this%free_base()
456
457 end subroutine wall_shear_stress_free
458
461 subroutine wall_shear_stress_compute(this, time)
462 class(wall_shear_stress_t), intent(inout) :: this
463 type(time_state_t), intent(in) :: time
464 type(field_t), pointer :: s11, s22, s33, s12, s13, s23
465 type(vector_t), pointer :: mu_msk, p_msk
466 type(vector_t), pointer :: s11_msk, s22_msk, s33_msk
467 type(vector_t), pointer :: s12_msk, s13_msk, s23_msk
468 type(vector_t), pointer :: t1, t2, t3, t_mag
469 type(vector_t), pointer :: pt1, pt2, pt3
470 integer :: field_indices(6)
471 integer :: vector_indices(15)
472 integer :: n_pts
473 character(len=LOG_SIZE) :: log_buf
474
475 n_pts = this%bdata%n_local
476
477 ! Re-gather the boundary geometry only when the mesh has moved.
478 if (this%mesh_has_changed) then
479 call this%bdata%update_geometry()
480 end if
481
482 ! Strain rate over the whole field, then gather it at the mask.
483 call neko_scratch_registry%request_field(s11, field_indices(1), .false.)
484 call neko_scratch_registry%request_field(s22, field_indices(2), .false.)
485 call neko_scratch_registry%request_field(s33, field_indices(3), .false.)
486 call neko_scratch_registry%request_field(s12, field_indices(4), .false.)
487 call neko_scratch_registry%request_field(s13, field_indices(5), .false.)
488 call neko_scratch_registry%request_field(s23, field_indices(6), .false.)
489
490 call strain_rate(s11, s22, s33, s12, s13, s23, this%u, this%v, &
491 this%w, this%coef)
492
493 if (n_pts .gt. 0) then
494
495 call neko_scratch_registry%request_vector(mu_msk, vector_indices(1), &
496 n_pts, .false.)
497 call neko_scratch_registry%request_vector(p_msk, vector_indices(2), &
498 n_pts, .false.)
499 call neko_scratch_registry%request_vector(s11_msk, vector_indices(3), &
500 n_pts, .false.)
501 call neko_scratch_registry%request_vector(s22_msk, vector_indices(4), &
502 n_pts, .false.)
503 call neko_scratch_registry%request_vector(s33_msk, vector_indices(5), &
504 n_pts, .false.)
505 call neko_scratch_registry%request_vector(s12_msk, vector_indices(6), &
506 n_pts, .false.)
507 call neko_scratch_registry%request_vector(s13_msk, vector_indices(7), &
508 n_pts, .false.)
509 call neko_scratch_registry%request_vector(s23_msk, vector_indices(8), &
510 n_pts, .false.)
511 call neko_scratch_registry%request_vector(t1, vector_indices(9), &
512 n_pts, .false.)
513 call neko_scratch_registry%request_vector(t2, vector_indices(10), &
514 n_pts, .false.)
515 call neko_scratch_registry%request_vector(t3, vector_indices(11), &
516 n_pts, .false.)
517 call neko_scratch_registry%request_vector(t_mag, vector_indices(12), &
518 n_pts, .false.)
519 call neko_scratch_registry%request_vector(pt1, vector_indices(13), &
520 n_pts, .false.)
521 call neko_scratch_registry%request_vector(pt2, vector_indices(14), &
522 n_pts, .false.)
523 call neko_scratch_registry%request_vector(pt3, vector_indices(15), &
524 n_pts, .false.)
525
526 call this%bdata%get(this%mu, mu_msk)
527 call this%bdata%get(this%p, p_msk)
528 call this%bdata%get(s11, s11_msk)
529 call this%bdata%get(s22, s22_msk)
530 call this%bdata%get(s33, s33_msk)
531 call this%bdata%get(s12, s12_msk)
532 call this%bdata%get(s13, s13_msk)
533 call this%bdata%get(s23, s23_msk)
534
535 if (neko_bcknd_device .eq. 1) then
536 call device_calc_force_array(pt1%x_d, pt2%x_d, pt3%x_d, &
537 t1%x_d, t2%x_d, t3%x_d, &
538 s11_msk%x_d, s22_msk%x_d, s33_msk%x_d, &
539 s12_msk%x_d, s13_msk%x_d, s23_msk%x_d, &
540 p_msk%x_d, this%bdata%n_x%x_d, &
541 this%bdata%n_y%x_d, this%bdata%n_z%x_d, &
542 mu_msk%x_d, n_pts)
543 else
544 call calc_force_array(pt1%x, pt2%x, pt3%x, &
545 t1%x, t2%x, t3%x, &
546 s11_msk%x, s22_msk%x, s33_msk%x, &
547 s12_msk%x, s13_msk%x, s23_msk%x, &
548 p_msk%x, this%bdata%n_x%x, &
549 this%bdata%n_y%x, this%bdata%n_z%x, &
550 mu_msk%x, n_pts)
551 end if
552
553 ! Remove the wall-normal part, leaving the tangential traction.
554 ! The projection is invariant to the sign of the normal.
555 call this%bdata%tangential(t1, t2, t3)
556
557 ! Magnitude of the tangential traction.
558 if (this%want_mag) then
559 if (neko_bcknd_device .eq. 1) then
560 call device_vdot3(t_mag%x_d, t1%x_d, t2%x_d, t3%x_d, &
561 t1%x_d, t2%x_d, t3%x_d, n_pts)
562 call device_sqrt_inplace(t_mag%x_d, n_pts)
563 else
564 call vdot3(t_mag%x, t1%x, t2%x, t3%x, &
565 t1%x, t2%x, t3%x, n_pts)
566 call sqrt_inplace(t_mag%x, n_pts)
567 end if
568 end if
569
570 ! Scatter the tangential traction and its magnitude into the
571 ! registered fields.
572 if (this%want_x) call this%bdata%scatter(t1, this%tau_x)
573 if (this%want_y) call this%bdata%scatter(t2, this%tau_y)
574 if (this%want_z) call this%bdata%scatter(t3, this%tau_z)
575 if (this%want_mag) call this%bdata%scatter(t_mag, this%tau_mag)
576
577 call neko_scratch_registry%relinquish_vector(vector_indices)
578 end if
579
580 call neko_scratch_registry%relinquish_field(field_indices)
581
582 write(log_buf, '(A,A,A,E15.7,A,*(I0,:,", "))') &
583 "WSS: '", trim(this%name), "' computed at t = ", &
584 time%t, ", zones: ", this%zone_indices
585 call neko_log%message(log_buf)
586
587 end subroutine wall_shear_stress_compute
588
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.
Compute the strain rate tensor of a vector field.
ALE Manager: Handles Mesh Motion.
type(ale_manager_t), pointer, public neko_ale
Implements the boundary_data_t type.
Defines a simulation case.
Definition case.f90:34
Coefficients.
Definition coef.f90:34
subroutine, public device_vdot3(dot_d, u1_d, u2_d, u3_d, v1_d, v2_d, v3_d, n, strm)
Compute a dot product (3-d version) assuming vector components etc.
subroutine, public device_sqrt_inplace(a_d, n, strm)
Sqrt a vector .
subroutine, public calc_force_array(force1, force2, force3, force4, force5, force6, s11, s22, s33, s12, s13, s23, p, n1, n2, n3, mu, n_pts)
Calculate drag and torque from array of points.
subroutine, public device_calc_force_array(force1, force2, force3, force4, force5, force6, s11, s22, s33, s12, s13, s23, p, n1, n2, n3, mu, n_pts)
Calculate drag and torque from array of points.
Defines a field.
Definition field.f90:34
Utilities for retrieving parameters from the case files.
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:80
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
subroutine, public sqrt_inplace(a, n)
Sqrt a vector .
Definition math.f90:1878
subroutine, public vdot3(dot, u1, u2, u3, v1, v2, v3, n)
Compute a dot product (3-d version) assuming vector components etc.
Definition math.f90:852
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Operators.
Definition operators.f90:34
Implements output_controller_t
Defines a registry for storing solution fields.
Definition registry.f90:34
type(registry_t), target, public neko_registry
Global field registry.
Definition registry.f90:144
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.
Contains the time_based_controller_t type.
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
integer, parameter, public neko_varname_len
Definition utils.f90:43
Defines a vector.
Definition vector.f90:34
Implements the wall_shear_stress_t type.
subroutine wall_shear_stress_build_field_list(computed_field, want_x, want_y, want_z, want_mag, fields)
Build the array of selected field names in x, y, z, mag order.
subroutine wall_shear_stress_init_from_controllers(this, name, case, order, preprocess_controller, compute_controller, output_controller, computed_field, viscosity_field, zone_indices, components, coef)
Constructor from components, passing controllers.
subroutine wall_shear_stress_init_common(this, name, computed_field, viscosity_field, zone_indices, components, coef)
Common part of all constructors.
subroutine wall_shear_stress_compute(this, time)
Compute the wall shear stress.
subroutine wall_shear_stress_init_from_json(this, json, case)
Constructor from json.
subroutine wall_shear_stress_parse_components(components, want_x, want_y, want_z, want_mag)
Translate a components list into the four selection flags.
subroutine wall_shear_stress_init_from_controllers_properties(this, name, case, order, preprocess_control, preprocess_value, compute_control, compute_value, output_control, output_value, computed_field, viscosity_field, zone_indices, components, coef)
Constructor from components, passing properties to the time_based_controller components in the base t...
subroutine wall_shear_stress_free(this)
Destructor.
Collects data on the boundary points of one or more labelled zones and perform some bounary operation...
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:63
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.
A simulation component that computes the wall shear stress on one or more labelled boundary zones and...