42 use mpi_f08,
only : mpi_barrier, mpi_gather, mpi_gatherv, mpi_integer
48 character(len=1024) :: output_path =
""
49 logical :: hdf5_output = .false.
50 logical :: inertia = .false.
51 integer :: snapshots_per_file = 0
52 integer :: snapshots_in_file = 0
53 integer :: output_file_index = 1
54 integer :: hdf5_output_count = 0
75 character(len=*),
intent(in) :: output_path
76 logical,
intent(in) :: inertia
77 integer,
intent(in) :: snapshots_per_file
80 this%output_path = trim(output_path)
81 this%inertia = inertia
82 this%snapshots_per_file = snapshots_per_file
96 character(len=1024) :: output_path
97 character(len=80) :: output_suffix
99 call this%output_file%free()
100 call this%current_path(output_path)
103 select case (trim(output_suffix))
105 if (this%inertia)
then
106 call this%output_file%init(output_path, &
107 header =
"tstep,time,particle_id,x,y,z,u,v,w,d,rho", &
110 call this%output_file%init(output_path, &
111 header =
"tstep,time,particle_id,x,y,z,u,v,w", &
114 this%hdf5_output = .false.
116 this%hdf5_output = .true.
117 call this%init_hdf5(output_path, this%inertia)
119 call neko_error(
"lpt output_filename must end in .csv, .h5, or .hdf5")
121 this%snapshots_in_file = 0
128 character(len=*),
intent(out) :: output_path
129 character(len=1024) :: path
130 character(len=1024) :: name
131 character(len=1024) :: suffix
135 write(output_path,
'(A,A,A,I0,A)') trim(path), trim(name), &
136 "_", this%output_file_index, trim(suffix)
145 character(len=*),
intent(in) :: output_path
146 logical,
intent(in) :: inertia
154 open(newunit = file_unit,
file = trim(output_path), status =
"replace", &
155 action =
"write", iostat = ierr)
156 if (ierr .ne. 0)
then
157 call neko_error(
"Error while creating " // trim(output_path))
159 close(file_unit, status =
"delete")
163 call this%output_file%init(output_path)
165 select type (ft => this%output_file%file_type)
167 call ft%set_overwrite(.false.)
169 call ft%set_active_group(
"lpt")
171 call ft%write_attribute(
"FormatVersion", out_int)
172 out_int = this%n_data
173 call ft%write_attribute(
"NColumns", out_int)
179 call ft%write_attribute(
"NCategories", out_int)
185 call ft%write_attribute(
"Inertia", out_int)
187 call ft%write_attribute(
"NSteps", out_int)
190 call neko_error(
"lpt internal error: expected hdf5_file_t")
193 this%hdf5_output_count = 0
201 integer,
intent(in) :: n_local
202 real(kind=
rp),
intent(in) :: local_data(this%n_data, n_local)
204 if (this%snapshots_per_file .gt. 0 .and. &
205 this%snapshots_in_file .ge. this%snapshots_per_file)
then
206 this%output_file_index = this%output_file_index + 1
207 call this%init_file()
210 if (this%hdf5_output)
then
211 call this%write_hdf5(local_data, n_local)
213 call this%write_csv(local_data, n_local)
215 this%snapshots_in_file = this%snapshots_in_file + 1
223 integer,
intent(in) :: n_local
224 real(kind=
rp),
intent(in) :: local_data(this%n_data, n_local)
234 call tsteps%init(1, n_local,
"tsteps")
235 call t%init(1, n_local,
"t")
236 call ids%init(1, n_local,
"ids")
237 call position%init(3, n_local,
"position")
238 call velocity%init(3, n_local,
"velocity")
239 if (this%inertia)
then
240 call diameter%init(1, n_local,
"diameter")
241 call density%init(1, n_local,
"density")
244 if (n_local .gt. 0)
then
245 tsteps%x(1, :) = local_data(1, :)
246 t%x(1, :) = local_data(2, :)
247 ids%x(1, :) = local_data(3, :)
248 position%x = local_data(4:6, :)
249 velocity%x = local_data(7:9, :)
250 if (this%inertia)
then
251 diameter%x(1, :) = local_data(10, :)
252 density%x(1, :) = local_data(11, :)
256 select type (ft => this%output_file%file_type)
259 call ft%set_active_group(
"lpt")
260 out_int = this%hdf5_output_count + 1
261 call ft%write_attribute(
"NSteps", out_int)
262 call ft%write_dataset(tsteps)
263 call ft%write_dataset(t)
264 call ft%write_dataset(ids)
265 call ft%write_dataset(position)
266 call ft%write_dataset(velocity)
267 if (this%inertia)
then
268 call ft%write_dataset(diameter)
269 call ft%write_dataset(density)
273 call neko_error(
"lpt internal error: expected hdf5_file_t")
276 this%hdf5_output_count = this%hdf5_output_count + 1
282 if (this%inertia)
then
293 integer,
intent(in) :: n_local
294 real(kind=
rp),
intent(in) :: local_data(this%n_data, n_local)
296 real(kind=
rp),
allocatable :: global_data(:, :)
297 integer,
allocatable :: n_local_particles_per_rank(:)
298 integer,
allocatable :: recvcounts(:)
299 integer,
allocatable :: displs(:)
300 integer :: total_particles
305 allocate(n_local_particles_per_rank(
pe_size))
307 allocate(n_local_particles_per_rank(0))
309 call mpi_gather(n_local, 1, mpi_integer, n_local_particles_per_rank, 1, &
320 total_particles = total_particles + n_local_particles_per_rank(i)
321 recvcounts(i) = this%n_data * n_local_particles_per_rank(i)
322 displs(i) = this%n_data * &
323 (total_particles - n_local_particles_per_rank(i))
326 allocate(global_data(this%n_data, total_particles))
328 allocate(recvcounts(0))
330 allocate(global_data(this%n_data, 0))
338 call block%init(total_particles, this%n_data)
339 call trsp(block%x, total_particles, global_data, this%n_data)
340 call this%output_file%write(block)
344 deallocate(global_data)
345 deallocate(n_local_particles_per_rank)
346 deallocate(recvcounts)
354 call this%output_file%free()
355 this%output_path =
""
356 this%hdf5_output = .false.
357 this%inertia = .false.
358 this%snapshots_per_file = 0
359 this%snapshots_in_file = 0
360 this%output_file_index = 0
361 this%hdf5_output_count = 0
type(mpi_datatype), public mpi_real_precision
MPI type for working precision of REAL types.
integer, public pe_size
MPI size of communicator.
integer, public pe_rank
MPI rank.
type(mpi_comm), public neko_comm
MPI communicator.
Module for file I/O operations.
Output support for Lagrangian particle tracking.
subroutine lpt_output_write(this, local_data, n_local)
Write one trajectory snapshot.
subroutine lpt_output_init_hdf5(this, output_path, inertia)
Initialise an HDF5 LPT trajectory file.
subroutine lpt_output_current_path(this, output_path)
Get the active output path, adding a file index when chunked output is on.
subroutine lpt_output_init(this, output_path, inertia, snapshots_per_file)
Initialise the LPT output writer.
subroutine lpt_output_write_csv(this, local_data, n_local)
Write one trajectory snapshot to CSV by gathering particle data to rank 0.
subroutine lpt_output_free(this)
Free the output writer and reset file/output counters.
subroutine lpt_output_init_file(this)
Initialise the currently active LPT output file.
subroutine lpt_output_write_hdf5(this, local_data, n_local)
Append one local LPT trajectory snapshot to an HDF5 file.
integer, parameter, public rp
Global precision used in computations.
subroutine, public trsp(a, lda, b, ldb)
Transpose of a rectangular tensor .
subroutine, public filename_split(fname, path, name, suffix)
Extract file name components.
subroutine, public filename_suffix(fname, suffix)
Extract a filename's suffix.
A wrapper around a polymorphic generic_file_t that handles its init. This is essentially a factory fo...
Interface for HDF5 files.