Path: blob/devel/elmerice/Solvers/AdjointSSA/AdjointSSA_AdjointSolver.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:25! * Email:26! * Web: http://elmerice.elmerfem.org27! *28! * Original Date:29! *30! *****************************************************************************31!------------------------------------------------------------------------------32SUBROUTINE AdjointSSA_AdjointSolver( Model,Solver,dt,TransientSimulation )33!------------------------------------------------------------------------------34!> Compute the adjoint state of the SSA equations.35!36! OUTPUT is : Solver % Variable the adjoint state of the SSA problem37!38! INPUT PARAMETERS are:39!40! In solver section:41! Flow Solution Equation Name = String (default 'SSA')42!43! Variables44! Velocityb (forcing for the adjoint pb)45!46!******************************************************************************47! ARGUMENTS:48!49! TYPE(Model_t) :: Model,50! INPUT: All model information (mesh, materials, BCs, etc...)51!52! TYPE(Solver_t) :: Solver53! INPUT: Linear & nonlinear equation solver options54!55! REAL(KIND=dp) :: dt,56! INPUT: Timestep size for time dependent simulations57!58! LOGICAL :: TransientSimulation59! INPUT: Steady state or transient simulation60!61!******************************************************************************62USE DefUtils63IMPLICIT NONE64!------------------------------------------------------------------------------65TYPE(Solver_t) :: Solver66TYPE(Model_t) :: Model67REAL(KIND=dp) :: dt68LOGICAL :: TransientSimulation69!------------------------------------------------------------------------------70! Local variables71!------------------------------------------------------------------------------72TYPE(Solver_t),Pointer :: NSSolver73TYPE(Matrix_t),POINTER :: InitMat,TransMat,StiffMatrix74TYPE(ValueList_t),POINTER :: BC,BF,SolverParams75TYPE(ValueListEntry_t),POINTER :: NormalTangential,NormalTangentialC76character(LEN=MAX_NAME_LEN),SAVE :: NormalTangentialName,NormalTangentialNameb77LOGICAL :: AnyNT78TYPE(Element_t),POINTER :: Element79TYPE(Variable_t), POINTER :: Sol80TYPE(Variable_t), POINTER :: VelocitybSol81REAL(KIND=dp), POINTER :: Vb(:)82INTEGER, POINTER :: VbPerm(:)83REAL(KIND=dp),POINTER :: ForceVector(:)84integer :: i,j,k,t,n,NSDOFs85INTEGER :: kmax86Logical :: Gotit87INTEGER, POINTER :: NodeIndexes(:),Perm(:)88integer :: p,q,dim,c,m89Real(KIND=dp) :: Unorm90Real(KIND=dp) :: RotVec(3)91character(LEN=MAX_NAME_LEN) :: SolName,NSVarName92LOGICAL :: Conditional,CheckNT93REAL(KIND=dp),ALLOCATABLE,SAVE :: Condition(:)9495INTEGER, POINTER,SAVE :: BoundaryReorder(:)=> NULL()96INTEGER,SAVE :: NormalTangentialNOFNodes97REAL(KIND=dp), POINTER :: BoundaryNormals(:,:)=> NULL(), &98BoundaryTangent1(:,:)=> NULL(), &99BoundaryTangent2(:,:)=> NULL()100101CHARACTER(LEN=MAX_NAME_LEN),SAVE :: SolverName="Adjoint Solver"102INTEGER, SAVE :: SolverInd103LOGICAL, SAVE :: Firsttime=.TRUE.104105106CALL Info(SolverName,'***********************',level=0)107CALL Info(SolverName,' This solver has been replaced by:',level=0)108CALL Info(SolverName,' Adjoint_LinearSolver ',level=0)109CALL Info(SolverName,' See documentation under: ',level=0)110CALL Info(SolverName,' elmerice/Solvers/Documentation ',level=0)111CALL Info(SolverName,'***********************',level=0)112CALL FATAL(SolverName,' Use new solver !!')113114115DIM = CoordinateSystemDimension()116117StiffMatrix => Solver % Matrix118ForceVector => StiffMatrix % RHS119120Sol => Solver % Variable121NSDOFs = Sol % DOFs122Perm => Sol % Perm123124! IF DIM = 3 and NSDOFs=2; Normal-Tangential can not be used => trick temporary set125! Model Dimension to 2126IF (DIM.eq.(NSDOFs+1)) CurrentModel % Dimension = NSDOFs127128129IF (Firsttime) then130Firsttime=.False.131132N = Model % MaxElementNodes133ALLOCATE(Condition(N))134135SolverParams => GetSolverParams(Solver)136SolName = ListGetString( SolverParams,'Flow Solution Equation Name',GotIt)137IF (.NOT.Gotit) Then138CALL WARN(SolverName,'Keyword >Flow Solution Equation Name< not found in SolverParams')139CALL WARN(SolverName,'Taking default value >SSA<')140WRITE(SolName,'(A)') 'SSA'141Endif142DO i=1,Model % NumberOfSolvers143if (TRIM(SolName) == ListGetString(Model % Solvers(i) % Values, 'Equation')) exit144End do145if (i.eq.(Model % NumberOfSolvers+1)) &146CALL FATAL(SolverName,'Could not find Equation Name ' // TRIM(SolName))147148SolverInd=i149NSSolver => Model % Solvers(SolverInd)150151!# Check For NT boundaries152NormalTangentialName = 'normal-tangential'153IF ( SEQL(NSSolver % Variable % Name, 'flow solution') ) THEN154NormalTangentialName = TRIM(NormalTangentialName) // ' velocity'155ELSE156NormalTangentialName = TRIM(NormalTangentialName) // ' ' // &157GetVarName(NSSolver % Variable)158END IF159160AnyNT = ListGetLogicalAnyBC( Model, TRIM(NormalTangentialName) )161IF (AnyNT) THEN162163!# We will stay in NT to impose dirichlet conditions164CALL ListAddLogical(SolverParams,'Back Rotate N-T Solution',.FALSE.)165166!# !!! Has to be in lower case to copy item167NormalTangentialNameb='normal-tangential' // ' ' // GetVarName(Solver % Variable)168169DO i=1,Model % NumberOfBCs170BC => Model % BCs(i) % Values171NormalTangential => ListFind( BC , NormalTangentialName , GotIt )172IF (.NOT.Gotit) CYCLE173174WRITE(Message,'(A,I0)') 'Copy Normal-Tangential keyword in BC ',i175CALL Info(SolverName,Message,level=4)176CALL ListCopyItem( NormalTangential, BC, NormalTangentialNameb)177178NormalTangentialC => ListFind( BC , TRIM(NormalTangentialName) // ' condition' , GotIt )179IF (.NOT.Gotit) CYCLE180181WRITE(Message,'(A,I0)') 'Copy Normal-Tangential Condition keyword in BC ',i182CALL Info(SolverName,Message,level=4)183CALL ListCopyItem( NormalTangentialC, BC, TRIM(NormalTangentialNameb) // ' condition' )184END DO185186CALL CheckNormalTangentialBoundary( Model, TRIM(NormalTangentialNameb), &187NormalTangentialNOFNodes, BoundaryReorder, &188BoundaryNormals, BoundaryTangent1, BoundaryTangent2, dim )189190END IF191END IF192193194NSSolver => Model % Solvers(SolverInd)195196IF ( SEQL(NSSolver % Variable % Name, 'flow solution') ) THEN197NSVarName = 'Velocity'198ELSE199NSVarName = GetVarName(NSSolver % Variable)200END IF201202CALL DefaultInitialize()203204InitMat => AllocateMatrix()205InitMat % NumberOfRows = NSSolver % Matrix % NumberOfRows206InitMat % Values => NSSolver % Matrix % Values207InitMat % Rows => NSSolver % Matrix % Rows208InitMat % Cols => NSSolver % Matrix % Cols209InitMat % Diag => NSSolver % Matrix % Diag210211212VelocitybSol => VariableGet( Solver % Mesh % Variables, 'Velocityb' )213IF ( ASSOCIATED( VelocitybSol ) ) THEN214Vb => VelocitybSol % Values215VbPerm => VelocitybSol % Perm216ELSE217WRITE(Message,'(A)') 'No variable > Velocityb < found'218CALL FATAL(SolverName,Message)219END IF220IF (VelocitybSol % DOFs.NE.NSDOFs) then221WRITE(Message,'(A,I1,A,I1)') &222'Variable Velocityb has ',VelocitybSol % DOFs,' DOFs, should be',NSDOFs223CALL FATAL(SolverName,Message)224END IF225226TransMat => NULL()227TransMat => CRS_Transpose(InitMat)228229NULLIFY( InitMat % Rows, InitMat % Cols, InitMat % Diag, InitMat % Values )230CALL FreeMatrix( InitMat )231232CALL CRS_SortMatrix( TransMat , .true. )233234StiffMatrix % Values = TransMat % Values235StiffMatrix % Rows = TransMat % Rows236StiffMatrix % Cols = TransMat % Cols237IF(ASSOCIATED(TransMat % Diag)) StiffMatrix % Diag = TransMat % Diag238ForceVector = 0.0239Perm = NSSolver % Variable % Perm240241deallocate( TransMat % Rows, TransMat % Cols , TransMat % Values)242IF(ASSOCIATED(TransMat % Diag)) DEALLOCATE(TransMat % Diag)243nullify(TransMat)244245!forcing of the adjoint system comes from the Velocityb variable computed246!with the cost function247248!! Vb is expressed in the model coordinate system => Rotate to NT249CALL RotateNTSystemAll( Vb, VbPerm, NSDOFs )250251c = NSDOFs252Do t=1,Solver%Mesh%NumberOfNodes253Do i=1,c254p=(Perm(t)-1)*c+i255q=(VbPerm(t)-1)*c+i256ForceVector(p)=Vb(q)257End Do258EndDo259260CALL FinishAssembly( Solver, ForceVector )261262Unorm = DefaultSolve()263264! Go through BC to check if dirichlet was applied to direct solver265! Go to the boundary elements266Do t=1,GetNOFBoundaryElements()267Element => GetBoundaryElement(t)268BC => GetBC(Element)269IF (.NOT.ASSOCIATED( BC ) ) CYCLE270271NodeIndexes => Element % NodeIndexes272n = Element % TYPE % NumberOfNodes273274! Cf correspond lines in SolverUtils275! Check for nodes belonging to n-t boundary getting set by other bcs.276! -------------------------------------------------------------------277CheckNT = .FALSE.278IF ( NormalTangentialNOFNodes>0 .AND. NSDOFs>0 ) THEN279CheckNT = .TRUE.280IF ( ALL(BoundaryReorder(NodeIndexes(1:n))<1) ) CheckNT = .FALSE.281IF ( ListGetLogical(BC,'normal-tangential' // ' ' // NSVarName,Gotit)) CheckNT=.FALSE.282END IF283284! set BC for NSDOFs=1 or applied to the whole vector285IF( ListCheckPresent( BC, NSVarName ) ) THEN286Condition(1:n) = ListGetReal( BC, &287TRIM(NSVarName) // ' Condition', n, NodeIndexes, Conditional )288DO j=1,n289IF ( Conditional .AND. Condition(j)<0._dp ) CYCLE290DO i=1,NSDOFS291Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1)+i)=0._dp292END DO293END DO294ENDIF295296! Do the same for each component297IF (NSDOFs>1) THEN298DO i=1,NSDOFS299IF( ListCheckPresent( BC, ComponentName(NSVarName,i)) ) THEN300Condition(1:n) = ListGetReal( BC, &301TRIM(ComponentName(NSVarName,i)) // ' Condition', n, NodeIndexes, Conditional )302303DO j=1,n304IF ( Conditional .AND. Condition(j)<0._dp ) CYCLE305306k = Perm(NodeIndexes(j))307IF ( k > 0 ) THEN308309m = 0310IF ( NormalTangentialNOFNodes>0 ) m=BoundaryReorder(NodeIndexes(j))311!! set in the NT system312IF ( m>0 .AND. CheckNT ) THEN313RotVec = 0._dp314RotVec(i) = 1._dp315CALL RotateNTSystem( RotVec, NodeIndexes(j) )316317! When cartesian component "DOF" is defined set the N-T component318! closest to its direction.319kmax = 1320DO k=2,dim321IF ( ABS(RotVec(k)) > ABS(RotVec(kmax)) ) THEN322kmax = k323END IF324END DO325Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1) + kmax)=0._dp326!else set the given DOF327ELSE328Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1)+i)=0._dp329END IF330331ENDIF332END DO333334ENDIF335336END DO337ENDIF338END DO339340! Go through the Body forces341Do t=1,Solver % NumberOfActiveElements342Element => GetActiveElement(t)343344BF => GetBodyForce(Element)345IF (.NOT.ASSOCIATED( BF ) ) CYCLE346347NodeIndexes => Element % NodeIndexes348n = Element % TYPE % NumberOfNodes349350! set BC for NSDOFs=1 or applied to the whole vector351IF( ListCheckPresent( BF, NSVarName ) ) THEN352Condition(1:n) = ListGetReal( BF, &353TRIM(NSVarName) // ' Condition', n, NodeIndexes, Conditional )354DO j=1,n355IF ( Conditional .AND. Condition(j)<0._dp ) CYCLE356DO i=1,NSDOFS357Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1)+i)=0._dp358END DO359END DO360ENDIF361362! Do the same for each component363IF (NSDOFs>1) THEN364DO i=1,NSDOFS365IF( ListCheckPresent( BF, ComponentName(NSVarName,i)) ) THEN366Condition(1:n) = ListGetReal( BF, &367TRIM(ComponentName(NSVarName,i)) // ' Condition', n, NodeIndexes, Conditional )368369DO j=1,n370IF ( Conditional .AND. Condition(j)<0._dp ) CYCLE371Sol%Values(NSDOFs*(Perm(NodeIndexes(j))-1)+i)=0._dp372END DO373END IF374END DO375END IF376377END DO378379! Back Rotate to model coordinate system380CALL BackRotateNTSystem(Sol%Values,Perm,NSDOFs)381382! reset Dimension to DIM383IF (DIM.eq.(NSDOFs+1)) CurrentModel % Dimension = DIM384385RETURN386!------------------------------------------------------------------------------387END SUBROUTINE AdjointSSA_AdjointSolver388!------------------------------------------------------------------------------389390391392