! !////////////////////////////////////////////////////// ! ! Module that provides routines to estimate the truncation error every n number of ! interactions and store it in files. ! !////////////////////////////////////////////////////// ! #include "Includes.h" module MultiTauEstimationClass use SMConstants use TruncationErrorClass , only: TruncationError_t, NON_ISOLATED_TE, ISOLATED_TE, NMINest use AnisFASMultigridClass , only: AnisFASMultigrid_t use FTValueDictionaryClass , only: FTValueDictionary use DGSEMClass , only: DGSem, ComputeTimeDerivative_f use ParamfileRegions , only: readValueInRegion, getSquashedLine use Utilities , only: toLower use MPI_Process_Info , only: MPI_Process use Headers , only: Subsection_Header implicit none private public MultiTauEstim_t ! ! Main type for multi tau-estimation ! ---------------------------------- type MultiTauEstim_t logical, private :: Active = .FALSE. integer :: interval integer :: TruncErrorType integer :: stage integer :: num_of_elements character(len=LINE_LENGTH) :: FolderName type(TruncationError_t),allocatable :: TE(:) type(AnisFASMultigrid_t) :: AnisFAS contains procedure :: construct => MultiTau_Construct procedure :: constructForPAdaptator => MultiTau_ConstructForPAdaptator procedure :: destruct => MultiTau_Destruct procedure :: describe => MultiTau_Describe procedure :: estimate => MultiTau_Estimate procedure :: GetTEmap => MultiTau_GetTEmap end type MultiTauEstim_t ! ! ======== contains ! ======== ! !/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! subroutine MultiTau_Construct(this, controlVariables, sem) implicit none !-arguments---------------------------------------------------- class(MultiTauEstim_t) , intent(inout) :: this type(FTValueDictionary) , intent(in) :: controlVariables type(DGSem) , intent(in) :: sem !-local-variables---------------------------------------------- integer :: eID character(LINE_LENGTH) :: paramFile character(LINE_LENGTH) :: in_label character(LINE_LENGTH) :: R_TruncErrorType, R_Folder integer, allocatable :: R_interval !-------------------------------------------------------------- ! ! Initialize ! ********** this % Active = MultiTauEstimationIsDefined() if (.not. this % Active) return ! ! Read the input ! ************** write(in_label , '(A)') "#define multi tau-estimation" call get_command_argument(1, paramFile) ! call readValueInRegion ( trim ( paramFile ) , "truncation error type" , R_TruncErrorType , in_label , "# end" ) call readValueInRegion ( trim ( paramFile ) , "interval" , R_interval , in_label , "# end" ) call readValueInRegion ( trim ( paramFile ) , "folder" , R_Folder , in_label , "# end" ) ! Truncation error type ! --------------------- call toLower (R_TruncErrorType) select case ( trim(R_TruncErrorType) ) case ('isolated') this % TruncErrorType = ISOLATED_TE case ('non-isolated') this % TruncErrorType = NON_ISOLATED_TE case default this % TruncErrorType = NON_ISOLATED_TE end select ! Estimation interval ! ------------------- if ( allocated(R_interval) ) then this % interval = R_interval else error stop 'Multi tau-estimation :: An interval must be specified' end if ! Output folder ! ------------- if ( R_Folder == "") then this % FolderName = "MultiTau" else this % FolderName = trim(R_Folder) end if ! ! Allocate memory to store the truncation error ! ********************************************* this % num_of_elements = sem % mesh % no_of_elements allocate (this % TE(this % num_of_elements)) do eID = 1, this % num_of_elements call this % TE(eID) % construct(sem % mesh % elements(eID) % Nxyz-1) this % TE(eID) % Dir(1) % P = sem % mesh % elements(eID) % Nxyz(1) - 1 this % TE(eID) % Dir(2) % P = sem % mesh % elements(eID) % Nxyz(2) - 1 this % TE(eID) % Dir(3) % P = sem % mesh % elements(eID) % Nxyz(3) - 1 end do this % stage = 0 ! ! Construct anisotropic FAS for error estimation ! ********************************************** call this % AnisFAS % construct(controlVariables,sem,estimator=.TRUE.,NMINestim = NMINest) ! ! Create folder for storing the truncation error ! ********************************************** call execute_command_line ('mkdir -p ' // this % FolderName) call this % describe end subroutine MultiTau_Construct ! !/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! subroutine MultiTau_ConstructForPAdaptator(this, TruncErrorType, NxyzMax, num_of_elements, Folder) implicit none !-arguments---------------------------------------------------- class(MultiTauEstim_t) , intent(inout) :: this integer , intent(in) :: TruncErrorType integer , intent(in) :: NxyzMax(NDIM) integer , intent(in) :: num_of_elements character(LINE_LENGTH) , intent(in) :: Folder !-local-variables---------------------------------------------- integer :: eID !-------------------------------------------------------------- ! ! Initialize ! ********** this % Active = .FALSE. ! Truncation error type ! --------------------- this % TruncErrorType = TruncErrorType ! Output folder ! ------------- this % FolderName = Folder ! ! Allocate memory to store the truncation error ! ********************************************* this % num_of_elements = num_of_elements this % stage = 0 !~ call this % describe end subroutine MultiTau_ConstructForPAdaptator ! !/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! subroutine MultiTau_Destruct(this) implicit none !-arguments---------------------------------------------------- class(MultiTauEstim_t), intent(inout) :: this !-------------------------------------------------------------- if (.not. this % Active) return ! Destruct truncation error storage ! --------------------------------- call this % TE % destruct deallocate (this % TE) ! Destruct multigrid ! ------------------ call this % AnisFAS % destruct end subroutine MultiTau_Destruct ! !/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! subroutine MultiTau_Describe(this) implicit none !-arguments---------------------------------------------------- class(MultiTauEstim_t), intent(inout) :: this !-------------------------------------------------------------- if (.not. MPI_Process % isRoot) return write(STD_OUT,'(/)') call Subsection_Header("Multi tau-estimation") write(STD_OUT,'(30X,A,A30,I6)') "->","Iteration interval: ", this % interval select case (this % TruncErrorType) case (NON_ISOLATED_TE) ; write(STD_OUT,'(30X,A,A30,A)') "->", "Truncation error type: ", "non-isolated" case (ISOLATED_TE) ; write(STD_OUT,'(30X,A,A30,A)') "->", "Truncation error type: ", "isolated" end select write(STD_OUT,'(30X,A,A30,A)') "->", "Storing in folder: ", this % FolderName end subroutine MultiTau_Describe ! !/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! subroutine MultiTau_Estimate(this, sem, iter, t, ComputeTimeDerivative, ComputeTimeDerivativeIsolated) implicit none !-arguments---------------------------------------------------- class(MultiTauEstim_t) , intent(inout) :: this type(DGSem) , intent(inout) :: sem integer , intent(in) :: iter real(kind=RP) , intent(in) :: t procedure(ComputeTimeDerivative_f) :: ComputeTimeDerivative procedure(ComputeTimeDerivative_f) :: ComputeTimeDerivativeIsolated !-local-variables---------------------------------------------- integer :: eID character(len=LINE_LENGTH) :: fName !-------------------------------------------------------------- ! Initial checks ! ************** if (.not. this % Active) return if (iter == 1 .or. mod(iter,this % interval) /= 0) return this % stage = this % stage + 1 ! ! Estimate the truncation error ! ***************************** call this % AnisFAS % solve(iter,t,computeTimeDerivative,ComputeTimeDerivativeIsolated,this % TE, this % TruncErrorType) ! ! Write the estimation to files ! ***************************** do eID = 1, this % num_of_elements write(fName,'(A,A,I8.8,A)') trim(this % FolderName), "/Elem", sem % mesh % elements(eID) % globID, ".dat" call this % TE(eID) % ExportToFile(fName) end do ! ! Reset the truncation error ! ************************** do eID = 1, this % num_of_elements this % TE(eID) % Dir(1) % maxTE = 0._RP this % TE(eID) % Dir(2) % maxTE = 0._RP this % TE(eID) % Dir(3) % maxTE = 0._RP end do end subroutine MultiTau_Estimate ! !/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! ! ---------------------------------------------- ! Get maximum values for the TEmap of an element ! ---------------------------------------------- subroutine MultiTau_GetTEmap(this,stages,glob_eID,Nmax,Nmin,P_1,TEmap) implicit none !-arguments---------------------------------------------------- class(MultiTauEstim_t) , intent(in) :: this integer , intent(in) :: stages(2) ! Initial and final estimation stage integer , intent(in) :: glob_eID integer , intent(in) :: Nmax(NDIM) ! Maximum polynomial order for adaptation integer , intent(in) :: Nmin(NDIM) ! Minimum polynomial order for adaptation integer , intent(inout) :: P_1 (NDIM) real(kind=RP) , intent(out) :: TEmap(NMINest:Nmax(1),NMINest:Nmax(2),NMINest:Nmax(3)) !-local-variables---------------------------------------------- integer :: stage, fd integer :: i, j, k, dir, error logical :: notenough real(kind=RP) :: TEmap_temp(NMINest:Nmax(1),NMINest:Nmax(2),NMINest:Nmax(3)) character(len=LINE_LENGTH) :: fName type(TruncationError_t) :: TE !-------------------------------------------------------------- write(fName,'(A,A,I8.8,A)') trim(this % FolderName), "/Elem", glob_eID, ".dat" open (newunit=fd, file = trim(fName)) call TE % construct( Nmax ) TEmap = 0._RP TEmap_temp = 0._RP do stage=stages(1), stages(2) call TE % reset call TE % ReadFromFile(fd_in = fd) do dir=1, 3 ! Adjust P-1 P_1(dir) = TE % Dir(dir) % P - 1 if ( (P_1(dir) < NMIN(dir)) .and. (P_1(dir) < NMINest+1) ) P_1(dir) = NMIN(dir) ! Extrapolate call TE % ExtrapolateInOneDir (P_1(dir),NMax(dir),Dir,notenough,error) if (notenough .or. error==1) TE % Dir(dir) % maxTE(P_1(dir)+1:Nmax(dir)) = huge(1._RP) / 4 ! Divide by 4 to prevent overflow end do call TE % GenerateTEmap(Nmax,TEmap_temp) do k = NMINest, Nmax(3) ; do j = NMINest, Nmax(2) ; do i = NMINest, Nmax(1) if (TEmap_temp(i,j,k) > TEmap(i,j,k)) TEmap(i,j,k) = TEmap_temp(i,j,k) end do ; end do ; end do end do call TE % destruct close (fd) end subroutine MultiTau_GetTEmap ! !/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! ! Auxiliary routines ! !/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! logical function MultiTauEstimationIsDefined() implicit none !-local-variables---------------------------------------------- character(len=LINE_LENGTH) :: case_name, line integer :: fID integer :: io !-------------------------------------------------------------- ! ! Initialize ! ---------- MultiTauEstimationIsDefined = .FALSE. ! ! Get case file name ! ------------------ call get_command_argument(1, case_name) ! ! Open case file ! -------------- open ( newunit = fID , file = case_name , status = "old" , action = "read" ) ! ! Read the whole file to find overenriching regions ! ------------------------------------------------- readloop:do read ( fID , '(A)' , iostat = io ) line if ( io .lt. 0 ) then ! ! End of file ! ----------- line = "" exit readloop elseif ( io .gt. 0 ) then ! ! Error ! ----- errorMessage(STD_OUT) error stop "Stopped." else ! ! Succeeded ! --------- line = getSquashedLine( line ) if ( index ( line , '#definemultitau-estimation' ) .gt. 0 ) then MultiTauEstimationIsDefined = .TRUE. close(fID) return end if end if end do readloop ! ! Close case file ! --------------- close(fID) end function MultiTauEstimationIsDefined ! !/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! end module MultiTauEstimationClass