Loading [MathJax]/extensions/tex2jax.js
Neko 0.9.99
A portable framework for high-order spectral element flow simulations
All Classes Namespaces Files Functions Variables Typedefs Enumerator Macros Pages
output_controller.f90
Go to the documentation of this file.
1! Copyright (c) 2020-2023, 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 output, only: output_t, output_ptr_t
36 use fld_file, only: fld_file_t
37 use comm
38 use logger, only : neko_log, log_size
39 use utils, only : neko_error
41 use num_types, only : rp, dp
43 implicit none
44 private
45
46
51 type, public :: output_controller_t
53 type(output_ptr_t), allocatable :: output_list(:)
55 type(time_based_controller_t), allocatable :: controllers(:)
57 integer :: n
59 integer :: size
61 real(kind=rp) :: time_end
62 contains
64 procedure, pass(this) :: init => output_controller_init
66 procedure, pass(this) :: free => output_controller_free
68 procedure, pass(this) :: add => output_controller_add
70 procedure, pass(this) :: execute => output_controller_execute
72 procedure, pass(this) :: set_counter => output_controller_set_counter
73 end type output_controller_t
74
75contains
76
81 subroutine output_controller_init(this, time_end, size)
82 class(output_controller_t), intent(inout) :: this
83 integer, intent(in), optional :: size
84 real(kind=rp), intent(in) :: time_end
85 character(len=LOG_SIZE) :: log_buf
86 integer :: n, i
87
88 call this%free()
89
90 if (present(size)) then
91 n = size
92 else
93 n = 1
94 end if
95
96 allocate(this%output_list(n))
97 allocate(this%controllers(n))
98
99 do i = 1, n
100 this%output_list(i)%ptr => null()
101 end do
102
103 this%size = n
104 this%n = 0
105 this%time_end = time_end
106
107 end subroutine output_controller_init
108
110 subroutine output_controller_free(this)
111 class(output_controller_t), intent(inout) :: this
112
113 if (allocated(this%output_list)) then
114 deallocate(this%output_list)
115 end if
116 if (allocated(this%controllers)) then
117 deallocate(this%controllers)
118 end if
119
120 this%n = 0
121 this%size = 0
122
123 end subroutine output_controller_free
124
132 subroutine output_controller_add(this, out, write_par, write_control, &
133 start_time)
134 class(output_controller_t), intent(inout) :: this
135 class(output_t), intent(inout), target :: out
136 real(kind=rp), intent(in) :: write_par
137 character(len=*), intent(in) :: write_control
138 real(kind=rp), optional, intent(in) :: start_time
139 type(output_ptr_t), allocatable :: tmp(:)
140 type(time_based_controller_t), allocatable :: tmp_ctrl(:)
141 character(len=LOG_SIZE) :: log_buf
142 integer :: n
143 class(*), pointer :: ft
144
145 if (this%n .ge. this%size) then
146 allocate(tmp(this%size * 2))
147 tmp(1:this%size) = this%output_list
148 call move_alloc(tmp, this%output_list)
149
150 allocate(tmp_ctrl(this%size * 2))
151 tmp_ctrl(1:this%size) = this%controllers
152 call move_alloc(tmp_ctrl, this%controllers)
153
154 this%size = this%size * 2
155 end if
156
157 this%n = this%n + 1
158 n = this%n
159 this%output_list(this%n)%ptr => out
160
161 if (trim(write_control) .eq. "org") then
162 this%controllers(n) = this%controllers(1)
163 else
164 call this%controllers(n)%init(this%time_end, write_control, write_par, &
165 start_time)
166 end if
167
168 ! The code below only prints to console
169 call neko_log%section('Adding write output')
170 call neko_log%message('File name : '// &
171 trim(this%output_list(this%n)%ptr%file_%file_type%fname))
172 call neko_log%message('Write control : '//trim(write_control))
173
174 ! Show the output precision if we are outputting an fld file
175 select type (ft => out%file_%file_type)
176 type is (fld_file_t)
177 if (ft%dp_precision) then
178 call neko_log%message('Output precision : double')
179 else
180 call neko_log%message('Output precision : single')
181 end if
182 end select
183
184 if (trim(write_control) .eq. 'simulationtime') then
185 write(log_buf, '(A,ES13.6)') 'Writes per time unit (Freq.): ', &
186 this%controllers(n)%frequency
187 call neko_log%message(log_buf)
188 write(log_buf, '(A,ES13.6)') 'Time between writes: ', &
189 this%controllers(n)%time_interval
190 call neko_log%message(log_buf)
191 else if (trim(write_control) .eq. 'nsamples') then
192 write(log_buf, '(A,I13)') 'Total samples: ', int(write_par)
193 call neko_log%message(log_buf)
194 write(log_buf, '(A,ES13.6)') 'Writes per time unit (Freq.): ', &
195 this%controllers(n)%frequency
196 call neko_log%message(log_buf)
197 write(log_buf, '(A,ES13.6)') 'Time between writes: ', &
198 this%controllers(n)%time_interval
199 call neko_log%message(log_buf)
200 else if (trim(write_control) .eq. 'tsteps') then
201 write(log_buf, '(A,I13)') 'Time step interval: ', int(write_par)
202 call neko_log%message(log_buf)
203 else if (trim(write_control) .eq. 'org') then
204 write(log_buf, '(A)') &
205 'Write control not set, defaulting to first output settings'
206 call neko_log%message(log_buf)
207 end if
208
209 call neko_log%end_section()
210 end subroutine output_controller_add
211
217 subroutine output_controller_execute(this, t, tstep, ifforce)
218 class(output_controller_t), intent(inout) :: this
219 real(kind=rp), intent(in) :: t
220 integer, intent(in) :: tstep
221 logical, intent(in), optional :: ifforce
222 real(kind=dp) :: sample_start_time, sample_end_time
223 real(kind=dp) :: sample_time
224 character(len=LOG_SIZE) :: log_buf
225 integer :: i, ierr
226 logical :: force, write_output, write_output_test
227
228 if (present(ifforce)) then
229 force = ifforce
230 else
231 force = .false.
232 end if
233
234 call profiler_start_region('Output controller', 22)
235 !Do we need this Barrier?
236 call mpi_barrier(neko_comm, ierr)
237 sample_start_time = mpi_wtime()
238
239 write_output = .false.
240 ! Determine if at least one output needs to be written
241 ! We should not need this extra select block, and it works great
242 ! without it for GNU, Intel and NEC, but breaks horribly on Cray
243 ! (>11.0.x) when using high opt. levels.
244 select type (samp => this)
245 type is (output_controller_t)
246 do i = 1, samp%n
247 if (this%controllers(i)%check(t, tstep, force)) then
248 write_output = .true.
249 exit
250 end if
251 end do
252 end select
253
254 if (write_output) then
255 call neko_log%section('Writer output ')
256 end if
257
258 ! Loop through the outputs and write if necessary.
259 ! We should not need this extra select block, and it works great
260 ! without it for GNU, Intel and NEC, but breaks horribly on Cray
261 ! (>11.0.x) when using high opt. levels.
262 select type (samp => this)
263 type is (output_controller_t)
264 do i = 1, this%n
265 if (this%controllers(i)%check(t, tstep, force)) then
266 call neko_log%message('File name : '// &
267 trim(samp%output_list(i)%ptr%file_%file_type%fname))
268
269 write(log_buf, '(A,I6)') 'Output number :', &
270 int(this%controllers(i)%nexecutions)
271 call neko_log%message(log_buf)
272
273 call samp%output_list(i)%ptr%sample(t)
274
275 call this%controllers(i)%register_execution()
276 end if
277 end do
278 class default
279 call neko_error('Invalid output_controller output list')
280 end select
281
282 call mpi_barrier(neko_comm, ierr)
283 sample_end_time = mpi_wtime()
284
285 sample_time = sample_end_time - sample_start_time
286 if (write_output) then
287 write(log_buf, '(A16,1x,F12.6,A,F9.6)') 'Writing at time:', t, &
288 ' Output time (s): ', sample_time
289 call neko_log%message(log_buf)
290 call neko_log%end_section()
291 end if
292 call profiler_end_region('Output controller', 22)
293 end subroutine output_controller_execute
294
298 class(output_controller_t), intent(inout) :: this
299 real(kind=rp), intent(in) :: t
300 integer :: i, nexecutions
301
302
303 do i = 1, this%n
304 if (this%controllers(i)%nsteps .eq. 0) then
305 nexecutions = int(t / this%controllers(i)%time_interval) + 1
306 this%controllers(i)%nexecutions = nexecutions
307
308 call this%output_list(i)%ptr%set_counter(nexecutions)
309 call this%output_list(i)%ptr%set_start_counter(nexecutions)
310 end if
311 end do
312
313 end subroutine output_controller_set_counter
314
317 subroutine output_controller_set_write_count(this, counter)
318 class(output_controller_t), intent(inout) :: this
319 integer, intent(in) :: counter
320 integer :: i
321
322 do i = 1, this%n
323 this%controllers(i)%nexecutions = counter
324 call this%output_list(i)%ptr%set_counter(counter)
325 call this%output_list(i)%ptr%set_start_counter(counter)
326 end do
327
329
330
331end module output_controller
Definition comm.F90:1
type(mpi_comm) neko_comm
MPI communicator.
Definition comm.F90:38
NEKTON fld file format.
Definition fld_file.f90:35
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:65
integer, parameter, public log_size
Definition log.f90:42
integer, parameter, public dp
Definition num_types.f90:9
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Implements output_controller_t
subroutine output_controller_free(this)
Destructor.
subroutine output_controller_init(this, time_end, size)
Constructor.
subroutine output_controller_set_counter(this, t)
Set write counter based on time (after restart)
subroutine output_controller_add(this, out, write_par, write_control, start_time)
Add an output out to the controller.
subroutine output_controller_execute(this, t, tstep, ifforce)
Query each of the controllers whether it is time to write, and if so, do so for the corresponding out...
subroutine output_controller_set_write_count(this, counter)
Set write counter (after restart) explicitly.
Defines an output.
Definition output.f90:34
Profiling interface.
Definition profiler.F90:34
subroutine, public profiler_start_region(name, region_id)
Started a named (name) profiler region.
Definition profiler.F90:78
subroutine, public profiler_end_region(name, region_id)
End the most recently started profiler region.
Definition profiler.F90:109
Contains the time_based_controller_t type.
Utilities.
Definition utils.f90:35
Interface for NEKTON fld files.
Definition fld_file.f90:64
Wrapper around an output_t pointer.
Definition output.f90:51
Abstract type defining an output type.
Definition output.f90:41
Centralized controller for a list of outputs.
A utility type for determening whether an action should be executed based on the current time value....