MODULE moduleMesh1DRead USE moduleMesh USE moduleMesh1D USE moduleMesh1DBoundary !TODO: make this abstract to allow different mesh formats TYPE, EXTENDS(meshGeneric):: mesh1DGeneric CONTAINS PROCEDURE, PASS:: init => init1DMesh PROCEDURE, PASS:: readMesh => readMesh1D END TYPE INTERFACE connected MODULE PROCEDURE connectedVolVol, connectedVolEdge END INTERFACE connected CONTAINS !Init 1D mesh SUBROUTINE init1DMesh(self, meshFormat) USE moduleMesh USE moduleErrors IMPLICIT NONE CLASS(mesh1DGeneric), INTENT(out):: self CHARACTER(:), ALLOCATABLE, INTENT(in):: meshFormat SELECT CASE(meshFormat) CASE ("gmsh") self%printOutput => printOutputGmsh self%printColl => printCollGmsh self%printEM => printEMGmsh CASE DEFAULT CALL criticalError("Mesh type " // meshFormat // " not supported.", "init1D") END SELECT END SUBROUTINE init1DMesh !Reads 1D mesh SUBROUTINE readMesh1D(self, filename) USE moduleBoundary IMPLICIT NONE CLASS(mesh1DGeneric), INTENT(inout):: self CHARACTER(:), ALLOCATABLE, INTENT(in):: filename REAL(8):: x INTEGER:: p(1:2) INTEGER:: e, et, n, eTemp, elemType, bt INTEGER:: totalNumElem INTEGER:: boundaryType !Open file mesh OPEN(10, FILE=TRIM(filename)) !Skip header READ(10, *) READ(10, *) READ(10, *) READ(10, *) !Read number of nodes READ(10, *) self%numNodes !Allocate required matrices and vectors ALLOCATE(self%nodes(1:self%numNodes)) ALLOCATE(self%K(1:self%numNodes, 1:self%numNodes)) ALLOCATE(self%IPIV(1:self%numNodes, 1:self%numNodes)) self%K = 0.D0 self%IPIV = 0 !Read nodes coordinates. Only relevant for x DO e = 1, self%numNodes READ(10, *) n, x ALLOCATE(meshNode1D:: self%nodes(n)%obj) CALL self%nodes(n)%obj%init(n, (/ x, 0.D0, 0.D0 /)) END DO !Skips comments READ(10, *) READ(10, *) !Reads the total number of elements (edges+vol) READ(10, *) totalNumElem self%numEdges = 0 DO e = 1, totalNumElem READ(10, *) eTemp, elemType IF (elemType == 15) THEN !15 is physical node in GMSH self%numEdges = e END IF END DO !Substract the number of edges to the total number of elements !to obtain the number of volume elements self%numVols = totalNumelem - self%numEdges !Allocates arrays ALLOCATE(self%edges(1:self%numEdges)) ALLOCATE(self%vols(1:self%numVols)) !Go back to the beginning of reading elements DO e = 1, totalNumelem BACKSPACE(10) END DO !Reads edges DO e = 1, self%numEdges READ(10, *) n, elemType, eTemp, boundaryType, eTemp, p(1) !Associate boundary condition bt = getBoundaryId(boundaryType) SELECT CASE(boundary(bt)%obj%boundaryType) CASE ('reflection') ALLOCATE(meshEdge1DRef:: self%edges(e)%obj) CASE ('absorption') ALLOCATE(meshEdge1DAbs:: self%edges(e)%obj) END SELECT CALL self%edges(e)%obj%init(n, p(1:1), bt, boundaryType) END DO !Read and initialize volumes DO e = 1, self%numVols READ(10, *) n, elemType, eTemp, eTemp, eTemp, p(1:2) ALLOCATE(meshVol1DSegm:: self%vols(e)%obj) CALL self%vols(e)%obj%init(n - self%numEdges, p(1:2)) END DO CLOSE(10) !Build connectivity between elements DO e = 1, self%numVols !Connectivity between volumes DO et = 1, self%numVols IF (e /= et) THEN CALL connected(self%vols(e)%obj, self%vols(et)%obj) END IF END DO !Connectivity betwen vols and edges DO et = 1, self%numEdges CALL connected(self%vols(e)%obj, self%edges(et)%obj) END DO !Constructs the global K matrix CALL constructGlobalK(self%K, self%vols(e)%obj) END DO END SUBROUTINE readMesh1D SUBROUTINE connectedVolVol(elemA, elemB) IMPLICIT NONE CLASS(meshVol), INTENT(inout):: elemA CLASS(meshVol), INTENT(inout):: elemB SELECT TYPE(elemA) TYPE IS(meshVol1DSegm) SELECT TYPE(elemB) TYPE IS(meshVol1DSegm) CALL connectedSegmSegm(elemA, elemB) END SELECT END SELECT END SUBROUTINE connectedVolVol SUBROUTINE connectedSegmSegm(elemA, elemB) IMPLICIT NONE CLASS(meshVol1DSegm), INTENT(inout), TARGET:: elemA CLASS(meshVol1DSegm), INTENT(inout), TARGET:: elemB IF (.NOT. ASSOCIATED(elemA%e1) .AND. & elemA%n2%n == elemB%n1%n) THEN elemA%e1 => elemB elemB%e2 => elemA END IF IF (.NOT. ASSOCIATED(elemA%e2) .AND. & elemA%n1%n == elemB%n2%n) THEN elemA%e2 => elemB elemB%e1 => elemA END IF END SUBROUTINE connectedSegmSegm SUBROUTINE connectedVolEdge(elemA, elemB) IMPLICIT NONE CLASS(meshVol), INTENT(inout):: elemA CLASS(meshEdge), INTENT(inout):: elemB SELECT TYPE(elemA) TYPE IS (meshVol1DSegm) SELECT TYPE(elemB) CLASS IS(meshEdge1D) CALL connectedSegmEdge(elemA, elemB) END SELECT END SELECT END SUBROUTINE connectedVolEdge SUBROUTINE connectedSegmEdge(elemA, elemB) IMPLICIT NONE CLASS(meshVol1DSegm), INTENT(inout), TARGET:: elemA CLASS(meshEdge1D), INTENT(inout), TARGET:: elemB IF (.NOT. ASSOCIATED(elemA%e1) .AND. & elemA%n2%n == elemB%n1%n) THEN elemA%e1 => elemB elemB%e2 => elemA END IF IF (.NOT. ASSOCIATED(elemA%e2) .AND. & elemA%n1%n == elemB%n1%n) THEN elemA%e2 => elemB elemB%e1 => elemA END IF END SUBROUTINE connectedSegmEdge SUBROUTINE constructGlobalK(K, elem) IMPLICIT NONE REAL(8), INTENT(inout):: K(1:,1:) CLASS(meshVol), INTENT(in):: elem REAL(8):: localK(1:2,1:2) INTEGER:: i, j INTEGER:: n(1:2) SELECT TYPE(elem) TYPE IS(meshVol1DSegm) localK = elem%elemK() n = (/ elem%n1%n, elem%n2%n /) CLASS DEFAULT n = 0 localK = 0.D0 END SELECT DO i = 1, 2 DO j = 1, 2 K(n(i), n(j)) = K(n(i), n(j)) + localK(i, j) END DO END DO END SUBROUTINE constructGlobalK END MODULE moduleMesh1DRead