Path: blob/devel/elmerice/Solvers/AdjointSSA/AdjointSSA_GradientSolver.F90
3206 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 Gagliardini25! * Email: [email protected]26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date: 30. April 201029! *30! *****************************************************************************31SUBROUTINE AdjointSSA_GradientSolver_init0(Model,Solver,dt,TransientSimulation )32!------------------------------------------------------------------------------33USE DefUtils34IMPLICIT NONE35!------------------------------------------------------------------------------36TYPE(Solver_t), TARGET :: Solver37TYPE(Model_t) :: Model38REAL(KIND=dp) :: dt39LOGICAL :: TransientSimulation40!------------------------------------------------------------------------------41! Local variables42!------------------------------------------------------------------------------43CHARACTER(LEN=MAX_NAME_LEN) :: Name4445Name = ListGetString( Solver % Values, 'Equation',UnFoundFatal=.TRUE.)46CALL ListAddNewString( Solver % Values,'Variable',&47'-nooutput '//TRIM(Name)//'_var')48CALL ListAddLogical(Solver % Values, 'Optimize Bandwidth',.FALSE.)4950END SUBROUTINE AdjointSSA_GradientSolver_init051! *****************************************************************************52SUBROUTINE AdjointSSA_GradientSolver( Model,Solver,dt,TransientSimulation )53!------------------------------------------------------------------------------54! Compute the Gradient of user defined cost functions with respect to various55! input parameters of the SSA model:56!57!58! OUTPUT is : (OPTIONAL) DJDBeta (gradient wr to slip coeff)59! (OPTIONAL) DJDZs (gradient wr to Zs)60! (OPTIONAL) DJDZb (gradient wr to Zb)61! (OPTIONAL) DJDRho (gradient wr to Mean Density)62! (OPTIONAL) DJDEta (gradient wr to Mean Viscosity)63!64! BE careful: - change of variable (for example slip coeff = 10^alpha) has to65! be taken care by the user in the .sif66! - by default the gradient is reset to 0 here; set "Reset DJD... = Logical False"67! if part of the gradient has already been computed before68!69!70! INPUT PARAMETERS are (in addition to the SSA required INPUTS):71!72! In solver section:73! Flow Solution Name = String (default SSAVelocity)74! Adjoint Solution Name = String (default Adjoint)75!76! Compute DJDBeta = Logical (default False)77! Reset DJDBeta = Logical (default True)78!79! Compute DJDZs = Logical (default False)80! Reset DJDZs = Logical (default True)81!82! Compute DJDZb = Logical (default False)83! Reset DJDZb = Logical (default True)84!85! Compute DJDRho = Logical (default False)86! Reset DJDRho = Logical (default True)87!88! Compute DJDEta = Logical (default False)89! Reset DJDEta = Logical (default True)90!91!92!93!******************************************************************************94!95! ARGUMENTS:96!97! TYPE(Model_t) :: Model,98! INPUT: All model information (mesh, materials, BCs, etc...)99!100! TYPE(Solver_t) :: Solver101! INPUT: Linear & nonlinear equation solver options102!103! REAL(KIND=dp) :: dt,104! INPUT: Timestep size for time dependent simulations105!106! LOGICAL :: TransientSimulation107! INPUT: Steady state or transient simulation108!109!******************************************************************************110USE DefUtils111112IMPLICIT NONE113!------------------------------------------------------------------------------114TYPE(Solver_t) :: Solver115TYPE(Model_t) :: Model116117REAL(KIND=dp) :: dt118LOGICAL :: TransientSimulation119!------------------------------------------------------------------------------120! Local variables121!------------------------------------------------------------------------------122TYPE(Solver_t), POINTER :: DSolver123TYPE(Nodes_t) :: ElementNodes124TYPE(Element_t),POINTER :: CurrentElement, Element, ParentElement, BoundaryElement125TYPE(Matrix_t),POINTER :: StiffMatrix126TYPE(ValueList_t), POINTER :: SolverParams, BodyForce, Material, BC127TYPE(Variable_t), POINTER :: ZsSol, ZbSol, &128VeloSolN,VeloSolD,&129DJDBetaSol,DJDZsSol,DJDZbSol,DJDRhoSol,DJDEtaSol130131LOGICAL :: AllocationsDone = .FALSE., Found, GotIt, CalvingFront132LOGICAL :: Newton133134INTEGER :: i, n, m, t, istat, DIM, p, STDOFs135INTEGER :: NonlinearIter, NewtonIter, iter, other_body_id136137INTEGER, POINTER :: ZsPerm(:), ZbPerm(:), &138VeloNPerm(:),VeloDPerm(:),&139DJDBetaPerm(:),DJDZsPerm(:),DJDZbPerm(:), DJDRhoPerm(:),DJDEtaPerm(:),&140NodeIndexes(:)141142REAL(KIND=dp), POINTER :: ForceVector(:)143REAL(KIND=dp), POINTER :: Zs(:), Zb(:)144REAL(KIND=dp), POINTER :: DJDBeta(:),DJDZs(:),DJDZb(:),DJDRho(:),DJDEta(:),VelocityN(:),VelocityD(:)145146REAL(KIND=dp) :: UNorm, cn, dd, NonlinearTol, NewtonTol, MinSRInv, rhow, sealevel, &147PrevUNorm, relativeChange,minv148149REAL(KIND=dp), ALLOCATABLE :: STIFF(:,:), LOAD(:), FORCE(:), &150NodalGravity(:), NodalViscosity(:), NodalDensity(:), &151NodalZs(:), NodalZb(:), NodalGM(:),NodalBed(:), &152NodalU(:), NodalV(:), NodalBeta(:),LocalLinVelo(:),&153Nodalbetab(:),Nodalzsb(:),Nodalzbb(:),NodalRhob(:),NodalEtab(:),&154NodalEtaDer(:),NodalBetaDer(:)155156INTEGER :: iFriction157REAL(KIND=dp) :: fm158CHARACTER(LEN=MAX_NAME_LEN) :: Friction159CHARACTER(LEN=MAX_NAME_LEN) :: SolverName='AdjointSSA_GradientSolver'160REAL(KIND=dp) :: at, at0161LOGICAL :: SEP ! Sub-element parametrization for Grounding line162INTEGER :: GLnIP ! number of Integ. Points for GL Sub-element parametrization163TYPE(Variable_t), POINTER :: GMSol,BedrockSol164165LOGICAL , SAVE :: ComputeDJDBeta,ComputeDJDZs,ComputeDJDZb,ComputeDJDRho,ComputeDJDEta,Reset166LOGICAL :: HaveBetaDer,HaveEtaDer167CHARACTER(LEN=MAX_NAME_LEN), SAVE :: NeumannSolName,AdjointSolName,SName168INTEGER,SAVE :: SolverInd169170SAVE rhow,sealevel171SAVE STIFF, LOAD, FORCE, AllocationsDone, DIM, SolverName, ElementNodes172SAVE NodalGravity, NodalViscosity, NodalDensity, &173NodalZs, NodalZb, NodalGM,NodalBed, &174NodalU, NodalV, NodeIndexes, NodalBeta,LocalLinVelo, &175Nodalbetab,Nodalzsb,NodalZbb,NodalRhob,NodalEtab,&176NodalEtaDer,NodalBetaDer177SAVE STDOFs178179!------------------------------------------------------------------------------180! Get variables needed for solution181!------------------------------------------------------------------------------182DIM = CoordinateSystemDimension()183184185186187!!!!!!!!!!! get Solver Variables188SolverParams => GetSolverParams()189!--------------------------------------------------------------190!Allocate some permanent storage, this is done first time only:191!--------------------------------------------------------------192IF ( (.NOT. AllocationsDone) .OR. Solver % Mesh % Changed ) THEN193194NeumannSolName = GetString( SolverParams,'Flow Solution Name', Found)195IF(.NOT.Found) THEN196CALL WARN(SolverName,'Keyword >Flow Solution Name< not found in section >Solver<')197CALL WARN(SolverName,'Taking default value >SSAVelocity<')198WRITE(NeumannSolName,'(A)') 'SSAVelocity'199END IF200!! SSA Solution201VeloSolN => VariableGet( Solver % Mesh % Variables, TRIM(NeumannSolName), UnFoundFatal=.TRUE. )202STDOFs = VeloSolN % DOFs203204! Get the Direct solver205DO i=1,Model % NumberOfSolvers206if (TRIM(NeumannSolName) == TRIM(Model % Solvers(i) % Variable % Name)) exit207End do208if (i.eq.(Model % NumberOfSolvers+1)) CALL FATAL(SolverName,'Could not find Flow Solver Equation Name')209SolverInd=i210211AdjointSolName = GetString( SolverParams,'Adjoint Solution Name', Found)212IF(.NOT.Found) THEN213CALL WARN(SolverName,'Keyword >Adjoint Solution Name< not found in section >Solver<')214CALL WARN(SolverName,'Taking default value >Adjoint<')215WRITE(AdjointSolName,'(A)') 'Adjoint'216END IF217ComputeDJDBeta = GetLogical( SolverParams,'Compute DJDBeta', Found)218IF(.NOT.Found) ComputeDJDBeta=.False.219ComputeDJDZs = GetLogical( SolverParams,'Compute DJDZs', Found)220IF(.NOT.Found) ComputeDJDZs=.False.221ComputeDJDZb = GetLogical( SolverParams,'Compute DJDZb', Found)222IF(.NOT.Found) ComputeDJDZb=.False.223ComputeDJDRho = GetLogical( SolverParams,'Compute DJDRho', Found)224IF(.NOT.Found) ComputeDJDRho=.False.225ComputeDJDEta = GetLogical( SolverParams,'Compute DJDEta', Found)226IF(.NOT.Found) ComputeDJDEta=.False.227228229! Get some constants230rhow = ListGetConstReal( Model % Constants, 'Water Density', UnFoundFatal=.TRUE.)231232sealevel = ListGetConstReal( Model % Constants, 'Sea Level', UnFoundFatal=.TRUE. )233234! Allocate235N = Model % MaxElementNodes236M = Model % Mesh % NumberOfNodes237IF (AllocationsDone) DEALLOCATE(FORCE, LOAD, STIFF, NodalGravity, &238NodalViscosity, NodalDensity, &239NodalZb, NodalZs, NodalGM,NodalBed, NodalU, NodalV, &240NodalBeta,LocalLinVelo, Nodalbetab,Nodalzsb,NodalRhob,&241NodalEtab,NodalZbb,&242NodalBetaDer,NodalEtaDer,&243ElementNodes % x, &244ElementNodes % y, ElementNodes % z )245246ALLOCATE( FORCE(STDOFs*N), LOAD(N), STIFF(STDOFs*N,STDOFs*N), &247NodalGravity(N), NodalDensity(N), NodalViscosity(N), &248NodalZb(N), NodalZs(N) , NodalGM(N),NodalBed(N),&249NodalU(N), NodalV(N), NodalBeta(N), LocalLinVelo(N),&250Nodalbetab(N),NodalZsb(N), NodalRhob(N),NodalEtab(N),&251NodalZbb(N),&252NodalBetaDer(N),NodalEtaDer(N),&253ElementNodes % x(N), ElementNodes % y(N), ElementNodes % z(N), &254STAT=istat )255IF ( istat /= 0 ) THEN256CALL Fatal( SolverName, 'Memory allocation error.' )257END IF258259AllocationsDone = .TRUE.260CALL INFO( SolverName, 'Memory allocation done.',Level=1 )261END IF262263! Get Info from Direct Solver Params264DSolver => Model % Solvers(SolverInd)265! Sub - element GL parameterisation266SEP=GetLogical( DSolver % Values, 'Sub-Element GL parameterization',GotIt)267IF (.NOT.GotIt) SEP=.False.268IF (SEP) THEN269GLnIP=ListGetInteger( DSolver % Values, &270'GL integration points number',UnFoundFatal=.TRUE. )271WRITE(Message,'(a,i0,a)') 'Sub-Element GL parameterization using ',GLnIP,' IPs'272CALL INFO(SolverName,TRIM(Message),level=4)273GMSol => VariableGet( Solver % Mesh % Variables, 'GroundedMask',UnFoundFatal=.TRUE. )274BedrockSol => VariableGet( Solver % Mesh % Variables, 'bedrock',UnFoundFatal=.TRUE. )275END IF276277ZbSol => VariableGet( Solver % Mesh % Variables, 'Zb', UnFoundFatal=.TRUE. )278Zb => ZbSol % Values279ZbPerm => ZbSol % Perm280281ZsSol => VariableGet( Solver % Mesh % Variables, 'Zs', UnFoundFatal=.TRUE. )282Zs => ZsSol % Values283ZsPerm => ZsSol % Perm284285!! SSA Solution286VeloSolN => VariableGet( Solver % Mesh % Variables, NeumannSolName, UnFoundFatal=.TRUE. )287VelocityN => VeloSolN % Values288VeloNPerm => VeloSolN % Perm289290!! Adjoint Solution291VeloSolD => VariableGet( Solver % Mesh % Variables, AdjointSolName, UnFoundFatal=.TRUE. )292VelocityD => VeloSolD % Values293VeloDPerm => VeloSolD % Perm294295IF (ComputeDJDBeta) Then296SName = GetString( SolverParams,'DJDBeta Name', Found)297IF(.NOT.Found) THEN298CALL WARN(SolverName,'Keyword >DJDBeta Name< not found in section >Solver<')299CALL WARN(SolverName,'Taking default value >DJDBeta<')300WRITE(SName,'(A)') 'DJDBeta'301CALL ListAddString( SolverParams, 'DJDBeta Name', TRIM(SName))302END IF303DJDBetaSol => VariableGet( Solver % Mesh % Variables, TRIM(SName) ,UnFoundFatal=.TRUE. )304DJDBeta => DJDBetaSol % Values305DJDBetaPerm => DJDBetaSol % Perm306307Reset = GetLogical( SolverParams,'Reset DJDBeta', Found)308if (Reset.OR.(.NOT.Found)) DJDBeta = 0.0309End if310311IF (ComputeDJDZs) Then312DJDZsSol => VariableGet( Solver % Mesh % Variables, 'DJDZs',UnFoundFatal=.TRUE. )313DJDZs => DJDZsSol % Values314DJDZsPerm => DJDZsSol % Perm315316Reset = GetLogical( SolverParams,'Reset DJDZs', Found)317if (Reset.OR.(.NOT.Found)) DJDZs = 0.0318End if319IF (ComputeDJDZb) Then320DJDZbSol => VariableGet( Solver % Mesh % Variables, 'DJDZb', UnFoundFatal=.TRUE. )321DJDZb => DJDZbSol % Values322DJDZbPerm => DJDZbSol % Perm323324Reset = GetLogical( SolverParams,'Reset DJDZb', Found)325if (Reset.OR.(.NOT.Found)) DJDZb = 0.0326End if327328IF (ComputeDJDRho) Then329DJDRhoSol => VariableGet( Solver % Mesh % Variables, 'DJDRho', UnFoundFatal=.TRUE. )330DJDRho => DJDRhoSol % Values331DJDRhoPerm => DJDRhoSol % Perm332333Reset = GetLogical( SolverParams,'Reset DJDRho', Found)334if (Reset.OR.(.NOT.Found)) DJDRho = 0.0335End if336IF (ComputeDJDEta) Then337DJDEtaSol => VariableGet( Solver % Mesh % Variables, 'DJDEta' ,UnFoundFatal=.TRUE.)338DJDEta => DJDEtaSol % Values339DJDEtaPerm => DJDEtaSol % Perm340341Reset = GetLogical( SolverParams,'Reset DJDEta', Found)342if (Reset.OR.(.NOT.Found)) DJDEta = 0.0343END IF344345! bulk assembly346DO t=1,Solver % NumberOfActiveElements347Element => GetActiveElement(t)348IF (ParEnv % myPe .NE. Element % partIndex) CYCLE349n = GetElementNOFNodes(Element)350351NodeIndexes => Element % NodeIndexes352353! set coords of highest occurring dimension to zero (to get correct path element)354!-------------------------------------------------------------------------------355ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)356IF (STDOFs == 1) THEN !1D SSA357ElementNodes % y(1:n) = 0.0_dp358ElementNodes % z(1:n) = 0.0_dp359ELSE IF (STDOFs == 2) THEN !2D SSA360ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)361ElementNodes % z(1:n) = 0.0_dp362ELSE363WRITE(Message,'(a,i1,a)')&364'It is not possible to compute SSA problems with DOFs=',&365STDOFs, ' . Aborting'366CALL Fatal( SolverName, Message)367STOP368END IF369370! Read the gravity in the Body Force Section371BodyForce => GetBodyForce()372NodalGravity = 0.0_dp373IF ( ASSOCIATED( BodyForce ) ) THEN374IF (STDOFs==1) THEN375NodalGravity(1:n) = ListGetReal( &376BodyForce, 'Flow BodyForce 2', n, NodeIndexes, UnFoundFatal=.TRUE.)377ELSE378NodalGravity(1:n) = ListGetReal( &379BodyForce, 'Flow BodyForce 3', n, NodeIndexes, UnFoundFatal=.TRUE.)380END IF381END IF382383! Read the Viscosity eta, density, and exponent m in MMaterial Section384! Same definition as NS Solver in Elmer - n=1/m , A = 1/ (2 eta^n)385Material => GetMaterial(Element)386cn = ListGetConstReal( Material, 'Viscosity Exponent',UnFoundFatal=.TRUE.)387MinSRInv = ListGetConstReal( Material, 'Critical Shear Rate',UnFoundFatal=.TRUE.)388389NodalDensity=0.0_dp390NodalDensity(1:n) = ListGetReal( Material, 'SSA Mean Density',n,NodeIndexes,UnFoundFatal=.TRUE.)391392NodalViscosity=0.0_dp393NodalViscosity(1:n) = ListGetReal( Material, 'SSA Mean Viscosity',n, NodeIndexes,UnFoundFatal=.TRUE.)394NodalEtaDer(1:n) = ListGetReal( Material, 'SSA Mean Viscosity Derivative',n, NodeIndexes,Found=HaveEtaDer)395396Friction = ListGetString(Material, 'SSA Friction Law', UnFoundFatal=.TRUE.)397398SELECT CASE(Friction)399CASE('linear')400iFriction = 1401fm = 1.0_dp402CASE('weertman')403iFriction = 2404CASE DEFAULT405CALL FATAL(SolverName,'Friction should be linear or Weertman')406END SELECT407408409NodalBeta(1:n) = ListGetReal( Material, 'SSA Friction Parameter',n, NodeIndexes,UnFoundFatal=.TRUE.)410NodalBetaDer(1:n) = ListGetReal( Material, 'SSA Friction Parameter Derivative',n, NodeIndexes,Found=HaveBetaDer)411IF (iFriction > 1) THEN412fm = ListGetConstReal( Material, 'SSA Friction Exponent', UnFoundFatal=.TRUE. )413414LocalLinVelo = 0.0_dp415LocalLinVelo(1:n) = ListGetReal(Material, 'SSA Friction Linear Velocity', n, NodeIndexes,UnFoundFatal=.TRUE.)416END IF417418IF (SEP) THEN419NodalGM(1:n)=GMSol%Values(GMSol%Perm(NodeIndexes(1:n)))420NodalBed(1:n)=BedrockSol%Values(BedrockSol%Perm(NodeIndexes(1:n)))421ENDIF422423! Get the Nodal value of Zb and Zs424NodalZb(1:n) = Zb(ZbPerm(NodeIndexes(1:n)))425NodalZs(1:n) = Zs(ZsPerm(NodeIndexes(1:n)))426427! Previous Velocity428NodalU(1:n) = VelocityN(STDOFs*(VeloNPerm(NodeIndexes(1:n))-1)+1)429NodalV = 0.0430IF (STDOFs.EQ.2) NodalV(1:n) = VelocityN(STDOFs*(VeloNPerm(NodeIndexes(1:n))-1)+2)431432CALL LocalMatrixUVSSA ( STIFF, FORCE, Element, n, ElementNodes, NodalGravity, &433NodalDensity, NodalViscosity, NodalEtaDer,HaveEtaDer,NodalZb, NodalZs, &434NodalU, NodalV, NodalBeta,NodalBetaDer,HaveBetaDer,iFriction,fm,LocalLinVelo, cn, &435NodalGM,NodalBed,SEP,GLnIP,sealevel,rhow,&436MinSRInv , STDOFs,&437Nodalbetab,nodalzsb,nodalzbb,nodalrhob,nodaletab)438439IF (ComputeDJDBeta) &440DJDBeta(DJDBetaPerm(NodeIndexes(1:n)))=DJDBeta(DJDBetaPerm(NodeIndexes(1:n)))+Nodalbetab(1:n)441IF (ComputeDJDZs) &442DJDZs(DJDZsPerm(NodeIndexes(1:n)))=DJDZs(DJDZsPerm(NodeIndexes(1:n)))+Nodalzsb(1:n)443IF (ComputeDJDZb) &444DJDZb(DJDZbPerm(NodeIndexes(1:n)))=DJDZb(DJDZbPerm(NodeIndexes(1:n)))+Nodalzbb(1:n)445IF (ComputeDJDRho) &446DJDRho(DJDRhoPerm(NodeIndexes(1:n)))=DJDRho(DJDRhoPerm(NodeIndexes(1:n)))+Nodalrhob(1:n)447IF (ComputeDJDEta) &448DJDEta(DJDEtaPerm(NodeIndexes(1:n)))=DJDEta(DJDEtaPerm(NodeIndexes(1:n)))+Nodaletab(1:n)449450END DO451452!453! Neumann condition454!455DO t=1,GetNOFBoundaryElements()456BoundaryElement => GetBoundaryElement(t)457458459IF ( .NOT. ActiveBoundaryElement(BoundaryElement,Solver) ) CYCLE460IF ( GetElementFamily() == 1 ) CYCLE461462NodeIndexes => BoundaryElement % NodeIndexes463!IF (ParEnv % myPe .NE. BoundaryElement % partIndex) CYCLE464465466n = GetElementNOFNodes(BoundaryElement)467FORCE = 0.0e0468STIFF = 0.0e0469470! set coords of highest occurring dimension to zero (to get correct path element)471!-------------------------------------------------------------------------------472ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)473IF (STDOFs == 1) THEN474ElementNodes % y(1:n) = 0.0_dp475ElementNodes % z(1:n) = 0.0_dp476ELSE IF (STDOFs == 2) THEN477ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)478ElementNodes % z(1:n) = 0.0_dp479ELSE480WRITE(Message,'(a,i1,a)')&481'It is not possible to compute SSA with SSA var DOFs=',&482STDOFs, '. Aborting'483CALL Fatal( SolverName, Message)484STOP485END IF486487BC => GetBC()488IF (.NOT.ASSOCIATED( BC ) ) CYCLE489490! Find the nodes for which 'Calving Front' = True491CalvingFront=.False.492CalvingFront = ListGetLogical( BC, 'Calving Front', GotIt )493IF (CalvingFront) THEN494NodalZs(1:n) = Zs(ZsPerm(NodeIndexes(1:n)))495NodalZb(1:n) = Zb(ZbPerm(NodeIndexes(1:n)))496497! Need to access Parent Element to get Material properties498other_body_id = BoundaryElement % BoundaryInfo % outbody499IF (other_body_id < 1) THEN ! only one body in calculation500ParentElement => BoundaryElement % BoundaryInfo % Right501IF ( .NOT. ASSOCIATED(ParentElement) ) ParentElement => BoundaryElement % BoundaryInfo % Left502ELSE ! we are dealing with a body-body boundary and assume that the normal is pointing outwards503ParentElement => BoundaryElement % BoundaryInfo % Right504IF (ParentElement % BodyId == other_body_id) ParentElement => BoundaryElement % BoundaryInfo % Left505END IF506507! Read Density in the Material Section508Material => GetMaterial(ParentElement)509510NodalDensity=0.0_dp511NodalDensity(1:n) = ListGetReal( Material, 'SSA Mean Density',n, NodeIndexes,UnFoundFatal=.TRUE.)512513! Read the gravity in the Body Force Section514BodyForce => GetBodyForce(ParentElement)515NodalGravity = 0.0_dp516IF ( ASSOCIATED( BodyForce ) ) THEN517IF (STDOFs==1) THEN518NodalGravity(1:n) = ListGetReal( &519BodyForce, 'Flow BodyForce 2', n, NodeIndexes,UnFoundFatal=.TRUE.)520ELSE521NodalGravity(1:n) = ListGetReal( &522BodyForce, 'Flow BodyForce 3', n, NodeIndexes,UnFoundFatal=.TRUE.)523END IF524END IF525526CALL LocalMatrixBCSSA( STIFF, FORCE, BoundaryElement, n, ElementNodes,&527NodalDensity, NodalGravity, NodalZb, NodalZs, rhow, sealevel , &528nodalzsb,nodalzbb,nodalrhob)529530IF (ComputeDJDZs) &531DJDZs(DJDZsPerm(NodeIndexes(1:n)))=DJDZs(DJDZsPerm(NodeIndexes(1:n)))+Nodalzsb(1:n)532IF (ComputeDJDZb) &533DJDZb(DJDZbPerm(NodeIndexes(1:n)))=DJDZb(DJDZbPerm(NodeIndexes(1:n)))+Nodalzbb(1:n)534IF (ComputeDJDRho) &535DJDRho(DJDRhoPerm(NodeIndexes(1:n)))=DJDRho(DJDRhoPerm(NodeIndexes(1:n)))+Nodalrhob(1:n)536END IF537END DO538539RETURN540CONTAINS541542!------------------------------------------------------------------------------543SUBROUTINE LocalMatrixUVSSA( STIFF, FORCE, Element, n, Nodes, gravity, &544Density, Viscosity,NodalEtaDer,HaveEtaDer, LocalZb, LocalZs, LocalU, &545LocalV, LocalBeta,NodalBetaDer,HaveBetaDer,iFriction,fm,LocalLinVelo, cm,&546NodalGM,NodalBed,SEP,GLnIP,sealevel,rhow,&547MinSRInv, STDOFs , &548nodalbetab,nodalzsb,nodalzbb,nodalrhob,nodaletab )549!------------------------------------------------------------------------------550REAL(KIND=dp) :: STIFF(:,:), FORCE(:), gravity(:), Density(:), &551Viscosity(:), LocalZb(:), LocalZs(:), &552LocalU(:), LocalV(:) , LocalBeta(:),LocalLinVelo(:), &553nodalbetab(:),nodalzbb(:),nodalzsb(:),nodalrhob(:),nodaletab(:),&554NodalEtaDer(:),NodalBetaDer(:)555LOGICAL :: HaveEtaDer,HaveBetaDer556INTEGER :: n, cp , STDOFs557INTEGER :: iFriction558REAL(KIND=dp) :: cm,fm559TYPE(Element_t), POINTER :: Element560LOGICAL :: Newton561REAL(KIND=dp) :: NodalGM(:),NodalBed(:)562REAL(KIND=dp) :: sealevel,rhow563LOGICAL :: SEP564INTEGER :: GLnIP565!------------------------------------------------------------------------------566REAL(KIND=dp) :: Basis(n), dBasisdx(n,3), ddBasisddx(n,3,3), detJ567REAL(KIND=dp) :: g, rho, eta, h, dhdx, dhdy , muder, bedrock,Hf568REAL(KIND=dp) :: gradS(2),gradSb(2),Slip, A(2,2), Exx, Eyy, Exy, Ezz, Ee, MinSRInv569REAL(KIND=dp) :: beta,Slip2,Velo(2),LinVelo,ub570REAL(KIND=dp) :: betab,hb,rhob,etab571REAL(KIND=dp) :: Id2572LOGICAL :: Stat, NewtonLin573INTEGER :: i, j, t, p, q574TYPE(GaussIntegrationPoints_t) :: IP575LOGICAL :: PartlyGroundedElement576577TYPE(Nodes_t) :: Nodes578!------------------------------------------------------------------------------579580581nodalbetab = 0.0_dp582nodalzsb = 0.0_dp583nodalzbb = 0.0_dp584nodalrhob = 0.0_dp585nodaletab = 0.0_dp586587IF (SEP) THEN588PartlyGroundedElement=(ANY(NodalGM(1:n).GE.0._dp).AND.ANY(NodalGM(1:n).LT.0._dp))589IF (PartlyGroundedElement) THEN590IP = GaussPoints( Element , np=GLnIP )591ELSE592IP = GaussPoints( Element )593ENDIF594ELSE595IP = GaussPoints( Element )596ENDIF597598DO t=1,IP % n599stat = ElementInfo( Element, Nodes, IP % U(t), IP % V(t), &600IP % W(t), detJ, Basis, dBasisdx, ddBasisddx, .FALSE. )601602! Needed Integration Point value603604g = ABS(SUM( Gravity(1:n) * Basis(1:n) ))605rho = SUM( Density(1:n) * Basis(1:n) )606eta = SUM( Viscosity(1:n) * Basis(1:n) )607gradS = 0._dp608gradS(1) = SUM( LocalZs(1:n) * dBasisdx(1:n,1) )609if (STDOFs == 2) gradS(2) = SUM( LocalZs(1:n) * dBasisdx(1:n,2) )610h = SUM( (LocalZs(1:n)-LocalZb(1:n)) * Basis(1:n) )611beta = SUM( LocalBeta(1:n) * Basis(1:n) )612613!------------------------------------------------------------------------------614! In the non-linear case, effective viscosity615Id2=1.0_dp616IF (cm.NE.1.0_dp) THEN617Exx = SUM(LocalU(1:n)*dBasisdx(1:n,1))618Eyy = 0.0619Exy = 0.0620IF (STDOFs.EQ.2) THEN621Eyy = SUM(LocalV(1:n)*dBasisdx(1:n,2))622Ezz = -Exx - Eyy623Exy = SUM(LocalU(1:n)*dBasisdx(1:n,2))624Exy = 0.5*(Exy + SUM(LocalV(1:n)*dBasisdx(1:n,1)))625Ee = 0.5*(Exx**2.0 + Eyy**2.0 + Ezz**2.0) + Exy**2.0626!Ee = SQRT(Ee)627ELSE628!Ee = ABS(Exx)629Ee = Exx * Exx630END IF631muder = eta * 0.5 * (2**cm) * ((cm-1.0)/2.0) * Ee**((cm-1.0)/2.0 - 1.0)632IF (sqrt(Ee) < MinSRInv) then633Ee = MinSRInv*MinSRInv634muder = 0.0_dp635Endif636Id2 = 0.5 * (2**cm) * Ee**((cm-1.0)/2.0)637END IF638639betab = 0.0640hb = 0.0641rhob = 0.0642etab = 0.0643gradsb = 0.0644645A = 0.0_dp646DO p=1,n647DO q=1,n648A(1,1) = 2.0*dBasisdx(q,1)*dBasisdx(p,1)649IF (STDOFs.EQ.2) THEN650A(1,1) = A(1,1) + 0.5*dBasisdx(q,2)*dBasisdx(p,2)651A(1,2) = dBasisdx(q,2)*dBasisdx(p,1) + &6520.5*dBasisdx(q,1)*dBasisdx(p,2)653A(2,1) = dBasisdx(q,1)*dBasisdx(p,2) + &6540.5*dBasisdx(q,2)*dBasisdx(p,1)655A(2,2) = 2.0*dBasisdx(q,2)*dBasisdx(p,2) +&6560.5*dBasisdx(q,1)*dBasisdx(p,1)657END IF658659DO i=1,STDOFs660betab = betab + Basis(q) * Basis(p) * IP % S(t) * detJ *&661(- VelocityN(STDOFs*(VeloNPerm(NodeIndexes(q))-1)+i) * &662VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i))663664DO j=1,STDOFs665etab = etab + 2.0 * h * Id2 * A(i,j) * IP % S(t) * detJ *&666(- VelocityN(STDOFs*(VeloNPerm(NodeIndexes(q))-1)+j) * &667VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i))668669hb = hb + 2.0 * eta * Id2 * A(i,j) * IP % S(t) * detJ *&670(- VelocityN(STDOFs*(VeloNPerm(NodeIndexes(q))-1)+j) * &671VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i))672END DO !j673END DO !i674675END DO !q676677DO i=1,STDOFs678rhob = rhob - h*g*gradS(i) * IP % s(t) * detJ * Basis(p) *&679VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i)680hb = hb - rho*g*gradS(i) * IP % s(t) * detJ * Basis(p) *&681VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i)682gradsb(i) = gradsb(i) - rho * g * h * IP % s(t) * detJ * Basis(p) *&683VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i)684END DO !i685END DO !p686687IF ((iFriction == 2).AND.(fm==1.0_dp)) iFriction=1688IF (iFriction > 1) THEN689LinVelo = SUM( LocalLinVelo(1:n) * Basis(1:n) )690Velo = 0.0_dp691Velo(1) = SUM(LocalU(1:n) * Basis(1:n))692IF (STDOFs == 2) Velo(2) = SUM(LocalV(1:n) * Basis(1:n))693ub = SQRT(Velo(1)*Velo(1)+Velo(2)*Velo(2))694IF (ub < LinVelo) then695ub = LinVelo696ENDIF697betab = betab * ub**(fm-1.0_dp)698END IF699700IF (SEP) THEN701IF (ALL(NodalGM(1:n).LT.0._dp)) THEN702betab=0._dp703ELSE IF (PartlyGroundedElement) THEN704bedrock = SUM( NodalBed(1:n) * Basis(1:n) )705Hf= rhow * (sealevel-bedrock) / rho706if (h.lt.Hf) betab=0._dp707END IF708END IF709710IF (HaveBetaDer) THEN711nodalbetab(1:n)=nodalbetab(1:n)+betab*Basis(1:n)*NodalBetaDer(1:n)712ELSE713nodalbetab(1:n)=nodalbetab(1:n)+betab*Basis(1:n)714ENDIF715716nodalzbb(1:n)=nodalzbb(1:n)-hb*Basis(1:n)717nodalzsb(1:n)=nodalzsb(1:n)+hb*Basis(1:n)718Do i=1,STDOFS719nodalzsb(1:n)=nodalzsb(1:n)+gradsb(i)*dBasisdx(1:n,i)720End do721nodalrhob(1:n)=nodalrhob(1:n)+rhob*Basis(1:n)722723IF (HaveEtaDer) THEN724nodaletab(1:n)=nodaletab(1:n)+etab*Basis(1:n)*NodalEtaDer(1:n)725ELSE726nodaletab(1:n)=nodaletab(1:n)+etab*Basis(1:n)727ENDIF728729END DO !IP730731!------------------------------------------------------------------------------732END SUBROUTINE LocalMatrixUVSSA733!------------------------------------------------------------------------------734735!------------------------------------------------------------------------------736SUBROUTINE LocalMatrixBCSSA( STIFF, FORCE, Element, n, ENodes, Density, &737Gravity, LocalZb, LocalZs, rhow, &738sealevel,nodalzsb,nodalzbb,nodalrhob)739!------------------------------------------------------------------------------740TYPE(Element_t), POINTER :: Element741TYPE(Nodes_t) :: ENodes742REAL(KIND=dp) :: STIFF(:,:), FORCE(:), density(:), Gravity(:), LocalZb(:),&743LocalZs(:),rhow, sealevel,&744nodalzsb(:),nodalzbb(:),nodalrhob(:)745INTEGER :: n746!------------------------------------------------------------------------------747REAL(KIND=dp) :: Basis(n),dBasisdx(n,3),ddBasisddx(n,3,3), &748DetJ,Normal(3), rhoi, g, alpha, h, h_im,norm749REAL(KIND=dp) :: alphab,zsb,zbb,rhob750LOGICAL :: Stat751INTEGER :: t, i752TYPE(GaussIntegrationPoints_t) :: IP753754!------------------------------------------------------------------------------755nodalzsb=0.0756nodalzbb=0.0757nodalrhob=0.0758759! The front force is a concentrated nodal force in 1D-SSA and760! a force distributed along a line in 2D-SSA761762! 1D-SSA Case : concentrated force at each nodes763IF (STDOFs==1) THEN !1D SSA but should be 2D problem (does elmer work in 1D?)764DO i = 1, n765g = ABS( Gravity(i) )766rhoi = Density(i)767h = LocalZs(i)-LocalZb(i)768h_im=max(0._dp,sealevel-LocalZb(i))769alpha=0.5 * g * (rhoi * h**2.0 - rhow * h_im**2.0)770771alphab=VelocityD(STDOFs*(VeloDPerm(NodeIndexes(i))-1)+1)772nodalzsb(i)=+alphab*2.0*h*rhoi*g*0.5773nodalzbb(i)=-alphab*2.0*h*rhoi*g*0.5774if ((sealevel-LocalZb(i)).GT.0._dp) then775nodalzbb(i)=nodalzbb(i)+alphab*2.0*h_im*rhow*g*0.5776endif777nodalrhob(i)=alphab * 0.5 * g * h**2.0778END DO779780! 2D-SSA Case : force distributed along the line781! This will work in DIM=3D only if working with Extruded Mesh and Preserve782! Baseline as been set to True to keep the 1D-BC783ELSE IF (STDOFs==2) THEN784785IP = GaussPoints( Element )786DO t=1,IP % n787stat = ElementInfo( Element, ENodes, IP % U(t), IP % V(t), &788IP % W(t), detJ, Basis, dBasisdx, ddBasisddx, .FALSE. )789790g = ABS(SUM( Gravity(1:n) * Basis(1:n) ))791rhoi = SUM( Density(1:n) * Basis(1:n) )792h = SUM( (LocalZs(1:n)-LocalZb(1:n)) * Basis(1:n))793h_im = max(0.0_dp , SUM( (sealevel-LocalZb(1:n)) * Basis(1:n)) )794alpha=0.5 * g * (rhoi * h**2.0 - rhow * h_im**2.0)795796! Normal in the (x,y) plane797Normal = NormalVector( Element, ENodes, IP % U(t), IP % V(t), .TRUE.)798norm=SQRT(normal(1)**2.0+normal(2)**2.0)799Normal(1) = Normal(1)/norm800Normal(2) = Normal(2)/norm801802rhob=0._dp803zbb=0.0_dp804zsb=0.0_dp805DO p=1,n806DO i=1,STDOFs807alphab=VelocityD(STDOFs*(VeloDPerm(NodeIndexes(p))-1)+i)*&808Normal(i) * IP % s(t) * detJ * Basis(p)809rhob=rhob+alphab * 0.5 * g * h**2.0810zsb=zsb+alphab*2.0*h*rhoi*g*0.5811zbb=zbb-alphab*2.0*h*rhoi*g*0.5812if (SUM( (sealevel-LocalZb(1:n)) * Basis(1:n)).GT.0.0_dp) Then813zbb=zbb+alphab*2.0*h_im*rhow*g*0.5814endif815END DO !p816END DO !q817818nodalrhob(1:n)=nodalrhob(1:n)+rhob*Basis(1:n)819nodalzsb(1:n)=nodalzsb(1:n)+zsb*Basis(1:n)820nodalzbb(1:n)=nodalzbb(1:n)+zbb*Basis(1:n)821END DO !IP822823ELSE824825CALL FATAL('SSASolver-SSABasalSolver','Do not work for STDOFs <> 1 or 2')826827END IF828!------------------------------------------------------------------------------829END SUBROUTINE LocalMatrixBCSSA830831END SUBROUTINE AdjointSSA_GradientSolver832833834835