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
234 call device_cfill(this%coef%h1_d, this%r**2, n)
235 call device_cfill(this%coef%h2_d, 1.0_rp, n)
238 this%coef%h1 = this%r**2
240 this%coef%h2 = 1.0_rp
242 this%coef%ifh2 = .true.
247 call field_copy(d_x_out, x_in)
248 call this%Ax%compute(rhs%x, d_x_out%x, this%coef, this%coef%msh, &
251 if (neko_bcknd_device .eq. 1)
then
252 call device_subcol3(rhs%x_d, x_in%x_d, this%coef%B_d, n)
253 call device_cmult(rhs%x_d, -1.0_rp, n)
257 rhs%x(i,1,1,1) = x_in%x(i,1,1,1) * this%coef%B(i,1,1,1) &
263 call this%coef%gs_h%op(rhs, gs_op_add)
266 call this%bclst_filt%apply_scalar(rhs%x, n)
269 call profiler_start_region(
'filter solve')
270 this%ksp_results(1) = &
271 this%ksp_filt%solve(this%Ax, d_x_out, rhs%x, n, this%coef, &
272 this%bclst_filt, this%coef%gs_h)
274 call profiler_end_region
277 call field_add3(x_out, x_in, d_x_out)
279 call this%pc_filt%update()
282 call neko_log%message(
'Filter')
284 write(log_buf,
'(A,A,A)')
'Iterations: ',&
285 'Start residual: ',
'Final residual:'
286 call neko_log%message(log_buf)
287 write(log_buf,
'(I11,3x, E15.7,5x, E15.7)') this%ksp_results%iter, &
288 this%ksp_results%res_start, this%ksp_results%res_final
289 call neko_log%message(log_buf)
291 call neko_scratch_registry%relinquish_field(temp_indices)
295 end subroutine pde_filter_forward_mapping
316 subroutine pde_filter_backward_mapping(this, sens_out, sens_in, X_in)
318 type(field_t),
intent(in) :: X_in
319 type(field_t),
intent(in) :: sens_in
320 type(field_t),
intent(inout) :: sens_out
322 type(field_t),
pointer :: RHS, delta
323 integer :: temp_indices(2)
324 character(len=LOG_SIZE) :: log_buf
326 n = this%coef%dof%size()
328 call neko_scratch_registry%request_field(rhs, temp_indices(1))
329 call neko_scratch_registry%request_field(delta, temp_indices(2))
332 if (neko_bcknd_device .eq. 1)
then
335 call device_cfill(this%coef%h1_d, this%r**2, n)
336 call device_cfill(this%coef%h2_d, 1.0_rp, n)
339 this%coef%h1 = this%r**2
341 this%coef%h2 = 1.0_rp
343 this%coef%ifh2 = .true.
348 call field_copy(delta, sens_in)
349 call this%Ax%compute(rhs%x, delta%x, this%coef, this%coef%msh, &
352 if (neko_bcknd_device .eq. 1)
then
353 call device_subcol3(rhs%x_d, sens_in%x_d, this%coef%B_d, n)
354 call device_cmult(rhs%x_d, -1.0_rp, n)
358 rhs%x(i,1,1,1) = sens_in%x(i,1,1,1) * this%coef%B(i,1,1,1) &
364 call this%coef%gs_h%op(rhs, gs_op_add)
367 call this%bclst_filt%apply_scalar(rhs%x, n)
370 call profiler_start_region(
'filter solve')
371 this%ksp_results(1) = &
372 this%ksp_filt%solve(this%Ax, delta, rhs%x, n, this%coef, &
373 this%bclst_filt, this%coef%gs_h)
376 call field_add3(sens_out, sens_in, delta)
378 call profiler_end_region
381 call this%pc_filt%update()
384 call neko_log%message(
'Filter')
386 write(log_buf,
'(A,A,A)')
'Iterations: ',&
387 'Start residual: ',
'Final residual:'
388 call neko_log%message(log_buf)
389 write(log_buf,
'(I11,3x, E15.7,5x, E15.7)') this%ksp_results%iter, &
390 this%ksp_results%res_start, this%ksp_results%res_final
391 call neko_log%message(log_buf)
393 call neko_scratch_registry%relinquish_field(temp_indices)
395 end subroutine pde_filter_backward_mapping
397 subroutine filter_precon_factory(pc, ksp, coef, dof, gs, bclst, pctype)
400 class(pc_t),
allocatable,
target,
intent(inout) :: pc
401 class(ksp_t),
target,
intent(inout) :: ksp
402 type(coef_t),
target,
intent(in) :: coef
403 type(dofmap_t),
target,
intent(in) :: dof
404 type(gs_t),
target,
intent(inout) :: gs
405 type(bc_list_t),
target,
intent(inout) :: bclst
406 character(len=*) :: pctype
408 call precon_factory(pc, pctype)
410 select type (pcp => pc)
412 call pcp%init(coef, dof, gs)
413 type is (sx_jacobi_t)
414 call pcp%init(coef, dof, gs)
415 type is (device_jacobi_t)
416 call pcp%init(coef, dof, gs)
421 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 .