MODULE ComputeFluxUtils
USE DefUtils
IMPLICIT NONE
CONTAINS
SUBROUTINE ComputeGLFlux_2D(Solver,FillValue)
TYPE(Solver_t) :: Solver
REAL(KIND=dp), OPTIONAL :: FillValue
Type(Mesh_t), POINTER :: Mesh
Type(Variable_t), POINTER :: GMask,FlowVar,HVar,EFluxVar
Type(Element_t), POINTER :: Element,Edge
TYPE(Nodes_t),SAVE :: EdgeNodes,ElementNodes
INTEGER :: tt,ii,jj,kk
INTEGER :: M,n,nEdges
INTEGER :: ngl
INTEGER :: DIM
INTEGER, POINTER :: NodeIndexes(:)
LOGICAL, SAVE :: FirstTime=.TRUE.
CHARACTER(LEN=MAX_NAME_LEN) :: Caller="ComputeGLFlux_2D"
REAL(KIND=dp), ALLOCATABLE,SAVE :: NodalGM(:)
REAL(KIND=dp), ALLOCATABLE,SAVE :: Basis(:)
TYPE(GaussIntegrationPoints_t) :: IntegStuff
REAL(KIND=dp) :: U,V,W,detJ
REAL(KIND=dp),DIMENSION(3) :: Normal,Flow
REAL(KIND=dp) :: Flux,area,H
INTEGER :: EIndex
LOGICAL :: stat
IF (FirstTime) THEN
M = CurrentModel % MaxElementNodes
ALLOCATE(NodalGM(M), Basis(M))
FirstTime=.FALSE.
END IF
EFluxVar => VariableGet(Solver%Mesh%Variables,'ligroundf',UnfoundFatal=.TRUE.)
IF (EFluxVar % TYPE /= Variable_on_elements) &
CALL FATAL(Caller,"ligroundf type should be on_elements")
FlowVar => Solver % Variable
DIM = FlowVar % DOFs
IF (DIM /= 2) &
CALL Fatal(Caller,"Can't handle but 2D flow variable, sorry")
GMask => VariableGet(Solver%Mesh%Variables,'GroundedMask',UnfoundFatal=.TRUE.)
HVar => VariableGet(Solver%Mesh%Variables,'H',UnfoundFatal=.TRUE.)
Mesh => Solver % Mesh
CALL FindMeshEdges(Mesh,FindFaces=.FALSE.)
IF (PRESENT(FillValue)) THEN
EFluxVar % Values = FillValue
ELSE
EFluxVar % Values = 0._dp
END IF
DO tt=1,Solver % NumberOfActiveElements
Element => GetActiveElement(tt)
IF (Element % TYPE % BasisFunctionDegree>1) &
CALL Fatal(Caller,"Can't handle but linear elements, sorry.")
n = GetElementNOFNodes(Element)
NodeIndexes => Element % NodeIndexes
NodalGM(1:n) = GMask % Values ( GMask % Perm ( NodeIndexes(1:n) ) )
ngl=COUNT(NodalGM == 0)
IF (ngl < 2) CYCLE
IF (.NOT.ANY(NodalGM(1:n).LT.0._dp)) CYCLE
nEdges = Element % Type % NumberOfEdges
Flux = 0._dp
DO ii=1,nEdges
Edge => Mesh%Edges(Element % EdgeIndexes(ii))
n = GetElementNOFNodes(Edge)
NodeIndexes => Edge % NodeIndexes
NodalGM(1:n) = GMask % Values ( GMask % Perm ( NodeIndexes(1:n) ) )
IF ( ANY( abs(NodalGM(1:n)) .GT. AEPS ) ) CYCLE
CALL GetElementNodes(EdgeNodes, Edge)
IntegStuff = GaussPoints( Edge )
DO kk=1,IntegStuff % n
U = IntegStuff % u(kk)
V = IntegStuff % v(kk)
W = IntegStuff % w(kk)
stat = ElementInfo(Edge,EdgeNodes,U,V,W,detJ,Basis)
Normal = -NormalVector(Edge,EdgeNodes,U,V,.FALSE.,Element)
DO jj=1,DIM
Flow(jj) = SUM( FlowVar % Values ( DIM*(FlowVar % Perm ( NodeIndexes(1:n) ) - 1) + jj ) * Basis(1:n))
END DO
H = SUM (HVar % Values ( HVar % Perm ( NodeIndexes(1:n) ) ) * Basis(1:n))
Flux = Flux + detJ * IntegStuff % s(kk) * h * SUM(Normal(1:DIM)*Flow(1:DIM))
END DO
END DO
CALL GetElementNodes(ElementNodes, Element)
IntegStuff = GaussPoints( Element )
area=0._dp
DO kk=1,IntegStuff % n
U = IntegStuff % u(kk)
V = IntegStuff % v(kk)
W = IntegStuff % w(kk)
stat = ElementInfo(Element,ElementNodes,U,V,W,detJ,Basis)
area=area+IntegStuff % s(kk)*detJ
END DO
EIndex=Element % ElementIndex
IF (ASSOCIATED(EFluxVar % Perm)) EIndex=EFluxVar % Perm (EIndex)
IF (EIndex > 0) EFluxVar % Values ( EIndex ) = Flux / area
END DO
END SUBROUTINE ComputeGLFlux_2D
SUBROUTINE ComputeCalvingFrontFlux_2D(Solver,FillValue)
TYPE(Solver_t) :: Solver
REAL(KIND=dp), OPTIONAL :: FillValue
Type(Variable_t), POINTER :: FlowVar,HVar,CFluxVar
TYPE(ValueList_t), POINTER :: BC
TYPE(GaussIntegrationPoints_t) :: IntegStuff
TYPE(Element_t), POINTER :: Element,Parent
TYPE(Nodes_t),SAVE :: ElementNodes,ParentNodes
REAL(KIND=dp), ALLOCATABLE,SAVE :: Basis(:)
REAL(KIND=dp) :: U,V,W,detJ
REAL(KIND=dp) :: Normal(3),Flow(3)
REAL(KIND=dp) :: CalvingFlux,H
REAL(KIND=dp) :: area
INTEGER,POINTER :: NodeIndexes(:)
INTEGER :: t,i,j,k
INTEGER :: n
INTEGER :: M
INTEGER :: EIndex,NofActive
INTEGER :: DIM
LOGICAL :: CalvingFront
LOGICAL :: Found
LOGICAL :: stat
LOGICAL,SAVE :: FirstTime=.TRUE.
LOGICAL,ALLOCATABLE :: VisitedParent(:)
CHARACTER(LEN=MAX_NAME_LEN) :: Caller="ComputeCalvingFrontFlux_2D"
IF (FirstTime) THEN
M = CurrentModel % MaxElementNodes
ALLOCATE(Basis(M))
FirstTime=.FALSE.
END IF
CFluxVar => VariableGet(Solver%Mesh%Variables,'calving_front_flux',UnfoundFatal=.TRUE.)
IF (CFluxVar % TYPE /= Variable_on_elements) &
CALL FATAL(Caller,"calving_front_flux type should be on_elements")
IF (PRESENT(FillValue)) THEN
CFluxVar % Values = FillValue
ELSE
CFluxVar % Values = 0._dp
END IF
NofActive = Solver % Mesh % NumberOfBulkElements
ALLOCATE(VisitedParent(NofActive))
VisitedParent=.FALSE.
FlowVar => Solver % Variable
DIM = FlowVar % DOFs
IF (DIM /= 2) &
CALL Fatal(Caller,"Can't handle but 2D flow variable, sorry")
HVar => VariableGet(Solver%Mesh%Variables,'H',UnfoundFatal=.TRUE.)
DO t = 1,GetNOFBoundaryElements()
Element => GetBoundaryElement(t)
IF ( .NOT. ActiveBoundaryElement(Element,Solver) ) CYCLE
IF ( GetElementFamily(Element) == 1 ) CYCLE
BC => GetBC()
IF ( .NOT. ASSOCIATED(BC) ) CYCLE
CalvingFront=.FALSE.
CalvingFront=ListGetLogical(BC,'Calving Front', Found)
IF (.NOT.CalvingFront) CYCLE
n = GetElementNOFNodes(Element)
NodeIndexes => Element % NodeIndexes
CALL GetElementNodes( ElementNodes )
IntegStuff = GaussPoints( Element )
CalvingFlux = 0._dp
DO i=1,IntegStuff % n
U = IntegStuff % u(i)
V = IntegStuff % v(i)
W = IntegStuff % w(i)
stat = ElementInfo(Element,ElementNodes,U,V,W,detJ,Basis)
Normal=0._dp
Normal = NormalVector( Element,ElementNodes,u,v,.TRUE. )
Flow=0._dp
DO j=1,DIM
Flow(j) = SUM( FlowVar % Values(DIM*(FlowVar % Perm(NodeIndexes(1:n))-1)+j) * Basis(1:n) )
END DO
H = SUM (HVar % Values ( HVar % Perm ( NodeIndexes(1:n) ) ) * Basis(1:n))
CalvingFlux=CalvingFlux+&
H*SUM(Normal * Flow)*detJ*IntegStuff % s(i)
END DO
Parent => Element % BoundaryInfo % Right
IF (ASSOCIATED(Parent)) THEN
IF (CheckPassiveElement( Parent )) &
Parent => Element % BoundaryInfo % Left
ELSE
Parent => Element % BoundaryInfo % Left
END IF
IF (.NOT.ASSOCIATED(Parent)) CYCLE
IF (ParEnv % myPe .NE. Parent % partIndex) CYCLE
CALL GetElementNodes(ParentNodes,Parent)
IntegStuff = GaussPoints( Parent )
area=0._dp
DO k=1,IntegStuff % n
U = IntegStuff % u(k)
V = IntegStuff % v(k)
W = IntegStuff % w(k)
stat = ElementInfo(Parent,ParentNodes,U,V,W,detJ,Basis)
area=area+IntegStuff % s(k)*detJ
END DO
EIndex=Parent % ElementIndex
IF (ASSOCIATED(CFluxVar % Perm)) EIndex=CFluxVar % Perm (EIndex)
IF (EIndex > 0) THEN
IF (VisitedParent(Parent % ElementIndex)) THEN
CFluxVar % Values ( EIndex ) = CFluxVar % Values ( EIndex ) + CalvingFlux / area
ELSE
CFluxVar % Values ( EIndex ) = CalvingFlux / area
IF (Parent % ElementIndex.GT.NofActive) &
CALL FATAL(Caller,"Pb with VisitedParent allocated size")
VisitedParent(Parent % ElementIndex)=.TRUE.
END IF
END IF
END DO
DEALLOCATE(VisitedParent)
End
END MODULE