Path: blob/devel/elmerice/UserFunctions/USF_Contact.F90
3196 views
!/*****************************************************************************/1! *2! * Elmer/Ice, a glaciological add-on to Elmer3! * http://elmerice.elmerfem.org4! *5! *6! * This program is free software; you can redistribute it and/or7! * modify it under the terms of the GNU General Public License8! * as published by the Free Software Foundation; either version 29! * of the License, or (at your option) any later version.10! *11! * This program is distributed in the hope that it will be useful,12! * but WITHOUT ANY WARRANTY; without even the implied warranty of13! * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14! * GNU General Public License for more details.15! *16! * You should have received a copy of the GNU General Public License17! * along with this program (in file fem/GPL-2); if not, write to the18! * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,19! * Boston, MA 02110-1301, USA.20! *21! *****************************************************************************/22! ******************************************************************************23! *24! * Authors:25! * Email:26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date:29! * Date Modifications:2007/10/25. Gael Durand30! *31! *****************************************************************************32!> tests if resting ice becomes floating ice (GroundedMask from 0 or 1 to -1)33!>34!> Return a friction coefficient35!> -from sliding weertman for resting ice (GroundedMask = 0 or 1)36!> -of 0 for floating ice (GroundedMask = -1)37!> 2014 : Introduce 3 different ways of defining the grounding line (Mask = 0)38!> Last Grounded ; First Floating ; Discontinuous3940FUNCTION SlidCoef_Contact ( Model, nodenumber, y) RESULT(Bdrag)4142USE ElementDescription43USE DefUtils4445IMPLICIT NONE4647TYPE(Model_t) :: Model48TYPE(Solver_t) :: Solver49TYPE(variable_t), POINTER :: TimeVar, NormalVar, VarSurfResidual, GroundedMaskVar, HydroVar, DistanceVar, FrictionVar50TYPE(ValueList_t), POINTER :: BC51TYPE(Element_t), POINTER :: Element, CurElement, BoundaryElement52TYPE(Nodes_t), SAVE :: Nodes5354REAL(KIND=dp), POINTER :: NormalValues(:), ResidValues(:), GroundedMask(:), Hydro(:), &55Distance(:), FrictionValues(:)56REAL(KIND=dp) :: Bdrag, t, told, thresh, FrictionValue57REAL(KIND=dp), ALLOCATABLE :: Normal(:), Fwater(:), Fbase(:)5859INTEGER, POINTER :: NormalPerm(:), ResidPerm(:), GroundedMaskPerm(:), HydroPerm(:), &60DistancePerm(:), FrictionPerm(:)61INTEGER :: nodenumber, ii, DIM, GL_retreat, n, tt, Nn, jj, MSum, ZSum6263LOGICAL :: FirstTime = .TRUE., GotIt, Yeschange, GLmoves, Friction, UnFoundFatal=.TRUE.6465REAL (KIND=dp) :: y, relChange, relChangeOld, Sliding_Budd, Sliding_Weertman, Friction_Coulomb6667REAL(KIND=dp) :: comp, cond, TestContact68CHARACTER(LEN=MAX_NAME_LEN) :: USF_Name='SlidCoef_Contact', Sl_Law, GLtype, FrictionVarName69CHARACTER(LEN=MAX_NAME_LEN) :: FlowLoadsName, FlowSolutionName7071SAVE FirstTime, yeschange, told, GLmoves, thresh, GLtype, TestContact72SAVE DIM, USF_Name, Normal, Fwater, Fbase, relChangeOld, Sl_Law73SAVE FrictionVar, FrictionValues, FrictionValue, FrictionPerm, BC, FlowLoadsName74SAVE FlowSolutionName7576!----------------------------------------------------------------------------7778! Real time import79Timevar => VariableGet( Model % Variables,'Time')80t = TimeVar % Values(1)8182! GroundedMask import83GroundedMaskVar => VariableGet( Model % Mesh % Variables, 'GroundedMask',UnFoundFatal=UnFoundFatal)84GroundedMask => GroundedMaskVar % Values85GroundedMaskPerm => GroundedMaskVar % Perm8687relchange = Model % Solver % Variable % NonLinChange8889!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!90! First time step for the First time91!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!9293IF (FirstTime) THEN94DIM = CoordinateSystemDimension()95FirstTime = .FALSE.96n = Model % MaxElementNodes97told = t9899! means have the possibility to change100yesChange = .TRUE.101ALLOCATE( Normal(DIM), Fwater(DIM), Fbase(DIM) )102103relChangeOld = relChange104105! choice of the Sliding Law106BoundaryElement => Model % CurrentElement107BC => GetBC(BoundaryElement)108109FlowSolutionName = GetString( BC, 'Flow Solution Name', GotIt )110IF (.NOT.Gotit) THEN111FlowSolutionName = 'Flow Solution'112CALL Info(USF_Name, 'Using default name >Flow Solution<', Level=4)113END IF114WRITE(FlowLoadsName,'(A)') TRIM(FlowSolutionName)//' Loads'115116Sl_Law = GetString( BC, 'Sliding Law', GotIt )117IF (.NOT.Gotit) THEN118CALL FATAL(USF_Name,'No "Sliding law" Name given')119END IF120121GLtype = GetString( BC, 'Grounding Line Definition', GotIt )122IF (.NOT.Gotit) THEN123GLtype = 'last grounded'124CALL Info(USF_Name, 'Grounded Line Defined as the last Grounded point', Level=3)125ELSE126WRITE(Message, '(A,A)') 'Grounding Line Defined as ', GLtype127CALL Info(USF_Name, Message, Level=3)128END IF129130! Possibility to fix the grounding line, default is a moving Grounding Line131GLmoves = GetLogical( BC, 'Grounding line moves', GotIt )132IF (.NOT.GotIt) THEN133GLmoves = .TRUE.134END IF135IF (GLmoves) THEN136CALL Info(USF_Name, 'GL may move by default', Level=3)137CALL Info(USF_Name, 'If you want to fix the Grounding Line, put the keyword "Grounding line moves" to False', Level=3)138ELSE139CALL Info(USF_Name, 'GL will be fixed', Level=3)140END IF141142TestContact = GetConstReal( BC, 'Test Contact Tolerance', GotIt )143IF (.NOT.Gotit) THEN144TestContact = 1.0e-3145CALL Info(USF_Name, 'Contact will be tested for a tolerance of 1.0e-3', Level=3)146ELSE147WRITE(Message, '(A,e14.8)') 'Contact tested for a tolerance of ', TestContact148CALL Info(USF_Name, Message, Level=3)149END IF150151! Possibility to avoid detachement from nodes that are too far inland from the Grounding line152! Uses the DistanceSolver153! Default is non possible detachment154thresh = GetConstReal( BC, 'non detachment inland distance', GotIt )155IF (.NOT.GotIt) THEN156thresh = -10000.0_dp157CALL INFO( USF_Name, 'far inland nodes have the possibility to detach by default', Level=3)158CALL INFO( USF_Name, 'to avoid detachment (when bedrock is well below sea level),', Level=3)159CALL INFO( USF_Name, 'use the keyword "non detachment inland distance" to the distance you wish', Level=3)160CALL INFO( USF_Name, 'This works with the DistanceSolver', Level=3)161ELSE162CALL INFO( USF_Name, 'far inland nodes will not detach', level=3)163END IF164ENDIF165166IF(Sl_Law(1:10) == 'prescribed') THEN167IF(Sl_Law(1:16) == 'prescribed value') THEN168FrictionValue = ListGetConstReal(BC, 'Friction Value', UnfoundFatal=.TRUE.)169ELSE170FrictionVarName = GetString( BC, 'Friction Variable Name', GotIt )171IF(.NOT. GotIt) CALL Fatal(USF_Name, 'Prescribed friction requested but no &172"Friction Variable Name" found!')173FrictionVar => VariableGet(Model % Mesh % Variables, FrictionVarName)174IF(ASSOCIATED(FrictionVar)) THEN175FrictionValues => FrictionVar % Values176FrictionPerm => FrictionVar % Perm177ELSE178WRITE(Message, '(A,A)') 'Unable to find variable: ',FrictionVarName179CALL Fatal(USF_Name, Message)180END IF181END IF182END IF183184185!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!186! First time step for a New time187!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!188189IF ( t > told ) THEN190told = t191yesChange = .TRUE.192relChangeOld = relChange193END IF194195! to use the non detachment possibility when a grounded node is too far from the grounding line196! and positioned on a well below sea level bedrock197IF (thresh.GT.0.0) THEN198DistanceVar => VariableGet( Model % Mesh % Variables, 'Distance',UnFoundFatal=UnFoundFatal)199Distance => DistanceVar % Values200DistancePerm => DistanceVar % Perm201END IF202203!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!204! Look at the convergence of the FlowSolver.205! If relative change < TestContact, test if traction occurs. To apply one time206!207! Only to release contact between bed and ice as hydrostatic pressure is higher than normal stress208!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!209210Normal = 0.0_dp211Fwater = 0.0_dp212Fbase = 0.0_dp213214IF ( (relChange.NE.relChangeOld) .AND. (relchange.GT.0.0_dp) .AND. &215& (relchange.LT.TestContact) .AND. (yesChange) .AND. GLmoves ) THEN216! Change the basal condition just once per timestep217yesChange = .FALSE.218219CALL Info(USF_name,'FLOW SOLVER HAS SLIGHTLY CONVERGED: look for new basal conditions', Level=3)220221VarSurfResidual => VariableGet( Model % Mesh % Variables, FlowLoadsName, UnFoundFatal=UnFoundFatal)222ResidPerm => VarSurfResidual % Perm223ResidValues => VarSurfResidual % Values224225NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)226NormalPerm => NormalVar % Perm227NormalValues => NormalVar % Values228229!Force exerted by the water, computed for each good boundary nodes (whatever on the bed or floating)230!From GetHydrostaticLoads231232HydroVar => VariableGet( Model % Mesh % Variables, 'Fw',UnFoundFatal=UnFoundFatal)233Hydro => HydroVar % Values234HydroPerm => HydroVar % Perm235236! Retreat of the Grounding line if Hydro loads higher than residual values237GL_retreat = 0238239CurElement => Model % CurrentElement240DO tt = 1, Model % NumberOfBoundaryElements241242Element => GetBoundaryElement(tt)243IF (ParEnv % myPe .NE. Element % partIndex) CYCLE244n = GetElementNOFNodes(Element)245246CALL GetElementNodes(Nodes, Element)247248IF (ANY(GroundedMaskPerm(Element % NodeIndexes(1:n))==0)) CYCLE249DO ii = 1,n250251Nn = GroundedMaskPerm(Element % NodeIndexes(ii))252! the grounded mask is not defined here253IF (Nn==0) CYCLE254IF (GroundedMask(Nn) < -0.5_dp) CYCLE255256jj = Element % NodeIndexes(ii)257258! comparison between water load and reaction259260Normal = NormalValues(DIM*(NormalPerm(jj)-1)+1 : DIM*NormalPerm(jj))261Fwater = Hydro(DIM*(HydroPerm(jj)-1)+1 : DIM*HydroPerm(jj))262Fbase = ResidValues((DIM+1)*(ResidPerm(jj)-1)+1 : (DIM+1)*ResidPerm(jj)-1)263264! comparison between water pressure and bed action265comp = SUM( Fwater * Normal ) + SUM( Fbase * Normal )266267IF (comp .GE. 0.0_dp) THEN268IF (thresh.LE.0.0_dp) THEN269GroundedMask(Nn) = -1.0_dp270GL_retreat = GL_retreat + 1271WRITE(Message,*)'Retreat of the Grounding Line : ', Nodes % x(ii), Nodes % y(ii)272CALL INFO(USF_Name, Message, Level=4)273ELSE274IF ( Distance(DistancePerm(Element % NodeIndexes(ii))).LE.thresh ) THEN275GroundedMask(Nn) = -1.0_dp276GL_retreat = GL_retreat + 1277WRITE(message,*)'Retreat of the Grounding Line : ', Nodes % x(ii), Nodes % y(ii)278CALL INFO(USF_Name, Message, Level=4)279END IF280END IF281END IF282END DO283284END DO285Model % CurrentElement => CurElement286287! with the previous step288! Some 0 (Grounding line) may have been replaced by -1 (floating nodes)289! here replacement of some 1 by 0's290291IF (GL_retreat.GT.0) THEN292CurElement => Model % CurrentElement293DO tt = 1, Model % NumberOfBoundaryElements294295Element => GetBoundaryElement(tt)296IF (ParEnv % myPe .NE. Element % partIndex) CYCLE297n = GetElementNOFNodes(Element)298299CALL GetElementNodes(Nodes, Element)300MSum = 0301ZSum = 0302303IF (ANY(GroundedMaskPerm(Element % NodeIndexes(1:n))==0)) CYCLE304DO ii = 1,n305306Nn = GroundedMaskPerm(Element % NodeIndexes(ii))307! the grounded mask is not defined here308IF (Nn==0) CYCLE309MSum = MSum + INT(GroundedMask(Nn))310IF (GroundedMask(Nn)==0.0_dp) ZSum = ZSum + 1311312END DO313314IF (MSum+ZSum .LT. n) THEN315DO ii=1,n316Nn = GroundedMaskPerm(Element % NodeIndexes(ii))317IF (Nn==0) CYCLE318319IF (GroundedMask(Nn)==1.0_dp) THEN320GroundedMask(Nn)=0.0_dp321END IF322323END DO324END IF325326END DO327Model % CurrentElement => CurElement328END IF329END IF330331relChangeOld = relChange332333334IF (GroundedMaskPerm(nodenumber) > 0) THEN335! for the bottom surface, where the GroundedMask is defined336cond = GroundedMask(GroundedMaskPerm(nodenumber))337338! Definition of the Grounding line in term of friction339! If GLtype = Last Grounded -> Bdrag = 0 if Nodal Mask < 0340! If GLtype = First Floating -> Bdrag = 0 if Nodal Mask <=0341! If GLtype = Discontinuous -> Bdrag = 0 if at one node of the element Mask<=0342343Friction = .FALSE.344SELECT CASE(GLtype)345CASE('last grounded')346IF (cond > -0.5) Friction = .TRUE.347CASE('first floating')348IF (cond > 0.5) Friction = .TRUE.349CASE('discontinuous')350BoundaryElement => Model % CurrentElement351IF (ALL(GroundedMask(GroundedMaskPerm(BoundaryElement % NodeIndexes))>-0.5)) Friction = .TRUE.352CASE DEFAULT353WRITE(Message, '(A,A)') 'GL type not recognised ', GLtype354CALL FATAL( USF_Name, Message)355END SELECT356357IF (Friction) THEN358! grounded node359SELECT CASE(Sl_law)360CASE ('weertman')361Bdrag = Sliding_weertman(Model, nodenumber, y)362CASE ('budd')363Bdrag = Sliding_Budd(Model, nodenumber, y)364CASE ('coulomb')365Bdrag = Friction_Coulomb(Model, nodenumber, y)366CASE('prescribed beta2')367Bdrag = FrictionValues(FrictionPerm(nodenumber))**2.0_dp368CASE('prescribed power')369Bdrag = 10.0_dp**FrictionValues(FrictionPerm(nodenumber))370CASE('prescribed variable')371Bdrag = FrictionValues(FrictionPerm(nodenumber))372CASE('prescribed value')373Bdrag = FrictionValue374CASE DEFAULT375WRITE(Message, '(A,A)') 'Sliding law not recognised ',Sl_law376CALL FATAL( USF_Name, Message)377END SELECT378ELSE379! floating node380Bdrag = 0.0_dp381END IF382ELSE383! for other surfaces, typically for lateral surfaces within buttressing experiments384Bdrag = Sliding_weertman(Model, nodenumber, y)385END IF386END FUNCTION SlidCoef_Contact387388389390391392