Path: blob/devel/elmerice/Solvers/CostSolver_Adjoint.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: f. Gillet-Chaulet (LGGE, Grenoble,France)25! * Email: [email protected]26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date:29! *30! *****************************************************************************31!Compute the Cost function of the Adjoint inverse Problem32! as Integral_Surface Node_Cost ds33! with a regularization as Sum_bedrock 0.5 Lambda (dBeta/dx)^234!35! Serial/Parallel 2D/3D36!37! Need :38! - Name of the Cost Variable39! - Lambda and Beta for regularization40! - define in the sif Name='surface' and Name='bed' in appropriate BC.41! - define in the sif in the surface BC:42! 'Adjoint Cost = Real ...' : The nodal value of the cost43! 'Adjoint Cost der 1 = Real ...' : The derivative of 'Adjoint Cost' w.r.t. u-velocity44! 'Adjoint Cost der 2 = Real ...' : The derivative of 'Adjoint Cost' w.r.t. v-velocity45! 'Adjoint Cost der 3 = Real ...' : The derivative of 'Adjoint Cost' w.r.t. w-velocity46!47! *****************************************************************************48SUBROUTINE CostSolver_Adjoint_init( Model,Solver,dt,TransientSimulation )49!------------------------------------------------------------------------------50USE DefUtils5152IMPLICIT NONE53!------------------------------------------------------------------------------54TYPE(Solver_t), TARGET :: Solver55TYPE(Model_t) :: Model56REAL(KIND=dp) :: dt57LOGICAL :: TransientSimulation58!------------------------------------------------------------------------------59! Local variables60!------------------------------------------------------------------------------61INTEGER :: NormInd, LineInd, i62LOGICAL :: GotIt, MarkFailed, AvoidFailed63CHARACTER(LEN=MAX_NAME_LEN) :: Name6465Name = ListGetString( Solver % Values, 'Equation',GotIt)66IF( .NOT. ListCheckPresent( Solver % Values,'Variable') ) THEN67CALL ListAddString( Solver % Values,'Variable',&68'-nooutput -global '//TRIM(Name)//'_var')69END IF70END71!******************************************************************************72SUBROUTINE CostSolver_Adjoint( Model,Solver,dt,TransientSimulation )73!------------------------------------------------------------------------------74!******************************************************************************75USE DefUtils76IMPLICIT NONE77!------------------------------------------------------------------------------78TYPE(Solver_t) :: Solver79TYPE(Model_t) :: Model8081REAL(KIND=dp) :: dt82LOGICAL :: TransientSimulation83!84CHARACTER(LEN=MAX_NAME_LEN), PARAMETER :: DefaultCostFile = 'CostOfT.dat'85CHARACTER(LEN=MAX_NAME_LEN) :: SolverName,CostFile86CHARACTER(LEN=MAX_NAME_LEN) :: BCName,CostSolName,VarSolName87TYPE(Element_t),POINTER :: Element88TYPE(Variable_t), POINTER :: TimeVar,CostVar,BetaSol89TYPE(Variable_t), POINTER :: VelocitybSol90TYPE(ValueList_t), POINTER :: BC,SolverParams91TYPE(Nodes_t) :: ElementNodes92TYPE(GaussIntegrationPoints_t) :: IntegStuff93REAL(KIND=dp), POINTER :: Beta(:)94REAL(KIND=dp), POINTER :: Vb(:)95INTEGER, POINTER :: NodeIndexes(:), BetaPerm(:)96INTEGER, POINTER :: VbPerm(:)97Logical :: Firsttime=.true.,Found,Parallel,stat,Gotit,UnFoundFatal=.TRUE.98integer :: i,j,k,l,t,n,NMAX,DIM,ierr,c99real(kind=dp) :: Cost,Cost_bed,Cost_surf,Cost_S,Cost_bed_S,Cost_surf_S,Lambda,Change100real(kind=dp),Save :: Oldf=0._dp101real(kind=dp) :: Bu,Bv,u,v,w,s,coeff,SqrtElementMetric,x102REAL(KIND=dp) :: NodeCost(Model % MaxElementNodes),Basis(Model % MaxElementNodes), dBasisdx(Model % MaxElementNodes,3)103REAL(KIND=dp) :: NodeCostb(Model % MaxElementNodes),NodeCost_der(3,Model %MaxElementNodes)104CHARACTER*10 :: date,temps105106save Firsttime,Parallel107save SolverName,CostSolName,VarSolName,Lambda,CostFile108save ElementNodes109110DIM = CoordinateSystemDimension()111112If (Firsttime) then113114WRITE(SolverName, '(A)') 'CostSolver_Adjoint'115116CALL Info(SolverName,'***********************',level=0)117CALL Info(SolverName,' This solver has been replaced by:',level=0)118CALL Info(SolverName,' Adjoint_CostContSolver ',level=0)119CALL Info(SolverName,' Adjoint_CostRegSolver ',level=0)120CALL Info(SolverName,' See documentation under: ',level=0)121CALL Info(SolverName,' elmerice/Solvers/Documentation ',level=0)122CALL Info(SolverName,'***********************',level=0)123CALL FATAL(SolverName,' Use new solver !!')124125!!!!!!! Check for parallel run126Parallel = (ParEnv % PEs > 1)127128!!!!!!!!!!! get Solver Variables129SolverParams => GetSolverParams()130131CostFile = ListGetString(Solver % Values,'Cost Filename',Found )132IF (.NOT. Found) CostFile = DefaultCostFile133CALL DATE_AND_TIME(date,temps)134If (Parallel) then135if (ParEnv % MyPe.EQ.0) then136OPEN (12, FILE=CostFile)137write(12,'(a1,a2,a1,a2,a1,a4,5x,a2,a1,a2,a1,a2)') '#',date(5:6),'/',date(7:8),'/',date(1:4), &138temps(1:2),':',temps(3:4),':',temps(5:6)139CLOSE(12)140End if141Else142OPEN (12, FILE=CostFile)143write(12,'(a1,a2,a1,a2,a1,a4,5x,a2,a1,a2,a1,a2)') '#',date(5:6),'/',date(7:8),'/',date(1:4), &144temps(1:2),':',temps(3:4),':',temps(5:6)145CLOSE(12)146End if147148149VarSolName = GetString( SolverParams,'Optimized Variable Name', Found)150IF(.NOT.Found) THEN151CALL WARN(SolverName,'Keyword >Optimized Variable Name< not found in section >Solver<')152CALL WARN(SolverName,'Taking default value >Beta<')153WRITE(VarSolName,'(A)') 'Beta'154END IF155156CostSolName = GetString( SolverParams,'Cost Variable Name', Found)157IF(.NOT.Found) THEN158CALL WARN(SolverName,'Keyword >Cost Variable Name< not found in section >Solver<')159CALL WARN(SolverName,'Taking default value >CostValue<')160WRITE(CostSolName,'(A)') 'CostValue'161END IF162163Lambda = GetConstReal( SolverParams,'Lambda', Found)164IF(.NOT.Found) THEN165CALL WARN(SolverName,'Keyword >Lambda< not found in section >Solver<')166CALL WARN(SolverName,'Taking default value Lambda=0.0')167Lambda = 0.0168End if169170!!! End of First visit171Firsttime=.false.172Endif173174BetaSol => VariableGet( Model % Mesh % Variables, VarSolName,UnFoundFatal=UnFoundFatal)175Beta => BetaSol % Values176BetaPerm => BetaSol % Perm177178VelocitybSol => VariableGet( Model % Mesh % Variables, 'Velocityb',UnFoundFatal=UnFoundFatal)179Vb => VelocitybSol % Values180VbPerm => VelocitybSol % Perm181c=DIM + 1 ! size of the velocity variable182IF (VelocitybSol % DOFs.NE.c) then183WRITE(Message,'(A,I1,A,I1)') &184'Variable Velocityb has ',VelocitybSol % DOFs,' DOFs, should be',c185CALL FATAL(SolverName,Message)186End If187Vb=0.0_dp188189190Cost=0._dp191Cost_surf=0._dp192Cost_bed=0._dp193DO t=1,Model % Mesh % NumberOfBoundaryElements194195Element => GetBoundaryElement(t)196197BC => GetBC()198IF ( .NOT. ASSOCIATED(BC) ) CYCLE199200BCName = ListGetString( BC,'Name', Found)201IF((BCName /= 'surface').AND.(BCName /= 'bed')) CYCLE202203CALL GetElementNodes( ElementNodes )204n = GetElementNOFNodes()205NodeIndexes => Element % NodeIndexes206207NodeCost=0.0_dp208IF (BCName == 'surface') THEN209NodeCost(1:n) = ListGetReal(BC, 'Adjoint Cost', n, NodeIndexes, GotIt,&210UnFoundFatal=UnFoundFatal)211NodeCost_der=0.0_dp212213NodeCost_der(1,1:n)=ListGetReal(BC, 'Adjoint Cost der 1', n, NodeIndexes, GotIt)214NodeCost_der(2,1:n)=ListGetReal(BC, 'Adjoint Cost der 2', n, NodeIndexes, GotIt)215NodeCost_der(3,1:n)=ListGetReal(BC, 'Adjoint Cost der 3', n, NodeIndexes, GotIt)216217Else IF (BCName == 'bed') Then218NodeCost(1:n)=Beta(BetaPerm(NodeIndexes(1:n)))219End if220221!------------------------------------------------------------------------------222! Numerical integration223!------------------------------------------------------------------------------224IntegStuff = GaussPoints( Element )225226227NodeCostb=0.0_dp228229DO i=1,IntegStuff % n230U = IntegStuff % u(i)231V = IntegStuff % v(i)232W = IntegStuff % w(i)233!------------------------------------------------------------------------------234! Basis function values & derivatives at the integration point235!------------------------------------------------------------------------------236stat = ElementInfo( Element,ElementNodes,U,V,W,SqrtElementMetric, &237Basis,dBasisdx )238239x = SUM( ElementNodes % x(1:n) * Basis(1:n) )240s = 1.0d0241242IF ( CurrentCoordinateSystem() /= Cartesian ) THEN243s = 2.0d0 * PI * x244END IF245s = s * SqrtElementMetric * IntegStuff % s(i)246247IF (BCName == 'surface') Then248coeff = SUM(NodeCost(1:n) * Basis(1:n))249Cost_surf=Cost_surf+coeff*s250NodeCostb(1:n)=NodeCostb(1:n) + s*Basis(1:n)251else IF (BCName == 'bed') Then252coeff = SUM(NodeCost(1:n) * dBasisdx(1:n,1))253coeff = coeff * coeff254IF (DIM.eq.3) then255coeff=coeff+ &256SUM(NodeCost(1:n)*dBasisdx(1:n,2))*SUM(NodeCost(1:n) * dBasisdx(1:n,2))257END IF258Cost_bed=Cost_bed+coeff*s259else260coeff = 0.0261End if262263End do264IF (BCName == 'surface') Then265c=DIM + 1 ! size of the velocity variable266Do j=1,n267Do i=1,DIM268k=(VbPerm(NodeIndexes(j))-1)*c+i269Vb(k)=Vb(k)+NodeCostb(j)*NodeCost_der(i,j)270End Do271End Do272END if273End do274275Cost=Cost_surf+0.5*Lambda*Cost_bed276277TimeVar => VariableGet( Model % Mesh % Variables, 'Time' )278279IF (Parallel) THEN280CALL MPI_ALLREDUCE(Cost,Cost_S,1,&281MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)282CALL MPI_ALLREDUCE(Cost_surf,Cost_surf_S,1,&283MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)284CALL MPI_ALLREDUCE(Cost_bed,Cost_bed_S,1,&285MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)286CostVar => VariableGet( Model % Mesh % Variables, CostSolName )287IF (ASSOCIATED(CostVar)) THEN288CostVar % Values(1)=Cost_S289END IF290IF (ParEnv % MyPE == 0) then291OPEN (12, FILE=CostFile,POSITION='APPEND')292write(12,'(e13.5,2x,e15.8,2x,e15.8,2x,e15.8)') TimeVar % Values(1),Cost_S,Cost_surf_S,Cost_bed_S293CLOSE(12)294End if295ELSE296CostVar => VariableGet( Model % Mesh % Variables, CostSolName )297IF (ASSOCIATED(CostVar)) THEN298CostVar % Values(1)=Cost299END IF300OPEN (12, FILE=CostFile,POSITION='APPEND')301write(12,'(e13.5,2x,e15.8,2x,e15.8,2x,e15.8)') TimeVar % Values(1),Cost,Cost_surf,Cost_bed302close(12)303Cost_S=Cost304END IF305306Solver % Variable % Values(1)=Cost_S307Solver % Variable % Norm = Cost_S308IF (SIZE(Solver%Variable % Values) == Solver%Variable % DOFs) THEN309!! MIMIC COMPUTE CHANGE STYLE310Change=2.*(Cost_S-Oldf)/(Cost_S+Oldf)311Change=abs(Change)312WRITE( Message, '(a,g15.8,g15.8,a)') &313'SS (ITER=1) (NRM,RELC): (',Cost_S, Change,&314' ) :: Cost'315CALL Info( 'ComputeChange', Message, Level=3 )316Oldf=Cost_S317ENDIF318319Return320!------------------------------------------------------------------------------321END SUBROUTINE CostSolver_Adjoint322!------------------------------------------------------------------------------323! *****************************************************************************324325326