Path: blob/devel/elmerice/Solvers/AdjointSSA/AdjointSSA_CostRegSolver.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! *****************************************************************************31! *****************************************************************************32SUBROUTINE AdjointSSA_CostRegSolver( Model,Solver,dt,TransientSimulation )33!------------------------------------------------------------------------------34!******************************************************************************35!36! Compute a regularisation term for SSA inverse problems and update the37! gradient of the cost function with respect to the regularized variable.38!39! Regularisation by default is: int_{Pb dimension} 0.5 * (d(var)/dx)**240! A priori regularisation can also be used ( A priori Regularisation=True) :41! int_{Pb dimension} 0.5 *(1/sigma**2)*(var-var{a_priori})**242!43! OUTPUT are : J and DJDvar44!45!46! !!!!! BE careful it will reset Cost and DJ to 0 by default !!!!47! !!! If other cost and gradient are computed before (i.e. from the adjoint pb,48! use "<Reset Cost Value> = False" to add cost and gradient to previously computed values !!!49!50!51! Required Sif parameters are:52!53! In the solver section:54! Problem Dimension=Integer (default:coordinate system dimension),55! Cost Filename=File (default: CostOfT.dat),56! Optimized Variable Name= String (default='Beta'),57! Gradient Variable Name= String (default = 'DJDBeta'),58! Cost Variable Name= String (default='Cost Value'),59! Lambda= Real (default 1.0),60! Reset Cost Value= Logical (default = True),61! A priori Regularisation= Logical (default = .False.),62!63! In Body Force section:64! <VarSolName> a priori value = Real (default =0.0),65! <VarSolName> variance = real (default=1.0)66!67!68!******************************************************************************69USE DefUtils70IMPLICIT NONE71!------------------------------------------------------------------------------72TYPE(Solver_t) :: Solver73TYPE(Model_t) :: Model7475REAL(KIND=dp) :: dt76LOGICAL :: TransientSimulation77!78CHARACTER(LEN=MAX_NAME_LEN), PARAMETER :: DefaultCostFile = 'CostOfT.dat'79CHARACTER(LEN=MAX_NAME_LEN) :: SolverName,CostFile80CHARACTER(LEN=MAX_NAME_LEN) :: CostSolName,VarSolName,GradSolName,varname81TYPE(Element_t),POINTER :: Element82TYPE(Variable_t), POINTER :: TimeVar,CostVar8384TYPE(Variable_t), POINTER :: Variable,DJDVariable85REAL(KIND=dp), POINTER :: Values(:),DJDValues(:)86INTEGER, POINTER :: Perm(:),DJDPerm(:)8788TYPE(ValueList_t), POINTER :: SolverParams,BodyForce89TYPE(Nodes_t) :: ElementNodes90TYPE(GaussIntegrationPoints_t) :: IntegStuff91INTEGER, POINTER :: NodeIndexes(:)9293Logical :: Firsttime=.true.,Found,Parallel,stat,Gotit94integer :: i,j,k,l,t,n,NMAX,DIM,ierr,c9596real(kind=dp) :: Cost,Cost_S,Lambda97real(kind=dp) :: u,v,w,s,coeff_reg,SqrtElementMetric,x9899REAL(KIND=dp),dimension(:),allocatable,SAVE :: NodeAp,NodeRMS,NodeValues,NodalRegb100REAL(KIND=dp) :: Basis(Model % MaxElementNodes), dBasisdx(Model % MaxElementNodes,3)101REAL(KIND=dp) :: IPerr,IPvar102103LOGICAL :: Apriori,Reset104105CHARACTER*10 :: date,temps106107save Firsttime,Parallel108save SolverName,CostSolName,VarSolName,Lambda,CostFile109save ElementNodes110111WRITE(SolverName, '(A)') 'CostSolver_Regular'112113CALL Info(SolverName,'***********************',level=0)114CALL Info(SolverName,' This solver has been replaced by:',level=0)115CALL Info(SolverName,' Adjoint_CostRegSolver ',level=0)116CALL Info(SolverName,' See documentation under: ',level=0)117CALL Info(SolverName,' elmerice/Solvers/Documentation ',level=0)118CALL Info(SolverName,'***********************',level=0)119CALL FATAL(SolverName,' Use new solver !!')120121SolverParams => GetSolverParams()122123!! Dimension of the pb; ie with SSA we can be 1D or 2D on a 2D mesh, or 2D on a 3D mesh124DIM=GetInteger(SolverParams ,'Problem Dimension',Found)125If (.NOT.Found) then126CALL WARN(SolverName,'Keyword >Problem Dimension< not found, assume DIM = CoordinateSystemDimension()')127DIM = CoordinateSystemDimension()128Endif129130! get some needed solver parameters131!! Cost File for Output132CostFile = ListGetString(Solver % Values,'Cost Filename',Found )133IF (.NOT. Found) CostFile = DefaultCostFile134135!! Name of the variable to regularise136VarSolName = GetString( SolverParams,'Optimized Variable Name', Found)137IF(.NOT.Found) THEN138CALL WARN(SolverName,'Keyword >Optimized Variable Name< not found in section >Solver<')139CALL WARN(SolverName,'Taking default value >Beta<')140WRITE(VarSolName,'(A)') 'Beta'141END IF142143!! Name of the variable to regularise144GradSolName = GetString( SolverParams,'Gradient Variable Name', Found)145IF(.NOT.Found) THEN146CALL WARN(SolverName,'Keyword >Optimized Variable Name< not found in section >Solver<')147CALL WARN(SolverName,'Taking default value >DJDBeta<')148WRITE(GradSolName,'(A)') 'DJDBeta'149END IF150151152!! Name of the variable with the cost function153CostSolName = GetString( SolverParams,'Cost Variable Name', Found)154IF(.NOT.Found) THEN155CALL WARN(SolverName,'Keyword >Cost Variable Name< not found in section >Solver<')156CALL WARN(SolverName,'Taking default value >CostValue<')157WRITE(CostSolName,'(A)') 'CostValue'158END IF159160!! Optional weighting term161Lambda = GetConstReal( SolverParams,'Lambda', Found)162IF(.NOT.Found) THEN163CALL WARN(SolverName,'Keyword >Lambda< not found in section >Solver<')164CALL WARN(SolverName,'Taking default value Lambda=1.0')165Lambda = 1.0166End if167168!! Do we need to reset cost and DJDVar to 0? Default YES169Reset = GetLogical( SolverParams,'Reset Cost Value', Found)170IF(.NOT.Found) Reset=.True.171172!! What type of regularistaion ? Default penalise 1st derivative173Apriori = GetLogical( SolverParams,'A priori Regularisation', Found)174IF(.NOT.Found) Apriori=.False.175176!!! SOME INITIALISATION AT FIRST TIME177If (Firsttime) then178N = model % MaxElementNodes179allocate(ElementNodes % x(N), ElementNodes % y(N), ElementNodes % z(N))180allocate(NodeAp(N),NodeRMS(N),NodeValues(N),NodalRegb(N))181182!!!!!!! Check for parallel run183Parallel = .FALSE.184IF ( ASSOCIATED( Solver % Matrix % ParMatrix ) ) THEN185IF ( Solver % Matrix % ParMatrix % ParEnv % PEs > 1 ) THEN186Parallel = .TRUE.187END IF188END IF189190!!!!!!!!!!! initiate Cost File191192CALL DATE_AND_TIME(date,temps)193If (Parallel) then194if (ParEnv % MyPe.EQ.0) then195OPEN (12, FILE=CostFile)196write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)197write(12,1001) Lambda198write(12,'(A)') '# iter, Jreg'199CLOSE(12)200End if201Else202OPEN (12, FILE=CostFile)203write(12,1000) date(5:6),date(7:8),date(1:4),temps(1:2),temps(3:4),temps(5:6)204write(12,1001) Lambda205write(12,'(A)') '# iter, Jreg'206CLOSE(12)207End if208209!!! End of First visit210Firsttime=.false.211Endif212!!!! INITIALISATION DONE213214Variable => VariableGet( Solver % Mesh % Variables, VarSolName )215IF ( ASSOCIATED( Variable ) ) THEN216Values => Variable % Values217Perm => Variable % Perm218ELSE219WRITE(Message,'(A,A,A)') &220'No variable >',VarSolName,' < found'221CALL FATAL(SolverName,Message)222END IF223DJDVariable => VariableGet( Solver % Mesh % Variables, GradSolName )224IF ( ASSOCIATED( DJDVariable ) ) THEN225DJDValues => DJDVariable % Values226DJDPerm => DJDVariable % Perm227ELSE228WRITE(Message,'(A,A,A)') &229'No variable >',VarSolName,' < found'230CALL FATAL(SolverName,Message)231END IF232IF (Reset) DJDValues=0.0_dp233234235Cost=0._dp236237DO t=1,Solver % NumberOfActiveElements238Element => GetActiveElement(t)239IF (CheckPassiveElement(Element)) THEN240!PRINT *,ParEnv%myPe,'REG: PASSIVE ELEEMNT'241CYCLE242END IF243IF (ParEnv % myPe .NE. Element % partIndex) CYCLE244n = GetElementNOFNodes()245246NodeIndexes => Element % NodeIndexes247248! set coords of highest occurring dimension to zero (to get correct path element)249!-------------------------------------------------------------------------------250ElementNodes % x(1:n) = Solver % Mesh % Nodes % x(NodeIndexes)251IF (DIM == 1) THEN !1D SSA252ElementNodes % y(1:n) = 0.0_dp253ElementNodes % z(1:n) = 0.0_dp254ELSE IF (DIM == 2) THEN !2D SSA255ElementNodes % y(1:n) = Solver % Mesh % Nodes % y(NodeIndexes)256ElementNodes % z(1:n) = 0.0_dp257ELSE258WRITE(Message,'(a,i1,a)')&259'It is not possible to compute SSA problems with DOFs=',&260DIM, ' . Aborting'261CALL Fatal( SolverName, Message)262STOP263END IF264265! Compute inetgrated cost266267268IF (Apriori) then269BodyForce => GetBodyForce()270write(varname,'(A,A)') trim(VarSolName),' a priori value'271NodeAp(1:n) = 0._dp272NodeAp(1:n) = ListGetReal( BodyForce, trim(varname), n, NodeIndexes, GotIt)273IF (.NOT.GotIt) Then274WRITE(Message,'(A,A,A)') &275'No variable >',trim(varname),'< found in "Body Forces" default is 0'276CALL Info(SolverName,Message,level=6)277END IF278write(varname,'(A,A)') trim(VarSolName),' variance'279NodeRMS(1:n)=ListGetReal( BodyForce, trim(varname), n, NodeIndexes, GotIt)280IF (.NOT.GotIt) Then281WRITE(Message,'(A,A,A)') &282'No variable >',trim(varname),'< found in "Body Forces" default is 1'283CALL Info(SolverName,Message,level=6)284NodeRMS=1.0_dp285END IF286END IF287288! Nodal values of the variable289NodeValues(1:n)=Values(Perm(NodeIndexes(1:n)))290291!------------------------------------------------------------------------------292! Numerical integration293!------------------------------------------------------------------------------294295NodalRegb = 0.0_dp296297IntegStuff = GaussPoints( Element )298299DO i=1,IntegStuff % n300U = IntegStuff % u(i)301V = IntegStuff % v(i)302W = IntegStuff % w(i)303!------------------------------------------------------------------------------304! Basis function values & derivatives at the integration point305!------------------------------------------------------------------------------306stat = ElementInfo( Element,ElementNodes,U,V,W,SqrtElementMetric, &307Basis,dBasisdx )308309x = SUM( ElementNodes % x(1:n) * Basis(1:n) )310s = 1.0d0311312IF ( CurrentCoordinateSystem() /= Cartesian ) THEN313s = 2.0d0 * PI * x314END IF315s = s * SqrtElementMetric * IntegStuff % s(i)316317IF (Apriori) then318IPerr = SUM((NodeValues(1:n)-NodeAp(1:n))*Basis(1:n))319IPvar = SUM(NodeRMS(1:n)*Basis(1:n))320coeff_reg=IPerr/IPvar321coeff_reg = coeff_reg*coeff_reg322323!Now compute the derivative324NodalRegb(1:n)=NodalRegb(1:n)+&325s*Lambda*IPerr*Basis(1:n)/(IPVar**2.0)326Else327coeff_reg = SUM(NodeValues(1:n) * dBasisdx(1:n,1))328coeff_reg = coeff_reg*coeff_reg329IF (DIM.eq.2) then330coeff_reg=coeff_reg+ &331SUM(NodeValues(1:n)*dBasisdx(1:n,2))*SUM(NodeValues(1:n) * dBasisdx(1:n,2))332END IF333334!Now compute the derivative335NodalRegb(1:n)=NodalRegb(1:n)+&336s*Lambda*(SUM(dBasisdx(1:n,1)*NodeValues(1:n))*dBasisdx(1:n,1))337IF (DIM.eq.2) then338NodalRegb(1:n)=NodalRegb(1:n)+&339s*Lambda*(SUM(dBasisdx(1:n,2)*NodeValues(1:n))*dBasisdx(1:n,2))340End if341Endif342343344Cost=Cost+0.5*coeff_reg*s345346End do !IP347348DJDValues(DJDPerm(NodeIndexes(1:n)))=DJDValues(DJDPerm(NodeIndexes(1:n))) + NodalRegb(1:n)349350End do !Elements351352TimeVar => VariableGet( Solver % Mesh % Variables, 'Time' )353354IF (Parallel) THEN355CALL MPI_ALLREDUCE(Cost,Cost_S,1,&356MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)357CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )358IF (ASSOCIATED(CostVar)) THEN359IF (Reset) then360CostVar % Values(1)=Lambda*Cost_S361Else362CostVar % Values(1)=CostVar % Values(1)+Lambda*Cost_S363Endif364END IF365IF (Solver % Matrix % ParMatrix % ParEnv % MyPE == 0) then366OPEN (12, FILE=CostFile,POSITION='APPEND')367write(12,'(e13.5,2x,e15.8)') TimeVar % Values(1),Cost_S368CLOSE(12)369End if370ELSE371CostVar => VariableGet( Solver % Mesh % Variables, CostSolName )372IF (ASSOCIATED(CostVar)) THEN373IF (Reset) then374CostVar % Values(1)=Lambda*Cost375Else376CostVar % Values(1)=CostVar % Values(1)+Lambda*Cost377Endif378END IF379OPEN (12, FILE=CostFile,POSITION='APPEND')380write(12,'(e13.5,2x,e15.8)') TimeVar % Values(1),Cost381close(12)382END IF383384Return3853861000 format('#date,time,',a2,'/',a2,'/',a4,',',a2,':',a2,':',a2)3871001 format('#lambda,',e15.8)388!------------------------------------------------------------------------------389END SUBROUTINE AdjointSSA_CostRegSolver390!------------------------------------------------------------------------------391! *****************************************************************************392393394