#include "Includes.h" module ResidualsMonitorClass use SMConstants use PhysicsStorage use HexMeshClass use MonitorDefinitions use MPI_Process_Info implicit none private public Residuals_t ! ! ************************** ! Residuals class definition ! ************************** ! type Residuals_t logical :: active real(kind=RP), allocatable :: values(:,:) real(kind=RP), allocatable :: CPUtime(:) character(len=STR_LEN_MONITORS) :: fileName contains procedure :: Initialization => Residuals_Initialization procedure :: Update => Residuals_Update procedure :: WriteLabel => Residuals_WriteLabel procedure :: WriteValues => Residuals_WriteValue procedure :: WriteToFile => Residuals_WriteToFile procedure :: destruct => Residuals_Destruct procedure :: copy => Residuals_Assign generic :: assignment(=) => copy end type Residuals_t ! ! ======== contains ! ======== ! !////////////////////////////////////////////////////////////////////////////////////////////////// ! ! RESIDUALS ROUTINES ! ------------------ !////////////////////////////////////////////////////////////////////////////////////////////////// ! subroutine Residuals_Initialization( self, solution_file, FirstCall ) ! ! ******************************************************************* ! This subroutine initializes the residuals structure ! ******************************************************************* ! implicit none class(Residuals_t) :: self character(len=*) :: solution_file logical, intent(in) :: FirstCall ! ! --------------- ! Local variables ! --------------- ! character(len=STR_LEN_MONITORS) :: fileName integer :: fID integer :: pos ! ! Enable the monitor ! ------------------ self % active = .true. allocate ( self % values(NCONS,1:BUFFER_SIZE) , self % CPUtime(BUFFER_SIZE) ) ! ! Get monitor file name ! --------------------- write( self % fileName , '(A,A)') trim(solution_file) , ".residuals" ! ! Create file to write the residuals ! ---------------------------------- if (FirstCall) then open ( newunit = fID , file = trim(self % fileName) , status = "unknown" , action = "write" ) write ( fID , ' ( A ) ' ) "#Residuals file" #if defined(NAVIERSTOKES) && (!(SPALARTALMARAS)) write ( fID , ' ( A10,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24 ) ' ) "#Iteration" , "Time" , & "Total elapsed Time (s)", "Solver elapsed Time (s)" , "continuity" , "x-momentum" , "y-momentum" , "z-momentum", "energy" , "Max-Residual" #elif defined(SPALARTALMARAS) write ( fID , ' ( A10,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24 ) ' ) "#Iteration" , "Time" , & "Total elapsed Time (s)", "Solver elapsed Time (s)" , "continuity" , "x-momentum" , "y-momentum" , "z-momentum", "energy" ," Turbulence Param" , "Max-Residual" #elif defined(INCNS) write ( fID , ' ( A10,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24 ) ' ) "#Iteration" , "Time" , & "Elapsed Time (s)" , "dens-transp" , "x-momentum" , "y-momentum" , "z-momentum", "div-v" , "Max-Residual" #elif defined(MULTIPHASE) write ( fID , ' ( A10,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24,2X,A24 ) ' ) "#Iteration" , "Time" , & "Elapsed Time (s)" , "concentration" , "x-momentum" , "y-momentum" , "z-momentum", "div-v" , "Max-Residual" #elif defined(SCALAR) write ( fID , ' ( A10,2X,A24,2X,A24) ' ) "#Iteration" , "Time" , "slr" #elif defined(CAHNHILLIARD) write ( fID , ' ( A10,2X,A24,2X,A24) ' ) "#Iteration" , "Time" , "concentration" #endif ! ! Close file ! ---------- close ( fID ) end if end subroutine Residuals_Initialization subroutine Residuals_Update ( self, mesh, maxResiduals, bufferPosition) ! ! ********************************************************* ! This subroutine updates the residuals values from ! those computed in the Monitor procedure ! ********************************************************* ! implicit none class(Residuals_t) :: self class(HexMesh), intent(in) :: mesh real(kind=RP) :: maxResiduals(NCONS) integer :: bufferPosition ! ! Update buffer values ! -------------------- self % values( 1:NCONS, bufferPosition ) = maxResiduals end subroutine Residuals_Update subroutine Residuals_WriteLabel ( self ) ! ! ************************************************************ ! This subroutine displays the residuals labels for the ! time integrator Display procedure. ! ************************************************************ ! implicit none class(Residuals_t) :: self #if defined(NAVIERSTOKES) && (!(SPALARTALMARAS)) write(STD_OUT , '(3X,A10)' , advance = "no") "continuity" write(STD_OUT , '(3X,A10)' , advance = "no") "x-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "y-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "z-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "energy" #elif defined(SPALARTALMARAS) write(STD_OUT , '(3X,A10)' , advance = "no") "continuity" write(STD_OUT , '(3X,A10)' , advance = "no") "x-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "y-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "z-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "energy" write(STD_OUT , '(3X,A10)' , advance = "no") "turbulence parameter" #elif defined(INCNS) write(STD_OUT , '(3X,A10)' , advance = "no") "dens-transp" write(STD_OUT , '(3X,A10)' , advance = "no") "x-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "y-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "z-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "div-v" #elif defined(MULTIPHASE) write(STD_OUT , '(3X,A10)' , advance = "no") "concentration" write(STD_OUT , '(3X,A10)' , advance = "no") "x-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "y-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "z-momentum" write(STD_OUT , '(3X,A10)' , advance = "no") "div-v" #elif defined(SCALAR) write(STD_OUT , '(3X,A10)' , advance = "no") "slr" #elif defined(CAHNHILLIARD) write(STD_OUT , '(3X,A10)' , advance = "no") "concentration" #endif end subroutine Residuals_WriteLabel subroutine Residuals_WriteValue ( self , bufferLine ) ! ! *************************************************************** ! This subroutine displays the residuals values for the ! time integrator Display procedure ! *************************************************************** ! implicit none class(Residuals_t) :: self integer :: bufferLine ! --------------------------------------------------------- integer :: eq do eq = 1 , NCONS write(STD_OUT , '(1X,A,1X,ES10.3)' , advance = "no") "|" , self % values(eq , bufferLine) end do end subroutine Residuals_WriteValue subroutine Residuals_WriteToFile ( self , iter , t, TotalSimuTime, SolverSimuTime , no_of_lines) ! ! ********************************************************************* ! This subroutine exports the results to the monitor file. ! Just "no_of_lines" buffer lines are written. ! ********************************************************************* ! implicit none class(Residuals_t) :: self integer :: iter(:) real(kind=RP) :: t(:) real(kind=RP) :: TotalSimuTime(:) real(kind=RP) :: SolverSimuTime(:) integer :: no_of_lines ! ------------------------------------------- integer :: i integer :: fID #ifdef _HPC_MODE return #endif if ( MPI_Process % isRoot ) then ! ! Open file ! --------- open( newunit = fID , file = trim ( self % fileName ) , action = "write" , access = "append" , status = "old" ) ! ! Write values ! ------------ do i = 1 , no_of_lines write(fID, '(I10,3(2X,ES24.16))', advance="no") iter(i), t(i), TotalSimuTime(i), SolverSimuTime(i) write(fID, 111) self % values(1:NCONS,i), maxval(self % values(1:NCONS,i)) end do ! ! Close file ! ---------- close ( fID ) end if if ( no_of_lines .ne. 0 ) then self % values(1:NCONS,1) = self % values(1:NCONS,no_of_lines) end if #if defined(FLOW) 111 format(6(2X,ES24.16)) #elif (!defined(NAVIERSTOKES) && defined(CAHNHILLIARD)) 111 format(2(2X,ES24.16)) #else 111 format(2(2X,ES24.16)) #endif end subroutine Residuals_WriteToFile pure subroutine Residuals_Destruct (self) implicit none class(Residuals_t), intent(inout) :: self safedeallocate (self % values) safedeallocate (self % CPUtime) self % fileName = "" self % active = .FALSE. end subroutine Residuals_Destruct elemental subroutine Residuals_Assign(to, from) implicit none class(Residuals_t), intent(inout) :: to type(Residuals_t) , intent(in) :: from to % active = from % active safedeallocate (to % values) allocate ( to % values( size(from % values,1) , size(from % values,2) ) ) to % values = from % values safedeallocate (to % CPUtime) allocate ( to % CPUtime( size(from % CPUtime) ) ) to % CPUtime = from % CPUtime to % fileName = from % fileName end subroutine Residuals_Assign end module ResidualsMonitorClass