Path: blob/devel/elmerice/Solvers/AdjointSSA/AdjointSSA_CostFluxDivSolver.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-Chaulet (LGGE, Grenoble,France)25! * Email: [email protected]26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date:29! *30! *****************************************************************************31SUBROUTINE AdjointSSA_CostFluxDivSolver_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_CostFluxDivSolver_init051! *****************************************************************************52SUBROUTINE AdjointSSA_CostFluxDivSolver( Model,Solver,dt,TransientSimulation )53! *****************************************************************************54!------------------------------------------------------------------------------55!56! Compute a cost function that measure the ice flux divergence anomaly57! and the required forcing for the SSA adjoint problem58! J=int_{Pb dimension} 0.5 * (dhdt{obs} + u.grad(H) + H* div(u) - MB )**259!60! OUTPUT are : J ; DJDu (==Velocityb variable used as forcing of the SSA adjoint problem)61! DJDZb (optional); DJDZs(optional)62!63! TODO : add a variance term to regularise the cost64!65! !!!!! BE careful it will reset Cost , Velocityb, and DJZb; DJDZs to 0 by default !!!!66! !!! If other cost and gradient are computed before ,67! use "<Reset Cost Value> = False" to add cost and gradient to previously computed values !!!68!69! INPUT PARAMETERS are:70!71! In solver section:72! Problem Dimension = Integer (default = Coordinate system dimension)73! Compute DJDZb = Logical (default= .True.)74! Compute DJDZs = Logical (default= .True.)75! Reset Cost Value = Logical (default = .True.)76! Cost Filename = File (default = 'CostOfT.dat')77! Cost Variable Name = String (default= 'CostValue')78!79! Variables80! SSAVelocity (solution of the SSA pb;DOFs== Pb Dimension)81! Velocityb (forcing for the adjoint pb;DOFs== Pb dimension)82! Zb (bottom elevation)83! DJDZb (gradient of J wr. to Zb, as J is fn of H=Zs-Zb)84! Zs (surface elevation)85! DJDZs (gradient of J wr. to Zs, as J is fn of H=Zs-Zb)86!87! In body Forces:88! Top Surface Accumulation = Real (default= 0)89! Bottom Surface Accumulation = Real (default = 0)90! Observed dhdt = Real (default = 0)91!92!******************************************************************************93USE DefUtils94IMPLICIT NONE95!------------------------------------------------------------------------------96TYPE(Solver_t) :: Solver97TYPE(Model_t) :: Model9899REAL(KIND=dp) :: dt100LOGICAL :: TransientSimulation101!102CHARACTER(LEN=MAX_NAME_LEN), PARAMETER :: DefaultCostFile = 'CostOfT.dat'103CHARACTER(LEN=MAX_NAME_LEN) :: SolverName,CostFile104CHARACTER(LEN=MAX_NAME_LEN) :: CostSolName,VarSolName105TYPE(Element_t),POINTER :: Element106TYPE(Variable_t), POINTER :: TimeVar,CostVar107108TYPE(Variable_t), POINTER :: VelocitySol,VelocitybSol109REAL(KIND=dp), POINTER :: Velocity(:),Vb(:)110INTEGER, POINTER :: VeloPerm(:),VbPerm(:)111112TYPE(Variable_t), POINTER :: ZbSol,ZsSol113TYPE(Variable_t), POINTER :: DJDZbSol,DJDZsSol114REAL(KIND=dp), POINTER :: Zb(:),Zs(:)115REAL(KIND=dp), POINTER :: DJDZb(:),DJDZs(:)116INTEGER, POINTER :: ZbPerm(:),ZsPerm(:)117INTEGER, POINTER :: DJDZbPerm(:),DJDZsPerm(:)118119TYPE(ValueList_t), POINTER :: SolverParams,BodyForce120121TYPE(Nodes_t) :: ElementNodes122123TYPE(GaussIntegrationPoints_t) :: IntegStuff124125INTEGER, POINTER :: NodeIndexes(:)126integer :: i,j,k,l,t,n,NMAX,DIM,ierr,c127128real(kind=dp) :: Cost,Cost_S,Costb,Lambda,area129real(kind=dp) :: u,v,w,s,coeff,SqrtElementMetric,x130REAL(KIND=dp) :: Basis(Model % MaxElementNodes), dBasisdx(Model % MaxElementNodes,3)131REAL(KIND=dp),dimension(:),allocatable,SAVE :: NodeSMB,NodeDHDT,NodeH132REAL(KIND=dp),dimension(:,:),allocatable,SAVE :: Velo133REAL(KIND=dp) :: smb,dhdt,h,ugrdh,divu,gradh(2),Vgauss(2)134135LOGICAL :: ComputeDJDZb,ComputeDJDZs,ResetCost136Logical :: Firsttime=.true.,Found,Parallel,stat,Gotit137LOGICAL :: BoundarySolver138CHARACTER*10 :: date,temps139140save Firsttime,Parallel141save SolverName,CostSolName,CostFile142save ElementNodes143144145SolverParams => GetSolverParams()146147!! check if we are on a boundary or in the bulk148BoundarySolver = ( Solver % ActiveElements(1) > Model % Mesh % NumberOfBulkElements )149IF (BoundarySolver) THEN150DIM = CoordinateSystemDimension() - 1151ELSE152DIM = CoordinateSystemDimension()153ENDIF154155Lambda = GetConstReal( SolverParams,'Lambda', Found)156IF(.NOT.Found) THEN157CALL WARN(SolverName,'Keyword >Lambda< not found in section >Solver<')158CALL WARN(SolverName,'Taking default value Lambda=1.0')159Lambda = 1.0160End if161162ComputeDJDZb = GetLogical( SolverParams,'Compute DJDZb', Found)163IF(.NOT.Found) ComputeDJDZb=.True.164ComputeDJDZs = GetLogical( SolverParams,'Compute DJDZs', Found)165IF(.NOT.Found) ComputeDJDZb=.True.166ResetCost = GetLogical( SolverParams,'Reset Cost Value', Found)167IF(.NOT.Found) ResetCost=.True.168169170If (Firsttime) then171N = model % MaxElementNodes172allocate(ElementNodes % x(N), ElementNodes % y(N), ElementNodes % z(N))173allocate(NodeSMB(N),NodeDHDT(N),Velo(2,N),NodeH(N))174175!!!!!!! Check for parallel run176Parallel = .FALSE.177IF ( ASSOCIATED( Solver % Matrix % ParMatrix ) ) THEN178IF ( Solver % Matrix % ParMatrix % ParEnv % PEs > 1 ) THEN179Parallel = .TRUE.180END IF181END IF182183WRITE(SolverName, '(A)') 'CostSolver_Adjoint'184185!!!!!!!!!!! get Solver Variables186187CostFile = ListGetString(Solver % Values,'Cost Filename',Found )188IF (.NOT. Found) CostFile = DefaultCostFile189CALL DATE_AND_TIME(date,temps)190If (Parallel) then191if (ParEnv % MyPe.EQ.0) then192OPEN (12, FILE=CostFile)193write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)194write(12,1001) Lambda195write(12,'(A)') '# iter, Jdiv'196CLOSE(12)197End if198Else199OPEN (12, FILE=CostFile)200write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)201write(12,1001) Lambda202write(12,'(A)') '# iter, Jdiv'203CLOSE(12)204End if205206CostSolName = GetString( SolverParams,'Cost Variable Name', Found)207IF(.NOT.Found) THEN208CALL WARN(SolverName,'Keyword >Cost Variable Name< not found in section >Solver<')209CALL WARN(SolverName,'Taking default value >CostValue<')210WRITE(CostSolName,'(A)') 'CostValue'211END IF212213!!! End of First visit214Firsttime=.false.215Endif216217218VelocitySol => VariableGet( Solver % Mesh % Variables, 'SSAVelocity',UnFoundFatal=.TRUE. )219Velocity => VelocitySol % Values220VeloPerm => VelocitySol % Perm221c=DIM ! size of the velocity variable222IF (VelocitySol % DOFs.NE.c) then223WRITE(Message,'(A,I1,A,I1)') &224'Variable SSAVelocity has ',VelocitySol % DOFs,' DOFs, should be',c225CALL FATAL(SolverName,Message)226End If227228VelocitybSol => VariableGet( Solver % Mesh % Variables, 'Velocityb',UnFoundFatal=.TRUE. )229Vb => VelocitybSol % Values230VbPerm => VelocitybSol % Perm231IF (VelocitybSol % DOFs.NE.c) then232WRITE(Message,'(A,I1,A,I1)') &233'Variable Velocityb has ',VelocitybSol % DOFs,' DOFs, should be',c234CALL FATAL(SolverName,Message)235End If236if (ResetCost) Vb=0.0_dp237238ZbSol => VariableGet( Solver % Mesh % Variables, 'Zb',UnFoundFatal=.TRUE. )239Zb => ZbSol % Values240ZbPerm => ZbSol % Perm241IF (ComputeDJDZb) Then242DJDZbSol => VariableGet( Solver % Mesh % Variables, 'DJDZb',UnFoundFatal=.TRUE. )243DJDZb => DJDZbSol % Values244DJDZbPerm => DJDZbSol % Perm245!!!!! Reset DJDZ to 0 HERE246DJDZb=0._dp247ENDIF248249ZsSol => VariableGet( Solver % Mesh % Variables, 'Zs',UnFoundFatal=.TRUE. )250Zs => ZsSol % Values251ZsPerm => ZsSol % Perm252IF (ComputeDJDZs) Then253DJDZsSol => VariableGet( Solver % Mesh % Variables, 'DJDZs',UnFoundFatal=.TRUE. )254DJDZs => DJDZsSol % Values255DJDZsPerm => DJDZsSol % Perm256!!!!! Reset DJDZ to 0 HERE257DJDZs=0._dp258ENDIF259260Cost=0._dp261area=0._dp262263DO t=1,Solver % NumberOfActiveElements264Element => GetActiveElement(t)265IF (CheckPassiveElement(Element)) CYCLE266IF (ParEnv % myPe .NE. Element % partIndex) CYCLE267n = GetElementNOFNodes()268269NodeIndexes => Element % NodeIndexes270271! set coords of highest occurring dimension to zero (to get correct path element)272!-------------------------------------------------------------------------------273ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)274IF (DIM == 1) THEN !1D SSA275ElementNodes % y(1:n) = 0.0_dp276ElementNodes % z(1:n) = 0.0_dp277ELSE IF (DIM == 2) THEN !2D SSA278ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)279ElementNodes % z(1:n) = 0.0_dp280ELSE281WRITE(Message,'(a,i1,a)')&282'It is not possible to compute SSA problems with DOFs=',&283DIM, ' . Aborting'284CALL Fatal( SolverName, Message)285STOP286END IF287288BodyForce => GetBodyForce()289290! nodal values of SMB291NodeSMB=0.0_dp292NodeSMB(1:n) = ListGetReal( BodyForce, 'Top Surface Accumulation', n, NodeIndexes, GotIt)293IF (.NOT.GotIt) Then294WRITE(Message,'(A)') &295'No variable >Top Surface Accumulation< found in "Body Forces" default is 0'296CALL Info(SolverName,Message,level=6)297END IF298NodeSMB(1:n) = NodeSMB(1:n) + ListGetReal( BodyForce, 'Bottom Surface Accumulation', n, NodeIndexes, GotIt)299IF (.NOT.GotIt) Then300WRITE(Message,'(A)') &301'No variable >Top Surface Accumulation< found in "Body Forces" default is 0'302CALL Info(SolverName,Message,level=6)303END IF304305! nodal values of observed dhdt306NodeDHDT=0._dp307NodeDHDT(1:n) = ListGetReal( BodyForce, 'Observed dhdt', n, NodeIndexes, GotIt)308IF (.NOT.GotIt) Then309WRITE(Message,'(A)') &310'No variable >Observed dhdt< found in "Body Forces"; default is 0'311CALL Info(SolverName,Message,level=6)312END IF313314! nodal values of velocities315Velo=0._dp316Do i=1,DIM317Velo(i,1:n)=Velocity(DIM*(VeloPerm(NodeIndexes(1:n))-1)+i)318End DO319! get Nodal values of H320NodeH(1:n)=Zs(ZsPerm(NodeIndexes(1:n)))-Zb(ZbPerm(NodeIndexes(1:n)))321322!------------------------------------------------------------------------------323! Numerical integration324!------------------------------------------------------------------------------325IntegStuff = GaussPoints( Element )326327328DO i=1,IntegStuff % n329U = IntegStuff % u(i)330V = IntegStuff % v(i)331W = IntegStuff % w(i)332!------------------------------------------------------------------------------333! Basis function values & derivatives at the integration point334!------------------------------------------------------------------------------335stat = ElementInfo( Element,ElementNodes,U,V,W,SqrtElementMetric, &336Basis,dBasisdx )337338x = SUM( ElementNodes % x(1:n) * Basis(1:n) )339s = 1.0d0340341IF ( CurrentCoordinateSystem() /= Cartesian ) THEN342s = 2.0d0 * PI * x343END IF344s = s * SqrtElementMetric * IntegStuff % s(i)345346!get smb at IP347smb = SUM(NodeSMB(1:n) * Basis(1:n))348!observed dhdt at IP349dhdt = SUM(NodeDHDT(1:n) * Basis(1:n))350!h at IP351h = SUM(NodeH(1:n) * Basis(1:n))352353!u.grad H354ugrdh=0._dp355Do j=1,DIM356gradh(j) = SUM( dBasisdx(1:n,j)*NodeH(1:n) )357Vgauss(j) = SUM( Basis(1:n)*(Velo(j,1:n)) )358ugrdh=ugrdh+gradh(j)*Vgauss(j)359End do360361divu=0._dp362Do j=1,DIM363divu = divu + SUM( dBasisdx(1:n,j)*(Velo(j,1:n)))364End Do365366coeff=dhdt+ugrdh+h*divu-smb367368Cost=Cost+0.5*coeff*coeff*s369area=area+s370371! compute the derivatives (NOTE Cost=Lambda*Cost at the end for output372! reasons)373Costb=0.5*s*Lambda*2.0*coeff374375Do l=1,n376IF (ComputeDJDZb) &377DJDZb(DJDZbPerm(NodeIndexes(l)))=DJDZb(DJDZbPerm(NodeIndexes(l))) - & ! - car h=Zs-Zb378Costb*divu*Basis(l)379IF (ComputeDJDZs) &380DJDZs(DJDZsPerm(NodeIndexes(l)))=DJDZs(DJDZsPerm(NodeIndexes(l))) + & ! + car h=Zs-Zb381Costb*divu*Basis(l)382Do j=1,DIM383k=(VbPerm(NodeIndexes(l))-1)*c+j384Vb(k)=Vb(k) + Costb * Basis(l) * gradh(j) +&385Costb * h * dBasisdx(l,j)386387IF (ComputeDJDZb) &388DJDZb(DJDZbPerm(NodeIndexes(l)))=DJDZb(DJDZbPerm(NodeIndexes(l))) - & ! - car h=Zs-Zb389Costb*Vgauss(j)*dBasisdx(l,j)390IF (ComputeDJDZs) &391DJDZs(DJDZsPerm(NodeIndexes(l)))=DJDZs(DJDZsPerm(NodeIndexes(l))) + & ! + car h=Zs-Zb392Costb*Vgauss(j)*dBasisdx(l,j)393End do !j394End do !l395396End do !IPs397398End do !elements399400401402TimeVar => VariableGet( Solver % Mesh % Variables, 'Time' )403404IF (Parallel) THEN405CALL MPI_ALLREDUCE(Cost,Cost_S,1,&406MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)407408IF (Solver % Matrix % ParMatrix % ParEnv % MyPE == 0) then409OPEN (12, FILE=CostFile,POSITION='APPEND')410write(12,'(3(e13.5,2x))') TimeVar % Values(1),Cost_S,sqrt(2*Cost_S/area)411CLOSE(12)412End if413414Cost_S = Lambda * Cost_S415416CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )417IF (ASSOCIATED(CostVar)) THEN418IF (ResetCost) then419CostVar % Values(1)=Cost_S420Else421CostVar % Values(1)=CostVar % Values(1)+Cost_S422Endif423END IF424ELSE425OPEN (12, FILE=CostFile,POSITION='APPEND')426write(12,'(3(e13.5,2x))') TimeVar % Values(1),Cost,sqrt(2*Cost/area)427close(12)428429Cost = Lambda * Cost430431CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )432IF (ASSOCIATED(CostVar)) THEN433IF (ResetCost) then434CostVar % Values(1)=Cost435Else436CostVar % Values(1)=CostVar % Values(1)+Cost437Endif438END IF439END IF440441Return4424431000 format('#date,time,',a2,'/',a2,'/',a4,',',a2,':',a2,':',a2)4441001 format('#lambda,',e15.8)445!------------------------------------------------------------------------------446END SUBROUTINE AdjointSSA_CostFluxDivSolver447!------------------------------------------------------------------------------448! *****************************************************************************449450451