module MeshClass use std implicit none integer(int32) :: PF_GLYCINE_MAX = 1 integer(int32) :: PF_GLYCINE_SOJA = 1 integer(int32) :: PF_SOYBEAN = 1 integer(int32) :: PF_MAIZE = 2 type:: Mesh_ ! Name character*200::FileName=" " ! Nodal coordinates real(real64),allocatable ::NodCoord(:,:) ! Connectivity information for FE-mesh integer(int32),allocatable::ElemNod(:,:) ! Material IDs for Finite Elements integer(int32),allocatable::ElemMat(:) integer(int32),allocatable::MasterID(:) integer(int32),allocatable::SlaveID(:) integer(int32),allocatable::NTSMasterFacetID(:) real(real64),allocatable :: xi(:,:) ! optional data; real(real64),allocatable ::NodCoordInit(:,:) integer(int32),allocatable::BottomElemID integer(int32),allocatable::TopElemID integer(int32),allocatable::FacetElemNod(:,:) integer(int32),allocatable::NextFacets(:,:) integer(int32),allocatable::SurfaceLine2D(:) integer(int32),allocatable::SubMeshNodFromTo(:,:) integer(int32),allocatable::SubMeshElemFromTo(:,:) integer(int32),allocatable::SubMeshSurfFromTo(:,:) integer(int32) :: surface=1 !for Interfaces integer(int32),allocatable::GlobalNodID(:) character(len=36) :: uuid character*70::ElemType=" " character*70:: ErrorMsg=" " character*70:: meshtype contains procedure :: add => addMesh procedure :: addElements => addElementsMesh procedure :: adjustSphere => AdjustSphereMesh procedure :: adjustCylinder => AdjustCylinderMesh procedure :: assemble => assembleMesh procedure :: arrangeNodeOrder => arrangeNodeOrderMesh procedure :: copy => CopyMesh procedure :: cut => cutMesh procedure :: convertMeshType => ConvertMeshTypeMesh procedure :: convertTetraToHexa => convertTetraToHexaMesh procedure :: convertTriangleToRectangular => convertTriangleToRectangularMesh procedure :: create=>createMesh procedure :: check=>checkMesh procedure :: convert2Dto3D => Convert2Dto3DMesh procedure :: clean => cleanMesh procedure :: delete => DeallocateMesh procedure :: detectIface => detectIfaceMesh procedure :: displayMesh => DisplayMesh procedure :: display => DisplayMesh procedure :: divide => divideMesh procedure :: delauneygetNewNode => DelauneygetNewNodeMesh procedure :: delauneygetNewNode3D => DelauneygetNewNode3DMesh procedure :: delauneygetNewTriangle => DelauneygetNewTriangleMesh procedure :: delauneyremoveOverlaps => DelauneyremoveOverlapsMesh procedure :: export => exportMeshObj procedure :: exportElemNod => ExportElemNod procedure :: exportNodCoord => ExportNodCoord procedure :: exportSurface2D => ExportSurface2D procedure :: empty => emptyMesh procedure :: edit => editMesh procedure :: getCoordinate => getCoordinateMesh procedure :: getNodeIDinElement => getNodeIDinElementMesh procedure :: getFacetElement => GetFacetElement procedure :: getFacetNodeID => getFacetNodeIDMesh procedure :: getSurface => GetSurface procedure :: getInterface => GetInterface procedure :: getInterfaceElemNod => GetInterfaceElemNod procedure :: getBoundingBox => GetBoundingBox procedure :: getFacetElemInsideBox => GetFacetElemInsideBox procedure :: getInterSectBox => GetInterSectBox procedure :: getNextFacets => GetNextFacets procedure :: getElemType => GetElemTypeMesh procedure :: getElement=> getElementMesh procedure :: getNumOfDomain => getNumOfDomainMesh procedure :: getCircumscribedCircle => getCircumscribedCircleMesh procedure :: getCircumscribedSphere => getCircumscribedSphereMesh procedure :: getCircumscribedTriangle => getCircumscribedTriangleMesh procedure :: getCircumscribedBox => getCircumscribedBoxMesh procedure :: getCircumscribedSphereOfTetra => getCircumscribedSphereOfTetraMesh procedure :: getNodeList => getNodeListMesh procedure :: getFacetList => getFacetListMesh procedure :: getElementList => getElementListMesh procedure :: getVolume => getVolumeMesh procedure :: getShapeFunction => getShapeFunctionMesh procedure :: getCenterCoordinate => getCenterCoordinateMesh procedure :: getNeighboringNode => getNeighboringNodeMesh procedure :: getNeighboringElement => getNeighboringElementMesh procedure :: ShapeFunction => getShapeFunctionMesh procedure :: gmsh => gmshMesh procedure :: import => importMeshObj procedure :: importElemNod => ImportElemNod procedure :: importNodCoord => ImportNodCoord procedure :: importElemMat => ImportElemMat procedure :: init => InitializeMesh procedure :: InsideOfElement => InsideOfElementMesh procedure :: json => jsonMesh procedure :: length => lengthMesh procedure :: Laplacian => LaplacianMesh procedure :: mergeMesh => MergeMesh procedure :: meltingSkelton => MeltingSkeltonMesh procedure :: meshing => MeshingMesh procedure :: numElements => numElementsMesh procedure :: ne => numElementsMesh procedure :: numNodes => numNodesMesh procedure :: nn => numNodesMesh procedure :: numNodesForEachElement => numNodesForEachElementMesh procedure :: nne => numNodesForEachElementMesh procedure :: numDimension => numDimensionMesh procedure :: nd => numDimensionMesh procedure :: nearestElementID => nearestElementIDMesh procedure :: getNearestElementID => NearestElementIDMesh procedure :: getNearestNodeID => getNearestNodeIDMesh procedure :: HowManyDomain => HowManyDomainMesh procedure :: open => openMesh procedure :: position => positionMesh procedure :: position_x => position_xMesh procedure :: position_y => position_yMesh procedure :: position_z => position_zMesh procedure :: remove => removeMesh procedure :: removeCircumscribedTriangle => removeCircumscribedTriangleMesh procedure :: removeFailedTriangle => RemoveFailedTriangleMesh procedure :: removeOverlappedNode =>removeOverlappedNodeMesh procedure :: removeElements => removeElementsMesh procedure :: resize => resizeMeshobj procedure :: remesh => remeshMesh procedure :: save => saveMesh procedure :: sortFacet => SortFacetMesh procedure :: shift=>shiftMesh procedure :: showRange => showRangeMesh procedure :: showMesh => ShowMesh procedure :: show => ShowMesh end type Mesh_ contains ! ########################################################################## function getCoordinateMesh(obj,NodeID,onlyX,onlyY,OnlyZ) result(x) class(Mesh_),intent(inout) :: obj integer(int32),optional,intent(in) :: NodeID real(real64),allocatable :: x(:) logical,optional,intent(in) :: onlyX,onlyY,OnlyZ integer(int32) :: n,m,itr,i,j if(.not.allocated(obj%nodcoord) )then print *, "getCoordinateMesh :: mesh is not allocated." return endif n = size(obj%nodcoord,1) m = size(obj%nodcoord,2) if(present(NodeID))then if(present(onlyX))then if(onlyX .eqv. .true.) then allocate(x(1) ) x(1) = obj%nodcoord(NodeID,1) return endif endif if(present(onlyY))then if(onlyY .eqv. .true.) then allocate(x(1) ) x(1) = obj%nodcoord(NodeID,2) return endif endif if(present(onlyZ))then if(onlyZ .eqv. .true.) then allocate(x(1) ) x(1) = obj%nodcoord(NodeID,3) return endif endif allocate(x(m) ) x(:) = obj%nodcoord(NodeID,:) else if(present(onlyX))then if(onlyX .eqv. .true.) then allocate(x(n) ) x(:) = obj%nodcoord(:,1) return endif endif if(present(onlyY))then if(onlyY .eqv. .true.) then allocate(x(n) ) x(:) = obj%nodcoord(:,2) return endif endif if(present(onlyZ))then if(onlyZ .eqv. .true.) then allocate(x(n) ) x(:) = obj%nodcoord(:,3) return endif endif allocate(x(n*m) ) itr=0 do i=1,m do j=1,m itr=itr+1 x(itr) = obj%nodcoord(i,j) enddo enddo endif end function ! ########################################################################## ! ########################################################################## function getNodeIDinElementMesh(obj,ElementID) result(NodeIDList) class(Mesh_),intent(inout) :: obj integer(int32),intent(in) :: ElementID integer(int32),allocatable :: NodeIDList(:) integer(int32) :: m if(.not.allocated(obj%elemnod) )then print *, "ERROR :: getNodeIDinElementMesh :: mesh is NOT created." return endif m = size(obj%elemnod,2) allocate(NodeIDList(m) ) NodeIDList(:) = obj%elemnod(ElementID,:) end function ! ########################################################################## ! #################################################################### function detectIfaceMesh(obj,material1, material2) result(list) class(Mesh_) ,intent(inout) :: obj integer(int32),optional,intent(in) :: material1, material2 integer(int32),allocatable :: list(:) integer(int32) :: itr, i,j,k,l,n,node_id,m ! if(present(,material1) .and. present(,material2))then ! ! rip between material 1 and material 2 ! ! if(material1 == material2)then ! print *, "caution! cutmesh >> material1 == material2" ! return ! endif ! ! ! detect interface ! do i=1,size(obj%ElemNod,1) ! if(obj%ElemMat(i) == material1 )then ! do j=i+1, size(obj%ElemNod,1) ! if(obj%ElemMat(j) == material2)then ! ! now , elem #i and #j touch interface ! ! let us record the interfacial nodes ! ! detect shared nodes ! do k=1,size(obj%ElemNod,2) ! do l=1,size(obj%ElemNod,2) ! if(obj%ElemNod(i,k) == obj%ElemNod(j,l) )then ! node_id=obj%ElemNod(i,k) ! call addlist(list,node_id) ! endif ! enddo ! enddo ! else ! cycle ! endif ! enddo ! else ! cycle ! endif ! enddo ! endif ! end function ! #################################################################### ! #################################################################### subroutine cutMesh(obj,material1, material2) class(Mesh_) ,intent(inout) :: obj integer(int32),allocatable :: list(:) integer(int32),optional,intent(in) :: material1, material2 integer(int32) :: itr, i,j,k,n ! if(present(,material1) .and. present(,material2))then ! ! rip between material 1 and material 2 ! if(material1 == material2)then ! print *, "caution! cutmesh >> material1 == material2" ! return ! endif ! ! ! detect interface ! list = obj%detectIface(material1, material2) ! ! ! add new nodes on interface ! n=size(obj%NodCoord,1) ! do i=1, size(list) ! call extendArray(mat=obj%NodCoord,extend1stColumn=.true.) ! obj%NodCoord(n+i,:)=obj%NodCoord(list(i),: ) ! enddo ! ! ! change node_id ! do i=1,size(obj%ElemNod,1) ! if(obj%elemmat(i) == material1 )then ! do j=1,size(obj%ElemNod,2) ! do k=1,size(list) ! if( obj%ElemNod(i,j) == list(k) )then ! obj%ElemNod(i,j) = n+k ! exit ! endif ! enddo ! enddo ! else ! cycle ! endif ! enddo ! ! endif end subroutine ! #################################################################### function lengthMesh(obj) result(length) class(Mesh_) ,intent(in) :: obj real(real64) :: length(3) integer(int32) :: i length(:)=0.0d0 do i=1,size(obj%NodCoord,2) length(i)=maxval(obj%NodCoord(:,i)) - minval(obj%NodCoord(:,i)) enddo end function ! #################################################################### subroutine saveMesh(obj,path,name) class(Mesh_),intent(inout)::obj character(*),intent(in) :: path character(*),optional,intent(in) :: name type(IO_) :: f integer(int32) :: i,j,dim_num,n,m if(present(name) )then call execute_command_line("mkdir -p "//trim(path)//"/"//trim(adjustl(name))) call f%open(trim(path)//"/"//trim(adjustl(name))//"/","Mesh",".prop") !call obj%gmsh(Name=trim(path)//"/"//trim(adjustl(name))//"/Mesh") !call obj%export(path=trim(path)//"/"//trim(adjustl(name))//"/",name="Mesh") !print *, trim(path)//"/"//trim(adjustl(name))//"/","Mesh",".prop" else call execute_command_line("mkdir -p "//trim(path)//"/Mesh") call f%open(trim(path)//"/Mesh/","Mesh",".prop") !call obj%gmsh(Name=trim(path)//"/Mesh/Mesh") !call obj%export(path=trim(path)//"/Mesh/",name="Mesh") !print *, trim(path)//"/Mesh/","Mesh",".prop" endif call writeArray(f%fh,obj%NodCoord) call writeArray(f%fh,obj%NodCoordInit) call writeArray(f%fh,obj%ElemNod) call writeArray(f%fh,obj%FacetElemNod) call writeArray(f%fh,obj%NextFacets) call writeArray(f%fh,obj%SurfaceLine2D) call writeArray(f%fh,obj%ElemMat) call writeArray(f%fh,obj%SubMeshNodFromTo) call writeArray(f%fh,obj%SubMeshElemFromTo) call writeArray(f%fh,obj%SubMeshSurfFromTo) call writeArray(f%fh,obj%GlobalNodID) write(f%fh,*) obj%surface write(f%fh,'(A)') trim(obj%FileName) write(f%fh,'(A)') trim(obj%ElemType) write(f%fh,'(A)') trim(obj%ErrorMsg) call f%close() end subroutine subroutine openMesh(obj,path,name) class(Mesh_),intent(inout)::obj character(*),intent(in) :: path character(*),optional,intent(in) :: name type(IO_) :: f integer(int32) :: i,j,dim_num,n,m if(present(name) )then call f%open(trim(path)//"/"//trim(adjustl(name))//"/","Mesh",".prop") else call f%open(trim(path)//"/Mesh/","Mesh",".prop") endif call openArray(f%fh,obj%NodCoord) call openArray(f%fh,obj%NodCoordInit) call openArray(f%fh,obj%ElemNod) call openArray(f%fh,obj%FacetElemNod) call openArray(f%fh,obj%NextFacets) call openArray(f%fh,obj%SurfaceLine2D) call openArray(f%fh,obj%ElemMat) call openArray(f%fh,obj%SubMeshNodFromTo) call openArray(f%fh,obj%SubMeshElemFromTo) call openArray(f%fh,obj%SubMeshSurfFromTo) call openArray(f%fh,obj%GlobalNodID) read(f%fh,*) obj%surface read(f%fh,'(A)') obj%FileName read(f%fh,'(A)') obj%ElemType read(f%fh,'(A)') obj%ErrorMsg call f%close() end subroutine subroutine removeMesh(obj,all,x_min,x_max,y_min,y_max,z_min,z_max) class(Mesh_),intent(inout)::obj logical,optional,intent(in) :: all logical :: removeall = .true. integer(int32),allocatable :: rm_node_list(:) integer(int32),allocatable :: newid_vs_oldid(:,:),elemnod(:,:) integer(int32),allocatable :: rm_elem_list(:),ElemMat(:) real(real64),allocatable :: nodcoord(:,:) integer(int32) :: i,j,k,n,totcount,oldid real(real64),optional,intent(in) :: x_min,x_max,y_min,y_max,z_min,z_max real(real64) :: xmin(3),xmax(3),x(3) logical :: tf type(IO_)::f if(present(all) )then removeall = all endif if(present(x_min) )then removeall = .false. endif if(present(x_max) )then removeall = .false. endif if(present(y_min) )then removeall = .false. endif if(present(y_max) )then removeall = .false. endif if(present(z_min) )then removeall = .false. endif if(present(z_max) )then removeall = .false. endif if(removeall .eqv. .true.)then if( allocated(obj%NodCoord ) ) deallocate(obj%NodCoord ) if( allocated(obj%NodCoordInit ) ) deallocate(obj%NodCoordInit ) if( allocated(obj%ElemNod ) ) deallocate(obj%ElemNod ) if( allocated(obj%FacetElemNod ) ) deallocate(obj%FacetElemNod ) if( allocated(obj%NextFacets ) ) deallocate(obj%NextFacets ) if( allocated(obj%SurfaceLine2D ) ) deallocate(obj%SurfaceLine2D ) if( allocated(obj%ElemMat ) ) deallocate(obj%ElemMat ) if( allocated(obj%SubMeshNodFromTo ) ) deallocate(obj%SubMeshNodFromTo ) if( allocated(obj%SubMeshElemFromTo) ) deallocate(obj%SubMeshElemFromTo) if( allocated(obj%SubMeshSurfFromTo) ) deallocate(obj%SubMeshSurfFromTo) if( allocated(obj%GlobalNodID ) ) deallocate(obj%GlobalNodID ) obj%surface=1 obj%FileName=" " obj%ElemType=" " obj%ErrorMsg=" " return endif ! remove only element if(obj%empty() .eqv. .true. )then print *, "ERROR obj%empty() .eqv. .true." stop endif ! initialization n = size(obj%NodCoord,1) allocate(rm_node_list(n) ) rm_node_list(:)=0 allocate(newid_vs_oldid(n,2) ) newid_vs_oldid(:,:)=-1 n = size(obj%ElemNod,1) allocate(rm_elem_list(n) ) rm_elem_list(:)=0 ! list-up all nodes which is to be removed. xmin(1)=input(default=-dble(1.0e+18),option=x_min) xmin(2)=input(default=-dble(1.0e+18),option=y_min) xmin(3)=input(default=-dble(1.0e+18),option=z_min) xmax(1)=input(default= dble(1.0e+18),option=x_max) xmax(2)=input(default= dble(1.0e+18),option=y_max) xmax(3)=input(default= dble(1.0e+18),option=z_max) totcount=0 do i=1, size(rm_node_list) x(:)=0 do j=1,size(obj%NodCoord,2) x(j)=obj%NodCoord(i,j) enddo tf = InOrOut(x=x,xmax=xmax,xmin=xmin,DimNum=3) if(tf .eqv. .true.)then rm_node_list(i)=1 ! to be removed newid_vs_oldid(i,1) = -1 ! new newid_vs_oldid(i,1) = i ! old id else rm_node_list(i)=0 ! not to be removed totcount=totcount+1 newid_vs_oldid(i,1) = totcount ! new newid_vs_oldid(i,1) = i ! old id endif enddo nodcoord = obj%nodcoord deallocate(obj%nodcoord) allocate(obj%nodcoord(totcount,size(nodcoord,2) ) ) totcount=0 do i=1,size(rm_node_list) if(rm_node_list(i)==1 )then cycle else totcount=totcount+1 obj%nodcoord(totcount,:) = nodcoord(i,:) endif enddo ! new id への更新 totcount=0 do i=1,obj%numElements() do j=1,obj%numNodesForEachElement() do k=1,size(rm_node_list) if( rm_node_list(obj%elemnod(i,j)) == 1 )then rm_elem_list(i)=1 exit endif enddo enddo enddo totcount=0 do i=1,size(rm_elem_list) totcount=totcount+rm_elem_list(i) enddo elemnod = obj%elemnod deallocate(obj%elemnod) allocate(obj%elemnod(size(elemnod,1)-totcount,size(elemnod,2) ) ) totcount=0 do i=1,size(rm_elem_list) if(rm_elem_list( i )==1 )then cycle else totcount=totcount+1 obj%elemnod(totcount,:) = elemnod(i,:) endif enddo do i=1,size(obj%elemnod,1) do j=1,size(obj%elemnod,2) totcount=0 do k=1,obj%elemnod(i,j)-1 totcount=totcount+rm_node_list(k) enddo obj%elemnod(i,j) = obj%elemnod(i,j) - totcount enddo enddo totcount=0 do i=1,size(rm_elem_list) totcount=totcount+rm_elem_list(i) enddo if(.not. allocated(obj%elemmat) )then call print(".not. allocated(obj%elemmat) >> ignored!") return endif elemmat = obj%elemmat deallocate(obj%elemmat) allocate(obj%elemmat(size(elemmat)- totcount) ) totcount=0 do i=1,size(rm_elem_list) if(rm_elem_list(i)==1 )then cycle else totcount=totcount+1 obj%elemmat(totcount) = elemmat(i) endif enddo end subroutine !################################################## subroutine DeallocateMesh(obj) class(Mesh_),intent(inout)::obj if( allocated(obj%NodCoord ) ) deallocate(obj%NodCoord ) if( allocated(obj%ElemNod ) ) deallocate(obj%ElemNod ) if( allocated(obj%FacetElemNod ) ) deallocate(obj%FacetElemNod ) if( allocated(obj%SurfaceLine2D ) ) deallocate(obj%SurfaceLine2D ) if( allocated(obj%ElemMat ) ) deallocate(obj%ElemMat ) if( allocated(obj%SubMeshNodFromTo ) ) deallocate(obj%SubMeshNodFromTo ) if( allocated(obj%SubMeshElemFromTo) ) deallocate(obj%SubMeshElemFromTo) if( allocated(obj%SubMeshSurfFromTo) ) deallocate(obj%SubMeshSurfFromTo) !obj%ErrorMsg="All allocatable entities are deallocated" end subroutine DeallocateMesh !################################################## !################################################## subroutine CopyMesh(obj,cobj,Minimum) class(Mesh_),intent(inout)::obj ! copied class(Mesh_),intent(in)::cobj! original logical,optional,intent(in)::Minimum !real(real64),allocatable::NodCoord(:,:) ! original >> obj, copy>> cobj call CopyArray(cobj%NodCoord, obj%NodCoord) call CopyArray(cobj%ElemNod , obj%ElemNod) call CopyArray(cobj%FacetElemNod , obj%FacetElemNod) call CopyArray(cobj%ElemMat , obj%ElemMat) if(present(Minimum) )then if(Minimum .eqv. .true.)then return endif endif call CopyArray(cobj%NodCoordInit , obj%NodCoordInit) call CopyArray(cobj%NextFacets , obj%NextFacets) call CopyArray(cobj%SurfaceLine2D , obj%SurfaceLine2D) call CopyArray(cobj%GlobalNodID , obj%GlobalNodID) call CopyArray(cobj%SubMeshNodFromTo , obj%SubMeshNodFromTo) call CopyArray(cobj%SubMeshElemFromTo , obj%SubMeshElemFromTo) call CopyArray(cobj%SubMeshSurfFromTo , obj%SubMeshSurfFromTo) obj%ElemType = cobj%ElemType obj%ErrorMsg = cobj%ErrorMsg end subroutine !################################################## subroutine InitializeMesh(obj,MaterialID,NoFacetMode,simple) class(Mesh_),intent(inout)::obj integer(int32),optional,intent(in)::MaterialID logical,optional,intent(in)::NoFacetMode logical,optional,intent(in) :: simple integer(int32) i,j,n1,n2,ne if(present(simple) )then if(simple .eqv. .true. )then return endif endif if(.not.allocated(obj%NodCoord) )then obj%ErrorMsg="Caution :: Initialize >> .not.allocated(obj%NodCoord)" print *, obj%ErrorMsg return endif n1=size(obj%NodCoord,1) if(allocated(obj%SubMeshNodFromTo ))then deallocate(obj%SubMeshNodFromTo) endif allocate(obj%SubMeshNodFromTo(1,3) ) obj%SubMeshNodFromTo(1,1)=1 obj%SubMeshNodFromTo(1,2)=1 obj%SubMeshNodFromTo(1,3)=n1 !print *, "Mesh%Init() => Domain information (Nodes) is imported" if(.not.allocated(obj%ElemNod) )then obj%ErrorMsg="Caution :: Initialize >> .not.allocated(obj%ElemNod)" print *, obj%ErrorMsg return endif n1=size(obj%ElemNod,1) ne=n1 if(allocated(obj%SubMeshElemFromTo ))then deallocate(obj%SubMeshElemFromTo) endif allocate(obj%SubMeshElemFromTo(1,3) ) obj%SubMeshElemFromTo(1,1)=1 obj%SubMeshElemFromTo(1,2)=1 obj%SubMeshElemFromTo(1,3)=n1 !print *, "Mesh%Init() => Domain information (Elements) is imported" if( allocated(obj%ElemMat) .and. size(obj%ElemMat)/=ne )then deallocate(obj%ElemMat) endif if(.not.allocated(obj%ElemMat) )then obj%ErrorMsg="Caution :: Initialize >> .not.allocated(obj%ElemMat)" print *, obj%ErrorMsg allocate(obj%ElemMat(ne) ) if(present(MaterialID) )then obj%ElemMat=MaterialID else obj%ElemMat=1 endif endif if(present(NoFacetMode) )then if(NoFacetMode .eqv. .true. )then return endif endif call GetFacetElement(obj) call GetSurface2D(obj) if(.not.allocated(obj%SurfaceLine2D) )then obj%ErrorMsg="Caution :: Initialize >> .not.allocated(obj%ESurfaceLine2D)" print *, obj%ErrorMsg return endif n1=size(obj%SurfaceLine2D,1) if(allocated(obj%SubMeshSurfFromTo ))then deallocate(obj%SubMeshSurfFromTo) endif allocate(obj%SubMeshSurfFromTo(1,3) ) obj%SubMeshSurfFromTo(1,1)=1 obj%SubMeshSurfFromTo(1,2)=1 obj%SubMeshSurfFromTo(1,3)=n1 end subroutine InitializeMesh !################################################## !################################################## subroutine ImportElemNod(obj,elem_nod) class(Mesh_),intent(inout)::obj integer(int32),intent(in)::elem_nod(:,:) if(allocated(obj%ElemNod) )then deallocate(obj%ElemNod) endif allocate(obj%ElemNod(size(elem_nod,1),size(elem_nod,2) ) ) obj%ElemNod(:,:)=elem_nod(:,:) if(allocated(obj%SubMeshElemFromTo))then deallocate(obj%SubMeshElemFromTo) endif allocate(obj%SubMeshElemFromTo(1,3 )) obj%SubMeshElemFromTo(1,1)=1 obj%SubMeshElemFromTo(1,2)=1 obj%SubMeshElemFromTo(1,3)=size(elem_nod,1) end subroutine ImportElemNod !################################################## !################################################## subroutine ImportNodCoord(obj,nod_coord) class(Mesh_),intent(inout)::obj real(real64),intent(in)::nod_coord(:,:) if(allocated(obj%NodCoord) )then deallocate(obj%NodCoord) endif allocate(obj%NodCoord(size(nod_coord,1),size(nod_coord,2) ) ) obj%NodCoord(:,:)=nod_coord(:,:) if(allocated(obj%SubMeshNodFromTo))then deallocate(obj%SubMeshNodFromTo) endif allocate(obj%SubMeshNodFromTo(1,3 )) obj%SubMeshNodFromTo(1,1)=1 obj%SubMeshNodFromTo(1,2)=1 obj%SubMeshNodFromTo(1,3)=size(nod_coord,1) end subroutine ImportNodCoord !################################################## !################################################## subroutine ImportElemMat(obj,elem_mat) class(Mesh_),intent(inout)::obj integer(int32),intent(in)::elem_mat(:) if(allocated(obj%ElemMat) )then deallocate(obj%ElemMat) endif allocate(obj%ElemMat(size(elem_mat,1) ) ) obj%ElemMat(:)=elem_mat(:) end subroutine ImportElemMat !################################################## subroutine resizeMeshobj(obj,x_rate,y_rate,z_rate,x_len,y_len,z_len) class(Mesh_),intent(inout) :: obj real(real64),optional,intent(in) :: x_rate,y_rate,z_rate,x_len,y_len,z_len real(real64) :: rate, len ! 2021/09/24 >> Tried to paralelize this by OpenMP, but failed. ! do not use !$OMP parallel do if(.not.allocated(obj%NodCoord) )then print *, "ERROR :: MeshClass resizeMeshObj >> no Nodal coordintates are not found." return endif if(present(x_rate) )then obj%NodCoord(:,1)=x_rate*obj%NodCoord(:,1) endif if(present(y_rate) )then obj%NodCoord(:,2)=y_rate*obj%NodCoord(:,2) endif if(present(z_rate) )then obj%NodCoord(:,3)=z_rate*obj%NodCoord(:,3) endif if(present(x_len) )then len = maxval(obj%NodCoord(:,1) ) - minval(obj%NodCoord(:,1) ) rate = x_len/len obj%NodCoord(:,1)=rate*obj%NodCoord(:,1) endif if(present(y_len) )then len = maxval(obj%NodCoord(:,2) ) - minval(obj%NodCoord(:,2) ) rate = y_len/len obj%NodCoord(:,2)=rate*obj%NodCoord(:,2) endif if(present(z_len) )then len = maxval(obj%NodCoord(:,3) ) - minval(obj%NodCoord(:,3) ) rate = z_len/len obj%NodCoord(:,3)=rate*obj%NodCoord(:,3) endif end subroutine !################################################## subroutine importMeshObj(obj,FileName,extention,ElemType,Mesh) class(Mesh_),intent(inout)::obj type(Mesh_),optional,intent(in) :: Mesh type(IO_) :: f character(*),optional,intent(in)::FileName,extention,ElemType character(200) :: MeshVersionFormatted,Dim,Vertices,Edges,Triangles character(200) :: Tetrahedra,ex,ch real(real64) :: null_num_real integer(int32) :: dim_num,node_num,elem_num,elemnod_num,i,j integer(int32) :: edge_num,null_num_int,num_of_triangles integer(int32) :: num_of_Tetrahedra call obj%delete() if(present(Mesh) )then call obj%copy(Mesh) return endif if(present(FileName) )then ex=getext(FileName) if( trim(ex)=="stl")then return endif endif if(trim(extention) == ".mesh")then open(17,file=FileName) read(17,*) MeshVersionFormatted,null_num_int read(17,*) Dim read(17,*) dim_num read(17,*) Vertices read(17,*) node_num allocate(obj%NodCoord(node_num,dim_num) ) do i=1,node_num read(17,*) obj%NodCoord(i,1:dim_num) enddo !print *, "MeshClass >> importMeshobj >> imported nod_coord" read(17,*) Edges read(17,*) edge_num do i=1,edge_num read(17,*) null_num_int enddo read(17,*) Triangles read(17,*) num_of_triangles if(trim(adjustl(ElemType))=="Triangles" )then allocate(obj%ElemNod(num_of_triangles,3) ) print *, "MeshClass >> importMeshobj >> Reading ", trim(Triangles) do i=1,num_of_triangles read(17,*) obj%ElemNod(i,1:3) enddo else do i=1,num_of_triangles read(17,*) null_num_int enddo endif read(17,*) Tetrahedra read(17,*) num_of_Tetrahedra if(trim(adjustl(ElemType))=="Tetrahedra" )then allocate(obj%ElemNod(num_of_Tetrahedra,4) ) print *, "MeshClass >> importMeshobj >> Reading ", trim(Tetrahedra) do i=1,num_of_Tetrahedra read(17,*) obj%ElemNod(i,1:4) enddo else do i=1,num_of_Tetrahedra read(17,*) null_num_int enddo endif close(17) else print *, "Extention",extention print *, "MeshClass >> importMeshObj >> extention is not supprted now." endif print *, "MeshClass >> importMeshobj >> Mesh is successfully imported." end subroutine !################################################## !################################################## subroutine exportMeshObj(obj,restart,path,stl,scalar,vector,tensor,name) class(Mesh_),intent(inout)::obj real(real64),optional,intent(in) :: scalar(:),vector(:,:),tensor(:,:,:) logical,optional,intent(in) :: restart,stl character(*),optional,intent(in) :: path character(*),optional,intent(in) :: name character(200) :: fieldname type(IO_) :: f integer(int32) :: i,j,dim_num real(real64) :: x1(3),x2(3),x3(3),x,y,z if(present(name) )then fieldname=trim(adjustl(name)) else fieldname="Mesh" endif if(size(obj%ElemNod,2)==2 )then call f%open(trim(fieldname)//".msh" ) call f%write("$MeshFormat") call f%write("2.2 0 8") call f%write("$EndMeshFormat\n") call f%write('$Nodes') write(f%fh,*) size(obj%NodCoord,1) do i=1,size(obj%NodCoord,1) write(f%fh,*) i,obj%NodCoord(i,:) enddo call f%write('$EndNodes') call f%write('$Elements') write(f%fh,*) size(obj%ElemNod,1) do i=1,size(obj%ElemNod,1) write(f%fh,*) i,"3 2 2 1",obj%ElemNod(i,:),obj%ElemNod(i,:) enddo call f%write('$EndElements') call f%close() return endif call execute_command_line("mkdir -p "//trim(path)//"/Mesh") if(obj%empty() .eqv. .true.)then return endif if(present(restart) )then call execute_command_line("mkdir -p "//trim(path)//"/Mesh") call f%open(trim(path)//"/Mesh/",trim(fieldname),".prop") call writeArray(f%fh,obj%NodCoord) call writeArray(f%fh,obj%NodCoordInit) call writeArray(f%fh,obj%ElemNod) call writeArray(f%fh,obj%FacetElemNod) call writeArray(f%fh,obj%NextFacets) call writeArray(f%fh,obj%SurfaceLine2D) call writeArray(f%fh,obj%ElemMat) call writeArray(f%fh,obj%SubMeshNodFromTo) call writeArray(f%fh,obj%SubMeshElemFromTo) call writeArray(f%fh,obj%SubMeshSurfFromTo) call writeArray(f%fh,obj%GlobalNodID) write(f%fh,*) obj%surface write(f%fh,'(A)') trim(obj%FileName) write(f%fh,'(A)') trim(obj%ElemType) write(f%fh,'(A)') trim(obj%ErrorMsg) call f%close() return endif ! export mesh call f%open(trim(path)//"/Mesh/","Mesh",".vtk") write(f%fh,'(A)' ) "# vtk DataFile Version 2.0" write(f%fh,'(A)' ) "Cube example" write(f%fh,'(A)' ) "ASCII" write(f%fh,'(A)' ) "DATASET POLYDATA" write(f%fh,'(A)' ,advance="no") "POINTS " write(f%fh,'(i10)' ,advance="no")size(obj%NodCoord,1) write(f%fh,'(A)')" float" if( size(obj%NodCoord,2)==3 )then do i=1,size(obj%NodCoord,1) do j=1,size(obj%NodCoord,2) if(j==size(obj%NodCoord,2))then write(f%fh,'(f20.8)' ) obj%NodCoord(i,j) else write(f%fh,'(f20.8)', advance="no" ) obj%NodCoord(i,j) write(f%fh,'(A)', advance="no" ) " " endif enddo enddo elseif( size(obj%NodCoord,2)==2 )then do i=1,size(obj%NodCoord,1) do j=1,size(obj%NodCoord,2) if(j==size(obj%NodCoord,2))then write(f%fh,'(f20.8)', advance="no" ) obj%NodCoord(i,j) write(f%fh,'(A)', advance="no" ) " " endif write(f%fh,'(f20.8)' ) 0.0d0 enddo enddo elseif( size(obj%NodCoord,2)==1 )then do i=1,size(obj%NodCoord,1) do j=1,size(obj%NodCoord,2) if(j==size(obj%NodCoord,2))then write(f%fh,'(f20.8)', advance="no" ) obj%NodCoord(i,j) write(f%fh,'(A)', advance="no" ) " " endif write(f%fh,'(f20.8)' ) 0.0d0,0.0d0 enddo enddo else print *, "Mesh % vtk >> invalid space dimension",size(obj%NodCoord,2) stop endif write(f%fh,'(A)',advance="no")" POLYGONS " write(f%fh,'(i10)',advance="no") 6*size(obj%ElemNod,1) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)') size(obj%ElemNod,1)*5*6 write(f%fh,'(A)') "CELL_DATA 6" call f%close() ! export mesh with scalar if(present(scalar) )then call f%open(trim(path)//"/Mesh/",trim(fieldname),".vtk") write(f%fh,'(A)' ) "# vtk DataFile Version 2.0" write(f%fh,'(A)' ) "Cube example" write(f%fh,'(A)' ) "ASCII" write(f%fh,'(A)' ) "DATASET POLYDATA" write(f%fh,'(A)' ,advance="no") "POINTS " write(f%fh,'(i10)' ,advance="no")size(obj%NodCoord,1) write(f%fh,'(A)')" float" do i=1,size(obj%NodCoord,1) do j=1,size(obj%NodCoord,2) if(j==size(obj%NodCoord,2))then write(f%fh,'(f20.8)' ) obj%NodCoord(i,j) else write(f%fh,'(f20.8)', advance="no" ) obj%NodCoord(i,j) write(f%fh,'(A)', advance="no" ) " " endif enddo enddo write(f%fh,'(A)',advance="no")" POLYGONS " write(f%fh,'(i10)',advance="no") 6*size(obj%ElemNod,1) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)') size(obj%ElemNod,1)*5*6 do i=1,size(obj%ElemNod,1) write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,1)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,2)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,3)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,4)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,5)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,6)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,7)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,8)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,1)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,2)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,6)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,5)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,3)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,4)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,8)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,7)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,1)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,5)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,8)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,4)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,2)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,3)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,7)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,6)) write(f%fh,'(A)') " " enddo call execute_command_line("mkdir -p "//trim(path)//"/Mesh") call f%open(trim(path)//"/Mesh/",trim(fieldname),".ply") write(f%fh,'(A)')"ply" write(f%fh,'(A)')"format ascii 1.0" write(f%fh,'(A)',advance="no")"element vertex " write(f%fh,'(i10)') size(obj%NodCoord,1) write(f%fh,'(A)')"property float32 x" write(f%fh,'(A)')"property float32 y" write(f%fh,'(A)')"property float32 z" write(f%fh,'(A)')"property uchar red" write(f%fh,'(A)')"property uchar green" write(f%fh,'(A)')"property uchar blue" write(f%fh,'(A)',advance="no")"element face " write(f%fh,'(i10)') size(obj%ElemNod,1)*6 write(f%fh,'(A)')"property list uint8 int32 vertex_indices" write(f%fh,'(A)') "end_header" do i=1,size(obj%NodCoord,1) do j=1,size(obj%NodCoord,2) if(j==size(obj%NodCoord,2))then write(f%fh,'(f20.8)', advance="no" ) obj%NodCoord(i,j) write(f%fh,'(A)', advance="no" ) " " else write(f%fh,'(f20.8)', advance="no" ) obj%NodCoord(i,j) write(f%fh,'(A)', advance="no" ) " " endif enddo write(f%fh,'(A)', advance="no" ) " " write(f%fh,'(i3)',advance="no") int(obj%NodCoord(i,1)*255.0d0/maxval(obj%NodCoord(:,1) )) write(f%fh,'(A)', advance="no" ) " " write(f%fh,'(i3)',advance="no") int(obj%NodCoord(i,2)*255.0d0/maxval(obj%NodCoord(:,2) )) write(f%fh,'(A)', advance="no" ) " " write(f%fh,'(i3)') int(obj%NodCoord(i,3)*255.0d0/maxval(obj%NodCoord(:,3) )) enddo do i=1,size(obj%ElemNod,1) write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,1)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,2)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,3)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,4)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,5)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,6)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,7)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,8)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,1)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,2)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,6)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,5)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,3)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,4)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,8)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,7)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,1)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,5)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,8)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,4)) write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,2)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,3)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,7)) write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") scalar(obj%ElemNod(i,6)) write(f%fh,'(A)') " " enddo call f%close() endif write(f%fh,'(A)') "CELL_DATA 6" call f%close() call execute_command_line("mkdir -p "//trim(path)//"/Mesh") call f%open(trim(path)//"/Mesh/","Mesh",".ply") write(f%fh,'(A)')"ply" write(f%fh,'(A)')"format ascii 1.0" write(f%fh,'(A)',advance="no")"element vertex " write(f%fh,'(i10)') size(obj%NodCoord,1) write(f%fh,'(A)')"property float32 x" write(f%fh,'(A)')"property float32 y" write(f%fh,'(A)')"property float32 z" write(f%fh,'(A)')"property uchar red" write(f%fh,'(A)')"property uchar green" write(f%fh,'(A)')"property uchar blue" write(f%fh,'(A)',advance="no")"element face " write(f%fh,'(i10)') size(obj%ElemNod,1)*6 write(f%fh,'(A)')"property list uint8 int32 vertex_indices" write(f%fh,'(A)') "end_header" do i=1,size(obj%NodCoord,1) do j=1,size(obj%NodCoord,2) if(j==size(obj%NodCoord,2))then write(f%fh,'(f20.8)', advance="no" ) obj%NodCoord(i,j) write(f%fh,'(A)', advance="no" ) " " else write(f%fh,'(f20.8)', advance="no" ) obj%NodCoord(i,j) write(f%fh,'(A)', advance="no" ) " " endif enddo write(f%fh,'(A)', advance="no" ) " " write(f%fh,'(i3)',advance="no") int(obj%NodCoord(i,1)*255.0d0/maxval(obj%NodCoord(:,1) )) write(f%fh,'(A)', advance="no" ) " " write(f%fh,'(i3)',advance="no") int(obj%NodCoord(i,2)*255.0d0/maxval(obj%NodCoord(:,2) )) write(f%fh,'(A)', advance="no" ) " " write(f%fh,'(i3)') int(obj%NodCoord(i,3)*255.0d0/maxval(obj%NodCoord(:,3) )) enddo do i=1,size(obj%ElemNod,1) write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,1)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,2)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,3)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,4)-1 write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,5)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,6)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,7)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,8)-1 write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,1)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,2)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,6)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,5)-1 write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,3)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,4)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,8)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,7)-1 write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,1)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,5)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,8)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,4)-1 write(f%fh,'(A)') " " write(f%fh,'(A)',advance="no") "4 " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,2)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,3)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,7)-1 write(f%fh,'(A)',advance="no") " " write(f%fh,'(i10)',advance="no") obj%ElemNod(i,6)-1 write(f%fh,'(A)') " " enddo call f%close() if(present(stl) )then call execute_command_line("mkdir -p "//trim(path)//"/Mesh") call f%open(trim(path)//"/Mesh/","Mesh",".stl") call obj%GetSurface() dim_num = size(obj%NodCoord,2) if(dim_num/=3)then print *, "Sorry, Export stl is supported only for 3-D mesh" close(f%fh) return endif write(f%fh,'(A)') "solid "//trim(path)//"/Mesh" print *, "Number of facet is",size(obj%FacetElemNod,1) do i=1,size(obj%FacetElemNod,1) if(size(obj%FacetElemNod,2)==4 )then ! rectangular ! describe two triangular x1(:)=obj%NodCoord(obj%FacetElemNod(i,1),: ) x2(:)=obj%NodCoord(obj%FacetElemNod(i,2),: ) x3(:)=obj%NodCoord(obj%FacetElemNod(i,3),: ) write(f%fh,'(A)') "facet normal 0.0 0.0 1.0" write(f%fh,'(A)') "outer loop" write(f%fh,*) "vertex ",real(x1(1) ),real(x1(2) ),real(x1(3) ) write(f%fh,*) "vertex ",real(x2(1) ),real(x2(2) ),real(x2(3) ) write(f%fh,*) "vertex ",real(x3(1) ),real(x3(2) ),real(x3(3) ) write(f%fh,'(A)') "endloop" write(f%fh,'(A)') "endfacet" x1(:)=obj%NodCoord(obj%FacetElemNod(i,1),: ) x2(:)=obj%NodCoord(obj%FacetElemNod(i,3),: ) x3(:)=obj%NodCoord(obj%FacetElemNod(i,4),: ) write(f%fh,'(A)') "facet normal 0.0 0.0 1.0" write(f%fh,'(A)') "outer loop" write(f%fh,*) "vertex ",real(x1(1) ),real(x1(2) ),real(x1(3) ) write(f%fh,*) "vertex ",real(x2(1) ),real(x2(2) ),real(x2(3) ) write(f%fh,*) "vertex ",real(x3(1) ),real(x3(2) ),real(x3(3) ) write(f%fh,'(A)') "endloop" write(f%fh,'(A)') "endfacet" elseif(size(obj%FacetElemNod,2)==3 )then ! rectangular ! describe two triangular x1(:)=obj%NodCoord(obj%FacetElemNod(i,1),: ) x2(:)=obj%NodCoord(obj%FacetElemNod(i,2),: ) x3(:)=obj%NodCoord(obj%FacetElemNod(i,3),: ) write(f%fh,'(A)') "facet normal 0.0 0.0 1.0" write(f%fh,'(A)') "outer loop" write(f%fh,*) "vertex ",real(x1(1) ),real(x1(2) ),real(x1(3) ) write(f%fh,*) "vertex ",real(x2(1) ),real(x2(2) ),real(x2(3) ) write(f%fh,*) "vertex ",real(x3(1) ),real(x3(2) ),real(x3(3) ) write(f%fh,'(A)') "endloop" write(f%fh,'(A)') "endfacet" else ! other print *, "Sorry, Export stl is supported only for rectangular mesh" return close(f%fh) endif enddo write(f%fh,'(A)') "endsolid "//trim(path)//"/Mesh" call f%close() endif end subroutine !################################################## recursive subroutine GetFacetElementByDivideConquor(obj) class(Mesh_),intent(inout)::obj type(Mesh_) :: smallObj print *, "ERROR :: not implemented yet >> GetFacetElementByDivideConquor" stop end subroutine !################################################## function getFacetNodeIDMesh(obj,ElementID) result(ret) class(Mesh_),intent(in) :: obj integer(int32),intent(in) :: ElementID integer(int32),allocatable :: ret(:,:),order(:,:) integeR(int32) :: i,j,n,elemid,k,dimnum,elemnodnum ! get element info dimnum = size(obj%nodcoord,2) elemnodnum = size(obj%elemnod,2) if(dimnum==3 .and. elemnodnum==4)then ! Tetra mesh allocate(ret(4,3) ) allocate(order(4,3) ) order(1,:) = [3, 2, 1] order(2,:) = [1, 2, 4] order(3,:) = [2, 3, 4] order(4,:) = [3, 1, 4] do k=1,4 ret(k,1) = obj%elemnod( ElementID, order(k,1) ) ret(k,2) = obj%elemnod( ElementID, order(k,2) ) ret(k,3) = obj%elemnod( ElementID, order(k,3) ) enddo return elseif(dimnum==3 .and. elemnodnum==8)then ! Tetra mesh allocate(ret(6,4) ) allocate(order(6,4) ) order(1,:) = [ 4, 3, 2, 1] order(2,:) = [ 1, 2, 6, 5] order(3,:) = [ 2, 3, 7, 6] order(4,:) = [ 3, 4, 8, 7] order(5,:) = [ 4, 1, 5, 8] order(6,:) = [ 5, 6, 7, 8] do k = 1,6 ret(k,1) = obj%elemnod( ElementID, order(k,1) ) ret(k,2) = obj%elemnod( ElementID, order(k,2) ) ret(k,3) = obj%elemnod( ElementID, order(k,3) ) ret(k,4) = obj%elemnod( ElementID, order(k,4) ) enddo return endif end function !################################################## !################################################## subroutine GetFacetElement(obj) class(Mesh_),intent(inout)::obj logical,parameter :: fast=.true. integer(int32) :: i,j,k,l,n,m integer(int32) :: NumOfElem,NumOfDim,NumNodePerElem integer(int32) :: id_1,id_2,id_3,id_4,num_face,div_num integer(int32) :: id_r1,id_r2,id_r3,id_r4,diff,elementID_I,elementID_J integer(int32),allocatable::id(:),idr(:) integer(int32),allocatable::buffer(:,:),ElementGroup(:,:) real(real64):: dx(3),x(3) logical,allocatable :: overlap(:) ! From 1 -> 2 -> -> 3 -> 4, outer normal vector is obtained if(allocated(obj%FacetElemNod) )then deallocate(obj%FacetElemNod) endif NumOfElem = size(obj%ElemNod,1) NumOfDim = size(obj%NodCoord,2) NumNodePerElem = size(obj%ElemNod,2) If(NumOfDim < 2 .or. NumOfDim > 4 ) then obj%ErrorMsg = "ERROR::GetFaceElement.f90 >> NumOfDim = 2 or 3" stop endif if(NumOfDim==2)then ! initialization only for linear_triangle&rectangular :: if(allocated(obj%FacetElemNod) ) then deallocate(obj%FacetElemNod) endif allocate(obj%FacetElemNod(NumOfElem*NumNodePerElem,2) ) obj%FacetElemNod(:,:) = 0 ! trial mode do i=1,NumOfElem do j=1,NumNodePerElem id_1=mod(j+NumNodePerElem ,NumNodePerElem) id_2=mod(j+NumNodePerElem+1 ,NumNodePerElem) if(id_1==0)then id_1=NumNodePerElem endif if(id_2==0)then id_2=NumNodePerElem endif obj%FacetElemNod( NumNodePerElem*(i-1)+j,1) = obj%ElemNod(i,id_1) obj%FacetElemNod( NumNodePerElem*(i-1)+j,2) = obj%ElemNod(i,id_2) enddo enddo ! cut off overlapped facets do i=1,size(obj%FacetElemNod,1)-1 if(obj%FacetElemNod(i,1)==-1 )then cycle endif do j=i+1,size(obj%FacetElemNod,1) if(obj%FacetElemNod(i,1) == obj%FacetElemNod(j,2) .and. & obj%FacetElemNod(i,2) == obj%FacetElemNod(j,1) )then obj%FacetElemNod(i,:)=-1 obj%FacetElemNod(j,:)=-1 exit endif if(obj%FacetElemNod(i,1)==-1 )then exit endif enddo enddo allocate(buffer(size(obj%FacetElemNod,1),size(obj%FacetElemNod,2) )) buffer(:,:)=0 j=0 k=0 do i=1,size(obj%FacetElemNod,1) if(obj%FacetElemNod(i,1)==-1)then cycle else k=k+1 buffer(k,:)=obj%FacetElemNod(i,:) endif enddo deallocate(obj%FacetElemNod) allocate(obj%FacetElemNod(k,2) ) do i=1,size(obj%FacetElemNod,1) obj%FacetElemNod(i,:)=buffer(i,:) enddo elseif(NumOfDim==3 )then ! New algorithm if(fast)then allocate(ElementGroup(size(obj%elemnod,1),3) ) !div_num = size(obj%elemnod,1)/200 + 1 div_num=10 dx(1) = (maxval(obj%nodcoord(:,1) ) - minval(obj%nodcoord(:,1) ))/dble(div_num) div_num=10 dx(2) = (maxval(obj%nodcoord(:,2) ) - minval(obj%nodcoord(:,2) ))/dble(div_num) div_num=10 dx(3) = (maxval(obj%nodcoord(:,3) ) - minval(obj%nodcoord(:,3) ))/dble(div_num) do i=1, size(obj%elemnod,1) x(1) = obj%nodcoord(obj%elemnod(i,1) ,1 ) x(2) = obj%nodcoord(obj%elemnod(i,1) ,2 ) x(3) = obj%nodcoord(obj%elemnod(i,1) ,3 ) ElementGroup(i,1) = int((x(1) -minval(obj%nodcoord(:,1) ))/dx(1)) ElementGroup(i,2) = int((x(2) -minval(obj%nodcoord(:,2) ))/dx(2)) ElementGroup(i,3) = int((x(3) -minval(obj%nodcoord(:,3) ))/dx(3)) enddo n = size(obj%ElemNod,1) NumNodePerElem = size(obj%ElemNod,2) if(NumNodePerElem==4)then num_face = 4 allocate(obj%FacetElemNod(NumOfElem*4,3),id(3),idr(3) ) do i=1,size(obj%ElemNod,1) obj%FacetElemNod( (i-1)*4+1 ,1) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*4+1 ,2) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*4+1 ,3) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*4+2 ,1) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*4+2 ,2) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*4+2 ,3) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*4+3 ,1) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*4+3 ,2) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*4+3 ,3) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*4+4 ,1) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*4+4 ,2) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*4+4 ,3) = obj%ElemNod(i,4) enddo elseif(NumNodePerElem==8)then num_face = 6 allocate(obj%FacetElemNod(NumOfElem*6,4),id(4),idr(4) ) do i=1,size(obj%ElemNod,1) obj%FacetElemNod( (i-1)*6+1 ,1) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*6+1 ,2) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*6+1 ,3) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*6+1 ,4) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*6+2 ,1) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*6+2 ,2) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*6+2 ,3) = obj%ElemNod(i,6) obj%FacetElemNod( (i-1)*6+2 ,4) = obj%ElemNod(i,5) obj%FacetElemNod( (i-1)*6+3 ,1) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*6+3 ,2) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*6+3 ,3) = obj%ElemNod(i,7) obj%FacetElemNod( (i-1)*6+3 ,4) = obj%ElemNod(i,6) obj%FacetElemNod( (i-1)*6+4 ,1) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*6+4 ,2) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*6+4 ,3) = obj%ElemNod(i,8) obj%FacetElemNod( (i-1)*6+4 ,4) = obj%ElemNod(i,7) obj%FacetElemNod( (i-1)*6+5 ,1) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*6+5 ,2) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*6+5 ,3) = obj%ElemNod(i,5) obj%FacetElemNod( (i-1)*6+5 ,4) = obj%ElemNod(i,8) obj%FacetElemNod( (i-1)*6+6 ,1) = obj%ElemNod(i,5) obj%FacetElemNod( (i-1)*6+6 ,2) = obj%ElemNod(i,6) obj%FacetElemNod( (i-1)*6+6 ,3) = obj%ElemNod(i,7) obj%FacetElemNod( (i-1)*6+6 ,4) = obj%ElemNod(i,8) enddo else stop "ERROR :: GetFacetElement :: only for Hexahedral/tetrahedron ##" endif allocate(overlap(size(obj%FacetElemNod,1) ) ) overlap(:) = .false. id = int( zeros(size(obj%FacetElemNod,2) ) ) idr= int( zeros(size(obj%FacetElemNod,2) ) ) ! Most time-consuming part elementID_I=0 do i=1,size(overlap)-1 if(mod(i-1,num_face)==0 )then elementID_I = elementID_I + 1 endif if(overlap(i) ) cycle ! 全然違うやつをすばやく弾きたい elementID_J = elementID_I do j=i+1,size(overlap) if(mod(j-1,num_face)==0 )then elementID_J = elementID_J + 1 endif if( abs(ElementGroup(elementID_I,1)-ElementGroup(elementID_J,1))>=2 ) cycle if( abs(ElementGroup(elementID_I,2)-ElementGroup(elementID_J,2))>=2 ) cycle if( abs(ElementGroup(elementID_I,3)-ElementGroup(elementID_J,3))>=2 ) cycle id = obj%FacetElemNod(i,:) idr= obj%FacetElemNod(j,:) if( sameAsGroup(id,idr) )then overlap(i) = .true. overlap(j) = .true. exit endif enddo enddo ! to here. j = 0 do i=1,size(overlap) if(.not.overlap(i) )then j = j+1 endif enddo buffer = obj%FacetElemNod obj%FacetElemNod = int(zeros( j,size(buffer,2) ) ) j=0 do i=1,size(overlap) if(.not.overlap(i) )then j = j+1 obj%FacetElemNod(j,:) = buffer(i,:) endif enddo return endif ! initialization only for Hexahedral/tetrahedron:: if(allocated(obj%FacetElemNod) ) then deallocate(obj%FacetElemNod) endif NumOfElem=size(obj%ElemNod,1) if(NumNodePerElem==4)then allocate(obj%FacetElemNod(NumOfElem*4,3),id(3),idr(3) ) elseif(NumNodePerElem==8)then allocate(obj%FacetElemNod(NumOfElem*6,4),id(4),idr(4) ) else stop "ERROR :: GetFacetElement :: only for Hexahedral/tetrahedron #" endif obj%FacetElemNod(:,:) = 0 ! trial mode do i=1,size(obj%ElemNod,1) if(NumNodePerElem==4)then obj%FacetElemNod( (i-1)*4+1 ,1) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*4+1 ,2) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*4+1 ,3) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*4+2 ,1) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*4+2 ,2) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*4+2 ,3) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*4+3 ,1) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*4+3 ,2) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*4+3 ,3) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*4+4 ,1) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*4+4 ,2) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*4+4 ,3) = obj%ElemNod(i,4) elseif(NumNodePerElem==8)then obj%FacetElemNod( (i-1)*6+1 ,1) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*6+1 ,2) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*6+1 ,3) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*6+1 ,4) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*6+2 ,1) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*6+2 ,2) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*6+2 ,3) = obj%ElemNod(i,6) obj%FacetElemNod( (i-1)*6+2 ,4) = obj%ElemNod(i,5) obj%FacetElemNod( (i-1)*6+3 ,1) = obj%ElemNod(i,2) obj%FacetElemNod( (i-1)*6+3 ,2) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*6+3 ,3) = obj%ElemNod(i,7) obj%FacetElemNod( (i-1)*6+3 ,4) = obj%ElemNod(i,6) obj%FacetElemNod( (i-1)*6+4 ,1) = obj%ElemNod(i,3) obj%FacetElemNod( (i-1)*6+4 ,2) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*6+4 ,3) = obj%ElemNod(i,8) obj%FacetElemNod( (i-1)*6+4 ,4) = obj%ElemNod(i,7) obj%FacetElemNod( (i-1)*6+5 ,1) = obj%ElemNod(i,4) obj%FacetElemNod( (i-1)*6+5 ,2) = obj%ElemNod(i,1) obj%FacetElemNod( (i-1)*6+5 ,3) = obj%ElemNod(i,5) obj%FacetElemNod( (i-1)*6+5 ,4) = obj%ElemNod(i,8) obj%FacetElemNod( (i-1)*6+6 ,1) = obj%ElemNod(i,5) obj%FacetElemNod( (i-1)*6+6 ,2) = obj%ElemNod(i,6) obj%FacetElemNod( (i-1)*6+6 ,3) = obj%ElemNod(i,7) obj%FacetElemNod( (i-1)*6+6 ,4) = obj%ElemNod(i,8) else stop "ERROR :: GetFacetElement :: only for Hexahedral/tetrahedron ##" endif enddo ! cut off overlapped facets do i=1,size(obj%FacetElemNod,1)-1 if(obj%FacetElemNod(i,1)==-1 )then cycle endif do j=i+1,size(obj%FacetElemNod,1) if(size(obj%FacetElemNod,2)==3 .or. size(obj%FacetElemNod,2)==4 )then id(:)=obj%FacetElemNod(i,:) idr(:)=obj%FacetElemNod(j,:) call heapsort(size(id) ,id) call heapsort(size(idr) ,idr) id_1=dot_product(id-idr,id-idr) if(id_1==0)then obj%FacetElemNod(i,:)=-1 obj%FacetElemNod(j,:)=-1 endif else stop "ERROR :: GetFacetElement :: only for Hexahedral/tetrahedron ##" endif enddo enddo allocate(buffer(size(obj%FacetElemNod,1),size(obj%FacetElemNod,2) )) buffer(:,:)=0 j=0 k=0 do i=1,size(obj%FacetElemNod,1) if(obj%FacetElemNod(i,1)==-1)then cycle else k=k+1 buffer(k,:)=obj%FacetElemNod(i,:) endif enddo deallocate(obj%FacetElemNod) allocate(obj%FacetElemNod(k, size(buffer,2) ) ) do i=1,size(obj%FacetElemNod,1) obj%FacetElemNod(i,:)=buffer(i,:) enddo endif end subroutine GetFacetElement !################################################## !################################################## subroutine GetSurface2D(obj) class(Mesh_),intent(inout)::obj integer(int32) :: i,j,k,n integer(int32) :: NumOfElem,NumOfDim,NumNodePerElem integer(int32) :: id_1,id_2 integer(int32),allocatable::buffer(:,:) NumOfElem = size(obj%ElemNod,1) NumOfDim = size(obj%NodCoord,2) NumNodePerElem = size(obj%ElemNod,2) If(NumOfDim /= 2) then obj%ErrorMsg = "ERROR::GetFaceElement.f90 >> NumOfDim /= 2" stop endif call GetFacetElement(obj) !initialize allocate(buffer(size(obj%FacetElemNod,1),size(obj%FacetElemNod,2)) ) buffer(1,:)=obj%FacetElemNod(1,:) !buffer is arranged by clock-wize do i=1,size(obj%FacetElemNod,1)-1 id_2=buffer(i,2) do j=1,size(obj%FacetElemNod,1) if(id_2==obj%FacetElemNod(j,1) )then buffer(i+1,:)=obj%FacetElemNod(j,:) else cycle endif enddo enddo if(allocated(obj%SurfaceLine2D) ) then deallocate(obj%SurfaceLine2D) endif allocate(obj%SurfaceLine2D(size(buffer,1) ) ) do i=1,size(buffer,1) obj%SurfaceLine2D(size(buffer,1)-i+1)=buffer(i,1) enddo if(allocated(obj%SubMeshSurfFromTo))then deallocate(obj%SubMeshSurfFromTo) endif allocate(obj%SubMeshSurfFromTo(1,3 )) obj%SubMeshSurfFromTo(1,1)=1 obj%SubMeshSurfFromTo(1,2)=1 obj%SubMeshSurfFromTo(1,3)=size(obj%SurfaceLine2D,1) end subroutine GetSurface2D !################################################## !################################################## subroutine GetSurface(obj) class(Mesh_),intent(inout)::obj integer(int32) :: i,j,k,n integer(int32) :: NumOfElem,NumOfDim,NumNodePerElem integer(int32) :: id_1,id_2 integer(int32),allocatable::buffer(:,:) if(allocated(obj%FacetElemNod) ) then deallocate(obj%FacetElemNod) endif if(allocated(obj%NextFacets) ) then deallocate(obj%NextFacets) endif if(allocated(obj%SurfaceLine2D) ) then deallocate(obj%SurfaceLine2D) endif ! if(allocated(obj%SubMeshNodFromTo) ) then ! deallocate(obj%SubMeshNodFromTo) ! endif ! if(allocated(obj%SubMeshElemFromTo) ) then ! deallocate(obj%SubMeshElemFromTo) ! endif if(allocated(obj%SubMeshSurfFromTo) ) then deallocate(obj%SubMeshSurfFromTo) endif NumOfDim=size(obj%NodCoord,2) if(NumOfDim==2)then call GetSurface2D(obj) obj%surface=1 elseif(NumOfDim==3)then call GetFacetElement(obj) call GetNextFacets(obj) obj%surface=1 else stop "ERROR >> GetSurface >> NumOfDim== 2 or 3 " endif call obj%SortFacet() end subroutine GetSurface !################################################## !################################################## subroutine GetInterface(obj1,obj2,iface1,iface2,err) class(Mesh_),intent(inout)::obj1,obj2 class(Mesh_),intent(inout)::iface1,iface2 type(Mesh_) :: BBox1,BBox2,BBox integer(int32),optional,intent(inout)::err integer(int32) :: i,j,n,ierr err =0 ! GetSurface call GetSurface(obj1) call GetSurface(obj2) ! GetBoundingBox call GetBoundingBox(obj1,BBox1) call GetBoundingBox(obj2,BBox2) call GetInterSectBox(BBox1,BBox2,BBox) if(.not.allocated(BBox%NodCoord) .or. size(BBox%NodCoord,1)==0)then print *, "No interface" err = 1 return endif call GetFacetElemInsideBox(obj1,BBox,iface1) call GetFacetElemInsideBox(obj2,BBox,iface2) call GetInterfaceElemNod(obj1,iface1) call GetInterfaceElemNod(obj2,iface2) end subroutine !################################################## !################################################## subroutine GetInterfaceElemNod(obj,iface) class(Mesh_),intent(in)::obj class(Mesh_),intent(inout)::iface integer(int32) :: i,j,n,felem_num,felemnod_num,dim_num integer(int32),allocatable::node_id_list(:) if(allocated(iface%ElemNod) )then deallocate(iface%ElemNod) endif if(allocated(iface%NodCoord) )then deallocate(iface%NodCoord) endif if(allocated(iface%NodCoordInit) )then deallocate(iface%NodCoordInit) endif allocate(node_id_list(size(obj%NodCoord,1) )) node_id_list(:)=0 ! check node_id_list dim_num=size(obj%NodCoord,2) felem_num=size(iface%FacetElemNod,1) felemnod_num=size(iface%FacetElemNod,2) do i=1,felem_num do j=1,felemnod_num node_id_list(iface%FacetElemNod(i,j))=1 enddo enddo n=sum(node_id_list) if(allocated(iface%GlobalNodID) ) deallocate(iface%GlobalNodID) if(allocated(iface%NodCoord) ) deallocate(iface%NodCoord) if(allocated(iface%NodCoordInit) ) deallocate(iface%NodCoordInit) allocate( iface%GlobalNodID(n) ) allocate( iface%NodCoord(n,dim_num ) ) allocate( iface%NodCoordInit(n,dim_num ) ) n=0 do i=1,size(node_id_list) if(node_id_list(i)==1 )then n=n+1 iface%GlobalNodID(n)=i iface%NodCoord(n,:)=obj%NodCoord(i,:) else cycle endif enddo allocate(iface%ElemNod(felem_num,felemnod_num ) ) do i=1,size(iface%ElemNod,1) do j=1,size(iface%ElemNod,2) iface%ElemNod(i,j)=SearchIDIntVec( iface%GlobalNodID, iface%FacetElemNod(i,j) ) enddo enddo iface%NodCoordInit(:,:)=iface%NodCoord(:,:) end subroutine !################################################## !################################################## subroutine GetBoundingBox(obj,BBox) class(Mesh_),intent(in)::obj class(Mesh_),intent(inout)::BBox real(real64),allocatable::max_coord(:),min_coord(:) integer(int32) :: dim_num,i dim_num=size(obj%NodCoord,2) allocate(max_coord(dim_num) ) allocate(min_coord(dim_num) ) do i=1,dim_num max_coord(i)=maxval(obj%NodCoord(:,i) ) min_coord(i)=minval(obj%NodCoord(:,i) ) enddo if(dim_num==2)then allocate(BBox%NodCoord(4,2) ) allocate(BBox%ElemNod( 1,4) ) allocate(BBox%ElemMat(1) ) BBox%ElemMat(1)=1 do i=1,4 BBox%ElemNod(1,i)=i enddo BBox%NodCoord(1,1)=min_coord(1) ; BBox%NodCoord(1,2)=min_coord(2) ; BBox%NodCoord(2,1)=max_coord(1) ; BBox%NodCoord(2,2)=min_coord(2) ; BBox%NodCoord(3,1)=max_coord(1) ; BBox%NodCoord(3,2)=max_coord(2) ; BBox%NodCoord(4,1)=min_coord(1) ; BBox%NodCoord(4,2)=max_coord(2) ; elseif(dim_num==3)then allocate(BBox%NodCoord(8,3) ) allocate(BBox%ElemNod( 1,8) ) allocate(BBox%ElemMat(1) ) BBox%ElemMat(1)=1 do i=1,8 BBox%ElemNod(1,i)=i enddo BBox%NodCoord(1,1)=min_coord(1) ; BBox%NodCoord(1,2)=min_coord(2) ; BBox%NodCoord(1,3)=min_coord(3) ; BBox%NodCoord(2,1)=max_coord(1) ; BBox%NodCoord(2,2)=min_coord(2) ; BBox%NodCoord(2,3)=min_coord(3) ; BBox%NodCoord(3,1)=max_coord(1) ; BBox%NodCoord(3,2)=max_coord(2) ; BBox%NodCoord(3,3)=min_coord(3) ; BBox%NodCoord(4,1)=min_coord(1) ; BBox%NodCoord(4,2)=max_coord(2) ; BBox%NodCoord(4,3)=min_coord(3) ; BBox%NodCoord(5,1)=min_coord(1) ; BBox%NodCoord(5,2)=min_coord(2) ; BBox%NodCoord(5,3)=max_coord(3) ; BBox%NodCoord(6,1)=max_coord(1) ; BBox%NodCoord(6,2)=min_coord(2) ; BBox%NodCoord(6,3)=max_coord(3) ; BBox%NodCoord(7,1)=max_coord(1) ; BBox%NodCoord(7,2)=max_coord(2) ; BBox%NodCoord(7,3)=max_coord(3) ; BBox%NodCoord(8,1)=min_coord(1) ; BBox%NodCoord(8,2)=max_coord(2) ; BBox%NodCoord(8,3)=max_coord(3) ; else stop "ERROR :: GetBoundingBox :: dim_num should be 2 or 3 " endif end subroutine !################################################## !################################################## subroutine GetFacetElemInsideBox(obj,BBox,iface) class(Mesh_),intent(in)::obj,BBox class(Mesh_),intent(inout)::iface integer(int32) i,j,n,dim_num,s_elem_num,count_s_elem_num,c_or_not,k,mm real(real64) ::max_obj,max_bb,min_obj,min_bb dim_num=size(obj%NodCoord,2) s_elem_num=size(obj%FacetElemNod,1) count_s_elem_num=0 do i=1,s_elem_num c_or_not=0 do j=1, dim_num mm=0 do k=1, size(obj%FacetElemNod,2) max_obj= obj%NodCoord( obj%FacetElemNod(i,k),j) max_bb = maxval(BBox%NodCoord(:,j)) min_obj= obj%NodCoord( obj%FacetElemNod(i,k),j) min_bb = minval(BBox%NodCoord(:,j)) if(max_obj <= max_bb .and. min_obj >= min_bb )then mm=mm+1 endif enddo if(mm >= 1)then c_or_not=c_or_not+1 endif enddo if(c_or_not==dim_num)then count_s_elem_num=count_s_elem_num+1 endif enddo if(allocated(iface%FacetElemNod) ) deallocate(iface%FacetElemNod) allocate(iface%FacetElemNod(count_s_elem_num,size(obj%FacetElemNod,2) ) ) count_s_elem_num=0 do i=1,s_elem_num c_or_not=0 do j=1, dim_num mm=0 do k=1, size(obj%FacetElemNod,2) max_obj= obj%NodCoord( obj%FacetElemNod(i,k),j) max_bb = maxval(BBox%NodCoord(:,j)) min_obj= obj%NodCoord( obj%FacetElemNod(i,k),j) min_bb = minval(BBox%NodCoord(:,j)) if(max_obj <= max_bb .and. min_obj >= min_bb )then mm=mm+1 endif enddo if(mm >= 1)then c_or_not=c_or_not+1 endif enddo if(c_or_not==dim_num)then count_s_elem_num=count_s_elem_num+1 iface%FacetElemNod(count_s_elem_num,:)=obj%FacetElemNod(i,:) endif enddo end subroutine !################################################## !################################################## subroutine GetInterSectBox(obj1,obj2,BBox) class(Mesh_),intent(in)::obj1,obj2 class(Mesh_),intent(inout)::BBox real(real64),allocatable::width1(:),width2(:),center1(:),center2(:),max_coord(:),min_coord(:),& x1_max(:),x1_min(:),x2_max(:),x2_min(:),center(:) real(real64) :: xmax_(2),xmin_(2) integer(int32) :: dim_num,i,j,c_or_not ! check contact dim_num=size(obj1%nodcoord,2) if(dim_num==2)then if(allocated(BBox%NodCoord) ) deallocate(BBox%NodCoord) if(allocated(BBox%ElemNod) ) deallocate(BBox%ElemNod) allocate(BBox%NodCoord(4,2) ) allocate(BBox%ElemNod( 1,4) ) elseif(dim_num==3)then if(allocated(BBox%NodCoord) ) deallocate(BBox%NodCoord) if(allocated(BBox%ElemNod) ) deallocate(BBox%ElemNod) allocate(BBox%NodCoord(8,3) ) allocate(BBox%ElemNod( 1,8) ) else stop "ERROR :: GetBoundingBox :: dim_num should be 2 or 3 " endif allocate(center1(dim_num) ) allocate(center2(dim_num) ) center1(:)=0.0d0 center2(:)=0.0d0 allocate(width1(dim_num) ) allocate(width2(dim_num) ) allocate(max_coord(dim_num) ) allocate(min_coord(dim_num) ) do i=1,dim_num center1(i)=0.50d0*minval(obj1%NodCoord(:,i))+0.50d0*maxval(obj1%NodCoord(:,i)) center2(i)=0.50d0*minval(obj2%NodCoord(:,i))+0.50d0*maxval(obj2%NodCoord(:,i)) width1(i) = maxval(obj1%NodCoord(:,i)) - minval(obj1%NodCoord(:,i)) width2(i) = maxval(obj2%NodCoord(:,i)) - minval(obj2%NodCoord(:,i)) enddo ! ! Detect intersection by nodes ! dim_num=size(obj1%NodCoord,2) ! allocate(x1_max(dim_num),x2_max(dim_num),x1_min(dim_num),x2_min(dim_num),center(dim_num) ) ! do i=1,dim_num ! x1_max(i) = maxval(obj1%nodcoord(:,i) ) ! x1_min(i) = minval(obj1%nodcoord(:,i) ) ! x2_max(i) = maxval(obj2%nodcoord(:,i) ) ! x2_min(i) = minval(obj2%nodcoord(:,i) ) ! enddo ! center(:) = 0.50d0*center1(:)+ 0.50d0*center1(:) ! ! c_or_not = 0 ! default :: contact ! do i=1,dim_num ! if(center() ) ! enddo ! ! Contact detection c_or_not=1 do i=1,dim_num if(abs(center1(i)-center2(i)) <= 0.50d0*width1(i)+0.50d0*width2(i) )then cycle else c_or_not=c_or_not*0 endif enddo if(c_or_not==0)then print *, "No contact ! GetInterSectBox " deallocate(BBox%NodCoord) deallocate(BBox%ElemNod) return else print *, "Contact ! GetInterSectBox " endif ! Cmputing Intersection Box do i=1,dim_num xmax_(1)=maxval(obj1%NodCoord(:,i)) xmax_(2)=maxval(obj2%NodCoord(:,i)) xmin_(1)=minval(obj1%NodCoord(:,i)) xmin_(2)=minval(obj2%NodCoord(:,i)) max_coord(i)=minval(xmax_) min_coord(i)=maxval(xmin_) enddo if(dim_num==2)then do i=1,4 BBox%ElemNod(1,i)=i enddo BBox%NodCoord(1,1)=min_coord(1) ; BBox%NodCoord(1,2)=min_coord(2) ; BBox%NodCoord(2,1)=max_coord(1) ; BBox%NodCoord(2,2)=min_coord(2) ; BBox%NodCoord(3,1)=max_coord(1) ; BBox%NodCoord(3,2)=max_coord(2) ; BBox%NodCoord(4,1)=min_coord(1) ; BBox%NodCoord(4,2)=max_coord(2) ; elseif(dim_num==3)then do i=1,8 BBox%ElemNod(1,i)=i enddo BBox%NodCoord(1,1)=min_coord(1) ; BBox%NodCoord(1,2)=min_coord(2) ; BBox%NodCoord(1,3)=min_coord(3) ; BBox%NodCoord(2,1)=max_coord(1) ; BBox%NodCoord(2,2)=min_coord(2) ; BBox%NodCoord(2,3)=min_coord(3) ; BBox%NodCoord(3,1)=max_coord(1) ; BBox%NodCoord(3,2)=max_coord(2) ; BBox%NodCoord(3,3)=min_coord(3) ; BBox%NodCoord(4,1)=min_coord(1) ; BBox%NodCoord(4,2)=max_coord(2) ; BBox%NodCoord(4,3)=min_coord(3) ; BBox%NodCoord(5,1)=min_coord(1) ; BBox%NodCoord(5,2)=min_coord(2) ; BBox%NodCoord(5,3)=max_coord(3) ; BBox%NodCoord(6,1)=max_coord(1) ; BBox%NodCoord(6,2)=min_coord(2) ; BBox%NodCoord(6,3)=max_coord(3) ; BBox%NodCoord(7,1)=max_coord(1) ; BBox%NodCoord(7,2)=max_coord(2) ; BBox%NodCoord(7,3)=max_coord(3) ; BBox%NodCoord(8,1)=min_coord(1) ; BBox%NodCoord(8,2)=max_coord(2) ; BBox%NodCoord(8,3)=max_coord(3) ; else stop "ERROR :: GetBoundingBox :: dim_num should be 2 or 3 " endif end subroutine !################################################## !################################################## subroutine GetNextFacets(obj) class(Mesh_),intent(inout)::obj integer(int32),allocatable::buffer(:) integer(int32) :: i,j,n,node_id,k,l,m if(allocated(obj%NextFacets) )then deallocate(obj%NextFacets) endif allocate(buffer(100) ) allocate(obj%NextFacets(size(obj%FacetElemNod,1),size(obj%FacetElemNod,2)*100+1 )) obj%NextFacets(:,:)=-1 do i=1,size(obj%FacetElemNod,1) buffer(:)=-1 obj%NextFacets(i,1)=i buffer(1)=i n=2 do j=1,size(obj%FacetElemNod,2) node_id=obj%FacetElemNod(i,j) do k=1,size(obj%FacetElemNod,1) if(k==j)then cycle endif do l=1,size(obj%FacetElemNod,2) if(n>size(obj%NextFacets,1))then stop "Warning!! >> GetNextFacets >> n>size(obj%NextFacets,1)" endif if(obj%FacetElemNod(k,l)==node_id )then buffer(n)=k n=n+1 endif enddo enddo enddo do j=1,size(buffer,1) do k=j+1,size(buffer,1) if(buffer(j)==buffer(k) )then buffer(k)=-1 endif enddo enddo n=1 do j=1,size(buffer,1) if(buffer(j)>0 )then if(i>size(obj%NextFacets,1) .or. n>size(obj%NextFacets,2) )then print *, "i , size(obj%NextFacets,1) : ",i,size(obj%NextFacets,1) print *, "n, size(obj%NextFacets,2) : ",n,size(obj%NextFacets,2) stop "MeshClass >> GetNextFacets >> invalid i,n" endif obj%NextFacets(i,n)=buffer(j) n=n+1 else cycle endif enddo enddo end subroutine !################################################## !################################################## subroutine addMesh(obj,mesh,from,length,rot_x,rot_y,rot_z,x,y,z,dx,dy,dz) class(Mesh_),intent(inout) :: obj class(Mesh_),optional,intent(inout) :: mesh integer(int32),optional,intent(in) :: from real(real64),optional,intent(in) :: length,rot_x,rot_y,rot_z,x,y,z,dx,dy,dz integer(int32) :: NumOfElem,node_id,elem_id real(real64) :: n(3),rotmat(3,3),L if(obj%meshtype == "Root" .or. obj%meshtype == "root")then ! add node node_id = size(obj%nodcoord,1) elem_id=size(obj%elemnod,1) call extendArray(obj%nodcoord,extend1stColumn=.true.) call extendArray(obj%elemnod,extend1stColumn=.true.) n(:) = 0.0d0 n(3) = -1.0d0 if(present(rot_x) )then rotmat(1,1)=1.0d0 ;rotmat(1,2)=0.0d0 ;rotmat(1,3)=0.0d0 ; rotmat(2,1)=0.0d0 ;rotmat(2,2)=cos(rot_x) ;rotmat(2,3)=-sin(rot_x); rotmat(3,1)=0.0d0 ;rotmat(3,2)=sin(rot_x) ;rotmat(3,3)= cos(rot_x); n(:) = matmul(rotmat,n) endif if(present(rot_y) )then rotmat(1,1)=cos(rot_y) ;rotmat(1,2)=0.0d0 ;rotmat(1,3)=sin(rot_y) ; rotmat(2,1)=0.0d0 ;rotmat(2,2)=1.0d0 ;rotmat(2,3)=0.0d0 ; rotmat(3,1)=-sin(rot_y) ;rotmat(3,2)=0.0d0 ;rotmat(3,3)= cos(rot_y) ; n(:) = matmul(rotmat,n) endif if(present(rot_z) )then rotmat(1,1)=cos(rot_z) ;rotmat(1,2)=-sin(rot_z) ;rotmat(1,3)=0.0d0 ; rotmat(2,1)=sin(rot_z) ;rotmat(2,2)=cos(rot_z) ;rotmat(2,3)=0.0d0 ; rotmat(3,1)=0.0d0 ;rotmat(3,2)=0.0d0 ;rotmat(3,3)=1.0d0 ; n(:) = matmul(rotmat,n) endif ! Or you can directly identify new node by coordinate n(1) = input(default=n(1), option=dx ) n(2) = input(default=n(2), option=dy ) n(3) = input(default=n(3), option=dz ) L = input(default=1.0d0,option=length) if(present(from) )then obj%nodcoord(node_id+1,:) = obj%nodcoord(From,:) + L*n(:) obj%nodcoord(node_id+1,1) = input(default=obj%nodcoord(node_id+1,1), option=x ) obj%nodcoord(node_id+1,2) = input(default=obj%nodcoord(node_id+1,2), option=y ) obj%nodcoord(node_id+1,3) = input(default=obj%nodcoord(node_id+1,3), option=z ) obj%elemnod(elem_id+1,1) = From obj%elemnod(elem_id+1,2:) = node_id+1 else obj%nodcoord(node_id+1,:) = obj%nodcoord(node_id,:) + L*n(:) obj%nodcoord(node_id+1,1) = input(default=obj%nodcoord(node_id+1,1), option=x ) obj%nodcoord(node_id+1,2) = input(default=obj%nodcoord(node_id+1,2), option=y ) obj%nodcoord(node_id+1,3) = input(default=obj%nodcoord(node_id+1,3), option=z ) obj%elemnod(elem_id+1,1) = node_id obj%elemnod(elem_id+1,2:) = node_id+1 endif return endif NumOfElem=size(obj%ElemNod,1) call addarray(obj%NodCoord,mesh%NodCoord) call addarray(obj%ElemNod,mesh%ElemNod) call addarray(obj%ElemMat,mesh%ElemMat) obj%ElemNod(NumOfElem+1:,:)=obj%ElemNod(NumOfElem+1:,:)+size(obj%NodCoord,1) end subroutine !################################################## !################################################## subroutine MergeMesh(inobj1,inobj2,outobj) class(Mesh_),intent(in) ::inobj1,inobj2 class(Mesh_),intent(out)::outobj integer(int32) node_num1,num1,num2,num3 integer(int32) i,j,k !MergeObjects if the array is allocated. ! ========= Merge nodes ============ num1=size(inobj1%NodCoord,1) node_num1=num1 num2=size(inobj2%NodCoord,1) num3=size(inobj2%NodCoord,2) if(num3 /= size(inobj1%NodCoord,1) )then outobj%ErrorMsg="MergeMesh >> num3 /= inobj1%NodCoord,1" endif allocate(outobj%NodCoord(num1+num2, num3)) do i=1,num1 outobj%NodCoord(i,:)=inobj1%NodCoord(i,:) enddo do i=1,num2 outobj%NodCoord(i+num1,:)=inobj2%NodCoord(i,:) enddo ! update subdomain infomation if(allocated(inobj1%SubMeshNodFromTo) )then if(allocated(inobj2%SubMeshNodFromTo) )then if(allocated(outobj%SubMeshNodFromTo) )then deallocate(outobj%SubMeshNodFromTo) endif allocate(outobj%SubMeshNodFromTo(2,3) ) outobj%SubMeshNodFromTo(1,1)=1 !subdomain ID outobj%SubMeshNodFromTo(1,2)=1 outobj%SubMeshNodFromTo(1,3)=num1 outobj%SubMeshNodFromTo(2,1)=2 !subdomain ID outobj%SubMeshNodFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshNodFromTo(2,3)=num1+num2 !node id goes to else if(allocated(outobj%SubMeshNodFromTo) )then deallocate(outobj%SubMeshNodFromTo) endif allocate(outobj%SubMeshNodFromTo(2,3) ) outobj%SubMeshNodFromTo(1,1)=1 !subdomain ID outobj%SubMeshNodFromTo(1,2)=1 outobj%SubMeshNodFromTo(1,3)=num1 outobj%SubMeshNodFromTo(2,1)=2 !subdomain ID outobj%SubMeshNodFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshNodFromTo(2,3)=num1+num2 !node id goes to endif else if(allocated(inobj2%SubMeshNodFromTo) )then if(allocated(outobj%SubMeshNodFromTo) )then deallocate(outobj%SubMeshNodFromTo) endif allocate(outobj%SubMeshNodFromTo(2,3) ) outobj%SubMeshNodFromTo(1,1)=1 !subdomain ID outobj%SubMeshNodFromTo(1,2)=1 outobj%SubMeshNodFromTo(1,3)=num1 outobj%SubMeshNodFromTo(2,1)=2 !subdomain ID outobj%SubMeshNodFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshNodFromTo(2,3)=num1+num2 !node id goes to else if(allocated(outobj%SubMeshNodFromTo) )then deallocate(outobj%SubMeshNodFromTo) endif allocate(outobj%SubMeshNodFromTo(2,3) ) outobj%SubMeshNodFromTo(1,1)=1 !subdomain ID outobj%SubMeshNodFromTo(1,2)=1 outobj%SubMeshNodFromTo(1,3)=num1 outobj%SubMeshNodFromTo(2,1)=2 !subdomain ID outobj%SubMeshNodFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshNodFromTo(2,3)=num1+num2 !node id goes to endif endif ! ========= Merge nodes ============ ! ========= Merge elements ============ num1=size(inobj1%ElemNod,1) num2=size(inobj2%ElemNod,1) num3=size(inobj2%ElemNod,2) if(num3 /= size(inobj1%ElemNod,1) )then outobj%ErrorMsg="MergeMesh >> num3 /= inobj1%ElemNod,1" endif allocate(outobj%ElemNod(num1+num2, num3)) do i=1,num1 outobj%ElemNod(i,:)=inobj1%ElemNod(i,:) enddo do i=1,num2 outobj%ElemNod(i+num1,:)=inobj2%ElemNod(i,:)+node_num1 enddo ! update subdomain infomation if(allocated(inobj1%SubMeshElemFromTo) )then if(allocated(inobj2%SubMeshElemFromTo) )then if(allocated(outobj%SubMeshElemFromTo) )then deallocate(outobj%SubMeshElemFromTo) endif allocate(outobj%SubMeshElemFromTo(2,3) ) outobj%SubMeshElemFromTo(1,1)=1 !subdomain ID outobj%SubMeshElemFromTo(1,2)=1 outobj%SubMeshElemFromTo(1,3)=num1 outobj%SubMeshElemFromTo(2,1)=2 !subdomain ID outobj%SubMeshElemFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshElemFromTo(2,3)=num1+num2 !node id goes to else if(allocated(outobj%SubMeshElemFromTo) )then deallocate(outobj%SubMeshElemFromTo) endif allocate(outobj%SubMeshElemFromTo(2,3) ) outobj%SubMeshElemFromTo(1,1)=1 !subdomain ID outobj%SubMeshElemFromTo(1,2)=1 outobj%SubMeshElemFromTo(1,3)=num1 outobj%SubMeshElemFromTo(2,1)=2 !subdomain ID outobj%SubMeshElemFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshElemFromTo(2,3)=num1+num2 !node id goes to endif else if(allocated(inobj2%SubMeshElemFromTo) )then if(allocated(outobj%SubMeshElemFromTo) )then deallocate(outobj%SubMeshElemFromTo) endif allocate(outobj%SubMeshElemFromTo(2,3) ) outobj%SubMeshElemFromTo(1,1)=1 !subdomain ID outobj%SubMeshElemFromTo(1,2)=1 outobj%SubMeshElemFromTo(1,3)=num1 outobj%SubMeshElemFromTo(2,1)=2 !subdomain ID outobj%SubMeshElemFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshElemFromTo(2,3)=num1+num2 !node id goes to else if(allocated(outobj%SubMeshElemFromTo) )then deallocate(outobj%SubMeshElemFromTo) endif allocate(outobj%SubMeshElemFromTo(2,3) ) outobj%SubMeshElemFromTo(1,1)=1 !subdomain ID outobj%SubMeshElemFromTo(1,2)=1 outobj%SubMeshElemFromTo(1,3)=num1 outobj%SubMeshElemFromTo(2,1)=2 !subdomain ID outobj%SubMeshElemFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshElemFromTo(2,3)=num1+num2 !node id goes to endif endif ! ========= Merge elements ============ ! ========= Merge Facet Elements ============ num1=size(inobj1%FacetElemNod,1) num2=size(inobj2%FacetElemNod,1) num3=size(inobj2%FacetElemNod,2) if(num3 /= size(inobj1%FacetElemNod,1) )then outobj%ErrorMsg="MergeMesh >> num3 /= inobj1%ElemNod,1" endif allocate(outobj%FacetElemNod(num1+num2, num3)) do i=1,num1 outobj%FacetElemNod(i,:)=inobj1%FacetElemNod(i,:) enddo do i=1,num2 outobj%FacetElemNod(i+num1,:)=inobj2%FacetElemNod(i,:)+node_num1 enddo ! ========= Merge Facet Elements ============ ! ========= Merge surface elements ============ num1=size(inobj1%SurfaceLine2D,1) num2=size(inobj2%SurfaceLine2D,1) allocate(outobj%SurfaceLine2D(num1+num2)) do i=1,num1 outobj%SurfaceLine2D(i)=inobj1%SurfaceLine2D(i) enddo do i=1,num2 outobj%SurfaceLine2D(i+num1)=inobj2%SurfaceLine2D(i)+node_num1 enddo ! update subdomain infomation if(allocated(inobj1%SubMeshSurfFromTo) )then if(allocated(inobj2%SubMeshSurfFromTo) )then if(allocated(outobj%SubMeshSurfFromTo) )then deallocate(outobj%SubMeshSurfFromTo) endif allocate(outobj%SubMeshSurfFromTo(2,3) ) outobj%SubMeshSurfFromTo(1,1)=1 !subdomain ID outobj%SubMeshSurfFromTo(1,2)=1 outobj%SubMeshSurfFromTo(1,3)=num1 outobj%SubMeshSurfFromTo(2,1)=2 !subdomain ID outobj%SubMeshSurfFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshSurfFromTo(2,3)=num1+num2 !node id goes to else if(allocated(outobj%SubMeshSurfFromTo) )then deallocate(outobj%SubMeshSurfFromTo) endif allocate(outobj%SubMeshSurfFromTo(2,3) ) outobj%SubMeshSurfFromTo(1,1)=1 !subdomain ID outobj%SubMeshSurfFromTo(1,2)=1 outobj%SubMeshSurfFromTo(1,3)=num1 outobj%SubMeshSurfFromTo(2,1)=2 !subdomain ID outobj%SubMeshSurfFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshSurfFromTo(2,3)=num1+num2 !node id goes to endif else if(allocated(inobj2%SubMeshSurfFromTo) )then if(allocated(outobj%SubMeshSurfFromTo) )then deallocate(outobj%SubMeshSurfFromTo) endif allocate(outobj%SubMeshSurfFromTo(2,3) ) outobj%SubMeshSurfFromTo(1,1)=1 !subdomain ID outobj%SubMeshSurfFromTo(1,2)=1 outobj%SubMeshSurfFromTo(1,3)=num1 outobj%SubMeshSurfFromTo(2,1)=2 !subdomain ID outobj%SubMeshSurfFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshSurfFromTo(2,3)=num1+num2 !node id goes to else if(allocated(outobj%SubMeshSurfFromTo) )then deallocate(outobj%SubMeshSurfFromTo) endif allocate(outobj%SubMeshSurfFromTo(2,3) ) outobj%SubMeshSurfFromTo(1,1)=1 !subdomain ID outobj%SubMeshSurfFromTo(1,2)=1 outobj%SubMeshSurfFromTo(1,3)=num1 outobj%SubMeshSurfFromTo(2,1)=2 !subdomain ID outobj%SubMeshSurfFromTo(2,2)=num1+1 !node id starts from outobj%SubMeshSurfFromTo(2,3)=num1+num2 !node id goes to endif endif ! ========= Merge surface elements ============ ! ========= Merge Material ID ================== num1=size(inobj1%ElemMat,1) num2=size(inobj2%ElemMat,1) if(num3 /= size(inobj1%ElemMat,1) )then outobj%ErrorMsg="MergeMesh >> num3 /= inobj1%ElemMat,1" endif allocate(outobj%ElemMat(num1+num2)) do i=1,num1 outobj%ElemMat(i)=inobj1%ElemMat(i) enddo do i=1,num2 outobj%ElemMat(i+num1)=inobj2%ElemMat(i)+Maxval(inobj1%ElemMat) enddo ! ========= Merge Material ID ================== end subroutine MergeMesh !################################################## !################################################## subroutine ExportElemNod(obj,elem_nod) class(Mesh_),intent(inout)::obj integer(int32),allocatable,intent(inout)::elem_nod(:,:) if(allocated(elem_nod ))then deallocate(elem_nod) endif allocate(elem_nod(size(obj%ElemNod,1),size(obj%ElemNod,2) ) ) elem_nod(:,:)=obj%ElemNod(:,:) end subroutine ExportElemNod !################################################## !################################################## subroutine ExportNodCoord(obj,nod_coord) class(Mesh_),intent(inout)::obj real(real64),allocatable,intent(inout)::nod_coord(:,:) if(allocated(nod_coord) )then deallocate(nod_coord) endif allocate(nod_coord(size(obj%NodCoord,1),size(obj%NodCoord,2) ) ) nod_coord(:,:)=obj%NodCoord(:,:) end subroutine ExportNodCoord !################################################## !################################################## subroutine ExportSurface2D(obj,surface_nod) class(Mesh_),intent(inout)::obj integer(int32),allocatable,intent(inout)::surface_nod(:) if(allocated(surface_nod) )then deallocate(surface_nod) endif allocate(surface_nod(size(obj%SurfaceLine2D,1) ) ) surface_nod(:)=obj%SurfaceLine2D(:) end subroutine ExportSurface2D !################################################## !################################################## subroutine DisplayMesh(obj,OptionalFolderName,OptionalFormat,FileHandle,Name) class(Mesh_),intent(inout)::obj character(*),optional,intent(in):: OptionalFolderName character(*),optional,intent(in) :: OptionalFormat,Name integer(int32),optional,intent(in) :: FileHandle integer(int32) :: fh character*70 DefaultFolderName character*70 FolderName character*76 command_mkdir character*86 surfaceout integer i,j,node_ID,node_ID_next,k fh=input(default=10,option=FileHandle) if(present(Name) )then open(fh,file=Name) if(.not.allocated(obj%ElemNod) )then print *, "DisplayMesh :: Error >> mesh-connectivity is not allocated." return endif do i=1,size(obj%ElemNod,1) do j=1,size(obj%ElemNod,2) write(fh,*) obj%NodCoord(obj%ElemNod(i,j),:) enddo write(fh,*) obj%NodCoord(obj%ElemNod(i,1),:) write(fh,*) " " enddo close(fh) return endif if(present(OptionalFormat) )then if(trim(OptionalFormat)==".gp")then ! Export Mesh as .gp open(102,file="SurfaceLine2D.txt") ! Surface line do i=1,size(obj%SubMeshSurfFromTo,1) do j=obj%SubMeshSurfFromTo(i,2),obj%SubMeshSurfFromTo(i,3)-1 node_ID =obj%SurfaceLine2D(j) node_ID_next=obj%SurfaceLine2D(j+1) write(102,*) obj%NodCoord(node_ID,:),& obj%NodCoord(node_ID_next,:)-obj%NodCoord(node_ID,:) enddo node_ID =obj%SurfaceLine2D(obj%SubMeshSurfFromTo(i,3)) node_ID_next=obj%SurfaceLine2D(obj%SubMeshSurfFromTo(i,2)) write(102,*) obj%NodCoord(node_ID,:),& obj%NodCoord(node_ID_next,:)-obj%NodCoord(node_ID,:) write(102,*) " " enddo close(102) open(102,file="SurfaceLine2D.gp") write(102,*) "plot 'SurfaceLine2D.txt' with vector " write(102,*) "pause -1" close(102) call execute_command_line("gnuplot SurfaceLine2D.gp") endif endif if(present(OptionalFormat) )then if(trim(OptionalFormat)==".gp")then ! Export Mesh as .gp open(102,file="ElemLine2D.txt") ! Elemace line do i=1,size(obj%SubMeshElemFromTo,1) do j=obj%SubMeshElemFromTo(i,2),obj%SubMeshElemFromTo(i,3) do k=1,size(obj%ElemNod,2)-1 write(102, * ) obj%NodCoord(obj%ElemNod(j,k),:),& obj%NodCoord(obj%ElemNod(j,k+1),:)-obj%NodCoord(obj%ElemNod(j,k),:) enddo write(102,*) obj%NodCoord(obj%ElemNod(j,size(obj%ElemNod,2)),:),& obj%NodCoord(obj%ElemNod(j,1),:)& -obj%NodCoord(obj%ElemNod(j,size(obj%ElemNod,2)),:) enddo write(102,*) " " enddo close(102) open(102,file="ElemLine2D.gp") write(102,*) "plot 'ElemLine2D.txt' with vector " write(102,*) "pause -1" close(102) call execute_command_line("gnuplot ElemLine2D.gp") return endif endif DefaultFolderName="DisplaySurface" if(present(OptionalFolderName) )then FolderName=OptionalFolderName else FolderName=DefaultFolderName endif command_mkdir ="mkdir -p " // trim(FolderName) command_mkdir =trim(command_mkdir ) call execute_command_line(command_mkdir ) surfaceout=trim(FolderName)//"/surface_nod.txt" surfaceout=trim(surfaceout) open(100,file=surfaceout) do i=1,size(obj%SurfaceLine2D,1) write(100,*) obj%NodCoord(obj%SurfaceLine2D(i),: ) enddo close(100) surfaceout=trim(FolderName)//"/surface_ids.txt" surfaceout=trim(surfaceout) open(100,file=surfaceout) do i=1,size(obj%SurfaceLine2D,1) write(100,*) obj%NodCoord(obj%SurfaceLine2D(i),: ) enddo close(100) surfaceout=trim(FolderName)//"/element_nod.txt" surfaceout=trim(surfaceout) open(100,file=surfaceout) do i=1,size(obj%SurfaceLine2D,1) write(100,*) obj%NodCoord(obj%SurfaceLine2D(i),: ) enddo close(100) end subroutine DisplayMesh !################################################## !################################################## subroutine ShowMesh(obj,FileHandle,OnlySurface) class(Mesh_),intent(inout)::obj integer(int32),optional,intent(in)::FileHandle logical,optional,intent(in)::OnlySurface logical :: no_fh integer(int32) :: i,j,fh,n,m,exp_mode if( present(FileHandle) )then fh=FileHandle no_fh = .false. else no_fh = .true. endif if(present(OnlySurface) )then if(OnlySurface .eqv. .true. )then n=size(obj%FacetElemNod,1) exp_mode=2 else n=size(obj%ElemNod,1) exp_mode=1 endif else n=size(obj%ElemNod,1) exp_mode=1 endif if(exp_mode==1)then do i=1,n do j=1,size(Obj%ElemNod,2) if(no_fh .eqv. .true.)then write(*,*) obj%NodCoord( Obj%ElemNod(i,j),: ) if(j==size(Obj%ElemNod,2) )then write(*,*) " " endif else write(fh,*) obj%NodCoord( Obj%ElemNod(i,j),: ) if(j==size(Obj%ElemNod,2) )then write(fh,*) " " endif endif enddo enddo else do i=1,n do j=1,size(Obj%FacetElemNod,2) if(no_fh .eqv. .true.)then write(*,*) obj%NodCoord( Obj%FacetElemNod(i,j),: ) if(j==size(Obj%FacetElemNod,2) )then write(*,*) " " endif else write(fh,*) obj%NodCoord( Obj%FacetElemNod(i,j),: ) if(j==size(Obj%FacetElemNod,2) )then write(fh,*) " " endif endif enddo enddo endif end subroutine !################################################## !################################################## subroutine MeltingSkeltonMesh(obj,ItrTol) class(Mesh_),intent(inout)::obj type(Mesh_) :: MeltObj integer(int32),optional,intent(in)::ItrTol integer(int32) :: itr,i,j,k,l,n,m,EndStep,dnum,dnum_init,nodeid,fnodeid ! ######## Caution ################# ! IT gets a "skelton mesh" ! "skelton mesh" is consists of the chain of elements, where all surface are facets ! you need to modify this code, since it may be incomplete and slow. ! ######## Caution ################# if(present(ItrTol) )then EndStep=ItrTol else EndStep=10 endif n=size(obj%ElemNod,1) m=size(obj%ElemNod,2) !call obj%Copy(MeltObj) call obj%GetSurface() call Meltobj%copy(obj,Minimum=.true.) dnum_init=obj%getNumOfDomain() do itr=1,EndStep call Meltobj%GetSurface() do i=1,size(Meltobj%ElemNod,1) do j=1, size(Meltobj%ElemNod,2) nodeid=Meltobj%ElemNod(i,j) if(nodeid <= 0 )then cycle endif do k=1,size(Meltobj%FacetElemNod,1) do l=1,size(Meltobj%FacetElemNod,2) fnodeid= Meltobj%FacetElemNod(k,l) if(fnodeid <= 0 )then print *, "Caution :: Meltobj%FacetElemNod >> NodeID <= 0 exists" exit endif if(nodeid==fnodeid)then MeltObj%ElemNod(i,:)=-1 exit endif enddo enddo enddo dnum=Meltobj%getNumOfDomain() if(dnum/=dnum_init)then Meltobj%ElemNod(i,:)=obj%ElemNod(i,:) endif enddo enddo end subroutine !################################################## !################################################## function getNumOfDomainMesh(obj,ItrTol) result(dnum) class(Mesh_),intent(inout)::obj integer(int32),optional,intent(in)::ItrTol integer(int32),allocatable :: domain_id(:), domain_id_ref(:),node_id(:) integer(int32) :: itr,i,j,k,l,n,m,node,cnode,itrmax,dnum n=size(obj%ElemNod,1) m=size(obj%ElemNod,2) allocate(domain_id(n),domain_id_ref(n),node_id(m) ) do i=1,n domain_id(i)=i enddo if(present(ItrTol))then itrmax=ItrTol else itrmax=100 endif do itr=1,itrmax domain_id_ref(:)=domain_id(:) do i=1,n do j=1,m node=obj%ElemNod(i,j) do k=1,n do l=1,m cnode=obj%ElemNod(k,l) if(node==cnode)then domain_id(i)=domain_id(n) exit endif enddo enddo enddo enddo if(dot_product(domain_id_ref-domain_id,domain_id_ref-domain_id) == 0 )then print *, "getNumOfDomainMesh >> converged" exit endif if(itr==itrmax)then print *, "getNumOfDomainMesh >> Did not converge" return endif enddo domain_id_ref(:)=0 do i=1,n do j=1,n if(domain_id(j)==i )then domain_id_ref(i)=1 endif enddo enddo dnum=0 do i=1,n dnum=dnum+domain_id_ref(i) enddo end function !################################################## !################################################## subroutine SortFacetMesh(obj) class(Mesh_),intent(inout)::obj integer(int32) :: i,j,n,m,a1,a2,id real(real64),allocatable :: buf(:) ! SortFacet n=size(obj%NodCoord,2) if(n==2)then if(.not.allocated(obj%FacetElemNod) )then !" SortFacetMesh >> for 3D, now implementing " return endif allocate(buf(size(obj%FacetElemNod,2) )) do i=1,size(obj%FacetElemNod,1)-1 a1=obj%FacetElemNod(i,2) do j=i+1,size(obj%FacetElemNod,1) a2=obj%FacetElemNod(j,1) if(a2==a1)then id=j exit endif enddo buf(:)=obj%FacetElemNod(i+1,:) obj%FacetElemNod(i+1,:)=obj%FacetElemNod(id,:) obj%FacetElemNod(id,:)=buf(:) enddo elseif(n==3)then !print *, "ERROR :: SortFacetMesh >> for 3D, now implementing " return endif end subroutine !################################################## !################################################## subroutine MeshingMesh(obj,Mode,itr_tol,delaunay2d) class(Mesh_),intent(inout)::obj type(Mesh_) :: box type(triangle_)::tri type(circle_)::cir logical,optional,intent(in) :: delaunay2d integer(int32),optional,intent(in) :: Mode,itr_tol integer(int32) :: i,j,k,n,m,node_num,dim_num,dim_mode,itr real(real64),allocatable :: stage_range(:,:),triangle(:,:),nodcoord(:,:) integer(int32),allocatable :: staged_node(:),lapl_node(:),& neighbornode(:),ElementElementConnect(:,:),elemnod(:,:) real(real64) :: centerx,centery,centerz,radius logical :: NoChange ! This method creates mesh-connectivity for the given nodal coordinates. ! Therefore, Mesh%NodCoord(:,:) should be filled preliminary. dim_mode=input(default=2,option=Mode) if(dim_mode==2 .or. present(delaunay2d))then if(.not. allocated(obj%NodCoord) )then print *, "ERROR :: MeshClass MeshingMesh" print *, "This method creates mesh-connectivity for the given nodal coordinates." print *, "Therefore, Mesh%NodCoord(:,:) should be filled preliminary." return endif print *, "Meshing sequence is started." if(.not. delaunay2d)then return endif node_num=size(obj%NodCoord,1) dim_num =size(obj%NodCoord,2) call obj%arrangeNodeOrder() call obj%getCircumscribedTriangle(triangle) if(allocated(obj%ElemNod) )then deallocate(obj%ElemNod) endif allocate(obj%ElemNod(node_num*2,3) ) allocate(staged_node(node_num+3)) obj%ElemNod(:,:)=-1 staged_node(:)=0 staged_node(node_num+1)=1 staged_node(node_num+2)=1 staged_node(node_num+3)=1 call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) obj%NodCoord(node_num+1,:)=triangle(1,:) obj%NodCoord(node_num+2,:)=triangle(2,:) obj%NodCoord(node_num+3,:)=triangle(3,:) do i=1,size(obj%NodCoord,1) ! Delauney triangulation for 2D print *, i,"/",size(obj%NodCoord,1)," :: ",dble(i)/dble(size(obj%NodCoord,1))*100,"% done." call obj%DelauneygetNewNode(i,staged_node,triangle) enddo ! Remove invalid triangle call obj%RemoveFailedTriangle() do k=1,size(obj%ElemNod,1) if(obj%ElemNod(k,1)<1)then cycle endif !write(123,*) obj%NodCoord(obj%ElemNod(k,1),:),obj%NodCoord(obj%ElemNod(k,2),:)-obj%NodCoord(obj%ElemNod(k,1),:) !write(123,*) obj%NodCoord(obj%ElemNod(k,2),:),obj%NodCoord(obj%ElemNod(k,3),:)-obj%NodCoord(obj%ElemNod(k,2),:) !write(123,*) obj%NodCoord(obj%ElemNod(k,3),:),obj%NodCoord(obj%ElemNod(k,1),:)-obj%NodCoord(obj%ElemNod(k,3),:) !writE(123,*) " " enddo ! Flipping (swapping) ) algorithm do k=1,input(default=1000,option=itr_tol) call obj%DelauneyremoveOverlaps(NoChange=NoChange) if(NoChange .eqv. .true.)then exit else cycle endif enddo ! Remove circumscribed triangle call obj%removeCircumscribedTriangle() ! Laplacian method call obj%getSurface() call obj%Laplacian(itr_tol=itr_tol) print *, "Meshing is successfully done based on Delauney 2D" elseif(dim_mode==3)then ! divide mesh by delauney ! step #0: check data quality if(.not. allocated(obj%NodCoord) )then print *, "ERROR :: MeshClass MeshingMesh" print *, "This method creates mesh-connectivity for the given nodal coordinates." print *, "Therefore, Mesh%NodCoord(:,:) should be filled preliminary." return endif print *, "Meshing sequence is started." node_num=size(obj%NodCoord,1) dim_num =size(obj%NodCoord,2) ! arrange node order from outer to inner. call obj%arrangeNodeOrder() ! step #1: get Curcumscribed Box call obj%getCircumscribedBox(box) ! prepare connectivity if(allocated(obj%ElemNod) )then deallocate(obj%ElemNod) endif obj%ElemNod = box%elemnod obj%ElemNod(:,:) =obj%ElemNod(:,:) + node_num ! staged_node(:)=0 ! staged_node(node_num+1)=1 ! staged_node(node_num+2)=1 ! staged_node(node_num+3)=1 call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) call ExtendArrayReal(obj%NodCoord,extend1stColumn=.true.,DefaultValue=0.0d0) obj%NodCoord(node_num+1,:)=box%NodCoord(1,:) obj%NodCoord(node_num+2,:)=box%NodCoord(2,:) obj%NodCoord(node_num+3,:)=box%NodCoord(3,:) obj%NodCoord(node_num+4,:)=box%NodCoord(4,:) obj%NodCoord(node_num+5,:)=box%NodCoord(5,:) obj%NodCoord(node_num+6,:)=box%NodCoord(6,:) obj%NodCoord(node_num+7,:)=box%NodCoord(7,:) obj%NodCoord(node_num+8,:)=box%NodCoord(8,:) do i=1,node_num ! Delauney triangulation for 2D print *, i,"/",size(obj%NodCoord,1)," :: ",dble(i)/dble(size(obj%NodCoord,1))*100,"% done." ! some bugs. call obj%DelauneygetNewNode3D(NodeID=i) print *, "Under debugging >> call obj%DelauneygetNewNode3D(NodeID=i)" if(i==1)then return endif enddo ! Remove outer box ! 最初に作った,全体を覆うスーパーボックスを取り除く ! 以上により,Delauney分割を完了する. print *, "Flipping algorithm is to be implemented." print *, "3D-Delaunay :: trial version. it may have some bugs." return else print *, "ERROR :: MeshClass :: MeshingMesh :: Dimension = ",dim_mode endif end subroutine !################################################## subroutine LaplacianMesh(obj,itr_tol) class(Mesh_),intent(inout) :: obj integer(int32),optional,intent(in) :: itr_tol integer(int32) :: i ,j, k, itr integer(int32),allocatable :: lapl_node(:),neighbornode(:) ! Laplacian method call obj%getSurface() lapl_node = int(zeros( size(obj%nodcoord,1) ) ) do i=1,size(obj%SurfaceLine2D) lapl_node( obj%SurfaceLine2D(i) ) = -1 enddo itr = input(default=10, option=itr_tol) do i=1,itr do j=1,size(lapl_node) if(lapl_node(j)==0 )then ! not boundary node => move node neighbornode = obj%getNeighboringNode(NodeId=j) obj%nodcoord(j,:) = 0.0d0 do k=1,size(neighbornode) obj%nodcoord( j ,:) =& obj%nodcoord( j ,:) + & 1.0d0/dble(size(neighbornode))*obj%nodcoord( neighbornode(k) ,:) enddo else cycle endif enddo enddo end subroutine !################################################## subroutine getCircumscribedCircleMesh(obj,centerx,centery,centerz,radius) class(Mesh_),intent(inout)::obj real(real64),intent(out)::centerx,centery,centerz,radius real(real64),allocatable::center(:) real(real64) :: dist integer(int32) ::i allocate(center( size(obj%NodCoord,2 ) ) ) ! get center corrdinate do i=1,size(center) center(i)=mean(obj%NodCoord(:,i) ) enddo ! get radius radius =0.0d0 do i=1,size(obj%NodCoord,1) dist=distance(obj%NodCoord(i,:),center) if(dist >= radius)then radius=dist else cycle endif enddo centerz=0.0d0 centerx=center(1) if(size(center)>=2 )then centery=center(2) endif if(size(center)>=3 )then centerz=center(3) endif end subroutine !################################################## function getElementMesh(obj,ElementID) result(element) class(Mesh_),intent(in) :: obj type(Mesh_) :: element integer(int32),intent(in) :: ElementID integer(int32) :: i,j,n,m n = size(obj%nodcoord,2) m = size(obj%elemnod,2) allocate(element%nodcoord(m,n) ) allocate(element%elemnod(1,m) ) do i=1,m element%nodcoord(i,:) = obj%nodcoord(obj%elemnod(ElementID,i),:) element%elemnod(1,i) = i enddo end function !################################################## subroutine getCircumscribedSphereOfTetraMesh(obj,center,radius) class(Mesh_),intent(in)::obj real(real64),intent(inout) :: center(3), radius real(real64) ::i, Matrix(3,3),N1(3),N2(3),N3(3),& a1(3),a2(3),a3(3),a4(3),M13(3),M14(3),M24(3),M12(3),p(3),Matrix_Inv(3,3) a1(:) = obj%nodcoord(1,:) a2(:) = obj%nodcoord(2,:) a3(:) = obj%nodcoord(3,:) a4(:) = obj%nodcoord(4,:) M13 = 0.50d0*a1 + 0.50d0*a3 M14 = 0.50d0*a1 + 0.50d0*a4 M12 = 0.50d0*a1 + 0.50d0*a2 N1 = a1 - M13 N2 = a1 - M14 N3 = a1 - M12 p(1) = dot_product(M13,N1) p(2) = dot_product(M14,N2) p(3) = dot_product(M12,N3) Matrix(1,:) = N1(:) Matrix(2,:) = N2(:) Matrix(3,:) = N3(:) Matrix_Inv = inverse(Matrix) center = matmul(Matrix_Inv,p) radius = sqrt(dot_product(center-a1,center-a1) ) end subroutine !################################################## subroutine getCircumscribedSphereMesh(obj,centerx,centery,centerz,radius) class(Mesh_),intent(inout)::obj real(real64),intent(out)::centerx,centery,centerz,radius real(real64),allocatable::center(:) real(real64) :: dist integer(int32) ::i allocate(center( 3 ) ) ! get center corrdinate do i=1,size(center) center(i)=mean(obj%NodCoord(:,i) ) enddo ! get radius radius =0.0d0 do i=1,size(obj%NodCoord,1) dist=distance(obj%NodCoord(i,:),center) if(dist >= radius)then radius=dist else cycle endif enddo centerx=center(1) centery=center(2) centerz=center(3) end subroutine !################################################## !################################################## subroutine getCircumscribedTriangleMesh(obj,triangle) class(Mesh_),intent(inout)::obj real(real64),allocatable :: center(:) real(real64),allocatable,intent(out) :: triangle(:,:) real(real64) :: centerx,centery,centerz,radius,pi integer(int32) :: i pi=3.1415926d0 allocate(triangle(3,size(obj%NodCoord,2) )) allocate(center(size(obj%NodCoord,2) )) call obj%getCircumscribedCircle(centerx,centery,centerz,radius) radius=radius*(1.20d0) center(1)=centerx center(2)=centery triangle(1,1)=center(1)+2.0d0*radius*cos(0.0d0); triangle(1,2)=center(2)+2.0d0*radius*sin(0.0d0) triangle(2,1)=center(1)+2.0d0*radius*cos(2.0d0*pi/3.0d0); triangle(2,2)=center(2)+2.0d0*radius*sin(2.0d0*pi/3.0d0) triangle(3,1)=center(1)+2.0d0*radius*cos(-2.0d0*pi/3.0d0); triangle(3,2)=center(2)+2.0d0*radius*sin(-2.0d0*pi/3.0d0) if(size(center)==3 )then center(3)=centerz triangle(:,3)=0.0d0 endif end subroutine !################################################## !################################################## subroutine getCircumscribedBoxMesh(obj,Box) class(Mesh_),intent(inout)::obj type(Mesh_),intent(inout) :: box real(real64),allocatable :: center(:) real(real64) :: centerx,centery,centerz,radius,pi integer(int32) :: i pi=3.1415926d0 allocate(Box%nodcoord(8,3 )) allocate(Box%elemnod(5,4)) allocate(center(3)) call obj%getCircumscribedSphere(centerx,centery,centerz,radius) radius=radius*(1.20d0) center(1)=centerx center(2)=centery center(3)=centerz Box%nodcoord(1,1)=centerx - radius ; Box%nodcoord(1,2)=centery - radius ; Box%nodcoord(1,3)=centerz - radius ; Box%nodcoord(2,1)=centerx + radius ; Box%nodcoord(2,2)=centery - radius ; Box%nodcoord(2,3)=centerz - radius ; Box%nodcoord(3,1)=centerx + radius ; Box%nodcoord(3,2)=centery + radius ; Box%nodcoord(3,3)=centerz - radius ; Box%nodcoord(4,1)=centerx - radius ; Box%nodcoord(4,2)=centery + radius ; Box%nodcoord(4,3)=centerz - radius ; Box%nodcoord(5,1)=centerx - radius ; Box%nodcoord(5,2)=centery - radius ; Box%nodcoord(5,3)=centerz + radius ; Box%nodcoord(6,1)=centerx + radius ; Box%nodcoord(6,2)=centery - radius ; Box%nodcoord(6,3)=centerz + radius ; Box%nodcoord(7,1)=centerx + radius ; Box%nodcoord(7,2)=centery + radius ; Box%nodcoord(7,3)=centerz + radius ; Box%nodcoord(8,1)=centerx - radius ; Box%nodcoord(8,2)=centery + radius ; Box%nodcoord(8,3)=centerz + radius ; ! Element-Node connectivity Box%elemnod(1,1)=1;Box%elemnod(1,2)=2;Box%elemnod(1,3)=4;Box%elemnod(1,4)=5; Box%elemnod(2,1)=2;Box%elemnod(2,2)=3;Box%elemnod(2,3)=4;Box%elemnod(2,4)=7; Box%elemnod(3,1)=5;Box%elemnod(3,2)=2;Box%elemnod(3,3)=7;Box%elemnod(3,4)=6; Box%elemnod(4,1)=5;Box%elemnod(4,2)=7;Box%elemnod(4,3)=4;Box%elemnod(4,4)=8; Box%elemnod(5,1)=2;Box%elemnod(5,2)=7;Box%elemnod(5,3)=4;Box%elemnod(5,4)=5; end subroutine !################################################## subroutine DelauneygetNewNode3DMesh(obj,NodeID) class(Mesh_),intent(inout)::obj type(Mesh_) :: element integer(int32),intent(in) :: NodeID integer(int32) :: ElementID, ElemNum,i,itr,newElemID,j,currentID integer(int32),allocatable :: element_id_list(:),elemnod(:,:),& staged_element(:),newElem(:,:),facetNodeID(:,:),staged_facet_id(:) real(real64) :: x,y,z,radius,coord(3),center(3),dist,surf(3) type(IO_) :: f call f%open("debug.txt","w") x = obj%nodcoord(nodeid,1) y = obj%nodcoord(nodeid,2) z = obj%nodcoord(nodeid,3) coord(:) = obj%nodcoord(nodeid,:) ! search element which contains the node ElementID = -1 do i=1, size(obj%ElemNod) if(obj%InsideOfElement(ElementID=i,x=x,y=y,z=z ) )then ElementID = i currentID = i exit else cycle endif enddo if(ElementID <=0)then print *, "ERROR ::DelauneygetNewNode3DMesh >> invalid nodal coordinate. " return endif ! flipping algorithm ! #1 check outer sphere for all neighbor elements ! ElementIDについて,接する全ての要素を探す element_id_list = obj%getNeighboringElement(ElementID,withSurfaceID=.true.,Interfaces=staged_facet_id) do i=1,size(element_id_list)/2 element = obj%getElement(ElementID=element_id_list(i)) call element%getCircumscribedSphereOfTetra(center,radius) dist = sqrt(dot_product(center-coord,center-coord) ) if(dist <= radius)then if(.not.allocated(staged_element) )then staged_element = int(zeros(1) ) staged_element(1) = ElementID endif call ExtendArrayIntVec(mat=staged_element) staged_element(size(staged_element) ) = element_id_list(i) else cycle endif enddo ! add elements in staged_elements i = 4-sum(staged_facet_id) allocate(newElem(sizE(staged_element)/2*3 + i ,4 ) ) newElemID = 0 do i=1, size(staged_element)/2 facetNodeID = obj%getFacetNodeID(ElementID=(staged_element(i) ) ) if( .not. allocated(facetNodeID) ) cycle if( size(facetNodeID)==0 ) cycle do j=1,4 if( i + size(staged_element)/2 == j )then ! facet of original tetra cycle else newElemID = newElemID + 1 newElem(newElemID,1) = facetNodeID(j,3) newElem(newElemID,2) = facetNodeID(j,2) newElem(newElemID,3) = facetNodeID(j,1) newElem(newElemID,4) = NodeID endif enddo enddo facetNodeID = obj%getFacetNodeID(ElementID=currentID) call print(obj%elemnod(currentID,:) ) call print(" ") call print(facetNodeID) call print(" ") call print(newElem) do i=1,sizE(staged_facet_id) if(staged_facet_id(i)==1 )then cycle else newElemID = newElemID + 1 newElem(newElemID,1) = facetNodeID(i,3) newElem(newElemID,2) = facetNodeID(i,2) newElem(newElemID,3) = facetNodeID(i,1) newElem(newElemID,4) = NodeID endif enddo call print(" ") call print(newElem) ! add elements call obj%addElements(connectivity = newElem) j = sizE(staged_element)/2 call obj%removeElements(ElementIDs = staged_element(1:j) ) ! remove staged_element(:) and create new elements end subroutine !################################################## subroutine DelauneygetNewNodeMesh(obj,node_id,staged_node,triangle,box) class(Mesh_),intent(inout)::obj type(Mesh_),optional,intent(in) :: box integer(int32),optional,intent(in) :: node_id integer(int32),optional,intent(inout):: staged_node(:) ! if =1,staged. real(real64),optional,intent(inout) :: triangle(:,:) real(real64) :: avec(3),bvec(3),cvec(3),s,t integer(int32) :: triangle_node_id(3),new_node_id,i,j,n,point,cover_triangle if(size(obj%nodcoord,2)==3 .and. present(Node_id) )then call obj%DelauneygetNewNode3D(NodeID=node_id) return endif ! add NewNode staged_node(node_id)=1 ! if i==1, create 3 triangle if(node_id==1)then triangle_node_id(1)=size(obj%NodCoord,1)+1-3 triangle_node_id(2)=size(obj%NodCoord,1)+2-3 triangle_node_id(3)=size(obj%NodCoord,1)+3-3 new_node_id=1 call obj%DelauneygetNewTriangle(triangle_node_id,new_node_id) else ! detect cover triangle do i=1,size(obj%ElemNod,1) if(obj%ElemNod(i,1)<1 )then cycle else point = 0 ! detect in-out avec(:)=0.0d0 bvec(:)=0.0d0 avec(1:2) = obj%NodCoord(obj%ElemNod(i,2),1:2 )-& obj%NodCoord(obj%ElemNod(i,1),1:2 ) bvec(1:2) = obj%NodCoord(obj%ElemNod(i,3),1:2 )-& obj%NodCoord(obj%ElemNod(i,1),1:2 ) cvec(1:2) = obj%NodCoord(node_id,1:2 )-& obj%NodCoord(obj%ElemNod(i,1),1:2 ) if( (bvec(1)*avec(2)-bvec(2)*avec(1)) ==0.0d0)then cycle endif s = (avec(2)*cvec(1)-avec(1)*cvec(2))/(bvec(1)*avec(2)-bvec(2)*avec(1)) t = (bvec(2)*cvec(1)-bvec(1)*cvec(2))/(avec(1)*bvec(2)-avec(2)*bvec(1)) !print *, "s,t=",s,t if(0.0d0 <= s .and. s<=1.0d0 )then if(0.0d0 <= t .and. t<=1.0d0 )then ! hit! point = point+1 else cycle endif else cycle endif ! detect in-out avec(:)=0.0d0 bvec(:)=0.0d0 avec(1:2) = obj%NodCoord(obj%ElemNod(i,1),1:2 )-& obj%NodCoord(obj%ElemNod(i,2),1:2 ) bvec(1:2) = obj%NodCoord(obj%ElemNod(i,3),1:2 )-& obj%NodCoord(obj%ElemNod(i,2),1:2 ) cvec(1:2) = obj%NodCoord(node_id,1:2 )-& obj%NodCoord(obj%ElemNod(i,2),1:2 ) s = (avec(2)*cvec(1)-avec(1)*cvec(2))/(bvec(1)*avec(2)-bvec(2)*avec(1)) t = (bvec(2)*cvec(1)-bvec(1)*cvec(2))/(avec(1)*bvec(2)-avec(2)*bvec(1)) !print *, "s,t=",s,t if(0.0d0 <= s .and. s<=1.0d0 )then if(0.0d0 <= t .and. t<=1.0d0 )then ! hit! point = point+1 else cycle endif else cycle endif ! detect in-out avec(:)=0.0d0 bvec(:)=0.0d0 avec(1:2) = obj%NodCoord(obj%ElemNod(i,1),1:2 )-& obj%NodCoord(obj%ElemNod(i,3),1:2 ) bvec(1:2) = obj%NodCoord(obj%ElemNod(i,2),1:2 )-& obj%NodCoord(obj%ElemNod(i,3),1:2 ) cvec(1:2) = obj%NodCoord(node_id,1:2 )-& obj%NodCoord(obj%ElemNod(i,3),1:2 ) s = (avec(2)*cvec(1)-avec(1)*cvec(2))/(bvec(1)*avec(2)-bvec(2)*avec(1)) t = (bvec(2)*cvec(1)-bvec(1)*cvec(2))/(avec(1)*bvec(2)-avec(2)*bvec(1)) !print *, "s,t=",s,t if(0.0d0 <= s .and. s<=1.0d0 )then if(0.0d0 <= t .and. t<=1.0d0 )then ! hit! point = point+1 else cycle endif else cycle endif if(point==3)then triangle_node_id(1)=obj%ElemNod(i,1) triangle_node_id(2)=obj%ElemNod(i,2) triangle_node_id(3)=obj%ElemNod(i,3) cover_triangle=i !print *, "hit!" endif endif enddo new_node_id=node_id call obj%DelauneygetNewTriangle(triangle_node_id,new_node_id) !print *, "deleted triangle id =",cover_triangle-1 call removeArray(obj%ElemNod,remove1stColumn=.true.,NextOf=cover_triangle-1) endif ! if staged_node(k)=1, it is staged. end subroutine !################################################## !################################################## subroutine DelauneygetNewTriangleMesh(obj,triangle_node_id,new_node_id) class(Mesh_),intent(inout)::obj integer(int32),intent(in)::triangle_node_id(:),new_node_id integer(int32) :: last_elem_id,i last_elem_id=0 do i=1,size(obj%ElemNod,1) if(obj%ElemNod(i,1) >= 1)then last_elem_id=last_elem_id+1 else exit endif enddo !print *, "last_elem_id",last_elem_id ! current Element id = last_elem_id+1 obj%ElemNod(last_elem_id+1,1)=triangle_node_id(1) obj%ElemNod(last_elem_id+1,2)=triangle_node_id(2) obj%ElemNod(last_elem_id+1,3)=new_node_id obj%ElemNod(last_elem_id+2,1)=triangle_node_id(2) obj%ElemNod(last_elem_id+2,2)=triangle_node_id(3) obj%ElemNod(last_elem_id+2,3)=new_node_id obj%ElemNod(last_elem_id+3,1)=triangle_node_id(3) obj%ElemNod(last_elem_id+3,2)=triangle_node_id(1) obj%ElemNod(last_elem_id+3,3)=new_node_id end subroutine !################################################## !################################################## subroutine DelauneyremoveOverlapsMesh(obj,step,NoChange) class(Mesh_),intent(inout)::obj type(Point_)::p1,p2,p3 type(Triangle_)::t1 type(Circle_)::c1 integer(int32),optional,intent(in) ::step logical,optional,intent(inout) :: NoChange real(real64) :: center(2),a(2),b(2),c(2),node(2) real(real64) :: x1,y1,x2,y2,x3,y3,radius,dist_tr integer(int32) :: i,j,n,k,l,nodeid_1,nodeid_2,nodeid_tr_1,nodeid_tr_2,point(3) integer(int32) :: elem_id, node_tr,nodeid_3,dot_1,count_num,countin,flip_node integer(int32) :: old_triangle_id_2,old_triangle_id_1,far_node,far_node_loc,rhs_node,lhs_node integer(int32) :: far_node_tr,far_node_loc_tr,k_1,k_2 count_num=0 NoChange = .False. ! Fliping for a time do i=1,size(obj%ElemNod,1) if(obj%ElemNod(i,1)<1 )then cycle endif ! 外心を計算する a(1:2)=obj%NodCoord( obj%ElemNod(i,1),1:2 ) b(1:2)=obj%NodCoord( obj%ElemNod(i,2),1:2 ) c(1:2)=obj%NodCoord( obj%ElemNod(i,3),1:2 ) call p1%init(dim=2) call p2%init(dim=2) call p3%init(dim=2) call p1%set(x=a(1),y=a(2) ) call p2%set(x=b(1),y=b(2) ) call p3%set(x=c(1),y=c(2) ) call t1%init(dim=2) call t1%setNode(point=p1,order=1) call t1%setNode(point=p2,order=2) call t1%setNode(point=p3,order=3) call t1%getCircle(type_of_circle="circumcenter",circle=c1) !print *, "c1%radius",c1%radius,c1%center ! 外心を計算する → 内外判定へ! ! from i th triangle to the last triangle countin=0 do j=i,size(obj%ElemNod,1) if(i==j)then cycle endif if(minval((obj%ElemNod(j,1:3) ))<=0 )then cycle endif !print *, "same node::",countifsame(obj%ElemNod(i,1:3) ,obj%ElemNod(j,1:3)) if(countifsame(obj%ElemNod(i,1:3) ,obj%ElemNod(j,1:3)) /=2 )then cycle endif do k=1,3 dist_tr=distance(c1%center(1:2),obj%NodCoord(obj%ElemNod(j,k),1:2 ) ) if(k==1)then k_1 = 2 k_2 = 3 elseif(k==2)then k_1 = 3 k_2 = 1 else k_1 = 1 k_2 = 2 endif if(dist_tr < c1%radius)then ! inside !print *, "inside" countin=countin+1 ! FLIP at HERE ! Triangles are generated anti-clockwize flip_node=obj%ElemNod(j,k) old_triangle_id_1=i old_triangle_id_2=j ! farhest node id : (1, 2 or 3) far_node_loc = 1 if( obj%ElemNod(j,k_1)==obj%ElemNod(old_triangle_id_1,2) .and. & obj%ElemNod(j,k_2)==obj%ElemNod(old_triangle_id_1,1) )then far_node = obj%ElemNod(i,3) lhs_node = obj%ElemNod(i,1) rhs_node = obj%ElemNod(i,2) elseif(obj%ElemNod(j,k_1)==obj%ElemNod(old_triangle_id_1,1) .and. & obj%ElemNod(j,k_2)==obj%ElemNod(old_triangle_id_1,3) )then far_node = obj%ElemNod(i,2) lhs_node = obj%ElemNod(i,3) rhs_node = obj%ElemNod(i,1) elseif( obj%ElemNod(j,k_1)==obj%ElemNod(old_triangle_id_1,3) .and. & obj%ElemNod(j,k_2)==obj%ElemNod(old_triangle_id_1,2) )then far_node = obj%ElemNod(i,1) lhs_node = obj%ElemNod(i,2) rhs_node = obj%ElemNod(i,3) else cycle endif !print *, "OLD :: ",obj%ElemNod(old_triangle_id_1,:),"|",obj%ElemNod(old_triangle_id_2,:) !open(134,file="before.txt",status="replace") !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_1,1),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_1,2),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_1,3),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_1,1),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_2,1),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_2,2),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_2,3),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_2,1),1:2) !close(134) obj%ElemNod(old_triangle_id_1,1)=flip_node obj%ElemNod(old_triangle_id_1,2)=far_node obj%ElemNod(old_triangle_id_1,3)=lhs_node obj%ElemNod(old_triangle_id_2,1)=flip_node obj%ElemNod(old_triangle_id_2,2)=rhs_node obj%ElemNod(old_triangle_id_2,3)=far_node ! (1) detect shared line ! (2) split shared line !print *, "NEW :: ",obj%ElemNod(old_triangle_id_1,:),"|",obj%ElemNod(old_triangle_id_2,:) !open(134,file="after.txt",status="replace") !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_1,1),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_1,2),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_1,3),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_1,1),1:2) ! !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_2,1),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_2,2),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_2,3),1:2) !write(134,*) obj%NodCoord(obj%ElemNod(old_triangle_id_2,1),1:2) !close(134) ! FLIP at HERE return else ! outside !print *, "outside" endif enddo enddo enddo NoChange = .true. !print *, "No flip-point is found." end subroutine !################################################## !################################################## subroutine RemoveFailedTriangleMesh(obj) class(Mesh_),intent(inout)::obj type(Point_)::p1,p2,p3 type(Triangle_)::t1 type(Circle_)::c1 integer(int32) :: i,j,n,remove,k ! remove non-triangle element print *, "debug flag0" n=size(obj%ElemNod,1) do i=n,1,-1 if(obj%ElemNod(i,1)<=0 )then print *, i call removeArray(obj%ElemNod,remove1stColumn=.true.,NextOf=i-1) else cycle !if(obj%ElemNod(i,1) == obj%ElemNod(i,2))then ! call removeArray(obj%ElemNod,remove1stColumn=.true.,NextOf=i-1) !elseif(obj%ElemNod(i,2) == obj%ElemNod(i,3))then ! call removeArray(obj%ElemNod,remove1stColumn=.true.,NextOf=i-1) !elseif(obj%ElemNod(i,3) == obj%ElemNod(i,1))then ! call removeArray(obj%ElemNod,remove1stColumn=.true.,NextOf=i-1) !else ! cycle !endif endif enddo print *, "debug flag1" ! remove overlapped triangle n=size(obj%ElemNod,1) k=1 do i=1,n remove=( obj%ElemNod(k,1)-obj%ElemNod(k,2) )*& ( obj%ElemNod(k,2)-obj%ElemNod(k,3) )*& ( obj%ElemNod(k,3)-obj%ElemNod(k,1) ) if( remove==0 )then call removeArray(obj%ElemNod,remove1stColumn=.true.,NextOf=k-1) else k=k+1 cycle endif enddo print *, "debug flag2" n=size(obj%ElemNod,1) do i=1,n do j=1,i-1 remove=countifsame(obj%ElemNod(i,1:3),obj%ElemNod(j,1:3) ) !print *, "remove2 =",remove if(remove>=3 )then call removeArray(obj%ElemNod,remove1stColumn=.true.,NextOf=j-1) else cycle endif enddo enddo print *, "debug flag3" end subroutine !################################################## !################################################## subroutine removeCircumscribedTriangleMesh(obj) class(Mesh_),intent(inout)::obj integer(int32) :: i,j,k,l,n,tri_nodes(3),rmn do i=1,3 tri_nodes(i)=size(obj%NodCoord,1) call removeArray(obj%NodCoord,remove1stColumn=.true.,NextOf=size(obj%NodCoord,1)-1 ) enddo rmn=0 n=size(obj%ElemNod,1) l=1 do i=1,n k=countifsame(tri_nodes(1:3), obj%ElemNod(l,1:3) ) !print *, k if(k/=0)then ! exist rmn=rmn+1 call removeArray(obj%ElemNod,remove1stColumn=.true.,NextOf=l-1 ) else l=l+1 cycle endif enddo print *, rmn," elements are successfully removed." return end subroutine !################################################## !################################################## function GetElemTypeMesh(obj) result(ElemType) class(Mesh_),intent(in)::obj type(ShapeFunction_)::sobj character*200 :: ElemType integer(int32) :: i,j,n,m n=size(obj%NodCoord,2) m=size(obj%ElemNod,2) call sobj%getType(NumOfDim=n,NumOfNodePerElem=m) ElemType=sobj%ElemType return end function !################################################## !################################################## function getShapeFunctionMesh(obj, ElementID,GaussPointID,ReducedIntegration) result(sobj) class(Mesh_),intent(inout)::obj integer(int32),intent(in) :: GaussPointID, ElementID logical,optional,intent(in) :: ReducedIntegration type(ShapeFunction_)::sobj character*200 :: ElemType integer(int32) :: i,j,n,m,gpid,elemID gpid = GaussPointID elemid = ElementID n=size(obj%NodCoord,2) m=size(obj%ElemNod,2) sobj%ReducedIntegration = input(default=.false.,option=ReducedIntegration) call sobj%getType(NumOfDim=n,NumOfNodePerElem=m) ! get shape functions call SetShapeFuncType(sobj) call getAllShapeFunc(sobj,elem_id=elemid,nod_coord=obj%NodCoord,elem_nod=obj%ElemNod,OptionalGpID=gpid) end function !################################################## !################################################## subroutine ConvertMeshTypeMesh(obj,Option) class(Mesh_),intent(inout) :: obj character(*),intent(in) :: Option if(Option=="TetraToHexa" .or. Option=="TetraToHex")then call obj%convertTetraToHexa() elseif(Option=="convertTriangleToRectangular" .or. Option=="TriangleToRectangule")then call obj%convertTriangleToRectangular() else print *, "Option :: ",Option,"is not valid, what if TetraToHexa ?" endif end subroutine !################################################## !################################################## subroutine convertTetraToHexaMesh(obj) class(Mesh_),intent(inout) :: obj integer(int32) :: i,node_num,elem_num,elemnod_num,incre_nod_num real(real64) :: incre_nod_num_real,x1(3),x2(3),x3(3),x4(3) real(real64) :: x12(3),x23(3),x31(3),x14(3),x24(3),x34(3) real(real64) :: x123(3),x234(3),x134(3),x124(3) real(real64) :: x1234(3),direct integer(int32),allocatable :: HexElemNod(:,:) real(real64),allocatable ::HexNodCoord(:,:) integer(int32) :: local_id(15),node_id ! converter for 3D node_num = size(obj%NodCoord,1) elem_num = size(obj%ElemNod,1) elemnod_num = size(obj%ElemNod,2) incre_nod_num=(4+6+1)*elem_num allocate(HexElemNod( elem_num*4,8) ) allocate(HexNodCoord(node_num+incre_nod_num,3) ) HexNodCoord(1:node_num,1:3) = obj%NodCoord(1:node_num,1:3) ! increase ElemNod (connectivity) node_id=node_num do i=1, elem_num ! for each element node_id=node_id x1(:) = obj%NodCoord( obj%ElemNod(i,1) ,:) ! #1 x2(:) = obj%NodCoord( obj%ElemNod(i,2) ,:) ! #2 x3(:) = obj%NodCoord( obj%ElemNod(i,3) ,:) ! #3 x4(:) = obj%NodCoord( obj%ElemNod(i,4) ,:) ! #4 ! check order !direct=dot_product(cross_product(x2-x1,x3-x1),x4-x1) !if(direct<=0.0d0)then ! print *, "Elemid = ",i,"is invalid",direct ! stop "debug" !else ! print *, "Elemid = ",i,"is ok",direct !endif x12(:)= 0.50d0*x1(:) + 0.50d0*x2(:) ! #5 x23(:)= 0.50d0*x2(:) + 0.50d0*x3(:) ! #6 x31(:)= 0.50d0*x3(:) + 0.50d0*x1(:) ! #7 x14(:)= 0.50d0*x1(:) + 0.50d0*x4(:) ! #8 x24(:)= 0.50d0*x2(:) + 0.50d0*x4(:) ! #9 x34(:)= 0.50d0*x3(:) + 0.50d0*x4(:) ! #10 x123(:) = 1.0d0/3.0d0*x1(:)+1.0d0/3.0d0*x2(:)+1.0d0/3.0d0*x3(:) ! #11 x234(:) = 1.0d0/3.0d0*x2(:)+1.0d0/3.0d0*x3(:)+1.0d0/3.0d0*x4(:) ! #12 x134(:) = 1.0d0/3.0d0*x1(:)+1.0d0/3.0d0*x3(:)+1.0d0/3.0d0*x4(:) ! #13 x124(:) = 1.0d0/3.0d0*x1(:)+1.0d0/3.0d0*x2(:)+1.0d0/3.0d0*x4(:) ! #14 x1234(:)=x1(:)+x2(:)+x3(:)+x4(:) x1234(:)=0.250d0*x1234(:) ! #15 local_id( 1) = obj%ElemNod(i,1) local_id( 2) = obj%ElemNod(i,2) local_id( 3) = obj%ElemNod(i,3) local_id( 4) = obj%ElemNod(i,4) local_id( 5) = node_id+ 1 local_id( 6) = node_id+ 2 local_id( 7) = node_id+ 3 local_id( 8) = node_id+ 4 local_id( 9) = node_id+ 5 local_id(10) = node_id+ 6 local_id(11) = node_id+ 7 local_id(12) = node_id+ 8 local_id(13) = node_id+ 9 local_id(14) = node_id+10 local_id(15) = node_id+11 node_id = node_id + 1 HexNodCoord(node_id,1:3) = x12(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x23(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x31(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x14(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x24(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x34(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x123(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x234(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x134(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x124(:) node_id = node_id + 1 HexNodCoord(node_id,1:3) = x1234(:) ! assemble new element HexElemNod( (i-1)*4 + 1,1) = local_id(1 ) HexElemNod( (i-1)*4 + 1,2) = local_id(5 ) HexElemNod( (i-1)*4 + 1,3) = local_id(11) HexElemNod( (i-1)*4 + 1,4) = local_id(7 ) HexElemNod( (i-1)*4 + 1,5) = local_id(8 ) HexElemNod( (i-1)*4 + 1,6) = local_id(14) HexElemNod( (i-1)*4 + 1,7) = local_id(15) HexElemNod( (i-1)*4 + 1,8) = local_id(13) HexElemNod( (i-1)*4 + 2,1) = local_id(5 ) HexElemNod( (i-1)*4 + 2,2) = local_id(2 ) HexElemNod( (i-1)*4 + 2,3) = local_id(6 ) HexElemNod( (i-1)*4 + 2,4) = local_id(11 ) HexElemNod( (i-1)*4 + 2,5) = local_id(14 ) HexElemNod( (i-1)*4 + 2,6) = local_id(9 ) HexElemNod( (i-1)*4 + 2,7) = local_id(12 ) HexElemNod( (i-1)*4 + 2,8) = local_id(15 ) HexElemNod( (i-1)*4 + 3,1) = local_id(6 ) HexElemNod( (i-1)*4 + 3,2) = local_id(3 ) HexElemNod( (i-1)*4 + 3,3) = local_id(7 ) HexElemNod( (i-1)*4 + 3,4) = local_id(11 ) HexElemNod( (i-1)*4 + 3,5) = local_id(15 ) HexElemNod( (i-1)*4 + 3,6) = local_id(12 ) HexElemNod( (i-1)*4 + 3,7) = local_id(10 ) HexElemNod( (i-1)*4 + 3,8) = local_id(13 ) HexElemNod( (i-1)*4 + 4,1) = local_id(8 ) HexElemNod( (i-1)*4 + 4,2) = local_id(14 ) HexElemNod( (i-1)*4 + 4,3) = local_id(15 ) HexElemNod( (i-1)*4 + 4,4) = local_id(13 ) HexElemNod( (i-1)*4 + 4,5) = local_id(4 ) HexElemNod( (i-1)*4 + 4,6) = local_id(9 ) HexElemNod( (i-1)*4 + 4,7) = local_id(12 ) HexElemNod( (i-1)*4 + 4,8) = local_id(10 ) enddo deallocate(obj%NodCoord) deallocate(obj%ElemNod) allocate(obj%NodCoord(size(HexNodCoord,1),size(HexNodCoord,2) ) ) allocate(obj%ElemNod(size(HexElemNod,1) ,size(HexElemNod,2) )) obj%NodCoord(:,:)=HexNodCoord(:,:) obj%ElemNod =HexElemNod(:,:) ! done, but overlaps exists call obj%removeOverlappedNode() end subroutine !################################################## !################################################## subroutine convertTriangleToRectangularMesh(obj) class(Mesh_),intent(inout) :: obj integer(int32) :: i,node_num,elem_num,elemnod_num,incre_nod_num real(real64) :: incre_nod_num_real,x1(2),x2(2),x3(2),x4(2) real(real64) :: x12(2),x23(2),x31(2) real(real64) :: x123(2) integer(int32),allocatable :: RectElemNod(:,:),before_after(:) real(real64),allocatable :: RectNodCoord(:,:) integer(int32) :: local_id(7),node_id ! converter for 3D node_num = size(obj%NodCoord,1) elem_num = size(obj%ElemNod,1) elemnod_num = size(obj%ElemNod,2) incre_nod_num=(4)*elem_num print *, "Triangle mesh to rectangular mesh" allocate(RectElemNod( elem_num*3,4) ) allocate(RectNodCoord(node_num+incre_nod_num,2) ) RectNodCoord(1:node_num,1:2) = obj%NodCoord(1:node_num,1:2) ! increase ElemNod (connectivity) node_id=node_num do i=1, elem_num ! for each element node_id=node_id x1(1:2) = obj%NodCoord( obj%ElemNod(i,1) ,1:2) ! #1 x2(1:2) = obj%NodCoord( obj%ElemNod(i,2) ,1:2) ! #2 x3(1:2) = obj%NodCoord( obj%ElemNod(i,3) ,1:2) ! #3 x12(1:2)= 0.50d0*x1(1:2) + 0.50d0*x2(1:2) ! #4 x23(1:2)= 0.50d0*x2(1:2) + 0.50d0*x3(1:2) ! #5 x31(1:2)= 0.50d0*x3(1:2) + 0.50d0*x1(1:2) ! #6 x123(:)=x1(:)+x2(:)+x3(:) x123(:)=1.0d0/3.0d0*x123(:) ! #7 local_id( 1) = obj%ElemNod(i,1) local_id( 2) = obj%ElemNod(i,2) local_id( 3) = obj%ElemNod(i,3) local_id( 4) = node_id+ 1 local_id( 5) = node_id+ 2 local_id( 6) = node_id+ 3 local_id( 7) = node_id+ 4 node_id = node_id + 1 RectNodCoord(node_id,1:2) = x12(:) node_id = node_id + 1 RectNodCoord(node_id,1:2) = x23(:) node_id = node_id + 1 RectNodCoord(node_id,1:2) = x31(:) node_id = node_id + 1 RectNodCoord(node_id,1:2) = x123(:) ! assemble new element RectElemNod( (i-1)*3 + 1,1) = local_id(1 ) RectElemNod( (i-1)*3 + 1,2) = local_id(4 ) RectElemNod( (i-1)*3 + 1,3) = local_id(7) RectElemNod( (i-1)*3 + 1,4) = local_id(6 ) RectElemNod( (i-1)*3 + 2,1) = local_id(4 ) RectElemNod( (i-1)*3 + 2,2) = local_id(2 ) RectElemNod( (i-1)*3 + 2,3) = local_id(5 ) RectElemNod( (i-1)*3 + 2,4) = local_id(7 ) RectElemNod( (i-1)*3 + 3,1) = local_id(5 ) RectElemNod( (i-1)*3 + 3,2) = local_id(3 ) RectElemNod( (i-1)*3 + 3,3) = local_id(6 ) RectElemNod( (i-1)*3 + 3,4) = local_id(7 ) enddo deallocate(obj%NodCoord) deallocate(obj%ElemNod) allocate(obj%NodCoord(size(RectNodCoord,1),size(RectNodCoord,2) ) ) allocate(obj%ElemNod(size(RectElemNod,1) ,size(RectElemNod,2) )) obj%NodCoord(:,:)=RectNodCoord(:,:) obj%ElemNod =RectElemNod(:,:) ! done, but overlaps exists call obj%removeOverlappedNode() end subroutine !################################################## !################################################## subroutine removeOverlappedNodeMesh(obj,tolerance) class(Mesh_),intent(inout)::obj real(real64),optional,intent(in) :: tolerance integer(int32),allocatable :: RectElemNod(:,:),checked(:),before_after(:) real(real64),allocatable :: New_NodCoord(:,:) integer(int32) :: i,j,k,dim_num,node_num,itr,elem_num,elemnod_num,l real(real64),allocatable :: x(:),x_tr(:) real(real64) :: error,tol if(present(tolerance) )then tol=tolerance else tol=1.0e-16 endif dim_num=size(obj%NodCoord,2) node_num=size(obj%NodCoord,1) elem_num=size(obj%ElemNod,1) elemnod_num=size(obj%ElemNod,2) allocate( x(dim_num),x_tr(dim_num),checked(node_num ) ) allocate(before_after(size(checked) ) ) do i=1,node_num before_after(i)=i enddo checked(:)=0 itr=0 do i=1,node_num-1 ! if already checked if(checked(i)>=1 )then cycle endif ! check about ith node x(:)=obj%NodCoord(i,:) do k=i+1,node_num ! if already checked if(checked(k)>=1 )then cycle endif x_tr(:)=obj%NodCoord(k,:) error = dot_product(x(:) -x_tr(:),x(:)-x_tr(:) ) if(error < tol)then ! node id i and node id k are the same node ! use smaller id checked(k)=checked(k)+1 before_after(k)=i else cycle endif enddo enddo k=0 do i=1,size(checked) if(checked(i)>=1 )then cycle else k=k+1 l=before_after(i) before_after(i)=k do j=i+1,node_num if(before_after(j)==l )then before_after(j)=k endif enddo endif enddo allocate(New_NodCoord(k,dim_num ) ) ! fix numbers do i=1,elem_num do j=1,elemnod_num obj%ElemNod(i,j)=before_after( obj%ElemNod(i,j) ) enddo enddo ! then remove node_id==k check(k)==1 k=0 do i=1,node_num if(checked(i)>=1 )then cycle else k=k+1 New_NodCoord(k,:)=obj%NodCoord(i,:) endif enddo deallocate(obj%NodCoord) allocate(obj%NodCoord( size(New_NodCoord,1), size(New_NodCoord,2) ) ) obj%NodCoord(:,:)=New_NodCoord(:,:) end subroutine !################################################## !################################################## subroutine AdjustSphereMesh(obj,rx,ry,rz,debug) class(Mesh_),intent(inout) :: obj type(Mesh_) :: mesh real(real64) :: o(3),rate,x_cur(3),x_pres(3) real(real64),optional,intent(in) :: rx,ry,rz real(real64) :: r_x,r_y,r_z,dist,r_tr(3) integer(int32) :: i,ii,j,k,n,node_id,itr integer(int32),allocatable :: elem(:) logical,optional,intent(in) :: debug n=size(obj%ElemNod,1) call mesh%copy(obj) itr=0 do itr=itr+1 o(1)=minval(mesh%NodCoord(:,1))+maxval(mesh%NodCoord(:,1)) o(2)=minval(mesh%NodCoord(:,2))+maxval(mesh%NodCoord(:,2)) o(3)=minval(mesh%NodCoord(:,3))+maxval(mesh%NodCoord(:,3)) o(:)=0.50d0*o(:) if(allocated(elem) )then deallocate(elem) endif n=size(mesh%ElemNod,1) if(present(debug) )then print *, "itr :",itr,"Number of element",n endif if(n==0)then exit endif allocate(elem(n) ) elem(:)=1 call mesh%getSurface() do i=1,size(mesh%FacetElemNod,1) do j=1,size(mesh%FacetElemNod,2) node_id=mesh%FacetElemNod(i,j) if(i==1 .and. j==1)then r_x=0.50d0*(mesh%NodCoord(node_id,1) - o(1) ) r_y=0.50d0*(mesh%NodCoord(node_id,2) - o(2) ) r_z=0.50d0*(mesh%NodCoord(node_id,3) - o(3) ) cycle else r_tr(1)=0.50d0*(mesh%NodCoord(node_id,1) - o(1) ) r_tr(2)=0.50d0*(mesh%NodCoord(node_id,2) - o(2) ) r_tr(3)=0.50d0*(mesh%NodCoord(node_id,3) - o(3) ) endif if(r_x < r_tr(1))then r_x=r_tr(1) endif if(r_y < r_tr(2))then r_y=r_tr(2) endif if(r_z < r_tr(3))then r_z=r_tr(3) endif enddo enddo print *, r_x,r_y,r_z do i=1,size(mesh%FacetElemNod,1) do j=1,size(mesh%FacetElemNod,2) node_id=mesh%FacetElemNod(i,j) x_cur(1:3)=obj%NodCoord(node_id,1:3) dist=distance(x_cur,o) x_pres(1)=o(1)+ r_x/dist*(x_cur(1) - o(1) )*2.0d0 x_pres(2)=o(2)+ r_y/dist*(x_cur(2) - o(2) )*2.0d0 x_pres(3)=o(3)+ r_z/dist*(x_cur(3) - o(3) )*2.0d0 obj%NodCoord(node_id,1:3)=x_pres(1:3) enddo enddo ! remove facets elem(:)=1 do i=1,size(mesh%ElemNod,1) do ii=1,size(mesh%ElemNod,2) do j=1,size(mesh%FacetElemNod,1) do k=1,size(mesh%FacetElemNod,2) node_id=mesh%FacetElemNod(j,k) if(mesh%ElemNod(i,ii)==node_id )then elem(i)=0 exit endif enddo enddo enddo enddo if(minval(elem)==1 )then print *, "ERROR :: AdjustSphereMesh minval(elem)==1" stop endif if(maxval(elem)==0 )then print *, "converged" exit endif ! remove elems do i=size(elem),1,-1 if(elem(i)==0 )then call removeArray(mat=mesh%ElemNod,remove1stColumn=.true.,NextOf=i-1) endif enddo !call showArray(mat=mesh%NodCoord,IndexArray=mesh%ElemNod,& ! Name=trim(adjustl( fstring(itr) ))//".txt") enddo end subroutine AdjustSphereMesh !################################################## !################################################## subroutine AdjustCylinderMesh(obj,rx,ry,rz,debug) class(Mesh_),intent(inout) :: obj type(Mesh_) :: mesh real(real64) :: o(3),rate,x_cur(3),x_pres(3) real(real64),optional,intent(in) :: rx,ry,rz real(real64) :: r_x,r_y,r_z,dist,r_tr(3) integer(int32) :: i,ii,j,k,n,node_id,itr integer(int32),allocatable :: elem(:) logical,optional,intent(in) :: debug n=size(obj%ElemNod,1) call mesh%copy(obj) itr=0 do itr=itr+1 o(1)=minval(mesh%NodCoord(:,1))+maxval(mesh%NodCoord(:,1)) o(2)=minval(mesh%NodCoord(:,2))+maxval(mesh%NodCoord(:,2)) o(3)=minval(mesh%NodCoord(:,3))+maxval(mesh%NodCoord(:,3)) o(:)=0.50d0*o(:) if(allocated(elem) )then deallocate(elem) endif n=size(mesh%ElemNod,1) if(present(debug) )then print *, "itr :",itr,"Number of element",n endif if(n==0)then exit endif allocate(elem(n) ) elem(:)=1 call mesh%getSurface() do i=1,size(mesh%FacetElemNod,1) do j=1,size(mesh%FacetElemNod,2) node_id=mesh%FacetElemNod(i,j) if(i==1 .and. j==1)then r_x=0.50d0*(mesh%NodCoord(node_id,1) - o(1) ) r_y=0.50d0*(mesh%NodCoord(node_id,2) - o(2) ) r_z=0.50d0*(mesh%NodCoord(node_id,3) - o(3) ) cycle else r_tr(1)=0.50d0*(mesh%NodCoord(node_id,1) - o(1) ) r_tr(2)=0.50d0*(mesh%NodCoord(node_id,2) - o(2) ) r_tr(3)=0.50d0*(mesh%NodCoord(node_id,3) - o(3) ) endif if(r_x < r_tr(1))then r_x=r_tr(1) endif if(r_y < r_tr(2))then r_y=r_tr(2) endif if(r_z < r_tr(3))then r_z=r_tr(3) endif enddo enddo do i=1,size(mesh%FacetElemNod,1) do j=1,size(mesh%FacetElemNod,2) node_id=mesh%FacetElemNod(i,j) x_cur(1:3)=obj%NodCoord(node_id,1:3) dist=distance(x_cur(1:3),o(1:3) ) x_pres(1)=o(1)+ r_x/dist*(x_cur(1) - o(1) )*2.0d0 x_pres(2)=o(2)+ r_y/dist*(x_cur(2) - o(2) )*2.0d0 x_pres(3)=o(3)+ r_z/dist*(x_cur(3) - o(3) )*2.0d0 obj%NodCoord(node_id,1:2)=x_pres(1:2) enddo enddo ! remove facets elem(:)=1 do i=1,size(mesh%ElemNod,1) do ii=1,size(mesh%ElemNod,2) do j=1,size(mesh%FacetElemNod,1) do k=1,size(mesh%FacetElemNod,2) node_id=mesh%FacetElemNod(j,k) if(mesh%ElemNod(i,ii)==node_id )then elem(i)=0 exit endif enddo enddo enddo enddo if(minval(elem)==1 )then print *, "ERROR :: AdjustSphereMesh minval(elem)==1" stop endif if(maxval(elem)==0 )then print *, "converged" exit endif ! remove elems do i=size(elem),1,-1 if(elem(i)==0 )then call removeArray(mat=mesh%ElemNod,remove1stColumn=.true.,NextOf=i-1) endif enddo !call showArray(mat=mesh%NodCoord,IndexArray=mesh%ElemNod,& ! Name=trim(adjustl( fstring(itr) ))//".txt") enddo end subroutine AdjustCylinderMesh !################################################## recursive subroutine createMesh(obj,meshtype,x_num,y_num,x_len,y_len,Le,Lh,Dr,thickness,& division,smooth,top,margin,inclineRate,shaperatio,master,slave,x,y,z,dx,dy,dz,coordinate,& species,SoyWidthRatio) class(Mesh_),intent(inout) :: obj type(Mesh_) :: mesh1,mesh2,interface1,interface2 type(Mesh_),optional,intent(inout) :: master,slave type(IO_) :: f type(ShapeFunction_) :: shape character(*),optional,intent(in) :: meshtype logical,optional,intent(in) :: smooth integer(int32),optional,intent(in) :: x_num,y_num ! number of division integer(int32),optional,intent(in) :: division ! for 3D rectangular real(real64),optional,intent(in) :: x_len,y_len,Le,Lh,Dr,coordinate(:,:) ! length real(real64),optional,intent(in) :: thickness,inclineRate ! for 3D rectangular real(real64),optional,intent(in) :: top,margin ! for 3D rectangular real(real64),optional,intent(in) :: shaperatio ! for 3D leaf real(real64),optional,intent(in) :: x,y,z,dx,dy,dz integer(int32),optional,intent(in) :: species real(real64),optional,intent(in) :: SoyWidthRatio ! width ratio for side leaves of soybean integer(int32) :: i,j,n,m,xn,yn,smoothedge(8),ini,k,dim_num,node_num,elem_num real(real64)::lx,ly,sx,sy,a_val,radius,x_,y_,diflen,Lt,& unitx,unity,xm, ym,tp,rx,ry,zc,zl,zm,ysize,ox,oy,dist,rr logical :: validmeshtype=.false. type(Mesh_) :: BoundBox real(real64)::ymin,ymax,ratio,width,pi,xx,yy,xvec(3),x_max(3),& x_min(3),x_m_mid(3),x_s_mid(3),x1vec(3),x2vec(3),nvec(3),hvec(3) integer(int32),allocatable:: OutNodeID(:),OutElementID(:) logical :: inside real(real64):: dist_tr, dist_cur,z_,zval1,zval2,x_1(3),x_2(3) integer(int32) :: num_layer,itr,node1,node2,node3,node4,count,prev_node1 integer(int32), allocatable :: elemnod(:,:) integer(int32) :: nearest_node_id,nearest_facet_id,node_id,elist(2),tri_excep,tri_excep_last integer(int32),allocatable :: checked(:),checked_node(:) real(real64),allocatable ::nodcoord(:,:) real(real64) :: ll,center(3),vector(3),e1(3),e2(3),e3(3),len_val real(real64) :: length,r,alpha,lin_curve_ratio,yy_,swratio lin_curve_ratio = 0.50d0 pi = 3.1415926535d0 ! this subroutine creates mesh obj%meshtype = meshtype if(obj%meshtype=="root" .or. obj%meshtype=="Root")then ! tree-like graph structure call obj%remove(all=.true.) if(present(coordinate) )then itr = 0 obj%nodcoord = coordinate ! assemble nodes to a mesh consisits of line elements call obj%assemble() if(.not. present(thickness) )then return endif width = input(default=1.0d0,option=thickness) elem_num = size(obj%elemnod,1) node_num = size(obj%nodcoord,1) dim_num = size(obj%nodcoord,2) allocate(nodcoord(node_num*4,dim_num)) elemnod = obj%elemnod ! 4倍に増やしてつなげる nodcoord(1 :node_num ,3) = obj%nodcoord(:,3) nodcoord(1 :node_num ,1) = obj%nodcoord(1 :node_num ,1) - width*0.50d0 nodcoord(1 :node_num ,2) = obj%nodcoord(1 :node_num ,2) - width*0.50d0 nodcoord(node_num+1 :node_num*2 ,3) = obj%nodcoord(:,3) +width*0.10d0 nodcoord(node_num+1 :node_num*2 ,1) = obj%nodcoord(1 :node_num ,1) + width*0.50d0 nodcoord(node_num+1 :node_num*2 ,2) = obj%nodcoord(1 :node_num ,2) - width*0.50d0 nodcoord(node_num*2+1 :node_num*3 ,3) = obj%nodcoord(:,3) +width*0.10d0 nodcoord(node_num*2+1 :node_num*3 ,1) = obj%nodcoord(1 :node_num ,1) + width*0.50d0 nodcoord(node_num*2+1 :node_num*3 ,2) = obj%nodcoord(1 :node_num ,2) + width*0.50d0 nodcoord(node_num*3+1 :node_num*4 ,3) = obj%nodcoord(:,3) nodcoord(node_num*3+1 :node_num*4 ,1) = obj%nodcoord(1 :node_num ,1) - width*0.50d0 nodcoord(node_num*3+1 :node_num*4 ,2) = obj%nodcoord(1 :node_num ,2) + width*0.50d0 do i=1,elem_num node1 = elemnod(i,1) node2 = elemnod(i,2) elemnod(i,1) = node1 + node_num*0 elemnod(i,2) = node1 + node_num*1 elemnod(i,3) = node1 + node_num*2 elemnod(i,4) = node1 + node_num*3 elemnod(i,5) = node2 + node_num*0 elemnod(i,6) = node2 + node_num*1 elemnod(i,7) = node2 + node_num*2 elemnod(i,8) = node2 + node_num*3 enddo obj%nodcoord = nodcoord obj%elemnod = elemnod return ! ! generate solid elements from line elements ! elem_num = size(obj%elemnod,1) ! allocate(nodcoord(elem_num*8,3)) ! allocate(elemnod(elem_num,8)) ! width = input(default=1.0d0,option=thickness) ! ll = width/2.0d0 ! ! e1(:)=0.0d0 ! e1(1)=1.0d0 ! ! e2(:)=0.0d0 ! e2(2)=1.0d0 ! ! e3(:)=0.0d0 ! e3(3)=1.0d0 ! ! ! O_________________O ! ! |\ \ ! ! | \ + \ ! ! | \ node2 \ ! ! | O_________________O ! ! O | | ! ! \ | node1 | ! ! \ | + | ! ! \O_________________O ! ! ! ! From +, create O ! do i=1,elem_num ! node1 = obj%elemnod(i,1) ! node2 = obj%elemnod(i,2) ! ! if(obj%nodcoord(node1,3) > obj%nodcoord(node2,3) )then ! node1 = obj%elemnod(i,2) ! node2 = obj%elemnod(i,1) ! endif ! x_1(:) = obj%nodcoord(node1,:) ! x_2(:) = obj%nodcoord(node2,:) ! center(:) =0.50d0*( x_2(:) + x_1(:) ) ! vector(:) = x_2(:) - x_1(:) ! len_val = abs(vector(3) ) ! ! vector の方向によって場合分け ! if( abs(vector(1)) > abs(vector(2)) .and. abs(vector(1)) > abs(vector(3)) ) then ! ! x-domination ! nodcoord(8*i-7,1)=x_1(1) - ll ; nodcoord(8*i-7,2)=x_1(2) - ll ;nodcoord(8*i-7,3)= center(3) - ll; ! nodcoord(8*i-6,1)=x_1(1) + ll ; nodcoord(8*i-6,2)=x_1(2) - ll ;nodcoord(8*i-6,3)= center(3) - ll; ! nodcoord(8*i-5,1)=x_1(1) + ll ; nodcoord(8*i-5,2)=x_1(2) + ll ;nodcoord(8*i-5,3)= center(3) - ll; ! nodcoord(8*i-4,1)=x_1(1) - ll ; nodcoord(8*i-4,2)=x_1(2) + ll ;nodcoord(8*i-4,3)= center(3) - ll; ! nodcoord(8*i-3,1)=x_1(1) - ll ; nodcoord(8*i-3,2)=x_1(2) - ll ;nodcoord(8*i-3,3)= center(3) + ll; ! nodcoord(8*i-2,1)=x_1(1) + ll ; nodcoord(8*i-2,2)=x_1(2) - ll ;nodcoord(8*i-2,3)= center(3) + ll; ! nodcoord(8*i-1,1)=x_1(1) + ll ; nodcoord(8*i-1,2)=x_1(2) + ll ;nodcoord(8*i-1,3)= center(3) + ll; ! nodcoord(8*i ,1)=x_1(1) - ll ; nodcoord(8*i ,2)=x_1(2) + ll ;nodcoord(8*i ,3)= center(3) + ll; ! elseif( abs(vector(2)) > abs(vector(1)) .and. abs(vector(2)) > abs(vector(3)) ) then ! ! y-domination ! nodcoord(8*i-7,1)=x_1(1) - ll ; nodcoord(8*i-7,2)=x_1(2) - ll ;nodcoord(8*i-7,3)= center(3) - ll; ! nodcoord(8*i-6,1)=x_1(1) + ll ; nodcoord(8*i-6,2)=x_1(2) - ll ;nodcoord(8*i-6,3)= center(3) - ll; ! nodcoord(8*i-5,1)=x_1(1) + ll ; nodcoord(8*i-5,2)=x_1(2) + ll ;nodcoord(8*i-5,3)= center(3) - ll; ! nodcoord(8*i-4,1)=x_1(1) - ll ; nodcoord(8*i-4,2)=x_1(2) + ll ;nodcoord(8*i-4,3)= center(3) - ll; ! nodcoord(8*i-3,1)=x_1(1) - ll ; nodcoord(8*i-3,2)=x_1(2) - ll ;nodcoord(8*i-3,3)= center(3) + ll; ! nodcoord(8*i-2,1)=x_1(1) + ll ; nodcoord(8*i-2,2)=x_1(2) - ll ;nodcoord(8*i-2,3)= center(3) + ll; ! nodcoord(8*i-1,1)=x_1(1) + ll ; nodcoord(8*i-1,2)=x_1(2) + ll ;nodcoord(8*i-1,3)= center(3) + ll; ! nodcoord(8*i ,1)=x_1(1) - ll ; nodcoord(8*i ,2)=x_1(2) + ll ;nodcoord(8*i ,3)= center(3) + ll; ! elseif( abs(vector(3)) > abs(vector(1)) .and. abs(vector(3)) > abs(vector(2)) ) then ! ! z-domination ! nodcoord(8*i-7,1)=x_1(1) - ll ; nodcoord(8*i-7,2)=x_1(2) - ll ;nodcoord(8*i-7,3)= center(3) - ll; ! nodcoord(8*i-6,1)=x_1(1) + ll ; nodcoord(8*i-6,2)=x_1(2) - ll ;nodcoord(8*i-6,3)= center(3) - ll; ! nodcoord(8*i-5,1)=x_1(1) + ll ; nodcoord(8*i-5,2)=x_1(2) + ll ;nodcoord(8*i-5,3)= center(3) - ll; ! nodcoord(8*i-4,1)=x_1(1) - ll ; nodcoord(8*i-4,2)=x_1(2) + ll ;nodcoord(8*i-4,3)= center(3) - ll; ! nodcoord(8*i-3,1)=x_1(1) - ll ; nodcoord(8*i-3,2)=x_1(2) - ll ;nodcoord(8*i-3,3)= center(3) + ll; ! nodcoord(8*i-2,1)=x_1(1) + ll ; nodcoord(8*i-2,2)=x_1(2) - ll ;nodcoord(8*i-2,3)= center(3) + ll; ! nodcoord(8*i-1,1)=x_1(1) + ll ; nodcoord(8*i-1,2)=x_1(2) + ll ;nodcoord(8*i-1,3)= center(3) + ll; ! nodcoord(8*i ,1)=x_1(1) - ll ; nodcoord(8*i ,2)=x_1(2) + ll ;nodcoord(8*i ,3)= center(3) + ll; ! else ! ! same ! ! endif ! ! nodcoord(8*i-7,1)= center(1) - abs(vector(1))*0.50d0 ! nodcoord(8*i-7,2)= center(2) - abs(vector(2))*0.50d0 ! nodcoord(8*i-7,3)= center(3) - abs(vector(3))*0.50d0 ! ! nodcoord(8*i-6,1)= center(1) + abs(vector(1))*0.50d0 ! nodcoord(8*i-6,2)= center(2) - abs(vector(2))*0.50d0 ! nodcoord(8*i-6,3)= center(3) - abs(vector(3))*0.50d0 ! ! nodcoord(8*i-5,1)= center(1) + abs(vector(1))*0.50d0 ! nodcoord(8*i-5,2)= center(2) + abs(vector(2))*0.50d0 ! nodcoord(8*i-5,3)= center(3) - abs(vector(3))*0.50d0 ! ! nodcoord(8*i-4,1)= center(1) - abs(vector(1))*0.50d0 ! nodcoord(8*i-4,2)= center(2) + abs(vector(2))*0.50d0 ! nodcoord(8*i-4,3)= center(3) - abs(vector(3))*0.50d0 ! ! nodcoord(8*i-3,1)= center(1) - abs(vector(1))*0.50d0 ! nodcoord(8*i-3,2)= center(2) - abs(vector(2))*0.50d0 ! nodcoord(8*i-3,3)= center(3) + abs(vector(3))*0.50d0 ! ! nodcoord(8*i-2,1)= center(1) + abs(vector(1))*0.50d0 ! nodcoord(8*i-2,2)= center(2) - abs(vector(2))*0.50d0 ! nodcoord(8*i-2,3)= center(3) + abs(vector(3))*0.50d0 ! ! nodcoord(8*i-1,1)= center(1) + abs(vector(1))*0.50d0 ! nodcoord(8*i-1,2)= center(2) + abs(vector(2))*0.50d0 ! nodcoord(8*i-1,3)= center(3) + abs(vector(3))*0.50d0 ! ! nodcoord(8*i ,1)= center(1) - abs(vector(1))*0.50d0 ! nodcoord(8*i ,2)= center(2) + abs(vector(2))*0.50d0 ! nodcoord(8*i ,3)= center(3) + abs(vector(3))*0.50d0 ! ! ! ! elemnod(i,1) = 8*i-7 ! elemnod(i,2) = 8*i-6 ! elemnod(i,3) = 8*i-5 ! elemnod(i,4) = 8*i-4 ! elemnod(i,5) = 8*i-3 ! elemnod(i,6) = 8*i-2 ! elemnod(i,7) = 8*i-1 ! elemnod(i,8) = 8*i ! enddo ! ! obj%nodcoord = nodcoord ! obj%elemnod = elemnod ! ! return !!!!! ! allocate(obj%elemnod(size(obj%nodcoord,1)*2 ,8) ) ! do ! itr = itr + 1 ! ! if(itr > size(obj%nodcoord,1) ) exit ! x_ = obj%nodcoord(itr,1) ! y_ = obj%nodcoord(itr,2) ! z_ = obj%nodcoord(itr,3) ! nearest_node_id = obj%getNearestNodeID(x=x_,y=y_,z=z_,except=itr) ! obj%elemnod(2*itr-1,1) = itr ! obj%elemnod(2*itr-1,2:) = nearest_node_id ! elist(1)=itr ! elist(2)=nearest_node_id ! x_ = obj%nodcoord(itr,1) ! y_ = obj%nodcoord(itr,2) ! z_ = obj%nodcoord(itr,3) ! nearest_node_id = obj%getNearestNodeID(x=x_,y=y_,z=z_,exceptlist=elist) ! obj%elemnod(2*itr,1) = itr ! obj%elemnod(2*itr,2:) = nearest_node_id ! enddo ! ! ! remove overlap elements ! ! ! case 1: ! ! A->A ! ! itr = 0 ! do i=1,size(obj%elemnod,1) ! if(obj%elemnod(i,1) == obj%elemnod(i,2))then ! obj%elemnod(i,:) = 0 ! itr=itr+1 ! endif ! enddo ! ! ! A -> B ! ! B <- A ! do i=1,size(obj%elemnod,1) ! if(obj%elemnod(i,1)==0 )then ! cycle ! endif ! node1 = obj%elemnod(i,1) ! node2 = obj%elemnod(i,2) ! do j=i+1,size(obj%elemnod,1) ! if(obj%elemnod(j,1)==0 )then ! cycle ! endif ! if(obj%elemnod(j,1) == node1 .and. & ! obj%elemnod(j,2) == node2)then ! obj%elemnod(j,:)=0 ! itr=itr+1 ! endif ! if(obj%elemnod(j,1) == node2 .and. & ! obj%elemnod(j,2) == node1)then ! obj%elemnod(j,:)=0 ! itr=itr+1 ! endif ! enddo ! enddo ! case 2 ! D->A ! A->B ! B->C ! C->A ! >> triangle-exception ! Find cyclic graph ! node1 = 2 ! node2 = 1 ! node3 = 1 ! node4 = 1 ! allocate(checked(size(obj%elemnod,1)) ) ! allocate(checked_node(size(obj%nodcoord,1)) ) ! checked(:) = 0 ! checked_node(:) = 0 ! count=0 ! do ! ! prev_node1=node1 ! ! triangle-exception探索 ! ! 通った要素はchecked=1 ! tri_excep=0 ! ! do i=1,size(obj%elemnod,1) ! ! if(checked(i) == 1) then ! cycle ! endif ! ! if(obj%elemnod(i,1) == 0 )then ! cycle ! endif ! ! checked(i) = 1 ! ! checked_node(obj%elemnod(i,1))=1 ! checked_node(obj%elemnod(i,2))=1 ! ! ! Find next node >> append ! if(obj%elemnod(i,1) == node1 .and. & ! obj%elemnod(i,2) /= node2)then ! node4 = node3 ! node3 = node2 ! node2 = node1 ! node1 = obj%elemnod(i,2) ! checked_node(node1) = 1 ! checked_node(node2) = 1 ! checked_node(node3) = 1 ! checked_node(node4) = 1 ! tri_excep=i ! checked(i) = 1 ! exit ! elseif(obj%elemnod(i,2) == node1 .and. & ! obj%elemnod(i,1) /= node2)then ! node4 = node3 ! node3 = node2 ! node2 = node1 ! node1 = obj%elemnod(i,1) ! checked_node(node1) = 1 ! checked_node(node2) = 1 ! checked_node(node3) = 1 ! checked_node(node4) = 1 ! tri_excep=i ! checked(i) = 1 ! exit ! else ! cycle ! endif ! ! enddo ! ! ! print *, node1, node2,node3,node4 ! ! print *, countif(Array=checked,Equal=.true.,value=0),"/",size(checked) ! ! ! if(prev_node1 == node1) then ! exit ! endif ! ! if(countif(Array=checked,Equal=.true.,value=0) ==0 ) then ! exit ! endif ! ! ! if(tri_excep==0)then ! do j=1,size(checked) ! if(checked(j)==0 .and. obj%elemnod(j,1)/=0 )then ! if(checked_node(obj%elemnod(j,1 ))==0 )then ! node1 = obj%elemnod(j,1 ) ! ! exit ! elseif(checked_node(obj%elemnod(j,2 ))==0 )then ! node1 = obj%elemnod(j,2 ) ! exit ! else ! cycle ! endif ! endif ! enddo ! endif ! ! if(node1==node4 .and. tri_excep/=0)then ! itr=itr+1 ! ! triangle-exception ! obj%elemnod(tri_excep,:) = 0 ! ! checkされてない中で最も接点番号が若いものから再スタート ! do j=1,size(checked) ! if(checked(j)==0 .and. obj%elemnod(j,1)/=0 )then ! if(checked_node(obj%elemnod(j,1 ))==0 )then ! node1 = obj%elemnod(j,1 ) ! ! exit ! elseif(checked_node(obj%elemnod(j,2 ))==0 )then ! node1 = obj%elemnod(j,2 ) ! exit ! else ! cycle ! endif ! cycle ! endif ! enddo ! endif ! ! ! enddo ! ! do i=1,size(obj%elemnod,1) ! node1 = obj%elemnod(i,1) ! node2 = obj%elemnod(i,2) ! do j=i+1,size(obj%elemnod,1) ! if(obj%elemnod(j,1) == node1 )then ! node3 = obj%elemnod(j,2) ! endif ! if(obj%elemnod(j,1) == node2 )then ! node3 = obj%elemnod(j,2) ! endif ! enddo ! enddo ! ! ! elemnod = obj%elemnod ! deallocate(obj%elemnod) ! allocate(obj%elemnod(size(elemnod,1)-itr,8 ) ) ! obj%elemnod(:,:)=0 ! itr=0 ! do i=1,size(elemnod,1) ! if(minval(elemnod(i,:))==0 )then ! cycle ! else ! itr=itr+1 ! obj%elemnod(itr,:) = elemnod(i,:) ! endif ! enddo ! return endif ! initialize root ! o (0,0,0) ! | ! | ! o (0,0,-1) allocate(obj%nodcoord(2,3)) obj%nodcoord(:,:) = 0.0d0 obj%nodcoord(2,3) = -1.0d0 obj%nodcoord(2,1) = input(default=obj%nodcoord(2,1), option=x) obj%nodcoord(2,2) = input(default=obj%nodcoord(2,2), option=y) obj%nodcoord(2,3) = input(default=obj%nodcoord(2,3), option=z) obj%nodcoord(2,1) = input(default=obj%nodcoord(2,1), option=dx) obj%nodcoord(2,2) = input(default=obj%nodcoord(2,2), option=dy) obj%nodcoord(2,3) = input(default=obj%nodcoord(2,3), option=dz) allocate(obj%elemnod(1,8)) obj%elemnod(1,1) = 1 obj%elemnod(1,2:8) = 2 endif if(meshtype=="Node-To-Segment" .or. meshtype=="node-to-segment") then if(.not. present(master) )then call print("ERROR :: please input FEMDomain_-typed object to master") endif if(.not. present(slave) )then call print("ERROR :: please input FEMDomain_-typed object to slave") endif ! create Node-To-Node elements call obj%create(meshtype="Node-To-Node",master=master,slave=slave) ! get segment ! First, identify facet lists ! If surface is not obtained, get surface. if(.not. allocated(master%FacetElemNod) )then call master%getSurface() endif if(allocated(obj%NTSMasterFacetID) )then deallocate(obj%NTSMasterFacetID) endif allocate(obj%NTSMasterFacetID(size(obj%slaveID)) ) do i=1,size(obj%SlaveID) !print *, slave%nodcoord(obj%SlaveID(i),1:3) ! get nearest facet ! ignore In/out :: find nearest segment for a node-to-segment pairing do j=1,size(master%FacetElemNod,1) center(:) = 0.0d0 xvec(:) = slave%nodcoord(obj%SlaveID(i),1:3) do k = 1,size(master%FacetElemNod,2) node_id = master%FacetElemNod(j,k) center(:) = center(:) + master%nodcoord(node_id,:) enddo center(:) = 1.0d0/dble(size(master%FacetElemNod,2))*center(:) dist_tr = sqrt(dot_product(center-xvec,center-xvec)) if(j==1)then dist = dist_tr nearest_facet_id = j else if(dist_tr < dist)then dist = dist_tr nearest_facet_id = j endif endif enddo obj%NTSMasterFacetID(i) = nearest_facet_id enddo if(allocated(obj%NodCoord) ) deallocate(obj%NodCoord) if(allocated(obj%ElemNod) ) deallocate(obj%ElemNod) if(allocated(obj%ElemMat) ) deallocate(obj%ElemMat) ! nodal coordinate >> slave1, master1, master2, ... allocate(obj%NodCoord(size(obj%slaveid)*(size(master%FacetElemNod,2)+1),3 ) ) node_id = 0 do i=1, size(obj%slaveID) node_id = node_id+1 obj%NodCoord(node_id,:) = slave%nodcoord(obj%slaveID(i),:) do j=1,size(master%FacetElemNod,2) node_id = node_id+1 obj%NodCoord(node_id,:) = & master%nodcoord( master%FacetElemNod(obj%NTSMasterFacetID(i),j),:) enddo enddo allocate(obj%ElemNod(size(obj%slaveid),size(slave%ElemNod,2)) ) node_id = 0 do i=1,size(obj%ElemNod,1) do j=1,size(master%FacetElemNod,2) node_id = node_id + 1 obj%elemnod(i,j:) = node_id enddo enddo allocate(obj%ElemMat(size(obj%slaveid) ) ) obj%ElemMat(:) = 1 !call print(obj%nodcoord) !call print(obj%elemnod) !stop ! get local coordinate (xi_1, xi_2) if(size(master%FacetElemNod,2) /=4)then ! if not 8-node isoparametric elements, call print("createMesh(NTS) >> not 8-node isoparametric elements >> no xi-local codinate is created") call print("Not supported now.") return endif allocate(obj%xi(size(obj%ElemNod,1),2 ) ) ! initialize shape function !call shape%init(ElemType="LinearRectangularGp4") do i=1,size(obj%elemnod,1) x1vec(:) = obj%nodcoord(obj%elemnod(i,4),:)-obj%nodcoord(obj%elemnod(i,3),:) x2vec(:) = obj%nodcoord(obj%elemnod(i,2),:)-obj%nodcoord(obj%elemnod(i,3),:) nvec(:) = cross_product(x1vec, x2vec) nvec(:) = 1.0d0/sqrt(dot_product(nvec,nvec) )*nvec(:) ! foot of the node xvec(:) = obj%nodcoord(obj%elemnod(i,1),:) - obj%nodcoord(obj%elemnod(i,3),:) hvec(:) = obj%nodcoord(obj%elemnod(i,1),:) - dot_product(xvec,nvec)*nvec(:) ! 4-node ! create shape function !call shape%getall() !do j=1,4 ! call obj%GetAll(elem_id=1,nod_coord=NodCoord,elem_nod=ElemNod,OptionalGpID=j) !enddo enddo endif if(meshtype=="Node-To-Node" .or. meshtype=="node-to-node") then call master%GetInterSectBox(slave,BoundBox) if( BoundBox%empty() .eqv. .true. ) then call print("No interface") return else call print("Contact interface detected.") ! get master and slave nodes ! Global search for master node by AABB algorithm (Bounding-Box method) dim_num = size(master%nodcoord,2) node_num = size(master%nodcoord,1) allocate(OutNodeID(size(master%nodcoord,1) ) ) OutNodeID(:) = 0 do i=1,size(master%nodcoord,1) xvec(:) = 0.0d0 x_max(:) = 0.0d0 x_min(:) = 0.0d0 xvec(1:size(master%nodcoord,2)) = master%nodcoord(i,1:size(master%nodcoord,2) ) do j=1,size(BoundBox%NodCoord,2) x_max(j) = maxval(BoundBox%NodCoord(:,j) ) enddo do j=1,size(BoundBox%NodCoord,2) x_min(j) = minval(BoundBox%NodCoord(:,j) ) enddo ! Judge inside or not inside = InOrOut(x=xvec,xmax=x_max,xmin=x_min) if(inside .eqv. .false.)then OutNodeID(i)=1 endif enddo call print("Interface node :: "//str(node_num - sum(OutNodeID))//"/"//str(node_num) ) allocate(interface1%nodcoord(node_num - sum(OutNodeID) , dim_num ) ) j=0 do i=1,size(master%Nodcoord,1) if(OutNodeID(i)==1 )then ! out >> ignore the node cycle else j=j+1 interface1%nodcoord(j,:) = master%Nodcoord(i,:) endif enddo allocate(OutElementID(size(master%elemnod,1) ) ) k=0 OutElementID(:) = 0 do i=1,size(master%elemnod,1) do j=1,size(master%elemnod,2) if(OutNodeID(master%elemnod(i,j) )==1)then ! out element k=k+1 OutElementID(i) = 1 exit endif enddo enddo call print("Interface element :: "//str(size(master%elemnod,1) - k)//"/"//str(size(master%elemnod,1)) ) allocate(interface1%elemnod(size(master%elemnod,1) - k ,size(master%elemnod,2) ) ) k=0 do i=1,size(OutElementID,1) if(OutElementID(i) == 1 )then cycle else k=k+1 do j=1,size(master%elemnod,2) interface1%elemnod(k,j) = master%elemnod(i,j) - sum(OutNodeID(1:master%elemnod(i,j)-1 )) enddo endif enddo deallocate(OutElementID) deallocate(OutNodeID) ! global search for slave dim_num = size(slave%nodcoord,2) node_num = size(slave%nodcoord,1) allocate(OutNodeID(size(slave%nodcoord,1) ) ) OutNodeID(:) = 0 do i=1,size(slave%nodcoord,1) xvec(:) = 0.0d0 x_max(:) = 0.0d0 x_min(:) = 0.0d0 xvec(1:size(slave%nodcoord,2)) = slave%nodcoord(i,1:size(slave%nodcoord,2) ) do j=1,size(BoundBox%NodCoord,2) x_max(j) = maxval(BoundBox%NodCoord(:,j) ) enddo do j=1,size(BoundBox%NodCoord,2) x_min(j) = minval(BoundBox%NodCoord(:,j) ) enddo ! Judge inside or not inside = InOrOut(x=xvec,xmax=x_max,xmin=x_min) if(inside .eqv. .false.)then OutNodeID(i)=1 endif enddo call print("Interface node :: "//str(node_num - sum(OutNodeID))//"/"//str(node_num) ) allocate(interface2%nodcoord(node_num - sum(OutNodeID) , dim_num ) ) j=0 do i=1,size(slave%Nodcoord,1) if(OutNodeID(i)==1 )then ! out >> ignore the node cycle else j=j+1 interface2%nodcoord(j,:) = slave%Nodcoord(i,:) endif enddo allocate(OutElementID(size(slave%elemnod,1) ) ) k=0 OutElementID(:) = 0 do i=1,size(slave%elemnod,1) do j=1,size(slave%elemnod,2) if(OutNodeID(slave%elemnod(i,j) )==1)then ! out element k=k+1 OutElementID(i) = 1 exit endif enddo enddo call print("Interface element :: "//str(size(slave%elemnod,1) - k)//"/"//str(size(slave%elemnod,1)) ) allocate(interface2%elemnod(size(slave%elemnod,1) - k ,size(slave%elemnod,2) ) ) k=0 do i=1,size(OutElementID,1) if(OutElementID(i) == 1 )then cycle else k=k+1 do j=1,size(slave%elemnod,2) interface2%elemnod(k,j) = slave%elemnod(i,j) - sum(OutNodeID(1:slave%elemnod(i,j)-1 )) enddo endif enddo deallocate(OutElementID) deallocate(OutNodeID) !obj%nodcoord = interface2%nodcoord !obj%elemnod = interface2%elemnod ! ! again get boundary box ! print *, maxval(interface1%nodcoord(:,1)), maxval(interface1%nodcoord(:,2)), maxval(interface1%nodcoord(:,3)) ! print *, minval(interface1%nodcoord(:,1)), minval(interface1%nodcoord(:,2)), minval(interface1%nodcoord(:,3)) ! print *, maxval(interface2%nodcoord(:,1)), maxval(interface2%nodcoord(:,2)), maxval(interface2%nodcoord(:,3)) ! print *, minval(interface2%nodcoord(:,1)), minval(interface2%nodcoord(:,2)), minval(interface2%nodcoord(:,3)) ! ! call interface1%GetInterSectBox(interface2,BoundBox) ! ! call interface1%remove(x_max=minval(BoundBox%nodcoord(:,1)) ) ! call interface1%remove(y_max=minval(BoundBox%nodcoord(:,2)) ) ! call interface1%remove(z_max=minval(BoundBox%nodcoord(:,3)) ) ! ! call interface1%remove(x_min=maxval(BoundBox%nodcoord(:,1)) ) ! call interface1%remove(y_min=maxval(BoundBox%nodcoord(:,2)) ) ! call interface1%remove(z_min=maxval(BoundBox%nodcoord(:,3)) ) ! ! call interface2%remove(x_max=minval(BoundBox%nodcoord(:,1)) ) ! call interface2%remove(y_max=minval(BoundBox%nodcoord(:,2)) ) ! call interface2%remove(z_max=minval(BoundBox%nodcoord(:,3)) ) ! ! call interface2%remove(x_min=maxval(BoundBox%nodcoord(:,1)) ) ! call interface2%remove(y_min=maxval(BoundBox%nodcoord(:,2)) ) ! call interface2%remove(z_min=maxval(BoundBox%nodcoord(:,3)) ) ! ! ! call print("Global Search Done!") call print("local search >> ") ! pairing ! link Node-To-Node allocate(obj%nodcoord(size(interface2%nodcoord,1)*2,size(interface2%nodcoord,2) ) ) node_num = size(interface2%nodcoord,1) ! = ! slave-node #1 x, y ! slave-node #2 x, y ! slave-node #3 x, y ! slave-node #4 x, y ! slave-node #5 x, y ! ... ! master-node #1 x, y ! master-node #2 x, y ! master-node #3 x, y ! master-node #4 x, y ! master-node #5 x, y ! ... allocate(obj%elemnod(size(interface2%nodcoord,1), 8 )) ! slave-node, master-node do j=1, size(interface2%nodcoord,1)! for each slave node ! どっちがmasterか気をつける。 ! initialize obj%elemnod(j,1) = j ! slave node obj%elemnod(j,2:8) = j+node_num ! master node x_s_mid(1:dim_num) = interface2%nodcoord(j,1:dim_num) x_m_mid(1:dim_num) = interface1%nodcoord(1,1:dim_num) dist_cur = dsqrt(dot_product(x_m_mid- x_s_mid, x_m_mid-x_s_mid ) ) ! get nearest master node obj%nodcoord(j,1:dim_num) = interface2%nodcoord(j,1:dim_num) ! slave node do i=1,size(interface1%nodcoord,1) ! for each master node x_s_mid(:) = 0.0d0 x_s_mid(1:dim_num) = interface2%nodcoord(j,1:dim_num) x_m_mid(:) = 0.0d0 x_m_mid(1:dim_num) = interface1%nodcoord(i,1:dim_num) dist_tr = dsqrt(dot_product(x_m_mid- x_s_mid, x_m_mid-x_s_mid ) ) if(dist_tr <= dist_cur)then dist_cur = dist_tr obj%nodcoord(j+node_num,:) = interface1%nodcoord(i,:) ! master node endif enddo enddo allocate(obj%masterID(node_num) ) allocate(obj%slaveID(node_num) ) ! search master ids do j=1,size(interface2%nodcoord,1) do i=1,size(master%nodcoord,1) xvec(:) = 0.0d0 x_m_mid(:) = 0.0d0 xvec(1:dim_num) = obj%nodcoord(j+node_num,1:dim_num) x_m_mid(1:dim_num) = master%nodcoord(i,1:dim_num) dist_tr = dsqrt(dot_product(xvec-x_m_mid, xvec-x_m_mid ) ) if(dist_tr == 0.0d0)then obj%masterID(j) = i exit endif enddo enddo ! search slave ids do j=1,size(interface2%nodcoord,1) do i=1,size(slave%nodcoord,1) xvec(:) = 0.0d0 x_m_mid(:) = 0.0d0 xvec(1:dim_num) = obj%nodcoord(j,1:dim_num) x_m_mid(1:dim_num) = slave%nodcoord(i,1:dim_num) dist_tr = dsqrt(dot_product(xvec-x_m_mid, xvec-x_m_mid ) ) if(dist_tr == 0.0d0)then obj%slaveID(j) = i exit endif enddo enddo endif return endif if(meshtype=="Leaf3D")then validmeshtype=.true. call obj%create(meshtype="rectangular3D",x_num=x_num,& y_num=y_num,x_len=x_len,y_len=y_len,Le=Le,Lh=Lh,Dr=Dr,thickness=thickness,& division=division,smooth=smooth,top=top,margin=margin,inclineRate=inclineRate) obj%NodCoord(:,1) =obj%NodCoord(:,1) - (maxval(obj%NodCoord(:,1))-minval(obj%NodCoord(:,1)))*0.50d0 obj%NodCoord(:,2) =obj%NodCoord(:,2) - (maxval(obj%NodCoord(:,2))-minval(obj%NodCoord(:,2)))*0.50d0 ! shape like this ! ! %%%%%%%%%%%%%%%%%%%%%%%%%%%%% B ! %% % % ! %% % %% ! %% % %% ! %% % %% ! %% % %% ! %% %% ! A %% %% ! <I> %%%%%%%%%%%%%%%% call obj%clean() if(present(species) )then if(species == PF_GLYCINE_MAX)then ! >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ! TOMOBE model (Tomobe 2021, in prep.) zm = minval(obj%NodCoord(:,3) ) length =maxval(obj%NodCoord(:,3) )- minval(obj%NodCoord(:,3) ) width = maxval(obj%NodCoord(:,1) )- minval(obj%NodCoord(:,1) ) zl = maxval(obj%NodCoord(:,3) )- minval(obj%NodCoord(:,3) ) swratio = input(default=0.50d0,option=SoyWidthRatio) if(swratio>=1.0d0 .or. swratio<=0.0d0 )then print *, "ERROR >> mesh%create(leaf3d, PF_SOYBEAN) >> invalid SoyWidthRatio ",SoyWidthRatio stop endif do i=1,size(obj%nodcoord,1) xx = obj%nodcoord(i,3) if(obj%NodCoord(i,1) <= (maxval(obj%NodCoord(:,1) ) + minval(obj%NodCoord(:,1)))*0.50d0 )then alpha = swratio*width else alpha = (1.0d0-swratio)*width endif r = (alpha**2 + (length - alpha)**2)/(2*alpha)*1.20d0 if(xx <= 1.0d0/25.0d0*length)then obj%NodCoord(i,1) = obj%NodCoord(i,1)*1.0d0/10.0d0 cycle elseif(xx < alpha)then yy = sqrt( alpha**2 - (xx-alpha)**2 ) yy_ = xx yy = lin_curve_ratio*yy + (1.0d0-lin_curve_ratio)*yy_ else yy_ = alpha + (-alpha)/(length-alpha)*(xx - alpha) yy = alpha - r + sqrt(r**2 - (xx - alpha)**2 ) yy = lin_curve_ratio*yy + (1.0d0-lin_curve_ratio)*yy_ endif yy = abs(yy) obj%nodcoord(i,1) = obj%nodcoord(i,1)*(yy/alpha) enddo ! TOMOBE model (Tomobe 2021, in prep.) ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< elseif(species == PF_MAIZE)then ! >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ! TOMOBE model (Tomobe 2021, in prep.) zm = minval(obj%NodCoord(:,3) ) length =maxval(obj%NodCoord(:,3) )- minval(obj%NodCoord(:,3) ) width = maxval(obj%NodCoord(:,1) )- minval(obj%NodCoord(:,1) ) zl = maxval(obj%NodCoord(:,3) )- minval(obj%NodCoord(:,3) ) swratio = input(default=0.50d0,option=SoyWidthRatio) if(swratio>=1.0d0 .or. swratio<=0.0d0 )then print *, "ERROR >> mesh%create(leaf3d, PF_SOYBEAN) >> invalid SoyWidthRatio ",SoyWidthRatio stop endif do i=1,size(obj%nodcoord,1) xx = obj%nodcoord(i,3) if(obj%NodCoord(i,1) <= (maxval(obj%NodCoord(:,1) ) + minval(obj%NodCoord(:,1)))*0.50d0 )then alpha = swratio*width else alpha = (1.0d0-swratio)*width endif r = (alpha**2 + (length - alpha)**2)/(2*alpha)*1.20d0 if(xx <= 1.0d0/25.0d0*length)then obj%NodCoord(i,1) = obj%NodCoord(i,1)*1.0d0/10.0d0 cycle elseif(xx < alpha)then yy = sqrt( alpha**2 - (xx-alpha)**2 ) yy_ = xx yy = lin_curve_ratio*yy + (1.0d0-lin_curve_ratio)*yy_ else yy_ = alpha + (-alpha)/(length-alpha)*(xx - alpha) yy = alpha - r + sqrt(r**2 - (xx - alpha)**2 ) yy = lin_curve_ratio*yy + (1.0d0-lin_curve_ratio)*yy_ endif yy = abs(yy) obj%nodcoord(i,1) = obj%nodcoord(i,1)*(yy/alpha) enddo ! TOMOBE model (Tomobe 2021, in prep.) ! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< else print *, "[ERROR] Mesh%create => No such species as ",species stop endif else do i=1,size(obj%NodCoord,1) zc = obj%NodCoord(i,3) zm = minval(obj%NodCoord(:,3) ) width = maxval(obj%NodCoord(:,1) )- minval(obj%NodCoord(:,1) ) width = width/2.0d0 zl = maxval(obj%NodCoord(:,3) )- minval(obj%NodCoord(:,3) ) if(zc <= 1.0d0/20.0d0*zl)then ratio = 1.0d0/10.0d0 elseif(1.0d0/20.0d0*zl < zc .and. zc <= zl*shaperatio )then ratio = 1.0d0/10.0d0 + 0.90d0/(zl*shaperatio - 1.0d0/20.0d0*zl)*(zc - 1.0d0/20.0d0*zl) else ratio = 1.0d0 -0.90d0/(zl - shaperatio*zl)*(zc - shaperatio*zl) endif obj%NodCoord(i,1) = obj%NodCoord(i,1)*ratio enddo endif endif if(meshtype=="HalfSphere3D")then validmeshtype=.true. call obj%create(meshtype="Sphere3D",x_num=x_num,y_num=y_num,x_len=x_len,& y_len=y_len,Le=Le,Lh=Lh,Dr=Dr,thickness=thickness,& division=division,smooth=smooth,top=top,margin=margin,inclineRate=inclineRate) ! remove half by x-z plane ysize = maxval(obj%NodCoord(:,2) ) - minval(obj%NodCoord(:,2) ) call obj%remove(y_max=ysize/2.0d0-dble(1.0e-8)) endif if(meshtype=="Bar1D" .or. meshtype=="bar1D")then ! need x_len, x_num validmeshtype=.true. if(allocated(obj%NodCoord)) deallocate(obj%NodCoord) if(allocated(obj%ElemNod)) deallocate(obj%ElemNod) if(allocated(obj%ElemMat)) deallocate(obj%ElemMat) n=input(default=10,option=x_num) allocate(obj%NodCoord(n+1,1) ) allocate(obj%ElemNod(n,2) ) allocate(obj%ElemMat(n) ) lx=input(default=10.0d0,option=x_len) do i=1,n+1 obj%NodCoord(i,1)=dble(i-1)*lx/n enddo do i=1,n obj%ElemNod(i,1)=i obj%ElemNod(i,2)=i+1 obj%ElemMat(i)=1 enddo endif if(meshtype=="rectangular3D" .or. meshtype=="Cube")then validmeshtype=.true. call obj%create(meshtype="rectangular2D",x_num=x_num,y_num=y_num,x_len=x_len,y_len=y_len) call obj%Convert2Dto3D(Thickness=Thickness,division=division) if(.not.allocated(obj%ElemMat))then n=size(obj%ElemNod,1) allocate(obj%ElemMat(n) ) endif ! create direction-data obj%BottomElemID = (x_num)*(y_num)/2 obj%TopElemID = (x_num)*(y_num)/2 + (x_num)*(y_num)*(division-1) endif if(meshtype=="Cube3D" .or.meshtype=="cube3D")then validmeshtype=.true. call obj%create(meshtype="rectangular2D",x_num=x_num,y_num=y_num,x_len=x_len,y_len=y_len) call obj%Convert2Dto3D(Thickness=Thickness,division=division) if(.not.allocated(obj%ElemMat))then n=size(obj%ElemNod,1) allocate(obj%ElemMat(n) ) endif ! create direction-data obj%BottomElemID = (x_num)*(y_num)/2 obj%TopElemID = (x_num)*(y_num)/2 + (x_num)*(y_num)*(division-1) endif if(meshtype=="Dam3D" )then validmeshtype=.true. call obj%create(meshtype="rectangular2D",x_num=x_num,y_num=y_num,x_len=x_len,y_len=y_len) xm=0.50d0*maxval(obj%NodCoord(:,1) )+0.50d0*minval(obj%NodCoord(:,1) ) ym=0.50d0*maxval(obj%NodCoord(:,2) )+0.50d0*minval(obj%NodCoord(:,2) ) lx=maxval(obj%NodCoord(:,1) )- minval(obj%NodCoord(:,1) ) ly=maxval(obj%NodCoord(:,2) )- minval(obj%NodCoord(:,2) ) ymin=minval(obj%NodCoord(:,2)) obj%NodCoord(:,1)=obj%NodCoord(:,1)-xm obj%NodCoord(:,2)=obj%NodCoord(:,2)-ymin tp = input(default=ly*1.50d0,option=top) if(top < ly)then print *, "ERROR createMesh >> top < ly" stop endif do i=1,size(obj%NodCoord,1) ry = obj%NodCoord(i,2) rx = (top-ry)*lx*0.50d0/top obj%NodCoord(i,1) = obj%NodCoord(i,1)/(lx*0.50d0)*rx enddo ! add mesh call mesh1%create(meshtype="rectangular2D",x_num=x_num,y_num=y_num,x_len=x_len,y_len=y_len) call mesh2%create(meshtype="rectangular2D",x_num=x_num,y_num=y_num,x_len=x_len,y_len=y_len) ymax=maxval(mesh1%NodCoord(:,2) ) mesh1%NodCoord(:,1)=mesh1%NodCoord(:,1) mesh1%NodCoord(:,2)=mesh1%NodCoord(:,2)-ymax mesh2%NodCoord(:,1)=mesh2%NodCoord(:,1)-2.0d0*xm mesh2%NodCoord(:,2)=mesh2%NodCoord(:,2)-ymax print *, "deo" call obj%add(mesh1) call obj%add(mesh2) print *, "deo" call showArray(obj%NodCoord,IndexArray=obj%ElemNod,Name="text.txt") print *, "ERROR :: Dam3D is not implemented yet." stop !call obj%removeOverlappedNode() call obj%Convert2Dto3D(Thickness=Thickness,division=division) if(.not.allocated(obj%ElemMat))then n=size(obj%ElemNod,1) allocate(obj%ElemMat(n) ) endif return endif if(meshtype=="Trapezoid2D" .or. meshtype=="Ridge2D")then validmeshtype=.true. call obj%create(meshtype="rectangular2D",x_num=x_num,y_num=y_num,x_len=x_len,y_len=y_len) xm=0.50d0*maxval(obj%NodCoord(:,1) )+0.50d0*minval(obj%NodCoord(:,1) ) ym=0.50d0*maxval(obj%NodCoord(:,2) )+0.50d0*minval(obj%NodCoord(:,2) ) lx=maxval(obj%NodCoord(:,1) )- minval(obj%NodCoord(:,1) ) ly=maxval(obj%NodCoord(:,2) )- minval(obj%NodCoord(:,2) ) obj%NodCoord(:,1)=obj%NodCoord(:,1)-xm tp = input(default=ly*1.50d0,option=top) if(top < ly)then print *, "ERROR createMesh >> top < ly" stop endif do i=1,size(obj%NodCoord,1) ry = obj%NodCoord(i,2) rx = (top-ry)*lx*0.50d0/top obj%NodCoord(i,1) = obj%NodCoord(i,1)/(lx*0.50d0)*rx enddo if(.not.allocated(obj%ElemMat))then n=size(obj%ElemNod,1) allocate(obj%ElemMat(n) ) endif return endif if(meshtype=="Trapezoid3D" .or. meshtype=="Ridge3D")then validmeshtype=.true. call obj%create(meshtype="rectangular2D",x_num=x_num,y_num=y_num,x_len=x_len,y_len=y_len) xm=0.50d0*maxval(obj%NodCoord(:,1) )+0.50d0*minval(obj%NodCoord(:,1) ) ym=0.50d0*maxval(obj%NodCoord(:,2) )+0.50d0*minval(obj%NodCoord(:,2) ) lx=maxval(obj%NodCoord(:,1) )- minval(obj%NodCoord(:,1) ) ly=maxval(obj%NodCoord(:,2) )- minval(obj%NodCoord(:,2) ) obj%NodCoord(:,1)=obj%NodCoord(:,1)-xm tp = input(default=ly*1.50d0,option=top) if(top < ly)then print *, "ERROR createMesh >> top < ly" stop endif do i=1,size(obj%NodCoord,1) ry = obj%NodCoord(i,2) rx = (top-ry)*lx*0.50d0/top obj%NodCoord(i,1) = obj%NodCoord(i,1)/(lx*0.50d0)*rx enddo call obj%Convert2Dto3D(Thickness=Thickness,division=division) if(.not.allocated(obj%ElemMat))then n=size(obj%ElemNod,1) allocate(obj%ElemMat(n) ) endif return endif if(meshtype=="Sphere3D" .or. meshtype=="Sphere")then validmeshtype=.true. call obj%create(meshtype="rectangular2D",x_num=x_num,y_num=y_num,x_len=1.0d0,y_len=1.0d0) call obj%Convert2Dto3D(Thickness=1.0d0,division=division) if(.not.allocated(obj%ElemMat))then n=size(obj%ElemNod,1) allocate(obj%ElemMat(n) ) endif call obj%AdjustSphere(debug=.true.) call obj%clean() call obj%resize(x_rate=x_len,& y_rate=y_len,& z_rate=thickness) return endif if(meshtype=="HQSphere3D" .or. meshtype=="HQSphere")then validmeshtype=.true. call obj%create(meshtype="rectangular2D",x_num=x_num,y_num=y_num,x_len=1.0d0,y_len=1.0d0) call obj%Convert2Dto3D(Thickness=1.0d0,division=division) if(.not.allocated(obj%ElemMat))then n=size(obj%ElemNod,1) allocate(obj%ElemMat(n) ) endif call obj%AdjustSphere(debug=.true.) call obj%resize(x_rate=x_len,& y_rate=y_len,& z_rate=thickness) return endif if(meshtype=="Cylinder3D" .or. meshtype=="Cylinder")then validmeshtype=.true. call obj%create(meshtype="Circle2D",x_num=x_num,y_num=y_num,x_len=1.0d0,y_len=1.0d0) call obj%Convert2Dto3D(Thickness=thickness,division=division) if(.not.allocated(obj%ElemMat))then n=size(obj%ElemNod,1) allocate(obj%ElemMat(n) ) endif !call obj%adjustCylinder(debug=.true.) ! move unconnected nodes call obj%clean() call obj%resize(x_rate=2.0d0*x_len,& y_rate=2.0d0*y_len,& z_rate=thickness) return endif if(meshtype=="Circle2D" .or. meshtype=="Circle")then validmeshtype=.true. ! create mesh by scheme-circle method ! https://support.jpmandt.com/mesh/create-mesh/surface-create-mesh/scheme-circle/ ! fraction:interval = 1:1 xn = input(default=10,option=x_num/2+1) yn = input(default=10,option=y_num/2+1) ! x方向とy方向のうち、より分割数が多い方に合わせる if(xn <= ym)then xn = ym else yn = xn endif ! 正方形ができる。 call obj%create(meshtype="rectangular2D",x_num=2*xn,y_num=2*yn,x_len=2.0d0,y_len=2.0d0) obj%nodcoord(:,1)=obj%nodcoord(:,1)-1.0d0 obj%nodcoord(:,2)=obj%nodcoord(:,2)-1.0d0 ! 正方形を整形して、円とのコネクティビティを改善 do i=1,size(obj%nodCoord,1) xx = obj%nodCoord(i,1) yy = obj%nodCoord(i,2) if(xx>=0.0d0 .and. yy>=0.0d0)then obj%nodCoord(i,1) = xx + xx*(sqrt(2.0d0)-1.0d0)*(1.0d0-yy) obj%nodCoord(i,2) = yy + yy*(sqrt(2.0d0)-1.0d0)*(1.0d0-xx) elseif(xx< 0.0d0 .and. yy>=0.0d0)then obj%nodCoord(i,1) = xx + xx*(sqrt(2.0d0)-1.0d0)*(1.0d0-yy) obj%nodCoord(i,2) = yy + yy*(sqrt(2.0d0)-1.0d0)*(1.0d0+xx) elseif(xx< 0.0d0 .and. yy< 0.0d0)then obj%nodCoord(i,1) = xx + xx*(sqrt(2.0d0)-1.0d0)*(1.0d0+yy) obj%nodCoord(i,2) = yy + yy*(sqrt(2.0d0)-1.0d0)*(1.0d0+xx) elseif(xx>=0.0d0 .and. yy< 0.0d0)then obj%nodCoord(i,1) = xx + xx*(sqrt(2.0d0)-1.0d0)*(1.0d0+yy) obj%nodCoord(i,2) = yy + yy*(sqrt(2.0d0)-1.0d0)*(1.0d0-xx) else print *, "ERROR :: createMesh >> circle error" stop endif enddo if(present(meshtype) .and. validmeshtype .eqv. .false. )then print *, "createMesh%error :: no such mesh as ", trim(meshtype) return endif !obj%nodcoord(:,1)=obj%nodcoord(:,1)*0.650d0 !obj%nodcoord(:,2)=obj%nodcoord(:,2)*0.650d0 obj%nodcoord(:,1)=dble(2*xn-1)/dble(2*xn)*obj%nodcoord(:,1)/sqrt(2.0d0) obj%nodcoord(:,2)=dble(2*xn-1)/dble(2*xn)*obj%nodcoord(:,2)/sqrt(2.0d0) ! 外周メッシュ allocate(mesh1%nodcoord( (2*xn)* (2*xn)*4 ,size(obj%nodcoord,2) ) ) do i=1, (2*xn) ! For each layer do j=1, (2*xn)*4 mesh1%nodcoord( (i-1)* (2*xn)*4+ j,1) = (1.0d0 + dble(i)*(1.0d0/dble( (2*xn)) ) )& *cos(2.0d0*pi/4.0d0/dble( (2*xn))*dble(j-1) ) mesh1%nodcoord( (i-1)* (2*xn)*4+ j,2) = (1.0d0 + dble(i)*(1.0d0/dble( (2*xn)) ) )& *sin(2.0d0*pi/4.0d0/dble( (2*xn))*dble(j-1) ) enddo enddo !call print(mat=mesh1%nodcoord,name="circle.txt") !call print(mat=obj%nodcoord,name="cube.txt") ! 要素 ! Starts from ElementID: (2*xn+1)*(2*xn+1) allocate(mesh1%elemnod(8*xn*(xn+1),4) ) mesh1%elemnod(:,:)=0 j=0 do i=1,xn j=j+1 mesh1%elemnod(j,1)= (2*xn+1)*(xn+i) mesh1%elemnod(j,2)= (2*xn+1)*(2*xn+1)+ j mesh1%elemnod(j,3)= (2*xn+1)*(2*xn+1)+ j+1 mesh1%elemnod(j,4)= (2*xn+1)*(xn+i+1) enddo do i=1,2*xn j=j+1 mesh1%elemnod(j,1)= (2*xn+1)*(2*xn+1)-i+1 mesh1%elemnod(j,2)= (2*xn+1)*(2*xn+1)+ j mesh1%elemnod(j,3)= (2*xn+1)*(2*xn+1)+ j+1 mesh1%elemnod(j,4)= (2*xn+1)*(2*xn+1)-i enddo do i=1,2*xn j=j+1 mesh1%elemnod(j,1)= (2*xn+1)*(2*xn+1)-(2*xn+1)+1-(i-1)*(2*xn+1) mesh1%elemnod(j,2)= (2*xn+1)*(2*xn+1)+ j mesh1%elemnod(j,3)= (2*xn+1)*(2*xn+1)+ j+1 mesh1%elemnod(j,4)= (2*xn+1)*(2*xn+1)-(2*xn+1)+1-(i)*(2*xn+1) enddo do i=1,2*xn j=j+1 mesh1%elemnod(j,1)= i mesh1%elemnod(j,2)= (2*xn+1)*(2*xn+1)+ j mesh1%elemnod(j,3)= (2*xn+1)*(2*xn+1)+ j+1 mesh1%elemnod(j,4)= i+1 enddo do i=1,xn j=j+1 mesh1%elemnod(j,1)= (2*xn+1)*i mesh1%elemnod(j,2)= (2*xn+1)*(2*xn+1)+ j mesh1%elemnod(j,3)= (2*xn+1)*(2*xn+1)+ j+1 mesh1%elemnod(j,4)= (2*xn+1)*(i+1) enddo mesh1%elemnod(j,3)= (2*xn+1)*(2*xn+1) +1 do i=1,xn ini=j+1 do k=1,8*xn-1 j=j+1 mesh1%elemnod(j,1)= (2*xn+1)*(2*xn+1)+ j - 8*xn mesh1%elemnod(j,2)= (2*xn+1)*(2*xn+1)+ j mesh1%elemnod(j,3)= (2*xn+1)*(2*xn+1)+ j+1 mesh1%elemnod(j,4)= (2*xn+1)*(2*xn+1)+ j+1 - 8*xn enddo j=j+1 mesh1%elemnod(j,1)= (2*xn+1)*(2*xn+1)+ j - 8*xn mesh1%elemnod(j,2)= (2*xn+1)*(2*xn+1)+ j mesh1%elemnod(j,3)= (2*xn+1)*(2*xn+1)+ ini mesh1%elemnod(j,4)= (2*xn+1)*(2*xn+1)+ ini - 8*xn enddo !call print(mat=mesh1%elemnod,name="elem.txt") allocate(mesh2%nodcoord(size(obj%nodcoord,1)+size(mesh1%nodcoord,1),& size(obj%nodcoord,2)) ) mesh2%nodcoord(1:size(obj%nodcoord,1),1:2)=obj%nodcoord(1:size(obj%nodcoord,1),1:2) mesh2%nodcoord(size(obj%nodcoord,1)+1:size(obj%nodcoord,1)+size(mesh1%nodcoord,1),1:2)& =mesh1%nodcoord(1:size(mesh1%nodcoord,1),1:2) allocate(mesh2%elemnod(size(obj%elemnod,1)+size(mesh1%elemnod,1),& size(obj%elemnod,2)) ) mesh2%elemnod(1:size(obj%elemnod,1),1:4)=obj%elemnod(1:size(obj%elemnod,1),1:4) mesh2%elemnod(size(obj%elemnod,1)+1:size(obj%elemnod,1)+size(mesh1%elemnod,1),1:4)& =mesh1%elemnod(1:size(mesh1%elemnod,1),1:4) !call print(mat=mesh2%elemnod,name="elem2.txt") !call print(mat=mesh2%nodcoord,IndexArray=mesh2%elemnod,name="mesh2.txt") !call f%open("mesh2.txt") !do i=1,size(mesh2%elemnod,1) ! do j=1,size(mesh2%elemnod,2) ! write(f%fh,*) mesh2%nodcoord(mesh2%elemnod(i,j),:) ! enddo ! write(f%fh,*) mesh2%nodcoord(mesh2%elemnod(i,1),:) ! write(f%fh,*) " " !enddo !call f%close() allocate(mesh2%elemmat(size(mesh2%elemnod,1) ) ) mesh2%elemmat(:)=1 call obj%remove() obj%nodcoord = mesh2%nodcoord obj%elemnod = mesh2%elemnod obj%elemmat = mesh2%elemmat return endif if(meshtype=="rectangular2D" .or. meshtype=="Box2D")then xn=input(default=1,option=x_num) yn=input(default=1,option=y_num) lx=input(default=1.0d0,option=x_len) ly=input(default=1.0d0,option=y_len) unitx=lx/dble(xn) unity=ly/dble(yn) ! creating rectangular mesh allocate(obj%NodCoord( (xn+1)*(yn+1) , 2 )) allocate(obj%ElemNod( xn*yn,4) ) allocate(obj%ElemMat(xn*yn) ) n=0 do j=1, yn+1 do i=1, xn+1 n=n+1 obj%NodCoord(n,1)=lx/dble(xn)*dble(i-1) obj%NodCoord(n,2)=ly/dble(yn)*dble(j-1) enddo enddo if(present(smooth) )then if(smooth .eqv. .true.)then smoothedge(1)=1 smoothedge(2)=xn+1 smoothedge(3)=(xn+1)*yn + 1 smoothedge(4)=(xn+1)*(yn+1) obj%NodCoord(smoothedge(1),1)=obj%NodCoord(smoothedge(1),1)+0.30d0*unitx obj%NodCoord(smoothedge(1),2)=obj%NodCoord(smoothedge(1),2)+0.30d0*unity obj%NodCoord(smoothedge(2),1)=obj%NodCoord(smoothedge(2),1)-0.30d0*unitx obj%NodCoord(smoothedge(2),2)=obj%NodCoord(smoothedge(2),2)+0.30d0*unity obj%NodCoord(smoothedge(3),1)=obj%NodCoord(smoothedge(3),1)+0.30d0*unitx obj%NodCoord(smoothedge(3),2)=obj%NodCoord(smoothedge(3),2)-0.30d0*unity obj%NodCoord(smoothedge(4),1)=obj%NodCoord(smoothedge(4),1)-0.30d0*unitx obj%NodCoord(smoothedge(4),2)=obj%NodCoord(smoothedge(4),2)-0.30d0*unity endif endif n=1 obj%ElemNod(1,1)=1 obj%ElemNod(1,2)=2 obj%ElemNod(1,3)=yn+3 obj%ElemNod(1,4)=yn+2 if(xn>=2)then obj%ElemNod(2,1)=2 obj%ElemNod(2,2)=3 obj%ElemNod(2,3)=yn+4 obj%ElemNod(2,4)=yn+3 endif n=0 do j=1, yn do i=1, xn n=n+1 obj%ElemNod(n,1)=i + (j-1)*(xn+1) obj%ElemNod(n,2)=i+1 + (j-1)*(xn+1) obj%ElemNod(n,3)=xn+2+i+ (j-1)*(xn+1) obj%ElemNod(n,4)=xn+1+i + (j-1)*(xn+1) obj%ElemMat(n)=1 enddo enddo endif if(meshtype=="Root2D")then xn=input(default=1,option=x_num) yn=input(default=1,option=y_num) lx=input(default=1.0d0,option=x_len) ly=input(default=1.0d0,option=y_len) ! creating rectangular mesh allocate(obj%NodCoord( (xn+1)*(yn+1) , 2 )) allocate(obj%ElemNod( xn*yn,4) ) allocate(obj%ElemMat(xn*yn) ) n=0 do j=1, yn+1 do i=1, xn+1 n=n+1 obj%NodCoord(n,1)=lx/dble(xn)*dble(i-1) obj%NodCoord(n,2)=ly/dble(yn)*dble(j-1) enddo enddo n=1 obj%ElemNod(1,1)=1 obj%ElemNod(1,2)=2 obj%ElemNod(1,3)=yn+3 obj%ElemNod(1,4)=yn+2 if(xn>=2)then obj%ElemNod(2,1)=2 obj%ElemNod(2,2)=3 obj%ElemNod(2,3)=yn+4 obj%ElemNod(2,4)=yn+3 endif n=0 do j=1, yn do i=1, xn n=n+1 obj%ElemNod(n,1)=i + (j-1)*(xn+1) obj%ElemNod(n,2)=i+1 + (j-1)*(xn+1) obj%ElemNod(n,3)=xn+2+i+ (j-1)*(xn+1) obj%ElemNod(n,4)=xn+1+i + (j-1)*(xn+1) obj%ElemMat(n)=1 enddo enddo !Lt : Length of root cap !Le : Length of enlongating-zone !Lh : Length of tail !Dr : Diameter of root ! first, shift to the origin call obj%shift(x=-lx*0.50d0) if(.not. present(Lh) )then print *, "createMesh >> ERROR >> Lh should be given." endif if(.not. present(Le) )then print *, "createMesh >> ERROR >> Lh should be given." endif ! get parabolic constant radius=0.50d0*lx a_val=Lh/radius/radius do i=1,xn+1 do j=1,yn+1 x_=obj%NodCoord(i+(xn+1)*(j-1) ,1) obj%NodCoord(i+(xn+1)*(j-1) ,2)=obj%NodCoord(i+(xn+1)*(j-1) ,2)& *(ly - a_val*x_*x_ )/ly obj%NodCoord(i+(xn+1)*(j-1) ,2)=-obj%NodCoord(i+(xn+1)*(j-1) ,2) obj%NodCoord(i+(xn+1)*(j-1) ,1)=-obj%NodCoord(i+(xn+1)*(j-1) ,1) enddo enddo ! Set material IDs ! rootcap=1, enlongating zone =2, and others are 3 obj%ElemMat(:)=3 do i=1,size(obj%ElemMat,1) x_=obj%NodCoord(obj%ElemNod(i,1),2)+obj%NodCoord(obj%ElemNod(i,3),2)& +obj%NodCoord(obj%ElemNod(i,2),2)+obj%NodCoord(obj%ElemNod(i,4),2) x_=x_*0.250d0 if(x_ >= -(y_len-Le-Lh) )then obj%ElemMat(i)=3 elseif( -(y_len-Le-Lh) > x_ .and. x_ > -(y_len-Lh))then obj%ElemMat(i)=2 else obj%ElemMat(i)=1 endif enddo call obj%GetSurface() endif if(meshtype=="RootAndSoil2D")then xn=input(default=1,option=x_num) yn=input(default=1,option=y_num) lx=input(default=1.0d0,option=x_len) ly=input(default=1.0d0,option=y_len) ! creating rectangular mesh allocate(obj%NodCoord( (xn+1)*(yn+1) , 2 )) allocate(obj%ElemNod( xn*yn,4) ) allocate(obj%ElemMat(xn*yn) ) n=0 do j=1, yn+1 do i=1, xn+1 n=n+1 obj%NodCoord(n,1)=lx/dble(xn)*dble(i-1) obj%NodCoord(n,2)=ly/dble(yn)*dble(j-1) enddo enddo n=1 obj%ElemNod(1,1)=1 obj%ElemNod(1,2)=2 obj%ElemNod(1,3)=yn+3 obj%ElemNod(1,4)=yn+2 if(xn>=2)then obj%ElemNod(2,1)=2 obj%ElemNod(2,2)=3 obj%ElemNod(2,3)=yn+4 obj%ElemNod(2,4)=yn+3 endif n=0 do j=1, yn do i=1, xn n=n+1 obj%ElemNod(n,1)=i + (j-1)*(xn+1) obj%ElemNod(n,2)=i+1 + (j-1)*(xn+1) obj%ElemNod(n,3)=xn+2+i+ (j-1)*(xn+1) obj%ElemNod(n,4)=xn+1+i + (j-1)*(xn+1) obj%ElemMat(n)=1 enddo enddo !Lt : Length of root cap !Le : Length of enlongating-zone !Lh : Length of tail !Dr : Diameter of root ! first, shift to the origin call obj%shift(x=-lx*0.50d0) if(.not. present(Lh) )then print *, "createMesh >> ERROR >> Lh should be given." endif if(.not. present(Le) )then print *, "createMesh >> ERROR >> Lh should be given." endif ! get parabolic constant radius=0.50d0*lx a_val=Lh/radius/radius do i=1,xn+1 do j=1,yn+1 x_=obj%NodCoord(i+(xn+1)*(j-1) ,1) obj%NodCoord(i+(xn+1)*(j-1) ,2)=obj%NodCoord(i+(xn+1)*(j-1) ,2)& *(ly - a_val*x_*x_ )/ly obj%NodCoord(i+(xn+1)*(j-1) ,2)=-obj%NodCoord(i+(xn+1)*(j-1) ,2) obj%NodCoord(i+(xn+1)*(j-1) ,1)=-obj%NodCoord(i+(xn+1)*(j-1) ,1) enddo enddo ! Set material IDs ! rootcap=1, enlongating zone =2, and others are 3 obj%ElemMat(:)=3 do i=1,size(obj%ElemMat,1) x_=obj%NodCoord(obj%ElemNod(i,1),2)+obj%NodCoord(obj%ElemNod(i,3),2)& +obj%NodCoord(obj%ElemNod(i,2),2)+obj%NodCoord(obj%ElemNod(i,4),2) x_=x_*0.250d0 if(x_ >= -(y_len-Le-Lh) )then obj%ElemMat(i)=3 elseif( -(y_len-Le-Lh) > x_ .and. x_ > -(y_len-Lh))then obj%ElemMat(i)=2 else obj%ElemMat(i)=1 endif enddo call obj%GetSurface() endif end subroutine createMesh !################################################## subroutine Convert2Dto3DMesh(obj,Thickness,division,smooth) class(Mesh_),intent(inout)::obj real(real64),allocatable::buffer(:,:) real(real64),optional,intent(in)::Thickness integer(int32),optional,intent(in)::division logical,optional,intent(in) :: smooth real(real64) :: Tn integer(int32) :: i,j,n,m,NumOfLayer,numnod ! only for linear elements if(present(Thickness))then if(Thickness==0.0d0)then print *, "ERROR :: Convert2Dto3D >> Thickness = 0" return else Tn=Thickness endif else Tn=1.0d0 endif if(present(division))then if(division==0)then print *, "ERROR :: Convert2Dto3D >> division = 0" return endif NumOfLayer=division else NumOfLayer=1 endif numnod=size(obj%NodCoord,1) n=size(obj%NodCoord,1) m=size(obj%NodCoord,2) allocate(buffer(n*(NumOfLayer+1),3)) do j=1,NumOfLayer+1 do i=1,n buffer( n*(j-1) + i ,1:2) = obj%NodCoord(i,1:2) buffer( n*(j-1) + i ,3) = Tn / dble(NumOfLayer)*dble(j-1) enddo enddo deallocate(obj%NodCoord) allocate(obj%NodCoord( size(buffer,1) ,size(buffer,2) ) ) obj%NodCoord(:,:)=buffer(:,:) deallocate(buffer) ! ElemNod if(.not.allocated(obj%ElemNod) )then print *, "Caution :: Convert2Dto3D >> ElemNod is not allocated = 0" return endif n=size(obj%ElemNod,1) m=size(obj%ElemNod,2) allocate(buffer(n*NumOfLayer,m*2)) do j=1,NumOfLayer do i=1,n buffer( n*(j-1)+i, 1:m ) = obj%ElemNod(i,1:m)+numnod*(j-1) buffer( n*(j-1)+i, m+1:2*m ) = obj%ElemNod(i,1:m)+numnod*(j) enddo enddo deallocate(obj%ElemNod) allocate(obj%ElemNod( size(buffer,1) ,size(buffer,2) ) ) obj%ElemNod(:,:)=buffer(:,:) deallocate(buffer) ! ElemMat if(.not.allocated(obj%ElemMat) )then print *, "Caution :: Convert2Dto3D >> ElemMat is not allocated = 0" return endif allocate(buffer(n*NumOfLayer,1)) do j=1,NumOfLayer do i=1,n buffer( n*(j-1)+i, 1 ) = obj%ElemMat(i) enddo enddo deallocate(obj%ElemMat) allocate(obj%ElemMat( size(buffer,1) ) ) obj%ElemMat(:)=buffer(:,1) deallocate(buffer) end subroutine !################################################## !################################################## subroutine remeshMesh(obj,meshtype,x_num,y_num,x_len,y_len,Le,Lh,Dr,thickness,& division,smooth,top,margin,inclineRate,shaperatio,master,slave,x,y,z,dx,dy,dz,coordinate) class(Mesh_),intent(inout) :: obj type(Mesh_) :: mesh1,mesh2,interface1,interface2 type(Mesh_),optional,intent(inout) :: master,slave type(IO_) :: f type(ShapeFunction_) :: shape character(*),optional,intent(in) :: meshtype logical,optional,intent(in) :: smooth integer(int32),optional,intent(in) :: x_num,y_num ! number of division integer(int32),optional,intent(in) :: division ! for 3D rectangular real(real64),optional,intent(in) :: x_len,y_len,Le,Lh,Dr,coordinate(:,:) ! length real(real64),optional,intent(in) :: thickness,inclineRate ! for 3D rectangular real(real64),optional,intent(in) :: top,margin ! for 3D rectangular real(real64),optional,intent(in) :: shaperatio ! for 3D leaf real(real64),optional,intent(in) :: x,y,z,dx,dy,dz integer(int32) :: i,j,n,m,xn,yn,smoothedge(8),ini,k,dim_num,node_num,elem_num real(real64)::lx,ly,sx,sy,a_val,radius,x_,y_,diflen,Lt,& unitx,unity,xm, ym,tp,rx,ry,zc,zl,zm,ysize,ox,oy,dist,rr logical :: validmeshtype=.false. type(Mesh_) :: BoundBox real(real64)::ymin,ymax,ratio,width,pi,xx,yy,xvec(3),x_max(3),& x_min(3),x_m_mid(3),x_s_mid(3),x1vec(3),x2vec(3),nvec(3),hvec(3) integer(int32),allocatable:: OutNodeID(:),OutElementID(:) logical :: inside real(real64):: dist_tr, dist_cur,z_,zval1,zval2,x_1(3),x_2(3) integer(int32) :: num_layer,itr,node1,node2,node3,node4,count,prev_node1 integer(int32), allocatable :: elemnod(:,:) integer(int32) :: nearest_node_id,nearest_facet_id,node_id,elist(2),tri_excep,tri_excep_last integer(int32),allocatable :: checked(:),checked_node(:) real(real64),allocatable ::nodcoord(:,:) real(real64) :: ll,center(3),vector(3),e1(3),e2(3),e3(3),len_val ! remesh ! only for build-in meshtypes if(trim(obj%meshtype)=="")then print *, "ERROR :: remeshMesh >> only for build-in meshtypes, & so the object should have created by createMesh" return endif call mesh1%create(meshtype=meshtype,x_num=x_num,y_num=y_num,x_len=x_len,y_len=y_len,Le=Le,Lh=Lh,Dr=Dr,thickness=thickness,& division=division,smooth=smooth,top=top,margin=margin,inclineRate=inclineRate,shaperatio=shaperatio,master=master,& slave=slave,x=x,y=y,z=z,dx=dx,dy=dy,dz=dz,coordinate=coordinate) obj%nodcoord = mesh1%nodcoord obj%elemnod = mesh1%elemnod obj%elemmat = mesh1%elemmat end subroutine !################################################## ! ############################################## subroutine shiftMesh(obj,x,y,z) class(Mesh_),intent(inout)::obj real(real64),optional,intent(in) :: x,y,z if(present(x) )then obj%NodCoord(:,1)=obj%NodCoord(:,1)+x endif if(present(y) )then obj%NodCoord(:,2)=obj%NodCoord(:,2)+y endif if(present(z) )then obj%NodCoord(:,3)=obj%NodCoord(:,3)+z endif end subroutine shiftMesh ! ############################################## subroutine checkMesh(obj) class(Mesh_),intent(inout)::obj integer(int32) :: i,j,n,m,a,b,c,k,l integer(int32),allocatable :: Elem(:) real(real64) :: x1(3),x2(3),x3(3),dp,normalvec(3) if(.not. allocated(obj%NodCoord))then print *, "Check-mesh :: ERROR >> nodal coordiate is empty" stop endif if(.not. allocated(obj%ElemNod))then print *, "Check-mesh :: ERROR >> Element-connectivity is empty" stop endif n=size(obj%ElemNod,2) m=size(obj%NodCoord,2) allocate(Elem(n)) if(n==4 .and. m==2)then do i=1,size(obj%ElemNod,1) !check node-order Elem(1:n)=obj%ElemNod(i,1:n) x1(:)=0.0d0 x2(:)=0.0d0 x1(1:2)=obj%NodCoord(Elem(2),1:2)-obj%NodCoord(Elem(1),1:2) x2(1:2)=obj%NodCoord(Elem(4),1:2)-obj%NodCoord(Elem(1),1:2) x3(:)=cross_product(x1,x2) normalvec(:)=0.0d0 normalvec(3)=1.0d0 dp=dot_product(x3,normalvec) if(dp <= 0)then !print *, dp !print *, normalvec !print *, x3(:) !print *, x2(:) !print *, x1(:) !print *, elem(:) !print *, obj%NodCoord(Elem(1),1:2), obj%NodCoord(Elem(2),1)-obj%NodCoord(Elem(1),1),& ! obj%NodCoord(Elem(2),2)-obj%NodCoord(Elem(1),2) !print *, obj%NodCoord(Elem(2),1:2), obj%NodCoord(Elem(3),1)-obj%NodCoord(Elem(2),1),& ! obj%NodCoord(Elem(3),2)-obj%NodCoord(Elem(2),2) !print *, obj%NodCoord(Elem(3),1:2), obj%NodCoord(Elem(4),1)-obj%NodCoord(Elem(3),1),& ! obj%NodCoord(Elem(4),2)-obj%NodCoord(Elem(3),2) !print *, obj%NodCoord(Elem(4),1:2), obj%NodCoord(Elem(1),1)-obj%NodCoord(Elem(4),1),& ! obj%NodCoord(Elem(1),2)-obj%NodCoord(Elem(4),2) print *, "Check-mesh :: ERROR >> Order of the connectivity is wrong!" ! modify connectivity do j=1,n obj%ElemNod(i,j)=elem(n-j+1) enddo print *, "Check-mesh :: OK >> ERROR is modified!" else cycle endif enddo print *, "Mesh-connectivity is OK" else print *, "Element type :: ",m,"dimensional",n,"node iso-parametric element" print *, "Check-mesh :: Sorry not implemented for such types of meshes." stop endif ! surface-node connectivity check only for 4-node isopara call obj%GetSurface() return if(.not.allocated(obj%SurfaceLine2D) )then a=obj%SurfaceLine2D(1) b=obj%SurfaceLine2D(2) do i=1,size(obj%ElemNod,1) do j=1,size(obj%ElemNod,2) if(obj%ElemNod(i,j)==a)then do k=1,size(obj%ElemNod,2) if(b==obj%ElemNod(i,k) )then if(j+1==k .or. j-3==k)then print *, "Check-mesh :: invalid surface-mesh order" stop endif endif enddo endif enddo enddo else endif end subroutine checkMesh ! ############################################## ! ######################################################################################### subroutine gmshMesh(obj,OptionalContorName,OptionalAbb,OptionalStep,Name,withNeumannBC,withDirichletBC& ,onlyNeumannBC,onlyDirichletBC,asMsh,withMaterial,ElemValue,timestep) class(Mesh_),intent(inout)::obj real(real64),allocatable::gp_value(:,:) integer(int32),optional,intent(in)::OptionalStep,timestep character,optional,intent(in):: OptionalAbb*6 character(*),optional,intent(in):: OptionalContorName character(*),optional,intent(in)::Name logical,optional,intent(in)::withNeumannBC,withDirichletBC,onlyNeumannBC,onlyDirichletBC,asMsh,withMaterial real(real64),allocatable::x_double(:,:) real(real64),allocatable::x(:,:) integer(int32) i,j,k,l,step,fh,nodeid1,nodeid2 real(real64),optional,intent(in) :: ElemValue(:,:) character filename0*11 character filename*200 character filetitle*6 character command*200 character:: mapname*30,abbmap*6 if(present(OptionalContorName) )then mapname=OptionalContorName else mapname="Value" endif if(present(OptionalAbb) )then abbmap=OptionalAbb else abbmap="Values" endif if(present(OptionalStep) )then step=OptionalStep elseif(present(timeStep) )then step=timestep else step=1 endif fh=123 filetitle(1:6)=abbmap(1:6) if(.not.allocated(obj%ElemMat) )then allocate(obj%ElemMat(size(obj%ElemNod,1) ) ) obj%ElemMat(:)=1 endif !--------------------- write (filename0, '("_", i6.6, ".pos")') step ! ここでファイル名を生成している if(present(Name) )then filename=filetitle//filename0 !call execute_command_line( "touch "//trim(adjustl(name))//trim(obj%FileName)//trim(filename) ) print *, trim(adjustl(name))//trim(filename) open(fh,file=trim(adjustl(name))//trim(filename) ) print *, "writing ",trim(adjustl(name))//trim(filename)," step>>",step else filename=filetitle//filename0 !call execute_command_line( "touch "//trim(obj%FileName)//trim(filename) ) print *, trim(obj%FileName)//trim(filename) open(fh,file=trim(obj%FileName)//trim(filename) ) print *, "writing ",trim(obj%FileName)//trim(filename)," step>>",step endif !--------------------- if( size(obj%ElemNod,2)==4 .and. size(obj%NodCoord,2)==2 ) then allocate(x(4,3) ) allocate(x_double(4,3) ) x(:,:)=0.0d0 x_double(:,:)=0.0d0 elseif( size(obj%ElemNod,2)==8 .and. size(obj%NodCoord,2)==3 ) then allocate(x(8,3) ) allocate(x_double(8,3) ) x(:,:)=0.0d0 x_double(:,:)=0.0d0 endif allocate(gp_value( size(obj%ElemNod,1),size(obj%ElemNod,2) )) if(.not.allocated(obj%ElemMat))then allocate(obj%ElemMat(size(obj%ElemNod,1)) ) obj%ElemMat(:)=1 endif do i=1,size(obj%ElemNod,1) gp_value(i,:)=input(default=dble(obj%ElemMat(i)),option=ElemValue(i,1)) enddo x(:,:)=0.0d0 write(fh,*) 'View "',mapname,'" {' do i=1,size(gp_value,1) if( size(obj%ElemNod,2)==4 .and. size(obj%NodCoord,2)==2 ) then ! 2-D, 4 noded, isoparametric elements with four gauss points x_double(1,1:2)=obj%NodCoord(obj%ElemNod(i,1),1:2 ) x_double(2,1:2)=0.50d0*obj%NodCoord(obj%ElemNod(i,1),1:2 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,2),1:2 ) x_double(3,1:2)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:2 )+0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:2 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:2 )+0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:2 ) x_double(4,1:2)=0.50d0*obj%NodCoord(obj%ElemNod(i,4),1:2 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,1),1:2 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),"){",gp_value(i,1),",",& gp_value(i,1),",",gp_value(i,1),",",gp_value(i,1),"};" x_double(1,1:2)=obj%NodCoord(obj%ElemNod(i,2),1:2 ) x_double(2,1:2)=0.50d0*obj%NodCoord(obj%ElemNod(i,2),1:2 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,3),1:2 ) x_double(3,1:2)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:2 )+0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:2 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:2 )+0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:2 ) x_double(4,1:2)=0.50d0*obj%NodCoord(obj%ElemNod(i,1),1:2 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,2),1:2 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),"){",gp_value(i,2),",",& gp_value(i,2),",",gp_value(i,2),",",gp_value(i,2),"};" x_double(1,1:2)=obj%NodCoord(obj%ElemNod(i,3),1:2 ) x_double(2,1:2)=0.50d0*obj%NodCoord(obj%ElemNod(i,3),1:2 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,4),1:2 ) x_double(3,1:2)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:2 )+0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:2 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:2 )+0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:2 ) x_double(4,1:2)=0.50d0*obj%NodCoord(obj%ElemNod(i,2),1:2 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,3),1:2 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),"){",gp_value(i,3),",",& gp_value(i,3),",",gp_value(i,3),",",gp_value(i,3),"};" x_double(1,1:2)=obj%NodCoord(obj%ElemNod(i,4),1:2 ) x_double(2,1:2)=0.50d0*obj%NodCoord(obj%ElemNod(i,4),1:2 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,1),1:2 ) x_double(3,1:2)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:2 )+0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:2 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:2 )+0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:2 ) x_double(4,1:2)=0.50d0*obj%NodCoord(obj%ElemNod(i,3),1:2 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,4),1:2 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),"){",gp_value(i,4),",",& gp_value(i,4),",",gp_value(i,4),",",gp_value(i,4),"};" elseif(size(obj%ElemNod,2)==8 .and. size(obj%NodCoord,2)==3 ) then ! 3-D, 8 noded, isoparametric elements with 8 gauss points ! 1/8 x_double(1,1:3)=obj%NodCoord(obj%ElemNod(i,1),1:3 ) x_double(2,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,1), 1:3 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,2),1:3 ) x_double(3,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.250d0*obj%NodCoord(obj%ElemNod(i,2), 1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )+0.250d0*obj%NodCoord(obj%ElemNod(i,4), 1:3 ) x_double(4,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,4), 1:3 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) x_double(5,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) x_double(6,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) x_double(7,1:3)=0.1250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(8,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(1,1),",",x(1,2),",",x(1,3),"){",gp_value(i,1),",",& gp_value(i,1),",",gp_value(i,1),",",gp_value(i,1),"};" write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(5,1),",",x(5,2),",",x(5,3),"){",gp_value(i,1),",",& gp_value(i,1),",",gp_value(i,1),",",gp_value(i,1),"};" write(fh,*)" SQ(",x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(6,1),",",x(6,2),",",x(6,3),"){",gp_value(i,1),",",& gp_value(i,1),",",gp_value(i,1),",",gp_value(i,1),"};" write(fh,*)" SQ(",x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),","& ,x(8,1),",",x(8,2),",",x(8,3),","& ,x(7,1),",",x(7,2),",",x(7,3),"){",gp_value(i,1),",",& gp_value(i,1),",",gp_value(i,1),",",gp_value(i,1),"};" write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(1,1),",",x(1,2),",",x(1,3),","& ,x(5,1),",",x(5,2),",",x(5,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,1),",",& gp_value(i,1),",",gp_value(i,1),",",gp_value(i,1),"};" write(fh,*)" SQ(",x(5,1),",",x(5,2),",",x(5,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,1),",",& gp_value(i,1),",",gp_value(i,1),",",gp_value(i,1),"};" ! 2/8 x_double(1,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,1), 1:3 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,2),1:3 ) x_double(2,1:3)=obj%NodCoord(obj%ElemNod(i,2),1:3 ) x_double(3,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,2), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) x_double(4,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 ) x_double(5,1:3)= 0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) x_double(6,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,2), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) x_double(7,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(8,1:3)=0.1250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(1,1),",",x(1,2),",",x(1,3),"){",gp_value(i,2),",",& gp_value(i,2),",",gp_value(i,2),",",gp_value(i,2),"};" write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(5,1),",",x(5,2),",",x(5,3),"){",gp_value(i,2),",",& gp_value(i,2),",",gp_value(i,2),",",gp_value(i,2),"};" write(fh,*)" SQ(",x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(6,1),",",x(6,2),",",x(6,3),"){",gp_value(i,2),",",& gp_value(i,2),",",gp_value(i,2),",",gp_value(i,2),"};" write(fh,*)" SQ(",x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),","& ,x(8,1),",",x(8,2),",",x(8,3),","& ,x(7,1),",",x(7,2),",",x(7,3),"){",gp_value(i,2),",",& gp_value(i,2),",",gp_value(i,2),",",gp_value(i,2),"};" write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(1,1),",",x(1,2),",",x(1,3),","& ,x(5,1),",",x(5,2),",",x(5,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,2),",",& gp_value(i,2),",",gp_value(i,2),",",gp_value(i,2),"};" write(fh,*)" SQ(",x(5,1),",",x(5,2),",",x(5,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,2),",",& gp_value(i,2),",",gp_value(i,2),",",gp_value(i,2),"};" ! 3/8 x_double(8,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(3,1:3)=obj%NodCoord(obj%ElemNod(i,3),1:3 ) x_double(2,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,2), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) x_double(1,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 ) x_double(6,1:3)= 0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) x_double(7,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,3), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(4,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,4),1:3 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) x_double(5,1:3)=0.1250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(1,1),",",x(1,2),",",x(1,3),"){",gp_value(i,3),",",& gp_value(i,3),",",gp_value(i,3),",",gp_value(i,3),"};" write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(5,1),",",x(5,2),",",x(5,3),"){",gp_value(i,3),",",& gp_value(i,3),",",gp_value(i,3),",",gp_value(i,3),"};" write(fh,*)" SQ(",x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(6,1),",",x(6,2),",",x(6,3),"){",gp_value(i,3),",",& gp_value(i,3),",",gp_value(i,3),",",gp_value(i,3),"};" write(fh,*)" SQ(",x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),","& ,x(8,1),",",x(8,2),",",x(8,3),","& ,x(7,1),",",x(7,2),",",x(7,3),"){",gp_value(i,3),",",& gp_value(i,3),",",gp_value(i,3),",",gp_value(i,3),"};" write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(1,1),",",x(1,2),",",x(1,3),","& ,x(5,1),",",x(5,2),",",x(5,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,3),",",& gp_value(i,3),",",gp_value(i,3),",",gp_value(i,3),"};" write(fh,*)" SQ(",x(5,1),",",x(5,2),",",x(5,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,3),",",& gp_value(i,3),",",gp_value(i,3),",",gp_value(i,3),"};" ! 4/8 x_double(6,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(3,1:3)=obj%NodCoord(obj%ElemNod(i,4),1:3 ) x_double(7,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,4), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(1,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 ) x_double(8,1:3)= 0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) x_double(4,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,4), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) x_double(2,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,4),1:3 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) x_double(5,1:3)=0.1250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(1,1),",",x(1,2),",",x(1,3),"){",gp_value(i,4),",",& gp_value(i,4),",",gp_value(i,4),",",gp_value(i,4),"};" write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(5,1),",",x(5,2),",",x(5,3),"){",gp_value(i,4),",",& gp_value(i,4),",",gp_value(i,4),",",gp_value(i,4),"};" write(fh,*)" SQ(",x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(6,1),",",x(6,2),",",x(6,3),"){",gp_value(i,4),",",& gp_value(i,4),",",gp_value(i,4),",",gp_value(i,4),"};" write(fh,*)" SQ(",x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),","& ,x(8,1),",",x(8,2),",",x(8,3),","& ,x(7,1),",",x(7,2),",",x(7,3),"){",gp_value(i,4),",",& gp_value(i,4),",",gp_value(i,4),",",gp_value(i,4),"};" write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(1,1),",",x(1,2),",",x(1,3),","& ,x(5,1),",",x(5,2),",",x(5,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,4),",",& gp_value(i,4),",",gp_value(i,4),",",gp_value(i,4),"};" write(fh,*)" SQ(",x(5,1),",",x(5,2),",",x(5,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,4),",",& gp_value(i,4),",",gp_value(i,4),",",gp_value(i,4),"};" ! 5/8 x_double(7,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(5,1:3)=obj%NodCoord(obj%ElemNod(i,5),1:3 ) x_double(6,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,5), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) x_double(2,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) x_double(4,1:3)= 0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) x_double(1,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,5), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) x_double(8,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(3,1:3)=0.1250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(1,1),",",x(1,2),",",x(1,3),"){",gp_value(i,5),",",& gp_value(i,5),",",gp_value(i,5),",",gp_value(i,5),"};" write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(5,1),",",x(5,2),",",x(5,3),"){",gp_value(i,5),",",& gp_value(i,5),",",gp_value(i,5),",",gp_value(i,5),"};" write(fh,*)" SQ(",x(2,1),",",x(2,2),",",x(2,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(7,1),",",x(7,2),",",x(7,3),"){",gp_value(i,5),",",& gp_value(i,5),",",gp_value(i,5),",",gp_value(i,5),"};" write(fh,*)" SQ(",x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),","& ,x(8,1),",",x(8,2),",",x(8,3),","& ,x(7,1),",",x(7,2),",",x(7,3),"){",gp_value(i,5),",",& gp_value(i,5),",",gp_value(i,5),",",gp_value(i,5),"};" write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(1,1),",",x(1,2),",",x(1,3),","& ,x(5,1),",",x(5,2),",",x(5,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,5),",",& gp_value(i,5),",",gp_value(i,5),",",gp_value(i,5),"};" write(fh,*)" SQ(",x(5,1),",",x(5,2),",",x(5,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,5),",",& gp_value(i,5),",",gp_value(i,5),",",gp_value(i,5),"};" ! 6/8 x_double(8,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(6,1:3)=obj%NodCoord(obj%ElemNod(i,6),1:3 ) x_double(5,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,5), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) x_double(1,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) x_double(3,1:3)= 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) x_double(2,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,6), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,2),1:3 ) x_double(7,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(4,1:3)=0.1250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(1,1),",",x(1,2),",",x(1,3),"){",gp_value(i,6),",",& gp_value(i,6),",",gp_value(i,6),",",gp_value(i,6),"};" write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(5,1),",",x(5,2),",",x(5,3),"){",gp_value(i,6),",",& gp_value(i,6),",",gp_value(i,6),",",gp_value(i,6),"};" write(fh,*)" SQ(",x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(6,1),",",x(6,2),",",x(6,3),"){",gp_value(i,6),",",& gp_value(i,6),",",gp_value(i,6),",",gp_value(i,6),"};" write(fh,*)" SQ(",x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),","& ,x(8,1),",",x(8,2),",",x(8,3),","& ,x(7,1),",",x(7,2),",",x(7,3),"){",gp_value(i,6),",",& gp_value(i,6),",",gp_value(i,6),",",gp_value(i,6),"};" write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(1,1),",",x(1,2),",",x(1,3),","& ,x(5,1),",",x(5,2),",",x(5,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,6),",",& gp_value(i,6),",",gp_value(i,6),",",gp_value(i,6),"};" write(fh,*)" SQ(",x(5,1),",",x(5,2),",",x(5,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,6),",",& gp_value(i,6),",",gp_value(i,6),",",gp_value(i,6),"};" ! 7/8 x_double(5,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(7,1:3)=obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(8,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,7), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(4,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(2,1:3)= 0.250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(3,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,3), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(6,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,6),1:3 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(1,1:3)=0.1250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(1,1),",",x(1,2),",",x(1,3),"){",gp_value(i,7),",",& gp_value(i,7),",",gp_value(i,7),",",gp_value(i,7),"};" write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(5,1),",",x(5,2),",",x(5,3),"){",gp_value(i,7),",",& gp_value(i,7),",",gp_value(i,7),",",gp_value(i,7),"};" write(fh,*)" SQ(",x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(6,1),",",x(6,2),",",x(6,3),"){",gp_value(i,7),",",& gp_value(i,7),",",gp_value(i,7),",",gp_value(i,7),"};" write(fh,*)" SQ(",x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),","& ,x(8,1),",",x(8,2),",",x(8,3),","& ,x(7,1),",",x(7,2),",",x(7,3),"){",gp_value(i,7),",",& gp_value(i,7),",",gp_value(i,7),",",gp_value(i,7),"};" write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(1,1),",",x(1,2),",",x(1,3),","& ,x(5,1),",",x(5,2),",",x(5,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,7),",",& gp_value(i,7),",",gp_value(i,7),",",gp_value(i,7),"};" write(fh,*)" SQ(",x(5,1),",",x(5,2),",",x(5,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,7),",",& gp_value(i,7),",",gp_value(i,7),",",gp_value(i,7),"};" ! 8/8 x_double(5,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) x_double(7,1:3)=obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(6,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,7), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(2,1:3)=0.250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(4,1:3)= 0.250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(3,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,4), 1:3 )+0.50d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(8,1:3)=0.50d0*obj%NodCoord(obj%ElemNod(i,5),1:3 ) + 0.50d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x_double(1,1:3)=0.1250d0*obj%NodCoord(obj%ElemNod(i,1),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,2),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,3),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,4),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,5),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,6),1:3 )& +0.1250d0*obj%NodCoord(obj%ElemNod(i,7),1:3 )+0.1250d0*obj%NodCoord(obj%ElemNod(i,8),1:3 ) x(:,:)=x_double(:,:) write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(1,1),",",x(1,2),",",x(1,3),"){",gp_value(i,8),",",& gp_value(i,8),",",gp_value(i,8),",",gp_value(i,8),"};" write(fh,*)" SQ(",x(1,1),",",x(1,2),",",x(1,3),","& ,x(2,1),",",x(2,2),",",x(2,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(5,1),",",x(5,2),",",x(5,3),"){",gp_value(i,8),",",& gp_value(i,8),",",gp_value(i,8),",",gp_value(i,8),"};" write(fh,*)" SQ(",x(2,1),",",x(2,2),",",x(2,3),","& ,x(3,1),",",x(3,2),",",x(3,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(6,1),",",x(6,2),",",x(6,3),"){",gp_value(i,8),",",& gp_value(i,8),",",gp_value(i,8),",",gp_value(i,8),"};" write(fh,*)" SQ(",x(3,1),",",x(3,2),",",x(3,3),","& ,x(4,1),",",x(4,2),",",x(4,3),","& ,x(8,1),",",x(8,2),",",x(8,3),","& ,x(7,1),",",x(7,2),",",x(7,3),"){",gp_value(i,8),",",& gp_value(i,8),",",gp_value(i,8),",",gp_value(i,8),"};" write(fh,*)" SQ(",x(4,1),",",x(4,2),",",x(4,3),","& ,x(1,1),",",x(1,2),",",x(1,3),","& ,x(5,1),",",x(5,2),",",x(5,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,8),",",& gp_value(i,8),",",gp_value(i,8),",",gp_value(i,8),"};" write(fh,*)" SQ(",x(5,1),",",x(5,2),",",x(5,3),","& ,x(6,1),",",x(6,2),",",x(6,3),","& ,x(7,1),",",x(7,2),",",x(7,3),","& ,x(8,1),",",x(8,2),",",x(8,3),"){",gp_value(i,8),",",& gp_value(i,8),",",gp_value(i,8),",",gp_value(i,8),"};" else print *, " size(obj%ElemNod,2)==",size(obj%ElemNod,2) print *, ".and. size(obj%NodCoord,2)==",size(obj%NodCoord,2) stop "plot_contour >> now constructing" endif enddo write(fh,*) '};' close(fh) end subroutine !=========================================================================================== subroutine showRangeMesh(obj) class(Mesh_),intent(in) :: obj real(real64) :: x_max, x_min,y_max, y_min, z_max, z_min x_max = maxval(obj%NodCoord(:,1) ) x_min = minval(obj%NodCoord(:,1) ) y_max = maxval(obj%NodCoord(:,2) ) y_min = minval(obj%NodCoord(:,2) ) z_max = maxval(obj%NodCoord(:,3) ) z_min = minval(obj%NodCoord(:,3) ) print *, " x_max=", x_max, " x_min=", x_min,& " y_max=",y_max, " y_min=", y_min, & " z_max=", z_max, " z_min=", z_min end subroutine !=========================================================================================== function emptyMesh(obj) result(res) class(Mesh_),intent(in) :: obj logical :: res integer(int32) :: cn cn=0 if(allocated(obj%NodCoord) )then cn=cn+1 endif if(allocated(obj%ElemNod) )then cn=cn+1 endif if(cn==0)then res=.true. else res=.false. endif end function ! ################################################################################ ! ################################################################################ function divideMesh(obj,n) result(meshes) class(Mesh_),intent(inout) :: obj class(Mesh_),allocatable :: meshes(:) integer(int32),intent(in) :: n integer(int32) :: i,j,k,l,m,mesh_num,loc_elem_num,elem_num,elem_type,dim_num integer(int32) :: cur_node_id,cur_elem_id,local_id,global_id,num_loc_node logical,allocatable :: selected(:) integer(int32),allocatable :: global_vs_local(:,:) integer(int32),allocatable :: buffer(:,:) logical :: tf if(n<2)then allocate(meshes(1)) call meshes(1)%copy(obj) return endif ! divide mesh by the Greedy algorithm. mesh_num = input(default=2, option=n) allocate(meshes(mesh_num) ) elem_num = size(obj%ElemNod,1) elem_type = size(obj%ElemNod,2) allocate(selected(elem_num) ) selected(:) = .false. loc_elem_num=int(elem_num/mesh_num) ! count number of mesh k=0 do i=1,mesh_num if(i<=mod(elem_num,mesh_num) )then allocate( meshes(i)%ElemNod(loc_elem_num+1, elem_type) ) allocate( meshes(i)%ElemMat(loc_elem_num+1 ) ) meshes(i)%ElemMat(:)=1 else allocate(meshes(i)%ElemNod(loc_elem_num,elem_type) ) allocate( meshes(i)%ElemMat(loc_elem_num ) ) meshes(i)%ElemMat(:)=1 endif enddo do i=1, size(meshes) print *, size(meshes(i)%ElemNod,1) enddo do i=1,size(meshes) do j=1,size(selected) if(selected(j) .eqv. .false. )then cur_elem_id=j exit endif enddo k=1 meshes(i)%ElemNod(k,:) = obj%ElemNod(cur_elem_id,:) selected(cur_elem_id)=.true. ! search neighbor element do l=cur_elem_id+1, elem_num if(k==size(meshes(i)%ElemNod,1) )then exit endif if(selected(l) .eqv. .true. )then cycle endif m=countifsame(meshes(i)%ElemNod(k,:),obj%ElemNod(l,:) ) if( m<=0)then ! no contact cycle else ! contact k=k+1 meshes(i)%ElemNod(k,:)=obj%ElemNod(l,:) selected(l)=.true. endif enddo enddo local_id=0 do i=1,size(meshes,1) allocate(global_vs_local(1,2) ) do j=1,size(meshes(i)%ElemNod,1) do k=1,size(meshes(i)%ElemNod,2) global_id=meshes(i)%ElemNod(j,k) if(m==0)then local_id=local_id+1 global_vs_local(1,1)=global_id ! global node id global_vs_local(1,2)=local_id ! local node id else tf=exist(vector=global_vs_local,val=global_id,columnid=1 ) if(tf .eqv. .true. )then cycle else call extend(mat=global_vs_local) local_id=local_id+1 global_vs_local(1,1)=global_id ! global node id global_vs_local(1,2)=local_id ! local node id endif endif enddo enddo ! change node-ids and allocate nodal-coordinat num_loc_node=size(global_vs_local) dim_num=size(obj%NodCoord,2) allocate(buffer(size(meshes(i)%ElemNod,1),size(meshes(i)%ElemNod,2) ) ) allocate(meshes(i)%NodCoord(num_loc_node,dim_num) ) do j=1,size(global_vs_local,1) ! update node id meshes(i)%NodCoord(global_vs_local(j,2),:) = obj%NodCoord(global_vs_local(j,1),: ) ! update elem_id do k=1,size(meshes(i)%ElemNod,1) do l=1,size(meshes(i)%ElemNod,2) if( meshes(i)%ElemNod(k,l) == global_vs_local(j,1) )then buffer(k,l) = global_vs_local(j,2) endif enddo enddo enddo meshes(i)%ElemNod(:,:)=buffer(:,:) deallocate(global_vs_local) deallocate(buffer) enddo end function ! ################################################################################ !####################################################################################### function HowManyDomainMesh(obj) result(ret) class(Mesh_),intent(in) :: obj integer(int32) :: ret, i,j,itr,k,n integer(int32),allocatable :: domain_id(:) ! if(obj%empty() .eqv. .true.)then ! print *, "HowManyDomainMesh :: obj%empty() .eqv. .true." ! return ! endif ! ! n=size(obj%NodCoord,1) ! allocate(domain_id(n) ) ! domain_id(:)=-1 ! k=1 ! domain_id(1)=1 ! do ! ! if(minval(domain_id)/=-1 )then ! exit ! endif ! enddo end function !####################################################################################### !####################################################################################### function getNodeListMesh(obj,BoundingBox,xmin,xmax,ymin,ymax,zmin,zmax) result(NodeList) class(Mesh_),intent(inout) :: obj type(Mesh_),optional,intent(inout) :: BoundingBox real(real64),optional,intent(in) :: xmin,xmax,ymin,ymax,zmin,zmax integer(int32),allocatable :: NodeList(:) integer(int32) :: i,j,n,num_of_node,m logical ,allocatable:: tf(:) real(real64),allocatable :: x(:),x_min(:),x_max(:) n=size(obj%NodCoord,1) m=size(obj%NodCoord,2) allocate( x(m),x_min(m),x_max(m),tf(n) ) if(present(BoundingBox) )then num_of_node=0 do i=1,n x(:)=obj%NodCoord(i,:) do j=1,m x_min(j)=minval(BoundingBox%NodCoord(:,j)) x_max(j)=maxval(BoundingBox%NodCoord(:,j)) enddo tf(i)=.false. tf(i) = InOrOut(x=x,xmax=x_max,xmin=x_min,DimNum=m) enddo else if(m==3)then x_min(1)=input(default=-dble(1.0e+18),option=xmin) x_min(2)=input(default=-dble(1.0e+18),option=ymin) x_min(3)=input(default=-dble(1.0e+18),option=zmin) x_max(1)=input(default= dble(1.0e+18),option=xmax) x_max(2)=input(default= dble(1.0e+18),option=ymax) x_max(3)=input(default= dble(1.0e+18),option=zmax) else print *, "Stop >> getNodeListMesh is supproted for 3D" stop endif num_of_node=0 do i=1,n x(:)=obj%NodCoord(i,:) tf(i)=.false. tf(i) = InOrOut(x=x,xmax=x_max,xmin=x_min,DimNum=m) enddo endif n=countif(Vector=tf,tf=.true.) allocate(NodeList(n) ) j=0 do i=1,size(tf) if(tf(i) .eqv. .true. )then j=j+1 NodeList(j) = i endif enddo end function !####################################################################################### !####################################################################################### function getFacetListMesh(obj,NodeID) result(FacetList) class(Mesh_),intent(inout) :: obj integer(int32),intent(in) :: NodeID integer(int32),allocatable :: FacetList(:,:) ! Node-ID = FacetList(FacetID, LocalNodeID ) integer(int32) :: i,j,k,l,count_id integer(int32) :: node_per_Facet = 4 integer(int32),allocatable :: ElementList(:),NodeList(:,:),CountNodeList(:,:) ! Facetとってからcheckのほうが簡単 ! search facets, in which a node is in ElementList = obj%getElementList(NodeID=NodeID) allocate(FacetList(size(ElementList),node_per_Facet ) ) FacetList(:,:) = 0 allocate(Nodelist(size(ElementList),size(obj%ElemNod,2) ) ) allocate(CountNodelist(size(ElementList),size(obj%ElemNod,2) ) ) CountNodelist(:,:) = 1 ! get all nodes do i=1,size(ElementList) NodeList(i,:) = obj%ElemNod(ElementList(i),: ) enddo do i=1,size(NodeList,1) do j=1,size(NodeList,2) do k=i+1,size(NodeList,1) do l=1,size(NodeList,2) if(NodeList(i,j)==0) then cycle endif if(NodeList(k,l)==0) then cycle endif if(NodeList(i,j) == NodeList(k,l) )then NodeList(k,l) = 0 CountNodeList(i,j) = CountNodeList(i,j) + 1 endif enddo enddo enddo enddo do i=1,size(NodeList,1) do j=1,size(NodeList,2) if(CountNodeList(i,j)==0 .or. CountNodeList(i,j)==1)then NodeList(i,j) = 0 endif enddo enddo call print(CountNodeList) call print("****") call print(NodeList) end function !####################################################################################### !####################################################################################### function getElementListMesh(obj,BoundingBox,xmin,xmax,ymin,ymax,zmin,zmax,NodeID) result(ElementList) class(Mesh_),intent(inout) :: obj type(Mesh_),optional,intent(inout) :: BoundingBox real(real64),optional,intent(in) :: xmin,xmax,ymin,ymax,zmin,zmax integer(int32),optional,intent(in) :: NodeID integer(int32),allocatable :: NodeList(:) integer(int32),allocatable :: ElementList(:) integer(int32) :: i,j,n,num_of_node,m,counter,k logical ,allocatable:: tf(:),exist real(real64),allocatable :: x(:),x_min(:),x_max(:) if(present(NodeID) )then if(obj%empty() .eqv. .true. )then call print("getElementListMesh >> obj%empty() .eqv. .true. ") allocate(ElementList(0)) return endif n = 0 do i=1,size(obj%elemnod,1) do j=1,size(obj%elemnod,2) if(obj%elemnod(i,j)==NodeID)then n = n + 1 exit endif enddo enddo allocate(ElementList(n) ) n = 0 do i=1,size(obj%elemnod,1) do j=1,size(obj%elemnod,2) if(obj%elemnod(i,j)==NodeID)then n = n + 1 ElementList(n) = i exit endif enddo enddo return endif NodeList = obj%getNodeList(BoundingBox,xmin,xmax,ymin,ymax,zmin,zmax) counter=0 do i=1,size(obj%ElemNod,1) exist=.false. do j=1,size(obj%ElemNod,2) do k=1,size(NodeList,1) if( obj%ElemNod(i,j) == Nodelist(k) )then exist=.true. exit endif enddo if(exist .eqv. .true.)then exit endif enddo if(exist .eqv. .true. )then counter=counter+1 else cycle endif enddo allocate(ElementList(counter) ) counter=0 do i=1,size(obj%ElemNod,1) exist=.false. do j=1,size(obj%ElemNod,2) do k=1,size(NodeList,1) if( obj%ElemNod(i,j) == Nodelist(k) )then exist=.true. exit endif enddo if(exist .eqv. .true.)then exit endif enddo if(exist .eqv. .true. )then counter=counter+1 ElementList(counter) = i else cycle endif enddo end function !####################################################################################### !####################################################################################### function getVolumeMesh(obj) result(volume) class(Mesh_),intent(inout) :: obj real(real64),allocatable :: volume(:),eNodCoord(:,:) integer(int32) :: i,j,numelem, numelemnod,numnode,dimnum if(obj%empty() .eqv. .true. )then print *, "getVolumeMesh >> Mesh is empty." return endif numelem = size(obj%ElemNod,1) numelemnod = size(obj%ElemNod,2) numnode = size(obj%NodCoord,1) dimnum = size(obj%NodCoord,2) allocate( volume(numelem) ) allocate(eNodCoord(numelemnod, dimnum) ) if(numelemnod == 8)then do i=1,numelem do j=1, numelemnod eNodCoord(j,:)=obj%NodCoord( obj%ElemNod(i,j) ,:) enddo enddo else print *, "getVolumeMesh >> Not imlemented." stop endif end function !####################################################################################### !####################################################################################### function numElementsMesh(obj) result(ret) class(Mesh_),intent(in) :: obj integer(int32) :: ret if(obj%empty() .eqv. .true. )then ret = 0 return endif ret = size(obj%ElemNod,1) end function !####################################################################################### !####################################################################################### function numNodesMesh(obj) result(ret) class(Mesh_),intent(in) :: obj integer(int32) :: ret if(obj%empty() .eqv. .true. )then ret = 0 return endif ret = size(obj%NodCoord,1) end function !####################################################################################### !####################################################################################### function numNodesForEachElementMesh(obj) result(ret) class(Mesh_),intent(in) :: obj integer(int32) :: ret if(obj%empty() .eqv. .true. )then ret = 0 return endif ret = size(obj%ElemNod,2) end function !####################################################################################### !####################################################################################### function numDimensionMesh(obj) result(ret) class(Mesh_),intent(in) :: obj integer(int32) :: ret if(obj%empty() .eqv. .true. )then ret = 0 return endif ret = size(obj%NodCoord,2) end function !####################################################################################### !####################################################################################### subroutine jsonMesh(obj,name,fh,endl) class(Mesh_),intent(in) :: obj type(IO_) :: f integer(int32),optional,intent(in) :: fh character(*),optional,intent(in) :: name integer(int32) :: fileid,i,j logical,optional,intent(in) :: endl ! export JSON file if(present(name) )then call f%open(name) fileid=f%fh else fileid=fh endif if(present(name) )then call f%write('{') write(fileid,*) '"name": "'//trim(name)//'",' endif write(fileid,*) '"mesh":{' if(allocated(obj%nodcoord) )then call json(array=obj%nodcoord,fh=fileid,name="NodCoord") endif if(allocated(obj%NodCoordInit) )then call json(array=obj%NodCoordInit,fh=fileid,name="NodCoordInit") endif if(allocated(obj%ElemNod) )then call json(array=obj%ElemNod,fh=fileid,name="ElemNod") endif if(allocated(obj%FacetElemNod) )then call json(array=obj%FacetElemNod,fh=fileid,name="FacetElemNod") endif if(allocated(obj%NextFacets) )then call json(array=obj%NextFacets,fh=fileid,name="NextFacets") endif if(allocated(obj%SurfaceLine2D) )then call json(array=obj%SurfaceLine2D,fh=fileid,name="SurfaceLine2D") endif if(allocated(obj%ElemMat) )then call json(array=obj%ElemMat,fh=fileid,name="ElemMat") endif if(allocated(obj%SubMeshNodFromTo) )then call json(array=obj%SubMeshNodFromTo,fh=fileid,name="SubMeshNodFromTo") endif if(allocated(obj%SubMeshElemFromTo) )then call json(array=obj%SubMeshElemFromTo,fh=fileid,name="SubMeshElemFromTo") endif if(allocated(obj%SubMeshSurfFromTo) )then call json(array=obj%SubMeshSurfFromTo,fh=fileid,name="SubMeshSurfFromTo") endif if(allocated(obj%GlobalNodID) )then call json(array=obj%GlobalNodID,fh=fileid,name="GlobalNodID") endif write(fileid,*) '"return_mesh":0' ! integer(int32),allocatable::BottomElemID ! integer(int32),allocatable::TopElemID ! integer(int32) :: surface=1 ! ! ! character*200::FileName=" " ! character*70::ElemType=" " ! character*70:: ErrorMsg=" " if(present(endl) )then if(endl .eqv. .false.)then write(fileid,*) '},' else write(fileid,*) '}' endif else write(fileid,*) '}' endif if(present(name) )then call f%close() endif end subroutine !####################################################################################### !####################################################################################### subroutine cleanMesh(obj) class(Mesh_),intent(inout) :: obj integer(int32) :: i,j,n,num_dim integer(int32),allocatable :: removes(:) real(real64),allocatable :: nodcoord(:,:) allocate(removes( size(obj%nodcoord,1) ) ) removes(:) = 1 num_dim =size(obj%nodcoord,2) do i=1,size(obj%ElemNod,1) do j=1, size(obj%ElemNod,2) removes(obj%ElemNod(i,j) ) = 0 enddo enddo n = size(obj%nodcoord,1) - sum(removes) allocate(nodcoord(n,num_dim) ) n=0 do i=1,size(removes) if(removes(i)==0 )then n=n+1 nodcoord(n,:) = obj%nodcoord(i,:) else cycle endif enddo obj%nodcoord = nodcoord do i=1,size(obj%elemnod,1) do j=1,size(obj%elemnod,2) obj%elemnod(i,j)=obj%elemnod(i,j)-sum(removes(1:obj%elemnod(i,j)) ) enddo enddo end subroutine !####################################################################################### !################################################################################ function nearestElementIDMesh(obj,x,y,z) result(ret) class(Mesh_),intent(inout) :: obj real(real64),optional,intent(in) :: x,y,z real(real64),allocatable :: xcoord(:),nodcoord(:,:),xmin(:),xmax(:) integer(int32),allocatable :: element_id_list(:) logical,allocatable :: Inside(:) integer(int32) :: ret,dim_num,elem_num,node_num,i,j,nearest_node_id real(real64) :: r_val dim_num = size(obj%nodcoord,2) node_num = size(obj%nodcoord,1) elem_num = size(obj%elemnod,2) ret = -1 ! default allocate(xcoord(dim_num) ) ! copy array if(dim_num==1)then xcoord(1) = x elseif(dim_num==2)then xcoord(1) = x xcoord(2) = y elseif(dim_num==3)then xcoord(1) = x xcoord(2) = y xcoord(3) = z endif ! nodcoord = obj%nodcoord ! do i=1,size(nodcoord,1) ! nodcoord(i,:) = nodcoord(i,:) - xcoord(:) ! enddo ! use heap sort ! if position is out of domain, ! return allocate(xmin(dim_num),xmax(dim_num) ) do i=1,dim_num xmin(i) = minval(obj%nodcoord( :,i) ) xmax(i) = maxval(obj%nodcoord( :,i) ) enddo if(.not.InOrOut(xcoord,xmax,xmin,dim_num) )then ret = -1 !print *, "Caution! :: getNearestElementID :: out of domain" return endif nearest_node_id = obj%getNearestNodeID(x=x,y=y,z=z) element_id_list = obj%getElementList(NodeID=nearest_node_id) do j=1, size(element_id_list) if(obj%InsideOfElement(ElementID=element_id_list(j),x=x,y=y,z=z ) )then ret = element_id_list(j) return else cycle endif enddo end function !################################################################################## !################################################################################## function InsideOfElementMesh(obj,ElementID,x,y,z) result(Inside) class(Mesh_),intent(in) :: obj integer(int32),intent(in) :: ElementID real(real64),intent(in) :: x,y,z real(real64) :: a,b real(real64),allocatable :: ElemCoord(:,:),p1(:),p2(:),o1(:),o2(:),nvec(:) logical :: Inside integer(int32) :: i,j,cross_count,in_count,node_1,node_2,node_0,node_id,dim_num,nne inside = .false. ! detect Inside or not. dim_num = size(obj%nodcoord,2) nne = size(obj%elemnod,2) allocate(ElemCoord( nne, dim_num ) ) ElemCoord(:,:) = 0.0d0 if(size(obj%elemnod,1) < ElementID )then print *, "ERROR :: InsideOfElementMesh >> size(obj%elemnod,1) < ElementID" Inside = .false. return endif do i=1,nne node_id = obj%elemnod(ElementID, i) elemcoord(i,:) = obj%nodcoord(node_id,:) enddo ! Question >>> ! x,y,z is in elemcoord? if(size(obj%elemnod,2)==4 .and. size(obj%nodcoord,2)==2 )then ! Line-Crossing algorithm ! x ------> this side cross_count = 0 allocate(p1(2), p2(2), o1(2), o2(2) ) do i=1,4 if(i==4)then p1(:) = ElemCoord( 4 ,:) p2(:) = ElemCoord( 1 ,:) else p1(:) = ElemCoord( i ,:) p2(:) = ElemCoord( i+1 ,:) endif o1(1) = x o1(2) = y ! p1, p2を通る直線の方程式 a = (p2(2)-p1(2) )/( p2(1) - p1(1) ) b = p2(2) - a * p2(1) ! y = o1(2) とy=ax+bとの交点のx座標 ! x = (y-b)/a if(a==0)then if(b==y )then if( abs(p1(1)-x)+abs(p2(1)-x) ==abs(p1(1)-p2(1) ) )then ! on the line! Inside = .true. return else cycle endif else cycle endif else if( (y-b)/a >= x )then cross_count=cross_count+1 endif endif enddo if(cross_count == 1)then ! inside Inside=.true. endif elseif (size(obj%elemnod,2)==8 .and. size(obj%nodcoord,2)==3 )then ! 内外判定 ! Z = zで断面を切り、(x,y)のリストを作り、交差判定 ! 3次元直線のZ=zにおける(x,y)を出す。>>ダメ ! 内積で、角度? in_count = 0 Inside = .false. allocate(p1(3) ) allocate(p2(3) ) allocate(o1(3) ) allocate(o2(3) ) allocate(nvec(3) ) !trial #1 node_0 = 1 node_1 = 4 node_2 = 2 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z !call print(elemcoord) o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif !trial #2 node_0 = 1 node_1 = 2 node_2 = 5 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif !trial #3 node_0 = 1 node_1 = 5 node_2 = 4 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif !trial #4 node_0 = 3 node_1 = 7 node_2 = 2 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif !trial #5 node_0 = 7 node_1 = 8 node_2 = 6 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif !trial #6 node_0 = 3 node_1 = 4 node_2 = 7 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif Inside = .true. return elseif(size(obj%elemnod,2)==4 .and. size(obj%nodcoord,2)==3 )then ! tetra element ! trial #1 in_count = 0 Inside = .false. allocate(p1(3) ) allocate(p2(3) ) allocate(o1(3) ) allocate(o2(3) ) allocate(nvec(3) ) !trial #1 node_0 = 3 node_1 = 2 node_2 = 1 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z !call print(elemcoord) o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif !trial #2 node_0 = 1 node_1 = 2 node_2 = 4 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z !call print(elemcoord) o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif !trial #3 node_0 = 1 node_1 = 4 node_2 = 3 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z !call print(elemcoord) o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif !trial #4 node_0 = 2 node_1 = 3 node_2 = 4 p1(:) = elemcoord(node_1,:) - elemcoord(node_0,:) p2(:) = elemcoord(node_2,:) - elemcoord(node_0,:) o1(1) = x o1(2) = y o1(3) = z !call print(elemcoord) o1(:) = o1(:) - elemcoord(node_0,:) nvec = cross_product(p1,p2) if(dot_product(nvec,o1) > 0.0d0 )then ! outside Inside = .false. return endif Inside = .true. return else print *, "ERROR :: InsideOfElementMesh >> 4-node box or 8-node cube are acceptable." stop endif end function !################################################################################## !################################################################################## function getCenterCoordinateMesh(obj, elemid) result(ret) class(Mesh_),intent(in) :: obj integer(int32),intent(in) :: elemid integer(int32) :: dimnum,i real(real64),allocatable :: ret(:) if(obj%empty() .eqv. .true. )then print *, "ERROR :: mesh is empty" return endif dimnum = size(obj%nodcoord,2) allocate(ret(dimnum) ) ret(:) = 0.0d0 do i=1,size(obj%elemnod,2) ret(:) = ret(:) + 1.0d0/dble(size(obj%elemnod,2))*obj%nodcoord(obj%elemnod(elemid,i),: ) enddo end function !################################################################################## function getNeighboringNodeMesh(obj,nodeid) result(ret) class(Mesh_),intent(inout) :: obj integer(int32),intent(in) :: nodeid integer(int32) :: dimnum,i,facetnum,elemnodnum,j,numnn integer(int32),allocatable :: ret(:),nodelist(:),elemnodtr(:) logical :: exists nodelist = int( zeros(size(obj%nodcoord,1) ) ) elemnodtr= int( zeros(size(obj%elemnod ,2) ) ) do i=1,size(obj%elemnod,1) elemnodtr = obj%elemnod(i,:) elemnodtr(:) = elemnodtr(:) - nodeid elemnodtr(:) = abs(elemnodtr(:)) if(minval(elemnodtr) == 0 )then do j=1,size(obj%elemnod,2) nodelist( obj%elemnod(i,j) ) = 1 enddo endif enddo nodelist(nodeid) = 0 ret = int(zeros(sum(nodelist) ) ) j = 0 do i=1,size(nodelist) if(nodelist(i)==1 )then j=j+1 ret( j ) = i endif enddo end function !################################################################################## function getNeighboringElementMesh(obj, elemid,withSurfaceID,interfaces) result(ret) class(Mesh_),intent(inout) :: obj integer(int32),intent(in) :: elemid integer(int32),allocatable,optional,intent(inout) :: interfaces(:) logical,optional,intent(in) :: withSurfaceID integer(int32) :: dimnum,i,facetnum,elemnodnum,j,n,k integer(int32),allocatable :: ret(:),nodelist(:),elemlist(:),id(:),idr(:),order(:,:) integer(int32),allocatable :: retbuf(:) logical :: exists if(obj%empty() .eqv. .true. )then print *, "ERROR :: mesh is empty" return endif ! get element info dimnum = size(obj%nodcoord,2) elemnodnum = size(obj%elemnod,2) if(dimnum==3 .and. elemnodnum==4)then ! Tetra mesh if(present(withSurfaceID) )then if(withSurfaceID)then allocate(ret(8) ) else allocate(ret(4) ) endif else allocate(ret(4) ) endif if(present(interfaces) )then interfaces = int(zeros(4) ) endif allocate(id(4) ) allocate(idr(4) ) allocate(order(4,3) ) order(1,:) = [3, 2, 1] order(2,:) = [1, 2, 4] order(3,:) = [2, 3, 4] order(4,:) = [3, 1, 4] ret = -1 n = 0 do k = 1,4 idr(1) = obj%elemnod( elemid, order(k,1) ) idr(2) = obj%elemnod( elemid, order(k,2) ) idr(3) = obj%elemnod( elemid, order(k,3) ) do i=size(obj%elemnod,1),1,-1 if(i==elemid) cycle do j=1,4 id(1) = obj%elemnod( i, order(j,1) ) id(2) = obj%elemnod( i, order(j,2) ) id(3) = obj%elemnod( i, order(j,3) ) if(sameAsGroup(id,idr) )then if(present(interfaces) )then interfaces(k)=1 endif n=n+1 ret(n) = i if(size(ret)==8 )then ret(n+4) = j endif exit endif enddo if(n==k)then exit endif enddo enddo call searchAndRemove(vec=ret,leq=0) return elseif(dimnum==3 .and. elemnodnum==8)then ! Tetra mesh if(present(withSurfaceID) )then if(withSurfaceID)then allocate(ret(12) ) else allocate(ret(6) ) endif else allocate(ret(6) ) endif if(present(interfaces) )then interfaces = int(zeros(6) ) endif allocate(id(6) ) allocate(idr(6) ) allocate(order(6,4) ) order(1,:) = [ 4, 3, 2, 1] order(2,:) = [ 1, 2, 6, 5] order(3,:) = [ 2, 3, 7, 6] order(4,:) = [ 3, 4, 8, 7] order(5,:) = [ 4, 1, 5, 8] order(6,:) = [ 5, 6, 7, 8] ret = -1 n = 0 do k = 1,6 idr(1) = obj%elemnod( elemid, order(k,1) ) idr(2) = obj%elemnod( elemid, order(k,2) ) idr(3) = obj%elemnod( elemid, order(k,3) ) idr(4) = obj%elemnod( elemid, order(k,4) ) idr(5) = obj%elemnod( elemid, order(k,5) ) idr(6) = obj%elemnod( elemid, order(k,6) ) do i=size(obj%elemnod,1),1,-1 if(i==elemid) cycle do j=1,6 id(1) = obj%elemnod( i, order(j,1) ) id(2) = obj%elemnod( i, order(j,2) ) id(3) = obj%elemnod( i, order(j,3) ) id(4) = obj%elemnod( i, order(j,4) ) id(5) = obj%elemnod( i, order(j,5) ) id(6) = obj%elemnod( i, order(j,6) ) if(sameAsGroup(id,idr) )then if(present(interfaces) )then interfaces(k)=1 endif n=n+1 ret(n) = i if(size(ret)==12 )then ret(n+6) = j endif exit endif enddo if(n==k)then exit endif enddo enddo call searchAndRemove(vec=ret,leq=0) return endif allocate(elemlist(size(obj%elemnod,1) ) ) elemlist(:) = 0 allocate(nodelist(elemnodnum) ) do i=1,size(obj%elemnod,2) nodelist(i)=obj%elemnod(elemid,i) enddo do i=1,size(obj%elemnod,1) exists = .false. do j=1,size(nodelist,1) if(existIntArray(vector=obj%elemnod,rowid=i,val=nodelist(j) ) .eqv. .true. )then exists = .true. exit else cycle endif enddo if(exists .eqv. .true.)then elemlist(i) = 1 endif enddo allocate(ret(sum(elemlist) )) j=0 do i=1,size(elemlist) if(elemlist(i)==1 )then j=j+1 ret(j) = i endif enddo end function !################################################################################## subroutine editMesh(obj,x,altitude) class(Mesh_),intent(inout) :: obj real(real64),optional,intent(in) :: x(:),altitude(:) real(real64) :: coord(3),top,original_top integer(int32) :: i,j if(present(x) .and. present(altitude) )then ! from x(n) -> x(n+1), the altitute (z-coordinate) changes from al(n) -> al(n+1) original_top=maxval(obj%nodcoord(:,3)) do i=1, size(obj%nodcoord,1) coord(:) =obj%nodcoord(i,:) if(coord(3) <= 0.0d0 )then ! only for above-ground part cycle endif do j=1,size(x)-1 if(x(j) <= coord(1) .and. coord(1)<x(j+1) )then top = (altitude(j+1)-altitude(j))/(x(j+1)-x(j) )*(coord(1)- x(j) ) +altitude(j) coord(3) = top/original_top*coord(3) exit endif if(j==size(x)-1 .and. coord(1)==x(j+1) )then top = (altitude(j+1)-altitude(j))/(x(j+1)-x(j) )*(coord(1)- x(j) ) +altitude(j) coord(3) = top/original_top*coord(3) exit endif enddo obj%nodcoord(i,:) = coord(:) enddo endif end subroutine ! ########################################################################## ! ########################################################################## function getNearestNodeIDMesh(obj,x,y,z,except,exceptlist) result(node_id) class(Mesh_),intent(inout) :: obj real(real64),optional,intent(in) :: x,y,z ! coordinate integer(int32),optional,intent(in) :: except ! excepted node id integer(int32),optional,intent(in) :: exceptlist(:) ! excepted node id integer(int32) :: i,j,dim_num, node_num,node_id,except_id real(real64),allocatable :: xvec(:),xvec_tr(:),dist_cur, dist_tr node_num =size(obj%nodcoord,1) dim_num = size(obj%nodcoord,2) except_id = input(default=0, option=except) allocate(xvec(dim_num),xvec_tr(dim_num) ) xvec(:) = 0.0d0 xvec(1) = input(default=0.0d0,option=x) xvec(2) = input(default=0.0d0,option=y) xvec(3) = input(default=0.0d0,option=z) xvec_tr(:) = 0.0d0 node_id = 1 xvec_tr(:) = obj%nodcoord(1,:) dist_cur = dot_product(xvec-xvec_tr,xvec-xvec_tr) do i=1,node_num if(i == except_id)then cycle endif if(present(exceptlist) )then if(exist(exceptlist,i) .eqv. .true. )then cycle endif endif xvec_tr(:) = obj%nodcoord(i,:) dist_tr = dot_product(xvec-xvec_tr,xvec-xvec_tr) if(dist_tr < dist_cur)then node_id = i dist_cur = dist_tr endif enddo end function ! ########################################################################## ! ########################################################################## function positionMesh(obj,id) result(x) class(Mesh_),intent(in) :: obj integer(int32),intent(in) :: id ! node_id real(real64) :: x(3) integer(int32) :: dim_num,i dim_num = size(obj%nodcoord,2) do i=1,dim_num x(i) = obj%nodcoord(id,i) enddo end function ! ########################################################################## ! ########################################################################## function position_xMesh(obj,id) result(x) class(Mesh_),intent(in) :: obj integer(int32),intent(in) :: id ! node_id real(real64) :: x x = obj%nodcoord(id,1) end function ! ########################################################################## ! ########################################################################## function position_yMesh(obj,id) result(x) class(Mesh_),intent(in) :: obj integer(int32),intent(in) :: id ! node_id real(real64) :: x x = obj%nodcoord(id,2) end function ! ########################################################################## ! ########################################################################## function position_zMesh(obj,id) result(x) class(Mesh_),intent(in) :: obj integer(int32),intent(in) :: id ! node_id real(real64) :: x x = obj%nodcoord(id,3) end function ! ########################################################################## ! ########################################################################## recursive subroutine assembleMesh(obj) class(Mesh_),intent(inout) :: obj integer(int32),allocatable :: elemnod_1(:,:) integer(int32) :: i,j,itr,node_num,dim_num integer(int32) :: node1,node2,node3,node4,node_1and2(2) real(real64) :: coord(3),center(3),vec1(3),vec2(3) ! 点群3DCTから線要素を作成 ! strategy#1 ! 1. 最寄りと結合し線分へ ! 2. 線分の中心から最寄りの線分を探索 ! 3. 発見した線分と結合 ! 1. 最寄りと結合し線分へ node_num = size(obj%nodcoord,1) dim_num = size(obj%nodcoord,2) if(dim_num/=3)then print *, "ERROR >> assembleMesh >> size(obj%nodcoord,1) should be 3" stop endif allocate(elemnod_1(2*node_num,2) ) elemnod_1(:,:) = 0 do i=1,node_num node1 = i coord(:) = obj%nodcoord(node1,:) node2 = obj%getNearestNodeID(& x=coord(1),& y=coord(2),& z=coord(3),& except=node1 & ) node_1and2(1) = node1 node_1and2(2) = node2 node3 = obj%getNearestNodeID(& x=coord(1),& y=coord(2),& z=coord(3),& exceptlist=node_1and2 & ) elemnod_1(i,1) = node1 elemnod_1(i,2) = node2 elemnod_1(i+node_num ,1) = node1 elemnod_1(i+node_num, 2) = node3 ! もし同じ方向だったら削除 vec1(:) = obj%nodcoord(node3,:) - obj%nodcoord(node1,:) vec2(:) = obj%nodcoord(node2,:) - obj%nodcoord(node1,:) if( dot_product(vec1,vec2) > 0.0d0 )then elemnod_1(i+node_num ,1) = 0 elemnod_1(i+node_num, 2) = 0 endif enddo do i=1,size(elemnod_1,1) node1 = elemnod_1(i,1) node2 = elemnod_1(i,2) do j=i+1,size(elemnod_1,1) if(elemnod_1(j,1) == 0)then cycle endif if(elemnod_1(j,1) == node1 .and. & elemnod_1(j,2) == node2 )then elemnod_1(j,:) = 0 endif if(elemnod_1(j,2) == node1 .and. & elemnod_1(j,1) == node2 )then elemnod_1(j,:) = 0 endif enddo enddo itr=0 do i=1,size(elemnod_1,1) if(elemnod_1(i,1)==0 )then itr=itr+1 endif enddo if(allocated(obj%elemnod) ) then deallocate(obj%elemnod) endif ! remove ! A ->B ! B <- A allocate(obj%elemnod(size(elemnod_1,1)-itr,8 ) ) obj%elemnod(:,:)=0 itr=0 do i=1,size(elemnod_1,1) if(minval(elemnod_1(i,:))==0 )then cycle else itr=itr+1 obj%elemnod(itr,1) = elemnod_1(i,1) obj%elemnod(itr,2:8) = elemnod_1(i,2) endif enddo if(minval(obj%elemnod) == 0 ) then print*, "ERROR :: assembleMesh minval(obj%elemnod) == 0 " stop endif end subroutine ! ########################################################################## subroutine arrangeNodeOrderMesh(obj,NumberOfLayer) class(Mesh_) ,intent(inout):: obj integer(int32),optional,intent(in) :: NumberOfLayer integer(int32),allocatable :: layer(:) real(real64),allocatable :: center(:),x(:),radius(:),nodcoord(:,:),nodeorder(:) real(real64) :: dr integer(int32) :: i,j,k,n,nl if(.not.allocated(obj%nodcoord) ) then print *, "ERROR :: no nodal coordinate was found." return endif ! arrange nodes from outer to center center = zeros(size(obj%nodcoord,2) ) x = zeros(size(obj%nodcoord,2) ) do i=1,size(center) center(i) = 1.0d0/dble(size(obj%nodcoord,1) ) *sum(obj%nodcoord(:,i) ) enddo nodeorder = zeros(size(obj%nodcoord,1) ) layer = int(zeros(size(obj%nodcoord,1) )) radius = zeros(size(obj%nodcoord,1) ) nl = input(default=10,option=NumberOfLayer) do i=1,size(obj%nodcoord,1) nodeorder(i) = dble(i) x(:) = obj%nodcoord(i,:) radius(i) = sqrt( dot_product(center-x,center-x) ) enddo dr = maxval(radius)/dble(nl) do i=1,size(obj%nodcoord,1) layer(i) = int(radius(i)/dr) enddo call heapsort(n=size(obj%nodcoord,1), array=layer, val=nodeorder) nodcoord = obj%nodcoord do i=1, sizE(nodeorder) obj%nodcoord(i,:) = nodcoord( int(nodeorder(i)),: ) enddo end subroutine ! ########################################################################## subroutine addElementsMesh(obj,Connectivity) class(Mesh_),intent(inout) :: obj integer(int32),intent(in) :: connectivity(:,:) integer(int32),allocatable :: buf(:,:) integer(int32) :: n,m,i,newnum n = size(obj%elemnod,1) m = size(obj%elemnod,2) newnum = sizE(connectivity,1) if(m/=size(connectivity,2) )then print *, "ERROR ::addElementsMesh >> size(obj%elemnod,2) /= size(connectivity,2)" stop endif allocate(buf(n+newnum,m) ) buf(1:n,:) = obj%elemnod(:,:) buf(n+1:,:) = connectivity(:,:) obj%elemnod = buf end subroutine ! ########################################################################## subroutine removeElementsMesh(obj,ElementIDs) class(Mesh_),intent(inout) :: obj integer(int32),intent(in) :: ElementIDs(:) integer(int32),allocatable :: buf(:,:) integer(int32) :: n,m,i,rmnum,itr n = size(obj%elemnod,1) m = size(obj%elemnod,2) rmnum = size(ElementIDs) allocate(buf(n-rmnum,m) ) do i=1,rmnum obj%elemnod(ElementIDs(i),1) = -1 enddo itr = 0 do i=1,n if( obj%elemnod(i,1) == -1 )then cycle else itr=itr+1 buf(itr,:) = obj%elemnod(i,:) endif enddo obj%elemnod = buf end subroutine ! ########################################################################## end module MeshClass