Path: blob/devel/elmerice/Solvers/AdjointThickness/AdjointThickness_ThicknessSolver.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: F. Gillet-Chaulet25! * Web: http://elmerice.elmerfem.org26! *27! * Original Date: Dec. 202028! *29! *****************************************************************************30!-----------------------------------------------------------------------------31SUBROUTINE AdjointThickness_ThicknessSolver( Model,Solver,dt,TransientSimulation )32USE DefUtils33IMPLICIT NONE34!------------------------------------------------------------------------------35! external variables36!------------------------------------------------------------------------------37TYPE(Model_t) :: Model38TYPE(Solver_t):: Solver39REAL(KIND=dp) :: dt40LOGICAL :: TransientSimulation41!------------------------------------------------------------------------------42! Local variables43!------------------------------------------------------------------------------44TYPE(ValueList_t), POINTER :: BodyForce, SolverParams4546INTEGER :: NMAX,NSDOFs47INTEGER :: istat48INTEGER :: t,i,j,n49LOGICAL :: ConvectionVar, Found5051REAL(KIND=dp) :: Norm5253CHARACTER(LEN=MAX_NAME_LEN) :: FlowSolName54TYPE(Variable_t), POINTER :: FlowSol55REAL(KIND=dp), POINTER :: FlowSolution(:)56INTEGER, POINTER :: FlowPerm(:)5758REAL(KIND=dp), ALLOCATABLE,SAVE :: STIFF(:,:),FORCE(:),LOAD(:),Velo(:,:)5960CHARACTER(LEN=MAX_NAME_LEN) :: SolverName= 'AdjointThickness_ThicknessSolver'6162TYPE(Nodes_t),SAVE :: ElementNodes63TYPE(Element_t),POINTER :: CurrentElement64INTEGER, POINTER :: NodeIndexes(:)6566LOGICAL, SAVE :: AllocationsDone = .FALSE.6768!------------------------------------------------------------------------------69! Go70!------------------------------------------------------------------------------71SolverParams => GetSolverParams()7273!------------------------------------------------------------------------------74! check incompatibilities75!------------------------------------------------------------------------------76IF ( CurrentCoordinateSystem() /= Cartesian ) THEN77CALL FATAL(SolverName,'sorry only for cartesian coordinate system')78END IF79IF (TransientSimulation) THEN80CALL FATAL(SolverName,'sorry works only in steady state')81ENDIF8283!------------------------------------------------------------------------------84! Allocate some permanent storage, this is done first time only85!------------------------------------------------------------------------------86IF ( .NOT. AllocationsDone .OR. Solver % Mesh % Changed) THEN87NMAX = Model % MaxElementNodes8889IF ( AllocationsDone ) THEN90DEALLOCATE( ElementNodes % x, &91ElementNodes % y, &92ElementNodes % z, &93FORCE, &94STIFF, &95LOAD,&96Velo)97END IF9899ALLOCATE( ElementNodes % x( NMAX ), &100ElementNodes % y( NMAX ), &101ElementNodes % z( NMAX ), &102FORCE( NMAX ), &103STIFF( NMAX, NMAX ), &104LOAD(NMAX) , &105Velo( 2, NMAX ), &106STAT=istat )107IF ( istat /= 0 ) THEN108CALL Fatal(SolverName,'Memory allocation error 1, Aborting.')109END IF110111CALL Info(SolverName,'Memory allocations done' )112AllocationsDone = .TRUE.113END IF114115!------------------------------------------------------------------------------116! Get Flow solution117!------------------------------------------------------------------------------118ConvectionVar=.True.119FlowSolName = GetString(SolverParams ,'Flow Solution Name', Found)120IF(.NOT.Found) THEN121WRITE(Message,'(A)') &122'<Flow Solution Name> Not Found; will look for <convection velocity> in body forces'123CALL Info(SolverName,Message,level=10)124ConvectionVar=.False.125NSDOFS=GetInteger(SolverParams ,'Convection Dimension',Found)126IF(.NOT.Found) &127CALL Fatal(SolverName,'if <Flow Solution Name> not given prescribe <Convection Dimension>')128ELSE129FlowSol => VariableGet( Solver % Mesh % Variables, FlowSolName,UnFoundFatal=.TRUE.)130FlowPerm => FlowSol % Perm131NSDOFs = FlowSol % DOFs132FlowSolution => FlowSol % Values133END IF134135136CALL DefaultInitialize()137!------------------------------------------------------------------------------138! Do the assembly139!------------------------------------------------------------------------------140DO t=1,Solver % NumberOfActiveElements141142CurrentElement => GetActiveElement(t)143n = GetElementNOFNodes(CurrentElement)144NodeIndexes => CurrentElement % NodeIndexes145146! set coords of highest occurring dimension to zero (to get correct path element)147!-------------------------------------------------------------------------------148ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)149IF (NSDOFs == 1) THEN150ElementNodes % y(1:n) = 0.0151ElementNodes % z(1:n) = 0.0152ELSE IF (NSDOFs == 2) THEN153ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)154ElementNodes % z(1:n) = 0.0_dp155ELSE156WRITE(Message,'(a,i0,a)')&157'It is not possible to compute Thickness evolution if Flow Sol DOFs=',&158NSDOFs, ' . Aborting'159CALL Fatal( SolverName, Message)160STOP161END IF162163! get pointers on BF164!---------------------------------------------------------------165BodyForce => GetBodyForce(CurrentElement)166167! get flow soulution and velocity field from it168!----------------------------------------------169Velo = 0.0_dp170!----------------------------------------------------171! get velocity profile172IF (ConvectionVar) Then173DO i=1,n174j = NSDOFs*FlowPerm(NodeIndexes(i))175!2D problem - 1D Thickness evolution176IF(NSDOFs == 1) THEN177Velo(1,i) = FlowSolution( j )178Velo(2,i) = 0.0_dp179!2D problem180ELSE IF (NSDOFs == 2) THEN181Velo(1,i) = FlowSolution( j-1 )182Velo(2,i) = FlowSolution( j )183ELSE184WRITE(Message,'(a)') 'Velocity should be size 1 or 2'185CALL Fatal( SolverName, Message)186END IF187END DO188ELSE189IF (ASSOCIATED( BodyForce ) ) THEN190Velo(1,1:n) = ListGetReal( BodyForce, 'Convection Velocity 1',n, NodeIndexes,UnFoundFatal=.TRUE. )191if (NSDOFs.eq.2) &192Velo(2,1:n) = ListGetReal( BodyForce, 'Convection Velocity 2',n, NodeIndexes,UnFoundFatal=.TRUE. )193END IF194END IF195!------------------------------------------------------------------------------196! get the accumulation/ablation rate (i.e. normal surface flux)197! from the body force section198!------------------------------------------------------------------------------199LOAD=0.0_dp200IF (ASSOCIATED( BodyForce ) ) THEN201LOAD(1:n) = LOAD(1:n) + &202GetReal( BodyForce, 'Top Surface Accumulation', Found )203LOAD(1:n) = LOAD(1:n) + &204GetReal( BodyForce, 'Bottom Surface Accumulation', Found )205END IF206207!------------------------------------------------------------------------------208! Get element local matrix, and rhs vector209!------------------------------------------------------------------------------210CALL LocalMatrix( STIFF, FORCE,LOAD,&211Velo, NSDOFs, &212CurrentElement, n, ElementNodes, NodeIndexes)213214!------------------------------------------------------------------------------215CALL DefaultUpdateEquations( STIFF, FORCE )216!------------------------------------------------------------------------------217218END DO ! End loop bulk elements219CALL DefaultFinishBulkAssembly()220221!------------------------------------------------------------------------------222! Neumann & Newton boundary conditions223!------------------------------------------------------------------------------224!225! MIND: In weak formulation it is not possible to prescribe a contact angle on226! a boundary in this solver. This has to be taken care of in the boundary227! condition for the stress tensor in the Navier-Stokes Solver. Thus, in228! generally it does not make sense to prescribe a Neumann type of229! condition here.230231!------------------------------------------------------------------------------232! FinishAssemebly must be called after all other assembly steps, but before233! Dirichlet boundary settings. Actually no need to call it except for234! transient simulations.235!------------------------------------------------------------------------------236CALL DefaultFinishAssembly()237CALL DefaultDirichletBCs()238239Norm = DefaultSolve()240241!------------------------------------------------------------------------------242CONTAINS243244!------------------------------------------------------------------------------245!==============================================================================246SUBROUTINE LocalMatrix( STIFF, FORCE,LOAD,&247Velo, NSDOFs, &248Element, n, Nodes, NodeIndexes)249!------------------------------------------------------------------------------250! INPUT: LOAD(:) nodal values of the accumulation/ablation function251!252! Element current element253! n number of nodes254! Nodes current node points255!256! OUTPUT: STIFF(:,:)257! FORCE(:)258!------------------------------------------------------------------------------259! external variables:260! ------------------------------------------------------------------------261REAL(KIND=dp) :: STIFF(:,:),FORCE(:), LOAD(:), Velo(:,:)262263INTEGER :: n, NodeIndexes(:), NSDOFs264TYPE(Nodes_t) :: Nodes265TYPE(Element_t), POINTER :: Element266267!------------------------------------------------------------------------------268! internal variables:269! ------------------------------------------------------------------------270TYPE(GaussIntegrationPoints_t) :: IntegStuff271REAL(KIND=dp) :: Basis(n),dBasisdx(n,3)272REAL(KIND=dp) :: SU(n),SW(n)273REAL(KIND=dp) :: Vgauss(2), UNorm,divu,Source274REAL(KIND=dp) :: U,V,W,S,SqrtElementMetric275REAL(KIND=dp) :: Tau,hk276INTEGER :: i,j,t,p,q277LOGICAL :: stat278!------------------------------------------------------------------------------279280FORCE = 0.0_dp281STIFF = 0.0_dp282283hK = ElementDiameter( Element, Nodes )284285!286! Numerical integration:287! ----------------------288IntegStuff = GaussPoints( Element )289290SU = 0.0_dp291SW = 0.0_dp292293DO t = 1,IntegStuff % n294U = IntegStuff % u(t)295V = IntegStuff % v(t)296W = IntegStuff % w(t)297S = IntegStuff % s(t)298!299! Basis function values & derivatives at the integration point:300! -------------------------------------------------------------301stat = ElementInfo( Element,Nodes,U,V,W,SqrtElementMetric, &302Basis,dBasisdx, Bubbles=.False. )303304! Correction from metric305! ----------------------306S = S * SqrtElementMetric307308!309! Velocities and (norm of) gradient of free surface and source function310! at Gauss point311! ---------------------------------------------------------------------312313Vgauss=0.0_dp314DO i=1,NSDOFs315Vgauss(i) = SUM( Basis(1:n)*(Velo(i,1:n)))316END DO317318divu = 0.0_dp319DO i=1,NSDOFs320divu = divu + SUM( dBasisdx(1:n,i)*(Velo(i,1:n)))321END DO322323UNorm = SQRT( SUM( Vgauss(1:NSDOFs)**2 ) )324Tau=0._dp325IF (UNorm .GT. 0.0_dp) Tau = hK / ( 2*Unorm )326327DO p=1,n328SU(p) = 0.0_dp329SW(p) = 0.0_dp330DO i=1,NSDOFs331SU(p) = SU(p) + Vgauss(i) * dBasisdx(p,i)332SW(p) = SW(p) + Vgauss(i) * dBasisdx(p,i)333END DO334END DO335336! Stiffness matrix:337! -----------------338DO p=1,n339DO q=1,n340DO i=1,NSDOFs341STIFF(p,q) = STIFF(p,q) + &342s * Vgauss(i) * dBasisdx(q,i) * Basis(p)343END DO344STIFF(p,q) = STIFF(p,q) + s * Tau * SU(q) * SW(p)345STIFF(p,q) = STIFF(p,q) + s * divu * Basis(q) * (Basis(p) + Tau*SW(p))346END DO347END DO348349! Get accumulation/ablation function350! ---------------------------------------------------------351Source = 0.0_dp352Source=SUM(Basis(1:n)*LOAD(1:n))353354! Assemble force vector:355! ---------------------356FORCE(1:n) = FORCE(1:n) &357+ Source * (Basis(1:n) + Tau*SW(1:n)) * s358359END DO360361!------------------------------------------------------------------------------362END SUBROUTINE LocalMatrix363364!------------------------------------------------------------------------------365END SUBROUTINE AdjointThickness_ThicknessSolver366!------------------------------------------------------------------------------367368369