Path: blob/devel/elmerice/Solvers/CalvingHydroInterp.F90
3204 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://www.csc.fi/elmer27! * Address: CSC - Scientific Computing Ltd.28! * Keilaranta 1429! * 02101 Espoo, Finland30! *31! * Original Date: 18 January 201832! *33! *****************************************************************************/34!> Interpolates ice variables necessary for hydrology from ice mesh to hydro35!> mesh as part of combined calving-hydrology simulations.36SUBROUTINE IceToHydroInterp( Model,Solver,Timestep,TransientSimulation )37!******************************************************************************38!39! ARGUMENTS:40!41! TYPE(Model_t) :: Model,42! INPUT: All model information (mesh,materials,BCs,etc...)43!44! TYPE(Solver_t) :: Solver45! INPUT: Linear equation solver options46!47! REAL(KIND=dp) :: Timestep48! INPUT: Timestep size for time dependent simulations49!50!******************************************************************************51USE Differentials52USE MaterialModels53USE DefUtils54USE InterpVarToVar55!------------------------------------------------------------------------------56IMPLICIT NONE57!------------------------------------------------------------------------------58!------------------------------------------------------------------------------59! External variables60!------------------------------------------------------------------------------61TYPE(Model_t) :: Model62TYPE(Solver_t), TARGET :: Solver63LOGICAL :: TransientSimulation64REAL(KIND=dp) :: Timestep65!------------------------------------------------------------------------------66! Local variables67!------------------------------------------------------------------------------68TYPE(Mesh_t), POINTER :: IceMesh, HydroMesh69TYPE(Solver_t), POINTER :: HydroSolver, TempSolver70TYPE(Variable_t), POINTER :: HydroVar=>NULL(),WorkVar=>NULL(),&71InterpVar1=>NULL(),InterpVar2=>NULL(),&72InterpVar3=>NULL(),InterpVar4=>NULL(),&73InterpVar5=>NULL(),WorkVar2=>NULL()74TYPE(Variable_t), TARGET :: InterpVar1Copy, InterpVar2Copy,&75InterpVar3Copy, InterpVar4Copy, InterpVar5Copy76TYPE(ValueList_t), POINTER :: Params, BC77TYPE(Element_t), POINTER :: Element=>NULL()78CHARACTER(MAX_NAME_LEN) :: Variable1, Variable2, Variable3, Variable4,&79Variable5, VarName, iString80LOGICAL :: Found=.FALSE., FirstTime=.TRUE., LoadReaders, Hit=.FALSE.81LOGICAL, POINTER :: BasalLogical(:)82INTEGER, POINTER :: InterpDim(:), IceMeshBasePerm(:)=>NULL(),&83NPP(:)=>NULL(), RefNode(:)=>NULL(), NewPerm1(:),&84ReaderPerm1(:), NewPerm2(:), NewPerm3(:),&85NewPerm4(:), NewPerm5(:), ReaderPerm2(:),&86ReaderPerm3(:), ReaderPerm4(:), ReaderPerm5(:),&87ReaderPerm6(:), ReaderPerm7(:), ReaderPerm8(:),&88ReaderPerm9(:), ReaderPerm10(:)89INTEGER, ALLOCATABLE, TARGET :: DefaultPerm(:), ZeroNodes(:)90INTEGER :: i, j, k, HPSolver, Reader1, Reader2, Reader3,&91Reader4, Reader5, Reader, NumVar, DummyInt, ierr,&92ElementBC, BasalBC, n, NearestNode, SideBC1, SideBC2, HitCount,&93ZeroCounter, TSolver94REAL(KIND=dp), POINTER :: NVP(:)=>NULL(), NewValues1(:), NewValues2(:),&95NewValues3(:), NewValues4(:), NewValues5(:),&96ReaderValues1(:), ReaderValues2(:),&97ReaderValues3(:), ReaderValues4(:),&98ReaderValues5(:), ReaderValues6(:),&99ReaderValues7(:), ReaderValues8(:),&100ReaderValues9(:), ReaderValues10(:)101REAL(KIND=dp) :: IceTempResSum, HydroTempResSum, ScaleFactor,&102ElementTempResSum, Dist, Threshold, MinDist, x, y,&103NewNS, MeanNS104REAL(KIND=dp), ALLOCATABLE :: NSValues(:)105REAL(KIND=dp), ALLOCATABLE, TARGET :: ParITRS(:), ParHTRS(:), NewValues6(:)106SAVE HydroMesh, FirstTime, HPSolver, TSolver107!NewPerm1,&108!NewValues1,NewValues2, NewValues3, NewValues4, NewValues5, DefaultPerm109!------------------------------------------------------------------------------110Params => GetSolverParams()111112!For loading variables that remain constant and are read in from files113!E.g. Zb or surface melting114!Various keywords need to be specified in solver section of SIF115IF(FirstTime) THEN116DO i=1,Model % NumberOfSolvers117IF(Model % Solvers(i) % Variable % Name == 'hydraulic potential') THEN118HPSolver = i119HydroSolver => Model % Solvers(HPSolver)120EXIT121END IF122END DO123DO i=1,Model % NumberOfSolvers124IF(Model % Solvers(i) % Variable % Name == 'temp') THEN125TSolver = i126TempSolver => Model % Solvers(TSolver)127EXIT128END IF129END DO130131LoadReaders = GetLogical(Params,'Load Reader Variables',Found)132IF(.NOT. Found) LoadReaders = .FALSE.133IF(LoadReaders) THEN134NumVar = GetInteger(Params, 'Number Of Variables To Read',Found)135IF(.NOT. Found) CALL Fatal('Ice2Hydro', 'Number of variables to read &136not specified')137IF(NumVar > 10) CALL Info('Ice2Hydro', 'Not set up for more than 10&138reader variables - increase maximum limit in source code', Level=1)139140!A default perm in case the variables to be loaded don't have a perm141!associated. Assumes node 1 = value 1142ALLOCATE(DefaultPerm(HydroSolver % Mesh % NumberOfNodes))143DO i=1, HydroSolver % Mesh % NumberOfNodes144DefaultPerm(i) = i145END DO146147DO i=1, NumVar148iString = STR(i)149Reader = GetInteger(Params, 'Reader Solver '//iString, Found)150IF(Found) THEN151VarName = GetString(Params, 'Reader V'//iString, Found)152IF(.NOT. Found) PRINT *, 'No reader '//iString//' variable specified'153!For the case if you're restarting from a mesh where this variable154!has already been added155WorkVar => VariableGet(HydroSolver % Mesh % Variables,&156VarName, ThisOnly=.TRUE.)157IF(ASSOCIATED(WorkVar)) CYCLE158159WorkVar => VariableGet(Model % Solvers(Reader) % Mesh % Variables,&160VarName, ThisOnly=.TRUE.)161162!Allocate the variable perm to default value if not associated163IF(.NOT. ASSOCIATED(WorkVar % Perm)) THEN164ALLOCATE(WorkVar % Perm(HydroSolver % Mesh % NumberOfNodes))165WorkVar % Perm(1:SIZE(WorkVar % Perm)) = DefaultPerm(1:SIZE(WorkVar % Perm))166END IF167168!There has to be a better way to do this, but you can't use indices169!in variable names, so I can't see a way of allocating the arrays in170!the loop, such that each variable gets its own perm and values171IF(i==1) ALLOCATE(ReaderPerm1(SIZE(WorkVar % Perm)), ReaderValues1(SIZE(WorkVar % Values)))172IF(i==2) ALLOCATE(ReaderPerm2(SIZE(WorkVar % Perm)), ReaderValues2(SIZE(WorkVar % Values)))173IF(i==3) ALLOCATE(ReaderPerm3(SIZE(WorkVar % Perm)), ReaderValues3(SIZE(WorkVar % Values)))174IF(i==4) ALLOCATE(ReaderPerm4(SIZE(WorkVar % Perm)), ReaderValues4(SIZE(WorkVar % Values)))175IF(i==5) ALLOCATE(ReaderPerm5(SIZE(WorkVar % Perm)), ReaderValues5(SIZE(WorkVar % Values)))176IF(i==6) ALLOCATE(ReaderPerm6(SIZE(WorkVar % Perm)), ReaderValues6(SIZE(WorkVar % Values)))177IF(i==7) ALLOCATE(ReaderPerm7(SIZE(WorkVar % Perm)), ReaderValues7(SIZE(WorkVar % Values)))178IF(i==8) ALLOCATE(ReaderPerm8(SIZE(WorkVar % Perm)), ReaderValues8(SIZE(WorkVar % Values)))179IF(i==9) ALLOCATE(ReaderPerm9(SIZE(WorkVar % Perm)), ReaderValues9(SIZE(WorkVar % Values)))180IF(i==10) ALLOCATE(ReaderPerm10(SIZE(WorkVar % Perm)), ReaderValues10(SIZE(WorkVar % Values)))181IF(i==1) THEN182ReaderPerm1 = WorkVar % Perm183ReaderValues1 = WorkVar % Values184CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &185Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues1, &186ReaderPerm1)187ELSEIF(i==2) THEN188ReaderPerm2 = WorkVar % Perm189ReaderValues2 = WorkVar % Values190CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &191Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues2, &192ReaderPerm2)193ELSEIF(i==3) THEN194ReaderPerm3 = WorkVar % Perm195ReaderValues3 = WorkVar % Values196CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &197Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues3, &198ReaderPerm3)199ELSEIF(i==4) THEN200ReaderPerm4 = WorkVar % Perm201ReaderValues4 = WorkVar % Values202CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &203Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues4, &204ReaderPerm4)205ELSEIF(i==5) THEN206ReaderPerm5 = WorkVar % Perm207ReaderValues5 = WorkVar % Values208CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &209Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues5, &210ReaderPerm5)211ELSEIF(i==6) THEN212ReaderPerm6 = WorkVar % Perm213ReaderValues6 = WorkVar % Values214CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &215Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues6, &216ReaderPerm6)217ELSEIF(i==7) THEN218ReaderPerm7 = WorkVar % Perm219ReaderValues7 = WorkVar % Values220CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &221Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues7, &222ReaderPerm7)223ELSEIF(i==8) THEN224ReaderPerm8 = WorkVar % Perm225ReaderValues8 = WorkVar % Values226CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &227Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues8, &228ReaderPerm8)229ELSEIF(i==9) THEN230ReaderPerm9 = WorkVar % Perm231ReaderValues9 = WorkVar % Values232CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &233Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues9, &234ReaderPerm9)235ELSEIF(i==10) THEN236ReaderPerm10 = WorkVar % Perm237ReaderValues10 = WorkVar % Values238CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &239Mesh, Model % Solvers(HPSolver), VarName, 1, ReaderValues10, &240ReaderPerm10)241END IF242243END IF244END DO245246NULLIFY(WorkVar)247248END IF!LoadReaders249END IF!FirstTime250251!To update reader variables each time called. Perhaps not always necessary252!but better safe than sorry253LoadReaders = GetLogical(Params,'Load Reader Variables',Found)254IF(LoadReaders .AND. .NOT. FirstTime) THEN255NumVar = GetInteger(Params, 'Number Of Variables To Read',Found)256IF(.NOT. Found) CALL Fatal('Ice2Hydro', 'Number of variables to read &257not specified')258IF(NumVar > 10) CALL Info('Ice2Hydro', 'Not set up for more than 10&259reader variables - increase maximum limit in source code', Level=1)260DO i=1, NumVar261iString = STR(i)262Reader = GetInteger(Params, 'Reader Solver '//iString, Found)263IF(Found) THEN264VarName = GetString(Params, 'Reader V'//iString, Found)265IF(.NOT. Found) PRINT *, 'No reader '//iString//' variable specified'266WorkVar => VariableGet(Model % Solvers(Reader) % Mesh % Variables,&267VarName, ThisOnly=.TRUE.)268WorkVar2 => VariableGet(Model % Solvers(HPSolver) % Mesh % Variables,&269VarName, ThisOnly=.TRUE.)270WorkVar2 % Values = WorkVar % Values271END IF272END DO273274END IF275276!Time to interpolate variables that are solved on ice mesh277HydroSolver => Model % Solvers(HPSolver)278TempSolver => Model % Solvers(TSolver)279ALLOCATE(InterpDim(1)); InterpDim = (/3/)280ALLOCATE(BasalLogical(Model % Mesh % NumberOfNodes))281ALLOCATE(IceMeshBasePerm(Model % Mesh % NumberOfNodes))282283CALL MakePermUsingMask(Model, Solver, Model % Mesh, "Bottom Surface Mask",&284.FALSE., IceMeshBasePerm, DummyInt)285286!True nodes ignored by InterpolateVarToVarReduced287DO i=1, Model % Mesh % NumberOfNodes288BasalLogical(i) = (IceMeshBasePerm(i) <=0)289END DO290291!Set up list of variables needed by GlaDS that have to be interpolated292InterpVar1 => VariableGet(Model % Mesh % Variables, "normalstress", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)293InterpVar2 => VariableGet(Model % Mesh % Variables, "velocity 1", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)294InterpVar3 => VariableGet(Model % Mesh % Variables, "velocity 2", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)295InterpVar4 => VariableGet(Model % Mesh % Variables, "groundedmask", ThisOnly=.TRUE., UnfoundFatal=.FALSE.)296InterpVar5 => VariableGet(Model % Mesh % Variables, "gmcheck", ThisOnly=.TRUE., UnfoundFatal=.FALSE.)297298!Make copies of the relevant variables to save messing around with the mesh299!variable list - only need perms and values300ALLOCATE(InterpVar1Copy % Values(SIZE(InterpVar1 % Values)), InterpVar1Copy % Perm(SIZE(InterpVar1 % Perm)))301InterpVar1Copy % Values = InterpVar1 % Values302InterpVar1Copy % Perm = InterpVar1 % Perm303InterpVar1Copy % Next => InterpVar2Copy304InterpVar1Copy % Name = InterpVar1 % Name305306ALLOCATE(InterpVar2Copy % Values(SIZE(InterpVar2 % Values)), InterpVar2Copy % Perm(SIZE(InterpVar2 % Perm)))307InterpVar2Copy % Values = InterpVar2 % Values308InterpVar2Copy % Perm = InterpVar2 % Perm309InterpVar2Copy % Next => InterpVar3Copy310InterpVar2Copy % Name = InterpVar2 % Name311312ALLOCATE(InterpVar3Copy % Values(SIZE(InterpVar3 % Values)), InterpVar3Copy % Perm(SIZE(InterpVar3 % Perm)))313InterpVar3Copy % Values = InterpVar3 % Values314InterpVar3Copy % Perm = InterpVar3 % Perm315IF(ASSOCIATED(InterpVar4)) THEN316InterpVar3Copy % Next => InterpVar4Copy317ELSE318InterpVar3Copy % Next => NULL()319END IF320InterpVar3Copy % Name = InterpVar3 % Name321322IF(ASSOCIATED(InterpVar4)) THEN323ALLOCATE(InterpVar4Copy % Values(SIZE(InterpVar4 % Values)), InterpVar4Copy % Perm(SIZE(InterpVar4 % Perm)))324InterpVar4Copy % Values = InterpVar4 % Values325InterpVar4Copy % Perm = InterpVar4 % Perm326IF(ASSOCIATED(InterpVar5)) THEN327InterpVar4Copy % Next => InterpVar5Copy328ELSE329InterpVar4Copy % Next => NULL()330END IF331InterpVar4Copy % Name = InterpVar4 % Name332END IF333334IF(ASSOCIATED(InterpVar5)) THEN335ALLOCATE(InterpVar5Copy % Values(SIZE(InterpVar5 % Values)), InterpVar5Copy % Perm(SIZE(InterpVar5 % Perm)))336InterpVar5Copy % Values = InterpVar5 % Values337InterpVar5Copy % Perm = InterpVar5 % Perm338InterpVar5Copy % Next => NULL()339InterpVar5Copy % Name = InterpVar5 % Name340END IF341342InterpVar1 => InterpVar1Copy343InterpVar2 => InterpVar2Copy344InterpVar3 => InterpVar3Copy345IF(ASSOCIATED(InterpVar4)) InterpVar4 => InterpVar4Copy346IF(ASSOCIATED(InterpVar5)) InterpVar5 => InterpVar5Copy347IF(FirstTime) THEN348FirstTime=.FALSE.349WorkVar => VariableGet(HydroSolver % Mesh % Variables,&350'hydraulic potential', ThisOnly=.TRUE.)351ALLOCATE(NewPerm1(SIZE(WorkVar % Perm)),NewValues1(SIZE(WorkVar % Values)))352ALLOCATE(NewPerm2(SIZE(WorkVar % Perm)),NewValues2(SIZE(WorkVar % Values)))353ALLOCATE(NewPerm3(SIZE(WorkVar % Perm)),NewValues3(SIZE(WorkVar % Values)))354ALLOCATE(NewPerm4(SIZE(WorkVar % Perm)),NewValues4(SIZE(WorkVar % Values)))355ALLOCATE(NewPerm5(SIZE(WorkVar % Perm)),NewValues5(SIZE(WorkVar % Values)))356NewPerm1 = WorkVar % Perm357NewPerm2 = WorkVar % Perm358NewPerm3 = WorkVar % Perm359NewPerm4 = WorkVar % Perm360NewPerm5 = WorkVar % Perm361!NPP => NewPerm1362NewValues1 = 0.0_dp363NewValues2 = 0.0_dp364NewValues3 = 0.0_dp365NewValues4 = 0.0_dp366NewValues5 = 0.0_dp367!NVP => NewValues1368CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &369Mesh, HydroSolver, InterpVar1 % Name, 1,&370NewValues1, NewPerm1)371!NVP => NewValues2372CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &373Mesh, HydroSolver, InterpVar2 % Name, 1,&374NewValues2, NewPerm2)375!NVP => NewValues3376CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &377Mesh, HydroSolver, InterpVar3 % Name, 1,&378NewValues3, NewPerm3)379IF(ASSOCIATED(InterpVar4)) THEN380!NVP => NewValues4381CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &382Mesh, HydroSolver, InterpVar4 % Name, 1,&383NewValues4, NewPerm4)384END IF385IF(ASSOCIATED(InterpVar5)) THEN386!NVP => NewValues5387CALL VariableAdd(HydroSolver % Mesh % Variables, HydroSolver % &388Mesh, HydroSolver, InterpVar5 % Name, 1,&389NewValues5, NewPerm5)390END IF391END IF392393!Have to divide temp residual by ice boundary weights before interpolating.394!I initially did this by creating a new variable and interpolating that, but395!it did some very odd things, such as randomly crashing the plume solver, so396!this just alters the values of temp residual in place, interpolates them,397!and then restores the old values.398WorkVar => VariableGet(Model % Mesh % Variables, 'temp residual', ThisOnly=.TRUE., UnfoundFatal=.TRUE.)399ALLOCATE(NewValues6(SIZE(WorkVar % Values)))400NewValues6 = 0.0_dp401NewValues6 = WorkVar % Values402!CALL CalculateNodalWeights(TempSolver, .TRUE., WorkVar % Perm, 'IceWeights')403WorkVar2 => VariableGet(Model % Mesh % Variables, 'IceWeights', ThisOnly=.TRUE., UnfoundFatal=.TRUE.)404!IF(ParEnv % PEs > 1) CALL ParallelSumVector(TempSolver % Matrix, WorkVar2 % Values)405!DO i=1, Model % Mesh % NumberOfBoundaryElements!SIZE(WorkVar % Perm)406!Element => Model % Mesh % Elements(Model % Mesh % NumberOfBulkElements+i)407!n = GetElementNOFNodes(Element)408!DO j=1, n409!IF(WorkVar2 % Values(WorkVar2 % Perm(Element % NodeIndexes(j)))==0) CYCLE410!WorkVar % Values(WorkVar % Perm(Element % NodeIndexes(j))) =&411!WorkVar % Values(WorkVar % Perm(Element % NodeIndexes(j)))/&412!WorkVar2 % Values(WorkVar2 % Perm(Element % NodeIndexes(j)))413!END DO414!END DO415DO i=1, SIZE(WorkVar % Perm)416IF(WorkVar2 % Values(WorkVar2 % Perm(i)) .NE. 0.0) THEN417WorkVar % Values(WorkVar % Perm(i)) = WorkVar % Values(WorkVar % Perm(i))/WorkVar2 % Values(WorkVar2 % Perm(i))418ELSE419WorkVar % Values(WorkVar % Perm(i)) = 0.0420END IF421END DO422423CALL ParallelActive(.TRUE.)424CALL InterpolateVarToVarReduced(Model % Mesh, HydroSolver % Mesh, 'temp residual',&425InterpDim, OldNodeMask=BasalLogical, Variables=InterpVar1)426CALL MPI_BARRIER(ELMER_COMM_WORLD, ierr)427428!To restore temp residual values on ice mesh429WorkVar % Values = NewValues6430DEALLOCATE(NewValues6)431432!Interpolating GroundedMask will inevitably create values that aren't -1, 0433!or 1, so need to round them to the nearest integer434!Also, enforce grounded on upstream areas to deal with boundary435!interpolation artefacts436IF(ASSOCIATED(InterpVar5)) THEN437WorkVar => VariableGet(HydroSolver % Mesh % Variables, "gmcheck", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)438DO i=1, SIZE(WorkVar % Values)439WorkVar % Values(i) = ANINT(WorkVar % Values(i))440END DO441END IF442IF(ASSOCIATED(InterpVar4)) THEN443WorkVar => VariableGet(HydroSolver % Mesh % Variables, "groundedmask", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)444DO i=1, SIZE(WorkVar % Values)445WorkVar % Values(i) = ANINT(WorkVar % Values(i))446END DO447448RefNode => ListGetIntegerArray(Params, 'Reference Node', Found)449IF(Found) THEN450Threshold = GetConstReal(Params, 'Threshold Distance', Found)451IF(.NOT. Found) Threshold = 10000.0452453DO i=1, SIZE(WorkVar % Perm)454Dist = (HydroSolver % Mesh % Nodes % x(WorkVar % Perm(i)) -&455RefNode(1))**2456Dist = Dist + (HydroSolver % Mesh % Nodes % y(WorkVar % Perm(i)) -&457RefNode(2))**2458Dist = SQRT(Dist)459IF(Dist > Threshold) WorkVar % Values(WorkVar % Perm(i)) = 1.0460END DO461END IF462463Hit = .FALSE.464SideBC1 = 0465SideBC2 = 0466HitCount = 0467DO i=1, Model % NumberOfBCs468BC => Model % BCs(i) % Values469Hit = ListGetLogical(BC, "Side", Found)470IF(Hit) THEN471IF(HitCount == 0) THEN472SideBC1 = i473ELSEIF(HitCount == 1) THEN474SideBC2 = i475ELSE476CALL Info('CalvingHydroInterp', 'You appear to have more than two&477lateral boundaries. Are you sure about this?')478END IF479Hit = .FALSE.480HitCount = HitCount+1481IF(HitCount == 2) EXIT482END IF483END DO484485DO i=1, HydroSolver % Mesh % NumberOfBoundaryElements486Element => GetBoundaryElement(i, HydroSolver)487ElementBC = GetBCId(Element)488IF(ElementBC == SideBC1 .OR. ElementBC == SideBC2) THEN489n = GetElementNOFNodes(Element)490DO j=1,n491IF(WorkVar % Values(WorkVar % Perm(Element % NodeIndexes(j))) == -1.0) THEN492WorkVar % Values(WorkVar % Perm(Element % NodeIndexes(j))) = 1.0493END IF494END DO495END IF496END DO497END IF498499!This is to remove boundary artefacts in normalstress, which, otherwise,500!really mess the hydrology up. Artefacts do exist in velocity and temp501!residual, but have much less impact502!Routine will search for nearest node that has a non-zero value of503!normalstress and substitute that value for the erroneous zero value.504!Ideally, should interpolate from nearest non-zero nodes, but not worth the505!extra faff for a minimal gain506507!This first section is due to SolveLinearSystem invalidating the508!Force2Stress variable (i.e. normalstress) on the hydro mesh. Not really509!sure why it does this, but this fix seems to work without any knock-on510!effects.511WorkVar2 => HydroSolver % Mesh % Variables512DO WHILE (ASSOCIATED(WorkVar2))513IF (TRIM(WorkVar2 % Name) == 'normalstress') THEN514IF (.NOT. WorkVar2 % Valid) THEN515WorkVar2 % Valid = .TRUE.516WorkVar2 % PrimaryMesh => HydroSolver % Mesh517END IF518EXIT519END IF520WorkVar2 => WorkVar2 % Next521END DO522523WorkVar2 => VariableGet(HydroSolver % Mesh % Variables, "normalstress", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)524MeanNS = 0.0_dp525!ZeroCounter = 0526527!DO i=1, HydroSolver % Mesh % NumberOfBoundaryElements528! Element => GetBoundaryElement(i, HydroSolver)529! n = GetElementNOFNodes(Element)530! IF(ANY(WorkVar % Values(WorkVar % Perm(Element % NodeIndexes(1:n))) == -1.0)) CYCLE531! DO j=1,n532! MeanNS = MeanNS+WorkVar2 % Values(WorkVar2 % Perm(Element %&533! NodeIndexes(j)))534! IF(WorkVar2 % Values(WorkVar2 % Perm(Element % NodeIndexes(j)))==0.0)&535! THEN536! ZeroCounter = ZeroCounter + 1537! END IF538! END DO539!END DO540!MeanNS = MeanNS/(HydroSolver % Mesh % NumberOfBoundaryElements-ZeroCounter)541542DO i=1, HydroSolver % Mesh % NumberOfBoundaryElements543Element => GetBoundaryElement(i, HydroSolver)544n = GetElementNOFNodes(Element)545IF(ANY(WorkVar % Values(WorkVar % Perm(Element % NodeIndexes(1:n))) == -1.0)) CYCLE546ALLOCATE(NSValues(n))547DO j=1,n548NSValues(j) = WorkVar2 % Values(WorkVar2 % Perm(Element % NodeIndexes(j)))549END DO550ZeroCounter = 0551DO j=1,n552IF(NSValues(j) .NE. 0.0) CYCLE553ZeroCounter = ZeroCounter + 1554END DO555!This will currently only work for elements with 2 or 3 nodes556SELECT CASE (n-ZeroCounter)557CASE (0)558CALL Info('CalvingHydroInterp', 'No non-0 values of NormalStress. &559Making a guess')560NewNS = (SUM(WorkVar2 % Values)/SIZE(WorkVar2 % Values))+3.0_dp !MeanNS561CASE (1)562NewNS = SUM(NSValues)563CASE (2)564NewNS = SUM(NSValues)/2565CASE DEFAULT566CALL Info('CalvingHydroInterp', 'No NormalStress correction possible')567PRINT *, 'Diagnostics: ',n,ZeroCounter,Element % NodeIndexes568END SELECT569DO j=1,n570IF(NSValues(j) .NE. 0.0) CYCLE571WorkVar2 % Values(WorkVar2 % Perm(Element % NodeIndexes(j))) = NewNS572END DO573DEALLOCATE(NSValues)574END DO575576!Finally, the area of the hydromesh beyond the calving front has to be577!forced to be ungrounded, so interpolation artefacts there have to be578!cleared away. The main job is done by InterpVarToVar, but there are always579!a few places where it messes up, which are corrected here.580DO i=1, HydroSolver % Mesh % NumberOfBulkElements581Element => HydroSolver % Mesh % Elements(i)582n = GetElementNOFNodes(Element)583DO j=1, n584IF(WorkVar2 % Values(WorkVar2 % Perm(Element % NodeIndexes(j))) == 0.0) THEN585WorkVar % Values(WorkVar % Perm(Element % NodeIndexes(j))) = -1.0586END IF587588END DO589END DO590591!Temp residual needs to be conserved. Here, just integrate across all592!elements and compare totals, then scale values on hydromesh uniformly to593!bring in line with ice mesh594WorkVar => VariableGet(Model % Mesh % Variables, "temp residual", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)595596IceTempResSum = 0.0_dp597IceTempResSum = SUM(WorkVar % Values)598599!WorkVar => VariableGet(HydroSolver % Mesh % Variables, "hydraulic potential", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)600WorkVar => VariableGet(HydroSolver % Mesh % Variables, "temp residual", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)601!WorkVar => VariableGet(HydroSolver % Mesh % Variables, "WeightedTR", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)602!CALL CalculateNodalWeights(HydroSolver, .FALSE., WorkVar % Perm, 'HydroWeights')603!WorkVar => VariableGet(HydroSolver % Mesh % Variables, "temp residual", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)604WorkVar2 => VariableGet(HydroSolver % Mesh % Variables, "HydroWeights", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)605!IF(ParEnv % PEs > 1) CALL ParallelSumVector(HydroSolver % Matrix, WorkVar2 % Values)606DO i=1,SIZE(WorkVar % Perm)607!Element => HydroSolver % Mesh % Elements(i)608!n = GetElementNOFNodes(Element)609!DO j=1, n610!WorkVar % Values(WorkVar % Perm(Element % NodeIndexes(j))) =&611!WorkVar % Values(WorkVar % Perm(Element % NodeIndexes(j)))*&612!WorkVar2 % Values(WorkVar2 % Perm(Element % NodeIndexes(j)))613!END DO614WorkVar % Values(WorkVar % Perm(i)) =&615WorkVar % Values(WorkVar % Perm(i))*WorkVar2 % Values(WorkVar2 % Perm(i))616END DO617HydroTempResSum = 0.0_dp618HydroTempResSum = SUM(WorkVar % Values)619620ALLOCATE(ParITRS(ParEnv % PEs), ParHTRS(ParEnv % PEs))621ParITRS = 0.0_dp622ParHTRS = 0.0_dp623624IF(ParEnv % PEs > 1) THEN625CALL MPI_BARRIER(ELMER_COMM_WORLD, ierr)626CALL MPI_Gather(IceTempResSum, 1, MPI_DOUBLE_PRECISION, ParITRS, 1, MPI_DOUBLE_PRECISION, 0, ELMER_COMM_WORLD, ierr)627CALL MPI_Gather(HydroTempResSum, 1, MPI_DOUBLE_PRECISION, ParHTRS, 1, MPI_DOUBLE_PRECISION, 0, ELMER_COMM_WORLD, ierr)628IF(ParEnv % myPE == 0) THEN629IF(ANINT(SUM(ParITRS)) .NE. ANINT(SUM(ParHTRS))) THEN630ScaleFactor = SUM(ParITRS)/SUM(ParHTRS)631END IF632END IF633CALL MPI_BARRIER(ELMER_COMM_WORLD, ierr)634CALL MPI_Bcast(ScaleFactor, 1, MPI_DOUBLE_PRECISION, 0, ELMER_COMM_WORLD, ierr)635DO i=1, SIZE(WorkVar % Values)636WorkVar % Values(i) = WorkVar % Values(i)*ScaleFactor637END DO638ELSE639IF(ANINT(IceTempResSum) .NE. ANINT(HydroTempResSum)) THEN640ScaleFactor = IceTempResSum/HydroTempResSum641DO i=1, SIZE(WorkVar % Values)642WorkVar % Values(i) = WorkVar % Values(i)*ScaleFactor643END DO644END IF645END IF646647DEALLOCATE(InterpDim, BasalLogical, IceMeshBasePerm, ParITRS, ParHTRS)648DEALLOCATE(InterpVar1Copy % Values, InterpVar2Copy % Values, InterpVar3Copy % Values)649DEALLOCATE(InterpVar1Copy % Perm, InterpVar2Copy % Perm, InterpVar3Copy % Perm)650IF(ASSOCIATED(InterpVar4)) DEALLOCATE(InterpVar4Copy % Values, InterpVar4Copy % Perm)651IF(ASSOCIATED(InterpVar5)) DEALLOCATE(InterpVar5Copy % Values, InterpVar5Copy % Perm)652NULLIFY(InterpVar1, InterpVar2, InterpVar3, InterpVar4, InterpVar5,&653WorkVar, HydroSolver, NVP, NPP, BC, Element, RefNode, WorkVar2,&654TempSolver)655!-------------------------------------------------------------------------------656CONTAINS657!-------------------------------------------------------------------------------658CHARACTER(len=20) FUNCTION STR(k)659!Converts and integer to a string660INTEGER, INTENT(IN) :: k661WRITE (STR, *) k662STR = adjustl(STR)663END FUNCTION STR664!-------------------------------------------------------------------------------665END SUBROUTINE666667! *****************************************************************************/668!> Interpolates hydrology variables necessary for calving from hydro mesh to ice669!> mesh as part of combined calving-hydrology simulations.670SUBROUTINE HydroToIceInterp( Model,Solver,Timestep,TransientSimulation )671!******************************************************************************672!673! ARGUMENTS:674!675! TYPE(Model_t) :: Model,676! INPUT: All model information (mesh,materials,BCs,etc...)677!678! TYPE(Solver_t) :: Solver679! INPUT: Linear equation solver options680!681! REAL(KIND=dp) :: Timestep682! INPUT: Timestep size for time dependent simulations683!684!******************************************************************************685USE Differentials686USE MaterialModels687USE DefUtils688USE InterpVarToVar689!------------------------------------------------------------------------------690IMPLICIT NONE691!------------------------------------------------------------------------------692!------------------------------------------------------------------------------693! External variables694!------------------------------------------------------------------------------695TYPE(Model_t) :: Model696TYPE(Solver_t), TARGET :: Solver697LOGICAL :: TransientSimulation698REAL(KIND=dp) :: Timestep699!------------------------------------------------------------------------------700! Local variables701!------------------------------------------------------------------------------702TYPE(Mesh_t), POINTER :: IceMesh, HydroMesh703TYPE(Solver_t), POINTER :: HydroSolver704TYPE(Variable_t), POINTER :: WorkVar=>NULL(), InterpVar1=>NULL(),&705InterpVar2=>NULL(), InterpVar3=>NULL()706TYPE(Variable_t), TARGET :: InterpVar1Copy, InterpVar2Copy, InterpVar3Copy707TYPE(ValueList_t), POINTER :: Params708LOGICAL :: FirstTime=.TRUE.709LOGICAL, POINTER :: BasalLogical(:)710INTEGER, POINTER :: InterpDim(:), IceMeshBasePerm(:)=>NULL(),&711NPP(:)=>NULL(), NewPerm1(:)712INTEGER, ALLOCATABLE, TARGET :: NewPerm2(:), NewPerm3(:)713INTEGER :: i, HPSolver, DummyInt, ierr714REAL(KIND=dp), POINTER :: NVP(:)=>NULL(), NewValues1(:)715REAL(KIND=dp), ALLOCATABLE, TARGET :: NewValues2(:),&716NewValues3(:)717SAVE HydroMesh, FirstTime, HPSolver! NewPerm1,&718!NewValues1, NewPerm2, NewValues2, NewPerm3, NewValues3719720!------------------------------------------------------------------------------721722Params => GetSolverParams()723724!For finding main hydrology solver so know where to interpolate from.725IF(FirstTime) THEN726DO i=1,Model % NumberOfSolvers727IF(Model % Solvers(i) % Variable % Name == 'hydraulic potential') THEN728HPSolver = i729EXIT730END IF731END DO732END IF!FirstTime733734!Time to interpolate variables that are solved on ice mesh735HydroSolver => Model % Solvers(HPSolver)736ALLOCATE(InterpDim(1)); InterpDim = (/3/)737ALLOCATE(BasalLogical(Model % Mesh % NumberOfNodes))738ALLOCATE(IceMeshBasePerm(Model % Mesh % NumberOfNodes))739740CALL MakePermUsingMask(Model, Solver, Model % Mesh, "Bottom Surface Mask",&741.FALSE., IceMeshBasePerm, DummyInt)742743!True nodes ignored by InterpolateVarToVarReduced744DO i=1, Model % Mesh % NumberOfNodes745BasalLogical(i) = (IceMeshBasePerm(i) <=0)746END DO747748!Set up list of variables needed by GlaDS that have to be interpolated749InterpVar1 => VariableGet(HydroSolver % Mesh % Variables, "water pressure", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)750!InterpVar2 => VariableGet(HydroSolver % Mesh % Variables, "sheet discharge 1", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)751!InterpVar3 => VariableGet(HydroSolver % Mesh % Variables, "sheet discharge 2", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)752753!Make copies of the relevant variables to save messing around with the mesh754!variable list - only need perms and values755ALLOCATE(InterpVar1Copy % Values(SIZE(InterpVar1 % Values)), InterpVar1Copy % Perm(SIZE(InterpVar1 % Perm)))756InterpVar1Copy % Values = InterpVar1 % Values757InterpVar1Copy % Perm = InterpVar1 % Perm758InterpVar1Copy % Next => NULL() !InterpVar2Copy759InterpVar1Copy % Name = InterpVar1 % Name760761!ALLOCATE(InterpVar2Copy % Values(SIZE(InterpVar2 % Values)), InterpVar2Copy % Perm(SIZE(InterpVar2 % Perm)))762!InterpVar2Copy % Values = InterpVar2 % Values763!InterpVar2Copy % Perm = InterpVar2 % Perm764!InterpVar2Copy % Next => InterpVar3Copy765!InterpVar2Copy % Name = InterpVar2 % Name766767!ALLOCATE(InterpVar3Copy % Values(SIZE(InterpVar3 % Values)), InterpVar3Copy % Perm(SIZE(InterpVar3 % Perm)))768!InterpVar3Copy % Values = InterpVar3 % Values769!InterpVar3Copy % Perm = InterpVar3 % Perm770!InterpVar3Copy % Next => NULL()771!InterpVar3Copy % Name = InterpVar3 % Name772773InterpVar1 => InterpVar1Copy774!InterpVar2 => InterpVar2Copy775!InterpVar3 => InterpVar3Copy776777!Variables need to be added to mesh before interpolated as list778IF(FirstTime) THEN779FirstTime = .FALSE.780WorkVar => VariableGet(Model % Mesh % Variables,&781'velocity 1', ThisOnly=.TRUE.)782ALLOCATE(NewPerm1(SIZE(WorkVar % Perm)),NewValues1(SIZE(WorkVar % Values)))783!ALLOCATE(NewPerm2(SIZE(WorkVar % Perm)),NewValues2(SIZE(WorkVar % Values)))784!ALLOCATE(NewPerm3(SIZE(WorkVar % Perm)),NewValues3(SIZE(WorkVar % Values)))785NewPerm1 = WorkVar % Perm786!NewPerm2 = NewPerm1787!NewPerm3 = NewPerm1788!NPP => NewPerm1789NewValues1 = 0.0_dp790!NewValues2 = 0.0_dp791!NewValues3 = 0.0_dp792!NVP => NewValues1793CALL VariableAdd(Model % Mesh % Variables, Model % &794Mesh, CurrentModel % Solver, InterpVar1 % Name, 1,&795NewValues1, NewPerm1)796!NPP => NewPerm2797!NVP => NewValues2798!CALL VariableAdd(Model % Mesh % Variables, Model % &799! Mesh, CurrentModel % Solver, InterpVar2 % Name, 1,&800! NVP, NPP)801!NPP => NewPerm3802!NVP => NewValues3803!CALL VariableAdd(Model % Mesh % Variables, Model % &804! Mesh, CurrentModel % Solver, InterpVar3 % Name, 1,&805! NVP, NPP)806END IF807808CALL ParallelActive(.TRUE.)809CALL InterpolateVarToVarReduced(HydroSolver % Mesh, Model % Mesh,&810'effective pressure', InterpDim, NewNodeMask=BasalLogical,&811Variables=InterpVar1)812CALL MPI_BARRIER(ELMER_COMM_WORLD, ierr)813CALL ParallelActive(.FALSE.)814815DEALLOCATE(InterpDim, BasalLogical, IceMeshBasePerm, InterpVar1Copy % Perm,&816InterpVar1Copy % Values)!, InterpVar2Copy % Perm,&817!InterpVar2Copy % Values, InterpVar3Copy % Perm,&818!InterpVar3Copy % Values)819NULLIFY(HydroSolver, WorkVar, NVP, NPP, InterpVar1)!, InterpVar2, InterpVar3)820821END SUBROUTINE822! *****************************************************************************/823!> Works out weights on hydro mesh at beginning of simulation824SUBROUTINE HydroWeightsSolver( Model,Solver,Timestep,TransientSimulation )825!******************************************************************************826!827! ARGUMENTS:828!829! TYPE(Model_t) :: Model,830! INPUT: All model information (mesh,materials,BCs,etc...)831!832! TYPE(Solver_t) :: Solver833! INPUT: Linear equation solver options834!835! REAL(KIND=dp) :: Timestep836! INPUT: Timestep size for time dependent simulations837!838!******************************************************************************839USE Differentials840USE MaterialModels841USE DefUtils842USE InterpVarToVar843!------------------------------------------------------------------------------844IMPLICIT NONE845!------------------------------------------------------------------------------846!------------------------------------------------------------------------------847! External variables848!------------------------------------------------------------------------------849TYPE(Model_t) :: Model850TYPE(Solver_t), TARGET :: Solver851LOGICAL :: TransientSimulation852REAL(KIND=dp) :: Timestep853!------------------------------------------------------------------------------854! Local variables855!------------------------------------------------------------------------------856TYPE(Variable_t), POINTER :: WorkVar857!------------------------------------------------------------------------------858CALL CalculateNodalWeights(Solver, .FALSE.,VarName='HydroWeights')859WorkVar => VariableGet(Solver % Mesh % Variables, "HydroWeights", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)860IF(ParEnv % PEs > 1) CALL ParallelSumVector(Solver % Matrix, WorkVar % Values)861NULLIFY(WorkVar)862END SUBROUTINE863! *****************************************************************************/864!> Works out weights on ice mesh865SUBROUTINE IceWeightsSolver( Model,Solver,Timestep,TransientSimulation )866!******************************************************************************867!868! ARGUMENTS:869!870! TYPE(Model_t) :: Model,871! INPUT: All model information (mesh,materials,BCs,etc...)872!873! TYPE(Solver_t) :: Solver874! INPUT: Linear equation solver options875!876! REAL(KIND=dp) :: Timestep877! INPUT: Timestep size for time dependent simulations878!879!******************************************************************************880USE Differentials881USE MaterialModels882USE DefUtils883USE InterpVarToVar884!------------------------------------------------------------------------------885IMPLICIT NONE886!------------------------------------------------------------------------------887!------------------------------------------------------------------------------888! External variables889!------------------------------------------------------------------------------890TYPE(Model_t) :: Model891TYPE(Solver_t), TARGET :: Solver892LOGICAL :: TransientSimulation893REAL(KIND=dp) :: Timestep894!------------------------------------------------------------------------------895! Local variables896!------------------------------------------------------------------------------897TYPE(Variable_t), POINTER :: WorkVar898!------------------------------------------------------------------------------899CALL CalculateNodalWeights(Solver, .TRUE.,VarName='IceWeights')900WorkVar => VariableGet(Solver % Mesh % Variables, "IceWeights", ThisOnly=.TRUE., UnfoundFatal=.TRUE.)901IF(ParEnv % PEs > 1) CALL ParallelSumVector(Solver % Matrix, WorkVar % Values)902NULLIFY(WorkVar)903END SUBROUTINE904905906