Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
scalar_sgs_stats_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!
33!
36 use num_types, only : rp, dp, sp
37 use json_module, only : json_file
39 use registry, only : neko_registry
40 use time_state, only : time_state_t
41 use field, only : field_t
44 use case, only : case_t
45 use coefs, only : coef_t
47 use logger, only : log_size, neko_log
50 use comm, only : neko_comm
51 use mpi_f08, only : mpi_wtime, mpi_barrier
52 implicit none
53 private
54
63 type(scalar_sgs_stats_output_t) :: stats_output
65 real(kind=dp) :: start_time
66 real(kind=dp) :: time
68 character(len=:), allocatable :: base_filename
69
70 contains
71 generic :: init_from_components => &
72 init_from_components_alphat, &
73 init_from_components_nut
75 procedure, pass(this) :: init => scalar_sgs_stats_simcomp_init_from_json
77 procedure, pass(this) :: init_from_components_alphat => &
80 procedure, pass(this) :: init_from_components_nut => &
83 procedure, pass(this) :: free => scalar_sgs_stats_simcomp_free
85 procedure, pass(this) :: compute_ => scalar_sgs_stats_simcomp_compute
87 procedure, pass(this) :: output_ => scalar_sgs_stats_simcomp_compute
89 procedure, pass(this) :: restart_ => scalar_sgs_stats_simcomp_restart
91
92contains
93
97 subroutine scalar_sgs_stats_simcomp_init_from_json(this, json, case)
98 class(scalar_sgs_stats_simcomp_t), target, intent(inout) :: this
99 type(json_file), intent(inout) :: json
100 class(case_t), intent(inout), target :: case
101 type(json_file) :: json_subdict
102 character(len=:), allocatable :: filename
103 character(len=NEKO_VARNAME_LEN), allocatable :: fields(:)
104 character(len=:), allocatable :: hom_dir
105 character(len=:), allocatable :: sname
106 character(len=:), allocatable :: name
107 real(kind=dp) :: start_time
108 type(coef_t), pointer :: coef
109 character(len=:), allocatable :: alphat_field, nut_field
110 real(kind=rp) :: pr_turb
111 logical :: nut_dependency
112
113 call json_get_or_default(json, 'field', &
114 sname, 's')
115 call json_get_or_default(json, "name", &
116 name, "scalar_sgs_stats_" // trim(sname))
117
118 call this%init_base(json, case)
119 call json_get_or_default(json, 'avg_direction', &
120 hom_dir, 'none')
121 call json_get_or_lookup_or_default(json, 'start_time', &
122 start_time, 0.0_dp)
123
124 call json_get(json, 'alphat', json_subdict)
125 call json_get(json_subdict, 'nut_dependency', nut_dependency)
126 if (nut_dependency) then
127 call json_get_or_lookup(json_subdict, 'Pr_t', pr_turb)
128 call json_get(json_subdict, 'nut_field', nut_field)
129 else
130 call json_get(json_subdict, 'alphat_field', alphat_field)
131 end if
132
133 coef => case%fluid%c_Xh
134 this%name = name
135
136 if (json%valid_path("output_filename")) then
137 call json_get(json, "output_filename", filename)
138 if (nut_dependency) then
139 call this%init_from_components(name, sname, coef, &
140 start_time, hom_dir, nut_field, pr_turb, filename)
141 else
142 call this%init_from_components(name, sname, coef, &
143 start_time, hom_dir, alphat_field, filename)
144 end if
145 else
146 if (nut_dependency) then
147 call this%init_from_components(name, sname, coef, &
148 start_time, hom_dir, nut_field, pr_turb, &
149 "scalar_sgs_stats_"//trim(sname))
150 else
151 call this%init_from_components(name, sname, coef, &
152 start_time, hom_dir, alphat_field, &
153 "scalar_sgs_stats_"//trim(sname))
154 end if
155 end if
156
158
167 name, sname, coef, start_time, hom_dir, alphat_field, fname)
168 class(scalar_sgs_stats_simcomp_t), target, intent(inout) :: this
169 character(len=*), intent(in) :: name
170 character(len=*), intent(in) :: sname
171 character(len=*), intent(in) :: hom_dir
172 real(kind=dp), intent(in) :: start_time
173 type(coef_t), intent(in), target :: coef
174 character(len=*), intent(in) :: alphat_field
175 character(len=*), intent(in) :: fname
176 character(len=NEKO_FNAME_LEN) :: stats_fname
177 character(len=LOG_SIZE) :: log_buf
178 character(len=5) :: prefix
179
180 call neko_log%section('Scalar SGS stats')
181 write(log_buf, '(A,A)') 'Scalar field: ', trim(sname)
182 call neko_log%message(log_buf)
183 write(log_buf, '(A,A)') 'Eddy diffusivity field: ', trim(alphat_field)
184 call neko_log%message(log_buf)
185 write(log_buf, '(A,E15.7)') 'Start time: ', start_time
186 call neko_log%message(log_buf)
187 write(log_buf, '(A,A)') 'Averaging in direction: ', trim(hom_dir)
188 call neko_log%message(log_buf)
189
190 call this%stats%init(coef, sname, alphat_field)
191
192 this%name = name
193 this%start_time = start_time
194 this%time = start_time
195 this%base_filename = fname
196 stats_fname = trim(fname) // "0"
197
198 call this%stats_output%init(this%stats, this%start_time, &
199 hom_dir = hom_dir, name = stats_fname, &
200 path = this%case%output_directory)
201
202 ! Statistics are averaged over the interval between two writes, so
203 ! writing at the very start of the averaging would only produce an
204 ! empty file. The schedule is anchored to the start of the averaging.
205 call this%case%output_controller%add(this%stats_output, &
206 this%output_controller%control_value, &
207 this%output_controller%control_mode, &
208 start_time = max(this%start_time, this%case%time%start_time), &
209 write_at_start = .false.)
210
211 call neko_log%end_section()
212
214
225 name, sname, coef, start_time, hom_dir, nut_field, pr_turb, fname)
226 class(scalar_sgs_stats_simcomp_t), target, intent(inout) :: this
227 character(len=*), intent(in) :: name
228 character(len=*), intent(in) :: sname
229 character(len=*), intent(in) :: hom_dir
230 real(kind=dp), intent(in) :: start_time
231 type(coef_t), intent(in), target :: coef
232 character(len=*), intent(in) :: nut_field
233 real(kind=rp), intent(in) :: pr_turb
234 character(len=*), intent(in), optional :: fname
235 character(len=NEKO_FNAME_LEN) :: stats_fname
236 character(len=LOG_SIZE) :: log_buf
237 character(len=5) :: prefix
238
239 call neko_log%section('scalar stats')
240 write(log_buf, '(A,A)') 'Scalar field: ', trim(sname)
241 call neko_log%message(log_buf)
242 write(log_buf, '(A,A)') 'Eddy viscosity field: ', trim(nut_field)
243 call neko_log%message(log_buf)
244 write(log_buf, '(A,E15.7)') 'Turbulent Prandtl number: ', pr_turb
245 call neko_log%message(log_buf)
246 write(log_buf, '(A,E15.7)') 'Start time: ', start_time
247 call neko_log%message(log_buf)
248 write(log_buf, '(A,A)') 'Averaging in direction: ', trim(hom_dir)
249 call neko_log%message(log_buf)
250
251
252 call this%stats%init(coef, sname, nut_field, pr_turb)
253
254 this%name = name
255 this%start_time = start_time
256 this%time = start_time
257 this%base_filename = fname
258 stats_fname = trim(fname) // "0"
259
260 call this%stats_output%init(this%stats, this%start_time, &
261 hom_dir = hom_dir, name = stats_fname, &
262 path = this%case%output_directory)
263
264 ! Statistics are averaged over the interval between two writes, so
265 ! writing at the very start of the averaging would only produce an
266 ! empty file. The schedule is anchored to the start of the averaging.
267 call this%case%output_controller%add(this%stats_output, &
268 this%output_controller%control_value, &
269 this%output_controller%control_mode, &
270 start_time = max(this%start_time, this%case%time%start_time), &
271 write_at_start = .false.)
272
273 call neko_log%end_section()
274
276
279 class(scalar_sgs_stats_simcomp_t), intent(inout) :: this
280 call this%free_base()
281 call this%stats%free()
282 call this%stats_output%free()
283 end subroutine scalar_sgs_stats_simcomp_free
284
285 subroutine scalar_sgs_stats_simcomp_restart(this, time)
286 class(scalar_sgs_stats_simcomp_t), intent(inout) :: this
287 type(time_state_t), intent(in) :: time
288 character(len=NEKO_FNAME_LEN) :: fname
289 character(len=5) :: prefix, suffix
290 real(kind=dp) :: t
291
292 t = time%t
293 if (t .gt. this%time) this%time = t
294
295 fname = this%stats_output%file_%get_base_fname()
296 write (prefix, '(I0)') &
297 this%stats_output%file_%file_type%get_start_counter()
298 call filename_suffix(fname, suffix)
299 fname = trim(this%case%output_directory) // &
300 trim(this%base_filename) // trim(prefix) // "." // trim(suffix)
301 call this%stats_output%init_base(fname)
302
304
307 subroutine scalar_sgs_stats_simcomp_compute(this, time)
308 class(scalar_sgs_stats_simcomp_t), intent(inout) :: this
309 type(time_state_t), intent(in) :: time
310 real(kind=rp) :: delta_t
311 real(kind=dp) :: sample_start_time, sample_time, t
312 character(len=LOG_SIZE) :: log_buf
313 integer :: ierr
314
315 if (time%start_time .gt. this%start_time) then
316 write(log_buf, '(A)') 'Simulation start time is later than the ' &
317 // 'scalar stats start time.'
318 call neko_log%warning(log_buf)
319 write(log_buf, '(A,E15.7)') 'Simulation start time:', time%start_time
320 call neko_log%warning(log_buf)
321 write(log_buf, '(A,E15.7)') 'scalar stats start time:', this%start_time
322 call neko_log%warning(log_buf)
323 write(log_buf, '(A)') 'Assigning the statistics start time to ' &
324 // 'the simulation start time.'
325 call neko_log%warning(log_buf)
326 this%start_time = time%start_time
327 this%time = time%start_time
328 end if
329
330 t = time%t
331
332 if (t .ge. this%start_time) then
333 delta_t = real(t - this%time, kind=rp) !This is only a real number
334
335 call mpi_barrier(neko_comm, ierr)
336
337 sample_start_time = mpi_wtime()
338
339 call this%stats%update(delta_t)
340 call mpi_barrier(neko_comm, ierr)
341 this%time = t
342
343 sample_time = mpi_wtime() - sample_start_time
344
345 call neko_log%section('scalar stats')
346 write(log_buf, '(A,E15.7)') 'Sampling at time:', t
347 call neko_log%message(log_buf)
348 write(log_buf, '(A33,E15.7)') 'Simulation time since last sample:', &
349 delta_t
350 call neko_log%message(log_buf)
351 write(log_buf, '(A,E15.7)') 'Sampling time (s):', sample_time
352 call neko_log%message(log_buf)
353 call neko_log%end_section()
354 end if
355
357
double real
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.
Defines a simulation case.
Definition case.f90:34
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
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:91
integer, parameter, public log_size
Definition log.f90:46
integer, parameter, public dp
Definition num_types.f90:10
integer, parameter, public sp
Definition num_types.f90:8
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines a registry for storing solution fields.
Definition registry.f90:34
type(registry_t), target, public neko_registry
Global field registry.
Definition registry.f90:158
Implements scalar_sgs_stats_ouput_t.
Implements the scalar_sgs_stats_simcomp_t type.
subroutine scalar_sgs_stats_simcomp_init_from_components_alphat(this, name, sname, coef, start_time, hom_dir, alphat_field, fname)
Actual constructor using directly the alphat field.
subroutine scalar_sgs_stats_simcomp_init_from_components_nut(this, name, sname, coef, start_time, hom_dir, nut_field, pr_turb, fname)
Actual constructor using directly the nut field and the turbulent Prandtl number.
subroutine scalar_sgs_stats_simcomp_free(this)
Destructor.
subroutine scalar_sgs_stats_simcomp_compute(this, time)
scalar_sgs_stats, called depending on compute_control and compute_value
subroutine scalar_sgs_stats_simcomp_init_from_json(this, json, case)
Constructor from json.
subroutine scalar_sgs_stats_simcomp_restart(this, time)
Computes the subgrid-scale contributions for the scalar fluxes. We use the Reynolds decomposition for...
Simulation components are objects that encapsulate functionality that can be fit to a particular comp...
subroutine restart_(this, time)
Dummy restart function.
subroutine compute_(this, time)
Dummy compute function.
Defines a container for all statistics.
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
integer, parameter, public neko_fname_len
Definition utils.f90:42
subroutine, public filename_suffix(fname, suffix)
Extract a filename's suffix.
Definition utils.f90:161
integer, parameter, public neko_varname_len
Definition utils.f90:43
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:135
Defines an output for the sgs statistics for scalar computed using the scalar_sgs_stats_t object.
A simulation component that computes the subgrid-scale contributions to the Reynolds stresses in LES.
Base abstract class for simulation components.
A struct that contains all info about the time, expand as needed.
#define max(a, b)
Definition tensor.cu:40