Path: blob/devel/elmerice/Solvers/AdjointThickness/AdjointThickness_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: F. Gillet-Chaulet25! * Web: http://elmerice.elmerfem.org26! *27! * Original Date: Dec. 202028! *29! *****************************************************************************30!31SUBROUTINE AdjointThickness_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 AdjointThickness_GradientSolver_init051!*****************************************************************************52!-----------------------------------------------------------------------------53SUBROUTINE AdjointThickness_GradientSolver( Model,Solver,dt,TransientSimulation )54USE DefUtils55IMPLICIT NONE5657!------------------------------------------------------------------------------58! external variables59!------------------------------------------------------------------------------60TYPE(Model_t) :: Model61TYPE(Solver_t):: Solver62REAL(KIND=dp) :: dt63LOGICAL :: TransientSimulation64!------------------------------------------------------------------------------65! Local variables66!------------------------------------------------------------------------------67TYPE(ValueList_t), POINTER :: BodyForce, SolverParams6869INTEGER :: NMAX,NSDOFs70INTEGER :: istat71INTEGER :: t,i,j,n72LOGICAL :: ConvectionVar, Found7374REAL(KIND=dp) :: Norm7576CHARACTER(LEN=MAX_NAME_LEN) :: FlowSolName77TYPE(Variable_t), POINTER :: FlowSol78REAL(KIND=dp), POINTER :: FlowSolution(:)79INTEGER, POINTER :: FlowPerm(:)8081REAL(KIND=dp), ALLOCATABLE,SAVE :: STIFF(:,:),FORCE(:),LOAD(:),Velo(:,:)8283CHARACTER(LEN=MAX_NAME_LEN) :: SolverName= 'AdjointThickness_ThicknessSolver'8485TYPE(Nodes_t),SAVE :: ElementNodes86TYPE(Element_t),POINTER :: CurrentElement87INTEGER, POINTER :: NodeIndexes(:)8889LOGICAL, SAVE :: AllocationsDone = .FALSE.9091CHARACTER(LEN=MAX_NAME_LEN) :: ThickSolName,ThickbSolName92TYPE(Variable_t), POINTER :: ThickSol,ThickbSol93REAL(KIND=dp), POINTER :: Thick(:),Thickb(:)94INTEGER, POINTER :: ThickPerm(:),ThickbPerm(:)9596LOGICAL :: Reset, ComputeDJDsmbTop,ComputeDJDsmbBot,ComputeDJDUV97TYPE(Variable_t), POINTER :: DJDsmbTopSol,DJDsmbBotSol,DJDUVSol98INTEGER,POINTER :: DJDsmbTopPerm(:),DJDsmbBotPerm(:),DJDUVPerm(:)99REAL(KIND=dp), POINTER :: DJDsmbTop(:),DJDsmbBot(:),DJDUV(:)100REAL(KIND=dp), ALLOCATABLE ,SAVE:: LOADb(:),Velob(:,:)101102!------------------------------------------------------------------------------103! Go104!------------------------------------------------------------------------------105SolverParams => GetSolverParams()106107!------------------------------------------------------------------------------108! check incompatibilities109!------------------------------------------------------------------------------110IF ( CurrentCoordinateSystem() /= Cartesian ) THEN111CALL FATAL(SolverName,'sorry only for cartesian coordinate system')112END IF113IF (TransientSimulation) THEN114CALL FATAL(SolverName,'sorry works only in steady state')115ENDIF116117!------------------------------------------------------------------------------118! Allocate some permanent storage, this is done first time only119!------------------------------------------------------------------------------120IF ( .NOT. AllocationsDone .OR. Solver % Mesh % Changed) THEN121NMAX = Model % MaxElementNodes122123IF ( AllocationsDone ) THEN124DEALLOCATE( ElementNodes % x, &125ElementNodes % y, &126ElementNodes % z, &127FORCE, &128STIFF, &129LOAD, LOADb,&130Velo,Velob)131END IF132133ALLOCATE( ElementNodes % x( NMAX ), &134ElementNodes % y( NMAX ), &135ElementNodes % z( NMAX ), &136FORCE( NMAX ), &137STIFF( NMAX, NMAX ), &138LOAD(NMAX) , LOADb(NMAX),&139Velo( 2, NMAX ), Velob( 2, NMAX ),&140STAT=istat )141IF ( istat /= 0 ) THEN142CALL Fatal(SolverName,'Memory allocation error 1, Aborting.')143END IF144145CALL Info(SolverName,'Memory allocations done' )146AllocationsDone = .TRUE.147END IF148149150!------------------------------------------------------------------------------151! Get variables152!------------------------------------------------------------------------------153ThickSolName = GetString(SolverParams ,'Thickness Solution Name', Found)154IF(.NOT.Found) THEN155CALL WARN(SolverName,'<Thickness Solution Name> not Found; assume default H')156ThickSolName = 'H'157ENDIF158ThickSol => VariableGet( Solver % Mesh % Variables, ThickSolName, UnFoundFatal=.TRUE.)159Thick => ThickSol % Values160ThickPerm => ThickSol % Perm161162ThickbSolName = GetString(SolverParams ,'Adjoint Solution Name', Found)163IF(.NOT.Found) THEN164CALL WARN(SolverName,'<Adjoint Solution Name> not Found; assume default Adjoint')165ThickSolName = 'Adjoint'166ENDIF167ThickbSol => VariableGet( Solver % Mesh % Variables, ThickbSolName,UnFoundFatal=.TRUE.)168Thickb => ThickbSol % Values169ThickbPerm => ThickbSol % Perm170171ComputeDJDsmbTop = GetLogical(SolverParams ,'ComputeDJDsmbTop' , Found)172IF (ComputeDJDsmbTop) THEN173DJDsmbTopSol => VariableGet( Solver % Mesh % Variables, 'DJDsmbTop', UnFoundFatal=.TRUE.)174DJDsmbTop => DJDsmbTopSol % Values175DJDsmbTopPerm => DJDsmbTopSol % Perm176Reset = GetLogical( SolverParams,'Reset DJDsmbTop', Found)177if (Reset.OR.(.NOT.Found)) DJDsmbTop = 0.0178ENDIF179180ComputeDJDsmbBot = GetLogical(SolverParams ,'ComputeDJDsmbBot' , Found)181IF (ComputeDJDsmbBot) THEN182DJDsmbBotSol => VariableGet( Solver % Mesh % Variables, 'DJDsmbBot',UnFoundFatal=.TRUE. )183DJDsmbBot => DJDsmbBotSol % Values184DJDsmbBotPerm => DJDsmbBotSol % Perm185Reset = GetLogical( SolverParams,'Reset DJDsmbBot', Found)186if (Reset.OR.(.NOT.Found)) DJDsmbBot = 0.0187ENDIF188189!------------------------------------------------------------------------------190! Get Flow solution191!------------------------------------------------------------------------------192ConvectionVar=.True.193FlowSolName = GetString(SolverParams ,'Flow Solution Name', Found)194IF(.NOT.Found) THEN195WRITE(Message,'(A)') &196'<Flow Solution Name> Not Found; will look for <convection velocity> in body forces'197CALL Info(SolverName,Message,level=10)198ConvectionVar=.False.199NSDOFS=GetInteger(SolverParams ,'Convection Dimension',Found)200IF(.NOT.Found) &201CALL Fatal(SolverName,'if <Flow Solution Name> not given prescribe <Convection Dimension>')202ELSE203FlowSol => VariableGet( Solver % Mesh % Variables, FlowSolName,UnFoundFatal=.TRUE.)204FlowPerm => FlowSol % Perm205NSDOFs = FlowSol % DOFs206FlowSolution => FlowSol % Values207END IF208209ComputeDJDUV = GetLogical(SolverParams ,'ComputeDJDUV' , Found)210IF (ComputeDJDUV) THEN211DJDUVSol => VariableGet( Solver % Mesh % Variables, 'DJDUV',UnFoundFatal=.TRUE. )212DJDUV => DJDUVSol % Values213DJDUVPerm => DJDUVSol % Perm214IF (DJDUVSol % DOFs.NE.NSDOFs) &215CALL FATAL(SolverName,'DJDUV DOFs is different from the velocity DOFs')216Reset = GetLogical( SolverParams,'Reset DJDUV', Found)217if (Reset.OR.(.NOT.Found)) DJDUV = 0.0218ENDIF219220!------------------------------------------------------------------------------221! Do the assembly222!------------------------------------------------------------------------------223DO t=1,Solver % NumberOfActiveElements224225CurrentElement => GetActiveElement(t)226n = GetElementNOFNodes(CurrentElement)227NodeIndexes => CurrentElement % NodeIndexes228229! set coords of highest occurring dimension to zero (to get correct path element)230!-------------------------------------------------------------------------------231ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)232IF (NSDOFs == 1) THEN233ElementNodes % y(1:n) = 0.0234ElementNodes % z(1:n) = 0.0235ELSE IF (NSDOFs == 2) THEN236ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)237ElementNodes % z(1:n) = 0.0_dp238ELSE239WRITE(Message,'(a,i0,a)')&240'It is not possible to compute Thickness evolution if Flow Sol DOFs=',&241NSDOFs, ' . Aborting'242CALL Fatal( SolverName, Message)243STOP244END IF245246! get pointers on BF247!----------------------------------------------------------------248BodyForce => GetBodyForce(CurrentElement)249250! get flow soulution and velocity field from it251!----------------------------------------------252Velo = 0.0_dp253!----------------------------------------------------254! get velocity profile255IF (ConvectionVar) Then256DO i=1,n257j = NSDOFs*FlowPerm(NodeIndexes(i))258!2D problem - 1D Thickness evolution259IF(NSDOFs == 1) THEN260Velo(1,i) = FlowSolution( j )261Velo(2,i) = 0.0_dp262!2D problem -263ELSE IF (NSDOFs == 2) THEN264Velo(1,i) = FlowSolution( j-1 )265Velo(2,i) = FlowSolution( j )266ELSE267WRITE(Message,'(a)') 'Velocity should be size 1 or 2'268CALL Fatal( SolverName, Message)269END IF270END DO271ELSE272IF (ASSOCIATED( BodyForce ) ) THEN273Velo(1,1:n) = ListGetReal( BodyForce, 'Convection Velocity 1',n, NodeIndexes,UnFoundFatal=.TRUE. )274if (NSDOFs.eq.2) &275Velo(2,1:n) = ListGetReal( BodyForce, 'Convection Velocity 2',n, NodeIndexes,UnFoundFatal=.TRUE. )276END IF277END IF278!------------------------------------------------------------------------------279! get the accumulation/ablation rate (i.e. normal surface flux)280! from the body force section281!------------------------------------------------------------------------------282LOAD=0.0_dp283IF (ASSOCIATED( BodyForce ) ) THEN284LOAD(1:n) = LOAD(1:n) + &285GetReal( BodyForce, 'Top Surface Accumulation', Found )286LOAD(1:n) = LOAD(1:n) + &287GetReal( BodyForce, 'Bottom Surface Accumulation', Found )288END IF289290291!------------------------------------------------------------------------------292! Get element local matrix, and rhs vector293!------------------------------------------------------------------------------294CALL LocalMatrix( STIFF, FORCE,LOAD,LOADb,&295Velo, Velob,NSDOFs, &296CurrentElement, n, ElementNodes, NodeIndexes)297298If (ComputeDJDsmbTop) &299DJDsmbTop(DJDsmbTopPerm(NodeIndexes(1:n)))=DJDsmbTop(DJDsmbTopPerm(NodeIndexes(1:n)))+LOADb(1:n)300If (ComputeDJDsmbBot) &301DJDsmbBot(DJDsmbBotPerm(NodeIndexes(1:n)))=DJDsmbBot(DJDsmbBotPerm(NodeIndexes(1:n)))+LOADb(1:n)302If (ComputeDJDUV) then303304Do j=1,n305Do i=1,NSDOFs306DJDUV(NSDOFs*(DJDUVPerm(NodeIndexes(j))-1)+i)=DJDUV(NSDOFs*(DJDUVPerm(NodeIndexes(j))-1)+i)+&307Velob(i,j)308End do309End Do310End if311312END DO ! End loop bulk elements313314!------------------------------------------------------------------------------315CONTAINS316317!------------------------------------------------------------------------------318!==============================================================================319SUBROUTINE LocalMatrix( STIFF, FORCE,&320LOAD,LOADb, Velo, Velob, NSDOFs, &321Element, n, Nodes, NodeIndexes)322!------------------------------------------------------------------------------323!------------------------------------------------------------------------------324! external variables:325! ------------------------------------------------------------------------326REAL(KIND=dp) :: STIFF(:,:),FORCE(:), LOAD(:), Velo(:,:)327REAL(KIND=dp) :: LOADb(:), Velob(:,:)328329INTEGER :: n, NodeIndexes(:), NSDOFs330TYPE(Nodes_t) :: Nodes331TYPE(Element_t), POINTER :: Element332333!------------------------------------------------------------------------------334! internal variables:335! ------------------------------------------------------------------------336TYPE(GaussIntegrationPoints_t) :: IntegStuff337REAL(KIND=dp) :: Basis(n),dBasisdx(n,3)338REAL(KIND=dp) :: SU(n),SW(n)339REAL(KIND=dp) :: Vgauss(2), UNorm,divu,Source340REAL(KIND=dp) :: U,V,W,S,SqrtElementMetric341REAL(KIND=dp) :: Tau,hk342INTEGER :: i,j,t,p,q343LOGICAL :: stat344345REAL(KIND=dp) :: Sourceb,divub,Vgaussb(2),SUb(n),SWb(n),Taub,Unormb346!------------------------------------------------------------------------------347348LOADb = 0.0_dp349Velob = 0.0_dp350351352hK = ElementDiameter( Element, Nodes )353354!355! Numerical integration:356! ----------------------357IntegStuff = GaussPoints( Element )358359SU = 0.0_dp360SW = 0.0_dp361362DO t = 1,IntegStuff % n363U = IntegStuff % u(t)364V = IntegStuff % v(t)365W = IntegStuff % w(t)366S = IntegStuff % s(t)367!368! Basis function values & derivatives at the integration point:369! -------------------------------------------------------------370stat = ElementInfo( Element,Nodes,U,V,W,SqrtElementMetric, &371Basis,dBasisdx, Bubbles=.False.)372373! Correction from metric374! ----------------------375S = S * SqrtElementMetric376377!378! Velocities and (norm of) gradient of free surface and source function379! at Gauss point380! ---------------------------------------------------------------------381382Vgauss=0.0_dp383DO i=1,NSDOFs384Vgauss(i) = SUM( Basis(1:n)*(Velo(i,1:n)))385END DO386387divu = 0.0_dp388DO i=1,NSDOFs389divu = divu + SUM( dBasisdx(1:n,i)*(Velo(i,1:n)))390END DO391392UNorm = SQRT( SUM( Vgauss(1:NSDOFs)**2 ) )393Tau = 0.0_dp394IF (UNorm .GT. 0.0_dp) Tau = hK / ( 2*Unorm )395396DO p=1,n397SU(p) = 0.0_dp398SW(p) = 0.0_dp399DO i=1,NSDOFs400SU(p) = SU(p) + Vgauss(i) * dBasisdx(p,i)401SW(p) = SW(p) + Vgauss(i) * dBasisdx(p,i)402END DO403END DO404405! Stiffness matrix:406! -----------------407!DO p=1,n408! DO q=1,n409! DO i=1,NSDOFs410! STIFF(p,q) = STIFF(p,q) + &411! s * Vgauss(i) * dBasisdx(q,i) * Basis(p)412! END DO413! STIFF(p,q) = STIFF(p,q) + s * Tau * SU(q) * SW(p)414! STIFF(p,q) = STIFF(p,q) + s * divu * Basis(q) * (Basis(p) + Tau*SW(p))415! END DO416!END DO417418!! Adjoint part of the stiffness matrix419divub = 0._dp420Vgaussb = 0._dp421SUb = 0._dp422SWb = 0._dp423Taub =0._dp424Do p=1,n425Do q=1,n426SUb(q) = SUb(q) + s * Tau * SW(p) * &427(-Thick(ThickPerm(NodeIndexes(q)))*Thickb(ThickbPerm(NodeIndexes(p))))428SWb(p) = SWb(p) + s * Tau * SU(q) * &429(-Thick(ThickPerm(NodeIndexes(q)))*Thickb(ThickbPerm(NodeIndexes(p))))430SWb(p) = SWb(p) + s * divu * Basis(q) * Tau * &431(-Thick(ThickPerm(NodeIndexes(q)))*Thickb(ThickbPerm(NodeIndexes(p))))432Taub = Taub + s * SU(q) * SW(p) * &433(-Thick(ThickPerm(NodeIndexes(q)))*Thickb(ThickbPerm(NodeIndexes(p))))434Taub = Taub + s * divu * Basis(q) * SW(p) * &435(-Thick(ThickPerm(NodeIndexes(q)))*Thickb(ThickbPerm(NodeIndexes(p))))436divub = divub + s * Basis(q) * (Basis(p) + Tau*SW(p)) * &437(-Thick(ThickPerm(NodeIndexes(q)))*Thickb(ThickbPerm(NodeIndexes(p))))438Do i=1,NSDOFs439Vgaussb(i)=Vgaussb(i) + s * dBasisdx(q,i) * Basis(p) * &440(-Thick(ThickPerm(NodeIndexes(q)))*Thickb(ThickbPerm(NodeIndexes(p))))441End do442End do443End do444445! Get accumulation/ablation function446! ---------------------------------------------------------447Source = 0.0_dp448Source=SUM(Basis(1:n)*LOAD(1:n))449450! Assemble force vector:451! ---------------------452!FORCE(1:n) = FORCE(1:n) &453! + Source * (Basis(1:n) + Tau*SW(1:n)) * s454455!! Adjoint Part of the accumulation/ablation function456Sourceb=0._dp457Do p=1,n458Sourceb = Sourceb + (Basis(p) + Tau*SW(p)) * s * Thickb(ThickbPerm(NodeIndexes(p)))459SWb(p) = SWb(p) + Source * Tau * s * Thickb(ThickbPerm(NodeIndexes(p)))460Taub = Taub + Source * SW(p) * s * Thickb(ThickbPerm(NodeIndexes(p)))461End Do462LOADb(1:n) = LOADb(1:n) + Sourceb * Basis(1:n)463!!464465!DO p=1,n466! SU(p) = 0.0_dp467! SW(p) = 0.0_dp468! DO i=1,NSDOFs469! SU(p) = SU(p) + Vgauss(i) * dBasisdx(p,i)470! SW(p) = SW(p) + Vgauss(i) * dBasisdx(p,i)471! END DO472!END IF473474DO p=1,n475DO i=1,NSDOFs476Vgaussb(i)=Vgaussb(i)+SUb(p)*dBasisdx(p,i)477Vgaussb(i)=Vgaussb(i)+SWb(p)*dBasisdx(p,i)478END DO479END DO480481!UNorm = SQRT( SUM( Vgauss(1:NSDOFs)**2 ) )482!Tau=0._dp483!IF (UNorm .NE. 0.0_dp) Tau = hK / ( 2*Unorm )484485IF (UNorm .GT. 0.0_dp) THEN486Unormb = -0.5*hK*(Unorm**(-2)) * Taub487ELSE488Unormb = 0._dp489END IF490491Do i=1,NSDOFs492IF (UNorm .GT. 0.0_dp) &493Vgaussb(i) = Vgaussb(i) + Unormb * 0.5*(SUM( Vgauss(1:NSDOFs)**2)**(-0.5))*2.0*Vgauss(i)494END DO495496Do p=1,n497Do i=1,NSDOFs498Velob(i,p)=Velob(i,p)+Vgaussb(i)*Basis(p)+divub*dBasisdx(p,i)499End do500End do501502503END DO504505!------------------------------------------------------------------------------506END SUBROUTINE LocalMatrix507508!------------------------------------------------------------------------------509END SUBROUTINE AdjointThickness_GradientSolver510!------------------------------------------------------------------------------511512513