Neko 1.99.7
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
flow_ic.f90
Go to the documentation of this file.
1! Copyright (c) 2021-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!
34module flow_ic
35 use num_types, only : rp
36 use logger, only : neko_log, log_size
37 use gather_scatter, only : gs_t, gs_op_add
43 use field, only : field_t
44 use utils, only : neko_error, filename_chsuffix, &
46 use coefs, only : coef_t
47 use math, only : col2, cfill, cfill_mask, abscmp
48 use device_math, only : device_col2
50 use json_module, only : json_file
54 use point_zone, only : point_zone_t
57 use fld_file, only : fld_file_t
58 use file, only : file_t
61 use space, only : space_t, gll
62 use field_list, only : field_list_t
63 use operators, only : rotate_cyc
65 implicit none
66 private
67
71 end interface set_flow_ic
72
74
75contains
76
78 subroutine set_flow_ic_int(u, v, w, p, coef, gs, type, params)
79 type(field_t), intent(inout) :: u
80 type(field_t), intent(inout) :: v
81 type(field_t), intent(inout) :: w
82 type(field_t), intent(inout) :: p
83 type(coef_t), intent(in) :: coef
84 type(gs_t), intent(inout) :: gs
85 character(len=*) :: type
86 type(json_file), intent(inout) :: params
87 real(kind=rp) :: delta
88 real(kind=rp), allocatable :: uinf(:)
89 real(kind=rp), allocatable :: zone_value(:)
90 character(len=:), allocatable :: read_str
91 character(len=NEKO_EXPR_LEN), allocatable :: expr_str(:)
92
93
94 !
95 ! Uniform (Uinf, Vinf, Winf)
96 !
97 if (trim(type) .eq. 'uniform') then
98
99 call json_get_or_lookup(params, 'value', uinf)
100 call set_flow_ic_uniform(u, v, w, uinf)
101
102 !
103 ! One mathematical expression per velocity component
104 !
105 else if (trim(type) .eq. 'expression') then
106
107 call json_get(params, 'value', expr_str, filler = '')
108 call set_flow_ic_expression(u, v, w, expr_str)
109 if (allocated(expr_str)) deallocate(expr_str)
110
111 !
112 ! Blasius boundary layer
113 !
114 else if (trim(type) .eq. 'blasius') then
115
116 call json_get_or_lookup(params, 'delta', delta)
117 call json_get(params, 'approximation', read_str)
118 call json_get_or_lookup(params, 'freestream_velocity', uinf)
119
120 call set_flow_ic_blasius(u, v, w, delta, uinf, read_str)
121
122 !
123 ! Point zone initial condition
124 !
125 else if (trim(type) .eq. 'point_zone') then
126
127 call json_get_or_lookup(params, 'base_value', uinf)
128 call json_get(params, 'zone_name', read_str)
129 call json_get_or_lookup(params, 'zone_value', zone_value)
130
131 call set_flow_ic_point_zone(u, v, w, uinf, read_str, zone_value)
132
133 !
134 ! Field initial condition (from fld file)
135 !
136 else if (trim(type) .eq. 'field') then
137
138 block
139 character(len=NEKO_FNAME_LEN) :: fname, mesh_fname
140 logical :: interpolate
141 type(json_file) :: interp_subdict
142
143 call json_get(params, 'file_name', read_str)
144 fname = trim(read_str)
145
146 call json_get_or_default(params, 'interpolate', interpolate, &
147 .false.)
148
149 call json_get_or_default(params, 'mesh_file_name', read_str, "none")
150 mesh_fname = trim(read_str)
151
152 call json_get_subdict_or_empty(params, "interpolation", &
153 interp_subdict)
154 call set_flow_ic_fld(u, v, w, p, fname, interpolate, &
155 mesh_fname, interp_subdict)
156 end block
157
158 else
159 call neko_error('Invalid initial condition')
160 end if
161
162 call set_flow_ic_common(u, v, w, p, coef, gs)
163
164 end subroutine set_flow_ic_int
165
167 subroutine set_flow_ic_usr(u, v, w, p, coef, gs, user_proc, scheme_name)
168 type(field_t), target, intent(inout) :: u
169 type(field_t), target, intent(inout) :: v
170 type(field_t), target, intent(inout) :: w
171 type(field_t), target, intent(inout) :: p
172 type(coef_t), intent(in) :: coef
173 type(gs_t), intent(inout) :: gs
174 procedure(user_initial_conditions_intf) :: user_proc
175 character(len=*), intent(in) :: scheme_name
176
177 type(field_list_t) :: fields
178
179
180 call neko_log%message("Type: user")
181
182 call fields%init(4)
183 call fields%assign_to_field(1, u)
184 call fields%assign_to_field(2, v)
185 call fields%assign_to_field(3, w)
186 call fields%assign_to_field(4, p)
187
188 call user_proc(scheme_name, fields)
189
190 call set_flow_ic_common(u, v, w, p, coef, gs)
191
192 end subroutine set_flow_ic_usr
193
196 subroutine set_compressible_flow_ic_usr(rho, u, v, w, p, coef, gs, &
197 user_proc, scheme_name)
198 type(field_t), target, intent(inout) :: rho
199 type(field_t), target, intent(inout) :: u
200 type(field_t), target, intent(inout) :: v
201 type(field_t), target, intent(inout) :: w
202 type(field_t), target, intent(inout) :: p
203 type(coef_t), intent(in) :: coef
204 type(gs_t), intent(inout) :: gs
205 procedure(user_initial_conditions_intf) :: user_proc
206 character(len=*), intent(in) :: scheme_name
207 integer :: n
208 type(field_list_t) :: fields
209
210
211 call neko_log%message("Type: user (compressible flows)")
212
213 call fields%init(5)
214 call fields%assign_to_field(1, rho)
215 call fields%assign_to_field(2, u)
216 call fields%assign_to_field(3, v)
217 call fields%assign_to_field(4, w)
218 call fields%assign_to_field(5, p)
219 call user_proc(scheme_name, fields)
220
221 call set_flow_ic_common(u, v, w, p, coef, gs)
222
223 n = u%dof%size()
224
225 if (neko_bcknd_device .eq. 1) then
226 call device_memcpy(p%x, p%x_d, n, host_to_device, sync = .false.)
227 call device_memcpy(rho%x, rho%x_d, n, host_to_device, sync = .false.)
228 end if
229
230 ! Ensure continuity across elements for initial conditions
231 ! These variables are not treated in the common constructor
232 call gs%op(p%x, p%dof%size(), gs_op_add)
233 call gs%op(rho%x, rho%dof%size(), gs_op_add)
234
235 if (neko_bcknd_device .eq. 1) then
236 call device_col2(rho%x_d, coef%mult_d, rho%dof%size())
237 call device_col2(p%x_d, coef%mult_d, p%dof%size())
238 else
239 call col2(rho%x, coef%mult, rho%dof%size())
240 call col2(p%x, coef%mult, p%dof%size())
241 end if
242
243 end subroutine set_compressible_flow_ic_usr
244
245 subroutine set_flow_ic_common(u, v, w, p, coef, gs)
246 type(field_t), intent(inout) :: u
247 type(field_t), intent(inout) :: v
248 type(field_t), intent(inout) :: w
249 type(field_t), intent(inout) :: p
250 type(coef_t), intent(in) :: coef
251 type(gs_t), intent(inout) :: gs
252 integer :: n
253
254 n = u%dof%size()
255
256 if (neko_bcknd_device .eq. 1) then
257 call u%copy_from(host_to_device, sync = .false.)
258 call v%copy_from(host_to_device, sync = .false.)
259 call w%copy_from(host_to_device, sync = .false.)
260
261 ! also copy pressure for consistency
262 call p%copy_from(host_to_device, sync = .true.)
263 end if
264
265 ! Ensure continuity across elements for initial conditions
266 call rotate_cyc(u, v, w, 1, coef)
267 call gs%op(u%x, u%dof%size(), gs_op_add)
268 call gs%op(v%x, v%dof%size(), gs_op_add)
269 call gs%op(w%x, w%dof%size(), gs_op_add)
270 call rotate_cyc(u, v, w, 0, coef)
271
272 if (neko_bcknd_device .eq. 1) then
273 call device_col2(u%x_d, coef%mult_d, u%dof%size())
274 call device_col2(v%x_d, coef%mult_d, v%dof%size())
275 call device_col2(w%x_d, coef%mult_d, w%dof%size())
276 else
277 call col2(u%x, coef%mult, u%dof%size())
278 call col2(v%x, coef%mult, v%dof%size())
279 call col2(w%x, coef%mult, w%dof%size())
280 end if
281
282 end subroutine set_flow_ic_common
283
285 subroutine set_flow_ic_uniform(u, v, w, uinf)
286 type(field_t), intent(inout) :: u
287 type(field_t), intent(inout) :: v
288 type(field_t), intent(inout) :: w
289 real(kind=rp), intent(in) :: uinf(3)
290 integer :: n, i
291 character(len=LOG_SIZE) :: log_buf
292
293 call neko_log%message("Type : uniform")
294 write (log_buf, '(A, 3(ES12.6, A))') "Value: [", &
295 (uinf(i), ", ", i = 1, 2), uinf(3), "]"
296 call neko_log%message(log_buf)
297
298 u = uinf(1)
299 v = uinf(2)
300 w = uinf(3)
301 n = u%dof%size()
302 if (neko_bcknd_device .eq. 1) then
303 call cfill(u%x, uinf(1), n)
304 call cfill(v%x, uinf(2), n)
305 call cfill(w%x, uinf(3), n)
306 end if
307
308 end subroutine set_flow_ic_uniform
309
320 subroutine set_flow_ic_expression(u, v, w, expr)
321 type(field_t), target, intent(inout) :: u
322 type(field_t), target, intent(inout) :: v
323 type(field_t), target, intent(inout) :: w
324 character(len=*), intent(in) :: expr(:)
325 character(len=1), parameter :: comp(3) = ['u', 'v', 'w']
326 type(field_t), pointer :: f
327 integer :: i, n
328
329 if (size(expr) .ne. 3) then
330 call neko_error('The expression initial condition takes exactly ' // &
331 'three expressions, one per velocity component')
332 end if
333
334 call neko_log%message("Type : expression")
335 do i = 1, 3
336 call neko_log%message(comp(i) // " : " // trim(expr(i)))
337 end do
338
339 n = u%dof%size()
340
341 do i = 1, 3
342 select case (i)
343 case (1)
344 f => u
345 case (2)
346 f => v
347 case default
348 f => w
349 end select
350
351 call expression_eval_static(expr(i), f%x, n, &
352 u%dof%x, u%dof%y, u%dof%z, 'fluid initial condition')
353 end do
354
355 nullify(f)
356
357 end subroutine set_flow_ic_expression
358
361 subroutine set_flow_ic_blasius(u, v, w, delta, uinf, type)
362 type(field_t), intent(inout) :: u
363 type(field_t), intent(inout) :: v
364 type(field_t), intent(inout) :: w
365 real(kind=rp), intent(in) :: delta
366 real(kind=rp), intent(in) :: uinf(3)
367 character(len=*), intent(in) :: type
368 procedure(blasius_profile), pointer :: bla => null()
369 integer :: i
370 character(len=LOG_SIZE) :: log_buf
371
372 call neko_log%message("Type : blasius")
373 write (log_buf, '(A,ES12.6)') "delta : ", delta
374 call neko_log%message(log_buf)
375 call neko_log%message("Approximation : " // trim(type))
376 write (log_buf, '(A,"[",2(ES12.6,","),ES12.6,"]")') "Value : ", &
377 uinf(1), uinf(2), uinf(3)
378 call neko_log%message(log_buf)
379
380 select case (trim(type))
381 case ('linear')
382 bla => blasius_linear
383 case ('quadratic')
384 bla => blasius_quadratic
385 case ('cubic')
386 bla => blasius_cubic
387 case ('quartic')
388 bla => blasius_quartic
389 case ('sin')
390 bla => blasius_sin
391 case ('tanh')
392 bla => blasius_tanh
393 case default
394 call neko_error('Invalid Blasius approximation')
395 end select
396
397 if ((uinf(1) .gt. 0.0_rp) .and. abscmp(uinf(2), 0.0_rp) &
398 .and. abscmp(uinf(3), 0.0_rp)) then
399 do i = 1, u%dof%size()
400 u%x(i,1,1,1) = bla(u%dof%z(i,1,1,1), delta, uinf(1))
401 v%x(i,1,1,1) = 0.0_rp
402 w%x(i,1,1,1) = 0.0_rp
403 end do
404 else if (abscmp(uinf(1), 0.0_rp) .and. (uinf(2) .gt. 0.0_rp) &
405 .and. abscmp(uinf(3), 0.0_rp)) then
406 do i = 1, u%dof%size()
407 u%x(i,1,1,1) = 0.0_rp
408 v%x(i,1,1,1) = bla(u%dof%x(i,1,1,1), delta, uinf(2))
409 w%x(i,1,1,1) = 0.0_rp
410 end do
411 else if (abscmp(uinf(1), 0.0_rp) .and. abscmp(uinf(2), 0.0_rp) &
412 .and. (uinf(3) .gt. 0.0_rp)) then
413 do i = 1, u%dof%size()
414 u%x(i,1,1,1) = 0.0_rp
415 v%x(i,1,1,1) = 0.0_rp
416 w%x(i,1,1,1) = bla(u%dof%y(i,1,1,1), delta, uinf(3))
417 end do
418 end if
419
420 end subroutine set_flow_ic_blasius
421
431 subroutine set_flow_ic_point_zone(u, v, w, base_value, zone_name, zone_value)
432 type(field_t), intent(inout) :: u
433 type(field_t), intent(inout) :: v
434 type(field_t), intent(inout) :: w
435 real(kind=rp), intent(in), dimension(3) :: base_value
436 character(len=*), intent(in) :: zone_name
437 real(kind=rp), intent(in) :: zone_value(:)
438 character(len=LOG_SIZE) :: log_buf
439
440 ! Internal variables
441 class(point_zone_t), pointer :: zone
442 integer :: size
443
444 call neko_log%message("Type : point_zone")
445 write (log_buf, '(A,ES12.6)') "Base value : ", base_value
446 call neko_log%message(log_buf)
447 call neko_log%message("Zone name : " // trim(zone_name))
448 write (log_buf, '(A,"[",2(ES12.6,","),ES12.6," ]")') "Value : ", &
449 zone_value(1), zone_value(2), zone_value(3)
450 call neko_log%message(log_buf)
451
452 call set_flow_ic_uniform(u, v, w, base_value)
453 size = u%dof%size()
454
455 zone => neko_point_zone_registry%get_point_zone(trim(zone_name))
456
457 call cfill_mask(u%x, zone_value(1), size, zone%mask%get(), zone%size)
458 call cfill_mask(v%x, zone_value(2), size, zone%mask%get(), zone%size)
459 call cfill_mask(w%x, zone_value(3), size, zone%mask%get(), zone%size)
460
461 end subroutine set_flow_ic_point_zone
462
478 subroutine set_flow_ic_fld(u, v, w, p, file_name, &
479 interpolate, mesh_file_name, global_interp_subdict)
480 type(field_t), target, intent(inout) :: u
481 type(field_t), target, intent(inout) :: v
482 type(field_t), target, intent(inout) :: w
483 type(field_t), target, intent(inout) :: p
484 character(len=*), intent(inout) :: file_name
485 logical, intent(in) :: interpolate
486 character(len=*), intent(inout) :: mesh_file_name
487 type(json_file), intent(inout) :: global_interp_subdict
488
489 type(field_t), pointer :: us, vs, ws, ps
490
491 us => u
492 vs => v
493 ws => w
494 ps => p
495
496 call import_fields(file_name, global_interp_subdict, mesh_file_name, &
497 u = us, v = vs, w = ws, p = ps, &
498 interpolate = interpolate)
499
500 nullify(us, vs, ws, ps)
501
502 ! If we are on GPU we need to move (u,v,w) and p back to the host
503 ! since set_flow_ic_common copies it again to the device.
504 call u%copy_from(device_to_host, sync = .false.)
505 call v%copy_from(device_to_host, sync = .false.)
506 call w%copy_from(device_to_host, sync = .false.)
507 call p%copy_from(device_to_host, sync = .true.)
508
509 end subroutine set_flow_ic_fld
510
511end module flow_ic
Copy data between host and device (or device and device)
Definition device.F90:72
Synchronize a device or stream.
Definition device.F90:119
Abstract interface for computing a Blasius flow profile.
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.
Apply cyclic boundary condition to a vector field.
Abstract interface for user defined initial conditions.
Definition user_intf.f90:70
Coefficients.
Definition coef.f90:34
subroutine, public device_col2(a_d, b_d, n, strm)
Vector multiplication .
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
integer, parameter, public device_to_host
Definition device.F90:48
Evaluation of mathematical expressions given as strings in the case file.
integer, parameter, public neko_expr_len
Maximum length of an expression string read from the case file.
subroutine, public expression_eval_static(str, res, n, x, y, z, usage)
Compile an expression and evaluate it in a set of points, in a context where there is no time state.
Defines a field.
Definition field.f90:34
Module for file I/O operations.
Definition file.f90:34
Simple module to handle fld file series. Provides an interface to the different fields sotred in a fl...
NEKTON fld file format.
Definition fld_file.f90:35
Initial flow condition.
Definition flow_ic.f90:34
subroutine set_flow_ic_usr(u, v, w, p, coef, gs, user_proc, scheme_name)
Set intial flow condition (user defined)
Definition flow_ic.f90:168
subroutine, public set_flow_ic_fld(u, v, w, p, file_name, interpolate, mesh_file_name, global_interp_subdict)
Set the initial condition of the flow based on a field. @detail The fields are read from an fld file....
Definition flow_ic.f90:480
subroutine set_flow_ic_point_zone(u, v, w, base_value, zone_name, zone_value)
Set the initial condition of the flow based on a point zone.
Definition flow_ic.f90:432
subroutine set_flow_ic_int(u, v, w, p, coef, gs, type, params)
Set initial flow condition (builtin)
Definition flow_ic.f90:79
subroutine set_compressible_flow_ic_usr(rho, u, v, w, p, coef, gs, user_proc, scheme_name)
Set intial flow condition (user defined) for compressible flows.
Definition flow_ic.f90:198
subroutine set_flow_ic_uniform(u, v, w, uinf)
Uniform initial condition.
Definition flow_ic.f90:286
subroutine set_flow_ic_common(u, v, w, p, coef, gs)
Definition flow_ic.f90:246
subroutine set_flow_ic_expression(u, v, w, expr)
Set the initial condition from one mathematical expression per velocity component.
Definition flow_ic.f90:321
subroutine set_flow_ic_blasius(u, v, w, delta, uinf, type)
Set a Blasius profile as initial condition.
Definition flow_ic.f90:362
Defines a flow profile.
real(kind=rp) function, public blasius_quadratic(y, delta, u)
Quadratic approximate Blasius Profile .
real(kind=rp) function, public blasius_quartic(y, delta, u)
Quartic approximate Blasius Profile .
real(kind=rp) function, public blasius_sin(y, delta, u)
Sinusoidal approximate Blasius Profile .
real(kind=rp) function, public blasius_cubic(y, delta, u)
Cubic approximate Blasius Profile .
real(kind=rp) function, public blasius_tanh(y, delta, u)
Hyperbolic tangent approximate Blasius Profile from O. Savas (2012) where is the 99 percent thickne...
real(kind=rp) function, public blasius_linear(y, delta, u)
Linear approximate Blasius profile .
Gather-scatter.
Implements global_interpolation given a dofmap.
Importation of fields from fld files.
Routines to interpolate between different spaces.
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.
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:80
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
subroutine, public cfill(a, c, n)
Set all elements to a constant c .
Definition math.f90:597
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:1046
subroutine, public cfill_mask(a, c, n, mask, n_mask)
Fill a constant to a masked vector. .
Definition math.f90:488
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Operators.
Definition operators.f90:34
type(point_zone_registry_t), target, public neko_point_zone_registry
Global point_zone registry.
Defines a function space.
Definition space.f90:34
integer, parameter, public gll
Definition space.f90:50
Interfaces for user interaction with NEKO.
Definition user_intf.f90:34
Utilities.
Definition utils.f90:35
integer function, public extract_fld_file_index(fld_filename, default_index)
Extracts the index of a field file. For example, "myfield.f00045" will return 45. If the suffix of th...
Definition utils.f90:209
integer, parameter, public neko_fname_len
Definition utils.f90:42
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Definition utils.f90:398
subroutine, public filename_chsuffix(fname, new_fname, new_suffix)
Change a filename's suffix.
Definition utils.f90:156
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:63
field_list_t, To be able to group fields together
A wrapper around a polymorphic generic_file_t that handles its init. This is essentially a factory fo...
Definition file.f90:56
Interface for NEKTON fld files.
Definition fld_file.f90:66
Gather-scatter kernel.
Implements global interpolation for arbitrary points in the domain.
Interpolation between two space::space_t.
Base abstract type for point zones.
The function space for the SEM solution fields.
Definition space.f90:64