36 use json_module,
only : json_file
74 character(:),
allocatable :: name
76 type(
field_t),
pointer :: u_field => null()
77 type(
field_t),
pointer :: v_field => null()
78 type(
field_t),
pointer :: w_field => null()
79 type(
field_t),
pointer :: mu_fluid => null()
80 type(
field_t),
pointer :: rho_fluid => null()
81 type(
mesh_t),
pointer :: msh => null()
83 type(
coef_t),
pointer :: coef => null()
84 integer :: time_order, lag_len
85 integer :: history_len = 0
86 logical :: inertia = .false.
87 real(kind=
rp) :: nonlinear_coefficient, nonlinear_exponent
88 logical :: elastic_wall_enabled = .false.
89 integer,
allocatable :: wall_zone_indices(:)
90 logical,
allocatable :: wall_facet_mask(:, :)
92 logical :: lpt_time_initialized = .false.
99 logical :: output_enabled = .false.
100 logical :: log = .true.
101 real(kind=
rp) :: start_time = -huge(0.0_rp)
121 module subroutine lpt_init_wall_facet_mask(wall_facet_mask, msh, &
123 logical,
allocatable,
intent(inout) :: wall_facet_mask(:, :)
124 type(
mesh_t),
intent(in) :: msh
125 integer,
intent(in) :: wall_zone_indices(:)
126 end subroutine lpt_init_wall_facet_mask
129 module subroutine lpt_handle_elastic_wall_collisions(this, x_old, y_old, &
130 z_old, u_old, v_old, w_old)
131 class(lpt_t),
intent(inout) :: this
132 type(
vector_t),
intent(in) :: x_old, y_old, z_old
133 type(
vector_t),
intent(inout) :: u_old, v_old, w_old
134 end subroutine lpt_handle_elastic_wall_collisions
142 subroutine lpt_init_from_json(this, json, case)
143 class(lpt_t),
intent(inout),
target :: this
144 type(json_file),
intent(inout) :: json
145 class(
case_t),
intent(inout),
target :: case
146 type(json_file) :: interp_subdict
147 character(len=:),
allocatable :: name
148 character(len=:),
allocatable :: migration_strategy
149 character(len=:),
allocatable :: output_filename
150 character(len=:),
allocatable :: output_format
151 character(len=:),
allocatable :: snapshots_per_file_str
152 character(len=:),
allocatable :: output_path
153 integer :: migration_strategy_id
154 integer :: snapshots_per_file
155 integer :: snapshots_per_file_type
156 logical :: snapshots_per_file_found
166 this%time_order =
case%fluid%ext_bdf%advection_time_order
167 this%msh =>
case%fluid%msh
168 this%dm_Xh =>
case%fluid%dm_Xh
169 this%coef =>
case%fluid%c_Xh
171 this%lag_len = this%time_order - 1
174 select case (trim(migration_strategy))
180 call neko_error(
"lpt migration_strategy must be 'owner' or 'none'")
182 call this%migration%init(this%lag_len, migration_strategy_id)
184 call json_get(json,
"inertia", this%inertia)
186 if (this%inertia)
then
188 this%nonlinear_coefficient, 0.15_rp)
190 this%nonlinear_exponent, 0.687_rp)
192 case%fluid%name //
"_mu")
194 case%fluid%name //
"_rho")
200 if (
case%params%valid_path(
"case.fluid.wall_zone_indices"))
then
201 call json_get(
case%params,
"case.fluid.wall_zone_indices", &
202 this%wall_zone_indices)
203 if (.not. this%inertia .and.
size(this%wall_zone_indices) .gt. 0)
then
204 call neko_error(
"lpt wall_zone_indices requires inertia = true")
206 this%elastic_wall_enabled =
size(this%wall_zone_indices) .gt. 0
207 if (this%elastic_wall_enabled .and. &
209 call neko_error(
"lpt migration_strategy = none is not " // &
210 "compatible with elastic wall collisions")
212 if (this%elastic_wall_enabled)
then
213 call lpt_init_wall_facet_mask(this%wall_facet_mask, this%msh, &
214 this%wall_zone_indices)
218 call this%read_particles_json(json)
219 call this%migration%initialize_particle_distribution(this%inertia, &
223 call this%global_interp%init(
case%fluid%dm_Xh, &
224 params_subdict = interp_subdict)
225 call this%periodic_bc%init(
case%fluid%msh,
case%fluid%dm_Xh, &
227 call this%migration%migrate_particles(this%global_interp, &
228 this%periodic_bc, this%inertia, this%particles)
229 call this%sync_time_controller(
case%time)
230 call this%update_current_rhs()
236 call json%info(
"snapshots_per_file", found = snapshots_per_file_found, &
237 var_type = snapshots_per_file_type)
238 if (snapshots_per_file_found)
then
239 select case (snapshots_per_file_type)
241 call json_get(json,
"snapshots_per_file", snapshots_per_file)
242 if (snapshots_per_file .lt. 1)
then
243 call neko_error(
"lpt snapshots_per_file must be a positive " // &
247 call json_get(json,
"snapshots_per_file", snapshots_per_file_str)
248 if (trim(snapshots_per_file_str) .eq.
"all")
then
249 snapshots_per_file = 0
251 call neko_error(
"lpt snapshots_per_file must be a positive " // &
255 call neko_error(
"lpt snapshots_per_file must be a positive " // &
259 snapshots_per_file = 0
260 call json%add(
"snapshots_per_file",
"all")
262 output_path =
case%output_directory // trim(output_filename) //
"." // &
264 call this%output%init(output_path, this%inertia, snapshots_per_file)
267 this%output_enabled = .true.
268 call this%write_output(
case%time)
270 call this%log_status()
271 end subroutine lpt_init_from_json
276 subroutine read_particles_json(this, json)
277 class(lpt_t),
intent(inout) :: this
278 type(json_file),
intent(inout) :: json
279 real(kind=
rp),
allocatable :: coords(:)
280 real(kind=
rp),
allocatable :: vels(:)
281 real(kind=
rp),
allocatable :: diams(:)
282 real(kind=
rp),
allocatable :: densities(:)
283 real(kind=
rp),
pointer,
dimension(:) :: x, y, z, u, v, w
284 integer :: n_particles, ind(6)
287 if (json%valid_path(
"coordinates"))
then
288 call json_get(json,
"coordinates", coords)
289 if (mod(
size(coords), 3) .ne. 0)
then
290 call neko_error(
"lpt coordinates must contain 3 values per " // &
293 n_particles =
size(coords) / 3
294 if (this%inertia)
then
295 call json_get(json,
"velocities", vels)
296 if (mod(
size(vels), 3) .ne. 0)
then
297 call neko_error(
"lpt velocities must contain 3 values per " // &
300 call json_get(json,
"diameters", diams)
301 call json_get(json,
"densities", densities)
302 if (
size(vels) / 3 .ne. n_particles .or. &
303 size(diams) .ne. n_particles .or. &
304 size(densities) .ne. n_particles)
then
305 call neko_error(
"lpt coordinates, velocities, diameters " // &
306 "and densities must describe the same number of " // &
310 allocate(vels(
size(coords)))
311 allocate(diams(n_particles))
312 allocate(densities(n_particles))
329 call this%particles%init(x, y, z, this%time_order, u, v, &
334 deallocate(densities)
337 else if (json%valid_path(
"points_file"))
then
338 call this%read_particles_csv(json)
340 call neko_error(
"lpt requires either coordinates or points_file")
345 end subroutine read_particles_json
349 subroutine read_particles_csv(this, json)
350 class(lpt_t),
intent(inout) :: this
351 type(json_file),
intent(inout) :: json
352 character(len=:),
allocatable :: points_file
355 real(kind=
rp),
pointer,
dimension(:) :: x, y, z, u, v, w
356 real(kind=
rp),
allocatable :: diams(:)
357 real(kind=
rp),
allocatable :: densities(:)
358 integer :: n_particles, ind_basic(3), ind_inertia(6)
362 call json_get(json,
"points_file", points_file)
363 call file_in%init(trim(points_file))
365 select type (ft => file_in%file_type)
367 if (this%inertia)
then
368 call mat_in%init(ft%count_lines(), 8)
370 n_particles = mat_in%get_nrows()
389 diams = mat_in%x(:, 7)
390 densities = mat_in%x(:, 8)
391 call this%particles%init(x, y, z, this%time_order, u, v, &
394 deallocate(densities)
397 call mat_in%init(ft%count_lines(), 3)
399 n_particles = mat_in%get_nrows()
406 call this%particles%init(x, y, z, this%time_order)
410 call neko_error(
"lpt points_file must be a csv file")
414 end subroutine read_particles_csv
420 subroutine evaluate_velocity(this, u_fluid, v_fluid, w_fluid)
421 class(lpt_t),
intent(inout) :: this
422 type(
vector_t),
intent(inout) :: u_fluid, v_fluid, w_fluid
423 logical :: do_interp_on_host
425 if (this%particles%n .eq. 0)
return
427 do_interp_on_host = .false.
428 call this%global_interp%evaluate(u_fluid%x, this%u_field%x, &
430 call this%global_interp%evaluate(v_fluid%x, this%v_field%x, &
432 call this%global_interp%evaluate(w_fluid%x, this%w_field%x, &
435 end subroutine evaluate_velocity
444 subroutine evaluate_acceleration(this, acc_x, acc_y, acc_z, &
445 u_fluid, v_fluid, w_fluid)
446 class(lpt_t),
intent(inout) :: this
447 type(
vector_t),
intent(in) :: u_fluid, v_fluid, w_fluid
448 type(
vector_t),
intent(inout) :: acc_x, acc_y, acc_z
449 type(
vector_t),
pointer :: tau_p, Re_p, f, rho_fluid_local
450 type(
vector_t),
pointer :: mu_fluid_local, nu_fluid_local
454 logical :: do_interp_on_host
456 if (this%particles%n .eq. 0)
return
472 do_interp_on_host = .false.
473 call this%global_interp%evaluate(mu_fluid_local%x, this%mu_fluid%x, &
475 call this%global_interp%evaluate(rho_fluid_local%x, this%rho_fluid%x, &
489 nu_fluid_local => mu_fluid_local
496 call vector_vdot3(re_p, acc_x, acc_y, acc_z, acc_x, acc_y, acc_z)
516 end subroutine evaluate_acceleration
519 subroutine update_current_rhs(this)
520 class(lpt_t),
intent(inout) :: this
521 type(
vector_t),
pointer :: u_fluid, v_fluid, w_fluid
526 call this%migration%migrate_particles(this%global_interp, &
527 this%periodic_bc, this%inertia, this%particles)
530 this%particles%n, .false.)
532 this%particles%n, .false.)
534 this%particles%n, .false.)
536 call this%evaluate_velocity(u_fluid, v_fluid, w_fluid)
538 if (this%inertia)
then
539 call this%evaluate_acceleration(this%particles%acc_x, &
540 this%particles%acc_y, this%particles%acc_z, &
541 u_fluid, v_fluid, w_fluid)
543 this%particles%u = u_fluid
544 this%particles%v = v_fluid
545 this%particles%w = w_fluid
551 end subroutine update_current_rhs
557 subroutine update_lags(lag, laglag, new_values)
558 type(
vector_t),
intent(inout) :: lag, laglag
559 type(
vector_t),
intent(in) :: new_values
564 end subroutine update_lags
568 subroutine lpt_preprocess(this, time)
569 class(lpt_t),
intent(inout) :: this
571 type(
vector_t),
pointer :: x_old, y_old, z_old, u_old, v_old, w_old
574 associate(x => this%particles%x, y => this%particles%y, &
575 z => this%particles%z, u => this%particles%u, &
576 v => this%particles%v, w => this%particles%w, &
577 acc_x => this%particles%acc_x, &
578 acc_y => this%particles%acc_y, &
579 acc_z => this%particles%acc_z, &
580 u_lag => this%particles%u_lag, &
581 v_lag => this%particles%v_lag, &
582 w_lag => this%particles%w_lag, &
583 u_laglag => this%particles%u_laglag, &
584 v_laglag => this%particles%v_laglag, &
585 w_laglag => this%particles%w_laglag, &
586 acc_xlag => this%particles%acc_xlag, &
587 acc_ylag => this%particles%acc_ylag, &
588 acc_zlag => this%particles%acc_zlag, &
589 acc_xlaglag => this%particles%acc_xlaglag, &
590 acc_ylaglag => this%particles%acc_ylaglag, &
591 acc_zlaglag => this%particles%acc_zlaglag, &
592 n => this%particles%n)
593 if (time%t .lt. this%start_time)
return
594 call this%sync_time_controller(time)
595 if (abs(this%lpt_time%dt) .le. epsilon(1.0_rp))
return
614 if (this%inertia)
then
615 call this%ODE_integrate_ab_3c(u, v, w, acc_x, acc_y, acc_z, &
616 acc_xlag, acc_ylag, acc_zlag, acc_xlaglag, acc_ylaglag, &
622 call this%ODE_integrate_ab_3c(x, y, z, u_old, v_old, w_old, &
623 u_lag, v_lag, w_lag, u_laglag, v_laglag, w_laglag, n)
626 if (this%inertia .and. this%elastic_wall_enabled)
then
627 call lpt_handle_elastic_wall_collisions(this, x_old, y_old, z_old, &
632 if (this%lag_len .gt. 0)
then
633 call update_lags(u_lag, u_laglag, u_old)
634 call update_lags(v_lag, v_laglag, v_old)
635 call update_lags(w_lag, w_laglag, w_old)
636 if (this%inertia)
then
637 call update_lags(acc_xlag, acc_xlaglag, acc_x)
638 call update_lags(acc_ylag, acc_ylaglag, acc_y)
639 call update_lags(acc_zlag, acc_zlaglag, acc_z)
641 this%history_len = min(this%history_len + 1, this%lag_len)
650 end subroutine lpt_preprocess
654 subroutine lpt_compute(this, time)
655 class(lpt_t),
intent(inout) :: this
656 type(time_state_t),
intent(in) :: time
658 if (time%t .lt. this%start_time)
return
660 call this%update_current_rhs()
662 if (this%output_enabled)
then
663 if (this%output_controller%check(time))
then
664 call this%write_output(time)
665 call this%output_controller%register_execution(time)
668 end subroutine lpt_compute
672 subroutine sync_time_controller(this, time)
673 class(lpt_t),
intent(inout) :: this
674 type(time_state_t),
intent(in) :: time
675 real(kind=rp) :: dt_local
676 real(kind=rp) :: t_ref
679 if (.not. this%lpt_time_initialized)
then
682 if (this%start_time .gt. time%t) t_ref = this%start_time
683 this%lpt_time%t = t_ref
684 this%lpt_time%tlag = t_ref
685 this%lpt_time%dt = 0.0_rp
686 this%lpt_time%dtlag = 0.0_rp
687 this%lpt_time_initialized = .true.
691 dt_local = time%t - this%lpt_time%t
692 if (abs(dt_local) .le. epsilon(1.0_rp))
then
693 this%lpt_time%t = time%t
694 this%lpt_time%tstep = time%tstep
695 this%lpt_time%dt = 0.0_rp
699 do i =
size(this%lpt_time%dtlag), 2, -1
700 this%lpt_time%dtlag(i) = this%lpt_time%dtlag(i - 1)
701 this%lpt_time%tlag(i) = this%lpt_time%tlag(i - 1)
703 this%lpt_time%dtlag(1) = this%lpt_time%dt
704 this%lpt_time%tlag(1) = this%lpt_time%t
705 this%lpt_time%dt = dt_local
706 this%lpt_time%t = time%t
707 this%lpt_time%tstep = time%tstep
708 end subroutine sync_time_controller
715 subroutine ode_integrate_ab_3c(this, sol_x, sol_y, sol_z, &
716 rhs_x, rhs_y, rhs_z, rhs_xlag, rhs_ylag, rhs_zlag, &
717 rhs_xlaglag, rhs_ylaglag, rhs_zlaglag, n)
718 class(lpt_t),
intent(inout) :: this
719 type(vector_t),
intent(inout) :: sol_x, sol_y, sol_z
720 type(vector_t),
intent(in) :: rhs_x, rhs_y, rhs_z
721 type(vector_t),
intent(in) :: rhs_xlag, rhs_ylag, rhs_zlag
722 type(vector_t),
intent(in) :: rhs_xlaglag, rhs_ylaglag
723 type(vector_t),
intent(in) :: rhs_zlaglag
724 integer,
intent(in) :: n
725 type(ab_time_scheme_t) :: ab_scheme
726 real(kind=rp) :: ab_coeffs(4), dt_history(10)
734 nadv = this%time_order
735 nadv = min(nadv, this%history_len + 1)
738 dt_history(1) = this%lpt_time%dt
739 dt_history(2) = this%lpt_time%dtlag(1)
740 dt_history(3) = this%lpt_time%dtlag(2)
741 call ab_scheme%compute_coeffs(ab_coeffs, dt_history, nadv)
744 dtc = this%lpt_time%dt * ab_coeffs(1)
746 call vector_add2s2(sol_x, rhs_x, dtc, n)
747 call vector_add2s2(sol_y, rhs_y, dtc, n)
748 call vector_add2s2(sol_z, rhs_z, dtc, n)
750 if (nadv .ge. 2)
then
751 dtc = this%lpt_time%dt * ab_coeffs(2)
752 call vector_add2s2(sol_x, rhs_xlag, dtc, n)
753 call vector_add2s2(sol_y, rhs_ylag, dtc, n)
754 call vector_add2s2(sol_z, rhs_zlag, dtc, n)
757 if (nadv .ge. 3)
then
758 dtc = this%lpt_time%dt * ab_coeffs(3)
759 call vector_add2s2(sol_x, rhs_xlaglag, dtc, n)
760 call vector_add2s2(sol_y, rhs_ylaglag, dtc, n)
761 call vector_add2s2(sol_z, rhs_zlaglag, dtc, n)
764 end subroutine ode_integrate_ab_3c
768 subroutine write_output(this, time)
769 class(lpt_t),
intent(inout) :: this
770 type(time_state_t),
intent(in) :: time
771 real(kind=rp),
allocatable :: local_data(:,:)
776 n_local = this%particles%n
778 call this%particles%device_sync(device_to_host)
780 if (this%inertia)
then
785 allocate(local_data(n_data, n_local))
787 local_data(1,i) =
real(time%tstep, rp)
788 local_data(2,i) = time%t
789 local_data(3,i) =
real(this%particles%ids(i), rp)
790 local_data(4,i) = this%particles%x%x(i)
791 local_data(5,i) = this%particles%y%x(i)
792 local_data(6,i) = this%particles%z%x(i)
793 local_data(7,i) = this%particles%u%x(i)
794 local_data(8,i) = this%particles%v%x(i)
795 local_data(9,i) = this%particles%w%x(i)
796 if (this%inertia)
then
797 local_data(10,i) = this%particles%d%x(i)
798 local_data(11,i) = this%particles%rho%x(i)
802 call this%output%write(local_data, n_local)
803 deallocate(local_data)
804 end subroutine write_output
807 subroutine lpt_free(this)
808 class(lpt_t),
intent(inout) :: this
810 call this%particles%free()
811 call this%global_interp%free()
812 call this%periodic_bc%free()
813 call this%migration%free()
814 call this%output%free()
815 call this%output_controller%free()
817 this%u_field => null()
818 this%v_field => null()
819 this%w_field => null()
823 if (
allocated(this%wall_zone_indices))
deallocate(this%wall_zone_indices)
824 if (
allocated(this%wall_facet_mask))
deallocate(this%wall_facet_mask)
825 this%elastic_wall_enabled = .false.
826 this%output_enabled = .false.
828 this%start_time = -huge(0.0_rp)
830 if (
allocated(this%name))
deallocate(this%name)
831 call this%lpt_time%reset()
832 this%lpt_time_initialized = .false.
833 end subroutine lpt_free
836 subroutine log_status(this)
837 class(lpt_t),
intent(in) :: this
838 character(len=LOG_SIZE) :: log_buf
840 if (.not. this%log)
return
842 call neko_log%section(
"Lagrangian particle tracking")
843 write(log_buf,
'(A,A)')
"Name: ", trim(this%name)
844 call neko_log%message(log_buf)
845 write(log_buf,
'(A,I0)')
"Global seeded particles: ", &
846 this%particles%n_global
847 call neko_log%message(log_buf)
848 if (this%periodic_bc%periodic_enabled)
then
849 write(log_buf,
'(A,I0)')
"Periodic wrap directions: ", &
850 this%periodic_bc%n_periodic_dirs
851 call neko_log%message(log_buf)
853 if (this%periodic_bc%rotational_periodic_enabled)
then
854 write(log_buf,
'(A,3(ES13.5,A),ES13.5)') &
855 "Rotational periodic sector: theta_min = ", &
856 this%periodic_bc%rotational_theta_min,
", theta_max = ", &
857 this%periodic_bc%rotational_theta_max,
", theta_len = ", &
858 this%periodic_bc%rotational_theta_len,
""
859 call neko_log%message(log_buf)
861 if (this%elastic_wall_enabled)
then
862 write(log_buf,
'(A,I0)')
"Elastic wall zones configured: ", &
863 size(this%wall_zone_indices)
864 call neko_log%message(log_buf)
866 write(log_buf,
'(A,I0)')
"Local particles on rank 0 at init: ", &
868 if (pe_rank .eq. 0)
call neko_log%message(log_buf)
869 call neko_log%end_section()
870 end subroutine log_status
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.
Adam-Bashforth scheme for time integration.
Defines a simulation case.
integer, public pe_rank
MPI rank.
File format for .csv files, used for any read/write operations involving floating point data.
Device abstraction, common interface for various accelerators.
integer, parameter, public device_to_host
Defines a mapping of the degrees of freedom.
Module for file I/O operations.
Implements global_interpolation given a dofmap.
Utilities for retrieving parameters from the case files.
subroutine, public json_get_subdict_or_empty(json, key, output)
Extract a sub-object from a json object and returns an empty object if the key is missing.
type(log_t), public neko_log
Global log stream.
integer, parameter, public log_size
Particle redistribution support for LPT.
integer, parameter, public lpt_migrate_to_owner
integer, parameter, public lpt_migrate_none
Output support for Lagrangian particle tracking.
Periodic and cyclic boundary-condition support for LPT.
Implements lpt_t. (Lagrangian Particle Tracking)
subroutine lpt_compute(this, time)
Refresh particle/fluid coupling after the fluid step and emit output.
subroutine lpt_init_from_json(this, json, case)
Build a mask of elastic wall facets from configured mesh zone ids.
subroutine evaluate_velocity(this, u_fluid, v_fluid, w_fluid)
Interpolate the carrier velocity at the local particles.
subroutine lpt_free(this)
Free all LPT-owned state and reset pointers/flags.
subroutine log_status(this)
Emit a setup summary for the configured LPT instance.
subroutine ode_integrate_ab_3c(this, sol_x, sol_y, sol_z, rhs_x, rhs_y, rhs_z, rhs_xlag, rhs_ylag, rhs_zlag, rhs_xlaglag, rhs_ylaglag, rhs_zlaglag, n)
Advance a three-component state with variable-step Adams-Bashforth.
subroutine, private update_lags(lag, laglag, new_values)
Shift one particle history level and store new current values.
subroutine write_output(this, time)
Write one trajectory snapshot.
subroutine read_particles_csv(this, json)
Read particle data from a CSV file and initialise particles on rank 0.
subroutine update_current_rhs(this)
Refresh particle RHS values using the current fluid solution.
subroutine sync_time_controller(this, time)
Build an LPT-local time-step history from the times at which LPT runs.
subroutine read_particles_json(this, json)
Read particle data from JSON and initialise particles on rank 0.
subroutine evaluate_acceleration(this, acc_x, acc_y, acc_z, u_fluid, v_fluid, w_fluid)
Estimate particle acceleration from local carrier-fluid velocity.
subroutine lpt_preprocess(this, time)
Advance particle positions and, for inertial particles, velocities.
integer, parameter, public rp
Global precision used in computations.
Implements output_controller_t
Defines a collection of Lagrangian particles.
subroutine, public profiler_start_region(name, region_id)
Started a named (name) profiler region.
subroutine, public profiler_end_region(name, region_id)
End the most recently started profiler region.
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.
Contains the time_based_controller_t type.
Module with things related to the simulation time.
subroutine, public vector_vdot3(dot, u1, u2, u3, v1, v2, v3, n)
Compute a dot product (3-d version) assuming vector components etc.
subroutine, public vector_sub3(a, b, c, n)
Vector subtraction .
subroutine, public vector_power(ap, a, p, n)
Take the power of a vector .
subroutine, public vector_cmult(a, c, n)
Multiplication by constant c .
subroutine, public vector_col2(a, b, n)
Vector multiplication .
subroutine, public vector_cfill(a, c, n)
Set all elements to a constant c .
subroutine, public vector_invcol2(a, b, n)
Vector division .
subroutine, public vector_sqrt_inplace(a, n)
Sqrt a vector .
subroutine, public vector_cadd(a, s, n)
Add a scalar to vector .
subroutine, public vector_add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
subroutine, public vector_cmult2(a, b, c, n)
Multiplication by constant c .
subroutine, public vector_col3(a, b, c, n)
Vector multiplication with 3 vectors .
Explicit Adam-Bashforth scheme for time integration.
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...
Implements global interpolation for arbitrary points in the domain.
Passive Lagrangian particle tracking.
Particle positions, velocities, properties, and time-history data.
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.