44 use mpi_f08,
only : mpi_wtime, mpi_barrier
63 real(kind=
dp) :: time_start
65 logical :: write_at_start = .true.
67 real(kind=
dp) :: time_end
98 integer,
intent(in),
optional :: size
99 real(kind=
dp),
intent(in) :: time_end
100 real(kind=
dp),
intent(in),
optional :: time_start
101 logical,
intent(in),
optional :: write_at_start
102 character(len=LOG_SIZE) :: log_buf
107 if (
present(size))
then
113 allocate(this%output_list(n))
114 allocate(this%controllers(n))
117 this%output_list(i)%ptr => null()
122 this%time_end = time_end
124 if (
present(time_start))
then
125 this%time_start = time_start
127 this%time_start = 0.0_dp
130 if (
present(write_at_start))
then
131 this%write_at_start = write_at_start
133 this%write_at_start = .true.
142 if (
allocated(this%output_list))
then
143 deallocate(this%output_list)
145 if (
allocated(this%controllers))
then
146 deallocate(this%controllers)
168 start_time, write_at_start)
170 class(
output_t),
intent(inout),
target :: out
171 real(kind=
dp),
intent(in) :: write_par
172 character(len=*),
intent(in) :: write_control
173 real(kind=
dp),
optional,
intent(in) :: start_time
174 logical,
optional,
intent(in) :: write_at_start
175 real(kind=
dp) :: start_time_
176 logical :: write_at_start_
179 character(len=LOG_SIZE) :: log_buf
180 integer :: n, nexecutions
181 class(*),
pointer :: ft
183 if (
present(start_time))
then
184 start_time_ = start_time
186 start_time_ = this%time_start
189 if (
present(write_at_start))
then
190 write_at_start_ = write_at_start
192 write_at_start_ = this%write_at_start
196 if (this%n .ge. this%size)
then
197 allocate(tmp(this%size * 2))
198 tmp(1:this%size) = this%output_list
199 call move_alloc(tmp, this%output_list)
201 allocate(tmp_ctrl(this%size * 2))
202 tmp_ctrl(1:this%size) = this%controllers
203 call move_alloc(tmp_ctrl, this%controllers)
205 this%size = this%size * 2
211 this%output_list(this%n)%ptr => out
213 if (trim(write_control) .eq.
"org")
then
214 this%controllers(n) = this%controllers(1)
216 call this%controllers(n)%init(start_time_, this%time_end, &
217 write_control, write_par, write_at_start_, &
218 direction = this%time_end - this%time_start)
222 call neko_log%section(
'Adding write output')
223 call neko_log%message(
'File name : '// &
224 trim(this%output_list(this%n)%ptr%file_%file_type%get_fname()))
225 call neko_log%message(
'Write control : '//trim(write_control))
226 if (.not. this%controllers(n)%never)
then
227 write(log_buf,
'(A,ES13.6)')
'First write at : ', &
228 this%controllers(n)%next_time()
229 if (trim(write_control) .ne.
'tsteps')
call neko_log%message(log_buf)
233 select type (ft => out%file_%file_type)
235 if (ft%dp_precision)
then
236 call neko_log%message(
'Output precision : double')
238 call neko_log%message(
'Output precision : single')
242 if (trim(write_control) .eq.
'simulationtime')
then
243 write(log_buf,
'(A,ES13.6)')
'Writes per time unit (Freq.): ', &
244 this%controllers(n)%frequency
246 write(log_buf,
'(A,ES13.6)')
'Time between writes: ', &
247 this%controllers(n)%time_interval
249 else if (trim(write_control) .eq.
'nsamples')
then
250 write(log_buf,
'(A,I13)')
'Total samples: ', int(write_par)
252 write(log_buf,
'(A,ES13.6)')
'Writes per time unit (Freq.): ', &
253 this%controllers(n)%frequency
255 write(log_buf,
'(A,ES13.6)')
'Time between writes: ', &
256 this%controllers(n)%time_interval
258 else if (trim(write_control) .eq.
'tsteps')
then
259 write(log_buf,
'(A,I13)')
'Time step interval: ', int(write_par)
261 else if (trim(write_control) .eq.
'org')
then
262 write(log_buf,
'(A)') &
263 'Write control not set, defaulting to first output settings'
278 logical,
intent(in),
optional :: ifforce
279 real(kind=
dp) :: sample_start_time, sample_end_time
280 real(kind=
dp) :: sample_time
281 character(len=LOG_SIZE) :: log_buf
282 character(len=1024) :: output_fname
284 logical :: force, write_output, write_output_test
286 if (
present(ifforce))
then
295 sample_start_time = mpi_wtime()
297 write_output = .false.
302 select type (samp => this)
305 if (this%controllers(i)%check(time, force))
then
306 write_output = .true.
312 if (write_output)
then
313 call neko_log%section(
'Writer output ')
320 select type (samp => this)
323 if (this%controllers(i)%check(time, force))
then
325 samp%output_list(i)%ptr%file_%file_type% &
326 get_next_output_fname()
327 call neko_log%message(
'File name : '//trim(output_fname))
329 write(log_buf,
'(A,I6)')
'Output number :', &
330 int(this%controllers(i)%nexecutions)
334 call samp%output_list(i)%ptr%sample(time%t)
336 call this%controllers(i)%register_execution(time)
340 call neko_error(
'Invalid output_controller output list')
344 sample_end_time = mpi_wtime()
346 sample_time = sample_end_time - sample_start_time
347 if (write_output)
then
348 write(log_buf,
'(A16,1x,F12.6,A,F9.6)')
'Writing at time:', time%t, &
349 ' Output time (s): ', sample_time
362 character(len=LOG_SIZE) :: log_buf
363 character(len=1024) :: output_fname
364 integer :: i, nexecutions
365 logical :: file_exists
368 call this%controllers(i)%set_counter(time)
371 if (this%controllers(i)%nsteps .eq. 0)
then
372 nexecutions = this%controllers(i)%nexecutions
373 call this%output_list(i)%ptr%set_counter(-1)
374 call this%output_list(i)%ptr%set_start_counter(nexecutions)
382 if (this%controllers(i)%never) cycle
383 file_exists = .false.
385 this%output_list(i)%ptr%file_%file_type%get_next_output_fname()
387 inquire(
file = trim(output_fname), exist = file_exists)
389 if (file_exists)
then
390 write(log_buf,
'(A,A)')
'Overwriting from: ', trim(output_fname)
401 integer,
intent(in) :: counter
405 this%controllers(i)%nexecutions = counter
406 call this%output_list(i)%ptr%set_counter(counter)
407 call this%output_list(i)%ptr%set_start_counter(counter)
425 t = min(t, this%controllers(i)%time_to_next(time))
integer, public pe_rank
MPI rank.
type(mpi_comm), public neko_comm
MPI communicator.
Module for file I/O operations.
type(log_t), public neko_log
Global log stream.
integer, parameter, public log_size
integer, parameter, public dp
Implements output_controller_t
subroutine output_controller_execute(this, time, ifforce)
Query each of the controllers whether it is time to write, and if so, do so for the corresponding out...
subroutine output_controller_init(this, time_end, size, time_start, write_at_start)
Constructor.
subroutine output_controller_free(this)
Destructor.
subroutine output_controller_add(this, out, write_par, write_control, start_time, write_at_start)
Add an output out to the controller.
pure real(kind=dp) function output_controller_time_to_next(this, time)
The time until the next scheduled write that the time step should land on, the smallest over all outp...
subroutine output_controller_set_counter(this, time)
Set write counter based on time (after restart)
subroutine output_controller_set_write_count(this, counter)
Set write counter (after restart) explicitly.
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.
Contains the time_based_controller_t type.
Module with things related to the simulation time.
Interface for NEKTON fld files.
Wrapper around an output_t pointer.
Abstract type defining an output type.
Centralized controller for a list of outputs.
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.