36 use num_types,
only: rp
37 use json_module,
only: json_file
38 use field_registry,
only: neko_field_registry
39 use field,
only: field_t
40 use coefs,
only: coef_t
41 use ax_product,
only: ax_t, ax_helm_factory
42 use krylov,
only: ksp_t, ksp_monitor_t, krylov_solver_factory
43 use precon,
only: pc_t, precon_factory, precon_destroy
44 use bc_list,
only: bc_list_t
45 use neumann,
only: neumann_t
46 use profiler,
only: profiler_start_region, profiler_end_region
47 use gather_scatter,
only: gs_t, gs_op_add
48 use pnpn_residual,
only: pnpn_prs_res_t
49 use mesh,
only: mesh_t, neko_msh_max_zlbls, neko_msh_max_zlbl_len
50 use field_registry,
only: neko_field_registry
52 use scratch_registry,
only: neko_scratch_registry
53 use field_math,
only: field_copy, field_add3
54 use coefs,
only: coef_t
55 use logger,
only: neko_log, log_size
56 use neko_config,
only: neko_bcknd_device
57 use dofmap,
only: dofmap_t
58 use jacobi,
only: jacobi_t
59 use device_jacobi,
only: device_jacobi_t
60 use sx_jacobi,
only: sx_jacobi_t
61 use utils,
only: neko_error
62 use device_math,
only: device_cfill, device_subcol3, device_cmult
63 use json_utils,
only: json_get, json_get_or_default
73 class(ax_t),
allocatable :: ax
75 type(ksp_monitor_t) :: ksp_results(1)
77 class(ksp_t),
allocatable :: ksp_filt
79 class(pc_t),
allocatable :: pc_filt
81 type(bc_list_t) :: bclst_filt
87 real(kind=rp) :: abstol_filt
89 integer :: ksp_max_iter
91 character(len=:),
allocatable :: ksp_solver
93 character(len=:),
allocatable :: precon_type_filt
94 integer :: ksp_n, n, i
100 procedure, pass(this) :: init => pde_filter_init_from_json
102 procedure, pass(this) :: init_from_attributes => &
103 pde_filter_init_from_attributes
105 procedure, pass(this) :: free => pde_filter_free
107 procedure, pass(this) :: forward_mapping => pde_filter_forward_mapping
117 procedure, pass(this) :: backward_mapping => pde_filter_backward_mapping
123 subroutine pde_filter_init_from_json(this, json, coef)
125 type(json_file),
intent(inout) :: json
126 type(coef_t),
intent(inout) :: coef
127 real(kind=rp) :: r, tol
129 character(len=:),
allocatable :: ksp_solver, precon_type
131 call json_get(json,
'r', r)
132 call json_get_or_default(json,
'tol', tol, 0.0000000001_rp)
133 call json_get_or_default(json,
'max_iter', max_iter, 200)
134 call json_get_or_default(json,
'solver', ksp_solver,
"cg")
135 call json_get_or_default(json,
'preconditioner', precon_type,
"jacobi")
137 call this%init_base(json, coef)
138 call this%init_from_attributes(coef, r, tol, max_iter, &
139 ksp_solver, precon_type)
141 end subroutine pde_filter_init_from_json
144 subroutine pde_filter_init_from_attributes(this, coef, r, tol, max_iter, &
145 ksp_solver, precon_type)
147 type(coef_t),
intent(inout) :: coef
148 real(kind=rp),
intent(in) :: r, tol
149 integer,
intent(in) :: max_iter
150 character(len=*),
intent(in) :: ksp_solver, precon_type
153 this%r = r / (2.0_rp * sqrt(3.0_rp))
154 this%abstol_filt = tol
155 this%ksp_max_iter = max_iter
156 this%ksp_solver = ksp_solver
157 this%precon_type_filt = precon_type
160 n = this%coef%dof%size()
163 call this%bclst_filt%init()
166 call ax_helm_factory(this%Ax, full_formulation = .false.)
169 call krylov_solver_factory(this%ksp_filt, n, this%ksp_solver, &
170 this%ksp_max_iter, this%abstol_filt)
173 call filter_precon_factory(this%pc_filt, this%ksp_filt, &
174 this%coef, this%coef%dof, this%coef%gs_h, this%bclst_filt, &
175 this%precon_type_filt)
177 end subroutine pde_filter_init_from_attributes
180 subroutine pde_filter_free(this)
183 if (
allocated(this%Ax))
then
187 if (
allocated(this%ksp_filt))
then
188 call this%ksp_filt%free()
189 deallocate(this%ksp_filt)
192 if (
allocated(this%pc_filt))
then
193 call precon_destroy(this%pc_filt)
194 deallocate(this%pc_filt)
197 call this%bclst_filt%free()
199 call this%free_base()
201 end subroutine pde_filter_free
207 subroutine pde_filter_forward_mapping(this, X_out, X_in)
209 type(field_t),
intent(in) :: X_in
210 type(field_t),
intent(inout) :: X_out
212 type(field_t),
pointer :: RHS, d_X_out
213 character(len=LOG_SIZE) :: log_buf
214 integer :: temp_indices(2)
216 n = this%coef%dof%size()
217 call neko_scratch_registry%request_field(rhs, temp_indices(1))
218 call neko_scratch_registry%request_field(d_x_out, temp_indices(2))
231 if (neko_bcknd_device .eq. 1)
then
232 call device_cfill(this%coef%h1_d, this%r**2, n)
233 call device_cfill(this%coef%h2_d, 1.0_rp, n)
236 this%coef%h1 = this%r**2
238 this%coef%h2 = 1.0_rp
240 this%coef%ifh2 = .true.
245 call field_copy(d_x_out, x_in)
246 call this%Ax%compute(rhs%x, d_x_out%x, this%coef, this%coef%msh, &
249 if (neko_bcknd_device .eq. 1)
then
250 call device_subcol3(rhs%x_d, x_in%x_d, this%coef%B_d, n)
251 call device_cmult(rhs%x_d, -1.0_rp, n)
255 rhs%x(i,1,1,1) = x_in%x(i,1,1,1) * this%coef%B(i,1,1,1) &
261 call this%coef%gs_h%op(rhs, gs_op_add)
264 call this%bclst_filt%apply_scalar(rhs%x, n)
267 call profiler_start_region(
'filter solve')
268 this%ksp_results(1) = &
269 this%ksp_filt%solve(this%Ax, d_x_out, rhs%x, n, this%coef, &
270 this%bclst_filt, this%coef%gs_h)
272 call profiler_end_region
275 call field_add3(x_out, x_in, d_x_out)
277 call this%pc_filt%update()
280 call neko_log%message(
'Filter')
282 write(log_buf,
'(A,A,A)')
'Iterations: ',&
283 'Start residual: ',
'Final residual:'
284 call neko_log%message(log_buf)
285 write(log_buf,
'(I11,3x, E15.7,5x, E15.7)') this%ksp_results%iter, &
286 this%ksp_results%res_start, this%ksp_results%res_final
287 call neko_log%message(log_buf)
289 call neko_scratch_registry%relinquish_field(temp_indices)
293 end subroutine pde_filter_forward_mapping
314 subroutine pde_filter_backward_mapping(this, sens_out, sens_in, X_in)
316 type(field_t),
intent(in) :: X_in
317 type(field_t),
intent(in) :: sens_in
318 type(field_t),
intent(inout) :: sens_out
320 type(field_t),
pointer :: RHS, delta
321 integer :: temp_indices(2)
322 character(len=LOG_SIZE) :: log_buf
324 n = this%coef%dof%size()
326 call neko_scratch_registry%request_field(rhs, temp_indices(1))
327 call neko_scratch_registry%request_field(delta, temp_indices(2))
330 if (neko_bcknd_device .eq. 1)
then
331 call device_cfill(this%coef%h1_d, this%r**2, n)
332 call device_cfill(this%coef%h2_d, 1.0_rp, n)
335 this%coef%h1 = this%r**2
337 this%coef%h2 = 1.0_rp
339 this%coef%ifh2 = .true.
344 call field_copy(delta, sens_in)
345 call this%Ax%compute(rhs%x, delta%x, this%coef, this%coef%msh, &
348 if (neko_bcknd_device .eq. 1)
then
349 call device_subcol3(rhs%x_d, sens_in%x_d, this%coef%B_d, n)
350 call device_cmult(rhs%x_d, -1.0_rp, n)
354 rhs%x(i,1,1,1) = sens_in%x(i,1,1,1) * this%coef%B(i,1,1,1) &
360 call this%coef%gs_h%op(rhs, gs_op_add)
363 call this%bclst_filt%apply_scalar(rhs%x, n)
366 call profiler_start_region(
'filter solve')
367 this%ksp_results(1) = &
368 this%ksp_filt%solve(this%Ax, delta, rhs%x, n, this%coef, &
369 this%bclst_filt, this%coef%gs_h)
372 call field_add3(sens_out, sens_in, delta)
374 call profiler_end_region
377 call this%pc_filt%update()
380 call neko_log%message(
'Filter')
382 write(log_buf,
'(A,A,A)')
'Iterations: ',&
383 'Start residual: ',
'Final residual:'
384 call neko_log%message(log_buf)
385 write(log_buf,
'(I11,3x, E15.7,5x, E15.7)') this%ksp_results%iter, &
386 this%ksp_results%res_start, this%ksp_results%res_final
387 call neko_log%message(log_buf)
389 call neko_scratch_registry%relinquish_field(temp_indices)
391 end subroutine pde_filter_backward_mapping
393 subroutine filter_precon_factory(pc, ksp, coef, dof, gs, bclst, pctype)
396 class(pc_t),
allocatable,
target,
intent(inout) :: pc
397 class(ksp_t),
target,
intent(inout) :: ksp
398 type(coef_t),
target,
intent(in) :: coef
399 type(dofmap_t),
target,
intent(in) :: dof
400 type(gs_t),
target,
intent(inout) :: gs
401 type(bc_list_t),
target,
intent(inout) :: bclst
402 character(len=*) :: pctype
404 call precon_factory(pc, pctype)
406 select type (pcp => pc)
408 call pcp%init(coef, dof, gs)
409 type is (sx_jacobi_t)
410 call pcp%init(coef, dof, gs)
411 type is (device_jacobi_t)
412 call pcp%init(coef, dof, gs)
417 end subroutine filter_precon_factory
Mappings to be applied to a scalar field.
Base abstract class for mapping.
A PDE based filter mapping , see Lazarov & O. Sigmund 2010, by solving an equation of the form .