Path: blob/devel/elmerice/UserFunctions/USF_Sliding.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: Olivier Gagliardini, Ga¨el Durand, Thomas Zwinger25! * Email:26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date:29! * 2007/10/25. Gael Durand30! * 2008/04/06 OG 2D -> 3D31! * 2009/05/18 OG FirstTime in the SAVE !32! *****************************************************************************33!> USF_Sliding.f9034!>35!>36!> Gives the basal drag for different sliding law37!>38!> (1) Sliding_Weertman39!> Need some inputs in the sif file.40!> Parameters: Weertman Friction Coefficient -> C41!> Weertman Exponent -> m42!> Weertman Linear Velocity -> ut043!>44!> Compute the Bdrag coefficient such as tau_b = Bdrag ub45!> for the non-linear Weertman law tau_b = C ub^m46!> To linearize the Weertman law, we can distinguish 4 cases:47!> 1/ ut=0 , tau_b=0 => Bdrag = infinity (no sliding, first step)48!> 2/ ut=0 , tau_b =/0 => Bdrag = C^1/m tau_b^(1-1/m)49!> 3/ ut=/0 , tau_b=0 => Bdrag = Cub^(m-1)50!> 4/ ut=/0 , tau_b=/0 => case 351!> For cases 3 and 4, if ut < ut0, Bdrag = C ut0^{m-1}52!>53!>54!> (2) Friction_Coulomb Sliding Gag JGR 200755!> Need some inputs in the sif file.56!> Parameters: Friction Law Sliding Coefficient -> As57!> Friction Law Post-Peak Exponent -> q >= 158!> Friction Law Maximum Value -> C ~ max bed slope59!> Friction Law Linear Velocity -> ut060FUNCTION Sliding_Weertman (Model, nodenumber, x) RESULT(Bdrag)6162USE types63USE CoordinateSystems64USE SolverUtils65USE ElementDescription66USE DefUtils67IMPLICIT NONE68TYPE(Model_t) :: Model69REAL (KIND=dp) :: y , x70INTEGER :: nodenumber7172TYPE(ValueList_t), POINTER :: BC73TYPE(Variable_t), POINTER :: NormalVar, FlowVariable74REAL(KIND=dp), POINTER :: NormalValues(:), FlowValues(:)75INTEGER, POINTER :: NormalPerm(:), FlowPerm(:)76INTEGER :: DIM, i, j, n77REAL (KIND=dp) :: C, m, Bdrag78REAL (KIND=dp) :: ut, un, ut079REAL (KIND=dp), ALLOCATABLE :: normal(:), velo(:), AuxReal(:)80LOGICAL :: GotIt, FirstTime = .TRUE., SSA = .FALSE., UnFoundFatal=.TRUE.8182CHARACTER(LEN=MAX_NAME_LEN) :: FlowSolverName8384SAVE :: normal, velo, DIM, SSA85SAVE :: FlowSolverName, FirstTime8687IF (FirstTime) THEN88FirstTime = .FALSE.89DIM = CoordinateSystemDimension()90n = Model % MaxElementNodes91IF ((DIM == 2).OR.(DIM == 3)) THEN92ALLOCATE(normal(DIM), velo(DIM))93ELSE94CALL FATAL('USF_sliding', 'Bad dimension of the problem')95END IF9697! BC => GetBC(Model % CurrentElement)98FlowSolverName = GetString( Model % Solver % Values , 'Flow Solver Name', GotIt )99IF (.NOT.Gotit) FlowSolverName = 'Flow Solution'100SELECT CASE (FlowSolverName)101CASE ('ssabasalflow')102SSA = .TRUE.103END SELECT104WRITE(Message,*)&105'Flow Solver Name:', TRIM(FlowSolverName),' SSA:',SSA106CALL INFO('Sliding_Weertman',Message,Level=3)107END IF108109!Read the coefficients C and m in the sif file110BC => GetBC(Model % CurrentElement)111IF (.NOT.ASSOCIATED(BC))THEN112CALL Fatal('Sliding_Weertman', 'No BC Found')113END IF114115n = GetElementNOFNodes()116ALLOCATE (auxReal(n))117auxReal(1:n) = GetReal( BC, 'Weertman Friction Coefficient', GotIt )118IF (.NOT.GotIt) THEN119CALL FATAL('USF_sliding', 'Need a Friction Coefficient for the Weertman sliding law')120END IF121DO i=1,n122IF (nodenumber == Model % CurrentElement % NodeIndexes( i )) EXIT123END DO124C = auxReal(i)125DEALLOCATE(auxReal)126127m = GetConstReal( BC, 'Weertman Exponent', GotIt )128IF (.NOT.GotIt) THEN129CALL FATAL('USF_sliding', 'Need an Exponent for the Weertman sliding law')130END IF131132ut0 = GetConstReal( BC, 'Weertman Linear Velocity', GotIt )133IF (.NOT.GotIt) THEN134CALL FATAL('USF_sliding', 'Need a Linear Velocity for the Weertman sliding law')135END IF136137! Get the variables to compute ut138FlowVariable => VariableGet( Model % Variables, FlowSolverName,UnFoundFatal=UnFoundFatal)139FlowPerm => FlowVariable % Perm140FlowValues => FlowVariable % Values141142! NS, AIFlow cases143IF (.NOT.SSA) THEN144! Get the variable to compute the normal145NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)146NormalPerm => NormalVar % Perm147NormalValues => NormalVar % Values148149DO i=1, DIM150normal(i) = -NormalValues(DIM*(NormalPerm(Nodenumber)-1) + i)151velo(i) = FlowValues( (DIM+1)*(FlowPerm(Nodenumber)-1) + i )152END DO153un = SUM(velo(1:DIM)*normal(1:DIM))154ut = SQRT( SUM( (velo(1:DIM)-un*normal(1:DIM))**2.0 ) )155! SSA Flow case156ELSE157DO i=1, DIM-1158velo(i) = FlowValues( (DIM-1)*(FlowPerm(Nodenumber)-1) + i )159END DO160ut = SQRT(SUM( velo(1:DIM-1)**2.0 ))161END IF162163ut = MAX(ut,ut0)164Bdrag = MIN(C * ut**(m-1.0),1.0e20)165END FUNCTION Sliding_Weertman166167!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!168!> (2) Sliding Gag JGR 2007169!>170!> Gagliardini, Cohen, Raback and Zwinger, 2007. Finite-Element Modelling of171!> Subglacial Cavities and Related Friction Law. J. of Geophys. Res., Earth172!> Surface, 112, F02027173!>174!> Need some inputs in the sif file.175!> Parameters: Friction Law Sliding Coefficient -> As176!> Friction Law Post-Peak Exponent -> q >= 1177!> Friction Law Maximum Value -> C ~ max bed slope178!> Friction Law Linear Velocity -> ut0179!> Friction Law PowerLaw Exponent -> m = (n Glen's law)180!>181!> Water Pressure (BC) (Compressive - positive)182!>183!> tau_b = C.N.[ X . ub^-n / (1 + a.X^q) ]^1/n . ub184!> with a = (q-1)^(q-1) / q^q and X = ub / (C^n N^n As)185!>186!> => Bdrag = C.N.[ X . ub^-n / (1 + a.X^q) ]^1/n187FUNCTION Friction_Coulomb (Model, nodenumber, y) RESULT(Bdrag)188189USE types190USE CoordinateSystems191USE SolverUtils192USE ElementDescription193USE DefUtils194IMPLICIT NONE195TYPE(Model_t) :: Model196REAL (KIND=dp) :: y , x197INTEGER :: nodenumber198199TYPE(ValueList_t), POINTER :: BC, Material200TYPE(Variable_t), POINTER :: TimeVar, NVariable, StressVariable, NormalVar, FlowVariable201TYPE(Element_t), POINTER :: BoundaryElement, ParentElement202REAL(KIND=dp), POINTER :: StressValues(:), NormalValues(:), FlowValues(:)203REAL(KIND=dp), POINTER :: NValues(:)204INTEGER, POINTER :: StressPerm(:), NormalPerm(:), FlowPerm(:), NPerm(:)205INTEGER :: DIM, i, j, Ind(3,3), n, other_body_id206REAL (KIND=dp) :: C, m, Bdrag, As, Ne, q, Xi, a, Pw, Pice207REAL (KIND=dp) :: Snt, Snn, ut, un, ut0, t, t0208LOGICAL :: GotIt, FirstTime = .TRUE., Cauchy, UnFoundFatal209REAL (KIND=dp), ALLOCATABLE :: Sig(:,:), normal(:), velo(:), Sn(:), AuxReal(:)210211SAVE :: Sig, normal, velo, DIM, Ind, Sn212SAVE :: t0, FirstTime213214TimeVar => VariableGet( Model % Variables,'Time')215t = TimeVar % Values(1)216217IF (FirstTime) THEN218FirstTime = .FALSE.219t0 = t220DIM = CoordinateSystemDimension()221IF ((DIM == 2).OR.(DIM == 3)) THEN222ALLOCATE(Sig(DIM,DIM),normal(DIM), velo(DIM), Sn(DIM))223ELSE224CALL FATAL('Friction_Coulomb', 'Bad dimension of the problem')225END IF226Do i=1, 3227Ind(i,i) = i228END DO229Ind(1,2) = 4230Ind(2,1) = 4231Ind(2,3) = 5232Ind(3,2) = 5233Ind(3,1) = 6234Ind(1,3) = 6235END IF236237!Read the coefficients As, C, q, and m=1/n in the BC Section238BoundaryElement => Model % CurrentElement239BC => GetBC(BoundaryElement)240n = GetElementNOFNodes()241IF (.NOT.ASSOCIATED(BC))THEN242CALL Fatal('Friction_Coulomb', 'No BC Found')243END IF244245! Friction Law Sliding Coefficient -> As246ALLOCATE (auxreal(n))247auxReal(1:n) = GetReal( BC, 'Friction Law Sliding Coefficient', GotIt )248IF (.NOT.GotIt) THEN249CALL FATAL('Friction_Coulomb', 'Need a Friction Law Sliding Coefficient for the Coulomb Friction Law')250END IF251DO i=1, n252IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT253END DO254As = auxReal(i)255256! Friction Law Post-Peak Exponent -> q >= 1257auxReal(1:n) = GetReal( BC, 'Friction Law Post-Peak Exponent', GotIt )258IF (.NOT.GotIt) THEN259CALL FATAL('Friction_Coulomb', 'Need a Friction Law Post-Peak Exponent &260& (>= 1) for the Coulomb Friction Law')261END IF262DO i=1, n263IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT264END DO265q = auxReal(i)266267a = (q-1.0)**(q-1.0) / q**q268269! Friction Law Maximum Value -> C ~ max bed slope270auxReal(1:n) = GetReal( BC, 'Friction Law Maximum Value', GotIt )271IF (.NOT.GotIt) THEN272CALL FATAL('Friction_Coulomb', 'Need a Friction Law Maximum Value &273& (~ Max Bed Slope) for the Coulomb Friction Law')274END IF275DO i=1, n276IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT277END DO278C = auxReal(i)279280281! Friction Law Linear Velocity -> ut0282ut0 = GetConstReal( BC, 'Friction Law Linear Velocity', GotIt )283IF (.NOT.GotIt) THEN284CALL FATAL('Friction_Coulomb', 'Need a Friction Law Linear Velocity for the Coulomb Friction Law ')285END IF286!287! friction Law PowerLaw Exponent m288m = GetConstReal( BC, 'Friction Law PowerLaw Exponent', GotIt )289IF (.NOT.GotIt) THEN290CALL FATAL('Friction_Coulomb', 'Need a Friction Law PowerLaw Exponent &291& (= n Glen law) for the Coulomb Friction Law')292END IF293!294! Effective Pressure is either given as a variable295! or computed as N = -Snn - pw296! Get the effective pressure297! If NVariable does not exist, N will be computed as N = -Snn - pw298NVariable => VariableGet( Model % Variables, 'Effective Pressure' )299IF ( ASSOCIATED( NVariable ) ) THEN300NPerm => NVariable % Perm301NValues => NVariable % Values302303ELSE304! Get the water Pressure from the Stokes keyword 'External Pressure'305! Use the convention for the water pressure Pw > 0 => Compression306auxReal(1:n) = GetReal( BC, 'External Pressure', GotIt )307IF (.NOT.GotIt) THEN308CALL FATAL('Friction_Coulomb', 'Need External Pressure &309& Or Variable Effective Pressure')310END IF311DO i=1, n312IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT313END DO314! Because the convention is External Pressure < 0 => Compression,315! need to change the sign316Pw = -auxReal(i)317318! Get the variables to compute tau_b319StressVariable => VariableGet( Model % Variables, 'Stress',UnFoundFatal=UnFoundFatal)320StressPerm => StressVariable % Perm321StressValues => StressVariable % Values322!323! Cauchy or deviatoric stresses ?324!325other_body_id = BoundaryElement % BoundaryInfo % outbody326IF (other_body_id < 1) THEN ! only one body in calculation327ParentElement => BoundaryElement % BoundaryInfo % Right328IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left329ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards330ParentElement => BoundaryElement % BoundaryInfo % Right331IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left332END IF333334Material => GetMaterial(ParentElement)335Cauchy = ListGetLogical( Material , 'Cauchy', Gotit )336337END IF338DEALLOCATE(auxReal)339340! Get the flow variables to compute ut341FlowVariable => VariableGet( Model % Variables, 'Flow Solution',UnFoundFatal=UnFoundFatal)342FlowPerm => FlowVariable % Perm343FlowValues => FlowVariable % Values344345! Get the normal variable to compute the normal346NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)347NormalPerm => NormalVar % Perm348NormalValues => NormalVar % Values349350DO i=1, DIM351normal(i) = -NormalValues(DIM*(NormalPerm(Nodenumber)-1) + i)352velo(i) = FlowValues( (DIM+1)*(FlowPerm(Nodenumber)-1) + i )353END DO354355un = SUM(velo(1:DIM)*normal(1:DIM))356ut = SQRT( SUM( (velo(1:DIM)-un*normal(1:DIM))**2.0 ) )357358! Compute Effective Pressure Ne359! Effective pressure N >=0360IF ( ASSOCIATED( NVariable ) ) THEN361Ne = NValues(NPerm(Nodenumber))362ELSE363DO i=1, DIM364DO j= 1, DIM365Sig(i,j) = &366StressValues( 2*DIM *(StressPerm(Nodenumber)-1) + Ind(i,j) )367END DO368END DO369! Stress vector Sn370DO i=1, DIM371Sn(i) = SUM(Sig(i,1:DIM)*normal(1:DIM))372END DO373! Normal stress (still Cauchy or deviatoric)374Snn = SUM( Sn(1:DIM) * normal(1:DIM) )375! Isotropic ice pressure376Pice = FlowValues((DIM+1)*FlowPerm(Nodenumber))377378IF (Cauchy) THEN379! At first time Snn = 0 and should be approximated by -pi380IF (ABS(Snn) < 1.0e-10*ABS(Pice)) Snn = -Pice381ELSE382Snn = Snn - Pice383END IF384385! Convention is such that Snn should be negative (compressive)386Ne = -Snn -Pw387ENDIF388389Bdrag = 0.0_dp390IF ( Ne>0 ) THEN391ut = MAX(ut,ut0)392Xi = ut / (As * (C*Ne)**m )393Xi = MIN(Xi,1.0e20_dp)394ELSE395Xi = 1.0e20_dp396WRITE(Message,*) '!!! Ne <=0, nodenumber',nodenumber, Ne397CALL INFO ("Friction_Coulomb", Message, Level=9)398! write(*,*)'!!! Ne <=0, nodenumber',nodenumber, Ne399Ne = 0.0400END IF401402Bdrag = C*Ne * ((Xi * ut**(-m)) / ( 1.0 + a * Xi**q))**(1.0/m)403Bdrag = MIN(Bdrag,1.0e20_dp)404405! Stress may be not known at first time / or first steady iteration406IF ((t==t0).AND.(.Not.ASSOCIATED( NVariable )).AND.(Snn.GE.0.0_dp)) Bdrag = 1.0e20407END FUNCTION Friction_Coulomb408409! Sliding after Budd et al 1984, Annals of Glaciology 5, page 29-36.410!411! Magnitude of sliding is:412!413! tau_b = C.{u_b}^{m}*Zab^{q}414!415! where Zab is height above buoyancy and C, m and q respectively are416! given in the sif by:417! Budd Friction Coefficient = Real 2.412579e-2418! Budd Velocity Exponent = Real $1.0/3.0419! Budd Zab Exponent = Real 2.0420!421! Budd Floatation = Logical False422! If this is set to true then the height above buoyancy will be based423! on the floatation condition instead of inferred from the effective424! pressure (i.e. depth is used instead of normal stress). Default is425! false.426!427! Linearisation for small velocity is used, similar to Weertman428! above:429! Budd Linear Velocity = Real 0.00001430!431! Slip coefficient in Elmer is given as432! C.{u_b}^{m - 1}*Zab^{q}433!434!435! Pre-requisites are as for EffectivePressure below, plus:436! "Budd Ice Density" and "Budd Gravity" need to be defined in the437! relevant (basal) boundary condition, in addition to the four438! parameters above.439!440FUNCTION Sliding_Budd (Model, nodenumber, z) RESULT(Bdrag)441442USE types443USE CoordinateSystems444USE SolverUtils445USE ElementDescription446USE DefUtils447448IMPLICIT NONE449450TYPE(Model_t) :: Model451REAL (KIND=dp) :: z452INTEGER :: nodenumber453454REAL (KIND=dp) :: Bdrag455456REAL (KIND=dp), ALLOCATABLE :: normal(:), velo(:), BuddFrictionCoeff(:)457TYPE(ValueList_t), POINTER :: BC, ParentMaterial458TYPE(Variable_t), POINTER :: NormalVar, FlowVariable, Hvar459TYPE(Element_t), POINTER :: parentElement, BoundaryElement460REAL(KIND=dp), POINTER :: NormalValues(:), FlowValues(:), HValues(:), WeertCoefValues(:)461TYPE(Variable_t), POINTER :: coefVar, WeertCoefVar462REAL(KIND=dp), POINTER :: coefValues(:)463INTEGER, POINTER :: coefPerm(:)464INTEGER, POINTER :: NormalPerm(:), FlowPerm(:), HPerm(:), WeertCoefPerm(:)465INTEGER :: DIM, i, body_id, other_body_id, material_id, elementNbNodes,elementNodeNumber466REAL (KIND=dp) :: m, q, g, rhoi, Zab, Zab_offset, ep, sl, H, rhow467REAL (KIND=dp) :: C, ut, un, ut0, WeertExp, Cw468LOGICAL :: GotIt, FirstTime = .TRUE., SSA = .FALSE., UseFloatation = .FALSE., H_scaling469LOGICAL :: UnFoundFatal=.TRUE., ConvertWeertman470CHARACTER(LEN=MAX_NAME_LEN) :: USF_name, FlowSolverName, CoefName, WeertCoefName, WeertForm471472SAVE :: normal, velo, DIM, SSA, FirstTime, FlowSolverName, UseFloatation473SAVE :: WeertCoefName, WeertExp, WeertForm, ConvertWeertman, BuddFrictionCoeff474475476USF_name = "Sliding_Budd"477478BC => GetBC(Model % CurrentElement)479IF (.NOT.ASSOCIATED(BC))THEN480CALL Fatal(USF_name, 'No BC Found')481END IF482483IF (FirstTime) THEN484FirstTime = .FALSE.485DIM = CoordinateSystemDimension()486IF ((DIM == 2).OR.(DIM == 3)) THEN487ALLOCATE(normal(DIM), velo(DIM))488ELSE489CALL FATAL(USF_name, 'Bad dimension of the problem')490END IF491492ALLOCATE(BuddFrictionCoeff(Model % MaxElementNodes))493494FlowSolverName = GetString( Model % Solver % Values , 'Flow Solver Name', GotIt )495IF (.NOT.Gotit) FlowSolverName = 'Flow Solution'496SELECT CASE (FlowSolverName)497CASE ('ssabasalflow')498SSA = .TRUE.499END SELECT500501WeertCoefName = GetString( BC, 'Budd Conv Weertman coef name', GotIt )502IF (GotIt) THEN503ConvertWeertman = .TRUE.504WeertExp = GetConstReal( BC, 'Budd Conv Weertman exponent', GotIt )505IF (.NOT. GotIt) THEN506CALL FATAL(USF_name, 'Converting coef, need >Budd Conv Weertman exponent<')507END IF508WeertForm = GetString( BC, 'Budd Conv Weertman formulation', GotIt )509IF (.NOT. GotIt) THEN510CALL FATAL(USF_name, 'Converting coef, need >Budd Conv Weertman formulation<')511END IF512ELSE513ConvertWeertman = .FALSE.514END IF515516END IF517518!-----------------------------------------------------------------519! get some information upon active boundary element and its parent520!-----------------------------------------------------------------521BoundaryElement => Model % CurrentElement522elementNbNodes = GetElementNOFNodes(BoundaryElement)523524! get number of node in element525DO elementNodeNumber=1,elementNbNodes526IF (BoundaryElement % NodeIndexes(elementNodeNumber) == nodenumber) EXIT527END DO528529IF ( .NOT. ASSOCIATED(BoundaryElement) ) THEN530CALL FATAL(USF_Name,'No boundary element found')531END IF532other_body_id = BoundaryElement % BoundaryInfo % outbody533IF (other_body_id < 1) THEN ! only one body in calculation534ParentElement => BoundaryElement % BoundaryInfo % Right535IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left536ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards537ParentElement => BoundaryElement % BoundaryInfo % Right538IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left539END IF540! all the above was just so we can get the material properties of the parent element...541body_id = ParentElement % BodyId542material_id = ListGetInteger(Model % Bodies(body_id) % Values, 'Material', GotIt,UnFoundFatal = UnFoundFatal)543ParentMaterial => Model % Materials(material_id) % Values544IF (.NOT. ASSOCIATED(ParentMaterial)) THEN545WRITE(Message,'(A,I10,A,I10)')&546'No material values found for body no ', body_id,&547' under material id ', material_id548CALL FATAL(USF_Name,Message)549END IF550551rhoi = GetConstReal( ParentMaterial, 'Density', GotIt )552IF (.NOT. GotIt) THEN553CALL FATAL(USF_Name, 'Material property Density not found.')554END IF555! rhoi = GetConstReal( BC, 'Budd Ice Density', GotIt )556! IF (.NOT.GotIt) THEN557! CALL FATAL(USF_name, 'Need Ice Density for the Budd sliding law')558! END IF559560!C = GetConstReal( BC, 'Budd Friction Coefficient', GotIt )561562BuddFrictionCoeff(1:elementNbNodes) = &563ListGetReal(BC, 'Budd Friction Coefficient', elementNbNodes, BoundaryElement % Nodeindexes, GotIt)564565IF (.NOT. GotIt) THEN566CALL FATAL(USF_name, 'Need a Friction Coefficient for the Budd sliding law')567END IF568569C = BuddFrictionCoeff(elementNodeNumber)570571m = GetConstReal( BC, 'Budd Velocity Exponent', GotIt )572IF (.NOT. GotIt) THEN573CALL FATAL(USF_name, 'Need a velocity Exponent for the Budd sliding law')574END IF575576q = GetConstReal( BC, 'Budd Zab Exponent', GotIt )577IF (.NOT. GotIt) THEN578CALL FATAL(USF_name, 'Need a Zab Exponent for the Budd sliding law')579END IF580581Zab_offset = GetConstReal( BC, 'Budd Zab Offset', GotIt )582IF (.NOT. GotIt) THEN583Zab_offset = 0.0_dp584END IF585586ut0 = GetConstReal( BC, 'Budd Linear Velocity', GotIt )587IF (.NOT. GotIt) THEN588CALL FATAL(USF_name, 'Need a Linear Velocity for the Budd sliding law')589END IF590591g = GetConstReal( BC, 'Budd Gravity', GotIt )592IF (.NOT. GotIt) THEN593CALL FATAL(USF_name, 'Need Gravity for the Budd sliding law')594END IF595596UseFloatation = GetLogical( BC, 'Budd Floatation', GotIt )597IF (.NOT. GotIt) THEN598CALL FATAL(USF_name, 'Need Floatation for the Budd sliding law')599END IF600601H_scaling = GetLogical( BC, 'Budd Thickness Scaling', GotIt )602IF (.NOT. GotIt) THEN603H_scaling = .FALSE.604END IF605606FlowVariable => VariableGet( Model % Variables, FlowSolverName,UnFoundFatal=UnFoundFatal)607FlowPerm => FlowVariable % Perm608FlowValues => FlowVariable % Values609610IF (.NOT.SSA) THEN611NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)612NormalPerm => NormalVar % Perm613NormalValues => NormalVar % Values614615DO i=1, DIM616normal(i) = -NormalValues(DIM*(NormalPerm(Nodenumber)-1) + i)617velo(i) = FlowValues( (DIM+1)*(FlowPerm(Nodenumber)-1) + i )618END DO619un = SUM(velo(1:DIM)*normal(1:DIM))620ut = SQRT( SUM( (velo(1:DIM)-un*normal(1:DIM))**2.0 ) )621ELSE622DO i=1, DIM-1623velo(i) = FlowValues( (DIM-1)*(FlowPerm(Nodenumber)-1) + i )624END DO625ut = SQRT(SUM( velo(1:DIM-1)**2.0 ))626END IF627628! Zab is height above buoyancy of the upper free surface. This is629! calculated based on the effective pressure at the bed. The630! effective pressure at the bed is calculated as the normal stress631! at the lower boundary minus the External Pressure (which is set in632! the boundary condition section of the sif).633! Alternatively it can be approximated using the floatation condition.634IF (UseFloatation) THEN635636Hvar => VariableGet( Model % Variables, "Depth",UnFoundFatal=UnFoundFatal)637HPerm => Hvar % Perm638HValues => Hvar % Values639H = HValues(HPerm(nodenumber))640641rhow = GetConstReal( BC, 'Budd Ocean Density', GotIt )642IF (.NOT.GotIt) THEN643CALL FATAL(USF_name, 'Need Ocean Density for the Budd sliding law')644END IF645646sl = GetCReal( ParentMaterial, 'Sea level', GotIt )647IF (.NOT.GotIt) THEN648CALL FATAL(USF_Name, 'Material property Sea level not found.')649END IF650651! floatation condition652! (H - Zab) * rhoi = (sl - z) * rhow653! => Zab = H - (sl-z)*rhow/rhoi654IF (z .LT. sl) THEN655Zab = H - (sl-z)*rhow/rhoi656ELSE657Zab = H658END IF659660IF (Zab .LT. 0.0) THEN661Zab = 0.0662END IF663664! this "offset" to the height above buoyancy is intended to provide a non-zero665! basal drag due to contact with the bed, even when effective pressure is zero.666! Physically, this can be seen as a compromise between Elmer's "Weertman"667! implementation and Elmer's "Budd" implementation.668Zab = Zab + Zab_offset669670ELSE671ep = effectivepressure (Model, nodenumber, z)672Zab = - ep / (g * rhoi)673END IF674675ut = MAX(ut,ut0) ! linearize for very low velocities676677IF (H_scaling) THEN678Zab = Zab / H679END IF680681! Convert a Weertman sliding coefficient to a Budd sliding coefficient to682! give the same basal shear stress683IF (ConvertWeertman) THEN684WeertCoefVar => VariableGet( Model % Variables, WeertCoefName, UnFoundFatal=UnFoundFatal)685WeertCoefPerm => WeertCoefVar % Perm686WeertCoefValues => WeertCoefVar % Values687Cw = WeertCoefValues(WeertCoefPerm(Nodenumber))688689SELECT CASE (WeertForm)690CASE ('power')691Cw = 10**Cw692CASE ('beta2')693Cw = Cw**2694CASE ('none')695CASE DEFAULT696CALL FATAL(USF_name, 'Unrecognised >Budd Conv Weertman formulation<')697END SELECT698699IF ( (WeertExp.NE.1.0).OR.(m.NE.1.0) ) THEN700CALL FATAL(USF_name, 'Currently only works for velocity exponents = 1.0')701END IF702703C = Cw / (Zab**q)704705END IF706707Bdrag = C * ut**(m-1.0) * Zab**q708709CONTAINS710711! Effective Pressure is overburden pressure (or, in our case, normal712! stress is more accurate) minus basal water pressure (or "external713! pressure").714!715! Pre-requisites:716! "External Pressure" needs to be defined in the relevant boundary717! condition.718! The "ComputeNormal" and "ComputeDevStressNS" solvers need to be719! active.720FUNCTION EffectivePressure (Model, nodenumber, y) RESULT(ep)721722USE types723USE CoordinateSystems724USE SolverUtils725USE ElementDescription726USE DefUtils727IMPLICIT NONE728729TYPE(Model_t) :: Model730REAL (KIND=dp) :: y , x731INTEGER :: nodenumber732733REAL (KIND=dp) :: ep734735TYPE(ValueList_t), POINTER :: BC, Material736TYPE(Variable_t), POINTER :: TimeVar, StressVariable, NormalVar, FlowVariable737TYPE(Element_t), POINTER :: BoundaryElement, ParentElement738REAL (KIND=dp), POINTER :: StressValues(:), NormalValues(:), FlowValues(:)739INTEGER, POINTER :: StressPerm(:), NormalPerm(:), FlowPerm(:)740INTEGER :: DIM, i, j, n, other_body_id, Ind(3,3)741REAL (KIND=dp) :: Pext742REAL (KIND=dp) :: Snn, ut, un, t743LOGICAL :: GotIt, FirstTime = .TRUE., Cauchy744REAL (KIND=dp), ALLOCATABLE :: Sig(:,:), normal(:), velo(:), Sn(:), AuxReal(:)745CHARACTER(LEN=MAX_NAME_LEN) :: USF_name746747SAVE :: Sig, normal, velo, DIM, Ind, Sn, FirstTime748749USF_name = "EffectivePressure"750751IF (FirstTime) THEN752FirstTime = .FALSE.753DIM = CoordinateSystemDimension()754IF ((DIM == 2).OR.(DIM == 3)) THEN755ALLOCATE(Sig(DIM,DIM),normal(DIM),Sn(DIM))756ELSE757CALL FATAL(USF_name, 'Bad dimension of the problem')758END IF759DO i=1, 3760Ind(i,i) = i761END DO762Ind(1,2) = 4763Ind(2,1) = 4764Ind(2,3) = 5765Ind(3,2) = 5766Ind(3,1) = 6767Ind(1,3) = 6768END IF769770! Check we have a boundary condition...771BoundaryElement => Model % CurrentElement772BC => GetBC(BoundaryElement)773IF (.NOT.ASSOCIATED(BC))THEN774CALL Fatal(USF_name, 'No BC Found')775END IF776777n = GetElementNOFNodes()778ALLOCATE (auxReal(n))779780! Get the external (probably water) pressure781! Use the convention Pext > 0 => Compression782auxReal(1:n) = GetReal( BC, 'External Pressure', GotIt )783DO i=1, n784IF (NodeNumber== BoundaryElement % NodeIndexes( i )) EXIT785END DO786Pext = auxReal(i)787DEALLOCATE(auxReal)788789! Get the variable to compute the normal790NormalVar => VariableGet(Model % Variables,'Normal Vector',UnFoundFatal=UnFoundFatal)791NormalPerm => NormalVar % Perm792NormalValues => NormalVar % Values793794! Get the stress variable795StressVariable => VariableGet( Model % Variables, 'Stress',UnFoundFatal=UnFoundFatal)796StressPerm => StressVariable % Perm797StressValues => StressVariable % Values798799! Cauchy or deviatoric stresses ?800! First, get parent element801other_body_id = BoundaryElement % BoundaryInfo % outbody802IF (other_body_id < 1) THEN ! only one body in calculation803ParentElement => BoundaryElement % BoundaryInfo % Right804IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left805ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards806ParentElement => BoundaryElement % BoundaryInfo % Right807IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left808END IF809Material => GetMaterial(ParentElement)810Cauchy = ListGetLogical( Material , 'Cauchy', Gotit )811812! stress tensor813DO i=1, DIM814DO j= 1, DIM815Sig(i,j) = &816StressValues( 2*DIM *(StressPerm(Nodenumber)-1) + Ind(i,j) )817END DO818IF (.NOT.Cauchy) THEN819Sig(i,i) = Sig(i,i) - FlowValues((DIM+1)*FlowPerm(Nodenumber))820END IF821END DO822823! normal stress824DO i=1, DIM825normal(i) = -NormalValues(DIM*(NormalPerm(Nodenumber)-1) + i)826END DO827DO i=1, DIM828Sn(i) = SUM(Sig(i,1:DIM)*normal(1:DIM))829END DO830Snn = SUM( Sn(1:DIM) * normal(1:DIM) )831832! effective pressure833ep = -Snn -Pext834835END FUNCTION EffectivePressure836837END FUNCTION Sliding_Budd838839840! ******************************************************************************841! *842! * Authors: Rupert Gladstone, Fabien Gillet-Chaulet843! * Email: [email protected]844! * Web:845! *846! * Original Date:847! * 2016/12/06848! *****************************************************************************849!> USF_Sliding.f90, function FreeSlipShelves850!>851!> Sets the basal drag to zero according to a grounded mask. Intended for use852!> when applying inverse methods in the presence of floating ice shelves.853!>854!> For the .sif (bottom boundary):855!> Slip Coefficient 2 = Variable beta856!> Real Procedure "ElmerIceUSF" "FreeSlipShelves"857!> Slip Coefficient 3 = Variable beta858!> Real Procedure "ElmerIceUSF" "FreeSlipShelves"859!> FreeSlipShelves mask name = Name of mask variable to use to set slip coef860!> to zero (default is GroundedMask)861!> FreeSlipShelves beta formulation = Power or Beta2 (same meaning as862!> described in DJDBeta_Adjoint solver)863!>864FUNCTION FreeSlipShelves (Model, nodenumber, BetaIn) RESULT(BetaOut)865866USE DefUtils867868IMPLICIT NONE869870TYPE(Model_t) :: Model871REAL (KIND=dp) :: BetaIn872INTEGER :: nodenumber873874REAL (KIND=dp) :: BetaOut, mask875LOGICAL :: FirstTime = .TRUE., GotIt876877CHARACTER(LEN=MAX_NAME_LEN) :: FunctionName = 'FreeSlipShelves', BetaForm, MaskName878TYPE(ValueList_t), POINTER :: BC => NULL()879TYPE(Variable_t), POINTER :: PointerToMask => NULL()880REAL(KIND=dp), POINTER :: MaskValues(:) => NULL()881INTEGER, POINTER :: MaskPerm(:) => NULL()882883SAVE FirstTime, MaskName, BetaForm884885IF (FirstTime) THEN886887BC => GetBC(Model % CurrentElement)888IF (.NOT.ASSOCIATED(BC))THEN889CALL Fatal(FunctionName, 'No BC Found')890END IF891892MaskName = GetString( BC, 'FreeSlipShelves mask name', GotIt)893IF (.Not.GotIt) THEN894CALL WARN(FunctionName,'Keyword >FreeSlipShelves mask name< not found in boundary condition')895CALL WARN(FunctionName,'Taking default value >GroundedMask<')896WRITE(MaskName,'(A)') 'GroundedMask'897END IF898899BetaForm = GetString( BC, 'FreeSlipShelves beta formulation', GotIt)900IF (.NOT.GotIt) THEN901WRITE(Message,'(A)') 'Need >FreeSlipShelves beta formulation< (e.g. Power or Beta2)'902CALL FATAL(FunctionName,Message)903END IF904905FirstTime = .FALSE.906NULLIFY(BC)907END IF908909! Obtain the value of the mask variable at the current node.910PointerToMask => VariableGet( Model % Variables, MaskName, UnFoundFatal=.TRUE.)911MaskValues => PointerToMask % Values912MaskPerm => PointerToMask % Perm913mask = MaskValues(MaskPerm(nodenumber))914NULLIFY(PointerToMask)915NULLIFY(MaskValues)916NULLIFY(MaskPerm)917918! We assume mask value is zero or higher for grounded ice, and strictly below zero919! for floating ice.920IF (mask.LT.0.0_dp) THEN921BetaOut = 0.0_dp922ELSE923SELECT CASE (BetaForm)924CASE("Power","power")925BetaOut = 10.0_dp**BetaIn926CASE("Beta2","beta2")927BetaOut = BetaIn*BetaIn928CASE DEFAULT929WRITE(Message,'(A)') 'beta formulation not recognised'930CALL FATAL(FunctionName,Message)931END SELECT932END IF933934END FUNCTION FreeSlipShelves935936937