88 INTEGER,
PARAMETER :: MIDPOINT = 1
92 INTEGER,
PARAMETER :: NFACES(3) = (/ 2, 4, 6 /)
93 INTEGER,
PARAMETER :: NCORNERS(3) = (/ 2, 4, 8 /)
95 INTEGER,
PARAMETER :: &
96 WEST = 1, & !< named constant for western boundary
104 enumerator :: vector_x = b
'001', &
112 CLASS(geometry_base),
ALLOCATABLE :: Geometry
113 TYPE(selection_base) :: without_ghost_zones
115 INTEGER :: GINUM,GJNUM,GKNUM
116 INTEGER :: INUM,JNUM,KNUM
120 INTEGER :: IGMIN,IGMAX
121 INTEGER :: JGMIN,JGMAX
122 INTEGER :: KGMIN,KGMAX
126 INTEGER :: Ip1,Ip2,Im1,Im2
127 INTEGER :: Jp1,Jp2,Jm1,Jm2
128 INTEGER :: Kp1,Kp2,Km1,Km2
133 REAL :: invdx,invdy,invdz
140 INTEGER :: VECTOR_COMPONENTS
144 TYPE(marray_cellvector) :: curv, & !< curvilinear coordinates
146 REAL,
DIMENSION(:,:,:,:),
POINTER :: &
147 center, & !< geometrical centers
148 bcenter, & !< bary centers
150 REAL,
DIMENSION(:,:,:,:,:),
POINTER :: &
151 fccart, & !< cartesian face centered positions
155 TYPE(marray_base) :: dlx,dly,dlz, & !< cell centered line elements
156 volume, & !< cell volumes
158 REAL,
DIMENSION(:,:,:,:),
POINTER :: &
159 dAx,dAy,dAz, & !< cell surface area elements
160 dAxdydz,dAydzdx,dAzdxdy
163 TYPE(marray_cellscalar) :: hx,hy,hz, & !< scale factors
164 sqrtg, & !< sqrt(det(metric))
165 cyxy,cyzy,cxzx,cxyx,czxz,czyz
168 TYPE(marray_cellscalar) :: radius
169 TYPE(marray_cellvector) :: posvec
172 REAL,
DIMENSION(:,:),
POINTER :: &
174 REAL,
DIMENSION(:,:,:,:,:,:),
POINTER :: &
178 INTEGER :: MAXINUM,MAXJNUM,MAXKNUM
179 INTEGER :: MININUM,MINJNUM,MINKNUM
181 INTEGER :: Icomm,Jcomm,Kcomm
183 INTEGER,
DIMENSION(NFACES(3)) :: comm_boundaries
184 INTEGER,
DIMENSION(NFACES(3)) :: rank0_boundaries
185 INTEGER,
DIMENSION(NFACES(3)) :: neighbor
186 INTEGER,
DIMENSION(3) :: dims
187 INTEGER,
DIMENSION(3) :: mycoords
190 PROCEDURE :: RemapBounds_1
191 PROCEDURE :: RemapBounds_2
192 PROCEDURE :: RemapBounds_3
193 PROCEDURE :: RemapBounds_4
194 generic :: remapbounds => remapbounds_1, remapbounds_2, remapbounds_3, remapbounds_4
195 PROCEDURE :: InitMesh
196 PROCEDURE :: Finalize_base
198 PROCEDURE :: InternalPoint
199 procedure(tensordivergence3d),
DEFERRED :: tensordivergence3d
200 procedure(vectordivergence3d),
DEFERRED :: vectordivergence3d
201 procedure(tensordivergence2d_1),
DEFERRED :: tensordivergence2d_1
202 procedure(vectordivergence2d_1),
DEFERRED :: vectordivergence2d_1
203 generic :: divergence => tensordivergence3d, vectordivergence3d, &
204 vectordivergence2d_1, &
209 PURE SUBROUTINE tensordivergence3d(this,Txx,Txy,Txz,Tyx,Tyy,Tyz,Tzx,Tzy,Tzz, &
214 CLASS(mesh_base),
INTENT(IN) :: this
215 REAL,
DIMENSION(this%IGMIN:this%IGMAX,this%JGMIN:this%JGMAX,this%KGMIN:this%KGMAX), &
216 INTENT(IN) :: Txx,Txy,Txz,Tyx,Tyy,Tyz,Tzx,Tzy,Tzz
217 REAL,
DIMENSION(this%IGMIN:this%IGMAX,this%JGMIN:this%JGMAX,this%KGMIN:this%KGMAX), &
218 INTENT(OUT) :: divTx,divTy,divTz
220 PURE SUBROUTINE vectordivergence3d(this,vx,vy,vz,divv)
224 CLASS(mesh_base),
INTENT(IN) :: this
225 REAL,
DIMENSION(this%IGMIN:this%IGMAX,this%JGMIN:this%JGMAX,this%KGMIN:this%KGMAX) &
228 INTENT(IN) :: vx,vy,vz
231 PURE SUBROUTINE vectordivergence2d_1(this,vx,vy,divv)
235 CLASS(mesh_base),
INTENT(IN) :: this
236 REAL,
DIMENSION(this%IGMIN:this%IGMAX,this%JGMIN:this%JGMAX,this%KGMIN:this%KGMAX) &
242 PURE SUBROUTINE tensordivergence2d_1(this,Txx,Txy,Tyx,Tyy,divTx,divTy)
246 CLASS(mesh_base),
INTENT(IN) :: this
247 REAL,
DIMENSION(this%IGMIN:this%IGMAX,this%JGMIN:this%JGMAX,this%KGMIN:this%KGMAX) &
248 :: Txx,Txy,Tyx,Tyy,divTx,divTy
250 INTENT(IN) :: txx,txy,tyx,tyy
251 INTENT(OUT) :: divtx,divty
257 CLASS(mesh_base),
INTENT(INOUT) :: this
272 cylindrical, logcylindrical, &
273 spherical, logspherical, &
274 vector_x, vector_y, vector_z, &
275 west, east, south, north, bottom, top
286 SUBROUTINE initmesh(this,config,IO,mtype,mname)
289 CLASS(mesh_base) :: this
290 TYPE(Dict_TYP),
POINTER :: config
292 TYPE(Dict_TYP),
POINTER :: IO
294 CHARACTER(LEN=32) :: mname
296 CHARACTER(LEN=32) :: xres,yres,zres,somega
297 INTEGER :: meshtype,use_fargo,fargo
299 REAL :: mesh_dx,mesh_dy,mesh_dz
301 INTEGER :: inum,jnum,knum,err
303 REAL,
DIMENSION(6,3) :: cfaces
304 REAL,
DIMENSION(8,3) :: ccorners
306 INTENT(INOUT) :: this
308 CALL this%logging_base%InitLogging(mtype,mname)
310 CALL new_geometry(this%geometry, config)
322 CALL getattr(config,
"omega", this%omega, 0.0)
325 CALL getattr(config,
"Q", this%Q, 1.5)
328 this%rotcent = (/ 0., 0., 0./)
329 CALL getattr(config,
"rotation_center", this%rotcent, this%rotcent)
336 CALL getattr(config,
"inum", this%INUM)
337 CALL getattr(config,
"jnum", this%JNUM)
338 CALL getattr(config,
"knum", this%KNUM)
341 IF (any((/ this%INUM.LE.0, this%JNUM.LE.0, this%KNUM.LE.0 /))) &
342 CALL this%Error(
"InitMesh",
"zero or negative resolution not allowed.")
343 IF (all((/ this%INUM.EQ.1, this%JNUM.EQ.1, this%KNUM.EQ.1 /))) &
344 CALL this%Error(
"InitMesh",
"at least one of inum,jnum,knum must be > 1.")
347 CALL getattr(config,
"xmin", this%xmin)
348 CALL getattr(config,
"xmax", this%xmax)
349 CALL getattr(config,
"ymin", this%ymin)
350 CALL getattr(config,
"ymax", this%ymax)
351 CALL getattr(config,
"zmin", this%zmin)
352 CALL getattr(config,
"zmax", this%zmax)
362 SELECT CASE(this%geometry%GetAzimuthIndex())
364 IF (this%INUM.EQ.1.AND.(abs(this%xmax-this%xmin-2*pi).LE.epsilon(this%xmin))) &
367 IF (this%JNUM.EQ.1.AND.(abs(this%ymax-this%ymin-2*pi).LE.epsilon(this%ymin))) &
370 IF (this%KNUM.EQ.1.AND.(abs(this%zmax-this%zmin-2*pi).LE.epsilon(this%zmin))) &
395 this%GINUM = this%GNUM
396 this%GJNUM = this%GNUM
397 this%GKNUM = this%GNUM
402 this%VECTOR_COMPONENTS = b
'111' 403 IF (this%INUM.EQ.1)
THEN 404 this%NDIMS = this%NDIMS-1
405 IF (this%ROTSYM.NE.1) this%VECTOR_COMPONENTS = ieor(this%VECTOR_COMPONENTS,vector_x)
412 IF (this%JNUM.EQ.1)
THEN 413 this%NDIMS = this%NDIMS-1
414 IF (this%ROTSYM.NE.2) this%VECTOR_COMPONENTS = ieor(this%VECTOR_COMPONENTS,vector_y)
421 IF (this%KNUM.EQ.1)
THEN 422 this%NDIMS = this%NDIMS-1
423 IF (this%ROTSYM.NE.3) this%VECTOR_COMPONENTS = ieor(this%VECTOR_COMPONENTS,vector_z)
431 this%NFACES = nfaces(this%NDIMS)
432 this%NCORNERS = ncorners(this%NDIMS)
440 CALL initmesh_parallel(this, config)
441 CALL mpi_barrier(mpi_comm_world,err)
443 inum = this%IMAX - this%IMIN + 1
444 CALL mpi_allreduce(inum,this%MININUM,1,mpi_integer,mpi_min,mpi_comm_world,err)
445 CALL mpi_allreduce(inum,this%MAXINUM,1,mpi_integer,mpi_max,mpi_comm_world,err)
447 jnum = this%JMAX - this%JMIN + 1
448 CALL mpi_allreduce(jnum,this%MINJNUM,1,mpi_integer,mpi_min,mpi_comm_world,err)
449 CALL mpi_allreduce(jnum,this%MAXJNUM,1,mpi_integer,mpi_max,mpi_comm_world,err)
451 knum = this%KMAX - this%KMIN + 1
452 CALL mpi_allreduce(knum,this%MINKNUM,1,mpi_integer,mpi_min,mpi_comm_world,err)
453 CALL mpi_allreduce(knum,this%MAXKNUM,1,mpi_integer,mpi_max,mpi_comm_world,err)
456 this%IMAX = this%INUM
458 this%JMAX = this%JNUM
460 this%KMAX = this%KNUM
464 this%IGMIN = this%IMIN - this%GINUM
465 this%IGMAX = this%IMAX + this%GINUM
466 this%JGMIN = this%JMIN - this%GJNUM
467 this%JGMAX = this%JMAX + this%GJNUM
468 this%KGMIN = this%KMIN - this%GKNUM
469 this%KGMAX = this%KMAX + this%GKNUM
472 CALL initmeshproperties(this%IGMIN,this%IGMAX,this%JGMIN,this%JGMAX,this%KGMIN,this%KGMAX)
475 this%without_ghost_zones = selection_base((/this%IMIN,this%IMAX,this%JMIN,this%JMAX,this%KMIN,this%KMAX/))
478 this%dx = (this%xmax - this%xmin) / this%INUM
480 this%dy = (this%ymax - this%ymin) / this%JNUM
482 this%dz = (this%zmax - this%zmin) / this%KNUM
487 IF (this%dx.LT.2*epsilon(this%dx))
THEN 488 IF (this%INUM.EQ.1)
THEN 492 CALL this%Error(
"mesh_base::InitMesh",
"INUM > 1 conflicts with zero x-extent")
495 IF (this%dy.LT.2*epsilon(this%dy))
THEN 496 IF (this%JNUM.EQ.1)
THEN 500 CALL this%Error(
"mesh_base::InitMesh",
"JNUM > 1 conflicts with zero y-extent")
503 IF (this%dz.LT.2*epsilon(this%dz))
THEN 504 IF (this%KNUM.EQ.1)
THEN 508 CALL this%Error(
"mesh_base::InitMesh",
"KNUM > 1 conflicts with zero z-extent")
513 this%invdx = 1./this%dx
514 this%invdy = 1./this%dy
515 this%invdz = 1./this%dz
518 this%curv = marray_cellvector()
519 this%center => this%curv%RemapBounds(this%curv%center)
520 this%bcenter => this%curv%RemapBounds(this%curv%bcenter)
523 this%hx = marray_cellscalar()
524 this%hy = marray_cellscalar()
525 this%hz = marray_cellscalar()
528 this%sqrtg = marray_cellscalar()
531 this%cxyx = marray_cellscalar()
532 this%cxzx = marray_cellscalar()
533 this%cyxy = marray_cellscalar()
534 this%cyzy = marray_cellscalar()
535 this%czxz = marray_cellscalar()
536 this%czyz = marray_cellscalar()
539 this%volume = marray_base()
540 this%dxdydV = marray_base()
541 this%dydzdV = marray_base()
542 this%dzdxdV = marray_base()
543 this%dlx = marray_base()
544 this%dly = marray_base()
545 this%dlz = marray_base()
548 NULLIFY(this%dAx,this%dAy,this%dAz, &
549 this%dAxdydz,this%dAydzdx,this%dAzdxdy, &
550 this%rotation,this%weights)
554 cfaces(1,1) = -0.5*mesh_dx
557 cfaces(2,1) = 0.5*mesh_dx
561 cfaces(3,2) = -0.5*mesh_dy
564 cfaces(4,2) = 0.5*mesh_dy
568 cfaces(5,3) = -0.5*mesh_dz
571 cfaces(6,3) = 0.5*mesh_dz
573 ccorners(1,1) = cfaces(1,1)
574 ccorners(1,2) = cfaces(3,2)
575 ccorners(1,3) = cfaces(5,3)
576 ccorners(2,1) = cfaces(2,1)
577 ccorners(2,2) = cfaces(3,2)
578 ccorners(2,3) = cfaces(5,3)
579 ccorners(3,1) = cfaces(1,1)
580 ccorners(3,2) = cfaces(4,2)
581 ccorners(3,3) = cfaces(5,3)
582 ccorners(4,1) = cfaces(2,1)
583 ccorners(4,2) = cfaces(4,2)
584 ccorners(4,3) = cfaces(5,3)
585 ccorners(5,1) = cfaces(1,1)
586 ccorners(5,2) = cfaces(3,2)
587 ccorners(5,3) = cfaces(6,3)
588 ccorners(6,1) = cfaces(2,1)
589 ccorners(6,2) = cfaces(3,2)
590 ccorners(6,3) = cfaces(6,3)
591 ccorners(7,1) = cfaces(1,1)
592 ccorners(7,2) = cfaces(4,2)
593 ccorners(7,3) = cfaces(6,3)
594 ccorners(8,1) = cfaces(2,1)
595 ccorners(8,2) = cfaces(4,2)
596 ccorners(8,3) = cfaces(6,3)
598 DO k=this%KGMIN,this%KGMAX
599 DO j=this%JGMIN,this%JGMAX
600 DO i=this%IGMIN,this%IGMAX
602 this%curv%center(i,j,k,1) = this%xmin + (2*i-1)*0.5*mesh_dx
603 this%curv%center(i,j,k,2) = this%ymin + (2*j-1)*0.5*mesh_dy
604 this%curv%center(i,j,k,3) = this%zmin + (2*k-1)*0.5*mesh_dz
606 this%curv%faces(i,j,k,1,:) = this%curv%center(i,j,k,:) + cfaces(1,:)
607 this%curv%faces(i,j,k,2,:) = this%curv%center(i,j,k,:) + cfaces(2,:)
608 this%curv%faces(i,j,k,3,:) = this%curv%center(i,j,k,:) + cfaces(3,:)
609 this%curv%faces(i,j,k,4,:) = this%curv%center(i,j,k,:) + cfaces(4,:)
610 this%curv%faces(i,j,k,5,:) = this%curv%center(i,j,k,:) + cfaces(5,:)
611 this%curv%faces(i,j,k,6,:) = this%curv%center(i,j,k,:) + cfaces(6,:)
613 this%curv%corners(i,j,k,1,:) = this%curv%center(i,j,k,:) + ccorners(1,:)
614 this%curv%corners(i,j,k,2,:) = this%curv%center(i,j,k,:) + ccorners(2,:)
615 this%curv%corners(i,j,k,3,:) = this%curv%center(i,j,k,:) + ccorners(3,:)
616 this%curv%corners(i,j,k,4,:) = this%curv%center(i,j,k,:) + ccorners(4,:)
617 this%curv%corners(i,j,k,5,:) = this%curv%center(i,j,k,:) + ccorners(5,:)
618 this%curv%corners(i,j,k,6,:) = this%curv%center(i,j,k,:) + ccorners(6,:)
619 this%curv%corners(i,j,k,7,:) = this%curv%center(i,j,k,:) + ccorners(7,:)
620 this%curv%corners(i,j,k,8,:) = this%curv%center(i,j,k,:) + ccorners(8,:)
627 this%curv%bcenter = this%curv%center
631 CALL getattr(config,
"meshtype", meshtype)
636 CALL getattr(config,
"shear_dir", this%shear_dir, 0)
639 IF(this%shear_dir.GT.0) use_fargo = 1
640 CALL getattr(config,
"use_fargo", this%use_fargo, use_fargo)
646 IF (this%use_fargo.NE.0)
THEN 647 IF(this%shear_dir.GT.0) fargo = 3
648 CALL getattr(config,
"fargo", this%FARGO, fargo)
657 CALL this%Geometry%ScaleFactors(this%curv,this%hx,this%hy,this%hz)
661 this%sqrtg = this%hx*(this%hy*this%hz)
664 this%cart = marray_cellvector()
665 this%bccart => this%cart%RemapBounds(this%cart%bcenter)
666 this%fccart => this%cart%RemapBounds(this%cart%faces)
667 this%ccart => this%cart%RemapBounds(this%cart%corners)
670 CALL this%Geometry%Convert2Cartesian(this%curv,this%cart)
673 this%radius = marray_cellscalar()
674 CALL this%geometry%Radius(this%curv,this%radius)
677 this%posvec = marray_cellvector()
678 CALL this%geometry%PositionVector(this%curv,this%posvec)
729 CALL this%Info(
" MESH-----> quadrature rule: " // trim(this%GetName()))
730 WRITE (xres,
'(I0)') this%INUM
731 WRITE (yres,
'(I0)') this%JNUM
732 WRITE (zres,
'(I0)') this%KNUM
733 CALL this%Info(
" resolution: " // trim(xres) //
" x " // trim(yres) //
" y "// trim(zres) //
" z ")
734 WRITE (xres,
'(ES9.2,A,ES9.2)') this%xmin,
" ..", this%xmax
735 WRITE (yres,
'(ES9.2,A,ES9.2)') this%ymin,
" ..", this%ymax
736 WRITE (zres,
'(ES9.2,A,ES9.2)') this%zmin,
" ..", this%zmax
737 CALL this%Info(
" computat. domain: x=" // trim(xres))
738 CALL this%Info(
" y=" // trim(yres))
739 CALL this%Info(
" z=" // trim(zres))
740 IF(this%omega.NE.0.)
THEN 741 WRITE (somega,
'(ES9.2)') this%omega
742 CALL this%Info(
" ang. velocity: " // trim(somega))
744 SELECT CASE(this%ROTSYM)
748 somega =
"x-coordinate" 750 somega =
"y-coordinate" 752 somega =
"z-coordinate" 754 CALL this%Info(
" rot. symmetry: " // trim(somega))
756 WRITE (xres,
'(I0)') this%dims(1)
757 WRITE (yres,
'(I0)') this%dims(2)
758 WRITE (zres,
'(I0)') this%dims(3)
759 CALL this%Info(
" MPI partition: " // trim(xres) //
" x " // trim(yres) //
" y "// trim(zres) //
" z ")
766 CALL setoutput(this,config,io)
768 END SUBROUTINE initmesh
771 SUBROUTINE setoutput(this,config,IO)
774 CLASS(mesh_base),
INTENT(INOUT) :: this
775 TYPE(Dict_TYP),
POINTER :: config,IO
777 INTEGER :: writefields
780 CALL getattr(config,
"output/corners", writefields, 1)
781 IF((writefields.EQ.1).AND.
ASSOCIATED(this%ccart)) &
785 CALL getattr(config,
"output/grid", writefields, 1)
786 IF((writefields.EQ.1).AND.
ASSOCIATED(this%ccart))
THEN 787 CALL setattr(io,
"grid_x",this%ccart(this%IMIN:this%IMAX+this%ip1, &
788 this%JMIN:this%JMAX+this%jp1, &
789 this%KMIN:this%KMAX+this%kp1,1,1))
790 CALL setattr(io,
"grid_y",this%ccart(this%IMIN:this%IMAX+this%ip1, &
791 this%JMIN:this%JMAX+this%jp1, &
792 this%KMIN:this%KMAX+this%kp1,1,2))
793 CALL setattr(io,
"grid_z",this%ccart(this%IMIN:this%IMAX+this%ip1, &
794 this%JMIN:this%JMAX+this%jp1, &
795 this%KMIN:this%KMAX+this%kp1,1,3))
798 CALL getattr(config,
"output/bary_curv", writefields, 1)
799 IF((writefields.EQ.1).AND.
ASSOCIATED(this%bcenter)) &
800 CALL setattr(io,
"bary_curv",this%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX,:))
802 CALL getattr(config,
"output/bary", writefields, 1)
803 IF((writefields.EQ.1).AND.
ASSOCIATED(this%bccart)) &
804 CALL setattr(io,
"bary_centers",this%bccart(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX,:))
807 CALL getattr(config,
"output/rotation", writefields, 0)
808 IF(writefields.EQ.1)
THEN 809 CALL calculaterotation(this)
810 CALL setattr(io,
"rotation",this%rotation(this%IMIN:this%IMAX,this%JMIN:this%JMAX))
813 CALL getattr(config,
"output/dl", writefields, 0)
814 IF(writefields.EQ.1)
THEN 815 IF (
ASSOCIATED(this%dlx%data3d)) &
816 CALL setattr(io,
"dlx",this%dlx%data3d(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
817 IF (
ASSOCIATED(this%dly%data3d)) &
818 CALL setattr(io,
"dly",this%dly%data3d(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
819 IF (
ASSOCIATED(this%dlz%data3d)) &
820 CALL setattr(io,
"dlz",this%dlz%data3d(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
823 CALL getattr(config,
"output/bh", writefields, 0)
824 IF(writefields.EQ.1)
THEN 825 IF (
ASSOCIATED(this%hx%bcenter)) &
826 CALL setattr(io,
"bhx",this%hx%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
827 IF (
ASSOCIATED(this%hy%bcenter)) &
828 CALL setattr(io,
"bhy",this%hy%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
829 IF (
ASSOCIATED(this%hz%bcenter)) &
830 CALL setattr(io,
"bhz",this%hz%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
833 CALL getattr(config,
"output/commutator", writefields, 0)
834 IF(writefields.EQ.1)
THEN 835 IF (
ASSOCIATED(this%cxyx%bcenter)) &
836 CALL setattr(io,
"cxyx",this%cxyx%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
837 IF (
ASSOCIATED(this%cxzx%bcenter)) &
838 CALL setattr(io,
"cxzx",this%cxzx%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
839 IF (
ASSOCIATED(this%cyxy%bcenter)) &
840 CALL setattr(io,
"cyxy",this%cyxy%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
841 IF (
ASSOCIATED(this%cyzy%bcenter)) &
842 CALL setattr(io,
"cyzy",this%cyzy%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
843 IF (
ASSOCIATED(this%czxz%bcenter)) &
844 CALL setattr(io,
"czxz",this%czxz%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
845 IF (
ASSOCIATED(this%czyz%bcenter)) &
846 CALL setattr(io,
"czyz",this%czyz%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
849 CALL getattr(config,
"output/volume", writefields, 0)
850 IF((writefields.EQ.1).AND.
ASSOCIATED(this%volume%data3d)) &
851 CALL setattr(io,
"volume",this%volume%data3d(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
853 CALL getattr(config,
"output/dA", writefields, 0)
854 IF(writefields.EQ.1)
THEN 855 IF (
ASSOCIATED(this%dAx)) &
856 CALL setattr(io,
"dAx",this%dAx(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX,:))
857 IF (
ASSOCIATED(this%dAy)) &
858 CALL setattr(io,
"dAy",this%dAy(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX,:))
859 IF (
ASSOCIATED(this%dAz)) &
860 CALL setattr(io,
"dAz",this%dAz(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX,:))
863 CALL getattr(config,
"output/radius", writefields, 0)
864 IF((writefields.EQ.1).AND.
ASSOCIATED(this%radius%bcenter)) &
865 CALL setattr(io,
"radius",this%radius%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX))
867 CALL getattr(config,
"output/position_vector", writefields, 0)
868 IF((writefields.EQ.1).AND.
ASSOCIATED(this%posvec%bcenter)) &
869 CALL setattr(io,
"position_vector",this%posvec%bcenter(this%IMIN:this%IMAX,this%JMIN:this%JMAX,this%KMIN:this%KMAX,:))
871 END SUBROUTINE setoutput
880 SUBROUTINE calculaterotation(this)
883 CLASS(mesh_base) :: this
886 REAL,
DIMENSION(this%IGMIN:this%IGMAX,this%JGMIN:this%JGMAX,this%KGMIN:this%KGMAX,3) :: cart,curv
888 ALLOCATE(this%rotation(this%IGMIN:this%IGMAX,this%JGMIN:this%JGMAX), &
891 CALL this%Error(
"CalculateRotation",
"Couldn't allocate memory")
896 CALL this%geometry%Convert2Curvilinear(this%bcenter, cart, curv)
897 this%rotation(:,:) = atan2(curv(:,:,1,2),curv(:,:,1,1))
898 END SUBROUTINE calculaterotation
906 PURE FUNCTION internalpoint(this,x,y,z,mask)
RESULT(ip)
909 CLASS(mesh_base),
INTENT(IN) :: this
910 INTEGER,
DIMENSION(6),
OPTIONAL :: mask
914 INTEGER :: imin,imax,jmin,jmax,kmin,kmax
916 INTENT(IN) :: x,y,z,mask
928 IF (
PRESENT(mask))
THEN 931 imin = max(this%IGMIN,mask(1))
932 imax = min(this%IGMAX,mask(2))
933 jmin = max(this%JGMIN,mask(3))
934 jmax = min(this%JGMAX,mask(4))
935 kmin = max(this%KGMIN,mask(5))
936 kmax = min(this%KGMAX,mask(6))
938 IF (((imin.LE.this%IGMAX).AND.(imax.GE.imin)).AND. &
939 ((jmin.LE.this%JGMAX).AND.(jmax.GE.jmin)).AND. &
940 ((kmin.LE.this%KGMAX).AND.(kmax.GE.kmin)))
THEN 943 IF ((x.GE.this%curv%faces(imin,jmin,kmin,1,1).AND.x.LE.this%curv%faces(imax,jmax,kmax,2,1)).AND. &
944 (y.GE.this%curv%faces(imin,jmin,kmin,1,2).AND.y.LE.this%curv%faces(imax,jmax,kmax,2,2)).AND. &
945 (z.GE.this%curv%faces(imin,jmin,kmin,1,3).AND.z.LE.this%curv%faces(imax,jmax,kmax,2,3)))
THEN 951 IF (((x.GE.this%xmin).AND.(x.LE.this%xmax)).AND. &
952 ((y.GE.this%ymin).AND.(y.LE.this%ymax)).AND. &
953 ((z.GE.this%zmin).AND.(z.LE.this%zmax)))
THEN 957 END FUNCTION internalpoint
967 SUBROUTINE initmesh_parallel(this, config)
970 CLASS(mesh_base),
INTENT(INOUT) :: this
971 TYPE(Dict_TYP),
POINTER :: config
973 CHARACTER(LEN=64) :: decomp_str
974 LOGICAL,
DIMENSION(3) :: remain_dims, periods
978 INTEGER :: worldgroup,newgroup
979 INTEGER,
DIMENSION(1) :: rank0in, rank0out
980 INTEGER,
DIMENSION(3) :: coords,ncells,dims
981 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ranks
1002 CALL getattr(config,
"decomposition", dims, dims(1:3))
1006 IF (this%GetRank().EQ.0)
THEN 1008 WRITE (decomp_str,
'(3(A,I0),A)')
"[ ", dims(1),
", ", dims(2),
", ",dims(3),
" ]" 1011 ncells(1) = this%INUM
1012 ncells(2) = this%JNUM
1013 ncells(3) = this%KNUM
1016 IF (all(dims(:).GE.1).AND.product(dims(:)).NE.this%GetNumProcs()) &
1017 CALL this%Error(
"InitMesh_parallel",
"total number of processes in domain decomposition " &
1018 // trim(decomp_str) // achar(10) // repeat(
' ',7) // &
1019 "does not match the number passed to mpirun")
1021 IF (any(dims(:).EQ.0)) &
1022 CALL this%Error(
"InitMesh_parallel",
"numbers in decomposition should not be 0")
1024 IF (mod(this%GetNumProcs(),product(dims(:),dims(:).GT.1)).NE.0) &
1025 CALL this%Error(
"InitMesh_parallel",
"numbers in decomposition " &
1026 // trim(decomp_str) // achar(10) // repeat(
' ',7) // &
1027 "are not devisors of the total number of processes passed to mpirun")
1030 IF (all(dims(:).GT.0))
THEN 1032 ELSE IF (product(dims(:)).GT.0)
THEN 1035 k = maxloc(dims(:),1)
1041 dims(3) = this%GetNumProcs() / dims(k)
1044 CALL calculatedecomposition(ncells(3),ncells(2),ncells(1),this%GKNUM, &
1045 dims(3),dims(2),dims(1))
1047 dims(1) = this%GetNumProcs() / dims(k)
1050 CALL calculatedecomposition(ncells(1),ncells(2),ncells(3),this%GKNUM, &
1051 dims(1),dims(2),dims(3))
1054 ELSE IF (all(dims(:).LT.0))
THEN 1056 dims(1) = this%GetNumProcs()
1059 CALL calculatedecomposition(ncells(1),ncells(2),ncells(3),this%GINUM, &
1060 dims(1),dims(2),dims(3))
1064 k = minloc(dims(:),1)
1065 dims(k) = this%GetNumProcs() / product(dims(:),dims(:).GT.1)
1068 WRITE (decomp_str,
'(3(A,I0),A)')
"[ ", dims(1),
", ", dims(2),
", ",dims(3),
" ]" 1071 ncells(1) = this%INUM
1072 ncells(2) = this%JNUM
1073 ncells(3) = this%KNUM
1075 IF (dims(i).GT.ncells(i)) &
1076 CALL this%Error(
"InitMesh_parallel",
"number of processes exceeds number of cells " &
1077 // achar(10) // repeat(
' ',7) //
"in dimension " // achar(48+i) //
", check decomposition " &
1078 // trim(decomp_str))
1081 IF (dims(3).LE.0)
THEN 1082 CALL this%Error(
"InitMesh_parallel",
"automatic domain decomposition failed.")
1085 this%dims(:) = dims(:)
1089 CALL mpi_bcast(this%dims,3,mpi_integer,0,mpi_comm_world,ierror)
1097 CALL mpi_cart_create(mpi_comm_world,3,this%dims,periods,.true., &
1098 this%comm_cart,ierror)
1101 this%mycoords(:) = 0
1102 CALL mpi_cart_get(this%comm_cart,3,this%dims,periods,this%mycoords,ierror)
1105 remain_dims = (/ .true., .false., .false. /)
1106 CALL mpi_cart_sub(this%comm_cart,remain_dims,this%Icomm,ierror)
1107 remain_dims = (/ .false., .true., .false. /)
1108 CALL mpi_cart_sub(this%comm_cart,remain_dims,this%Jcomm,ierror)
1109 remain_dims = (/ .false., .false., .true. /)
1110 CALL mpi_cart_sub(this%comm_cart,remain_dims,this%Kcomm,ierror)
1114 rem = mod(this%INUM,this%dims(1))
1115 num = (this%INUM-rem) / this%dims(1)
1116 IF (this%mycoords(1).LT.rem)
THEN 1118 this%IMIN = this%mycoords(1) * (num + 1) + 1
1119 this%IMAX = this%IMIN + num
1121 this%IMIN = rem * (num+1) + (this%mycoords(1) - rem) * num + 1
1122 this%IMAX = this%IMIN + num - 1
1125 rem = mod(this%JNUM,this%dims(2))
1126 num = (this%JNUM-rem) / this%dims(2)
1127 IF (this%mycoords(2).LT.rem)
THEN 1129 this%JMIN = this%mycoords(2) * (num + 1) + 1
1130 this%JMAX = this%JMIN + num
1132 this%JMIN = rem * (num+1) + (this%mycoords(2) - rem) * num + 1
1133 this%JMAX = this%JMIN + num - 1
1136 rem = mod(this%KNUM,this%dims(3))
1137 num = (this%KNUM-rem) / this%dims(3)
1138 IF (this%mycoords(3).LT.rem)
THEN 1140 this%KMIN = this%mycoords(3) * (num + 1) + 1
1141 this%KMAX = this%KMIN + num
1143 this%KMIN = rem * (num+1) + (this%mycoords(3) - rem) * num + 1
1144 this%KMAX = this%KMIN + num - 1
1148 ALLOCATE(ranks(max(this%dims(1)*this%dims(2),this%dims(1)*this%dims(3),this%dims(2)*this%dims(3))))
1150 CALL mpi_comm_group(mpi_comm_world,worldgroup,ierror)
1153 DO k=0,this%dims(3)-1
1154 DO j=0,this%dims(2)-1
1157 CALL mpi_cart_rank(this%comm_cart,coords,i,ierror)
1158 ranks(j+1+k*this%dims(2))=i
1161 CALL mpi_group_incl(worldgroup,this%dims(2)*this%dims(3),ranks,newgroup,ierror)
1162 CALL mpi_comm_create(this%comm_cart,newgroup,this%comm_boundaries(1),ierror)
1164 CALL mpi_group_translate_ranks(newgroup,1,rank0in,worldgroup,rank0out,ierror)
1165 this%rank0_boundaries(1) = rank0out(1)
1166 CALL mpi_group_free(newgroup,ierror)
1168 coords(1) = this%dims(1)-1
1169 DO k=0,this%dims(3)-1
1170 DO j=0,this%dims(2)-1
1173 CALL mpi_cart_rank(this%comm_cart,coords,i,ierror)
1174 ranks(j+1+k*this%dims(2))=i
1177 CALL mpi_group_incl(worldgroup,this%dims(2)*this%dims(3),ranks,newgroup,ierror)
1178 CALL mpi_comm_create(this%comm_cart,newgroup,this%comm_boundaries(2),ierror)
1180 CALL mpi_group_translate_ranks(newgroup,1,rank0in,worldgroup,rank0out,ierror)
1181 this%rank0_boundaries(2) = rank0out(1)
1182 CALL mpi_group_free(newgroup,ierror)
1185 DO k=0,this%dims(3)-1
1186 DO i=0,this%dims(1)-1
1189 CALL mpi_cart_rank(this%comm_cart,coords,j,ierror)
1190 ranks(i+1+k*this%dims(1))=j
1193 CALL mpi_group_incl(worldgroup,this%dims(1)*this%dims(3),ranks,newgroup,ierror)
1194 CALL mpi_comm_create(this%comm_cart,newgroup,this%comm_boundaries(3),ierror)
1196 CALL mpi_group_translate_ranks(newgroup,1,rank0in,worldgroup,rank0out,ierror)
1197 this%rank0_boundaries(3) = rank0out(1)
1198 CALL mpi_group_free(newgroup,ierror)
1200 coords(2) = this%dims(2)-1
1201 DO k=0,this%dims(3)-1
1202 DO i=0,this%dims(1)-1
1205 CALL mpi_cart_rank(this%comm_cart,coords,j,ierror)
1206 ranks(i+1+k*this%dims(1))=j
1209 CALL mpi_group_incl(worldgroup,this%dims(1)*this%dims(3),ranks,newgroup,ierror)
1210 CALL mpi_comm_create(this%comm_cart,newgroup,this%comm_boundaries(4),ierror)
1212 CALL mpi_group_translate_ranks(newgroup,1,rank0in,worldgroup,rank0out,ierror)
1213 this%rank0_boundaries(4) = rank0out(1)
1214 CALL mpi_group_free(newgroup,ierror)
1217 DO j=0,this%dims(2)-1
1218 DO i=0,this%dims(1)-1
1221 CALL mpi_cart_rank(this%comm_cart,coords,k,ierror)
1222 ranks(i+1+j*this%dims(1))=k
1225 CALL mpi_group_incl(worldgroup,this%dims(1)*this%dims(2),ranks,newgroup,ierror)
1226 CALL mpi_comm_create(this%comm_cart,newgroup,this%comm_boundaries(5),ierror)
1228 CALL mpi_group_translate_ranks(newgroup,1,rank0in,worldgroup,rank0out,ierror)
1229 this%rank0_boundaries(5) = rank0out(1)
1230 CALL mpi_group_free(newgroup,ierror)
1232 coords(3) = this%dims(3)-1
1233 DO j=0,this%dims(2)-1
1234 DO i=0,this%dims(1)-1
1237 CALL mpi_cart_rank(this%comm_cart,coords,k,ierror)
1238 ranks(i+1+j*this%dims(1))=k
1241 CALL mpi_group_incl(worldgroup,this%dims(1)*this%dims(2),ranks,newgroup,ierror)
1242 CALL mpi_comm_create(this%comm_cart,newgroup,this%comm_boundaries(6),ierror)
1244 CALL mpi_group_translate_ranks(newgroup,1,rank0in,worldgroup,rank0out,ierror)
1245 this%rank0_boundaries(6) = rank0out(1)
1246 CALL mpi_group_free(newgroup,ierror)
1248 CALL mpi_group_free(worldgroup,ierror)
1250 END SUBROUTINE initmesh_parallel
1260 SUBROUTINE calculatedecomposition(ni,nj,nk,ginum,pi,pj,pk)
1264 INTEGER,
INTENT(IN) :: ni,nj,nk,ginum
1265 INTEGER,
INTENT(INOUT) :: pi,pj,pk
1267 CHARACTER(LEN=8) :: svl_char
1271 svl_char = vector_length
1272 READ (svl_char,
'(I8)',iostat=err) svl
1274 IF (any((/pi.LT.1,pi.GT.
maxnum,pj.NE.1,pk.NE.1,err.NE.0, &
1275 min(ni,nj,nk).LT.1/)))
THEN 1279 CALL decompose(pi,pj,pk)
1295 RECURSIVE SUBROUTINE decompose(pi,pj,pk)
1298 INTEGER,
INTENT(INOUT) :: pi,pj,pk
1301 INTEGER :: p1,p2,p3,pinew,pjnew,pknew,piold,pjold,pkold,pinew_,pjnew_,pknew_
1302 INTEGER :: pfmin,pfnew,pfold
1303 INTEGER :: bl,vl,blnew,vlnew,blnew_,vlnew_
1304 REAL :: bl_gain,vl_gain
1308 IF (pj.GT.nj.OR.pk.GT.nk)
RETURN 1310 CALL getcosts(ni,nj,nk,pi,pj,pk,bl,vl)
1329 IF ((pfnew.GT.pfmin).AND.(pfmin.NE.1))
EXIT 1332 IF (pfnew.NE.pfold)
THEN 1342 CALL decompose(pinew,pjnew,pknew)
1343 CALL getcosts(ni,nj,nk,pinew,pjnew,pknew,blnew,vlnew)
1348 CALL decompose(pinew_,pjnew_,pknew_)
1349 CALL getcosts(ni,nj,nk,pinew_,pjnew_,pknew_,blnew_,vlnew_)
1351 bl_gain = blnew*(1.0/blnew_)
1352 vl_gain = vlnew_*(1.0/vlnew)
1357 IF (vl_gain*bl_gain.GT.1.0)
THEN 1366 bl_gain = bl*(1.0/blnew)
1367 vl_gain = vlnew*(1.0/vl)
1368 IF (vl_gain*bl_gain.GT.1.0)
THEN 1383 END SUBROUTINE decompose
1387 PURE SUBROUTINE getcosts(n1,n2,n3,p1,p2,p3,bl,vl)
1390 INTEGER,
INTENT(IN) :: n1,n2,n3,p1,p2,p3
1391 INTEGER,
INTENT(OUT) :: bl,vl
1396 bl = n3*n2*(p1-1) + n1*n3*(p2-1) + n1*n2*(p3-1)
1401 num = n1 / p1 + 2*ginum
1402 IF (mod(n1,p1).NE.0) num = num + 1
1403 IF (num.LE.svl)
THEN 1409 vl = num / ((num / svl) + 1)
1414 END SUBROUTINE getcosts
1416 END SUBROUTINE calculatedecomposition
1428 FUNCTION remapbounds_1(this,array)
RESULT(ptr)
1431 CLASS(mesh_base) :: this
1432 REAL,
DIMENSION(this%IGMIN:,this%JGMIN:,this%KGMIN:),
TARGET :: array
1434 REAL,
DIMENSION(:,:,:),
POINTER :: ptr
1439 END FUNCTION remapbounds_1
1442 FUNCTION remapbounds_2(this,array)
RESULT(ptr)
1445 CLASS(mesh_base) :: this
1446 REAL,
DIMENSION(this%IGMIN:,this%JGMIN:,this%KGMIN:,:),
TARGET &
1449 REAL,
DIMENSION(:,:,:,:),
POINTER :: ptr
1454 END FUNCTION remapbounds_2
1457 FUNCTION remapbounds_3(this,array)
RESULT(ptr)
1460 CLASS(mesh_base) :: this
1461 REAL,
DIMENSION(this%IGMIN:,this%JGMIN:,this%KGMIN:,:,:),
TARGET &
1464 REAL,
DIMENSION(:,:,:,:,:),
POINTER :: ptr
1469 END FUNCTION remapbounds_3
1472 FUNCTION remapbounds_4(this,array)
RESULT(ptr)
1475 CLASS(mesh_base) :: this
1476 REAL,
DIMENSION(this%IGMIN:,this%JGMIN:,this%KGMIN:,:,:,:),
TARGET &
1479 REAL,
DIMENSION(:,:,:,:,:,:),
POINTER :: ptr
1484 END FUNCTION remapbounds_4
1488 SUBROUTINE finalize_base(this)
1491 CLASS(mesh_base),
INTENT(INOUT) :: this
1496 IF (.NOT.this%Initialized()) &
1497 CALL this%Error(
"CloseMesh",
"not initialized")
1500 IF (this%comm_boundaries(i).NE.mpi_comm_null) &
1501 CALL mpi_comm_free(this%comm_boundaries(i),ierror)
1506 CALL this%curv%Destroy()
1507 CALL this%hx%Destroy()
1508 CALL this%hy%Destroy()
1509 CALL this%hz%Destroy()
1510 CALL this%sqrtg%Destroy()
1511 CALL this%cxyx%Destroy()
1512 CALL this%cxzx%Destroy()
1513 CALL this%cyxy%Destroy()
1514 CALL this%cyzy%Destroy()
1515 CALL this%czxz%Destroy()
1516 CALL this%czyz%Destroy()
1518 CALL this%volume%Destroy()
1519 CALL this%dxdydV%Destroy()
1520 CALL this%dydzdV%Destroy()
1521 CALL this%dzdxdV%Destroy()
1523 CALL this%dlx%Destroy()
1524 CALL this%dly%Destroy()
1525 CALL this%dlz%Destroy()
1527 CALL this%cart%Destroy()
1528 CALL this%radius%Destroy()
1529 CALL this%posvec%Destroy()
1531 IF (
ASSOCIATED(this%rotation))
DEALLOCATE(this%rotation)
1533 CALL this%without_ghost_zones%Destroy()
1535 CALL closemeshproperties
1537 CALL this%Geometry%Finalize()
1538 DEALLOCATE(this%Geometry)
1539 END SUBROUTINE finalize_base
1542 END MODULE mesh_base_mod
subroutine finalize(this)
Destructor of common class.
integer, save default_mpi_real
default real type for MPI
base class for mesh arrays
pure integer function, public getfactor(number)
derived mesh array class for scalar cell data
integer, parameter, public maxnum
constructor for geometry class
base class for geometrical properties
derived mesh array class for vector cell data
module for prime factorization
Dictionary for generic data types.