Path: blob/devel/elmerice/Solvers/Covarianceutils/BackgroundErrorCostSolver.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! *25! * Authors: F. Gillet-Chaulet26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date: 24/06/202429! *30! *****************************************************************************31!***********************************************************************************************32! Compute a cost function from a background as Cost=0.5 * (x-x^b). B^-1 .(x-x^b)33! x is the optimized variable; x^b the background34! B^1 is the background error covariance matrix:35! here B= S . C . S36! with:37! - S is a diagonal matrix with the standard deviation (assumed constant for now)38! - C is a correlation matrix39! Available choices for C "Covariance type = String ..."40! - diagonal; i.e. C=I and B=S^2 is diagonal with the variances41! - "full matrix" : C is computed from standard correlation42! functions and inverted using Lapack routines43! - "diffusion operator" : C is approximated with the diffusion operator approach44! Current limitations :45! - Serial for the full-matrix approach46!47! Rq.48! - IF x has DOFs > 1 we apply independently the same B^-149! - IF 2 instances of the same solver are used in the same .sif make a50! copy of the lib as things are initialized and saved....51!52! TODO:53! - add mandatory keywords at init, e.g. variable, ...54!55!***********************************************************************************************56SUBROUTINE BackgroundErrorCostSolver( Model,Solver,dt,TransientSimulation )57!***********************************************************************************************58USE GeneralUtils59USE CovarianceUtils60IMPLICIT NONE61!------------------------------------------------------------------------------62TYPE(Solver_t) :: Solver6364TYPE(Model_t) :: Model65REAL(KIND=dp) :: dt66LOGICAL :: TransientSimulation6768TYPE(ValueList_t), POINTER :: SolverParams6970TYPE(Variable_t), POINTER :: Var,Var_b,DJDVariable,CostVar71REAL(KIND=dp), POINTER :: Values(:), Values_b(:),DJDValues(:)72INTEGER, POINTER :: Perm(:),Perm_b(:),DJDPerm(:)73CHARACTER(LEN=MAX_NAME_LEN) :: Varname,VarbName,GradVarName,CostName74INTEGER :: DOFs7576INTEGER :: i,j,k,l,t77INTEGER :: ierr78INTEGER :: MeshDim7980TYPE(Solver_t), POINTER, SAVE :: MSolver,KMSolver81REAL(kind=dp),allocatable,save :: aap(:) ! matrix in packed format82REAL(kind=dp),allocatable,save :: x(:),y(:)83REAL(kind=dp),allocatable,save :: One(:)84REAL(kind=dp) :: Cost,Cost_S8586INTEGER,SAVE :: nn87INTEGER, ALLOCATABLE, SAVE :: ActiveNodes(:),InvPerm(:)88INTEGER,SAVE :: PbDim8990CHARACTER(LEN=MAX_NAME_LEN),SAVE :: CovType91REAL(kind=dp),SAVE :: std92CHARACTER(LEN=MAX_NAME_LEN) :: Ctype93REAL(kind=dp) :: CRange,Cm94INTEGER :: p95REAL(kind=dp) :: sigma296INTEGER :: Op9798LOGICAL, SAVE :: Firsttime=.TRUE.99LOGICAL :: Reset100LOGICAL :: Found101Logical :: Parallel102103CHARACTER(LEN=MAX_NAME_LEN) :: SolverName="CostCov"104CHARACTER(LEN=MAX_NAME_LEN) :: CostFile105106! check Parallel/Serial107Parallel=(ParEnv % PEs > 1)108109110SolverParams => GetSolverParams()111112VarName = ListGetString(SolverParams,"Variable name",UnFoundFatal=.TRUE.)113GradVarName = ListGetString(SolverParams,"Gradient Variable name",UnFoundFatal=.TRUE.)114VarbName = ListGetString(SolverParams,"Background Variable name",UnFoundFatal=.TRUE.)115CostName = ListGetString(SolverParams,"Cost Variable name",UnFoundFatal=.TRUE.)116117CostFile = ListGetString(SolverParams,'Cost Filename',UnFoundFatal=.TRUE. )118119! get handles on the variables120Reset = GetLogical( SolverParams,'Reset Cost Value', Found)121IF(.NOT.Found) Reset=.True.122123Var => VariableGet( Solver % Mesh % Variables,TRIM(VarName), UnFoundFatal=.TRUE. )124Values => Var % Values125Perm => Var % Perm126DOFs = Var % DOFs127128Var_b => VariableGet(Solver % Mesh % Variables,TRIM(VarbName),UnFoundFatal=.TRUE.)129Values_b => Var_b % Values130Perm_b => Var_b % Perm131IF (Var_b % DOFs .NE. DOFs) &132CALL FATAL(SolverName,"Var and Var_b have different dofs")133134DJDVariable => VariableGet( Solver % Mesh % Variables,TRIM(GradVarName), UnFoundFatal=.TRUE. )135DJDValues => DJDVariable % Values136DJDPerm => DJDVariable % Perm137IF (DJDVariable % DOFs .NE. DOFs) &138CALL FATAL(SolverName,"Var and grad have different dofs")139IF (Reset) DJDValues=0.0_dp140141CostVar => VariableGet( Solver % Mesh % Variables,TRIM(CostName),UnFoundFatal=.TRUE.)142IF (Reset) CostVar % Values=0.0_dp143144!! some initialisation145IF (Firsttime) THEN146CALL GetActiveNodesSet(Solver,nn,ActiveNodes,InvPerm,PbDim)147148!! The covariance type149CovType = ListGetString(SolverParams,"Covariance type",UnFoundFatal=.TRUE.)150151std = ListGetConstReal(SolverParams,"standard deviation",UnFoundFatal=.TRUE.)152153IF (ParEnv%MyPE.EQ.0) THEN154open(10,file=TRIM(CostFile))155write(10,*) '# Covariance type: ',TRIM(CovType)156write(10,*) '# standard deviation: ',std157END IF158159SELECT CASE (CovType)160161CASE('diagonal')162CALL INFO(SolverName,"Using diagonal covariance",level=3)163164CASE('full matrix')165CALL INFO(SolverName,"Using full matrix covariance",level=3)166167Op=3168ALLOCATE(aap(nn*(nn+1)/2))169CALL CovarianceInit(Solver,nn,InvPerm,aap,Op,PbDim)170171Ctype = ListGetString(SolverParams,"correlation type",UnFoundFatal=.TRUE.)172IF (ParEnv%MyPE.EQ.0) &173write(10,*) '# Correlation type: ',TRIM(Ctype)174175Crange = ListGetConstReal(SolverParams,"correlation range", UnFoundFatal=.TRUE.)176177IF (Ctype == 'maternp') THEN178p = ListGetInteger(SolverParams,"MaternP polynomial order",UnFoundFatal=.TRUE.)179IF (ParEnv%MyPE.EQ.0) &180write(10,*) '# range, exponent: ',Crange,p181ELSE IF (Ctype == 'materni') THEN182p = ListGetInteger(SolverParams,"MaternI order",UnFoundFatal=.TRUE.)183IF (ParEnv%MyPE.EQ.0) &184write(10,*) '# range, exponent: ',Crange,p185ELSE186IF (ParEnv%MyPE.EQ.0) &187write(10,*) '# range:',Crange188END IF189190CASE('diffusion operator')191CALL INFO(SolverName,"Using diffusion operator covariance",level=3)192193CALL CovarianceInit(Solver,MSolver,KMSolver)194195Cm = ListGetInteger(SolverParams,"Matern exponent m",UnFoundFatal=.TRUE.)196Crange = ListGetConstReal(SolverParams,"correlation range", UnFoundFatal=.TRUE.)197198IF (ParEnv%MyPE.EQ.0) &199write(10,*) '# range, exponent: ',Crange,Cm200201CASE DEFAULT202CALL FATAL(SolverName,"Covariance type not known")203204END SELECT205206IF (ParEnv%MyPE.EQ.0) &207close(10)208209allocate(x(nn),y(nn),One(nn))210! normalisation vector; usefull for parallel211One=1._dp212IF (Parallel) CALL ParallelSumVector(Solver%Matrix, One)213214Firsttime=.FALSE.215END IF216217Cost=0._dp218DO i=1,DOFS219220!(x-x_b)221x(Solver%Variable%Perm(ActiveNodes(1:nn))) = Values(DOFs*(Perm(ActiveNodes(1:nn))-1)+i)- &222Values_b(DOFs*(Perm_b(ActiveNodes(1:nn))-1)+i)223224SELECT CASE (CovType)225226CASE('diagonal')227sigma2=std**2228y(1:nn) = x(1:nn)/sigma2229230CASE('full matrix')231CALL InvCovarianceVectorMultiply(Solver,nn,aap,x,y)232233CASE('diffusion operator')234! y = SIGMA^1 C^1 SIGMA^1 . (x-x_b)235CALL InvCovarianceVectorMultiply(Solver,MSolver,KMSolver,nn,x,y)236237END SELECT238239! gradient = SIGMA^1 C^1 SIGMA^1 . (x-x_b)240! gradients are gathered in the optimisation step; so also normalize by One.241DJDValues(DOFS*(DJDPerm(ActiveNodes(1:nn))-1)+i)=DJDValues(DOFS*(DJDPerm(ActiveNodes(1:nn))-1)+i)+ &242y(Solver%Variable%Perm(ActiveNodes(1:nn)))/One(Solver%Variable%Perm(ActiveNodes(1:nn)))243244245! 1/2 (x-x_b) . SIGMA^1 C^1 SIGMA^1 . (x-x_b)246! normalisation by one insure that shared nodes are not counted twice...247Cost=Cost+0.5*SUM(x(1:nn)*y(1:nn)/One(1:nn))248249END DO250251IF (Parallel) THEN252CALL MPI_ALLREDUCE(Cost,Cost_S,1,&253MPI_DOUBLE_PRECISION,MPI_SUM,ELMER_COMM_WORLD,ierr)254CostVar % Values(1)=CostVar % Values(1)+Cost_S255IF (ParEnv % MyPE == 0) then256OPEN (10, FILE=CostFile,POSITION='APPEND')257write(10,'(2(ES20.11E3))') GetTime(),Cost_S258CLOSE(10)259End if260ELSE261CostVar % Values(1)=CostVar % Values(1)+Cost262open(10,file=TRIM(CostFile),position='append')263write(10,'(2(ES20.11E3))') GetTime(),Cost264close(10)265END IF266267END SUBROUTINE BackgroundErrorCostSolver268269270