Neko  0.8.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
67  use neko_config, only : neko_bcknd_device
70  implicit none
71  private
72 
73 
74  type, public, extends(scalar_scheme_t) :: scalar_pnpn_t
75 
77  type(field_t) :: s_res
78 
80  type(field_t) :: ds
81 
83  class(ax_t), allocatable :: ax
84 
86  type(projection_t) :: proj_s
87 
91  type(dirichlet_t) :: bc_res
92 
95  type(bc_list_t) :: bclst_ds
96 
98  class(advection_t), allocatable :: adv
99 
100  ! Time interpolation scheme
101  logical :: oifs
102 
103  ! Lag arrays for the RHS.
104  type(field_t) :: abx1, abx2
105 
106  ! Advection terms for the oifs method
107  type(field_t) :: advs
108 
110  class(scalar_residual_t), allocatable :: res
111 
113  class(rhs_maker_ext_t), allocatable :: makeext
114 
116  class(rhs_maker_bdf_t), allocatable :: makebdf
117 
119  class(rhs_maker_oifs_t), allocatable :: makeoifs
120 
121  contains
123  procedure, pass(this) :: init => scalar_pnpn_init
125  procedure, pass(this) :: restart => scalar_pnpn_restart
127  procedure, pass(this) :: free => scalar_pnpn_free
129  procedure, pass(this) :: step => scalar_pnpn_step
130  end type scalar_pnpn_t
131 
132 contains
133 
140  subroutine scalar_pnpn_init(this, msh, coef, gs, params, user, &
141  material_properties, ulag, vlag, wlag, &
142  time_scheme)
143  class(scalar_pnpn_t), target, intent(inout) :: this
144  type(mesh_t), target, intent(inout) :: msh
145  type(coef_t), target, intent(inout) :: coef
146  type(gs_t), target, intent(inout) :: gs
147  type(json_file), target, intent(inout) :: params
148  type(user_t), target, intent(in) :: user
149  type(material_properties_t), intent(inout) :: material_properties
150  type(field_series_t), target, intent(in) :: ulag, vlag, wlag
151  type(time_scheme_controller_t), target, intent(in) :: time_scheme
152  integer :: i
153  character(len=15), parameter :: scheme = 'Modular (Pn/Pn)'
154 
155  call this%free()
156 
157  ! Initiliaze base type.
158  call this%scheme_init(msh, coef, gs, params, scheme, user, &
160 
161  ! Setup backend dependent Ax routines
162  call ax_helm_factory(this%ax, full_formulation = .false.)
163 
164  ! Setup backend dependent scalar residual routines
165  call scalar_residual_factory(this%res)
166 
167  ! Setup backend dependent summation of extrapolation scheme
168  call rhs_maker_ext_fctry(this%makeext)
169 
170  ! Setup backend depenent contributions to F from lagged BD terms
171  call rhs_maker_bdf_fctry(this%makebdf)
172 
173  ! Setup backend dependent contributions of the OIFS scheme
174  call rhs_maker_oifs_fctry(this%makeoifs)
175 
176  ! Initialize variables specific to this plan
177  associate(xh_lx => this%Xh%lx, xh_ly => this%Xh%ly, xh_lz => this%Xh%lz, &
178  dm_xh => this%dm_Xh, nelv => this%msh%nelv)
179 
180  call this%s_res%init(dm_xh, "s_res")
181 
182  call this%abx1%init(dm_xh, "abx1")
183 
184  call this%abx2%init(dm_xh, "abx2")
185 
186  call this%advs%init(dm_xh, "advs")
187 
188  call this%ds%init(dm_xh, 'ds')
189 
190  end associate
191 
192  ! Initialize dirichlet bcs for scalar residual
193  ! todo: look that this works
194  call this%bc_res%init_base(this%c_Xh)
195  do i = 1, this%n_dir_bcs
196  call this%bc_res%mark_facets(this%dir_bcs(i)%marked_facet)
197  end do
198 
199  ! Check for user bcs
200  if (this%user_bc%msk(0) .gt. 0) then
201  call this%bc_res%mark_facets(this%user_bc%marked_facet)
202  end if
203 
204  call this%bc_res%mark_zones_from_list(msh%labeled_zones, 'd_s', &
205  this%bc_labels)
206  call this%bc_res%finalize()
207  call this%bc_res%set_g(0.0_rp)
208 
209  call bc_list_init(this%bclst_ds)
210  call bc_list_add(this%bclst_ds, this%bc_res)
211 
212 
213  ! Intialize projection space
214  call this%proj_s%init(this%dm_Xh%size(), this%projection_dim, &
215  this%projection_activ_step)
216 
217  ! Add lagged term to checkpoint
218  ! @todo Init chkp object, note, adding 3 slags
219  ! call this%chkp%add_lag(this%slag, this%slag, this%slag)
220 
221  ! Determine the time-interpolation scheme
222  call json_get_or_default(params, 'case.numerics.oifs', this%oifs, .false.)
223 
224  ! Initialize advection factory
225  call advection_factory(this%adv, params, this%c_Xh, &
226  ulag, vlag, wlag, this%chkp%dtlag, &
227  this%chkp%tlag, time_scheme, 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  ! Pre-multiply the source terms with the mass matrix.
349  if (neko_bcknd_device .eq. 1) then
350  call device_col2(f_xh%x_d, c_xh%B_d, n)
351  else
352  call col2(f_xh%x, c_xh%B, n)
353  end if
354 
355  ! Apply Neumann boundary conditions
356  call bc_list_apply_scalar(this%bclst_neumann, this%f_Xh%x, dm_xh%size())
357 
358  if (oifs) then
359  ! Add the advection operators to the right-hans-side.
360  call this%adv%compute_scalar(u, v, w, s, this%advs, &
361  xh, this%c_Xh, dm_xh%size())
362 
363  call makeext%compute_scalar(this%abx1, this%abx2, f_xh%x, rho, &
364  ext_bdf%advection_coeffs, n)
365 
366  call makeoifs%compute_scalar(this%advs%x, f_xh%x, rho, dt, n)
367  else
368  ! Add the advection operators to the right-hans-side.
369  call this%adv%compute_scalar(u, v, w, s, f_xh, &
370  xh, this%c_Xh, dm_xh%size())
371 
372  ! At this point the RHS contains the sum of the advection operator,
373  ! Neumann boundary sources and additional source terms, evaluated using
374  ! the scalar field from the previous time-step. Now, this value is used in
375  ! the explicit time scheme to advance these terms in time.
376  call makeext%compute_scalar(this%abx1, this%abx2, f_xh%x, rho, &
377  ext_bdf%advection_coeffs, n)
378 
379  ! Add the RHS contributions coming from the BDF scheme.
380  call makebdf%compute_scalar(slag, f_xh%x, s, c_xh%B, rho, dt, &
381  ext_bdf%diffusion_coeffs, ext_bdf%ndiff, n)
382  end if
383 
384  call slag%update()
385 
389  call this%field_dir_bc%update(this%field_dir_bc%field_list, &
390  this%field_dirichlet_bcs, this%c_Xh, t, tstep, "scalar")
391  call bc_list_apply_scalar(this%bclst_dirichlet, &
392  this%s%x, this%dm_Xh%size())
393 
394 
395  ! Update material properties if necessary
396  call this%update_material_properties()
397 
398  ! Compute scalar residual.
399  call profiler_start_region('Scalar_residual', 20)
400  call res%compute(ax, s, s_res, f_xh, c_xh, msh, xh, lambda_field, &
401  rho*cp, ext_bdf%diffusion_coeffs(1), dt, dm_xh%size())
402 
403  call gs_xh%op(s_res, gs_op_add)
404 
405  ! Apply a 0-valued Dirichlet boundary conditions on the ds.
406  call bc_list_apply_scalar(this%bclst_ds, s_res%x, dm_xh%size())
407 
408  call profiler_end_region('Scalar_residual', 20)
409 
410  call this%proj_s%pre_solving(s_res%x, tstep, c_xh, n, dt_controller)
411 
412  call this%pc%update()
413  call profiler_start_region('Scalar_solve', 21)
414  ksp_results(1) = this%ksp%solve(ax, ds, s_res%x, n, &
415  c_xh, this%bclst_ds, gs_xh)
416  call profiler_end_region('Scalar_solve', 21)
417 
418  call this%proj_s%post_solving(ds%x, ax, c_xh, &
419  this%bclst_ds, gs_xh, n, tstep, dt_controller)
420 
421  ! Update the solution
422  if (neko_bcknd_device .eq. 1) then
423  call device_add2s2(s%x_d, ds%x_d, 1.0_rp, n)
424  else
425  call add2s2(s%x, ds%x, 1.0_rp, n)
426  end if
427 
428  call scalar_step_info(tstep, t, dt, ksp_results)
429 
430  end associate
431  call profiler_end_region('Scalar', 2)
432  end subroutine scalar_pnpn_step
433 
434 
435 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:53
Retrieves a parameter by name or throws an error.
Definition: json_utils.f90:44
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:501
subroutine, public bc_list_init(bclst, size)
Constructor for a list of boundary conditions.
Definition: bc.f90:460
subroutine, public bc_list_free(bclst)
Destructor for a list of boundary conditions.
Definition: bc.f90:487
subroutine, public bc_list_apply_scalar(bclst, x, n, t, tstep)
Apply a list of boundary conditions to a scalar field.
Definition: bc.f90:526
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:69
type(log_t), public neko_log
Global log stream.
Definition: log.f90:61
integer, parameter, public log_size
Definition: log.f90:40
Implements material_properties_t type.
Definition: math.f90:60
real(kind=rp) function, public glsc2(a, b, n)
Weighted inner product .
Definition: math.f90:836
subroutine, public col2(a, b, n)
Vector multiplication .
Definition: math.f90:689
subroutine, public add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
Definition: math.f90:633
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_step(this, t, tstep, dt, ext_bdf, dt_controller)
subroutine scalar_pnpn_init(this, msh, coef, gs, params, user, material_properties, ulag, vlag, wlag, time_scheme)
Constructor.
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
Contains all the material properties necessary in the simulation.
Generic Neumann boundary condition. This 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.