FUNCTION SeaPressure ( Model, nodenumber, y) RESULT(pw)
USE types
USE CoordinateSystems
USE SolverUtils
USE ElementDescription
USE DefUtils
IMPLICIT NONE
TYPE(Model_t) :: Model
TYPE(Solver_t):: Solver
TYPE(Nodes_t), SAVE :: Nodes
TYPE(variable_t), POINTER :: Timevar
TYPE(Element_t), POINTER :: BoundaryElement, BCElement, CurElement, ParentElement
TYPE(ValueList_t), POINTER :: BC, material, ParentMaterial, BodyForce
INTEGER :: NBoundary, NParent, BoundaryElementNode, ParentElementNode, body_id, other_body_id, material_id
INTEGER :: nodenumber, NumberOfNodesOnBoundary, OldMeshTag
INTEGER, ALLOCATABLE :: NodeOnBoundary(:)
INTEGER :: Nn, i, j, p, n, Nmax, bf_id, DIM, bf_id_FS
REAL(KIND=dp) :: y, pw, t, told, dt, Bu, Bv
REAL(KIND=dp) :: Zsl, rhow, gravity
REAL(KIND=dp), ALLOCATABLE :: S(:), Ns(:), a_perp(:), SourceFunc(:), normal(:,:)
LOGICAL :: FirstTime = .TRUE., NewTime, GotIt, ComputeS, NormalFlux = .TRUE., UnFoundFatal=.TRUE., MeshChanged=.FALSE.
CHARACTER(LEN=MAX_NAME_LEN) :: BottomSurfaceName
SAVE told, FirstTime, NewTime, Nn, dt, Ns, Bodyforce, DIM
SAVE S, rhow, gravity, Zsl, NormalFlux, a_perp, SourceFunc
SAVE NumberOfNodesOnBoundary, NodeOnBoundary, normal
SAVE BottomSurfaceName, bf_id_FS, OldMeshTag
Timevar => VariableGet( Model % Variables,'Time')
t = TimeVar % Values(1)
dt = Model % Solver % dt
IF(GetElementFamily(Model % CurrentElement) < 2) THEN
pw = 0.0_dp
RETURN
END IF
IF (FirstTime) THEN
NewTime = .TRUE.
told = t
OldMeshTag = Model % Mesh % MeshTag
DIM = CoordinateSystemDimension()
rhow = GetConstReal( Model % Constants, 'Water Density', GotIt )
IF (.NOT.GotIt) THEN
WRITE(Message,'(A)') 'Variable Water Density not found. &
&Setting to 1.03225e-18'
CALL INFO('SeaPressure', Message, level=20)
rhow = 1.03225e-18_dp
ELSE
WRITE(Message,'(A,F10.4)') 'Water Density = ', rhow
CALL INFO('SeaPressure', Message , level = 20)
END IF
NormalFlux = GetLogical( Model % Constants, 'Buoyancy Use Basal Melt', GotIt )
IF (.NOT.GotIt) THEN
WRITE(Message,'(A)') 'Variable Buoyancy Use Basal Melt not found. &
&Setting to FALSE'
CALL INFO('SeaPressure', Message, level=20)
NormalFlux = .FALSE.
ELSE
WRITE(Message,*) 'Buoyancy Use Basal Melt = ', NormalFlux
CALL INFO('SeaPressure', Message , level = 20)
END IF
IF (NormalFlux) THEN
BottomSurfaceName = GetString( Model % Constants, 'Bottom Surface Name', GotIt )
IF (.NOT.GotIt) THEN
WRITE(Message,'(A)') 'Variable Bottom SUrface Name not found. &
&Setting to DyBottom'
CALL INFO('SeaPressure', Message, level=20)
BottomSurfaceName = 'DyBottom'
ELSE
WRITE(Message,*)'Bottom Surface Name = ',TRIM(BottomSurfaceName)
CALL INFO('SeaPressure', Message , level = 20)
END IF
bf_id_FS = -1
DO bf_id=1,Model % NumberOFBodyForces
IF( ListCheckPresent( Model % BodyForces(bf_id) % Values, &
TRIM(BottomSurfaceName)//' Accumulation') ) bf_id_FS = bf_id
END DO
IF (bf_id_FS<0) THEN
CALL FATAL('Sea Pressure','No Basal Melt found in any body Force')
END IF
END IF
bf_id = ListGetInteger( Model % Bodies(1) % Values,&
'Body Force', minv=1, maxv=Model % NumberOFMaterials)
IF (DIM==2) THEN
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Lateral Friction Gravity 2',Gotit)
IF (.NOT. Gotit) THEN
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 2',Gotit)
END IF
ELSE
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 3',Gotit)
END IF
ELSE
IF (t > told) THEN
NewTime = .TRUE.
told = t
END IF
ENDIF
IF(OldMeshTag /= Model % Mesh % MeshTag) THEN
OldMeshTag = Model % Mesh % MeshTag
MeshChanged = .TRUE.
END IF
IF(Model % Mesh % Changed) MeshChanged = .TRUE.
IF(FirstTime .OR. (NewTime .AND. MeshChanged)) THEN
MeshChanged = .FALSE.
IF(.NOT. FirstTime) &
DEALLOCATE(NodeOnBoundary, SourceFunc)
ALLOCATE( NodeOnBoundary( Model % Mesh % NumberOfNodes ))
n = Model % MaxElementNodes
ALLOCATE( SourceFunc(n) )
FirstTime = .FALSE.
CurElement => Model % CurrentElement
NodeOnBoundary = 0
NumberOfNodesOnBoundary = 0
DO p = 1, Model % NumberOfBoundaryElements
BCElement => GetBoundaryElement(p)
BC => GetBC( BCElement )
IF( GetElementFamily(BCElement) == 1 ) CYCLE
ComputeS = GetLogical( BC, 'Compute Sea Pressure', GotIt)
IF (.Not.GotIt) ComputeS = .FALSE.
IF (ComputeS) THEN
n = BCElement % Type % NumberOfNodes
DO i = 1, n
j = BCElement % NodeIndexes (i)
IF (NodeOnBoundary(j)==0) THEN
NumberOfNodesOnBoundary = NumberOfNodesOnBoundary + 1
NodeOnBoundary(j) = NumberOfNodesOnBoundary
END IF
END DO
END IF
END DO
Model % CurrentElement => CurElement
IF(ALLOCATED(S)) DEALLOCATE(S,Ns)
IF(ALLOCATED(a_perp)) DEALLOCATE(a_perp)
ALLOCATE( S( NumberOfNodesOnBoundary ), Ns( NumberOfNodesOnBoundary ))
IF (NormalFlux) ALLOCATE( a_perp ( NumberOfNodesOnBoundary ))
END IF
IF (NewTime) THEN
NewTime = .FALSE.
BoundaryElement => Model % CurrentElement
IF ( .NOT. ASSOCIATED(BoundaryElement) ) THEN
CALL FATAL('Sea Pressure','No boundary element found')
END IF
other_body_id = BoundaryElement % BoundaryInfo % outbody
IF (other_body_id < 1) THEN
ParentElement => BoundaryElement % BoundaryInfo % Right
IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left
ELSE
ParentElement => BoundaryElement % BoundaryInfo % Right
IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left
END IF
body_id = ParentElement % BodyId
material_id = ListGetInteger(Model % Bodies(body_id) % Values, 'Material', GotIt, UnFoundFatal=UnFoundFatal)
ParentMaterial => Model % Materials(material_id) % Values
IF ((.NOT. ASSOCIATED(ParentMaterial))) THEN
WRITE(Message,'(A,I10,A,I10)')&
'No material values found for body no ', body_id,&
' under material id ', material_id
CALL FATAL('Sea Pressure',Message)
END IF
NParent = ParentElement % Type % NumberOfNodes
Zsl = GetCReal( ParentMaterial, 'Sea level', GotIt )
IF (.NOT.GotIt) THEN
WRITE(Message,'(A)') 'Variable Sea level not found. &
&Setting to 0.0'
CALL INFO('SeaPressure', Message, level=2)
Zsl = 0.0_dp
ELSE
WRITE(Message,'(A,F10.4)') 'Sea level = ', Zsl
CALL INFO('SeaPressure', Message , level = 2)
END IF
CurElement => Model % CurrentElement
S = 0.0
DO p = 1, Model % NumberOfBoundaryElements
BCElement => GetBoundaryElement(p)
BC => GetBC( BCElement )
IF( GetElementFamily(BCElement) == 1 ) CYCLE
ComputeS = GetLogical( BC, 'Compute Sea Pressure', GotIt)
IF (.Not.GotIt) ComputeS = .FALSE.
IF (ComputeS) THEN
n = BCElement % Type % NumberOfNodes
DO i = 1, n
j = BCElement % NodeIndexes (i)
IF (DIM==2) THEN
S(NodeOnBoundary(j)) = Model % Nodes % y (j)
ELSE
S(NodeOnBoundary(j)) = Model % Nodes % z (j)
END IF
END DO
END IF
END DO
Model % CurrentElement => CurElement
Ns = 0.0_dp
IF (NormalFlux) THEN
a_perp = 0.0_dp
ALLOCATE( Normal(3, NumberOfNodesOnBoundary))
Normal = 0.0_dp
CurElement => Model % CurrentElement
DO p = 1, Model % NumberOfBoundaryElements
BCElement => GetBoundaryElement(p)
BC => GetBC( BCElement )
IF( GetElementFamily(BCElement) == 1 ) CYCLE
ComputeS = GetLogical( BC, 'Compute Sea Spring', GotIt)
IF (.Not.GotIt) ComputeS = .FALSE.
SourceFunc = 0.0_dp
IF (ComputeS) THEN
n = BCElement % Type % NumberOfNodes
SourceFunc(1:n) = GetReal( Model % BodyForces(bf_id_FS) % Values, &
TRIM(BottomSurfaceName)//' Accumulation', GotIt)
CALL GetElementNodes( Nodes , BCElement )
DO i = 1,n
j = BCElement % NodeIndexes( i )
Bu = BCElement % Type % NodeU(i)
IF ( BCElement % Type % Dimension > 1 ) THEN
Bv = BCElement % Type % NodeV(i)
ELSE
Bv = 0.0D0
END IF
Normal(:,NodeOnBoundary(j)) = Normal(:,NodeOnBoundary(j)) + &
NormalVector(BCElement, Nodes, Bu, Bv, .TRUE.)
a_perp( NodeOnBoundary(j) ) = SourceFunc (i)
END DO
END IF
END DO
DO i=1, NumberOfNodesOnBoundary
IF (ABS(Normal(DIM,i)) > 1.0e-20_dp) THEN
Ns(i) = 1.0_dp + (Normal(1,i)/Normal(DIM,i))**2.0_dp
IF (DIM>2) THEN
Ns(i) = Ns(i) + (Normal(2,i)/Normal(3,i))**2.0_dp
END IF
Ns(i) = SQRT(Ns(i))
ELSE
Ns(i) = -999.0
END IF
END DO
DEALLOCATE (Normal)
Model % CurrentElement => CurElement
END IF
ENDIF
j = NodeOnBoundary( nodenumber )
IF ( NormalFlux .AND. (Ns(j) > 0.0_dp)) THEN
pw = -gravity * rhow * (Zsl - S(j) - a_perp(j) * dt * Ns(j) )
ELSE
pw = -gravity * rhow * (Zsl - S(j))
END IF
IF (pw > 0.0) pw = 0.0
END FUNCTION SeaPressure
FUNCTION SeaSpring ( Model, nodenumber, y) RESULT(C)
USE types
USE CoordinateSystems
USE SolverUtils
USE ElementDescription
USE DefUtils
IMPLICIT NONE
TYPE(Model_t) :: Model
TYPE(Solver_t):: Solver
TYPE(Nodes_t), SAVE :: Nodes
TYPE(variable_t), POINTER :: Timevar, NormalSolution
TYPE(Element_t), POINTER :: BoundaryElement, BCElement, CurElement, ParentElement
TYPE(ValueList_t), POINTER :: BC, material, ParentMaterial, BodyForce
INTEGER :: NBoundary, NParent, BoundaryElementNode, ParentElementNode, body_id, other_body_id, material_id
INTEGER :: nodenumber, NumberOfNodesOnBoundary
INTEGER, ALLOCATABLE :: NodeOnBoundary(:)
INTEGER :: Nn, i, j, k, p, n, Nmax, bf_id, DIM, OldMeshTag
REAL(KIND=dp) :: y, C, t, told, dt, Bu, Bv, aux
REAL(KIND=dp) :: rhow, gravity, Nsi, NodeNormal(3)
REAL(KIND=dp), ALLOCATABLE :: Ns(:), normal(:,:)
LOGICAL :: FirstTime = .TRUE., NewTime, GotIt, ComputeS,MeshChanged=.FALSE.
SAVE told, FirstTime, NewTime, Nn, dt, Ns, Bodyforce, DIM
SAVE rhow, gravity
SAVE NumberOfNodesOnBoundary, NodeOnBoundary, normal,OldMeshTag
SAVE NormalSolution
Timevar => VariableGet( Model % Variables,'Time')
t = TimeVar % Values(1)
aux = GetConstReal(Model % Constants, 'Sea Spring Timestep Size', GotIt)
IF (GotIt) THEN
dt = aux
ELSE
dt = Model % Solver % dt
END IF
IF(GetElementFamily(Model % CurrentElement) < 2) THEN
C = 1.0e20_dp
RETURN
END IF
IF(FirstTime) THEN
NewTime = .TRUE.
OldMeshTag = Model % Mesh % MeshTag
ELSE IF(t > told) THEN
NewTime = .TRUE.
told = t
END IF
IF(OldMeshTag .NE. Model % Mesh % MeshTag) THEN
OldMeshTag = Model % Mesh % MeshTag
MeshChanged = .TRUE.
END IF
IF(Model % Mesh % Changed) MeshChanged = .TRUE.
IF (FirstTime .OR. (NewTime .AND. MeshChanged)) THEN
NormalSolution => VariableGet( Model % Variables, 'Normal Vector')
IF(.NOT. FirstTime) DEALLOCATE(NodeOnBoundary, Ns)
FirstTime = .FALSE.
NewTime = .FALSE.
ALLOCATE( NodeOnBoundary( Model % Mesh % NumberOfNodes ))
n = Model % MaxElementNodes
DIM = CoordinateSystemDimension()
rhow = GetConstReal( Model % Constants, 'Water Density', GotIt )
IF (.NOT.GotIt) THEN
WRITE(Message,'(A)') 'Variable "Water Density" not found in Constants.'
CALL FATAL('SeaSpring', Message)
ELSE
WRITE(Message,'(A,F10.4)') 'Water Density = ', rhow
CALL INFO('SeaSpring', Message , level = 20)
END IF
BoundaryElement => Model % CurrentElement
IF ( .NOT. ASSOCIATED(BoundaryElement) ) THEN
CALL FATAL('SeaSpring','No boundary element found')
END IF
other_body_id = BoundaryElement % BoundaryInfo % outbody
IF (other_body_id < 1) THEN
ParentElement => BoundaryElement % BoundaryInfo % Right
IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left
ELSE
ParentElement => BoundaryElement % BoundaryInfo % Right
IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left
END IF
BodyForce => GetBodyForce(ParentElement)
bf_id = ListGetInteger( Model % Bodies(1) % Values,&
'Body Force', minv=1, maxv=Model % NumberOFMaterials)
IF (DIM==2) THEN
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Lateral Friction Gravity 2',Gotit)
IF (.NOT. Gotit) THEN
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 2',Gotit)
END IF
ELSE
gravity = -GetConstReal( Model % BodyForces(bf_id) % Values, 'Flow BodyForce 3',Gotit)
END IF
CurElement => Model % CurrentElement
NodeOnBoundary = 0
NumberOfNodesOnBoundary = 0
DO p = 1, Model % NumberOfBoundaryElements
BCElement => GetBoundaryElement(p)
BC => GetBC( BCElement )
IF( GetElementFamily(BCElement) == 1 ) CYCLE
ComputeS = GetLogical( BC, 'Compute Sea Spring', GotIt)
IF (.Not.GotIt) ComputeS = .FALSE.
IF (ComputeS) THEN
n = BCElement % Type % NumberOfNodes
DO i = 1, n
j = BCElement % NodeIndexes (i)
IF (NodeOnBoundary(j)==0) THEN
NumberOfNodesOnBoundary = NumberOfNodesOnBoundary + 1
NodeOnBoundary(j) = NumberOfNodesOnBoundary
END IF
END DO
END IF
END DO
Model % CurrentElement => CurElement
ALLOCATE( Ns( NumberOfNodesOnBoundary ))
ALLOCATE( Normal(3, NumberOfNodesOnBoundary))
Ns = 0.0_dp
Normal = 0.0_dp
CurElement => Model % CurrentElement
DO p = 1, Model % NumberOfBoundaryElements
BCElement => GetBoundaryElement(p)
BC => GetBC( BCElement )
IF( GetElementFamily(BCElement) == 1 ) CYCLE
ComputeS = GetLogical( BC, 'Compute Sea Spring', GotIt)
IF (.Not.GotIt) ComputeS = .FALSE.
IF (ComputeS) THEN
CALL GetElementNodes( Nodes , BCElement )
n = BCElement % Type % NumberOfNodes
DO i = 1,n
j = BCElement % NodeIndexes( i )
Bu = BCElement % Type % NodeU(i)
IF ( BCElement % TYPE % DIMENSION > 1 ) THEN
Bv = BCElement % Type % NodeV(i)
ELSE
Bv = 0.0D0
END IF
Normal(:,NodeOnBoundary(j)) = Normal(:,NodeOnBoundary(j)) + &
NormalVector(BCElement, Nodes, Bu, Bv, .TRUE.)
END DO
END IF
END DO
DO i=1, NumberOfNodesOnBoundary
IF (ABS(Normal(DIM,i)) > 1.0e-20_dp) THEN
Ns(i) = 1.0_dp + (Normal(1,i)/Normal(DIM,i))**2.0_dp
IF (DIM>2) THEN
Ns(i) = Ns(i) + (Normal(2,i)/Normal(3,i))**2.0_dp
END IF
Ns(i) = SQRT(Ns(i))
ELSE
Ns(i) = -999.0_dp
CALL WARN('SeaSpring', 'Lower surface almost is vertically aligned')
END IF
END DO
DEALLOCATE (Normal)
Model % CurrentElement => CurElement
ENDIF
GotIt = .FALSE.
Nsi = -999.0_dp
NodeNormal = ConsistentNormalVector( CurrentModel % Solver, NormalSolution, &
Model % CurrentElement, GotIt, Node = NodeNumber )
IF( GotIt ) THEN
IF(ABS(NodeNormal(dim)) > 1.0e-20_dp) THEN
Nsi = SQRT( 1.0_dp + (SUM(NodeNormal(1:dim-1)**2)) / NodeNormal(dim)**2.0_dp )
GotIt = .TRUE.
END IF
END IF
IF(.NOT. GotIt ) THEN
j = NodeOnBoundary( nodenumber )
IF( j > 0 ) Nsi = Ns(j)
END IF
IF( Nsi > 0.0_dp ) THEN
C = gravity * rhow * dt * Nsi
ELSE
C = 1.0e20_dp
END IF
END FUNCTION SeaSpring