Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
PDE_filter.f90
Go to the documentation of this file.
1! Copyright (c) 2023-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!
35
37 use num_types, only : rp
38 use json_module, only : json_file
39 use registry, only : neko_registry
40 use field, only : field_t
41 use coefs, only : coef_t
42 use ax_product, only : ax_t, ax_helm_allocator
43 use krylov, only : ksp_t, ksp_monitor_t, krylov_solver_factory
44 use precon, only : pc_t, precon_allocator, precon_destroy
45 use bc_list, only : bc_list_t
47 use neumann, only : neumann_t
49 use gather_scatter, only : gs_t, gs_op_add
52 use registry, only : neko_registry
53 use filter, only : filter_t
56 use coefs, only : coef_t
57 use logger, only : neko_log, log_size
59 use dofmap, only : dofmap_t
60 use jacobi, only : jacobi_t
62 use sx_jacobi, only : sx_jacobi_t
63 use utils, only : neko_error
66 implicit none
67 private
68
73 type, public, extends(filter_t) :: pde_filter_t
74
76 class(ax_t), allocatable :: ax
78 type(ksp_monitor_t) :: ksp_results(1)
80 class(ksp_t), allocatable :: ksp_filt
82 class(pc_t), allocatable :: pc_filt
84 type(scalar_bc_projector_t) :: bc_projector_filt
85
86 ! Inputs from the user
88 real(kind=rp) :: r
90 real(kind=rp) :: abstol_filt
92 integer :: ksp_max_iter
94 character(len=:), allocatable :: ksp_solver
95 ! > preconditioner type
96 character(len=:), allocatable :: precon_type_filt
97 integer :: ksp_n, n, i
98
99
100
101 contains
103 procedure, pass(this) :: init => pde_filter_init_from_json
105 procedure, pass(this) :: init_from_components => &
108 procedure, pass(this) :: free => pde_filter_free
110 procedure, pass(this) :: apply => pde_filter_apply
111 end type pde_filter_t
112
113contains
114
116 subroutine pde_filter_init_from_json(this, json, coef)
117 class(pde_filter_t), intent(inout) :: this
118 type(json_file), intent(inout) :: json
119 type(coef_t), target, intent(in) :: coef
120 real(kind=rp) :: r, tol
121 integer :: max_iter
122 character(len=:), allocatable :: ksp_solver, precon_type
123
124 ! user parameters
125 call json_get(json, "radius", r)
126 call json_get_or_default(json, "tolerance", tol, 1e-10_rp)
127 call json_get_or_default(json, "max_iter", max_iter, 200)
128 call json_get_or_default(json, "solver", ksp_solver, "cg")
129 call json_get_or_default(json, "preconditioner", precon_type, "jacobi")
130
131 call this%init_from_components(coef, r, tol, max_iter, ksp_solver, &
132 precon_type)
133
134 end subroutine pde_filter_init_from_json
135
137 subroutine pde_filter_init_from_components(this, coef, r, tol, max_iter, &
138 ksp_solver, precon_type)
139 class(pde_filter_t), intent(inout) :: this
140 type(coef_t), target, intent(in) :: coef
141 real(kind=rp), intent(in) :: r, tol
142 integer, intent(in) :: max_iter
143 character(len=*), intent(in) :: ksp_solver, precon_type
144 integer :: n
145
146 call this%init_base(coef)
147
148 this%r = r
149 this%abstol_filt = tol
150 this%ksp_max_iter = max_iter
151 this%ksp_solver = ksp_solver
152 this%precon_type_filt = precon_type
153
154 ! set the number of dofs
155 n = this%coef%dof%size()
156
157 ! Setup backend dependent Ax routines
158 call ax_helm_allocator(this%Ax, type_name = "standard")
159
160 ! set up krylov solver
161 call krylov_solver_factory(this%ksp_filt, n, this%ksp_solver, &
162 this%ksp_max_iter, this%abstol_filt)
163
164 ! set up preconditioner
165 call filter_precon_factory(this%pc_filt, this%ksp_filt, &
166 this%coef, this%coef%dof, &
167 this%coef%gs_h, &
168 this%bc_projector_filt, this%precon_type_filt)
169
171
173 subroutine pde_filter_free(this)
174 class(pde_filter_t), intent(inout) :: this
175
176 if (allocated(this%Ax)) then
177 call this%Ax%free()
178 deallocate(this%Ax)
179 end if
180
181 if (allocated(this%ksp_filt)) then
182 call this%ksp_filt%free()
183 deallocate(this%ksp_filt)
184 end if
185
186 if (allocated(this%pc_filt)) then
187 call precon_destroy(this%pc_filt)
188 deallocate(this%pc_filt)
189 end if
190
191 if (allocated(this%ksp_solver)) then
192 deallocate(this%ksp_solver)
193 end if
194
195 if (allocated(this%precon_type_filt)) then
196 deallocate(this%precon_type_filt)
197 end if
198
199 call this%bc_projector_filt%free()
200
201 call this%free_base()
202
203 end subroutine pde_filter_free
204
209 subroutine pde_filter_apply(this, F_out, F_in)
210 class(pde_filter_t), intent(inout) :: this
211 type(field_t), intent(in) :: F_in
212 type(field_t), intent(inout) :: F_out
213 integer :: n, i
214 type(field_t), pointer :: RHS, d_F_out
215 character(len=LOG_SIZE) :: log_buf
216 integer :: temp_indices(2)
217
218 n = this%coef%dof%size()
219 call neko_scratch_registry%request_field(rhs, temp_indices(1), .false.)
220 call neko_scratch_registry%request_field(d_f_out, temp_indices(2), .false.)
221 ! in a similar fasion to pressure/velocity, we will solve for d_F_out.
222
223 ! to improve convergence, we use F_in as an initial guess for F_out.
224 ! so F_out = F_in + d_F_in.
225
226 ! Defining the operator A = -r^2 \nabla^2 + I
227 ! the system changes from:
228 ! A (F_out) = F_in
229 ! to
230 ! A (d_F_out) = F_in - A(F_in)
231
232 ! set up Helmholtz operators and RHS
233 if (neko_bcknd_device .eq. 1) then
234 call device_cfill(this%coef%h1_d, &
235 (this%r / (2.0_rp * sqrt(3.0_rp)))**2, n)
236 call device_cfill(this%coef%h2_d, 1.0_rp, n)
237 else
238 ! h1 is already negative in its definition
239 this%coef%h1 = (this%r / (2.0_rp * sqrt(3.0_rp)))**2
240 ! ax_helm includes the mass matrix in h2
241 this%coef%h2 = 1.0_rp
242 end if
243 this%coef%ifh2 = .true.
244
245 ! compute the A(F_in) component of the RHS
246 ! (note, to be safe with the inout intent we first copy F_in to the
247 ! temporary d_F_out)
248 call field_copy(d_f_out, f_in)
249 call this%Ax%compute(rhs%x, d_f_out%x, this%coef, this%coef%msh, &
250 this%coef%Xh)
251
252 if (neko_bcknd_device .eq. 1) then
253 call device_subcol3(rhs%x_d, f_in%x_d, this%coef%B_d, n)
254 call device_cmult(rhs%x_d, -1.0_rp, n)
255 else
256 do i = 1, n
257 ! mass matrix should be included here
258 rhs%x(i,1,1,1) = f_in%x(i,1,1,1) * this%coef%B(i,1,1,1) &
259 - rhs%x(i,1,1,1)
260 end do
261 end if
262
263 ! gather scatter
264 call this%coef%gs_h%op(rhs, gs_op_add)
265
266 ! set BCs
267 call this%bc_projector_filt%apply(rhs%x, n)
268
269 ! Solve Helmholtz equation
270 call profiler_start_region("filter solve")
271 this%ksp_results(1) = &
272 this%ksp_filt%solve(this%Ax, d_f_out, rhs%x, n, this%coef, &
273 this%bc_projector_filt, this%coef%gs_h)
274
276
277 ! add result
278 call field_add3(f_out, f_in, d_f_out)
279 ! update preconditioner (needed?)
280 call this%pc_filt%update()
281
282 ! write it all out
283 call neko_log%section('PDE Filter')
284
285 write(log_buf, '(A,A,A)') 'Iterations: ', 'Start residual: ', &
286 'Final residual:'
287 call neko_log%message(log_buf)
288 write(log_buf, '(I11,3x, E15.7,5x, E15.7)') this%ksp_results%iter, &
289 this%ksp_results%res_start, this%ksp_results%res_final
290 call neko_log%message(log_buf)
291 call neko_log%end_section()
292
293 call neko_scratch_registry%relinquish_field(temp_indices)
294
295 end subroutine pde_filter_apply
296
298 subroutine filter_precon_factory(pc, ksp, coef, dof, gs, bc_projector, &
299 pctype)
300 class(pc_t), allocatable, target, intent(inout) :: pc
301 class(ksp_t), target, intent(inout) :: ksp
302 type(coef_t), target, intent(in) :: coef
303 type(dofmap_t), target, intent(in) :: dof
304 type(gs_t), target, intent(inout) :: gs
305 type(scalar_bc_projector_t), target, intent(inout) :: bc_projector
306 character(len=*) :: pctype
307
308 call precon_allocator(pc, pctype)
309
310 select type (pcp => pc)
311 type is (jacobi_t)
312 call pcp%init(coef, dof, gs)
313 type is (sx_jacobi_t)
314 call pcp%init(coef, dof, gs)
315 type is (device_jacobi_t)
316 call pcp%init(coef, dof, gs)
317 end select
318
319 call ksp%set_pc(pc)
320
321 end subroutine filter_precon_factory
322
323end module pde_filter
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 Matrix-vector product.
Definition ax.f90:34
Defines a list of bc_t.
Definition bc_list.f90:34
Coefficients.
Definition coef.f90:34
Jacobi preconditioner accelerator backend.
subroutine, public device_cmult(a_d, c, n, strm)
Multiplication by constant c .
subroutine, public device_subcol3(a_d, b_d, c_d, n, strm)
Returns .
subroutine, public device_cfill(a_d, c, n, strm)
Set all elements to a constant c .
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
subroutine, public field_copy(a, b, n)
Copy a vector .
subroutine, public field_add3(a, b, c, n)
Vector addition .
Defines a field.
Definition field.f90:34
Filter to be applied to a scalar field.
Definition filter.f90:38
Gather-scatter.
Jacobi preconditioner.
Definition pc_jacobi.f90:34
Utilities for retrieving parameters from the case files.
Implements the base abstract type for Krylov solvers plus helper types.
Definition krylov.f90:34
integer, parameter, public ksp_max_iter
Maximum number of iters.
Definition krylov.f90:52
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
Defines a mesh.
Definition mesh.f90:34
integer, parameter, public neko_msh_max_zlbls
Max num. zone labels.
Definition mesh.f90:65
integer, parameter, public neko_msh_max_zlbl_len
Max length of a zone label.
Definition mesh.f90:67
Build configurations.
integer, parameter neko_bcknd_device
Defines a Neumann boundary condition.
Definition neumann.f90:34
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
A PDE based filter.
subroutine pde_filter_free(this)
Destructor.
subroutine pde_filter_init_from_json(this, json, coef)
Constructor from json.
subroutine filter_precon_factory(pc, ksp, coef, dof, gs, bc_projector, pctype)
Initialize a Krylov preconditioner.
subroutine pde_filter_init_from_components(this, coef, r, tol, max_iter, ksp_solver, precon_type)
Actual constructor.
subroutine pde_filter_apply(this, f_out, f_in)
Apply the filter.
Defines Pressure and velocity residuals in the Pn-Pn formulation.
Definition pnpn_res.f90:34
Krylov preconditioner.
Definition precon.f90:34
Profiling interface.
Definition profiler.F90:34
subroutine, public profiler_start_region(name, region_id)
Started a named (name) profiler region.
Definition profiler.F90:79
subroutine, public profiler_end_region(name, region_id)
End the most recently started profiler region.
Definition profiler.F90:116
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_projector_t.
Defines a registry for storing and requesting temporary objects This can be used when you have a func...
type(scratch_registry_t), target, public neko_scratch_registry
Global scratch registry.
Jacobi preconditioner SX-Aurora backend.
Utilities.
Definition utils.f90:35
Base type for a matrix-vector product providing .
Definition ax.f90:43
A list of allocatable `bc_t`. Follows the standard interface of lists.
Definition bc_list.f90:49
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:93
Defines a jacobi preconditioner.
Base abstract class for filter.
Definition filter.f90:47
Gather-scatter kernel.
Defines a jacobi preconditioner.
Definition pc_jacobi.f90:45
Type for storing initial and final residuals in a Krylov solver.
Definition krylov.f90:57
Base abstract type for a canonical Krylov method, solving .
Definition krylov.f90:74
A Neumann boundary condition. Sets the flux of the field to the chosen values.
Definition neumann.f90:60
A PDE based filter mapping , see Lazarov & O. Sigmund 2010, by solving an equation of the form .
Abstract type to compute pressure residual.
Definition pnpn_res.f90:48
Defines a canonical Krylov preconditioner.
Definition precon.f90:40
Projector for scalar boundary conditions.
Defines a jacobi preconditioner for SX-Aurora.