!------------------------------------------------------------------------ ! Subroutine : ppm_mg_init !------------------------------------------------------------------------ ! ! Purpose : This routine initializes the solver for ! 2D and 3D problems ! ! Input : equation (I) : KIND OF EQUATION TO BE SOLVED ! FOR THE MOMENT ONLY POISSON ! ighostsize (I) : GHOSTSIZE ! ! smoother (I) : NOW GAUSS-SEIDEL ! ! [lda] (I) : LEADING DIMENSION, ONLY TO BE ! GIVEN FOR VECTOR CASES ! ! ibcdef (I) : ARRAY OF BOUNDARY CONDITION ! ! ! bcvalue (F) : ARRAY WHERE THE VALUES OF THE BC ! ARE STORED.IN CASE OF PERIODIC ! JUST GIVE ANY KIND OF VALUE ! ! limlev (I) :Number of levels that the user ! wants to coarse. ! ! wcycle (L) : TRUE if the user wants W-cycle. ! OTHERWISE FALSE ! lprint (L) : TRUE IF YOU WANT TO DUMP OUT ! INFORMATION ! ! omega (F) : relaxation parameter for SOR ! ! ! Input/output : ! ! Output : info (I) return status. 0 upon success. ! ! Remarks : PLEASE PAY ATTENTION THAT IN ORDER TO DIVIDE ! FURTHER A MESH IT SHOULD BE DIVISIBLE WITH 2. ! IF YOU WANT TO SOLVE DIFFERENT EQUATIONS ! THE WHOLE MACHINERY SHOULD BE CALLED TWICE. ! ALSO THE SOLVER IS NOW PROGRAMMED FOR THE POISSON ! PROBLEM. A FUTURE IMPROVEMENT WOULD BE ! TO USE A GENERAL STENCIL. ! ! References : ! ! Revisions : !------------------------------------------------------------------------ ! $Log: ppm_mg_init.f,v $ ! Revision 1.1.1.1 2007/07/13 10:18:56 ivos ! CBL version of the PPM library ! ! Revision 1.17 2006/09/26 16:01:22 ivos ! Fixed wrongly indented CPP directives. Remember: they have to start in ! Col 1, otherwise it does not compile on certain systems. In fact, this ! code did NOT compile as it was!! ! ! Revision 1.16 2006/09/05 08:01:27 pchatela ! Proper scaling for REAL comparisons ! Added module_alloc to ppm_decomp_boxsplit ! ! Revision 1.15 2006/07/21 11:30:54 kotsalie ! FRIDAY ! ! Revision 1.13 2006/06/08 08:38:18 kotsalie ! Cosmetics ! ! Revision 1.12 2006/06/08 08:27:37 kotsalie ! changed bcvalue to support different BCs on the same face but different sub ! ! Revision 1.8 2006/05/15 14:44:26 kotsalie ! cosmetics ! ! Revision 1.7 2006/02/03 09:34:03 ivos ! Fixed bug 00015: ppm_subs_bc was only allocated and stored for the ! local subs in topo_store. Several mapping routines however need the ! info about all (global) subs. ! Changed subs_bc to hold now the GLOBAL subid and adjusted all ! occurrences. ! ! Revision 1.6 2005/12/08 12:43:16 kotsalie ! commiting dirichlet ! ! Revision 1.5 2005/01/04 09:47:45 kotsalie ! ghostsize=2 for scalar case ! ! Revision 1.4 2004/10/29 15:59:14 kotsalie ! RED BLACK SOR FOR 3d vec case. 2d will soon follow. ! ! Revision 1.3 2004/09/28 14:04:49 kotsalie ! Changes concerning 4th order finite differences ! ! Revision 1.2 2004/09/23 09:38:30 kotsalie ! added details in the header ! ! Revision 1.1 2004/09/22 18:27:09 kotsalie ! MG new version ! !------------------------------------------------------------------------ ! Parallel Particle Mesh Library (PPM) ! Institute of Computational Science ! ETH Zentrum, Hirschengraben 84 ! CH-8092 Zurich, Switzerland !------------------------------------------------------------------------ #if __DIM == __SFIELD #if __MESH_DIM == __2D #if __KIND == __SINGLE_PRECISION SUBROUTINE ppm_mg_init_2d_sca_s(topo_id,equation,ighostsize,smoother,ibcdef,& & bcvalue,mesh_id,limlev,wcycle,lprint,omega,info) #elif __KIND == __DOUBLE_PRECISION SUBROUTINE ppm_mg_init_2d_sca_d(topo_id,equation,ighostsize,smoother,ibcdef,& & bcvalue,mesh_id,limlev,wcycle,lprint,omega,info) #endif #elif __MESH_DIM == __3D #if __KIND == __SINGLE_PRECISION SUBROUTINE ppm_mg_init_3d_sca_s(topo_id,equation,ighostsize,smoother,ibcdef,& & bcvalue,mesh_id,limlev,wcycle,lprint,omega,info) #elif __KIND == __DOUBLE_PRECISION SUBROUTINE ppm_mg_init_3d_sca_d(topo_id,equation,ighostsize,smoother,ibcdef,& & bcvalue,mesh_id,limlev,wcycle,lprint,omega,info) #endif #endif #elif __DIM == __VFIELD #if __MESH_DIM == __2D #if __KIND == __SINGLE_PRECISION SUBROUTINE ppm_mg_init_2d_vec_s(topo_id,equation,ighostsize,smoother,lda,ibcdef,& & bcvalue,mesh_id,limlev,wcycle,lprint,omega,info) #elif __KIND == __DOUBLE_PRECISION SUBROUTINE ppm_mg_init_2d_vec_d(topo_id,equation,ighostsize,smoother,lda,ibcdef,& & bcvalue,mesh_id,limlev,wcycle,lprint,omega,info) #endif #elif __MESH_DIM == __3D #if __KIND == __SINGLE_PRECISION SUBROUTINE ppm_mg_init_3d_vec_s(topo_id,equation,ighostsize,smoother,lda,ibcdef,& & bcvalue,mesh_id,limlev,wcycle,lprint,omega,info) #elif __KIND == __DOUBLE_PRECISION SUBROUTINE ppm_mg_init_3d_vec_d(topo_id,equation,ighostsize,smoother,lda,ibcdef,& & bcvalue,mesh_id,limlev,wcycle,lprint,omega,info) #endif #endif #endif !---------------------------------------------------------------------- ! Includes !---------------------------------------------------------------------- #include "ppm_define.h" !---------------------------------------------------------------------- ! Modules !---------------------------------------------------------------------- USE ppm_module_data USE ppm_module_data_mg USE ppm_module_mg_alloc USE ppm_module_alloc USE ppm_module_mg_alloc USE ppm_module_error USE ppm_module_write USE ppm_module_mesh USE ppm_module_substart USE ppm_module_substop USE ppm_module_typedef IMPLICIT NONE #if __KIND == __SINGLE_PRECISION INTEGER, PARAMETER :: MK = ppm_kind_single #else INTEGER, PARAMETER :: MK = ppm_kind_double #endif !---------------------------------------------------------------------- ! Arguments !---------------------------------------------------------------------- INTEGER, INTENT(IN) :: equation INTEGER,DIMENSION(:),INTENT(IN) :: ighostsize INTEGER, INTENT(IN) :: smoother #if __DIM == __VFIELD INTEGER, INTENT(IN) :: lda #endif #if __DIM == __SFIELD #if __MESH_DIM == __2D INTEGER,DIMENSION(:) :: ibcdef REAL(MK),DIMENSION(:,:,:) :: bcvalue #elif __MESH_DIM == __3D INTEGER,DIMENSION(:) :: ibcdef REAL(MK),DIMENSION(:,:,:,:) :: bcvalue #endif #elif __DIM == __VFIELD #if __MESH_DIM == __2D INTEGER,DIMENSION(:,:) :: ibcdef REAL(MK),DIMENSION(:,:,:,:) :: bcvalue #elif __MESH_DIM == __3D INTEGER,DIMENSION(:,:) :: ibcdef REAL(MK),DIMENSION(:,:,:,:,:) :: bcvalue #endif #endif INTEGER, INTENT(IN) :: mesh_id,topo_id INTEGER,INTENT(IN) :: limlev LOGICAL,INTENT(IN) :: wcycle LOGICAL,INTENT(IN) :: lprint REAL(MK),INTENT(IN) :: omega INTEGER, INTENT(OUT) :: info !---------------------------------------------------------------------- ! Local variables !---------------------------------------------------------------------- REAL(MK) :: t0 REAL(MK) :: lmyeps INTEGER :: meshid,mlev,isub INTEGER :: idom INTEGER :: count,ilda,iface INTEGER :: i,j,k INTEGER :: kk TYPE(ppm_t_topo), POINTER :: topo TYPE(ppm_t_equi_mesh), POINTER :: mesh #if __MESH_DIM == __2D INTEGER :: dir #endif INTEGER :: iter1,iter2,ix,iy INTEGER :: ipoint,jpoint INTEGER :: newmeshid,lmesh_id INTEGER , DIMENSION(1) :: ldu1 INTEGER , DIMENSION(2) :: ldu2,ldl2 ,direc INTEGER , DIMENSION(3) :: ldu3,ldl3 #if __MESH_DIM == __3D INTEGER :: dir1,dir2,jj,iz INTEGER , DIMENSION(4) :: ldu4,ldl4 #endif INTEGER , DIMENSION(ppm_dim) :: Nml REAL(MK), DIMENSION(ppm_dim) :: min_phys,max_phys REAL(MK), DIMENSION(ppm_dim,ppm_topo(topo_id)%t%nsubs) & & :: min_sub,max_sub INTEGER :: iopt,topoid #if __DIM == __SFIELD #if __MESH_DIM == __2D #if __KIND == __SINGLE_PRECISION TYPE(mg_field_2d_sca_s),DIMENSION(:,:),POINTER :: mgfield #elif __KIND == __DOUBLE_PRECISION TYPE(mg_field_2d_sca_d),DIMENSION(:,:),POINTER :: mgfield #endif #elif __MESH_DIM == __3D #if __KIND == __SINGLE_PRECISION TYPE(mg_field_3d_sca_s),DIMENSION(:,:),POINTER :: mgfield #elif __KIND == __DOUBLE_PRECISION TYPE(mg_field_3d_sca_d),DIMENSION(:,:),POINTER :: mgfield #endif #endif #elif __DIM == __VFIELD #if __MESH_DIM == __2D #if __KIND == __SINGLE_PRECISION TYPE(mg_field_2d_vec_s),DIMENSION(:,:),POINTER :: mgfield #elif __KIND == __DOUBLE_PRECISION TYPE(mg_field_2d_vec_d),DIMENSION(:,:),POINTER :: mgfield #endif #elif __MESH_DIM == __3D #if __KIND == __SINGLE_PRECISION TYPE(mg_field_3d_vec_s),DIMENSION(:,:),POINTER :: mgfield #elif __KIND == __DOUBLE_PRECISION TYPE(mg_field_3d_vec_d),DIMENSION(:,:),POINTER :: mgfield #endif #endif #endif #if __DIM == __SFIELD #if __MESH_DIM == __2D REAL(MK),DIMENSION(:,:),POINTER :: tuc REAL(MK),DIMENSION(:,:),POINTER :: terr #elif __MESH_DIM == __3D REAL(MK),DIMENSION(:,:,:),POINTER :: tuc REAL(MK),DIMENSION(:,:,:),POINTER :: terr #endif #elif __DIM == __VFIELD #if __MESH_DIM == __2D REAL(MK),DIMENSION(:,:,:),POINTER :: tuc REAL(MK),DIMENSION(:,:,:),POINTER :: terr #elif __MESH_DIM == __3D REAL(MK),DIMENSION(:,:,:,:),POINTER :: tuc REAL(MK),DIMENSION(:,:,:,:),POINTER :: terr #endif #endif !---------------------------------------------------------------------- ! Externals !---------------------------------------------------------------------- !---------------------------------------------------------------------- ! Initialize !---------------------------------------------------------------------- CALL substart('ppm_mg_init',t0,info) !---------------------------------------------------------------------- ! Check arguments !---------------------------------------------------------------------- IF (ppm_debug.GT.0) THEN #if __DIM == __VFIELD IF (lda.LE.0) THEN info = ppm_error_error CALL ppm_error(ppm_err_argument,'ppm_poiss_mg_init', & & 'lda must be >0',__LINE__,info) GOTO 9999 ENDIF #endif ENDIF !---------------------------------------------------------------------- ! Definition of necessary variables and allocation of arrays !---------------------------------------------------------------------- #if __DIM == __SFIELD vecdim = 1 #elif __DIM == __VFIELD vecdim = lda #endif w_cycle=wcycle l_print=lprint topoid = topo_id topo => ppm_topo(topo_id)%t mesh => topo%mesh(mesh_id) nsubs = topo%nsublist meshid = mesh%ID lmesh_id = mesh_id #if __KIND == __SINGLE_PRECISION min_phys(:)=topo%min_physs(:) max_phys(:)=topo%max_physs(:) min_sub(:,:)=topo%min_subs(:,:) max_sub(:,:)=topo%max_subs(:,:) omega_s=omega lmyeps=ppm_myepss #elif __KIND == __DOUBLE_PRECISION min_phys(:)=topo%min_physd(:) max_phys(:)=topo%max_physd(:) min_sub(:,:)=topo%min_subd(:,:) max_sub(:,:)=topo%max_subd(:,:) omega_d=omega lmyeps=ppm_myepsd #endif #if __MESH_DIM == __2D Nml(1) = mesh%Nm(1) Nml(2) = mesh%Nm(2) maxlev = INT(log10(Nml(1)*Nml(2)*REAL(ppm_nproc,MK))/log10(2.0_MK)) IF (maxlev.GT.limlev) THEN maxlev=limlev ENDIF #if __KIND == __SINGLE_PRECISION dx_s = (max_phys(1)-min_phys(1))/REAL((Nml(1)-1),MK) dy_s = (max_phys(2)-min_phys(2))/REAL((Nml(2)-1),MK) rdx2_s = 1.0_MK/(dx_s*dx_s) rdy2_s = 1.0_MK/(dy_s*dy_s) #elif __KIND == __DOUBLE_PRECISION dx_d = (max_phys(1)-min_phys(1))/REAL((Nml(1)-1),MK) dy_d = (max_phys(2)-min_phys(2))/REAL((Nml(2)-1),MK) rdx2_d = 1.0_MK/(dx_d*dx_d) rdy2_d = 1.0_MK/(dy_d*dy_d) #endif #elif __MESH_DIM == __3D Nml(1) = mesh%Nm(1) Nml(2) = mesh%Nm(2) Nml(3) = mesh%Nm(3) maxlev = INT(log10(Nml(1)*Nml(2)*Nml(3)* & & REAL(ppm_nproc,MK))/log10(2.0_MK)) IF (maxlev.GT.limlev) THEN maxlev=limlev ENDIF #if __KIND == __SINGLE_PRECISION dx_s = (max_phys(1)-min_phys(1))/REAL((Nml(1)-1),MK) dy_s = (max_phys(2)-min_phys(2))/REAL((Nml(2)-1),MK) dz_s = (max_phys(3)-min_phys(3))/REAL((Nml(3)-1),MK) rdx2_s = 1.0_MK/(dx_s*dx_s) rdy2_s = 1.0_MK/(dy_s*dy_s) rdz2_s = 1.0_MK/(dz_s*dz_s) #elif __KIND == __DOUBLE_PRECISION dx_d = (max_phys(1)-min_phys(1))/REAL((Nml(1)-1),MK) dy_d = (max_phys(2)-min_phys(2))/REAL((Nml(2)-1),MK) dz_d = (max_phys(3)-min_phys(3))/REAL((Nml(3)-1),MK) rdx2_d = 1.0_MK/(dx_d*dx_d) rdy2_d = 1.0_MK/(dy_d*dy_d) rdz2_d = 1.0_MK/(dz_d*dz_d) #endif #endif #if __DIM == __SFIELD iopt = ppm_param_alloc_fit ldu2(1) = nsubs ldu2(2) = 2*ppm_dim CALL ppm_alloc(bcdef_sca,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Boundary condiotions',__LINE__,info) GOTO 9999 ENDIF bcdef_sca(:,:)=0 DO isub=1,nsubs idom=topo%isublist(isub) !--------------------------------------------------------------------- ! compare the west boundary !--------------------------------------------------------------------- IF (ABS(min_sub(1,idom)-min_phys(1)) .LT. & & lmyeps*(max_sub(1,i)-min_sub(1,i))) THEN bcdef_sca(isub,1)=ibcdef(1) ENDIF !--------------------------------------------------------------------- ! compare the east boundary !--------------------------------------------------------------------- IF (ABS(max_sub(1,idom)-max_phys(1)) .LT. & & lmyeps*(max_sub(1,i)-min_sub(1,i))) THEN bcdef_sca(isub,2)=ibcdef(2) ENDIF !--------------------------------------------------------------------- ! compare the south boundary !--------------------------------------------------------------------- IF (ABS(min_sub(2,idom)-min_phys(2)) .LT. & & lmyeps*(max_sub(2,i)-min_sub(2,i))) THEN bcdef_sca(isub,3)=ibcdef(3) ENDIF !--------------------------------------------------------------------- ! compare the north boundary !--------------------------------------------------------------------- IF (ABS(max_sub(2,idom)-max_phys(2)) .LT. & & lmyeps*(max_sub(2,i)-min_sub(2,i))) THEN bcdef_sca(isub,4)=ibcdef(4) ENDIF !----------------------------------------------------------------- ! compare the south boundary !--------------------------------------------------------------------- #if __MESH_DIM == __3D IF (ABS(min_sub(3,idom)-min_phys(3)) .LT. & & lmyeps*(max_sub(3,i)-min_sub(3,i))) THEN bcdef_sca(isub,5)=ibcdef(5) ENDIF !--------------------------------------------------------------------- ! compare the north boundary !--------------------------------------------------------------------- IF (ABS(max_sub(3,idom)-max_phys(3)) .LT. & & lmyeps*(max_sub(3,i)-min_sub(3,i))) THEN bcdef_sca(isub,6)=ibcdef(6) ENDIF #endif ENDDO lperiodic=.TRUE. DO isub=1,nsubs DO i=1,2*ppm_dim IF (bcdef_sca(isub,i).NE.ppm_param_bcdef_periodic) THEN lperiodic=.FALSE. EXIT ENDIF ENDDO ENDDO #elif __DIM == __VFIELD iopt = ppm_param_alloc_fit ldu3(1) = vecdim ldu3(2) = nsubs ldu3(3) = 2*ppm_dim CALL ppm_alloc(bcdef_vec,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Boundary condiotions',__LINE__,info) GOTO 9999 ENDIF bcdef_vec(:,:,:)=0 DO isub=1,nsubs idom=topo%isublist(isub) DO ilda=1,vecdim !------------------------------------------------------------------ ! compare the west boundary !--------------------------------------------------------------------- IF (ABS(min_sub(1,idom)-min_phys(1)) .LT. & & lmyeps*(max_sub(1,i)-min_sub(1,i))) THEN bcdef_vec(ilda,isub,1)=ibcdef(ilda,1) ENDIF !--------------------------------------------------------------------- ! compare the east boundary !--------------------------------------------------------------------- IF (ABS(max_sub(1,idom)-max_phys(1)) .LT. & & lmyeps*(max_sub(1,i)-min_sub(1,i))) THEN bcdef_vec(ilda,isub,2)=ibcdef(ilda,2) ENDIF !--------------------------------------------------------------------- ! compare the south boundary !--------------------------------------------------------------------- IF (ABS(min_sub(2,idom)-min_phys(2)) .LT. & & lmyeps*(max_sub(2,i)-min_sub(2,i))) THEN bcdef_vec(ilda,isub,3)=ibcdef(ilda,3) ENDIF !--------------------------------------------------------------------- ! compare the north boundary !--------------------------------------------------------------------- IF (ABS(max_sub(2,idom)-max_phys(2)) .LT. & & lmyeps*(max_sub(2,i)-min_sub(2,i))) THEN bcdef_vec(ilda,isub,4)=ibcdef(ilda,4) ENDIF #if __MESH_DIM == __3D !----------------------------------------------------------------- ! compare the south boundary !--------------------------------------------------------------------- IF (ABS(min_sub(3,idom)-min_phys(3)) .LT. & & lmyeps*(max_sub(3,i)-min_sub(3,i))) THEN bcdef_vec(ilda,isub,5)=ibcdef(ilda,5) ENDIF !--------------------------------------------------------------------- ! compare the north boundary !--------------------------------------------------------------------- IF (ABS(max_sub(3,idom)-max_phys(3)) .LT. & & lmyeps*(max_sub(3,i)-min_sub(3,i))) THEN bcdef_vec(ilda,isub,6)=ibcdef(ilda,6) ENDIF #endif enddo enddo lperiodic=.TRUE. Do isub=1,nsubs DO i=1,2*ppm_dim DO ilda=1,vecdim IF (bcdef_vec(ilda,isub,i).NE.ppm_param_bcdef_periodic) Then lperiodic=.FALSE. EXIT ENDIF ENDDO ENDDO ENDDO #endif !------------------------------------------------------------------------------ !Allocation of the ghostsize !------------------------------------------------------------------------------ iopt = ppm_param_alloc_fit ldu1(1) = ppm_dim CALL ppm_alloc(ghostsize,ldu1,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'ghostsize',__LINE__,info) GOTO 9999 ENDIF ghostsize=ighostsize !---------------------------------------------------------------------------- !ALLOCATIION OF THE FACTOR FOR COARSENING (LATER SET TO 2)) !---------------------------------------------------------------------------- iopt = ppm_param_alloc_fit ldu1(1) = ppm_dim CALL ppm_alloc(factor,ldu1,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'factor',__LINE__,info) GOTO 9999 ENDIF !---------------------------------------------------------------------------- !INTERNAL IDS FOR MESHES !---------------------------------------------------------------------------- iopt = ppm_param_alloc_fit ldu1(1) = maxlev CALL ppm_alloc(meshid_g,ldu1,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'meshid_g',__LINE__,info) GOTO 9999 ENDIF !---------------------------------------------------------------------------- !USER IDS FOR MESHES !---------------------------------------------------------------------------- iopt = ppm_param_alloc_fit ldu1(1) = maxlev CALL ppm_alloc(mesh_id_g,ldu1,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'mesh_id_g',__LINE__,info) GOTO 9999 ENDIF iopt = ppm_param_alloc_fit ldu3(1) = ppm_dim ldu3(2) = nsubs ldu3(3) = maxlev CALL ppm_alloc(start,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'starting indices when updating the field',__LINE__,info) GOTO 9999 ENDIF iopt = ppm_param_alloc_fit ldu3(1) = ppm_dim ldu3(2) = nsubs ldu3(3) = maxlev CALL ppm_alloc(istop,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'istopping indices when updating the field',__LINE__,info) GOTO 9999 ENDIF #if __DIM == __SFIELD #if __MESH_DIM == __2D #if __KIND == __SINGLE_PRECISION iopt = ppm_param_alloc_fit ldu2(1) = nsubs ldu2(2) = maxlev CALL ppm_mg_alloc(mgfield_2d_sca_s,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Multigrid fields used on the different levels',__LINE__,info) GOTO 9999 ENDIF mgfield => mgfield_2d_sca_s #elif __KIND == __DOUBLE_PRECISION iopt = ppm_param_alloc_fit ldu2(1) = nsubs ldu2(2) = maxlev CALL ppm_mg_alloc(mgfield_2d_sca_d,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Multigrid fields used on the different levels',__LINE__,info) GOTO 9999 ENDIF mgfield => mgfield_2d_sca_d #endif #elif __MESH_DIM == __3D #if __KIND == __SINGLE_PRECISION iopt = ppm_param_alloc_fit ldu2(1) = nsubs ldu2(2) = maxlev CALL ppm_mg_alloc(mgfield_3d_sca_s,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Multigrid fields used on the different levels',__LINE__,info) GOTO 9999 ENDIF mgfield => mgfield_3d_sca_s #elif __KIND == __DOUBLE_PRECISION iopt = ppm_param_alloc_fit ldu2(1) = nsubs ldu2(2) = maxlev CALL ppm_mg_alloc(mgfield_3d_sca_d,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Multigrid fields used on the different levels',__LINE__,info) GOTO 9999 ENDIF mgfield => mgfield_3d_sca_d #endif #endif #elif __DIM == __VFIELD #if __MESH_DIM == __2D #if __KIND == __SINGLE_PRECISION iopt = ppm_param_alloc_fit ldu2(1) = nsubs ldu2(2) = maxlev CALL ppm_mg_alloc(mgfield_2d_vec_s,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Multigrid fields used on the different levels',__LINE__,info) GOTO 9999 ENDIF mgfield => mgfield_2d_vec_s #elif __KIND == __DOUBLE_PRECISION iopt = ppm_param_alloc_fit ldu2(1) = nsubs ldu2(2) = maxlev CALL ppm_mg_alloc(mgfield_2d_vec_d,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Multigrid fields used on the different levels',__LINE__,info) GOTO 9999 ENDIF mgfield => mgfield_2d_vec_d #endif #elif __MESH_DIM == __3D #if __KIND == __SINGLE_PRECISION iopt = ppm_param_alloc_fit ldu2(1) = nsubs ldu2(2) = maxlev CALL ppm_mg_alloc(mgfield_3d_vec_s,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Multigrid fields used on the different levels',__LINE__,info) GOTO 9999 ENDIF mgfield => mgfield_3d_vec_s #elif __KIND == __DOUBLE_PRECISION iopt = ppm_param_alloc_fit ldu2(1) = nsubs ldu2(2) = maxlev CALL ppm_mg_alloc(mgfield_3d_vec_d,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Multigrid fields used on the different levels',__LINE__,info) GOTO 9999 ENDIF mgfield => mgfield_3d_vec_d #endif #endif #endif iopt = ppm_param_alloc_fit ldu2(1) = 2*ppm_dim ldu2(2) = nsubs CALL ppm_alloc(lboundary,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the boundary alloc.',__LINE__,info) GOTO 9999 ENDIF iopt = ppm_param_alloc_fit ldu2(1) = ppm_dim ldu2(2) = maxlev CALL ppm_alloc(max_node,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with a maximum number alloc.',__LINE__,info) GOTO 9999 ENDIF max_node(:,:)=0 lboundary(:,:)=.FALSE. start(:,:,:)=1 !---------------------------------------------------------------------- ! Derive coarser meshes !---------------------------------------------------------------------- DO mlev=1,maxlev #if __MESH_DIM == __2D !------------------------------------------------------------------- ! Go through the subs, define the istopping indices on each mesh, ! check and store if it is on the boundary, allocate the ! multigrid fields, pass the boundary values. !------------------------------------------------------------------- DO i=1,nsubs idom=topo%isublist(i) istop(:,i,mlev)= mesh%nnodes(:,idom) DO j=1,ppm_dim IF (max_node(j,mlev).LT.istop(j,i,mlev)) THEN max_node(j,mlev)=istop(j,i,mlev) ENDIF ENDDO !---------------------------------------------------------------- ! Allocate the function correction, the restricted errors, ! the residuals and the values on the boundary on each level. !---------------------------------------------------------------- #if __DIM == __SFIELD iopt = ppm_param_alloc_fit ldl2(1) = 1-ghostsize(1) ldl2(2) = 1-ghostsize(2) ldu2(1) = mesh%nnodes(1,idom)+ghostsize(1) ldu2(2) = mesh%nnodes(2,idom)+ghostsize(2) CALL ppm_alloc(mgfield(i,mlev)%uc,ldl2,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the function corr. alloc.',__LINE__,info) GOTO 9999 ENDIF tuc=>mgfield(i,mlev)%uc tuc=0.0_MK iopt = ppm_param_alloc_fit ldu2(1) = mesh%nnodes(1,idom) ldu2(2) = mesh%nnodes(2,idom) CALL ppm_alloc(mgfield(i,mlev)%fc,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the restricted err. alloc.',__LINE__,info) GOTO 9999 ENDIF mgfield(i,mlev)%fc(:,:)=0.0_MK iopt = ppm_param_alloc_fit ldl2(1) = 1-ghostsize(1) ldl2(2) = 1-ghostsize(2) ldu2(1) = mesh%nnodes(1,idom)+ghostsize(1) ldu2(2) = mesh%nnodes(2,idom)+ghostsize(2) CALL ppm_alloc(mgfield(i,mlev)%err,ldl2,ldu2,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the residual alloc.',__LINE__,info) GOTO 9999 ENDIF terr=>mgfield(i,mlev)%err terr(:,:)=0.0_MK !ALLOCATE THE BCVALUE(IT IS A TYPE!!) !PRINT *,'LPERIODIC:',lperiodic IF (.NOT.lperiodic) THEN iopt = ppm_param_alloc_fit ldu1(1) = 2*ppm_dim CALL ppm_mg_alloc(mgfield(i,mlev)%bcvalue,ldu1,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the BOUNDARY alloc.',__LINE__,info) GOTO 9999 ENDIF !ALLOCATE THE PBCVALUE DO iface=1,2*ppm_dim iopt = ppm_param_alloc_fit IF (iface.EQ.1.OR.iface.EQ.2) THEN ldu1(1) = max_node(2,mlev) ELSE ldu1(1) = max_node(1,mlev) ENDIF CALL ppm_alloc(mgfield(i,mlev)%bcvalue(iface)%pbcvalue,ldu1,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the BOUNDARY alloc.',__LINE__,info) GOTO 9999 ENDIF ENDDO DO iface=1,2*ppm_dim IF (iface.EQ.1.OR.iface.EQ.2) THEN direc(1)=2 ELSEIF (iface.EQ.3.OR.iface.EQ.4) then direc(1)=1 ENDIF DO ipoint=1,max_node(direc(1),mlev) IF (mlev.EQ.1) THEN mgfield(i,mlev)%bcvalue(iface)%pbcvalue(ipoint)=bcvalue(i,iface,ipoint) ELSE IF(bcdef_sca(i,iface).EQ.ppm_param_bcdef_neumann) THEN mgfield(i,mlev)%bcvalue(iface)%pbcvalue(ipoint)=& & mgfield(i,mlev-1)%bcvalue(iface)%pbcvalue(2*ipoint-1) ELSE !NO CORRECTIONS FOR THE DIRICHLET mgfield(i,mlev)%bcvalue(iface)%pbcvalue(ipoint)=0.0_MK ENDIF ENDIF ENDDO ENDDO!faces ENDIF!lperiodic #elif __DIM == __VFIELD iopt = ppm_param_alloc_fit ldl3(1) = 1 ldl3(2) = 1-ghostsize(1) ldl3(3) = 1-ghostsize(2) ldu3(1) = vecdim ldu3(2) = mesh%nnodes(1,idom)+ghostsize(1) ldu3(3) = mesh%nnodes(2,idom)+ghostsize(2) CALL ppm_alloc(mgfield(i,mlev)%uc,ldl3,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the function corr. alloc.',__LINE__,info) GOTO 9999 ENDIF tuc=>mgfield(i,mlev)%uc tuc=0.0_MK iopt = ppm_param_alloc_fit ldu3(1) = vecdim ldu3(2) = mesh%nnodes(1,idom) ldu3(3) = mesh%nnodes(2,idom) CALL ppm_alloc(mgfield(i,mlev)%fc,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the restricted err. alloc.',__LINE__,info) GOTO 9999 ENDIF mgfield(i,mlev)%fc(:,:,:)=0.0_MK iopt = ppm_param_alloc_fit ldl3(1) = 1 ldl3(2) = 1-ghostsize(1) ldl3(3) = 1-ghostsize(2) ldu3(1) = vecdim ldu3(2) = mesh%nnodes(1,idom)+ghostsize(1) ldu3(3) = mesh%nnodes(2,idom)+ghostsize(2) CALL ppm_alloc(mgfield(i,mlev)%err,ldl3,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the residual alloc.',__LINE__,info) GOTO 9999 ENDIF terr=>mgfield(i,mlev)%err terr(:,:,:)=0.0_MK #endif ENDDO!DO 1,nsubs #elif __MESH_DIM == __3D DO i=1,nsubs idom=topo%isublist(i) istop(:,i,mlev) = mesh%nnodes(:,idom) DO j=1,ppm_dim IF (max_node(j,mlev).LT.istop(j,i,mlev)) THEN max_node(j,mlev)=istop(j,i,mlev) ENDIF ENDDO IF (topo%subs_bc(1,idom).EQ.1) THEN lboundary(1,i)=.TRUE. ELSEIF (topo%subs_bc(3,idom).EQ.1) THEN lboundary(3,i)=.TRUE. ELSEIF (topo%subs_bc(2,idom).EQ.1) THEN lboundary(2,i)=.TRUE. ELSEIF (topo%subs_bc(4,idom).EQ.1) THEN lboundary(4,i)=.TRUE. ELSEIF (topo%subs_bc(5,idom).EQ.1) THEN lboundary(5,i)=.TRUE. ELSEIF (topo%subs_bc(6,idom).EQ.1) THEN lboundary(6,i)=.TRUE. ENDIF !---------------------------------------------------------------- ! Allocate the function correction, the restricted errors and the !residuals on each level. !---------------------------------------------------------------- #if __DIM == __SFIELD iopt = ppm_param_alloc_fit ldl3(1) = 1-ghostsize(1) ldl3(2) = 1-ghostsize(2) ldl3(3) = 1-ghostsize(3) ldu3(1) = mesh%nnodes(1,idom)+ghostsize(1) ldu3(2) = mesh%nnodes(2,idom)+ghostsize(2) ldu3(3) = mesh%nnodes(3,idom)+ghostsize(3) CALL ppm_alloc(mgfield(i,mlev)%uc,ldl3,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the function corr. alloc.',__LINE__,info) GOTO 9999 ENDIF tuc=>mgfield(i,mlev)%uc tuc=0.0_MK iopt = ppm_param_alloc_fit ldu3(1) = mesh%nnodes(1,idom) ldu3(2) = mesh%nnodes(2,idom) ldu3(3) = mesh%nnodes(3,idom) CALL ppm_alloc(mgfield(i,mlev)%fc,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the restricted err. alloc.',__LINE__,info) GOTO 9999 ENDIF mgfield(i,mlev)%fc=0.0_MK iopt = ppm_param_alloc_fit ldl3(1) = 1-ghostsize(1) ldl3(2) = 1-ghostsize(2) ldl3(3) = 1-ghostsize(3) ldu3(1) = mesh%nnodes(1,idom)+ghostsize(1) ldu3(2) = mesh%nnodes(2,idom)+ghostsize(2) ldu3(3) = mesh%nnodes(3,idom)+ghostsize(3) CALL ppm_alloc(mgfield(i,mlev)%err,ldl3,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the residual alloc.',__LINE__,info) GOTO 9999 ENDIF terr=>mgfield(i,mlev)%err terr=0.0_MK !ALLOCATE THE BCVALUE(IT IS A TYPE!!) IF (.NOT.lperiodic) THEN iopt = ppm_param_alloc_fit ldu1(1) = 2*ppm_dim CALL ppm_mg_alloc(mgfield(i,mlev)%bcvalue,ldu1,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the BOUNDARY alloc.',__LINE__,info) GOTO 9999 ENDIF !ALLOCATE THE PBCVALUE DO iface=1,2*ppm_dim iopt = ppm_param_alloc_fit IF (iface.EQ.1.OR.iface.EQ.2) THEN ldu2(1) = max_node(2,mlev) ldu2(2)= max_node(3,mlev) ELSEif (iface.EQ.3.OR. iface.EQ.4) then ldu2(1) = max_node(1,mlev) ldu2(2)=max_node(3,mlev) else ldu2(1)=max_node(1,mlev) ldu2(2)=max_node(2,mlev) ENDIF CALL ppm_alloc(mgfield(i,mlev)%bcvalue(iface)%pbcvalue,ldu2,iopt,info) !Print *,size(mgfield(i,mlev)%bcvalue(iface)%pbcvalue,1) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the BOUNDARY alloc.',__LINE__,info) GOTO 9999 ENDIF ENDDO DO iface=1,2*ppm_dim IF (iface.EQ.1.OR.iface.EQ.2) THEN direc(1)=2 direc(2)=3 elseif (iface.EQ.3.OR.iface.EQ.4) THEN direc(1)=1 direc(2)=3 else direc(1)=1 direc(2)=2 endif DO ipoint=1,max_node(direc(1),mlev) DO jpoint=1,max_node(direc(2),mlev) IF (mlev.EQ.1) THEN mgfield(i,mlev)%bcvalue(iface)%pbcvalue(ipoint,jpoint)=bcvalue(i,iface,ipoint,jpoint) ELSE IF(bcdef_sca(i,iface).EQ.ppm_param_bcdef_neumann) THEN mgfield(i,mlev)%bcvalue(iface)%pbcvalue(ipoint,jpoint)=& & mgfield(i,mlev-1)%bcvalue(iface)%pbcvalue(2*ipoint-1,2*jpoint-1) ELSE !NO CORRECTIONS FOR THE DIRICHLET mgfield(i,mlev)%bcvalue(iface)%pbcvalue(ipoint,jpoint)=0.0_MK ENDIF ENDIF ENDDO ENDDO ENDDO!faces endif !lperiodic #elif __DIM == __VFIELD iopt = ppm_param_alloc_fit ldl4(1) = 1 ldl4(2) = 1-ghostsize(1) ldl4(3) = 1-ghostsize(2) ldl4(4) = 1-ghostsize(3) ldu4(1) = vecdim ldu4(2) = mesh%nnodes(1,idom)+ghostsize(1) ldu4(3) = mesh%nnodes(2,idom)+ghostsize(2) ldu4(4) = mesh%nnodes(3,idom)+ghostsize(3) CALL ppm_alloc(mgfield(i,mlev)%uc,ldl4,ldu4,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the function corr. alloc.',__LINE__,info) GOTO 9999 ENDIF tuc=>mgfield(i,mlev)%uc tuc=0.0_MK iopt = ppm_param_alloc_fit ldu4(1) = vecdim ldu4(2) = mesh%nnodes(1,idom) ldu4(3) = mesh%nnodes(2,idom) ldu4(4) = mesh%nnodes(3,idom) CALL ppm_alloc(mgfield(i,mlev)%fc,ldu4,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the restricted err. alloc.',__LINE__,info) GOTO 9999 ENDIF mgfield(i,mlev)%fc=0.0_MK iopt = ppm_param_alloc_fit ldl4(1) = 1 ldl4(2) = 1-ghostsize(1) ldl4(3) = 1-ghostsize(2) ldl4(4) = 1-ghostsize(3) ldu4(1) = vecdim ldu4(2) = mesh%nnodes(1,idom)+ghostsize(1) ldu4(3) = mesh%nnodes(2,idom)+ghostsize(2) ldu4(4) = mesh%nnodes(3,idom)+ghostsize(3) CALL ppm_alloc(mgfield(i,mlev)%err,ldl4,ldu4,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the residual alloc.',__LINE__,info) GOTO 9999 ENDIF terr=>mgfield(i,mlev)%err terr=0.0_MK !ALLOCATE THE BCVALUE(IT IS A TYPE!!) IF (.NOT.lperiodic) THEN iopt = ppm_param_alloc_fit ldu1=2*ppm_dim CALL ppm_mg_alloc(mgfield(i,mlev)%bcvalue,ldu1,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the BOUNDARY alloc.',__LINE__,info) GOTO 9999 ENDIF !ALLOCATE THE PBCVALUE DO iface=1,2*ppm_dim iopt = ppm_param_alloc_fit ldu3(1)=vecdim IF (iface.EQ.1.OR.iface.EQ.2) THEN ldu3(2) = max_node(2,mlev) ldu3(3)= max_node(3,mlev) ELSEIF (iface.EQ.3.OR. iface.EQ.4) then ldu3(2) = max_node(1,mlev) ldu3(3)=max_node(3,mlev) ELSE ldu3(2)=max_node(1,mlev) ldu3(3)=max_node(2,mlev) ENDIF CALL ppm_alloc(mgfield(i,mlev)%bcvalue(iface)%pbcvalue,ldu3,iopt,info) IF (info .NE. 0) THEN info = ppm_error_fatal CALL ppm_error(ppm_err_alloc,'ppm_poiss_mg_init', & & 'Problem with the BOUNDARY alloc.',__LINE__,info) GOTO 9999 ENDIF ENDDO DO iface=1,2*ppm_dim IF (iface.EQ.1.OR.iface.EQ.2) THEN direc(1)=2 direc(2)=3 elseif (iface.EQ.3.OR.iface.EQ.4) THEN direc(1)=1 direc(2)=3 else direc(1)=1 direc(2)=2 endif DO ipoint=1,max_node(direc(1),mlev) DO jpoint=1,max_node(direc(2),mlev) DO ilda=1,vecdim IF (mlev.EQ.1) THEN mgfield(i,mlev)%bcvalue(iface)%pbcvalue(ilda,ipoint,jpoint) & & =bcvalue(ilda,i,iface,ipoint,jpoint) ELSE IF(bcdef_vec(ilda,i,iface).EQ.ppm_param_bcdef_neumann) THEN mgfield(i,mlev)%bcvalue(iface)%pbcvalue(ilda,ipoint,jpoint)=& & mgfield(i,mlev-1)%bcvalue(iface)%pbcvalue(ilda,2*ipoint-1,2*jpoint-1) ELSE !NO CORRECTIONS FOR THE DIRICHLET mgfield(i,mlev)%bcvalue(iface)%pbcvalue(ilda,ipoint,jpoint)=0.0_MK ENDIF ENDIF ENDDO ENDDO ENDDO ENDDO ENDIF !lperiodic #endif ENDDO!DO i=1,nsubs #endif factor(:)=2 mesh_id_g(mlev)=lmesh_id meshid_g(mlev)=meshid newmeshid=-1 IF (mlev.LT.maxlev) THEN CALL ppm_mesh_derive(topoid,meshid,newmeshid,& & ppm_param_mesh_coarsen,factor,info) lmesh_id = newmeshid meshid = topo%mesh(lmesh_id)%ID ENDIF ENDDO!DO mlev=1,maxlev !---------------------------------------------------------------------- ! Return !---------------------------------------------------------------------- 9999 CONTINUE CALL substop('ppm_mg_init',t0,info) RETURN #if __DIM == __SFIELD #if __MESH_DIM == __2D #if __KIND == __SINGLE_PRECISION END SUBROUTINE ppm_mg_init_2d_sca_s #elif __KIND == __DOUBLE_PRECISION END SUBROUTINE ppm_mg_init_2d_sca_d #endif #elif __MESH_DIM == __3D #if __KIND == __SINGLE_PRECISION END SUBROUTINE ppm_mg_init_3d_sca_s #elif __KIND == __DOUBLE_PRECISION END SUBROUTINE ppm_mg_init_3d_sca_d #endif #endif #elif __DIM == __VFIELD #if __MESH_DIM == __2D #if __KIND == __SINGLE_PRECISION END SUBROUTINE ppm_mg_init_2d_vec_s #elif __KIND == __DOUBLE_PRECISION END SUBROUTINE ppm_mg_init_2d_vec_d #endif #elif __MESH_DIM == __3D #if __KIND == __SINGLE_PRECISION END SUBROUTINE ppm_mg_init_3d_vec_s #elif __KIND == __DOUBLE_PRECISION END SUBROUTINE ppm_mg_init_3d_vec_d #endif #endif #endif