Path: blob/devel/elmerice/UserFunctions/USF_SourceCalcCalving.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: Samuel Cook25! * Email: [email protected]26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date:29! * 2018/05/30. Samuel Cook30! *****************************************************************************31!------------------------------------------------------------------------------32!> Works out a total source (meltwater input) term for GlaDS calculations.33!> Uses surface runoff (from RACMO, etc.) and temp residual values from Elmer.34!> Additional keywords needed in Body Force section of SIF:35!>36!> Surface Melt = Logical True or False37!> If True, will look for a surface melt variable to add to source38!>39!> Internal Melt = Logical True or False40!> If True, will calculate melt due to friction heating using residuals41!> from the TemperateIceSolver42!>43!> Surface Melt Variable Name = String "[name of variable]"44!> If Surface Melt = Logical True, the name of the relevant variable to45!> search for surface melt values in needs to be provided. Make sure this46!> variable is defined throughout the vertical extent of the mesh, not47!> just on the surface, or it won't be found48!>49!> Internal Melt Variable Name = String "[name of variable]"50!> The name of the variable in which the residual temperature values are51!> stored, if Internal Melt = Logical True52!>53!------------------------------------------------------------------------------54FUNCTION SourceCalc (Model, NodeNumber, SomeVariable) RESULT(Source)55!------------------------------------------------------------------------------56USE DefUtils57IMPLICIT NONE5859TYPE(Model_t) :: Model60INTEGER :: NodeNumber61REAL(KIND=dp) :: SomeVariable6263!----------------------------------------------------------64TYPE(Element_t), POINTER :: CurrentElement65TYPE(Variable_t), POINTER :: IMVar, SMVar, Weights66TYPE(ValueList_t), POINTER :: BodyForce67INTEGER :: i, HPSolver68REAL(KIND=dp) :: Source, InternalMelt, SurfaceMelt69LOGICAL :: Found, SMLogical, IMLogical, FirstTime=.TRUE., Calving70CHARACTER(LEN=20) :: IMVarName, SMVarName7172SAVE FirstTime, HPSolver, Calving73!------------------------------------------------------------------------74Found = .FALSE.75SMLogical = .FALSE.76IMLogical = .FALSE.7778CurrentElement => Model % CurrentElement79BodyForce => GetBodyForce(CurrentElement)8081!Construct table of element areas and get some mesh parameters.82!Only needed first time function called; subsequently saved83IF (FirstTime) THEN84Calving = GetLogical(Model % Simulation, 'Calving', Found)85IF(.NOT. Found) Calving = .FALSE.86DO i=1, Model % NumberOfSolvers87IF(Model % Solvers(i) % Variable % Name == 'hydraulic potential') THEN88HPSolver = i89EXIT90END IF91END DO9293!Calculate nodal weights for scaling purposes94CALL CalculateNodalWeights(Model % Solvers(HPSolver), .FALSE., VarName='Weights')95FirstTime = .FALSE.96END IF !FirstTime9798!Get internal melt variable - in Elmer, will be the temperature residual99!Name and logical defined in Body Force section of sif100IMLogical = GetLogical(BodyForce,'Internal Melt',Found)101IF(.NOT. Found) CALL Fatal('SourceCalc', "You've not specified if you want internal melt, silly")102IF (IMLogical) THEN103IMVarName = GetString(BodyForce,'Internal Melt Variable Name',Found)104IF(Calving) THEN105IMVar => VariableGet(Model % Solvers(HPSolver) % Mesh % Variables,&106IMVarName, ThisOnly = .TRUE., UnfoundFatal = .TRUE.)107Weights => VariableGet(Model % Solvers(HPSolver) % Mesh % Variables,&108'Weights', ThisOnly = .TRUE., UnfoundFatal = .TRUE.)109ELSE110IMVar => VariableGet(Model % Variables, IMVarName, ThisOnly = .TRUE., UnfoundFatal = .TRUE.)111Weights => VariableGet(Model % Variables, 'Weights', ThisOnly = .TRUE., UnfoundFatal = .TRUE.)112END IF113Found = .FALSE.114END IF115116!Get Surface Melt - Logical and name set in Body Force in sif117!Needs to be surface runoff values in m/year118!Make sure is defined on basal nodes/throughout glacier, rather than just119!surface120SMVarName = GetString(BodyForce,'Surface Melt Variable Name',Found)121SMLogical = GetLogical(BodyForce,'Surface Melt',Found)122IF(.NOT. Found) CALL Fatal('SourceCalc', "You've not defined surface melt, you muppet")123IF (SMLogical) THEN124IF(Calving) THEN125SMVar => VariableGet(Model % Solvers(HPSolver) % Mesh % Variables,&126SMVarName, ThisOnly = .TRUE., UnfoundFatal = .TRUE.)127ELSE128SMVar => VariableGet(Model % Variables, SMVarName, ThisOnly = .TRUE., UnfoundFatal = .TRUE.)129END IF130Found = .FALSE.131END IF132133IF(IMLogical) THEN134!If Temp Residual overall positive, no internal melting135!Temp Res is essentially difference between temperature and upper or lower136!limit137!If temp exceeded upper limit, then is negative; if below lower limit,138!is positive139!Here, should therefore all be negative, unless glacier dropped below140!absolute zero....141IF(IMVar % Values(IMVar % Perm(NodeNumber))>=0.0) THEN142InternalMelt = 0.0143ELSE144!Latent heat of fusion of water is 333.55 J/g, so dividing by that gives145! g of ice melted.146!TempRes in MJ, though (probably), so dividing by 333.55 gives Mg of ice147! melted148!1 Mg is 1 t, which is 1000 kg, so 1000 l, so 1 m3 (all per year), so149!that's it150!Also need to divide by element area to get m151InternalMelt = (ABS(IMVar % Values(IMVar % Perm(NodeNumber)))/Weights % Values(Weights % Perm(NodeNumber)))/333.55152END IF153ELSE154InternalMelt = 0.0155END IF156157IF(SMLogical) THEN158IF(Calving) THEN159IF(SMVar % Values(SMVar % Perm(NodeNumber))>0.0) THEN160SurfaceMelt = SMVar % Values(SMVar % Perm(NodeNumber))161ELSE162SurfaceMelt = 0.0163END IF164ELSE165IF(SMVar % Values(SMVar % Perm(NodeNumber))>0.0) THEN166SurfaceMelt = SMVar % Values(SMVar % Perm(NodeNumber))167ELSE168SurfaceMelt = 0.0169END IF170END IF171ELSE172SurfaceMelt = 0.0173END IF174175!Work out total176Source = InternalMelt + SurfaceMelt177178!------------------------------------------------------------------------------179END FUNCTION SourceCalc180!------------------------------------------------------------------------------181182183