SUBROUTINE AdjointSolver( Model,Solver,dt,TransientSimulation )
USE DefUtils
USE NavierStokes
IMPLICIT NONE
TYPE(Solver_t) :: Solver
TYPE(Model_t) :: Model
REAL(KIND=dp) :: dt
LOGICAL :: TransientSimulation
TYPE(Solver_t),Pointer :: NSSolver
TYPE(Matrix_t),POINTER :: InitMat,TransMat,StiffMatrix
TYPE(ValueList_t),POINTER :: BC,SolverParams
TYPE(Nodes_t) :: ElementNodes
TYPE(Element_t),POINTER :: Element
TYPE(Variable_t), POINTER :: Sol
TYPE(Variable_t), POINTER :: VelocitybSol
REAL(KIND=dp), POINTER :: Vb(:)
INTEGER, POINTER :: VbPerm(:)
REAL(KIND=dp),POINTER :: ForceVector(:)
integer :: t,n,NSDOFs,NVals,SolverInd
REAL(KIND=dp),ALLOCATABLE :: STIFF(:,:),FORCE(:),ExtPressure(:),LoadVector(:,:),Alpha(:),Beta(:),SlipCoeff(:,:),w(:)
Logical :: Gotit,GotForceBC,NormalTangential,Firsttime=.true.,UnFoundFatal=.TRUE.
INTEGER, POINTER :: NodeIndexes(:),Perm(:)
integer :: p,q,dim,c
integer :: i,iii,jjj,k
Real(KIND=dp) :: Unorm
REAL(KIND=dp), allocatable :: FullMat(:,:)
character(len=50) :: fo1
character(LEN=MAX_NAME_LEN) :: SolName
character(LEN=MAX_NAME_LEN) :: SolverName="Adjoint Solver"
save SolverName,Firsttime,SolverInd,STIFF,FORCE,ExtPressure,LoadVector,Alpha,Beta,SlipCoeff,w
CALL Info(SolverName,'***********************',level=0)
CALL Info(SolverName,' This solver has been replaced by:',level=0)
CALL Info(SolverName,' Adjoint_LinearSolver ',level=0)
CALL Info(SolverName,' See documentation under: ',level=0)
CALL Info(SolverName,' elmerice/Solvers/Documentation ',level=0)
CALL Info(SolverName,'***********************',level=0)
CALL FATAL(SolverName,' Use new solver !!')
DIM = CoordinateSystemDimension()
StiffMatrix => Solver % Matrix
ForceVector => StiffMatrix % RHS
Sol => Solver % Variable
NSDOFs = Sol % DOFs
Perm => Sol % Perm
CALL DefaultInitialize()
if (Firsttime) then
Firsttime=.False.
N = Solver % Mesh % MaxElementDOFs
allocate(FORCE( 2*NSDOFs*N ),STIFF( 2*NSDOFs*N,2*NSDOFs*N ),ExtPressure(N), &
SlipCoeff(3,N),LoadVector(4,N),Alpha(N),Beta(N),w(N))
SolverParams => GetSolverParams()
SolName = GetString( SolverParams,'Flow Solution Equation Name',Gotit)
IF (.NOT.Gotit) Then
CALL WARN(SolverName,'Keyword >Flow Solution Equation Name< not found in SolverParams')
CALL WARN(SolverName,'Taking default value >Flow Solution<')
WRITE(SolName,'(A)') 'Flow Solution'
Endif
DO i=1,Model % NumberOfSolvers
if (TRIM(SolName) == ListGetString(Model % Solvers(i) % Values, 'Equation')) exit
End do
if (i.eq.(Model % NumberOfSolvers+1)) CALL FATAL(SolverName,'Could not find Flow Solver Equation Name')
SolverInd=i
end if
NSSolver => Model % Solvers(SolverInd)
IF(.NOT.ASSOCIATED(NSSolver % Matrix % BulkValues)) CALL FATAL(SolverName,'Flow Solver BulkValues not associated. &
Add >Calculate Loads = Logical true< In the flow solver section')
InitMat => AllocateMatrix()
InitMat % NumberOfRows = NSSolver % Matrix % NumberOfRows
InitMat % Values => NSSolver % Matrix % BulkValues
InitMat % Rows => NSSolver % Matrix % Rows
InitMat % Cols => NSSolver % Matrix % Cols
InitMat % Diag => NSSolver % Matrix % Diag
VelocitybSol => VariableGet( Solver % Mesh % Variables, 'Velocityb',UnFoundFatal=UnFoundFatal )
Vb => VelocitybSol % Values
VbPerm => VelocitybSol % Perm
IF (VelocitybSol % DOFs.NE.(dim+1)) then
WRITE(Message,'(A,I1,A,I1)') &
'Variable Velocityb has ',VelocitybSol % DOFs,' DOFs, should be',dim+1
CALL FATAL(SolverName,Message)
End If
TransMat => NULL()
TransMat => CRS_Transpose(InitMat)
NULLIFY( InitMat % Rows, InitMat % Cols, InitMat % Diag, InitMat % Values )
CALL FreeMatrix( InitMat )
CALL CRS_SortMatrix( TransMat , .true. )
IF ( SIZE(StiffMatrix % Values) .NE. SIZE(TransMat % Values) ) THEN
CALL WARN(SolverName,'StiffMatrix different size to TransMat. Is this the correct the body?')
END IF
StiffMatrix % Values = TransMat % Values
StiffMatrix % Rows = TransMat % Rows
StiffMatrix % Cols = TransMat % Cols
IF(ASSOCIATED(TransMat % Diag)) StiffMatrix % Diag = TransMat % Diag
ForceVector = 0.0
Perm = NSSolver % Variable % Perm
deallocate( TransMat % Rows, TransMat % Cols , TransMat % Values)
IF(ASSOCIATED(TransMat % Diag)) DEALLOCATE(TransMat % Diag)
nullify(TransMat)
DO t = 1,Solver % Mesh % NumberOfBoundaryElements
Element => GetBoundaryElement(t)
IF ( .NOT. ActiveBoundaryElement() ) CYCLE
n = GetElementNOFNodes()
IF ( GetElementFamily() == 1 ) CYCLE
CALL GetElementNodes( ElementNodes )
NodeIndexes => Element % NodeIndexes
BC => GetBC()
IF ( .NOT. ASSOCIATED(BC) ) CYCLE
GotForceBC = GetLogical( BC, 'Adjoint Force BC',gotIt )
IF (GotForceBC) Then
LoadVector=0.0d0
Alpha=0.0d0
Beta=0.0d0
STIFF=0.0
FORCE=0.0
ExtPressure=0.0
SlipCoeff = 0.0d0
NormalTangential = GetLogical( BC, &
'Normal-Tangential Adjoint', GotIt )
SlipCoeff(1,1:n) = GetReal( BC, 'Slip Coefficient 1',GotIt )
SlipCoeff(2,1:n) = GetReal( BC, 'Slip Coefficient 2',GotIt )
SlipCoeff(3,1:n) = GetReal( BC, 'Slip Coefficient 3',GotIt )
CALL NavierStokesBoundary( STIFF, FORCE, &
LoadVector, Alpha, Beta, ExtPressure, SlipCoeff, NormalTangential, &
Element, n, ElementNodes )
CALL DefaultUpdateEquations( STIFF, FORCE )
end if
END DO
c = dim + 1
Do t=1,Solver%Mesh%NumberOfNodes
Do i=1,c
p=(Perm(t)-1)*c+i
q=(VbPerm(t)-1)*c+i
ForceVector(p)=Vb(q)
End Do
EndDo
CALL FinishAssembly( Solver, ForceVector )
CALL DefaultDirichletBCs()
Unorm = DefaultSolve()
Return
END SUBROUTINE AdjointSolver