Neko  0.9.0
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 
153  call this%free()
154 
155  ! Initiliaze base type.
156  call this%scheme_init(msh, coef, gs, params, scheme, user, rho)
157 
158  ! Setup backend dependent Ax routines
159  call ax_helm_factory(this%ax, full_formulation = .false.)
160 
161  ! Setup backend dependent scalar residual routines
162  call scalar_residual_factory(this%res)
163 
164  ! Setup backend dependent summation of extrapolation scheme
165  call rhs_maker_ext_fctry(this%makeext)
166 
167  ! Setup backend depenent contributions to F from lagged BD terms
168  call rhs_maker_bdf_fctry(this%makebdf)
169 
170  ! Setup backend dependent contributions of the OIFS scheme
171  call rhs_maker_oifs_fctry(this%makeoifs)
172 
173  ! Initialize variables specific to this plan
174  associate(xh_lx => this%Xh%lx, xh_ly => this%Xh%ly, xh_lz => this%Xh%lz, &
175  dm_xh => this%dm_Xh, nelv => this%msh%nelv)
176 
177  call this%s_res%init(dm_xh, "s_res")
178 
179  call this%abx1%init(dm_xh, "abx1")
180 
181  call this%abx2%init(dm_xh, "abx2")
182 
183  call this%advs%init(dm_xh, "advs")
184 
185  call this%ds%init(dm_xh, 'ds')
186 
187  end associate
188 
189  ! Initialize dirichlet bcs for scalar residual
190  ! todo: look that this works
191  call this%bc_res%init_base(this%c_Xh)
192  do i = 1, this%n_dir_bcs
193  call this%bc_res%mark_facets(this%dir_bcs(i)%marked_facet)
194  end do
195 
196  ! Check for user bcs
197  if (this%user_bc%msk(0) .gt. 0) then
198  call this%bc_res%mark_facets(this%user_bc%marked_facet)
199  end if
200 
201  call this%bc_res%mark_zones_from_list(msh%labeled_zones, 'd_s', &
202  this%bc_labels)
203  call this%bc_res%finalize()
204  call this%bc_res%set_g(0.0_rp)
205 
206  call bc_list_init(this%bclst_ds)
207  call bc_list_add(this%bclst_ds, this%bc_res)
208 
209 
210  ! Intialize projection space
211  call this%proj_s%init(this%dm_Xh%size(), this%projection_dim, &
212  this%projection_activ_step)
213 
214  ! Add lagged term to checkpoint
215  ! @todo Init chkp object, note, adding 3 slags
216  ! call this%chkp%add_lag(this%slag, this%slag, this%slag)
217 
218  ! Determine the time-interpolation scheme
219  call json_get_or_default(params, 'case.numerics.oifs', this%oifs, .false.)
220 
221  ! Initialize advection factory
222  call advection_factory(this%adv, params, this%c_Xh, &
223  ulag, vlag, wlag, this%chkp%dtlag, &
224  this%chkp%tlag, time_scheme, this%slag)
225  end subroutine scalar_pnpn_init
226 
228  subroutine scalar_pnpn_restart(this, dtlag, tlag)
229  class(scalar_pnpn_t), target, intent(inout) :: this
230  real(kind=rp) :: dtlag(10), tlag(10)
231  integer :: n
232 
233 
234  n = this%s%dof%size()
235 
236  call col2(this%s%x, this%c_Xh%mult, n)
237  call col2(this%slag%lf(1)%x, this%c_Xh%mult, n)
238  call col2(this%slag%lf(2)%x, this%c_Xh%mult, n)
239  if (neko_bcknd_device .eq. 1) then
240  call device_memcpy(this%s%x, this%s%x_d, &
241  n, host_to_device, sync = .false.)
242  call device_memcpy(this%slag%lf(1)%x, this%slag%lf(1)%x_d, &
243  n, host_to_device, sync = .false.)
244  call device_memcpy(this%slag%lf(2)%x, this%slag%lf(2)%x_d, &
245  n, host_to_device, sync = .false.)
246  call device_memcpy(this%abx1%x, this%abx1%x_d, &
247  n, host_to_device, sync = .false.)
248  call device_memcpy(this%abx2%x, this%abx2%x_d, &
249  n, host_to_device, sync = .false.)
250  call device_memcpy(this%advs%x, this%advs%x_d, &
251  n, host_to_device, sync = .false.)
252  end if
253 
254  call this%gs_Xh%op(this%s, gs_op_add)
255  call this%gs_Xh%op(this%slag%lf(1), gs_op_add)
256  call this%gs_Xh%op(this%slag%lf(2), gs_op_add)
257 
258  end subroutine scalar_pnpn_restart
259 
260  subroutine scalar_pnpn_free(this)
261  class(scalar_pnpn_t), intent(inout) :: this
262 
263  !Deallocate scalar field
264  call this%scheme_free()
265 
266  call bc_list_free(this%bclst_ds)
267  call this%proj_s%free()
268 
269  call this%s_res%free()
270 
271  call this%ds%free()
272 
273  call this%abx1%free()
274  call this%abx2%free()
275 
276  call this%advs%free()
277 
278  if (allocated(this%Ax)) then
279  deallocate(this%Ax)
280  end if
281 
282  if (allocated(this%res)) then
283  deallocate(this%res)
284  end if
285 
286  if (allocated(this%makeext)) then
287  deallocate(this%makeext)
288  end if
289 
290  if (allocated(this%makebdf)) then
291  deallocate(this%makebdf)
292  end if
293 
294  if (allocated(this%makeoifs)) then
295  deallocate(this%makeoifs)
296  end if
297 
298  end subroutine scalar_pnpn_free
299 
300  subroutine scalar_pnpn_step(this, t, tstep, dt, ext_bdf, dt_controller)
301  class(scalar_pnpn_t), intent(inout) :: this
302  real(kind=rp), intent(inout) :: t
303  integer, intent(inout) :: tstep
304  real(kind=rp), intent(in) :: dt
305  type(time_scheme_controller_t), intent(inout) :: ext_bdf
306  type(time_step_controller_t), intent(in) :: dt_controller
307  ! Number of degrees of freedom
308  integer :: n
309  ! Linear solver results monitor
310  type(ksp_monitor_t) :: ksp_results(1)
311  character(len=LOG_SIZE) :: log_buf
312 
313  n = this%dm_Xh%size()
314 
315  call profiler_start_region('Scalar', 2)
316  associate(u => this%u, v => this%v, w => this%w, s => this%s, &
317  cp => this%cp, rho => this%rho, &
318  ds => this%ds, &
319  s_res => this%s_res, &
320  ax => this%Ax, f_xh => this%f_Xh, xh => this%Xh, &
321  c_xh => this%c_Xh, dm_xh => this%dm_Xh, gs_xh => this%gs_Xh, &
322  slag => this%slag, oifs => this%oifs, &
323  lambda_field => this%lambda_field, &
324  projection_dim => this%projection_dim, &
325  msh => this%msh, res => this%res, makeoifs => this%makeoifs, &
326  makeext => this%makeext, makebdf => this%makebdf, &
327  if_variable_dt => dt_controller%if_variable_dt, &
328  dt_last_change => dt_controller%dt_last_change)
329 
330  if (neko_log%level_ .ge. neko_log_debug) then
331  write(log_buf, '(A,A,E15.7,A,E15.7,A,E15.7)') 'Scalar debug', &
332  ' l2norm s', glsc2(this%s%x, this%s%x, n), &
333  ' slag1', glsc2(this%slag%lf(1)%x, this%slag%lf(1)%x, n), &
334  ' slag2', glsc2(this%slag%lf(2)%x, this%slag%lf(2)%x, n)
335  call neko_log%message(log_buf)
336  write(log_buf, '(A,A,E15.7,A,E15.7)') 'Scalar debug2', &
337  ' l2norm abx1', glsc2(this%abx1%x, this%abx1%x, n), &
338  ' abx2', glsc2(this%abx2%x, this%abx2%x, n)
339  call neko_log%message(log_buf)
340  end if
341 
342  ! Compute the source terms
343  call this%source_term%compute(t, tstep)
344 
345  ! Compute the grandient jump penalty term
346  if (this%if_gradient_jump_penalty .eqv. .true.) then
347  call this%gradient_jump_penalty%compute(u, v, w, s)
348  call this%gradient_jump_penalty%perform(f_xh)
349  end if
350 
351  ! Apply Neumann boundary conditions
352  call bc_list_apply_scalar(this%bclst_neumann, this%f_Xh%x, dm_xh%size())
353 
354  if (oifs) then
355  ! Add the advection operators to the right-hans-side.
356  call this%adv%compute_scalar(u, v, w, s, this%advs, &
357  xh, this%c_Xh, dm_xh%size())
358 
359  call makeext%compute_scalar(this%abx1, this%abx2, f_xh%x, rho, &
360  ext_bdf%advection_coeffs, n)
361 
362  call makeoifs%compute_scalar(this%advs%x, f_xh%x, rho, dt, n)
363  else
364  ! Add the advection operators to the right-hans-side.
365  call this%adv%compute_scalar(u, v, w, s, f_xh, &
366  xh, this%c_Xh, dm_xh%size())
367 
368  ! At this point the RHS contains the sum of the advection operator,
369  ! Neumann boundary sources and additional source terms, evaluated using
370  ! the scalar field from the previous time-step. Now, this value is used in
371  ! the explicit time scheme to advance these terms in time.
372  call makeext%compute_scalar(this%abx1, this%abx2, f_xh%x, rho, &
373  ext_bdf%advection_coeffs, n)
374 
375  ! Add the RHS contributions coming from the BDF scheme.
376  call makebdf%compute_scalar(slag, f_xh%x, s, c_xh%B, rho, dt, &
377  ext_bdf%diffusion_coeffs, ext_bdf%ndiff, n)
378  end if
379 
380  call slag%update()
381 
385  call this%field_dir_bc%update(this%field_dir_bc%field_list, &
386  this%field_dirichlet_bcs, this%c_Xh, t, tstep, "scalar")
387  call bc_list_apply_scalar(this%bclst_dirichlet, &
388  this%s%x, this%dm_Xh%size())
389 
390 
391  ! Update material properties if necessary
392  call this%update_material_properties()
393 
394  ! Compute scalar residual.
395  call profiler_start_region('Scalar_residual', 20)
396  call res%compute(ax, s, s_res, f_xh, c_xh, msh, xh, lambda_field, &
397  rho*cp, ext_bdf%diffusion_coeffs(1), dt, dm_xh%size())
398 
399  call gs_xh%op(s_res, gs_op_add)
400 
401  ! Apply a 0-valued Dirichlet boundary conditions on the ds.
402  call bc_list_apply_scalar(this%bclst_ds, s_res%x, dm_xh%size())
403 
404  call profiler_end_region('Scalar_residual', 20)
405 
406  call this%proj_s%pre_solving(s_res%x, tstep, c_xh, n, dt_controller)
407 
408  call this%pc%update()
409  call profiler_start_region('Scalar_solve', 21)
410  ksp_results(1) = this%ksp%solve(ax, ds, s_res%x, n, &
411  c_xh, this%bclst_ds, gs_xh)
412  call profiler_end_region('Scalar_solve', 21)
413 
414  call this%proj_s%post_solving(ds%x, ax, c_xh, &
415  this%bclst_ds, gs_xh, n, tstep, dt_controller)
416 
417  ! Update the solution
418  if (neko_bcknd_device .eq. 1) then
419  call device_add2s2(s%x_d, ds%x_d, 1.0_rp, n)
420  else
421  call add2s2(s%x, ds%x, 1.0_rp, n)
422  end if
423 
424  call scalar_step_info(tstep, t, dt, ksp_results)
425 
426  end associate
427  call profiler_end_region('Scalar', 2)
428  end subroutine scalar_pnpn_step
429 
430 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.