Neko  0.9.99
A portable framework for high-order spectral element flow simulations
scalar_pnpn.f90
Go to the documentation of this file.
1 ! Copyright (c) 2022-2024, 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 !
34 
36  use num_types, only: rp
38  rhs_maker_ext_fctry, rhs_maker_bdf_fctry, rhs_maker_oifs_fctry
39  use scalar_scheme, only : scalar_scheme_t
40  use dirichlet, only : dirichlet_t
41  use neumann, only : neumann_t
42  use field, only : field_t
45  use mesh, only : mesh_t
46  use checkpoint, only : chkp_t
47  use coefs, only : coef_t
49  use gather_scatter, only : gs_t, gs_op_add
50  use scalar_residual, only : scalar_residual_t, scalar_residual_factory
51  use ax_product, only : ax_t, ax_helm_factory
52  use field_series, only: field_series_t
53  use facet_normal, only : facet_normal_t
54  use krylov, only : ksp_monitor_t
56  use scalar_aux, only : scalar_step_info
58  use projection, only : projection_t
59  use math, only : glsc2, col2, add2s2
61  use advection, only : advection_t, advection_factory
64  use json_module, only : json_file
65  use user_intf, only : user_t
66  use neko_config, only : neko_bcknd_device
69  implicit none
70  private
71 
72 
73  type, public, extends(scalar_scheme_t) :: scalar_pnpn_t
74 
76  type(field_t) :: s_res
77 
79  type(field_t) :: ds
80 
82  class(ax_t), allocatable :: ax
83 
85  type(projection_t) :: proj_s
86 
90  type(dirichlet_t) :: bc_res
91 
94  type(bc_list_t) :: bclst_ds
95 
97  class(advection_t), allocatable :: adv
98 
99  ! Time interpolation scheme
100  logical :: oifs
101 
102  ! Lag arrays for the RHS.
103  type(field_t) :: abx1, abx2
104 
105  ! Advection terms for the oifs method
106  type(field_t) :: advs
107 
109  class(scalar_residual_t), allocatable :: res
110 
112  class(rhs_maker_ext_t), allocatable :: makeext
113 
115  class(rhs_maker_bdf_t), allocatable :: makebdf
116 
118  class(rhs_maker_oifs_t), allocatable :: makeoifs
119 
120  contains
122  procedure, pass(this) :: init => scalar_pnpn_init
124  procedure, pass(this) :: restart => scalar_pnpn_restart
126  procedure, pass(this) :: free => scalar_pnpn_free
128  procedure, pass(this) :: step => scalar_pnpn_step
129  end type scalar_pnpn_t
130 
131 contains
132 
139  subroutine scalar_pnpn_init(this, msh, coef, gs, params, user, &
140  ulag, vlag, wlag, time_scheme, rho)
141  class(scalar_pnpn_t), target, intent(inout) :: this
142  type(mesh_t), target, intent(inout) :: msh
143  type(coef_t), target, intent(inout) :: coef
144  type(gs_t), target, intent(inout) :: gs
145  type(json_file), target, intent(inout) :: params
146  type(user_t), target, intent(in) :: user
147  type(field_series_t), target, intent(in) :: ulag, vlag, wlag
148  type(time_scheme_controller_t), target, intent(in) :: time_scheme
149  real(kind=rp), intent(in) :: rho
150  integer :: i
151  character(len=15), parameter :: scheme = 'Modular (Pn/Pn)'
152  logical :: advection
153 
154  call this%free()
155 
156  ! Initiliaze base type.
157  call this%scheme_init(msh, coef, gs, params, scheme, user, rho)
158 
159  ! Setup backend dependent Ax routines
160  call ax_helm_factory(this%ax, full_formulation = .false.)
161 
162  ! Setup backend dependent scalar residual routines
163  call scalar_residual_factory(this%res)
164 
165  ! Setup backend dependent summation of extrapolation scheme
166  call rhs_maker_ext_fctry(this%makeext)
167 
168  ! Setup backend depenent contributions to F from lagged BD terms
169  call rhs_maker_bdf_fctry(this%makebdf)
170 
171  ! Setup backend dependent contributions of the OIFS scheme
172  call rhs_maker_oifs_fctry(this%makeoifs)
173 
174  ! Initialize variables specific to this plan
175  associate(xh_lx => this%Xh%lx, xh_ly => this%Xh%ly, xh_lz => this%Xh%lz, &
176  dm_xh => this%dm_Xh, nelv => this%msh%nelv)
177 
178  call this%s_res%init(dm_xh, "s_res")
179 
180  call this%abx1%init(dm_xh, "abx1")
181 
182  call this%abx2%init(dm_xh, "abx2")
183 
184  call this%advs%init(dm_xh, "advs")
185 
186  call this%ds%init(dm_xh, 'ds')
187 
188  end associate
189 
190  ! Initialize dirichlet bcs for scalar residual
191  ! todo: look that this works
192  call this%bc_res%init_base(this%c_Xh)
193  do i = 1, this%n_dir_bcs
194  call this%bc_res%mark_facets(this%dir_bcs(i)%marked_facet)
195  end do
196 
197  ! Check for user bcs
198  if (this%user_bc%msk(0) .gt. 0) then
199  call this%bc_res%mark_facets(this%user_bc%marked_facet)
200  end if
201 
202  call this%bc_res%mark_zones_from_list(msh%labeled_zones, 'd_s', &
203  this%bc_labels)
204  call this%bc_res%finalize()
205  call this%bc_res%set_g(0.0_rp)
206 
207  call bc_list_init(this%bclst_ds)
208  call bc_list_add(this%bclst_ds, this%bc_res)
209 
210 
211  ! Intialize projection space
212  call this%proj_s%init(this%dm_Xh%size(), this%projection_dim, &
213  this%projection_activ_step)
214 
215  ! Add lagged term to checkpoint
216  ! @todo Init chkp object, note, adding 3 slags
217  ! call this%chkp%add_lag(this%slag, this%slag, this%slag)
218 
219  ! Determine the time-interpolation scheme
220  call json_get_or_default(params, 'case.numerics.oifs', this%oifs, .false.)
221 
222  ! Initialize advection factory
223  call json_get_or_default(params, 'case.scalar.advection', advection, .true.)
224  call advection_factory(this%adv, params, this%c_Xh, &
225  ulag, vlag, wlag, this%chkp%dtlag, &
226  this%chkp%tlag, time_scheme, .not. advection, &
227  this%slag)
228  end subroutine scalar_pnpn_init
229 
231  subroutine scalar_pnpn_restart(this, dtlag, tlag)
232  class(scalar_pnpn_t), target, intent(inout) :: this
233  real(kind=rp) :: dtlag(10), tlag(10)
234  integer :: n
235 
236 
237  n = this%s%dof%size()
238 
239  call col2(this%s%x, this%c_Xh%mult, n)
240  call col2(this%slag%lf(1)%x, this%c_Xh%mult, n)
241  call col2(this%slag%lf(2)%x, this%c_Xh%mult, n)
242  if (neko_bcknd_device .eq. 1) then
243  call device_memcpy(this%s%x, this%s%x_d, &
244  n, host_to_device, sync = .false.)
245  call device_memcpy(this%slag%lf(1)%x, this%slag%lf(1)%x_d, &
246  n, host_to_device, sync = .false.)
247  call device_memcpy(this%slag%lf(2)%x, this%slag%lf(2)%x_d, &
248  n, host_to_device, sync = .false.)
249  call device_memcpy(this%abx1%x, this%abx1%x_d, &
250  n, host_to_device, sync = .false.)
251  call device_memcpy(this%abx2%x, this%abx2%x_d, &
252  n, host_to_device, sync = .false.)
253  call device_memcpy(this%advs%x, this%advs%x_d, &
254  n, host_to_device, sync = .false.)
255  end if
256 
257  call this%gs_Xh%op(this%s, gs_op_add)
258  call this%gs_Xh%op(this%slag%lf(1), gs_op_add)
259  call this%gs_Xh%op(this%slag%lf(2), gs_op_add)
260 
261  end subroutine scalar_pnpn_restart
262 
263  subroutine scalar_pnpn_free(this)
264  class(scalar_pnpn_t), intent(inout) :: this
265 
266  !Deallocate scalar field
267  call this%scheme_free()
268 
269  call bc_list_free(this%bclst_ds)
270  call this%proj_s%free()
271 
272  call this%s_res%free()
273 
274  call this%ds%free()
275 
276  call this%abx1%free()
277  call this%abx2%free()
278 
279  call this%advs%free()
280 
281  if (allocated(this%Ax)) then
282  deallocate(this%Ax)
283  end if
284 
285  if (allocated(this%res)) then
286  deallocate(this%res)
287  end if
288 
289  if (allocated(this%makeext)) then
290  deallocate(this%makeext)
291  end if
292 
293  if (allocated(this%makebdf)) then
294  deallocate(this%makebdf)
295  end if
296 
297  if (allocated(this%makeoifs)) then
298  deallocate(this%makeoifs)
299  end if
300 
301  end subroutine scalar_pnpn_free
302 
303  subroutine scalar_pnpn_step(this, t, tstep, dt, ext_bdf, dt_controller)
304  class(scalar_pnpn_t), intent(inout) :: this
305  real(kind=rp), intent(inout) :: t
306  integer, intent(inout) :: tstep
307  real(kind=rp), intent(in) :: dt
308  type(time_scheme_controller_t), intent(inout) :: ext_bdf
309  type(time_step_controller_t), intent(in) :: dt_controller
310  ! Number of degrees of freedom
311  integer :: n
312  ! Linear solver results monitor
313  type(ksp_monitor_t) :: ksp_results(1)
314  character(len=LOG_SIZE) :: log_buf
315 
316  n = this%dm_Xh%size()
317 
318  call profiler_start_region('Scalar', 2)
319  associate(u => this%u, v => this%v, w => this%w, s => this%s, &
320  cp => this%cp, rho => this%rho, &
321  ds => this%ds, &
322  s_res => this%s_res, &
323  ax => this%Ax, f_xh => this%f_Xh, xh => this%Xh, &
324  c_xh => this%c_Xh, dm_xh => this%dm_Xh, gs_xh => this%gs_Xh, &
325  slag => this%slag, oifs => this%oifs, &
326  lambda_field => this%lambda_field, &
327  projection_dim => this%projection_dim, &
328  msh => this%msh, res => this%res, makeoifs => this%makeoifs, &
329  makeext => this%makeext, makebdf => this%makebdf, &
330  if_variable_dt => dt_controller%if_variable_dt, &
331  dt_last_change => dt_controller%dt_last_change)
332 
333  if (neko_log%level_ .ge. neko_log_debug) then
334  write(log_buf, '(A,A,E15.7,A,E15.7,A,E15.7)') 'Scalar debug', &
335  ' l2norm s', glsc2(this%s%x, this%s%x, n), &
336  ' slag1', glsc2(this%slag%lf(1)%x, this%slag%lf(1)%x, n), &
337  ' slag2', glsc2(this%slag%lf(2)%x, this%slag%lf(2)%x, n)
338  call neko_log%message(log_buf)
339  write(log_buf, '(A,A,E15.7,A,E15.7)') 'Scalar debug2', &
340  ' l2norm abx1', glsc2(this%abx1%x, this%abx1%x, n), &
341  ' abx2', glsc2(this%abx2%x, this%abx2%x, n)
342  call neko_log%message(log_buf)
343  end if
344 
345  ! Compute the source terms
346  call this%source_term%compute(t, tstep)
347 
348  ! Compute the grandient jump penalty term
349  if (this%if_gradient_jump_penalty .eqv. .true.) then
350  call this%gradient_jump_penalty%compute(u, v, w, s)
351  call this%gradient_jump_penalty%perform(f_xh)
352  end if
353 
354  ! Apply Neumann boundary conditions
355  call bc_list_apply_scalar(this%bclst_neumann, this%f_Xh%x, dm_xh%size())
356 
357  if (oifs) then
358  ! Add the advection operators to the right-hans-side.
359  call this%adv%compute_scalar(u, v, w, s, this%advs, &
360  xh, this%c_Xh, dm_xh%size())
361 
362  call makeext%compute_scalar(this%abx1, this%abx2, f_xh%x, rho, &
363  ext_bdf%advection_coeffs, n)
364 
365  call makeoifs%compute_scalar(this%advs%x, f_xh%x, rho, dt, n)
366  else
367  ! Add the advection operators to the right-hans-side.
368  call this%adv%compute_scalar(u, v, w, s, f_xh, &
369  xh, this%c_Xh, dm_xh%size())
370 
371  ! At this point the RHS contains the sum of the advection operator,
372  ! Neumann boundary sources and additional source terms, evaluated using
373  ! the scalar field from the previous time-step. Now, this value is used in
374  ! the explicit time scheme to advance these terms in time.
375  call makeext%compute_scalar(this%abx1, this%abx2, f_xh%x, rho, &
376  ext_bdf%advection_coeffs, n)
377 
378  ! Add the RHS contributions coming from the BDF scheme.
379  call makebdf%compute_scalar(slag, f_xh%x, s, c_xh%B, rho, dt, &
380  ext_bdf%diffusion_coeffs, ext_bdf%ndiff, n)
381  end if
382 
383  call slag%update()
384 
388  call this%field_dir_bc%update(this%field_dir_bc%field_list, &
389  this%field_dirichlet_bcs, this%c_Xh, t, tstep, "scalar")
390  call bc_list_apply_scalar(this%bclst_dirichlet, &
391  this%s%x, this%dm_Xh%size())
392 
393 
394  ! Update material properties if necessary
395  call this%update_material_properties()
396 
397  ! Compute scalar residual.
398  call profiler_start_region('Scalar_residual', 20)
399  call res%compute(ax, s, s_res, f_xh, c_xh, msh, xh, lambda_field, &
400  rho*cp, ext_bdf%diffusion_coeffs(1), dt, dm_xh%size())
401 
402  call gs_xh%op(s_res, gs_op_add)
403 
404  ! Apply a 0-valued Dirichlet boundary conditions on the ds.
405  call bc_list_apply_scalar(this%bclst_ds, s_res%x, dm_xh%size())
406 
407  call profiler_end_region('Scalar_residual', 20)
408 
409  call this%proj_s%pre_solving(s_res%x, tstep, c_xh, n, dt_controller)
410 
411  call this%pc%update()
412  call profiler_start_region('Scalar_solve', 21)
413  ksp_results(1) = this%ksp%solve(ax, ds, s_res%x, n, &
414  c_xh, this%bclst_ds, gs_xh)
415  call profiler_end_region('Scalar_solve', 21)
416 
417  call this%proj_s%post_solving(ds%x, ax, c_xh, &
418  this%bclst_ds, gs_xh, n, tstep, dt_controller)
419 
420  ! Update the solution
421  if (neko_bcknd_device .eq. 1) then
422  call device_add2s2(s%x_d, ds%x_d, 1.0_rp, n)
423  else
424  call add2s2(s%x, ds%x, 1.0_rp, n)
425  end if
426 
427  call scalar_step_info(tstep, t, dt, ksp_results)
428 
429  end associate
430  call profiler_end_region('Scalar', 2)
431  end subroutine scalar_pnpn_step
432 
433 
434 end module scalar_pnpn
Copy data between host and device (or device and device)
Definition: device.F90:51
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Definition: json_utils.f90:54
Retrieves a parameter by name or throws an error.
Definition: json_utils.f90:45
Subroutines to add advection terms to the RHS of a transport equation.
Definition: advection.f90:34
Defines a Matrix-vector product.
Definition: ax.f90:34
Defines a boundary condition.
Definition: bc.f90:34
subroutine, public bc_list_add(bclst, bc)
Add a condition to a list of boundary conditions.
Definition: bc.f90:505
subroutine, public bc_list_init(bclst, size)
Constructor for a list of boundary conditions.
Definition: bc.f90:464
subroutine, public bc_list_free(bclst)
Destructor for a list of boundary conditions.
Definition: bc.f90:491
subroutine, public bc_list_apply_scalar(bclst, x, n, t, tstep)
Apply a list of boundary conditions to a scalar field.
Definition: bc.f90:530
Defines a checkpoint.
Definition: checkpoint.f90:34
Coefficients.
Definition: coef.f90:34
subroutine, public device_col2(a_d, b_d, n)
Vector multiplication .
subroutine, public device_add2s2(a_d, b_d, c1, n)
Vector addition with scalar multiplication (multiplication on first argument)
Device abstraction, common interface for various accelerators.
Definition: device.F90:34
integer, parameter, public host_to_device
Definition: device.F90:47
Defines a dirichlet boundary condition.
Definition: dirichlet.f90:34
Dirichlet condition applied in the facet normal direction.
Stores a series fields.
Defines a field.
Definition: field.f90:34
Gather-scatter.
Utilities for retrieving parameters from the case files.
Definition: json_utils.f90:34
Implements the base abstract type for Krylov solvers plus helper types.
Definition: krylov.f90:34
Logging routines.
Definition: log.f90:34
integer, parameter, public neko_log_debug
Debug log level.
Definition: log.f90:73
type(log_t), public neko_log
Global log stream.
Definition: log.f90:65
integer, parameter, public log_size
Definition: log.f90:42
Definition: math.f90:60
real(kind=rp) function, public glsc2(a, b, n)
Weighted inner product .
Definition: math.f90:876
subroutine, public col2(a, b, n)
Vector multiplication .
Definition: math.f90:729
subroutine, public add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
Definition: math.f90:673
Defines a mesh.
Definition: mesh.f90:34
Build configurations.
Definition: neko_config.f90:34
integer, parameter neko_bcknd_device
Definition: neko_config.f90:44
Defines a Neumann boundary condition.
Definition: neumann.f90:34
integer, parameter, public rp
Global precision used in computations.
Definition: num_types.f90:12
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
Project x onto X, the space of old solutions and back again.
Definition: projection.f90:63
Routines to generate the right-hand sides for the convection-diffusion equation. Employs the EXT/BDF ...
Definition: rhs_maker.f90:38
Auxiliary routines for fluid solvers.
Definition: scalar_aux.f90:2
subroutine scalar_step_info(step, t, dt, ksp_results)
Prints for prs, velx, vely, velz the following: Number of iterations, start residual,...
Definition: scalar_aux.f90:14
Containts the scalar_pnpn_t type.
Definition: scalar_pnpn.f90:35
subroutine scalar_pnpn_init(this, msh, coef, gs, params, user, ulag, vlag, wlag, time_scheme, rho)
Constructor.
subroutine scalar_pnpn_step(this, t, tstep, dt, ext_bdf, dt_controller)
subroutine scalar_pnpn_restart(this, dtlag, tlag)
I envision the arguments to this func might need to be expanded.
subroutine scalar_pnpn_free(this)
Defines the residual for the scalar transport equation.
Contains the scalar_scheme_t type.
Defines a registry for storing and requesting temporary fields This can be used when you have a funct...
type(scratch_registry_t), target, public neko_scratch_registry
Global scratch registry.
Compound scheme for the advection and diffusion operators in a transport equation.
Base class for time integration schemes.
Definition: time_scheme.f90:61
Implements type time_step_controller.
Interfaces for user interaction with NEKO.
Definition: user_intf.f90:34
Base abstract type for computing the advection operator.
Definition: advection.f90:46
Base type for a matrix-vector product providing .
Definition: ax.f90:43
A list of boundary conditions.
Definition: bc.f90:104
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition: coef.f90:55
Generic Dirichlet boundary condition on .
Definition: dirichlet.f90:44
Dirichlet condition in facet normal direction.
Type for storing initial and final residuals in a Krylov solver.
Definition: krylov.f90:56
A Neumann boundary condition for scalar fields. Sets the flux of the field to the chosen value.
Definition: neumann.f90:48
Abstract type to add contributions to F from lagged BD terms.
Definition: rhs_maker.f90:59
Abstract type to sum up contributions to kth order extrapolation scheme.
Definition: rhs_maker.f90:52
Abstract type to add contributions of kth order OIFS scheme.
Definition: rhs_maker.f90:66
Abstract type to compute scalar residual.
Base type for a scalar advection-diffusion solver.
Implements the logic to compute the time coefficients for the advection and diffusion operators in a ...
Provides a tool to set time step dt.