New functionality:
- DSMC module:
- 2D cyl geometry
- GMSH file format
- Elastic cross-section for Argon-Argon collisions.
- Basic boundary conditions: reflection, absorption and axis
symmetry.
Bugs fixed:
Other comments:
- Still searching for name.
428 lines
12 KiB
Fortran
428 lines
12 KiB
Fortran
MODULE moduleMeshCylRead
|
|
USE moduleMesh
|
|
USE moduleMeshCyl
|
|
USE moduleMeshCylBoundary
|
|
|
|
TYPE, EXTENDS(meshGeneric):: meshCylGeneric
|
|
CONTAINS
|
|
PROCEDURE, PASS:: readMesh => readMeshCyl
|
|
PROCEDURE, PASS:: printOutput => printOutputCyl
|
|
PROCEDURE, PASS:: printColl => printCollisionsCyl
|
|
|
|
END TYPE
|
|
|
|
INTERFACE connected
|
|
MODULE PROCEDURE connectedVolVol, connectedVolEdge
|
|
|
|
END INTERFACE connected
|
|
|
|
CONTAINS
|
|
SUBROUTINE readMeshCyl(self, filename)
|
|
USE moduleRefParam
|
|
USE moduleBoundary
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshCylGeneric), INTENT(out):: self
|
|
CHARACTER(:), ALLOCATABLE, INTENT(in):: filename
|
|
REAL(8):: r, z
|
|
INTEGER:: p(1:4)
|
|
INTEGER:: e=0, et=0, n=0, eTemp=0, elemType=0, bt = 0
|
|
INTEGER:: totalNumElem
|
|
INTEGER:: boundaryType
|
|
|
|
!Read msh
|
|
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:numNodes,1:numNodes))
|
|
! ALLOCATE(self%F(1:numNodes))
|
|
!Read nodes cartesian coordinates (x=z, y=r, z=null)
|
|
DO e=1, self%numNodes
|
|
READ(10, *) n, z, r
|
|
ALLOCATE(meshNodeCyl:: self%nodes(n)%obj)
|
|
CALL self%nodes(n)%obj%init(n, (/r, z, 0.D0 /))
|
|
|
|
END DO
|
|
!Skips comments
|
|
READ(10, *)
|
|
READ(10, *)
|
|
!Reads Totalnumber of elements
|
|
READ(10, *) TotalnumElem
|
|
!counts edges and volume elements
|
|
self%numEdges = 0
|
|
DO e=1, TotalnumElem
|
|
READ(10,*) eTemp, elemType
|
|
IF (elemType==1) THEN
|
|
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 beggining to read elements
|
|
DO e=1, totalNumElem
|
|
BACKSPACE(10)
|
|
END DO
|
|
|
|
!TODO: symplify to read all elements independently if they are edges or vols
|
|
!Reads edges
|
|
DO e=1, self%numEdges
|
|
READ(10,*) n, elemType, eTemp, boundaryType, eTemp, p(1:2)
|
|
!Associate boundary condition procedure.
|
|
!TODO: move to subroutine
|
|
bt = getBoundaryId(boundaryType)
|
|
SELECT CASE(boundary(bt)%obj%boundaryType)
|
|
CASE ('reflection')
|
|
ALLOCATE(meshEdgeCylRef:: self%edges(e)%obj)
|
|
|
|
CASE ('absorption')
|
|
ALLOCATE(meshEdgeCylAbs:: self%edges(e)%obj)
|
|
|
|
CASE ('axis')
|
|
ALLOCATE(meshEdgeCylAxis:: self%edges(e)%obj)
|
|
|
|
END SELECT
|
|
|
|
CALL self%edges(e)%obj%init(n, p, bt, boundaryType)
|
|
|
|
END DO
|
|
|
|
!Read and initialize volumes
|
|
!TODO: Extend to triangular elements
|
|
DO e=1, self%numVols
|
|
READ(10,*) n, elemType, eTemp, eTemp, eTemp, p(1:4)
|
|
ALLOCATE(meshVolCylQuad:: self%vols(e)%obj)
|
|
CALL self%vols(e)%obj%init(n - self%numEdges, p)
|
|
|
|
END DO
|
|
|
|
CLOSE(10)
|
|
|
|
!Build connectivity between elements
|
|
DO e = 1, self%numVols
|
|
!Connectivity between volumes
|
|
DO et = 1, self%numVols
|
|
CALL connected(self%vols(e)%obj, self%vols(et)%obj)
|
|
|
|
END DO
|
|
|
|
!Connectivity between vols and edges
|
|
DO et = 1, self%numEdges
|
|
CALL connected(self%vols(e)%obj, self%edges(et)%obj)
|
|
|
|
END DO
|
|
|
|
END DO
|
|
|
|
! !Compute global stiffness matrix
|
|
! GlobalK=0.D0
|
|
! DO e=1, numElem
|
|
! DO i=1, 4
|
|
! DO j=1, 4
|
|
! GlobalK(elems(e)%p(i),elems(e)%p(j)) = GlobalK(elems(e)%p(i),elems(e)%p(j)) + elems(e)%Ke(i,j)
|
|
! END DO
|
|
! END DO
|
|
! END DO
|
|
! ! Apply Dirichlet boundary conditions to GlobalK
|
|
! DO n=1, numNodes
|
|
! IF (nodes(n)%bound == 1) THEN
|
|
! GlobalK(n,:)=0.D0
|
|
! GlobalK(n,n)=1.D0
|
|
! END IF
|
|
! END DO
|
|
|
|
END SUBROUTINE
|
|
|
|
SUBROUTINE connectedVolVol(elemA, elemB)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshVol), INTENT(inout):: elemA
|
|
CLASS(meshVol), INTENT(inout):: elemB
|
|
|
|
|
|
SELECT TYPE(elemA)
|
|
TYPE IS (meshVolCylQuad)
|
|
SELECT TYPE(elemB)
|
|
TYPE IS(meshVolCylQuad)
|
|
CALL connectedQuadQuad(elemA, elemB)
|
|
|
|
END SELECT
|
|
|
|
END SELECT
|
|
|
|
END SUBROUTINE connectedVolVol
|
|
|
|
SUBROUTINE connectedVolEdge(elemA, elemB)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshVol), INTENT(inout):: elemA
|
|
CLASS(meshEdge), INTENT(inout):: elemB
|
|
|
|
SELECT TYPE(elemA)
|
|
TYPE IS (meshVolCylQuad)
|
|
SELECT TYPE(elemB)
|
|
CLASS IS(meshEdgeCyl)
|
|
CALL connectedQuadEdge(elemA, elemB)
|
|
|
|
END SELECT
|
|
|
|
END SELECT
|
|
|
|
END SUBROUTINE connectedVolEdge
|
|
|
|
SUBROUTINE connectedQuadQuad(elemA, elemB)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshVolCylQuad), INTENT(inout), TARGET:: elemA
|
|
CLASS(meshVolCylQuad), INTENT(inout), TARGET:: elemB
|
|
|
|
!Check direction 1
|
|
IF (.NOT. ASSOCIATED(elemA%e1) .AND. &
|
|
elemA%n1%n == elemB%n4%n .AND. &
|
|
elemA%n2%n == elemB%n3%n) THEN
|
|
elemA%e1 => elemB
|
|
elemB%e3 => elemA
|
|
|
|
END IF
|
|
|
|
!Check direction 2
|
|
IF (.NOT. ASSOCIATED(elemA%e2) .AND. &
|
|
elemA%n2%n == elemB%n1%n .AND. &
|
|
elemA%n3%n == elemB%n4%n) THEN
|
|
elemA%e2 => elemB
|
|
elemB%e4 => elemA
|
|
|
|
END IF
|
|
|
|
!Check direction 3
|
|
IF (.NOT. ASSOCIATED(elemA%e3) .AND. &
|
|
elemA%n3%n == elemB%n2%n .AND. &
|
|
elemA%n4%n == elemB%n1%n) THEN
|
|
elemA%e3 => elemB
|
|
elemB%e1 => elemA
|
|
|
|
|
|
END IF
|
|
|
|
!Check direction 4
|
|
IF (.NOT. ASSOCIATED(elemA%e4) .AND. &
|
|
elemA%n4%n == elemB%n3%n .AND. &
|
|
elemA%n1%n == elemB%n2%n) THEN
|
|
elemA%e4 => elemB
|
|
elemB%e2 => elemA
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE connectedQuadQuad
|
|
|
|
SUBROUTINE connectedQuadEdge(elemA, elemB)
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshVolCylQuad), INTENT(inout), TARGET:: elemA
|
|
CLASS(meshEdgeCyl), INTENT(inout), TARGET:: elemB
|
|
|
|
!Check direction 1
|
|
IF (.NOT. ASSOCIATED(elemA%e1)) THEN
|
|
IF (elemA%n1%n == elemB%n1%n .AND. &
|
|
elemA%n2%n == elemB%n2%n) THEN
|
|
elemA%e1 => elemB
|
|
elemB%e2 => elemA
|
|
|
|
ELSEIF (elemA%n1%n == elemB%n2%n .AND. &
|
|
elemA%n2%n == elemB%n1%n) THEN
|
|
elemA%e1 => elemB
|
|
elemB%e1 => elemA
|
|
|
|
END IF
|
|
|
|
END IF
|
|
|
|
!Check direction 2
|
|
IF (.NOT. ASSOCIATED(elemA%e2)) THEN
|
|
IF (elemA%n2%n == elemB%n1%n .AND. &
|
|
elemA%n3%n == elemB%n2%n) THEN
|
|
elemA%e2 => elemB
|
|
elemB%e2 => elemA
|
|
|
|
ELSEIF (elemA%n2%n == elemB%n2%n .AND. &
|
|
elemA%n3%n == elemB%n1%n) THEN
|
|
elemA%e2 => elemB
|
|
elemB%e1 => elemA
|
|
|
|
END IF
|
|
|
|
END IF
|
|
|
|
!Check direction 3
|
|
IF (.NOT. ASSOCIATED(elemA%e3)) THEN
|
|
IF (elemA%n3%n == elemB%n1%n .AND. &
|
|
elemA%n4%n == elemB%n2%n) THEN
|
|
elemA%e3 => elemB
|
|
elemB%e2 => elemA
|
|
|
|
ELSEIF (elemA%n3%n == elemB%n2%n .AND. &
|
|
elemA%n4%n == elemB%n1%n) THEN
|
|
elemA%e3 => elemB
|
|
elemB%e1 => elemA
|
|
|
|
END IF
|
|
|
|
END IF
|
|
|
|
!Check direction 4
|
|
IF (.NOT. ASSOCIATED(elemA%e4)) THEN
|
|
IF (elemA%n4%n == elemB%n1%n .AND. &
|
|
elemA%n1%n == elemB%n2%n) THEN
|
|
elemA%e4 => elemB
|
|
elemB%e2 => elemA
|
|
|
|
ELSEIF (elemA%n4%n == elemB%n2%n .AND. &
|
|
elemA%n1%n == elemB%n1%n) THEN
|
|
elemA%e4 => elemB
|
|
elemB%e1 => elemA
|
|
|
|
END IF
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE connectedQuadEdge
|
|
|
|
SUBROUTINE printOutputCyl(self, t)
|
|
USE moduleRefParam
|
|
USE moduleSpecies
|
|
USE moduleOutput
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshCylGeneric), INTENT(in):: self
|
|
INTEGER, INTENT(in):: t
|
|
INTEGER:: n, i
|
|
TYPE(outputFormat):: output(1:self%numNodes)
|
|
REAL(8):: time
|
|
CHARACTER(:), ALLOCATABLE:: fileName
|
|
CHARACTER (LEN=6):: tstring !TODO: Review to allow any number of iterations
|
|
|
|
time = DBLE(t)*tau*ti_ref
|
|
|
|
DO i = 1, nSpecies
|
|
WRITE(tstring, '(I6.6)') t
|
|
fileName='OUTPUT_' // tstring// '_' // species(i)%obj%name // '.msh'
|
|
PRINT *, "Creado archivo de datos:", fileName
|
|
OPEN (60, file = path // folder // '/' // fileName)
|
|
WRITE(60, "(A)") '$MeshFormat'
|
|
WRITE(60, "(A)") '2.2 0 8'
|
|
WRITE(60, "(A)") '$EndMeshFormat'
|
|
WRITE(60, "(A)") '$NodeData'
|
|
WRITE(60, "(A)") '1'
|
|
WRITE(60, "(A)") '"Density (m^-3)"'
|
|
WRITE(60, *) 1
|
|
WRITE(60, *) time
|
|
WRITE(60, *) 3
|
|
WRITE(60, *) t
|
|
WRITE(60, *) 1
|
|
WRITE(60, *) self%numNodes
|
|
DO n=1, self%numNodes
|
|
CALL calculateOutput(self%nodes(n)%obj%output(i), output(n), self%nodes(n)%obj%v, species(i)%obj)
|
|
WRITE(60, "(I6,ES20.6E3)") n, output(n)%density
|
|
END DO
|
|
WRITE(60, "(A)") '$EndNodeData'
|
|
WRITE(60, "(A)") '$NodeData'
|
|
WRITE(60, "(A)") '1'
|
|
WRITE(60, "(A)") '"Velocity (m/s)"'
|
|
WRITE(60, *) 1
|
|
WRITE(60, *) time
|
|
WRITE(60, *) 3
|
|
WRITE(60, *) t
|
|
WRITE(60, *) 3
|
|
WRITE(60, *) self%numNodes
|
|
DO n=1, self%numNodes
|
|
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%velocity
|
|
END DO
|
|
WRITE(60, "(A)") '$EndNodeData'
|
|
WRITE(60, "(A)") '$NodeData'
|
|
WRITE(60, "(A)") '1'
|
|
WRITE(60, "(A)") '"Pressure (Pa)"'
|
|
WRITE(60, *) 1
|
|
WRITE(60, *) time
|
|
WRITE(60, *) 3
|
|
WRITE(60, *) t
|
|
WRITE(60, *) 1
|
|
WRITE(60, *) self%numNodes
|
|
DO n=1, self%numNodes
|
|
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%pressure
|
|
END DO
|
|
WRITE(60, "(A)") '$EndNodeData'
|
|
WRITE(60, "(A)") '$NodeData'
|
|
WRITE(60, "(A)") '1'
|
|
WRITE(60, "(A)") '"Temperature (K)"'
|
|
WRITE(60, *) 1
|
|
WRITE(60, *) time
|
|
WRITE(60, *) 3
|
|
WRITE(60, *) t
|
|
WRITE(60, *) 1
|
|
WRITE(60, *) self%numNodes
|
|
DO n=1, self%numNodes
|
|
WRITE(60, "(I6,3(ES20.6E3))") n, output(n)%temperature
|
|
END DO
|
|
WRITE(60, "(A)") '$EndNodeData'
|
|
CLOSE (60)
|
|
|
|
END DO
|
|
|
|
END SUBROUTINE printOutputCyl
|
|
|
|
SUBROUTINE printCollisionsCyl(self, t)
|
|
USE moduleRefParam
|
|
USE moduleCaseParam
|
|
USE moduleOutput
|
|
IMPLICIT NONE
|
|
|
|
CLASS(meshCylGeneric), INTENT(in):: self
|
|
INTEGER, INTENT(in):: t
|
|
INTEGER:: n
|
|
REAL(8):: time
|
|
CHARACTER(:), ALLOCATABLE:: fileName
|
|
CHARACTER (LEN=6):: tstring !TODO: Review to allow any number of iterations
|
|
|
|
|
|
IF (collOutput) THEN
|
|
time = DBLE(t)*tau*ti_ref
|
|
WRITE(tstring, '(I6.6)') t
|
|
|
|
fileName='OUTPUT_' // tstring// '_Collisions.msh'
|
|
PRINT *, "Creado archivo de datos:", fileName
|
|
OPEN (60, file = path // folder // '/' // fileName)
|
|
WRITE(60, "(A)") '$MeshFormat'
|
|
WRITE(60, "(A)") '2.2 0 8'
|
|
WRITE(60, "(A)") '$EndMeshFormat'
|
|
WRITE(60, "(A)") '$ElementData'
|
|
WRITE(60, "(A)") '1'
|
|
WRITE(60, "(A)") '"Collisions"'
|
|
WRITE(60, *) 1
|
|
WRITE(60, *) time
|
|
WRITE(60, *) 3
|
|
WRITE(60, *) t
|
|
WRITE(60, *) 1
|
|
WRITE(60, *) self%numVols
|
|
DO n=1, self%numVols
|
|
WRITE(60, "(I6,I10)") n + self%numEdges, self%vols(n)%obj%nColl
|
|
END DO
|
|
WRITE(60, "(A)") '$EndElementData'
|
|
|
|
CLOSE(60)
|
|
|
|
END IF
|
|
|
|
END SUBROUTINE printCollisionsCyl
|
|
|
|
END MODULE moduleMeshCylRead
|