MatrixFreeClass.f90 Source File


Source Code

!
!//////////////////////////////////////////////////////
!
!
!   Matrix-free operations.
!
!//////////////////////////////////////////////////////
!
module MatrixFreeClass
   USE SMConstants             
   use GenericMatrixClass   , only: Matrix_t, DenseBlock_t
   use LinkedListMatrixClass
   use JacobianDefinitions  , only: JACEPS
   use DGSEMClass
   use PhysicsStorage
#include "Includes.h"
   implicit none
   !-----------------------------------------------------------------------------   
   private
   public  :: MF_JacVecMul, MF_p_F
   
!
!========
 contains
!========
!
!
!///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
!
   !  ----------------------------------------------------
   !  MF_JacVecMul:
   !  Matrix vector product (v = Au) 
   !  ----------------------------------------------------
   subroutine MF_JacVecMul(p_sem, DimPrb, Ur, F_Ur, x, Ax, dt, timesolve, shift, ComputeTimeDerivative)
      implicit none
      !-arguments-----------------------------------------------
      type(DGSem),               intent(inout) :: p_sem
      integer,                   intent(in)    :: DimPrb
      real(kind=RP),             intent(in)    :: x    (DimPrb)
      real(kind=RP),             intent(in)    :: Ur   (DimPrb)
      real(kind=RP),             intent(in)    :: F_Ur (DimPrb)
      real(kind=RP),             intent(in)    :: timesolve
      real(kind=RP),             intent(in)    :: dt
      real(kind=RP),             intent(in)    :: shift
      real(kind=RP),             intent(out)   :: Ax   (DimPrb)
      procedure(ComputeTimeDerivative_f)   :: ComputeTimeDerivative
      !-local-variables-----------------------------------------
      ! real(kind=RP) :: eps, shift
      real(kind=RP) :: eps
      real(kind=RP) :: L2x
      !---------------------------------------------------------
      
      L2x = norm2(x)

      if (L2x < 1e-12) then 
         Ax = 0.0_RP
      else 
         !eps = 1e-11_RP * (1._RP + norm2(p_sem % mesh % storage % Q) ) / norm2(x)
         eps = 1e-8_RP * (1._RP + norm2(x) )
         ! eps = 1e-2_RP * (1._RP + norm2(x) )

         Ax = ( MF_p_F(p_sem, DimPrb, Ur + x * eps, dt + timesolve, ComputeTimeDerivative) - F_Ur)/ eps + shift * x  ! First Order 

         !Ax = ( MF_p_F(p_sem, DimPrb, Ur + x * eps, dt + timesolve, ComputeTimeDerivative) - MF_p_F(p_sem, DimPrb, Ur, dt + timesolve, ComputeTimeDerivative))/ eps + shift * x  ! First Order 

         !Ax = ( MF_p_F(p_sem,DimPrb,Ur + x * eps, dt+timesolve,ComputeTimeDerivative) - MF_p_F(p_sem,DimPrb,Ur - x * eps,dt+timesolve, ComputeTimeDerivative))  /(2._RP * eps)  + shift*x   !Second order

      end if
   end subroutine MF_JacVecMul
!
!///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
!
!     ---------------------------------------------------
!     Function to return the time derivative using a specific solution vector
!     ---------------------------------------------------
      function MF_p_F(p_sem, DimPrb, u, CTD_time, computeTimeDerivative) result(F)
         implicit none
         !-arguments-----------------------------------------------
         type(DGSem),           intent(inout) :: p_sem
         integer,               intent(in)    :: DimPrb
         real(kind=rp),         intent(in)    :: u(DimPrb)
         real(kind=RP),         intent(in)    :: CTD_time
         procedure(ComputeTimeDerivative_f)   :: ComputeTimeDerivative
         real(kind=rp)                        :: F(DimPrb)
         !-local-variables-----------------------------------------
         real(kind=rp)                        :: u_p(DimPrb)
         !---------------------------------------------------------
         
         ! Save original Q
         u_p = p_sem % mesh % storage % Q
         
         ! Obtain derivative with new Q
         p_sem % mesh % storage % Q = u
         call p_sem % mesh % storage % global2LocalQ
         call ComputeTimeDerivative(p_sem % mesh, p_sem % particles, CTD_time, CTD_IGNORE_MODE)
         call p_sem % mesh % storage % local2GlobalQdot(p_sem % NDOF)
         
         F = p_sem % mesh % storage % Qdot

         ! Restore original Q
         p_sem % mesh % storage % Q = u_p   ! TODO: this step can be avoided if Ur is not read in the "child" GMRES (the preconditioner)
         call p_sem % mesh % storage % global2LocalQ
      end function MF_p_F
!
!///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
!
end module MatrixFreeClass