10#include "scaleFElib.h"
20 use scale_prc,
only: prc_abort
72 procedure :: final => multigridsolver3d_final
73 procedure :: solve => multigridsolver3d_solve
74 procedure :: do_vcycle => multigridsolver3d_do_vcycle
76 procedure :: do_hmg_vcycle => multigridsolver3d_do_hmg_vcycle
77 procedure :: operate_pmg_restriction => multigridsolver3d_operate_pmg_restriction
78 procedure :: operate_pmg_correction => multigridsolver3d_operate_pmg_correction
79 procedure :: operate_hmg_restriction => multigridsolver3d_operate_hmg_restriction
80 procedure :: operate_hmg_correction => multigridsolver3d_operate_hmg_correction
101 mesh_hierarchy, mg_smoother, &
102 aux_var_num, aux_vec_num )
108 integer,
intent(in) :: aux_var_num
109 integer,
intent(in) :: aux_vec_num
117 this%mesh_hierarchy_ptr => mesh_hierarchy
118 this%mg_smoother_ptr => mg_smoother
121 allocate( this%fields_p( mesh_hierarchy%NUM_pMG_LEVEL ) )
122 do lev_p=1, mesh_hierarchy%NUM_pMG_LEVEL
123 call this%fields_p(lev_p)%Init( mesh_hierarchy%p_mesh_list(lev_p)%ptr, &
124 aux_var_num, aux_vec_num, lev_p )
128 allocate( this%fields_h( mesh_hierarchy%NUM_hMG_LEVEL ) )
129 do lev_h=1, mesh_hierarchy%NUM_hMG_LEVEL
130 call this%fields_h(lev_h)%Init( mesh_hierarchy%h_mesh_list(lev_h)%ptr, &
131 aux_var_num, aux_vec_num, lev_h )
138 subroutine multigridsolver3d_final(this)
149 if (
allocated(this%fields_p) )
then
150 do lev_p=1, this%mesh_hierarchy_ptr%NUM_pMG_LEVEL
151 call this%fields_p(lev_p)%Final()
154 deallocate( this%fields_p )
156 if (
allocated(this%fields_h) )
then
157 do lev_h=1, this%mesh_hierarchy_ptr%NUM_hMG_LEVEL
158 call this%fields_h(lev_h)%Final()
161 deallocate( this%fields_h )
164 end subroutine multigridsolver3d_final
168 subroutine multigridsolver3d_solve(this, q, &
183 do ldomid=1, q%mesh%LOCAL_MESH_NUM
184 lmesh => q%mesh%lcmesh_list(ldomid)
185 do ke=lmesh%NeS, lmesh%NeE
186 this%fields_p(pmg_finest_level)%dq%local(ldomid)%val(:,ke) = q%local(ldomid)%val(:,ke)
190 this%current_p_lev = pmg_finest_level-1
191 this%current_h_lev = hmg_finest_level-1
194 do vcyc_itr=1, this%vcyc_num_max
195 log_info(
"MultiGridSolver3D_solve",*)
"V-cycle iteration:", vcyc_itr
197 call this%do_Vcycle( pmg_finest_level, f, vcyc_itr )
198 if ( this%Is_converged(this%mg_smoother_ptr) )
then
199 log_info(
"MultiGridSolver3D_solve",*)
"V-cycle converged: vcyc_itr=", vcyc_itr
205 do ldomid=1, q%mesh%LOCAL_MESH_NUM
206 lmesh => q%mesh%lcmesh_list(ldomid)
207 do ke=lmesh%NeS, lmesh%NeE
208 q%local(ldomid)%val(:,ke) = this%fields_p(pmg_finest_level)%dq%local(ldomid)%val(:,ke)
212 end subroutine multigridsolver3d_solve
216 recursive subroutine multigridsolver3d_do_vcycle( this, &
217 mg_level, f_in, vcyc_itr )
220 integer,
intent(in) :: mg_level
222 integer,
intent(in) :: vcyc_itr
224 logical :: invoke_hMG
230 this%current_p_lev = this%current_p_lev + 1
232 mesh_hierarchy => this%mesh_hierarchy_ptr
233 fs_p => this%fields_p(mg_level)
235 log_info(
"MultiGridSolver3D_do_Vcycle",*)
"Start: p_level=", this%current_p_lev
238 call this%mg_smoother_ptr%Do_smoothing( fs_p%dq, fs_p%res, &
239 f_in, fs_p%aux_var, fs_p%var_comm_ptr, fs_p%aux_comm_ptr, &
240 fs_p%Dx, fs_p%Dy, fs_p%Dz, fs_p%Lift, mesh_hierarchy%p_mesh_list(mg_level)%ptr, &
243 if ( vcyc_itr == 1 .and. this%current_p_lev == pmg_finest_level )
then
244 call this%mg_smoother_ptr%Get_initial_residual_statistics( &
245 this%history_residual_l2_initial, this%history_residual_max_initial )
247 call this%mg_smoother_ptr%Output_residual_history()
251 if ( mg_level == mesh_hierarchy%NUM_pMG_LEVEL .and. mesh_hierarchy%NUM_hMG_LEVEL == 0 )
then
253 log_info(
"MultiGridSolver3D_do_Vcycle",*)
"End: p_level=", this%current_p_lev
254 this%current_p_lev = this%current_p_lev - 1
259 invoke_hmg = ( mg_level+1 >= mesh_hierarchy%NUM_pMG_LEVEL .and. mesh_hierarchy%NUM_hMG_LEVEL > 0 )
261 if ( invoke_hmg )
then
263 call this%Operate_pMG_restriction( this%fields_h(hmg_finest_level)%f, &
264 this%fields_p(mg_level)%res, mg_level )
267 call this%do_hMG_Vcycle( hmg_finest_level, this%fields_h(hmg_finest_level)%f )
270 call this%Operate_pMG_correction( this%fields_p(mg_level)%dq, &
271 this%fields_h(hmg_finest_level)%dq, mg_level )
274 call this%Operate_pMG_restriction( this%fields_p(mg_level+1)%f, &
275 this%fields_p(mg_level)%res, mg_level )
278 call this%do_Vcycle( mg_level+1, this%fields_p(mg_level+1)%f, vcyc_itr )
281 call this%Operate_pMG_correction( this%fields_p(mg_level)%dq, &
282 this%fields_p(mg_level+1)%dq, mg_level )
286 call this%mg_smoother_ptr%Do_smoothing( fs_p%dq, fs_p%res, &
287 f_in, fs_p%aux_var, fs_p%var_comm_ptr, fs_p%aux_comm_ptr, &
288 fs_p%Dx, fs_p%Dy, fs_p%Dz, fs_p%Lift, mesh_hierarchy%p_mesh_list(mg_level)%ptr, &
293 call this%mg_smoother_ptr%Output_residual_history()
294 log_info(
"MultiGridSolver3D_do_Vcycle",*)
"End: p_level=", this%current_p_lev
296 this%current_p_lev = this%current_p_lev - 1
298 end subroutine multigridsolver3d_do_vcycle
301 recursive subroutine multigridsolver3d_do_hmg_vcycle( this, mg_level, f_in )
304 integer,
intent(in) :: mg_level
311 mesh_hierarchy => this%mesh_hierarchy_ptr
312 fs_h => this%fields_h(mg_level)
314 this%current_h_lev = this%current_h_lev + 1
316 log_info(
"MultiGridSolver3D_do_hMG_Vcycle",*)
"Start: h_level=", this%current_h_lev
318 if ( mg_level == mesh_hierarchy%NUM_hMG_LEVEL )
then
320 call this%mg_smoother_ptr%Do_smoothing( fs_h%dq, fs_h%res, &
321 f_in, fs_h%aux_var, fs_h%var_comm_ptr, fs_h%aux_comm_ptr, &
322 fs_h%Dx, fs_h%Dy, fs_h%Dz, fs_h%Lift, mesh_hierarchy%h_mesh_list(mg_level)%ptr, &
325 call this%mg_smoother_ptr%Output_residual_history()
327 log_info(
"MultiGridSolver3D_do_hMG_Vcycle",*)
"End: h_level=", this%current_h_lev
328 this%current_h_lev = this%current_h_lev - 1
333 call this%mg_smoother_ptr%Do_smoothing( fs_h%dq, fs_h%res, &
334 f_in, fs_h%aux_var, fs_h%var_comm_ptr, fs_h%aux_comm_ptr, &
335 fs_h%Dx, fs_h%Dy, fs_h%Dz, fs_h%Lift, mesh_hierarchy%h_mesh_list(mg_level)%ptr, &
339 call this%Operate_hMG_restriction( this%fields_h(mg_level+1)%f, &
340 this%fields_h(mg_level)%res, mg_level )
343 call this%do_hMG_Vcycle( mg_level+1, this%fields_h(mg_level+1)%f )
346 call this%Operate_hMG_correction( this%fields_h(mg_level)%dq, &
347 this%fields_h(mg_level+1)%dq, mg_level )
350 call this%mg_smoother_ptr%Do_smoothing( fs_h%dq, fs_h%res, &
351 f_in, fs_h%aux_var, fs_h%var_comm_ptr, fs_h%aux_comm_ptr, &
352 fs_h%Dx, fs_h%Dy, fs_h%Dz, fs_h%Lift, mesh_hierarchy%h_mesh_list(mg_level)%ptr, &
355 log_info(
"MultiGridSolver3D_do_hMG_Vcycle",*)
"End: h_level=", this%current_h_lev
356 this%current_h_lev = this%current_h_lev - 1
358 end subroutine multigridsolver3d_do_hmg_vcycle
362 subroutine multigridsolver3d_operate_pmg_restriction( this, res_c, &
368 integer,
intent(in) :: p_lev
375 if ( this%mesh_hierarchy_ptr%NUM_pMG_LEVEL < p_lev+1 )
then
379 hierarchy => this%mesh_hierarchy_ptr
380 mesh3d => hierarchy%p_mesh_list(p_lev)%ptr
381 do ldomid=1, mesh3d%LOCAL_MESH_NUM
382 call multigridsolver3d_pmg_operation( res_c%local(ldomid)%val, &
383 res%local(ldomid)%val, &
384 hierarchy%elem3D_list(p_lev), hierarchy%elem3D_list(p_lev+1), &
385 mesh3d%lcmesh_list(ldomid), hierarchy%p_level(p_lev)%pMat1D_f2c, &
389 end subroutine multigridsolver3d_operate_pmg_restriction
392 subroutine multigridsolver3d_operate_pmg_correction( this, dq, &
398 integer,
intent(in) :: p_lev
406 hierarchy => this%mesh_hierarchy_ptr
407 mesh3d => hierarchy%p_mesh_list(p_lev)%ptr
409 do ldomid=1, mesh3d%LOCAL_MESH_NUM
410 call multigridsolver3d_pmg_operation( dq%local(ldomid)%val, &
411 cor_c%local(ldomid)%val, &
412 hierarchy%elem3D_list(p_lev+1), hierarchy%elem3D_list(p_lev), &
413 mesh3d%lcmesh_list(ldomid), hierarchy%p_level(p_lev)%pMat1D_c2f, &
417 end subroutine multigridsolver3d_operate_pmg_correction
420 subroutine multigridsolver3d_operate_hmg_restriction( this, res_c, &
427 integer,
intent(in) :: h_lev
436 hierarchy => this%mesh_hierarchy_ptr
437 mesh3d => hierarchy%h_mesh_list(h_lev)%ptr
438 mesh3d_c => hierarchy%h_mesh_list(h_lev+1)%ptr
440 do ldomid=1, mesh3d%LOCAL_MESH_NUM
441 call multigridsolver3d_hmg_restriction_core( res_c%local(ldomid)%val, &
442 res%local(ldomid)%val, &
443 hierarchy%h_level(h_lev)%mg_local(ldomid), mesh3d%lcmesh_list(ldomid), &
444 hierarchy%elem3D_list(hierarchy%NUM_pMG_LEVEL), mesh3d_c%lcmesh_list(ldomid) )
447 end subroutine multigridsolver3d_operate_hmg_restriction
450 subroutine multigridsolver3d_operate_hmg_correction( this, dq, &
457 integer,
intent(in) :: h_lev
464 hierarchy => this%mesh_hierarchy_ptr
465 mesh3d => hierarchy%h_mesh_list(h_lev)%ptr
467 do ldomid=1, mesh3d%LOCAL_MESH_NUM
468 call multigridsolver3d_hmg_correction_core( dq%local(ldomid)%val, &
469 cor_c%local(ldomid)%val, hierarchy%h_level(h_lev)%mg_local(ldomid), &
470 mesh3d%lcmesh_list(ldomid), mesh3d%refElem3D )
473 end subroutine multigridsolver3d_operate_hmg_correction
478 subroutine output_tmp_data( this, fs, fin, vcyc_itr, postfix )
479 use scale_prc,
only: prc_myrank
485 class(meshfield3d),
intent(in) :: fin
486 integer,
intent(in) :: vcyc_itr
487 character(len=*),
intent(in) :: postfix
491 character(len=H_MID) :: fname
492 logical :: fileexisted
494 integer,
parameter :: DQ_VID = 1
495 integer,
parameter :: RES_VID = 2
496 integer,
parameter :: FIN_VID = 3
499 select type (mesh => fs%dq%mesh)
501 call file%Init(2, mesh3d=mesh)
504 write(fname,
'(a,i2.2,a,i2.2,a)')
"tmp_plev", this%current_p_lev,
"_vcyc", vcyc_itr, trim(postfix)
505 call file%Create( fname,
"MG",
"REAL8", fileexisted, myrank=prc_myrank )
511 call file%Write_var3D( dq_vid, fs%dq, 0.0_rp, 1.0_rp)
512 call file%Write_var3D( res_vid, fs%res, 0.0_rp, 1.0_rp)
513 call file%Write_var3D( fin_vid, fin, 0.0_rp, 1.0_rp)
517 end subroutine output_tmp_data
520 subroutine multigridsolver3d_hmg_restriction_core( res_c_lc, &
521 res_lc, mg_local, lmesh, elem, lmesh_c )
526 real(RP),
intent(out) :: res_c_lc(elem%Np,lmesh_c%NeA)
527 real(RP),
intent(in) :: res_lc(elem%Np,lmesh%NeA)
530 integer :: k, ke, ke_c
531 real(RP) :: Ic2fT_lc(8,8)
532 real(RP) :: tmp_c(elem%Np)
533 real(RP) :: tmp2(elem%Np)
538 do ke_c=lmesh_c%NeS, lmesh_c%NeE
542 ke = mg_local%If2c_emap(k,ke_c)
544 tmp2(:) = matmul( elem%M, res_lc(:,ke) )
545 ic2ft_lc(:,:) = transpose( mg_local%Ic2f(:,:,ke) )
546 tmp_c(:) = tmp_c(:) + matmul( ic2ft_lc, tmp2(:) )
549 res_c_lc(:,ke_c) = matmul(lmesh_c%refElem3D%invM, tmp_c(:)) * 0.25_rp
553 end subroutine multigridsolver3d_hmg_restriction_core
556 subroutine multigridsolver3d_hmg_correction_core( dq_lc, &
557 dq_c_lc, mg_local, lmesh, elem )
561 real(RP),
intent(out) :: dq_lc(elem%Np,lmesh%NeA)
562 real(RP),
intent(in) :: dq_c_lc(elem%Np,lmesh%NeA)
565 integer :: k, ke, ke_c
569 do ke=lmesh%NeS, lmesh%NeE
570 ke_c = mg_local%Ic2f_emap(ke)
571 dq_lc(:,ke) = dq_lc(:,ke) + &
572 matmul( mg_local%Ic2f(:,:,ke), dq_c_lc(:,ke_c) )
575 end subroutine multigridsolver3d_hmg_correction_core
578 subroutine multigridsolver3d_pmg_operation( q_o, &
579 q_i, elem3D_i, elem3D_o, lcmesh, pMat1D, is_added )
584 real(RP),
intent(inout) :: q_o(elem3D_o%Nnode_h1D,elem3D_o%Nnode_h1D,elem3D_o%Nnode_v,lcmesh%NeA)
585 real(RP),
intent(in) :: q_i(elem3D_i%Nnode_h1D,elem3D_i%Nnode_h1D,elem3D_i%Nnode_v,lcmesh%NeA)
586 real(RP),
intent(in) :: pMat1D(elem3D_o%Nnode_h1D,elem3D_i%Nnode_h1D)
587 logical,
intent(in) :: is_added
591 integer :: px, py, pz
592 integer :: pxx, pyy, pzz
594 real(RP) :: tmp2(elem3D_o%Nnode_h1D,elem3D_i%Nnode_h1D)
595 real(RP) :: tmp3(elem3D_o%Nnode_h1D,elem3D_o%Nnode_h1D,elem3D_i%Nnode_v)
596 real(RP) :: tmp4(elem3D_o%Nnode_h1D)
597 real(RP) :: tmp_h(elem3D_o%Nnode_h1D,elem3D_o%Nnode_h1D)
599 real(RP) :: mat_tr(elem3D_i%Nnode_h1D,elem3D_o%Nnode_h1D)
602 mat_tr(:,:) = transpose(pmat1d)
605 do ke=lcmesh%NeS, lcmesh%NeE
607 do pz=1, elem3d_i%Nnode_v
608 do py=1, elem3d_i%Nnode_h1D
609 do pxx=1, elem3d_o%Nnode_h1D
611 do px=1, elem3d_i%Nnode_h1D
612 tmp1 = tmp1 + mat_tr(px,pxx) * q_i(px,py,pz,ke)
618 do pyy=1, elem3d_o%Nnode_h1D
620 do py=1, elem3d_i%Nnode_h1D
621 do px=1, elem3d_o%Nnode_h1D
622 tmp4(px) = tmp4(px) + mat_tr(py,pyy) * tmp2(px,py)
625 tmp3(:,pyy,pz) = tmp4(:)
630 do pzz=1, elem3d_o%Nnode_v
632 do pz=1, elem3d_i%Nnode_v
633 do py=1, elem3d_o%Nnode_h1D
634 do px=1, elem3d_o%Nnode_h1D
635 tmp_h(px,py) = tmp_h(px,py) + mat_tr(pz,pzz) * tmp3(px,py,pz)
639 q_o(:,:,pzz,ke) = q_o(:,:,pzz,ke) + tmp_h(:,:)
642 do pzz=1, elem3d_o%Nnode_v
644 do pz=1, elem3d_i%Nnode_v
645 do py=1, elem3d_o%Nnode_h1D
646 do px=1, elem3d_o%Nnode_h1D
647 tmp_h(px,py) = tmp_h(px,py) + mat_tr(pz,pzz) * tmp3(px,py,pz)
651 q_o(:,:,pzz,ke) = tmp_h(:,:)
656 end subroutine multigridsolver3d_pmg_operation
module FElib / Element / Base
module FElib / Element / hexahedron
module FElib / Element / Quadrilateral
module FElib / File / Base
module FElib / Mesh / Local 3D
module FElib / Mesh / Base 3D
integer, public meshbase3d_dimtypeid_xyz
module FElib / Mesh / Cubic 3D domain
module FElib / Mesh / 3D 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 3D cubic domain
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 3D
subroutine multigridsolver3d_init(this, mesh_hierarchy, mg_smoother, aux_var_num, aux_vec_num)
Initialize an object for multigrid solver in 3D 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 3D reference element.
Derived type representing a hexahedral element.
Derived type representing a quadrilateral element.
Derived type to manage file output with MeshField data.
Derived type to manage a local 3D computational domain.
Derived type to manage a computational mesh (base type for 3D domain)
Derived type to manage a cubic 3D computational domain.
Derived type for mesh hierarchy in 3D domain.
Derived type to represent mesh hierarchy level in 3D domain.
Derived type to manage 3D local mesh data for multigrid.
Derived type to manage a rectangular 2D computational domain.
Derived type representing a field with 2D mesh.
Derived type representing a field with 3D mesh.
Base derived type to manage data communication with 3D cubic domain.
Base derived type to manage data communication with 2D rectangle domain.
Derived type for 3D multigrid field set.
Derived type for 3D multigrid smoother.
Derived type for multigrid solver in 3D domain.
Base type for multigrid solver.
Derived type to manage a sparse matrix.