10#include "scaleFElib.h"
20 use scale_prc,
only: prc_abort
68 procedure :: final => multigridsolver2d_final
69 procedure :: solve => multigridsolver2d_solve
70 procedure :: do_vcycle => multigridsolver2d_do_vcycle
72 procedure :: do_hmg_vcycle => multigridsolver2d_do_hmg_vcycle
73 procedure :: operate_pmg_restriction => multigridsolver2d_operate_pmg_restriction
74 procedure :: operate_pmg_correction => multigridsolver2d_operate_pmg_correction
75 procedure :: operate_hmg_restriction => multigridsolver2d_operate_hmg_restriction
76 procedure :: operate_hmg_correction => multigridsolver2d_operate_hmg_correction
97 mesh_hierarchy, mg_smoother, &
98 aux_var_num, aux_vec_num )
105 integer,
intent(in) :: aux_var_num
106 integer,
intent(in) :: aux_vec_num
114 this%mesh_hierarchy_ptr => mesh_hierarchy
115 this%mg_smoother_ptr => mg_smoother
118 allocate( this%fields_p( mesh_hierarchy%NUM_pMG_LEVEL ) )
119 do lev_p=1, mesh_hierarchy%NUM_pMG_LEVEL
120 call this%fields_p(lev_p)%Init( mesh_hierarchy%p_mesh_list(lev_p)%ptr, &
121 aux_var_num, aux_vec_num, lev_p )
125 allocate( this%fields_h( mesh_hierarchy%NUM_hMG_LEVEL ) )
126 do lev_h=1, mesh_hierarchy%NUM_hMG_LEVEL
127 call this%fields_h(lev_h)%Init( mesh_hierarchy%h_mesh_list(lev_h)%ptr, &
128 aux_var_num, aux_vec_num, lev_h )
135 subroutine multigridsolver2d_final(this)
146 if (
allocated(this%fields_p) )
then
147 do lev_p=1,
size(this%fields_p)
148 call this%fields_p(lev_p)%Final()
151 deallocate( this%fields_p )
153 if (
allocated(this%fields_h) )
then
154 do lev_h=1,
size(this%fields_h)
155 call this%fields_h(lev_h)%Final()
158 deallocate( this%fields_h )
161 end subroutine multigridsolver2d_final
165 subroutine multigridsolver2d_solve(this, q, &
180 do ldomid=1, q%mesh%LOCAL_MESH_NUM
181 lmesh => q%mesh%lcmesh_list(ldomid)
182 do ke=lmesh%NeS, lmesh%NeE
183 this%fields_p(pmg_finest_level)%dq%local(ldomid)%val(:,ke) = q%local(ldomid)%val(:,ke)
187 this%current_p_lev = pmg_finest_level-1
188 this%current_h_lev = hmg_finest_level-1
191 do vcyc_itr=1, this%vcyc_num_max
192 log_info(
"MultiGridSolver2D_solve",*)
"V-cycle iteration:", vcyc_itr
194 call this%do_Vcycle( pmg_finest_level, f, vcyc_itr )
195 if ( this%Is_converged(this%mg_smoother_ptr) )
then
196 log_info(
"MultiGridSolver2D_solve",*)
"V-cycle converged: vcyc_itr=", vcyc_itr
202 do ldomid=1, q%mesh%LOCAL_MESH_NUM
203 lmesh => q%mesh%lcmesh_list(ldomid)
204 do ke=lmesh%NeS, lmesh%NeE
205 q%local(ldomid)%val(:,ke) = this%fields_p(pmg_finest_level)%dq%local(ldomid)%val(:,ke)
209 end subroutine multigridsolver2d_solve
213 recursive subroutine multigridsolver2d_do_vcycle(this, mg_level, f_in, vcyc_itr)
216 integer,
intent(in) :: mg_level
218 integer,
intent(in) :: vcyc_itr
219 logical :: invoke_hMG
225 this%current_p_lev = this%current_p_lev + 1
227 mesh_hierarchy => this%mesh_hierarchy_ptr
228 fs_p => this%fields_p(mg_level)
230 log_info(
"MultiGridSolver2D_do_Vcycle",*)
"Start: p_level=", this%current_p_lev
233 call this%mg_smoother_ptr%Do_smoothing( fs_p%dq, fs_p%res, &
234 f_in, fs_p%aux_var, fs_p%var_comm_ptr, fs_p%aux_comm_ptr, &
235 fs_p%Dx, fs_p%Dy, fs_p%Lift, mesh_hierarchy%p_mesh_list(mg_level)%ptr, &
238 if ( vcyc_itr == 1 .and. this%current_p_lev == pmg_finest_level )
then
239 call this%mg_smoother_ptr%Get_initial_residual_statistics( &
240 this%history_residual_l2_initial, this%history_residual_max_initial )
242 call this%mg_smoother_ptr%Output_residual_history()
244 if ( mg_level == mesh_hierarchy%NUM_pMG_LEVEL .and. mesh_hierarchy%NUM_hMG_LEVEL == 0 )
then
245 log_info(
"MultiGridSolver2D_do_Vcycle",*)
"End: p_level=", this%current_p_lev
246 this%current_p_lev = this%current_p_lev - 1
251 invoke_hmg = ( mg_level+1 >= mesh_hierarchy%NUM_pMG_LEVEL .and. mesh_hierarchy%NUM_hMG_LEVEL > 0 )
253 if ( invoke_hmg )
then
255 call this%Operate_pMG_restriction( this%fields_h(hmg_finest_level)%f, &
256 this%fields_p(mg_level)%res, mg_level )
259 call this%do_hMG_Vcycle( hmg_finest_level, this%fields_h(hmg_finest_level)%f )
262 call this%Operate_pMG_correction( this%fields_p(mg_level)%dq, &
263 this%fields_h(hmg_finest_level)%dq, mg_level )
266 call this%Operate_pMG_restriction( this%fields_p(mg_level+1)%f, &
267 this%fields_p(mg_level)%res, mg_level )
270 call this%do_Vcycle( mg_level+1, this%fields_p(mg_level+1)%f, vcyc_itr )
273 call this%Operate_pMG_correction( this%fields_p(mg_level)%dq, &
274 this%fields_p(mg_level+1)%dq, mg_level )
278 call this%mg_smoother_ptr%Do_smoothing( fs_p%dq, fs_p%res, &
279 f_in, fs_p%aux_var, fs_p%var_comm_ptr, fs_p%aux_comm_ptr, &
280 fs_p%Dx, fs_p%Dy, fs_p%Lift, mesh_hierarchy%p_mesh_list(mg_level)%ptr, &
283 call this%mg_smoother_ptr%Output_residual_history()
284 log_info(
"MultiGridSolver2D_do_Vcycle",*)
"End: p_level=", this%current_p_lev
286 this%current_p_lev = this%current_p_lev - 1
288 end subroutine multigridsolver2d_do_vcycle
291 recursive subroutine multigridsolver2d_do_hmg_vcycle( this, mg_level, f_in )
294 integer,
intent(in) :: mg_level
301 mesh_hierarchy => this%mesh_hierarchy_ptr
302 fs_h => this%fields_h(mg_level)
304 this%current_h_lev = this%current_h_lev + 1
306 log_info(
"MultiGridSolver2D_do_hMG_Vcycle",*)
"Start: h_level=", this%current_h_lev
308 if ( mg_level == mesh_hierarchy%NUM_hMG_LEVEL )
then
310 call this%mg_smoother_ptr%Do_smoothing( fs_h%dq, fs_h%res, &
311 f_in, fs_h%aux_var, fs_h%var_comm_ptr, fs_h%aux_comm_ptr, &
312 fs_h%Dx, fs_h%Dy, fs_h%Lift, mesh_hierarchy%h_mesh_list(mg_level)%ptr, &
315 call this%mg_smoother_ptr%Output_residual_history()
317 log_info(
"MultiGridSolver2D_do_hMG_Vcycle",*)
"End: h_level=", this%current_h_lev
318 this%current_h_lev = this%current_h_lev - 1
323 call this%mg_smoother_ptr%Do_smoothing( fs_h%dq, fs_h%res, &
324 f_in, fs_h%aux_var, fs_h%var_comm_ptr, fs_h%aux_comm_ptr, &
325 fs_h%Dx, fs_h%Dy, fs_h%Lift, mesh_hierarchy%h_mesh_list(mg_level)%ptr, &
329 call this%Operate_hMG_restriction( this%fields_h(mg_level+1)%f, &
330 this%fields_h(mg_level)%res, mg_level )
333 call this%do_hMG_Vcycle( mg_level+1, this%fields_h(mg_level+1)%f )
336 call this%Operate_hMG_correction( this%fields_h(mg_level)%dq, &
337 this%fields_h(mg_level+1)%dq, mg_level )
340 call this%mg_smoother_ptr%Do_smoothing( fs_h%dq, fs_h%res, &
341 f_in, fs_h%aux_var, fs_h%var_comm_ptr, fs_h%aux_comm_ptr, &
342 fs_h%Dx, fs_h%Dy, fs_h%Lift, mesh_hierarchy%h_mesh_list(mg_level)%ptr, &
345 log_info(
"MultiGridSolver2D_do_hMG_Vcycle",*)
"End: h_level=", this%current_h_lev
346 this%current_h_lev = this%current_h_lev - 1
348 end subroutine multigridsolver2d_do_hmg_vcycle
352 subroutine multigridsolver2d_operate_pmg_restriction( this, res_c, &
358 integer,
intent(in) :: p_lev
365 if ( this%mesh_hierarchy_ptr%NUM_pMG_LEVEL < p_lev+1 )
then
369 hierarchy => this%mesh_hierarchy_ptr
370 mesh2d => hierarchy%p_mesh_list(p_lev)%ptr
371 do ldomid=1, mesh2d%LOCAL_MESH_NUM
372 call multigridsolver2d_pmg_operation( res_c%local(ldomid)%val, &
373 res%local(ldomid)%val, &
374 hierarchy%elem2D_list(p_lev), hierarchy%elem2D_list(p_lev+1), &
375 mesh2d%lcmesh_list(ldomid), hierarchy%p_level(p_lev)%pMat1D_f2c, &
379 end subroutine multigridsolver2d_operate_pmg_restriction
382 subroutine multigridsolver2d_operate_pmg_correction( this, dq, &
388 integer,
intent(in) :: p_lev
396 hierarchy => this%mesh_hierarchy_ptr
397 mesh2d => hierarchy%p_mesh_list(p_lev)%ptr
399 do ldomid=1, mesh2d%LOCAL_MESH_NUM
400 call multigridsolver2d_pmg_operation( dq%local(ldomid)%val, &
401 cor_c%local(ldomid)%val, &
402 hierarchy%elem2D_list(p_lev+1), hierarchy%elem2D_list(p_lev), &
403 mesh2d%lcmesh_list(ldomid), hierarchy%p_level(p_lev)%pMat1D_c2f, &
407 end subroutine multigridsolver2d_operate_pmg_correction
410 subroutine multigridsolver2d_operate_hmg_restriction( this, res_c, &
417 integer,
intent(in) :: h_lev
426 hierarchy => this%mesh_hierarchy_ptr
427 mesh2d => hierarchy%h_mesh_list(h_lev)%ptr
428 mesh2d_c => hierarchy%h_mesh_list(h_lev+1)%ptr
430 do ldomid=1, mesh2d%LOCAL_MESH_NUM
431 call multigridsolver2d_hmg_restriction_core( res_c%local(ldomid)%val, &
432 res%local(ldomid)%val, &
433 hierarchy%h_level(h_lev)%mg_local(ldomid), mesh2d%lcmesh_list(ldomid), &
434 hierarchy%elem2D_list(hierarchy%NUM_pMG_LEVEL), mesh2d_c%lcmesh_list(ldomid) )
437 end subroutine multigridsolver2d_operate_hmg_restriction
440 subroutine multigridsolver2d_operate_hmg_correction( this, dq, &
447 integer,
intent(in) :: h_lev
454 hierarchy => this%mesh_hierarchy_ptr
455 mesh2d => hierarchy%h_mesh_list(h_lev)%ptr
457 do ldomid=1, mesh2d%LOCAL_MESH_NUM
458 call multigridsolver2d_hmg_correction_core( dq%local(ldomid)%val, &
459 cor_c%local(ldomid)%val, hierarchy%h_level(h_lev)%mg_local(ldomid), &
460 mesh2d%lcmesh_list(ldomid), mesh2d%refElem2D )
463 end subroutine multigridsolver2d_operate_hmg_correction
469 subroutine multigridsolver2d_hmg_restriction_core( res_c_lc, &
470 res_lc, mg_local, lmesh, elem, lmesh_c )
475 real(RP),
intent(out) :: res_c_lc(elem%Np,lmesh_c%NeA)
476 real(RP),
intent(in) :: res_lc(elem%Np,lmesh%NeA)
479 integer :: k, ke, ke_c
480 real(RP) :: Ic2fT_lc(4,4)
481 real(RP) :: tmp_c(elem%Np)
482 real(RP) :: tmp2(elem%Np)
484 real(RP) :: int_tmp(lmesh_c%Ne)
490 do ke_c=lmesh_c%NeS, lmesh_c%NeE
494 ke = mg_local%If2c_emap(k,ke_c)
496 tmp2(:) = matmul( elem%M, res_lc(:,ke) )
498 ic2ft_lc(:,:) = transpose( mg_local%Ic2f(:,:,ke) )
499 tmp_c(:) = tmp_c(:) + matmul( ic2ft_lc, tmp2(:) )
502 res_c_lc(:,ke_c) = matmul(lmesh_c%refElem2D%invM, tmp_c(:)) * 0.25_rp
507 end subroutine multigridsolver2d_hmg_restriction_core
510 subroutine multigridsolver2d_hmg_correction_core( dq_lc, &
511 dq_c_lc, mg_local, lmesh, elem )
515 real(RP),
intent(out) :: dq_lc(elem%Np,lmesh%NeA)
516 real(RP),
intent(in) :: dq_c_lc(elem%Np,lmesh%NeA)
519 integer :: k, ke, ke_c
523 do ke=lmesh%NeS, lmesh%NeE
524 ke_c = mg_local%Ic2f_emap(ke)
525 dq_lc(:,ke) = dq_lc(:,ke) + &
526 matmul( mg_local%Ic2f(:,:,ke), dq_c_lc(:,ke_c) )
529 end subroutine multigridsolver2d_hmg_correction_core
532 subroutine multigridsolver2d_pmg_operation( q_o, &
533 q_i, elem2D_i, elem2D_o, lcmesh, pMat1D, is_added )
538 real(RP),
intent(inout) :: q_o(elem2D_o%Nfp,elem2D_o%Nfp,lcmesh%NeA)
539 real(RP),
intent(in) :: q_i(elem2D_i%Nfp,elem2D_i%Nfp,lcmesh%NeA)
540 real(RP),
intent(in) :: pMat1D(elem2D_o%Nfp,elem2D_i%Nfp)
541 logical,
intent(in) :: is_added
548 real(RP) :: tmp2(elem2D_o%Nfp,elem2D_i%Nfp)
549 real(RP) :: tmp3(elem2D_o%Nfp)
551 real(RP) :: mat_tr(elem2D_i%Nfp,elem2D_o%Nfp)
554 mat_tr(:,:) = transpose(pmat1d)
557 do ke=lcmesh%NeS, lcmesh%NeE
558 do py=1, elem2d_i%Nfp
559 do pxx=1, elem2d_o%Nfp
561 do px=1, elem2d_i%Nfp
562 tmp1 = tmp1 + mat_tr(px,pxx) * q_i(px,py,ke)
569 do pyy=1, elem2d_o%Nfp
571 do py=1, elem2d_i%Nfp
572 do px=1, elem2d_o%Nfp
573 tmp3(px) = tmp3(px) + mat_tr(py,pyy) * tmp2(px,py)
576 q_o(:,pyy,ke) = q_o(:,pyy,ke) + tmp3(:)
579 do pyy=1, elem2d_o%Nfp
581 do py=1, elem2d_i%Nfp
582 do px=1, elem2d_o%Nfp
583 tmp3(px) = tmp3(px) + mat_tr(py,pyy) * tmp2(px,py)
586 q_o(:,pyy,ke) = tmp3(:)
591 end subroutine multigridsolver2d_pmg_operation
module FElib / Element / Base
module FElib / Element / Quadrilateral
module FElib / Mesh / Local 2D
module FElib / Mesh / Base 2D
module FElib / Mesh / 2D domain
module FElib / Mesh / Hierarchy base
integer, parameter, public mesh_hierarchy_type_pmg
Type ID of mesh hierarchy: p-MG.
integer, parameter, public mesh_hierarchy_hmg_finest_level
Finest level index in h-MG.
integer, parameter, public mesh_hierarchy_type_hmg
Type ID of mesh hierarchy: h-MG.
integer, parameter, public mesh_hierarchy_pmg_finest_level
Finest level index in p-MG.
module FElib / Mesh / Rectangle 2D domain
module FElib / Data / base
module FElib / Data / Communication 2D rectangle domain
module FElib / Multigrid / Field set base
module FElib / Multigrid / Smoother base
integer, parameter, public mgsmoother_pre_id
ID to represent pre-smoothing.
integer, parameter, public mgsmoother_post_id
ID to represent post-smoothing.
module FElib / Multigrid / Solver 2D
subroutine multigridsolver2d_init(this, mesh_hierarchy, mg_smoother, aux_var_num, aux_vec_num)
Initialize an object for multigrid solver in 2D domain.
module FElib / Multigrid / Solver base
subroutine, public multigridsolverbase_final(this)
Finalize a base object for multigrid solver.
subroutine, public multigridsolverbase_init(this, mesh_hierarchy)
Initialize a base object for multigrid solver.
Module common / sparsemat.
Derived type representing a 2D reference element.
Derived type representing a quadrilateral element.
Derived type representing a local mesh for 2D domain.
Derived type to manage a computational mesh (base type for 2D domain)
Derived type for mesh hierarchy in 2D domain.
Derived type to represent mesh hierarchy level in 2D domain.
Derived type to manage 2D local mesh data for multigrid.
Derived type to manage a rectangular 2D computational domain.
Derived type representing a field with 2D mesh.
Base derived type to manage data communication with 2D rectangle domain.
Derived type for 2D multigrid field set.
Derived type for 2D multigrid smoother.
Derived type for multigrid solver in 2D domain.
Base type for multigrid solver.
Derived type to manage a sparse matrix.