https://www.cdslab.org/paramonte/fortran/2
Current view: top level - main - pm_sampling@routines.inc.F90 (source / functions) Hit Total Coverage
Test: ParaMonte 2.0.0 :: Serial Fortran - Code Coverage Report Lines: 361 385 93.8 %
Date: 2024-04-08 03:18:57 Functions: 1 3 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       2             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       3             : !!!!                                                                                                                            !!!!
       4             : !!!!    ParaMonte: Parallel Monte Carlo and Machine Learning Library.                                                           !!!!
       5             : !!!!                                                                                                                            !!!!
       6             : !!!!    Copyright (C) 2012-present, The Computational Data Science Lab                                                          !!!!
       7             : !!!!                                                                                                                            !!!!
       8             : !!!!    This file is part of the ParaMonte library.                                                                             !!!!
       9             : !!!!                                                                                                                            !!!!
      10             : !!!!    LICENSE                                                                                                                 !!!!
      11             : !!!!                                                                                                                            !!!!
      12             : !!!!       https://github.com/cdslaborg/paramonte/blob/main/LICENSE.md                                                          !!!!
      13             : !!!!                                                                                                                            !!!!
      14             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      15             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      16             : 
      17             : !>  \brief
      18             : !>  This file contains the implementations of the generic interfaces in [pm_sampling]@(ref pm_sampling).
      19             : !>
      20             : !>  \test
      21             : !>  [test_pm_sampling](@ref test_pm_sampling)
      22             : !>
      23             : !>  \finmain
      24             : !>
      25             : !>  \author
      26             : !>  \AmirShahmoradi, September 1, 2012, 12:00 AM, National Institute for Fusion Studies, The University of Texas at Austin
      27             : 
      28             : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      29             : 
      30             : #define RETURN_IF_FAILED(LINE,FAILED,MSG) \
      31             : if (FAILED) then; \
      32             : err%occurred = .true._LK; \
      33             : err%msg = PROCEDURE_NAME//getLine(LINE)//SKC_": "//NL1//MSG; \
      34             : call spec%disp%stop%show(err%msg); \
      35             : return; \
      36             : end if;
      37             :         ! Define intel-specific shared property of files on Windows.
      38             : #if     INTEL_ENABLED && WINDOWS_ENABLED
      39             : #define SHARED, shared
      40             : #else
      41             : #define SHARED
      42             : #endif
      43             :         ! Define runtime error handling mode.
      44             : #if     TESTING_ENABLED && (CAF_ENABLED || MPI_ENABLED || OMP_ENABLED)
      45             : #define FAILED_IMAGE(FAILED)isFailedImage(FAILED)
      46             : #else
      47             : #define FAILED_IMAGE(FAILED)FAILED
      48             : #endif
      49             : #if     CAF_ENABLED || MPI_ENABLED
      50             : #define SET_CAFMPI(X)X
      51             : #define SET_SERIAL(X)
      52             : #else
      53             : #define SET_CAFMPI(X)
      54             : #define SET_SERIAL(X)X
      55             : #endif
      56             : #if     CAF_ENABLED
      57             : #define SET_CAF(X)X
      58             : #else
      59             : #define SET_CAF(X)
      60             : #endif
      61             : #if     MPI_ENABLED
      62             : #define SET_MPI(X)X
      63             : #else
      64             : #define SET_MPI(X)
      65             : #endif
      66             : #if     OMP_ENABLED
      67             : #define SET_OMP(X)X
      68             : #else
      69             : #define SET_OMP(X)
      70             : #endif
      71             : #if     DEBUG_ENABLED
      72             : #define SET_DEBUG(X)X
      73             : #else
      74             : #define SET_DEBUG(X)
      75             : #endif
      76             : !#if     CAF_ENABLED
      77             : !#define COINDEX(I)[I]
      78             : !#else
      79             : !#define COINDEX(I)
      80             : !#endif
      81             :         ! Set the traceback information.
      82             : !#define TRACE(LINE) SKC_"@file::"//getStr(__FILE__)//getLine(LINE)//PROCEDURE_NAME
      83             : !        ! Set the alert optional input arguments.
      84             : !#define ALERT_OPTIONS unit = reportFileUnit, width = disp%width, prefix = method, tmsize = tmsize, bmsize = bmsize
      85             : 
      86             :         !%%%%%%%%%%%%%%%%%%
      87             : #if     runParaDRAM_ENABLED
      88             :         !%%%%%%%%%%%%%%%%%%
      89             : 
      90             :         abstract interface
      91             : #if     OMP_ENABLED && (MATLAB_ENABLED || PYTHON_ENABLED || R_ENABLED)
      92             :         recursive function getLogFuncPtr_proc(logFuncState, ndim, njob, avgTimePerFunCall, avgCommPerFunCall) result(mold) bind(C)
      93             :             import :: IK, RKC, RKD
      94             :             integer(IK), intent(in), value :: ndim, njob
      95             :             real(RKD), intent(inout) :: avgTimePerFunCall, avgCommPerFunCall
      96             :             real(RKC), intent(inout) :: logFuncState(ndim, njob)
      97             :             real(RKC) :: mold
      98             :         end function
      99             : #else
     100             :         recursive function getLogFuncPtr_proc(state, ndim) result(logFunc) bind(C)
     101             :             import :: IK, RKC
     102             :             integer(IK), intent(in), value :: ndim
     103             :             real(RKC), intent(in) :: state(ndim)
     104             :             real(RKC) :: logFunc
     105             :         end function
     106             : #endif
     107             :         end interface
     108             :         procedure(getLogFuncPtr_proc), pointer :: getLogFuncPtr
     109             :         !procedure(real(RKC)), pointer :: getLogFuncPtr
     110           1 :         type(paradram_type) :: sampler
     111           1 :         type(err_type) :: err
     112             :         integer(IK) :: lenin
     113             :         stat = 0_IK
     114             : 
     115             :         ! Reconstruct the input file.
     116             : 
     117           1 :         if (present(input)) then
     118             :             lenin = 1
     119          97 :             do
     120          98 :                 if (input(lenin) == c_null_char) exit
     121          97 :                 lenin = lenin + 1
     122             :             end do
     123           1 :             if (1 < lenin) sampler%inputFile = getCharSeq(input(1 : lenin - 1))
     124             :         end if
     125             : 
     126             :         !if (0 < lenin) then
     127             :         !    allocate(character(lenin) :: sampler%inputFile)
     128             :         !    do iell = 1, lenin
     129             :         !        sampler%inputFile(iell : iell) = input(iell)
     130             :         !    end do
     131             :         !end if
     132             : 
     133             :         ! Associate the input C procedure pointer to a Fortran procedure pointer.
     134             : 
     135           1 :         call c_f_procpointer(cptr = getLogFunc, fptr = getLogFuncPtr)
     136           1 :         err = getErrSampling(sampler, getLogFuncWrapper, ndim) ! run ParaDRAM.
     137           1 :         if (err%occurred) stat = 1_IK
     138           1 :         nullify(getLogFuncPtr)
     139             : 
     140             :     contains
     141             : 
     142             : #if     OMP_ENABLED && (MATLAB_ENABLED || PYTHON_ENABLED || R_ENABLED)
     143             :         recursive function getLogFuncWrapper(logFuncState, avgTimePerFunCall, avgCommPerFunCall) result(mold)
     144             :             real(RKC), intent(inout), contiguous :: logFuncState(0:,:)
     145             :             real(RKD), intent(inout) :: avgTimePerFunCall, avgCommPerFunCall
     146             :             real(RKC) :: mold
     147             :             mold = getLogFuncPtr(logFuncState, ndim, size(logFuncState, 2, IK), avgTimePerFunCall, avgCommPerFunCall)
     148             :         end function
     149             : #else
     150       91228 :         recursive function getLogFuncWrapper(state) result(logFunc)
     151             :             real(RKC), intent(in), contiguous :: state(:)
     152             :             real(RKC) :: logFunc
     153       91228 :             logFunc = getLogFuncPtr(state, ndim)
     154             :             !write(*,"(1I5,5E30.20,:,', ')") precision(state), state!, logFunc
     155       91228 :         end function
     156             : #endif
     157             : 
     158             :         !%%%%%%%%%%%%%%%%%%%%%
     159             : #elif   getErrSampling_ENABLED
     160             :         !%%%%%%%%%%%%%%%%%%%%%
     161             : 
     162             :         use pm_matrixClass, only: isMatClass, posdefmat
     163             :         use pm_sampling_kernel, only: getErrChainRead, getErrChainWrite, isFailedChainResize
     164             :         use pm_sampling_kernel, only: spec_type, stat_type, proposal_type
     165             :         use pm_sampling_kernel, only: chainFileColName
     166             :         use pm_sampling_kernel, only: getErrKernelRun
     167             :         use pm_sampling_kernel, only: NL1, NL2, RKC
     168             : #if     ParaDISE_ENABLED
     169             : #define SET_DRAMDISE(X)X
     170             : #define SET_ParaNest(X)
     171             :         character(*,SKC), parameter :: method = SKC_"ParaDISE"
     172             : #elif   ParaDRAM_ENABLED
     173             : #define SET_DRAMDISE(X)X
     174             : #define SET_ParaNest(X)
     175             :         character(*,SKC), parameter :: method = SKC_"ParaDRAM"
     176             : #elif   ParaNest_ENABLED
     177             : #define SET_ParaNest(X)X
     178             : #define SET_DRAMDISE(X)
     179             :         character(*,SKC), parameter :: method = SKC_"ParaNest"
     180             : #else
     181             : #error  "Unrecognized interface."
     182             : #endif
     183             :         character(*,SKC), parameter :: PROCEDURE_NAME = MODULE_NAME//SKC_"@getErrSampling()"
     184             :        !character(*,SKC), parameter :: NL1 = new_line(SKC_"a"), NL2 = NL1//NL1
     185             :         integer(IK) :: ndimp1, idim, iq
     186          13 :         type(proposal_type) :: proposal
     187          65 :         type(spec_type) :: spec
     188         481 :         type(stat_type) :: stat
     189          13 :         ndimp1 = ndim + 1_IK
     190             :         !!#if CAF_ENABLED
     191             :         !!! This must be coarray allocatable `[:]`, even though it will have only one element.
     192             :         !!! Otherwise, GNU Fortran 10 compiler results in runtime segmentation
     193             :         !!! fault in coarray mode, when the routine is called multiple times.
     194             :         !!! This used to be the case for a compound object. Does it also hold for intrinsic type objects?
     195             :         !!integer(IK), allocatable :: comv_unifRandState(:,:)[:]
     196             :         !!#else
     197             :         !!integer(IK), allocatable :: comv_unifRandState(:,:)
     198             :         !!#endif
     199             :         !
     200             :         !! Initialize the simulation auxiliary variables.
     201             :         !
     202             :         !!allocate(character(2**13 - 1, SK) :: errmsg) ! 8191: roughly 66Kb of memory for error message accumulation.
     203             :         !!reportFileUnit = output_unit ! Temporarily set the report file to stdout until the report file is set up.
     204             : 
     205             :         ! Setup the simulation specifications.
     206             : 
     207          13 :         spec = spec_type(modelr_type(0._RKC), method, ndim)
     208          13 :         err = spec%set(sampler)
     209          13 :         RETURN_IF_FAILED(__LINE__,FAILED_IMAGE(err%occurred),err%msg)
     210             : 
     211             :         !print *, """"//getStr([css_type(chainFileColName), css_type(spec%domainAxisName%val)], format = spec%chainFile%format%header)//achar(0, SKC)//""""
     212          13 :         if (spec%run%is%new .and. spec%image%is%leader) then
     213          13 :             if (spec%outputChainFileFormat%isBinary) then
     214           0 :                 write(spec%chainFile%unit) getStr([css_type(chainFileColName), css_type(spec%domainAxisName%val)], format = spec%chainFile%format%header)//achar(0, SKC)
     215             :             else
     216         144 :                 write(spec%chainFile%unit, spec%chainFile%format%header) (trim(chainFileColName(idim)), idim = 1, size(chainFileColName, 1, IK)), (trim(spec%domainAxisName%val(idim)), idim = 1, ndim)
     217             :             end if
     218             :         end if
     219             : 
     220             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     221             : 
     222          13 :         proposal = proposal_type(spec, err)
     223          13 :         RETURN_IF_FAILED(__LINE__,FAILED_IMAGE(err%occurred),err%msg)
     224             : 
     225             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     226             : 
     227          13 :         if (spec%image%is%leader) call spec%disp%text%wrap(NL1//spec%method%val//SKC_" simulation began on "//getDateTime(SK_"%c %z")//NL1)
     228          13 :         err = getErrKernelRun(getLogFunc, spec, stat, proposal)
     229          13 :         RETURN_IF_FAILED(__LINE__,FAILED_IMAGE(err%occurred),err%msg)
     230          13 :         if (spec%image%is%leader) call spec%disp%text%wrap(NL1//spec%method%val//SKC_" simulation ended on "//getDateTime(SK_"%c %z")//NL1)
     231          13 :         if (spec%image%is%first) then
     232          13 :             call spec%disp%skip(count = 2_IK, unit = output_unit)
     233             :             !call execute_command_line(" ")
     234          13 :             flush(output_unit)
     235             :         end if
     236          13 :         RETURN_IF_FAILED(__LINE__,FAILED_IMAGE(err%occurred),err%msg)
     237             : 
     238             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     239             : 
     240          13 :         blockLeaderPostProcessing: if (spec%image%is%leader) then
     241             : 
     242             :             ! Rules:
     243             :             !   -   Statistics values that require more than 1 line of the output file
     244             :             !       must be in the form of a table, the first line always being the column names.
     245             :             !       If the subsequent lines have one more column than the header line,
     246             :             !       then the first column of the subsequent lines will be interpreted as row names.
     247             :             !       Respecting this rule is important for parsing the contents of the report file in dynamic programming languages.
     248             : 
     249             :             associate(format => spec%reportFile%format%generic)
     250             : 
     251             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     252             : 
     253          13 :                 call spec%disp%show("stats.numFuncCall.accepted")
     254          13 :                 call spec%disp%show(stat%numFunCallAccepted, format = format)
     255          13 :                 call spec%disp%note%show("This is the total number of accepted function calls (unique samples).")
     256             : 
     257             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     258             : 
     259          13 :                 call spec%disp%show("stats.numFuncCall.acceptedRejected")
     260          13 :                 call spec%disp%show(stat%numFunCallAcceptedRejected, format = format)
     261          13 :                 call spec%disp%note%show("This is the total number of accepted or rejected function calls.")
     262             : 
     263             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     264             : 
     265          13 :                 call spec%disp%show("stats.numFuncCall.acceptedRejectedDelayed")
     266          13 :                 call spec%disp%show(stat%numFunCallAcceptedRejectedDelayed, format = format)
     267          13 :                 call spec%disp%note%show("This is the total number of accepted or rejected or delayed-rejection (if any requested) function calls.")
     268             : 
     269             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     270             : 
     271          13 :                 call spec%disp%show("stats.numFuncCall.acceptedRejectedDelayedUnused")
     272          13 :                 call spec%disp%show(stat%numFunCallAcceptedRejectedDelayedUnused, format = format)
     273          13 :                 call spec%disp%note%show("This is the total number of accepted or rejected or unused function calls (by all processes, including delayed rejections, if any requested).")
     274             : 
     275             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     276             : 
     277          13 :                 SET_DRAMDISE(call spec%disp%show("stats.chain.verbose.efficiency.meanAcceptanceRate"))
     278          13 :                 SET_DRAMDISE(call spec%disp%show(stat%cfc%meanAcceptanceRate(stat%numFunCallAccepted), format = format))
     279          13 :                 SET_DRAMDISE(call spec%disp%note%show(SKC_"This is the average MCMC acceptance rate of the "//spec%method%val//SKC_" sampler."))
     280             : 
     281             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     282             : 
     283          13 :                 SET_DRAMDISE(call spec%disp%show("stats.chain.verbose.efficiency.acceptedOverAcceptedRejected"))
     284             :                 SET_ParaNest(call spec%disp%show("stats.chain.uniques.efficiency.acceptedOverAcceptedRejected"))
     285          13 :                 call spec%disp%show(real(stat%numFunCallAccepted, RKC) / real(stat%numFunCallAcceptedRejected, RKC), format = format) ! accepted2AcceptedRejected
     286             :                 spec%msg = SKC_"This is the "//spec%method%val//SKC_" sampler efficiency given the accepted and rejected function calls, &
     287          13 :                 &that is, the number of accepted function calls divided by the number of (accepted + rejected) function calls."
     288          13 :                 call spec%disp%note%show(spec%msg)
     289             : 
     290             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     291             : 
     292          13 :                 SET_DRAMDISE(call spec%disp%show("stats.chain.verbose.efficiency.acceptedOverAcceptedRejectedDelayed"))
     293             :                 SET_ParaNest(call spec%disp%show("stats.chain.uniques.efficiency.acceptedOverAcceptedRejectedDelayed"))
     294          13 :                 call spec%disp%show(real(stat%numFunCallAccepted, RKC) / real(stat%numFunCallAcceptedRejectedDelayed, RKC), format = format)
     295             :                 spec%msg = SKC_"This is the "//spec%method%val//SKC_" sampler efficiency given the accepted, rejected, and delayed-rejection (if any requested) &
     296          13 :                 &function calls, that is, the number of accepted function calls divided by the number of (accepted + rejected + delayed-rejection) function calls."
     297          13 :                 call spec%disp%note%show(spec%msg)
     298             : 
     299             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     300             : 
     301          13 :                 SET_DRAMDISE(call spec%disp%show("stats.chain.verbose.efficiency.acceptedOverAcceptedRejectedDelayedUnused"))
     302             :                 SET_ParaNest(call spec%disp%show("stats.chain.uniques.efficiency.acceptedOverAcceptedRejectedDelayedUnused"))
     303          13 :                 call spec%disp%show(real(stat%numFunCallAccepted, RKC) / real(stat%numFunCallAcceptedRejectedDelayedUnused, RKC), format = format)
     304             :                 spec%msg = SKC_"This is the "//spec%method%val//SKC_" sampler efficiency given the accepted, rejected, delayed-rejection (if any requested), and unused function calls &
     305          13 :                 &(in parallel simulations), that is, the number of accepted function calls divided by the number of (accepted + rejected + delayed-rejection + unused) function calls."
     306          13 :                 call spec%disp%note%show(spec%msg)
     307             : 
     308             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     309             : 
     310          13 :                 call spec%disp%show("stats.time.total")
     311          13 :                 call spec%disp%show(stat%timer%clock, format = format)
     312          13 :                 call spec%disp%note%show("This is the total runtime in seconds.")
     313             : 
     314             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     315             : 
     316          13 :                 call spec%disp%show("stats.time.perFuncCallAccepted")
     317          13 :                 call spec%disp%show(stat%timer%clock / real(stat%numFunCallAccepted, RKC), format = format)
     318          13 :                 call spec%disp%note%show("This is the average effective time cost of each accepted function call, in seconds.")
     319             : 
     320             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     321             : 
     322          13 :                 call spec%disp%show("stats.time.perFuncCallAcceptedRejected")
     323          13 :                 call spec%disp%show(stat%timer%clock / real(stat%numFunCallAcceptedRejected, RKC), format = format)
     324          13 :                 call spec%disp%note%show("This is the average effective time cost of each accepted or rejected function call, in seconds.")
     325             : 
     326             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     327             : 
     328          13 :                 call spec%disp%show("stats.time.perFuncCallAcceptedRejectedDelayed")
     329          13 :                 call spec%disp%show(stat%timer%clock / real(stat%numFunCallAcceptedRejectedDelayed, RKC), format = format)
     330          13 :                 call spec%disp%note%show("This is the average effective time cost of each accepted or rejected function call (including delayed-rejections, if any requested), in seconds.")
     331             : 
     332             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     333             : 
     334          13 :                 call spec%disp%show("stats.time.perFuncCallAcceptedRejectedDelayedUnused")
     335          13 :                 call spec%disp%show(stat%timer%clock / real(stat%numFunCallAcceptedRejectedDelayedUnused, RKC), format = format)
     336             :                 spec%msg = "This is the average effective time cost of each accepted or rejected or unused function call (including delayed-rejections, if any requested), in seconds. &
     337             :                 &This timing can be directly compared to the corresponding timing of other parallel runs of the same simulation but with different processor counts to assess the parallel scaling. &
     338          13 :                 &A lower timing value implies a better parallel scaling and performance."
     339          13 :                 call spec%disp%note%show(spec%msg)
     340             : 
     341             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     342             : 
     343          13 :                 call spec%disp%show("stats.time.perInterProcessCommunication")
     344          13 :                 call spec%disp%show(stat%avgCommPerFunCall, format = format)
     345          13 :                 call spec%disp%note%show("This is the average time cost of parallel inter-process communications per used (accepted or rejected or delayed-rejection) function call, in seconds.")
     346             : 
     347             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     348             : 
     349          13 :                 call spec%disp%show("stats.time.perFuncCall")
     350          13 :                 call spec%disp%show(stat%avgTimePerFunCall, format = format)
     351          13 :                 call spec%disp%note%show("This is the average pure time cost of each function call, in seconds.")
     352             : 
     353             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     354             : 
     355          13 :                 call spec%disp%show("stats.parallelism.current.process.count")
     356          13 :                 call spec%disp%show(spec%image%count, format = format)
     357          13 :                 call spec%disp%note%show("This is the number of images/processes/threads used in this simulation.")
     358             : 
     359             : #if             CAF_ENABLED || MPI_ENABLED || OMP_ENABLED
     360             :                 if (spec%image%count == 1_IK) then
     361             :                     spec%msg = spec%method%val//SKC_" is used in parallel mode with only one processor. This can be computationally inefficient. &
     362             :                     &Consider using the serial version of the code or provide more processes at runtime if it seems to be beneficial."
     363             :                     call spec%disp%note%show(spec%msg, unit = output_unit)!, format = format, tmsize = 3_IK, bmsize = 1_IK)
     364             :                 end if
     365             : #endif
     366             : 
     367             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     368             :                 ! Find individual image contributions and the Cyclic Geometric fit to the contributions.
     369             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     370             : 
     371             :                 imageContribution_block: block
     372             : 
     373             :                     real(RKC) :: successProbNormFac(2)
     374             :                     integer(IK) :: pidSuccessLen, iell
     375             :                     integer(IK), allocatable :: index(:), cntSuccess(:), pidSuccess(:)
     376             : 
     377          13 :                     call setResized(index, spec%image%count)
     378          13 :                     call setResized(cntSuccess, spec%image%count)
     379          13 :                     call setResized(pidSuccess, spec%image%count)
     380          13 :                     call setUnique(stat%cfc%processID, unique = pidSuccess, lenUnique = pidSuccessLen, count = cntSuccess)
     381             : 
     382          13 :                     if (pidSuccessLen < spec%image%count) then
     383           0 :                         pidSuccess(pidSuccessLen + 1 :) = getComplementRange(pidSuccess(1 : pidSuccessLen), start = 1_IK, stop = spec%image%count, step = 1_IK)
     384           0 :                         cntSuccess(pidSuccessLen + 1 :) = 0_IK
     385             :                     end if
     386          13 :                     call setSorted(pidSuccess, index)
     387          39 :                     pidSuccess(:) = pidSuccess(index)
     388          39 :                     cntSuccess(:) = cntSuccess(index)
     389             : 
     390             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     391             : 
     392          13 :                     call spec%disp%show("stats.parallelism.current.process.contribution.count")
     393          65 :                     call spec%disp%show(css_type([character(15) :: "processID", "count"]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     394          26 :                     do iell = 1, spec%image%count
     395          26 :                         write(spec%reportFile%unit, spec%reportFile%format%integer) iell, cntSuccess(iell)
     396             :                     end do
     397          13 :                     call spec%disp%skip(count = spec%disp%bmsize)
     398             :                     spec%msg = SKC_"These are the contributions of individual processes to the construction of the output chain of the "//spec%method%val//SKC_" sampler. &
     399             :                     &Essentially, they represent the total number of accepted states (useful contributions to the simulation) by the corresponding processor, &
     400          13 :                     &starting from the first processor to the last. This information is mostly informative in parallel Fork-Join (singleChain) simulations."
     401          13 :                     call spec%disp%note%show(spec%msg)
     402             : 
     403             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     404             : 
     405          13 :                     call spec%disp%show("stats.parallelism.current.process.contribution.fit")
     406          65 :                     call spec%disp%show(css_type([character(15) :: "successProb", "normFac"]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     407          13 :                     if (spec%parallelism%is%forkJoin) then
     408           0 :                         pidSuccess = pack(pidSuccess, 0 < cntSuccess)
     409           0 :                         cntSuccess = pack(cntSuccess, 0 < cntSuccess)
     410           0 :                         err%occurred = isFailedGeomCyclicFit(pidSuccess, cntSuccess, spec%image%count, successProbNormFac(1), successProbNormFac(2))
     411           0 :                         if (err%occurred) then
     412           0 :                             call spec%disp%show(css_type([character(15) :: "NaN", "NaN"]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     413           0 :                             err%occurred = .false._LK
     414             :                         else
     415           0 :                             call spec%disp%show(successProbNormFac, format = spec%reportFile%format%allreal, tmsize = 0_IK)
     416             :                         end if
     417             :                     else
     418          39 :                         successProbNormFac = [1._RKC, real(cntSuccess(size(cntSuccess, 1, IK)), RKC)]
     419          13 :                         call spec%disp%show(successProbNormFac, format = spec%reportFile%format%allreal, tmsize = 0_IK)
     420             :                     end if
     421          13 :                     call spec%disp%skip(count = spec%disp%bmsize)
     422             :                     spec%msg =  SKC_"These are the two parameters of the Cyclic Geometric fit to the distribution of the processor contributions to the construction &
     423             :                                     &of the final output chain of visited states. The processor contributions are reported in the first column of the output chain file. &
     424             :                                     &The processor contribution frequencies are listed above. The fit has the following form: "//NL2// &
     425             :                                 SKC_"    processConstribution(i) ="//NL1//&
     426             :                                     SKC_"successProb * normFac * (1 - successProb)^(i - 1) / (1 - (1 - successProb)^processCount)"//NL2// &
     427             :                                 SKC_"where `i` is the ID of the processor (starting from index `1`), `processCount` is the total number of &
     428             :                                     &processes used in the simulation, `successProb` is equivalent to an effective sampling efficiency computed &
     429          13 :                                     &from the contributions of individual processes to the output chain, and `normFac` is a normalization constant."
     430          13 :                     call spec%disp%note%show(spec%msg)
     431             : 
     432             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     433             : 
     434             :                 end block imageContribution_block
     435             : 
     436             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     437             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% begin speedup compute %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     438             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     439             : 
     440             :                 blockParallelSpeedup: block
     441             : 
     442             :                     integer(IK) :: scalingMaxLoc, iell
     443             :                     integer(IK), parameter :: nscol = 5_IK
     444             :                     integer(IK), allocatable :: numproc(:)
     445             :                     real(RKC), allocatable :: scaling(:)
     446             :                     real(RKC) :: scalingMaxVal
     447             : 
     448             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     449             :                     ! Compute the effective efficiency from the processor contributions and the current strong scaling.
     450             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     451             : 
     452             :                     ! \todo
     453             :                     ! The specified epsilon values for `parSecTime` and `comSecTime` are points of weakness of the following call
     454             :                     ! if the computers of the future civilization are roughly 1 billion times or more faster than the current 2020 technologies.
     455             :                     ! Therefore, a more robust solution is required for cases where the entire simulation is a dry run of the old existing simulation.
     456             :                     ! This situation is, however, such a rare occurrence that does not merit further investment in the current version of the library.
     457             :                     call setForkJoinScaling ( conProb = real(stat%numFunCallAccepted, RKC) / real(stat%numFunCallAcceptedRejected, RKC) & ! LCOV_EXCL_LINE
     458             :                                             , seqSecTime = epsilon(1._RKC) & ! LCOV_EXCL_LINE time cost of the sequential section of the code, which is negligible here
     459             :                                             , comSecTime = real(stat%avgCommPerFunCall, RKC) / spec%image%count & ! LCOV_EXCL_LINE
     460             :                                             , parSecTime = real(stat%avgTimePerFunCall, RKC) & ! LCOV_EXCL_LINE
     461             :                                             , scalingMinLen = max(10_IK, spec%image%count * 2_IK) & ! LCOV_EXCL_LINE
     462             :                                             , scalingMaxLoc = scalingMaxLoc & ! LCOV_EXCL_LINE
     463             :                                             , scalingMaxVal = scalingMaxVal & ! LCOV_EXCL_LINE
     464             :                                             , numproc = numproc & ! LCOV_EXCL_LINE
     465             :                                             , scaling = scaling & ! LCOV_EXCL_LINE
     466          13 :                                             )
     467             : 
     468             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     469             : 
     470          13 :                     call spec%disp%show("stats.parallelism.current.speedup")
     471          13 :                     call spec%disp%show(scaling(spec%image%count), format = format)
     472             :                     spec%msg = "This is the estimated maximum speedup gained via "//spec%parallelism%val// & ! LCOV_EXCL_LINE
     473          13 :                     SKC_" parallelization model compared to serial mode given the current parallel communication overhead."
     474          13 :                     call spec%disp%note%show(spec%msg)
     475             : 
     476             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     477             : 
     478          13 :                     call spec%disp%show("stats.parallelism.optimal.process.count")
     479          13 :                     call spec%disp%show(scalingMaxLoc, format = format)
     480             :                     spec%msg = SKC_"This is the predicted optimal number of physical computing processes for "//spec%parallelism%val// & ! LCOV_EXCL_LINE
     481          13 :                     SKC_" parallelization model, given the current sampling efficiency and parallel communication overhead."
     482          13 :                     call spec%disp%note%show(spec%msg)
     483             : 
     484             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     485             : 
     486          13 :                     spec%msg = ""
     487          13 :                     call spec%disp%show("stats.parallelism.optimal.speedup")
     488          13 :                     call spec%disp%show(scalingMaxVal, format = format)
     489          13 :                     if (spec%parallelism%is%forkJoin .and. scaling(spec%image%count) < 1._RKC) then
     490             :                         spec%msg = "The time cost of calling the user-provided objective function must be at least "//getStr(1._RKC / scaling(spec%image%count), SK_"(g0.6)")//&
     491             :                         SKC_" times more (that is, ~"//getStr(10**6 * stat%avgTimePerFunCall / scaling(spec%image%count), SK_"(g0.6)")//" microseconds) to see any performance benefits from "//&
     492           0 :                         spec%parallelism%val//SKC_" parallelization model for this simulation. "
     493           0 :                         if (scalingMaxLoc == 1_IK) then
     494           0 :                             spec%msg = spec%msg//SKC_"Consider simulating in serial mode in the future (if used within the same computing environment and with the same configuration as used here)."
     495             :                         else
     496             :                             spec%msg = spec%msg//SKC_"Consider simulating on "//getStr(scalingMaxLoc)//&
     497           0 :                             SKC_" processors in the future (if used within the same computing environment and with the same configuration as used here)."
     498             :                         end if
     499           0 :                         if (.not. spec%outputSplashMode%is%silent) call spec%disp%note%show(spec%msg, unit = output_unit, tmsize = spec%disp%tmsize, bmsize = spec%disp%bmsize)
     500           0 :                         spec%msg = NL1//spec%msg
     501             :                     end if
     502             :                     spec%msg = SKC_"This is the predicted optimal maximum speedup gained via "//spec%parallelism%val// & ! LCOV_EXCL_LINE
     503          13 :                     SKC_" parallelization model, given the current sampling efficiency and parallel communication overhead."//spec%msg
     504          13 :                     call spec%disp%note%show(spec%msg)
     505             : 
     506             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     507             : 
     508          13 :                     call spec%disp%show("stats.parallelism.optimal.scaling.strong.speedup")
     509          65 :                     call spec%disp%show(css_type([character(15) :: "processCount", "speedup"]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     510         416 :                     do iell = 1, size(scaling, 1, IK)
     511         416 :                         write(spec%reportFile%unit, spec%reportFile%format%intreal) numproc(iell), scaling(iell)
     512             :                         !call spec%disp%show(scaling(iell : min(iell + nscol - 1_IK, size(scaling, 1, IK))), format = scalingFormat, tmsize = 0_IK, bmsize = 0_IK)
     513             :                     end do
     514          13 :                     call spec%disp%skip(count = spec%disp%bmsize)
     515             :                     spec%msg = SKC_"This is the predicted strong-scaling speedup behavior of the "//spec%parallelism%val//SKC_" parallelization model, &
     516          13 :                     &given the current sampling efficiency and parallel communication overhead, for increasing numbers of processes, starting from a single process."
     517          13 :                     call spec%disp%note%show(spec%msg)
     518             : 
     519             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     520             :                     ! compute the absolute parallelism efficiency under any sampling efficiency.
     521             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     522             : 
     523             :                     ! \todo
     524             :                     ! The specified epsilon values for `parSecTime` and `comSecTime` are points of weakness of the following call
     525             :                     ! if the computers of the future civilization are roughly 1 billion times or more faster than the current 2020 technologies.
     526             :                     ! Therefore, a more robust solution is required for cases where the entire simulation is a dry run of the old existing simulation.
     527             :                     ! This situation is, however, such a rare occurrence that does not merit further investment in the current version of the library.
     528             :                     call setForkJoinScaling ( conProb = 0._RKC & ! LCOV_EXCL_LINE
     529             :                                             , seqSecTime = epsilon(1._RKC) & ! LCOV_EXCL_LINE time cost of the sequential section of the code, which is negligible here
     530             :                                             , comSecTime = real(stat%avgCommPerFunCall, RKC) / spec%image%count & ! LCOV_EXCL_LINE
     531             :                                             , parSecTime = real(stat%avgTimePerFunCall, RKC) & ! LCOV_EXCL_LINE
     532             :                                             , scalingMinLen = max(10_IK, spec%image%count * 2_IK) & ! LCOV_EXCL_LINE
     533             :                                             , scalingMaxVal = scalingMaxVal & ! LCOV_EXCL_LINE
     534             :                                             , scalingMaxLoc = scalingMaxLoc & ! LCOV_EXCL_LINE
     535             :                                             , numproc = numproc & ! LCOV_EXCL_LINE
     536             :                                             , scaling = scaling & ! LCOV_EXCL_LINE
     537          13 :                                             )
     538             : 
     539             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     540             : 
     541          13 :                     call spec%disp%show("stats.parallelism.absolute.process.count")
     542          13 :                     call spec%disp%show(scalingMaxLoc, format = format)
     543             :                     spec%msg = "This is the predicted absolute number of physical computing processes for "//spec%parallelism%val// & ! LCOV_EXCL_LINE
     544          13 :                     SKC_" parallelization model, under any sampling efficiency for this sampling problem, given the current parallel communication overhead."
     545          13 :                     call spec%disp%note%show(spec%msg)
     546             : 
     547             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     548             : 
     549          13 :                     call spec%disp%show("stats.parallelism.absolute.speedup")
     550          13 :                     call spec%disp%show(scalingMaxVal, format = format)
     551             :                     spec%msg = SKC_"This is the predicted absolute optimal maximum speedup gained via "//spec%parallelism%val//SKC_" parallelization model, under any sampling efficiency. &
     552             :                     &This simulation will likely NOT benefit from any additional computing processors beyond the predicted absolute optimal number, "//getStr(scalingMaxLoc)//SKC_", in the above. &
     553             :                     &This is true for any value of MCMC sampling efficiency given the current parallel communication overhead. Keep in mind that the predicted absolute optimal number of processors &
     554             :                     &is just an estimate whose accuracy depends on many runtime factors, including the topology of the communication network being used, the number of processors per node, &
     555          13 :                     &and the number of tasks to each processor or node."
     556          13 :                     call spec%disp%note%show(spec%msg)
     557             : 
     558             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     559             : 
     560          13 :                     call spec%disp%show("stats.parallelism.absolute.scaling.strong.speedup")
     561          65 :                     call spec%disp%show(css_type([character(15) :: "processCount", "speedup"]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     562         416 :                     do iell = 1, size(scaling, 1, IK)
     563         416 :                         write(spec%reportFile%unit, spec%reportFile%format%intreal) numproc(iell), scaling(iell)
     564             :                         !call spec%disp%show(scaling(iell : min(iell + nscol - 1_IK, size(scaling, 1, IK))), format = scalingFormat, tmsize = 0_IK, bmsize = 0_IK)
     565             :                     end do
     566          13 :                     call spec%disp%skip(count = spec%disp%bmsize)
     567             :                     spec%msg = SKC_"This is the predicted absolute strong-scaling speedup behavior of the "//spec%parallelism%val//&
     568             :                     SKC_" parallelization model, under any MCMC sampling efficiency, given the current parallel communication overhead,&
     569          13 :                     &for increasing numbers of processes, starting from a single process."
     570          13 :                     call spec%disp%note%show(spec%msg)
     571             : 
     572             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     573             : 
     574             :                 end block blockParallelSpeedup
     575             : 
     576             : 
     577             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     578             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end speedup compute %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     579             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     580             : 
     581          13 :                 call spec%disp%show("stats.domain.logVolume")
     582          13 :                 call spec%disp%show(spec%domain%logVol, format = format)
     583          13 :                 call spec%disp%note%show("This is the natural logarithm of the volume of the "//spec%ndim%str//SKC_"-dimensional domain over which the objective function was defined.")
     584             : 
     585             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     586             : 
     587          13 :                 SET_DRAMDISE(call spec%disp%show("stats.chain.verbose.logFunc.max.val"))
     588             :                 SET_ParaNest(call spec%disp%show("stats.chain.uniques.logFunc.max.val"))
     589          13 :                 call spec%disp%show(stat%chain%mode%val, format = format)
     590          13 :                 call spec%disp%note%show("This is the maximum logFunc value (the maximum of the user-specified objective function).")
     591             : 
     592             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     593             : 
     594          13 :                 SET_DRAMDISE(call spec%disp%show("stats.chain.verbose.logFunc.max.crd"))
     595             :                 SET_ParaNest(call spec%disp%show("stats.chain.uniques.logFunc.max.crd"))
     596          67 :                 call spec%disp%show(css_type(spec%domainAxisName%val), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     597          13 :                 call spec%disp%show(stat%chain%mode%crd, format = spec%reportFile%format%allreal)
     598          13 :                 call spec%disp%note%show("This is the coordinates, within the domain of the user-specified objective function, where the maximum function value occurs.")
     599             : 
     600             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     601             : 
     602             : #if             ParaDRAM_ENABLED || ParaDISE_ENABLED
     603          13 :                 call spec%disp%show("stats.chain.compact.logFunc.max.loc")
     604          13 :                 call spec%disp%show(stat%chain%mode%loc, format = format)
     605          13 :                 call spec%disp%note%show("This is the location of the first occurrence of the maximum logFunc in the compact chain.")
     606             : 
     607             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     608             : 
     609          13 :                 call spec%disp%show("stats.chain.verbose.logFunc.max.loc")
     610      104094 :                 call spec%disp%show(sum(stat%cfc%sampleWeight(1 : stat%chain%mode%loc - 1)) + 1_IK, format = format) ! stat%chain%mode%Loc%verbose
     611          13 :                 call spec%disp%note%show("This is the location of the first occurrence of the maximum logFunc in the verbose (Markov) chain.")
     612             : 
     613             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     614             : 
     615          13 :                 call spec%disp%show("stats.chain.compact.burnin.loc.likelihoodBased")
     616          13 :                 call spec%disp%show(stat%burninLocMCMC%compact, format = format)
     617          13 :                 call spec%disp%note%show("This is the burnin location in the compact chain, based on the occurrence likelihood.")
     618             : 
     619             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     620             : 
     621          13 :                 call spec%disp%show("stats.chain.compact.burnin.loc.adaptationBased")
     622          13 :                 call spec%disp%show(stat%burninLocDRAM%compact, format = format)
     623          13 :                 call spec%disp%note%show("This is the burnin location in the compact chain, based on the value of burninAdaptationMeasure simulation specification.")
     624             : 
     625             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     626             : 
     627          13 :                 call spec%disp%show("stats.chain.verbose.burnin.loc.likelihoodBased")
     628          13 :                 call spec%disp%show(stat%burninLocMCMC%verbose, format = format)
     629          13 :                 call spec%disp%note%show("This is the burnin location in the verbose (Markov) chain, based on the occurrence likelihood.")
     630             : 
     631             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     632             : 
     633          13 :                 call spec%disp%show("stats.chain.verbose.burnin.loc.adaptationBased")
     634          13 :                 call spec%disp%show(stat%burninLocDRAM%verbose, format = format)
     635          13 :                 call spec%disp%note%show("This is the burnin location in the verbose (Markov) chain, based on the value of burninAdaptationMeasure simulation specification.")
     636             : 
     637             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     638             : 
     639             :                 ! reset burninLocation to the maximum value
     640             : 
     641          13 :                 if (stat%burninLocDRAM%compact > stat%burninLocMCMC%compact) then
     642           0 :                     stat%burninLocMCMC%compact = stat%burninLocDRAM%compact
     643           0 :                     stat%burninLocMCMC%verbose = stat%burninLocDRAM%verbose
     644             :                 end if
     645             : 
     646             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     647             :                 ! Compute the statistical properties of the MCMC chain
     648             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     649             : 
     650          13 :                 if (spec%image%is%first .and. .not. spec%outputSplashMode%is%silent) then
     651          13 :                     call spec%disp%note%show("Computing the statistical properties of the Markov chain...", unit = output_unit)
     652             :                 end if
     653          13 :                 call spec%disp%text%wrap(NL1//SKC_"The statistical properties of the Markov chain"//NL1)
     654             : 
     655             :                 ! Compute the covariance and correlation upper-triangle matrices.
     656             : 
     657             :                 !>  \warning
     658             :                 !>  forrtl: severe (174): SIGSEGV, segmentation fault occurred
     659             :                 !>  Apparently, when the chain is too long (e.g., 300000), the stack size can lead to such an error.
     660             :                 !>  The stack size will have to be adjusted in such cases.
     661             :                 !>  \todo
     662             :                 !>  A robust fix to the above segmentation fault error required further digging into this problem.
     663             :                 !>  This could become a serious hard-to-resolve error at higher levels in dynamic languages, especially on Windows.
     664             :                 !>  update: The problem is now resolved by allocating on the heap.
     665             : 
     666          13 :                 call setResized(stat%chain%avg, ndim)
     667          39 :                 call setResized(stat%chain%cov, [ndim, ndim])
     668          13 :                 call setMean(stat%chain%avg, stat%cfc%sampleState(:, stat%burninLocMCMC%compact : stat%cfc%nsam), 2_IK, stat%cfc%sampleWeight(stat%burninLocMCMC%compact : stat%cfc%nsam), stat%chain%size)
     669          13 :                 call setCov(stat%chain%cov, lowDia, stat%chain%avg, stat%cfc%sampleState(:, stat%burninLocMCMC%compact : stat%cfc%nsam), 2_IK, stat%cfc%sampleWeight(stat%burninLocMCMC%compact : stat%cfc%nsam), stat%chain%size)
     670          13 :                 call setMatCopy(stat%chain%cov, rdpack, stat%chain%cov, rdpack, lowDia, transHerm)
     671         238 :                 stat%chain%cor = getCor(stat%chain%cov, subsetv = lowDia)
     672             : 
     673             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     674             : 
     675          13 :                 call spec%disp%show("stats.chain.verbose.size.burninExcluded")
     676          13 :                 call spec%disp%show(stat%chain%size, format = format)
     677          13 :                 call spec%disp%note%show("This is the length of the verbose (Markov) Chain excluding burnin.")
     678             : 
     679             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     680             : 
     681          13 :                 call spec%disp%show("stats.chain.verbose.avg")
     682          67 :                 call spec%disp%show(css_type(spec%domainAxisName%val), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     683          13 :                 call spec%disp%show(stat%chain%avg, format = spec%reportFile%format%allreal)
     684          13 :                 call spec%disp%note%show("This is the mean (avg) of the verbose (Markov) chain variables.")
     685             : 
     686             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     687             : 
     688          13 :                 call spec%disp%show("stats.chain.verbose.std")
     689          67 :                 call spec%disp%show(css_type(spec%domainAxisName%val), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     690          67 :                 call spec%disp%show([(sqrt(stat%chain%cov(idim, idim)), idim = 1, ndim)], format = spec%reportFile%format%allreal)
     691          13 :                 call spec%disp%note%show("This is the standard deviation (std) of the verbose (Markov) chain variables.")
     692             : 
     693             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     694             : 
     695          13 :                 call spec%disp%show("stats.chain.verbose.covmat")
     696         120 :                 call spec%disp%show(css_type([character(len(spec%domainAxisName%val),SKC) :: SKC_"axis", spec%domainAxisName%val]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     697          13 :                 call spec%disp%skip(count = spec%disp%tmsize)
     698          40 :                 do idim = 1, ndim
     699          40 :                     write(spec%reportFile%unit, spec%reportFile%format%strreal) trim(adjustl(spec%domainAxisName%val(idim))), stat%chain%cov(1 : ndim, idim)
     700             :                 end do
     701          13 :                 call spec%disp%skip(count = spec%disp%bmsize)
     702          13 :                 call spec%disp%note%show("This is the covariance matrix of the verbose (Markov) chain.")
     703             : 
     704             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     705             : 
     706          13 :                 call spec%disp%show("stats.chain.verbose.cormat")
     707         120 :                 call spec%disp%show(css_type([character(len(spec%domainAxisName%val),SKC) :: SKC_"axis", spec%domainAxisName%val]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     708          13 :                 call spec%disp%skip(count = spec%disp%tmsize)
     709          40 :                 do idim = 1, ndim
     710          40 :                     write(spec%reportFile%unit, spec%reportFile%format%strreal) trim(adjustl(spec%domainAxisName%val(idim))), stat%chain%cor(1 : ndim, idim)
     711             :                 end do
     712          13 :                 call spec%disp%skip(count = spec%disp%bmsize)
     713          13 :                 call spec%disp%note%show("This is the correlation matrix of the verbose (Markov) chain.")
     714             : 
     715             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     716             : 
     717             :                 ! Compute the chain quantiles.
     718             :                 ! \bug Intel ifort bug with heap memory allocations:
     719             :                 ! The Intel ifort cannot digest the following task for an input 2D sample, throwing `double free or corruption (out)`.
     720             :                 ! The source of this error was traced back to the return point from `setExtrap()` within `getQuan()`.
     721             :                 ! The runtime error seems to resolve if the quantile matrix is computed in a loop like the following.
     722             : 
     723          39 :                 call setResized(stat%chain%quantile%quan, [size(stat%chain%quantile%prob, 1, IK), ndim])
     724             :                 block
     725             :                     real(RKC), allocatable :: sample(:)
     726          40 :                     do idim = 1, ndim
     727     1015026 :                         sample = stat%cfc%sampleState(idim, stat%burninLocMCMC%compact : stat%cfc%nsam)
     728         283 :                         stat%chain%quantile%quan(:, idim) = getQuan(neimean, stat%chain%quantile%prob, sample, stat%cfc%sampleWeight(stat%burninLocMCMC%compact : stat%cfc%nsam), stat%chain%size)
     729             :                     end do
     730             :                 end block
     731             :                 !stat%chain%quantile%quan = getQuan(neimean, stat%chain%quantile%prob, stat%cfc%sampleState(idim, stat%burninLocMCMC%compact : stat%cfc%nsam), 2_IK, stat%cfc%sampleWeight(stat%burninLocMCMC%compact : stat%cfc%nsam), stat%chain%size)
     732             : 
     733          13 :                 call spec%disp%show("stats.chain.verbose.quantile")
     734         120 :                 call spec%disp%show(css_type([character(len(spec%domainAxisName%val),SKC) :: SKC_"quantile", spec%domainAxisName%val]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
     735          13 :                 call spec%disp%skip(count = spec%disp%tmsize)
     736         130 :                 do iq = 1, size(stat%chain%quantile%prob, 1, IK)
     737         373 :                     write(spec%reportFile%unit, spec%reportFile%format%allreal) stat%chain%quantile%prob(iq), (stat%chain%quantile%quan(iq, idim), idim = 1, ndim)
     738             :                 end do
     739          13 :                 call spec%disp%skip(count = spec%disp%bmsize)
     740          13 :                 call spec%disp%note%show("This is the quantiles table of the variables of the verbose (Markov) chain.")
     741             : #endif
     742             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     743             :                 ! Generate the i.i.d. sample statistics and output file (if requested)
     744             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     745             : 
     746             :                 ! report refined sample statistics, and generate output refined sample if requested.
     747             : 
     748          13 :                 if (spec%image%is%first .and. .not. spec%outputSplashMode%is%silent) then
     749          13 :                     call spec%disp%note%show("Computing the final refined i.i.d. sample size...", unit = output_unit)
     750             :                 end if
     751             : #if             ParaDRAM_ENABLED || ParaDISE_ENABLED
     752             :                 err = stat%sfc%getErrRefinement ( sampleWeight = stat%cfc%sampleWeight(stat%burninLocMCMC%compact :) & ! LCOV_EXCL_LINE
     753             :                                                 , sampleLogFunc = stat%cfc%sampleLogFunc(stat%burninLocMCMC%compact :) & ! LCOV_EXCL_LINE
     754             :                                                 , sampleState = stat%cfc%sampleState(:, stat%burninLocMCMC%compact :) & ! LCOV_EXCL_LINE
     755             :                                                 , outputSampleRefinementCount = spec%outputSampleRefinementCount%val & ! LCOV_EXCL_LINE
     756             :                                                 , outputSampleRefinementMethod = spec%outputSampleRefinementMethod%val & ! LCOV_EXCL_LINE
     757          13 :                                                 )
     758             : 
     759             :                 ! compute the maximum integrated autocorrelation times for each variable.
     760             : 
     761             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     762             : 
     763          13 :                 call spec%disp%show("stats.chain.refined.act")
     764          13 :                 call spec%disp%skip(count = spec%disp%tmsize)
     765          40 :                 write(spec%reportFile%unit, spec%reportFile%format%fixform) "refinementStage", "sampleSize", "ACT_sampleLogFunc", (SKC_"ACT_"//trim(adjustl(spec%domainAxisName%val(idim))), idim = 1, ndim)
     766          13 :                 block
     767             :                     integer(IK) :: iref
     768             :                     character(:,SKC), allocatable :: thisForm
     769             :                     thisForm = SKC_"('"//spec%reportFile%indent//SKC_"',2(I"//spec%outputColumnWidth%max//SKC_",' '),*("//& ! LCOV_EXCL_LINE
     770          13 :                     spec%real%ed//spec%outputColumnWidth%max//SKC_"."//spec%outputPrecision%str//spec%real%ex//SKC_",:,' '))"
     771          13 :                     call spec%disp%skip(count = spec%disp%tmsize)
     772          52 :                     do iref = 0, stat%sfc%nref
     773          52 :                         write(spec%reportFile%unit, thisForm) iref, stat%sfc%sumw(iref), stat%sfc%act(0 : ndim, iref)
     774             :                     end do
     775          26 :                     call spec%disp%skip(count = spec%disp%bmsize)
     776             :                 end block
     777          13 :                 spec%msg = SKC_"This is the table of the Integrated Autocorrelation (ACT) of individual variables in the verbose (Markov) chain, at increasing stages of chain refinements."
     778             :                 if (stat%sfc%nref == 0_IK) spec%msg = spec%msg//NL1// & ! LCOV_EXCL_LINE
     779             :                 SKC_"The user-specified `outputSampleRefinementCount` ("//getStr(spec%outputSampleRefinementCount%val)//SKC_") &
     780           0 :                 &is too small to ensure an accurate computation of the decorrelated i.i.d. effective sample size. No refinement of the Markov chain was performed."
     781          13 :                 call spec%disp%note%show(spec%msg)
     782             : 
     783             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     784             : 
     785             :                 ! Report the final Effective Sample Size (ESS) based on ACT.
     786             : 
     787          13 :                 stat%ess = stat%sfc%sumw(stat%sfc%nref)
     788             : 
     789             : #elif           ParaNest_ENABLED
     790             : 
     791             :                 ! Read the ParaNest output chain file contents.
     792             : 
     793             :                 err = getErrChainRead(stat%cfc, file = spec%chainFile%file, spec%outputChainFileFormat%val, pre = stat%numFunCallAccepted)
     794             :                 if (err%occurred) then
     795             :                     err%msg = PROCEDURE_NAME//err%msg ! LCOV_EXCL_LINE
     796             :                     exit blockLeaderPostProcessing ! LCOV_EXCL_LINE
     797             :                     return ! LCOV_EXCL_LINE
     798             :                 end if
     799             : 
     800             :                 ! Compute the effective sample size.
     801             : 
     802             :                 stat%ess = nint(sum(exp(stat%cfc%sampleLogWeight - maxval(stat%cfc%sampleLogWeight))), IK)
     803             : #else
     804             : #error          "Unrecognized interface."
     805             : #endif
     806          13 :                 stat%sample%size = abs(spec%outputSampleSize%val)
     807          13 :                 if (spec%outputSampleSize%val < 0_IK) stat%sample%size = stat%sample%size * stat%ess
     808             : 
     809             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     810             : 
     811          13 :                 call spec%disp%show("stats.chain.refined.ess")
     812          13 :                 call spec%disp%show(stat%ess, format = format)
     813          13 :                 call spec%disp%note%show("This is the estimated Effective (i.i.d.) Sample Size (ESS) of the final refined chain.")
     814             : 
     815             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     816             : 
     817          13 :                 call spec%disp%show("stats.chain.refined.efficiency.essOverAccepted")
     818          13 :                 call spec%disp%show(real(stat%ess, RKC) / real(stat%numFunCallAccepted, RKC), format = format)
     819             :                 spec%msg = SKC_"This is the effective sampling efficiency given the accepted function calls, that is, &
     820          13 :                 &the final refined effective sample size (ESS) divided by the number of accepted function calls."
     821          13 :                 call spec%disp%note%show(spec%msg)
     822             : 
     823             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     824             : 
     825          13 :                 call spec%disp%show("stats.chain.refined.efficiency.essOverAcceptedRejected")
     826          13 :                 call spec%disp%show(real(stat%ess, RKC) / real(stat%numFunCallAcceptedRejected, RKC), format = format)
     827             :                 spec%msg = SKC_"This is the effective sampling efficiency given the accepted and rejected function calls, that is, &
     828          13 :                 &the final refined effective sample size (ESS) divided by the number of (accepted + rejected) function calls."
     829          13 :                 call spec%disp%note%show(spec%msg)
     830             : 
     831             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     832             : 
     833          13 :                 call spec%disp%show("stats.chain.refined.efficiency.essOverAcceptedRejectedDelayed")
     834          13 :                 call spec%disp%show(real(stat%ess, RKC) / real(stat%numFunCallAcceptedRejectedDelayed, RKC), format = format)
     835             :                 spec%msg = SKC_"This is the effective sampling efficiency given the accepted, rejected, and delayed-rejection (if any requested) function calls, &
     836          13 :                 &that is, the final refined effective sample size (ESS) divided by the number of (accepted + rejected + delayed-rejection) function calls."
     837          13 :                 call spec%disp%note%show(spec%msg)
     838             : 
     839             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     840             : 
     841          13 :                 call spec%disp%show("stats.chain.refined.efficiency.essOverAcceptedRejectedDelayedUnused")
     842          13 :                 call spec%disp%show(real(stat%ess, RKC) / real(stat%numFunCallAcceptedRejectedDelayedUnused, RKC), format = format)
     843             :                 spec%msg = SKC_"This is the effective sampling efficiency given the accepted, rejected, delayed-rejection (if any requested), and unused function calls, &
     844          13 :                 &(in parallel simulations), that is, the final refined effective sample size (ESS) divided by the number of (accepted + rejected + delayed-rejection + unused) function calls."
     845          13 :                 call spec%disp%note%show(spec%msg)
     846             : 
     847             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     848             : 
     849             :                 !end associate blockEffectiveSampleSize
     850             : 
     851             :                 ! Generate the output refined sample if requested.
     852             : 
     853          13 :                 blockSampleFileGeneration: if (spec%outputSampleSize%val == 0_IK) then
     854             : 
     855           0 :                     call spec%disp%note%show(SKC_"Skipping the generation of the refined chain and the output "//spec%sampleFile%kind//SKC_" file, as requested by the user...")
     856             : 
     857             :                 else blockSampleFileGeneration
     858             : 
     859             :                     ! report to the report-file(s)
     860             : 
     861          13 :                     call spec%disp%note%show(SKC_"Generating the output "//spec%sampleFile%kind//SKC_" file:"//NL1//spec%sampleFile%file)
     862          13 :                     if (spec%image%is%first .and. .not. spec%outputSplashMode%is%silent) then
     863             :                         ! print the message for the generating the output sample file on the first image
     864          13 :                         call spec%disp%note%show(SKC_"Generating the output "//spec%sampleFile%kind//SKC_" file:"//NL1//spec%sampleFile%file, unit = output_unit, bmsize = 0_IK)
     865             :                         ! print the message for the generating the output sample file on the rest of the images in order.
     866             : #if                     CAF_ENABLED || MPI_ENABLED || OMP_ENABLED
     867             :                         if (spec%parallelism%is%multiChain) then
     868             :                             block
     869             :                                 integer(IK) :: imageID
     870             :                                 do imageID = 2, spec%image%count
     871             :                                     call spec%disp%note%show(getReplaced(spec%sampleFile%file, SKC_"pid1", SKC_"pid"//getStr(imageID)), unit = output_unit, tmsize = 0_IK, bmsize = 0_IK)
     872             :                                 end do
     873             :                             end block
     874             :                         end if
     875             : #endif
     876          13 :                         call spec%disp%skip(unit = output_unit)
     877             :                     end if
     878             : 
     879             :                     ! Begin sample file generation.
     880             : 
     881         133 :                     stat%sfc%colname = [css_type(chainFileColName(size(chainFileColName, 1, IK))), css_type(spec%domainAxisName%val)]
     882          13 :                     stat%sfc%header = getStr(stat%sfc%colname, format = spec%sampleFile%format%header)
     883             : #if                 ParaDISE_ENABLED || ParaDRAM_ENABLED
     884          13 :                     if (spec%outputSampleSize%val /= -1_IK) then
     885             :                         ! Regenerate the refined sample, this time with the user-specified sample size.
     886             :                         block
     887             :                             integer(IK), allocatable :: cumSumWeight(:), unifrnd(:)
     888             :                             integer(IK) :: isam, iloc
     889           7 :                             stat%sfc%nref = 0_IK
     890           7 :                             call setRebound(stat%sfc%nsam, 0_IK, 0_IK)
     891           7 :                             call setRebound(stat%sfc%sumw, 0_IK, 0_IK)
     892           7 :                             stat%sfc%nsam(stat%sfc%nref) = stat%numFunCallAccepted - stat%burninLocMCMC%compact + 1_IK
     893           7 :                             call setResized(cumSumWeight, stat%sfc%nsam(stat%sfc%nref))
     894           7 :                             call setCumSum(cumSumWeight, stat%cfc%sampleWeight(stat%burninLocMCMC%compact :))
     895          14 :                             unifrnd = getUnifRand(spec%rng, 1_IK, cumSumWeight(stat%sfc%nsam(stat%sfc%nref)), stat%sample%size)
     896          21 :                             call setRebound(stat%sfc%sampleLogFuncState, [0_IK, 1_IK], [ndim, stat%sfc%nsam(stat%sfc%nref)])
     897       70007 :                             stat%sfc%sampleLogFuncState(1 :, :) = stat%cfc%sampleState(:, stat%burninLocMCMC%compact :)
     898       35007 :                             stat%sfc%sampleLogFuncState(0, :) = stat%cfc%sampleLogFunc(stat%burninLocMCMC%compact :)
     899       35014 :                             stat%sfc%sampleWeight = getFilled(0_IK, stat%sfc%nsam(stat%sfc%nref))
     900       17507 :                             loopOverSample: do isam = 1, stat%sample%size
     901    43487256 :                                 do iloc = 1, size(cumSumWeight, 1, IK)
     902    43487256 :                                     if (cumSumWeight(iloc) < unifrnd(isam)) cycle
     903       17500 :                                     stat%sfc%sampleWeight(iloc) = stat%sfc%sampleWeight(iloc) + 1_IK
     904    43469756 :                                     cycle loopOverSample
     905             :                                 end do
     906           7 :                                 error stop "This is a miracle! Please report it to the developers at: https://github.com/cdslaborg/paramonte"
     907             :                             end do loopOverSample
     908       35007 :                             stat%sfc%sumw(stat%sfc%nref) = sum(stat%sfc%sampleWeight)
     909             :                         end block
     910             :                     end if
     911             : #elif               ParaNest_ENABLED
     912             :                     stat%sfc%nref = 0_IK
     913             :                     call setRebound(stat%sfc%nsam, 0_IK, 0_IK)
     914             :                     call setRebound(stat%sfc%sumw, 0_IK, 0_IK)
     915             :                     stat%sfc%sampleWeight = nint(getReweight(exp(stat%cfc%sampleLogWeight - getLogSumExp(stat%cfc%sampleLogWeight)), 1._RKC / stat%sample%size), IK)
     916             :                     stat%sfc%nsam(stat%sfc%nref) = size(stat%sfc%sampleWeight, 1, IK)
     917             :                     call setRebound(stat%sfc%sampleLogFuncState, [0_IK, 1_IK], [ndim, stat%sfc%nsam(stat%sfc%nref)])
     918             :                     stat%sfc%sumw(stat%sfc%nref) = sum(stat%sfc%sampleWeight)
     919             : #else
     920             : #error              "Unrecognized interface."
     921             : #endif
     922             :                     ! open the output sample file and write the sample.
     923             : 
     924             :                     sfc_block: block
     925             :                         integer(IK) :: isam, iwei
     926          13 :                         spec%sampleFile%iomsg = SKC_""
     927          13 :                         spec%sampleFile%unit = getFileUnit() ! for some unknown reason, if newunit is used, GFortran opens the file as an internal file
     928          13 :                         open(unit = spec%sampleFile%unit, file = spec%sampleFile%file, form = spec%sampleFile%form, status = spec%sampleFile%status, position = spec%sampleFile%position, iostat = spec%sampleFile%iostat, iomsg = spec%sampleFile%iomsg SHARED)
     929          13 :                         if (spec%sampleFile%iostat /= 0_IK) exit sfc_block
     930          13 :                         write(spec%sampleFile%unit, spec%sampleFile%format%header, iostat = spec%sampleFile%iostat, iomsg = spec%sampleFile%iomsg) stat%sfc%header
     931          13 :                         if (spec%sampleFile%iostat /= 0_IK) exit sfc_block
     932      104884 :                         do isam = 1, stat%sfc%nsam(stat%sfc%nref)
     933      193879 :                             do iwei = 1, stat%sfc%sampleWeight(isam)
     934       88995 :                                 write(spec%sampleFile%unit, spec%sampleFile%format%rows, iostat = spec%sampleFile%iostat, iomsg = spec%sampleFile%iomsg) stat%sfc%sampleLogFuncState(:, isam)
     935      193866 :                                 if (spec%sampleFile%iostat /= 0_IK) exit sfc_block
     936             :                             end do
     937             :                         end do
     938          13 :                         close(spec%sampleFile%unit, iostat = spec%sampleFile%iostat, iomsg = spec%sampleFile%iomsg)
     939             :                         if (spec%sampleFile%iostat /= 0_IK) exit sfc_block
     940             :                     end block sfc_block
     941          13 :                     err%occurred = spec%sampleFile%iostat /= 0_IK
     942          13 :                     if (err%occurred) then
     943           0 :                         err%stat = spec%sampleFile%iostat
     944           0 :                         err%msg = spec%sampleFile%iomsg
     945           0 :                         exit blockLeaderPostProcessing
     946             :                     end if
     947             : 
     948             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     949             :                     ! Compute the statistical properties of the refined sample
     950             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     951             : 
     952          13 :                     if (spec%image%is%first .and. .not. spec%outputSplashMode%is%silent) then
     953          13 :                         call spec%disp%note%show(SKC_"Computing the statistical properties of the final output sample...", unit = output_unit)
     954             :                     end if
     955          13 :                     call spec%disp%text%wrap(NL1//SKC_"The statistical properties of the final output sample"//NL1)
     956             : #if                 ParaDRAM_ENABLED || ParaDISE_ENABLED
     957          52 :                     CHECK_ASSERTION(__LINE__, stat%sample%size == stat%sfc%sumw(stat%sfc%nref), \
     958             :                     SK_"@getErrSampling(): The condition `stat%sample%size == stat%sfc%sumw(stat%sfc%nref)` must hold. stat%sample%size, stat%sfc%sumw(stat%sfc%nref), stat%sfc%nref = "//\
     959             :                     getStr([stat%sample%size, stat%sfc%sumw(stat%sfc%nref), stat%sfc%nref]))
     960             : #endif
     961             :                     ! Compute the covariance and correlation upper-triangle matrices.
     962             : 
     963          13 :                     call setRebound(stat%sample%avg, 0_IK, ndim)
     964          39 :                     call setRebound(stat%sample%cov, [0_IK, 0_IK], [ndim, ndim])
     965          13 :                     call setMean(stat%sample%avg, stat%sfc%sampleLogFuncState(:, 1 : stat%sfc%nsam(stat%sfc%nref)), 2_IK, stat%sfc%sampleWeight(1 : stat%sfc%nsam(stat%sfc%nref)), stat%sfc%sumw(stat%sfc%nref))
     966          13 :                     if (ndim < stat%sfc%nsam(stat%sfc%nref)) then
     967          12 :                         call setCov(stat%sample%cov, lowDia, stat%sample%avg, stat%sfc%sampleLogFuncState(:, 1 : stat%sfc%nsam(stat%sfc%nref)), 2_IK, stat%sfc%sampleWeight(1:stat%sfc%nsam(stat%sfc%nref)), stat%sfc%sumw(stat%sfc%nref))
     968          12 :                         call setMatCopy(stat%sample%cov, rdpack, stat%sample%cov, rdpack, lowDia, transHerm)
     969         372 :                         stat%sample%cor = getCor(stat%sample%cov, subsetv = lowDia)
     970             :                     else
     971          16 :                         stat%sample%cor = getMatInit([ndim, ndim], uppLowDia, 0._RKC, 0._RKC, 0._RKC)
     972          16 :                         stat%sample%cov = getMatInit([ndim, ndim], uppLowDia, 0._RKC, 0._RKC, 0._RKC)
     973             :                     end if
     974             : 
     975             :                     ! Report the refined chain statistics.
     976             : 
     977             :                     !formatStr = "(1A"//spec%outputColumnWidth%max//SKC_",*(E"//spec%outputColumnWidth%max//SKC_"."//spec%outputPrecision%str//SKC_"))"
     978             : 
     979             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     980             : 
     981          13 :                     call spec%disp%show("stats.chain.refined.length")
     982          13 :                     call spec%disp%show(stat%sample%size, format = format)
     983          13 :                     spec%msg = "This is the final output refined sample size."
     984          13 :                     if (spec%outputSampleSize%val /= -1_IK) then
     985           7 :                         if (stat%sample%size < stat%ess) then
     986             :                             spec%msg = spec%msg//NL1//SKC_"The user-requested sample size ("//getStr(stat%sample%size)//SKC_") is smaller &
     987             :                             &than the potentially-optimal i.i.d. sample size ("//getStr(stat%ess)//SKC_"). The output sample &
     988             :                             &contains i.i.d. samples, however, the sample-size could have been larger if it had been set to the optimal size. &
     989           0 :                             &To get the optimal size in the future runs, set outputSampleSize = -1, or drop it from the input list."
     990           7 :                         elseif (stat%ess < stat%sample%size) then
     991             :                             spec%msg = spec%msg//NL1//SKC_"The user-requested sample size ("//getStr(stat%sample%size)//SKC_") is larger than &
     992             :                             &the potentially-optimal i.i.d. sample size ("//getStr(stat%ess)//SKC_"). The resulting sample likely contains &
     993             :                             &duplicates and is not independently and identically distributed (i.i.d.). To get the optimal &
     994           7 :                             &size in the future runs, set outputSampleSize = -1, or drop it from the input list."
     995             :                         else ! LCOV_EXCL_LINE
     996             :                             spec%msg = spec%msg//NL1//SKC_"How lucky that could be! The user-requested sample size ("//getStr(stat%sample%size)//& ! LCOV_EXCL_LINE
     997             :                             SKC_") is equal to the potentially-optimal i.i.d. sample size determined by the "//spec%method%val//SKC_" sampler." ! LCOV_EXCL_LINE
     998             :                         end if
     999             :                     end if
    1000          13 :                     call spec%disp%note%show(spec%msg)
    1001             : 
    1002             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1003             : 
    1004          13 :                     call spec%disp%show("stats.chain.refined.avg")
    1005          67 :                     call spec%disp%show(css_type(spec%domainAxisName%val), format = spec%reportFile%format%fixform, bmsize = 0_IK)
    1006          13 :                     call spec%disp%show(stat%sample%avg(1:), format = spec%reportFile%format%allreal)
    1007          13 :                     call spec%disp%note%show("This is the mean (avg) of the final output refined sample.")
    1008             : 
    1009             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1010             : 
    1011          13 :                     call spec%disp%show("stats.chain.refined.std")
    1012          67 :                     call spec%disp%show(css_type(spec%domainAxisName%val), format = spec%reportFile%format%fixform, bmsize = 0_IK)
    1013          67 :                     call spec%disp%show([(sqrt(stat%sample%cov(idim, idim)), idim = 1, ndim)], format = spec%reportFile%format%allreal)
    1014          13 :                     call spec%disp%note%show("This is the standard deviation (std) of the final output refined sample.")
    1015             : 
    1016             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1017             : 
    1018          13 :                     call spec%disp%show("stats.chain.refined.covmat")
    1019         120 :                     call spec%disp%show(css_type([character(len(spec%domainAxisName%val),SKC) :: SKC_"axis", spec%domainAxisName%val]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
    1020          13 :                     call spec%disp%skip(count = spec%disp%tmsize)
    1021          40 :                     do idim = 1, ndim
    1022          40 :                         write(spec%reportFile%unit, spec%reportFile%format%strreal) trim(adjustl(spec%domainAxisName%val(idim))), stat%sample%cov(1 : ndim, idim)
    1023             :                     end do
    1024          13 :                     call spec%disp%skip(count = spec%disp%bmsize)
    1025          13 :                     call spec%disp%note%show("This is the covariance matrix of the final output refined sample.")
    1026          13 :                     if (.not. isMatClass(stat%sample%cov, posdefmat)) call spec%disp%warn%show("The sample covariance matrix is not positive-definite. sample size = "//getStr(stat%sfc%nsam(stat%sfc%nref)))
    1027             : 
    1028             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1029             : 
    1030          13 :                     call spec%disp%show("stats.chain.refined.cormat")
    1031         120 :                     call spec%disp%show(css_type([character(len(spec%domainAxisName%val),SKC) :: SKC_"axis", spec%domainAxisName%val]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
    1032          13 :                     call spec%disp%skip(count = spec%disp%tmsize)
    1033          40 :                     do idim = 1, ndim
    1034          40 :                         write(spec%reportFile%unit, spec%reportFile%format%strreal) trim(adjustl(spec%domainAxisName%val(idim))), stat%sample%cor(1 : ndim, idim)
    1035             :                     end do
    1036          13 :                     call spec%disp%skip(count = spec%disp%bmsize)
    1037          13 :                     call spec%disp%note%show("This is the correlation matrix of the final output refined sample.")
    1038          13 :                     if (.not. isMatClass(stat%sample%cor, posdefmat)) call spec%disp%warn%show("The sample correlation matrix is not positive-definite. sample size = "//getStr(stat%sfc%nsam(stat%sfc%nref)))
    1039             : 
    1040             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1041             : 
    1042             :                     ! Compute the sample quantiles.
    1043             :                     ! \bug Intel ifort bug with heap memory allocations:
    1044             :                     ! The Intel ifort cannot digest the following task for an input 2D sample, throwing `double free or corruption (out)`.
    1045             :                     ! The source of this error was traced back to the return point from `setExtrap()` within `getQuan()`.
    1046             :                     ! The runtime error seems to resolve if the quantile matrix is computed in a loop like the following.
    1047             : 
    1048          39 :                     call setResized(stat%sample%quantile%quan, [size(stat%sample%quantile%prob, 1, IK), ndim])
    1049             :                     block
    1050             :                         real(RKC), allocatable :: sample(:)
    1051          40 :                         do idim = 1, ndim
    1052      314252 :                             sample = stat%sfc%sampleLogFuncState(idim, :)
    1053         283 :                             stat%sample%quantile%quan(:, idim) = getQuan(neimean, stat%sample%quantile%prob, sample, stat%sfc%sampleWeight, stat%sfc%sumw(stat%sfc%nref))
    1054             :                         end do
    1055             :                     end block
    1056             :                     !stat%sample%quantile%quan = getQuan(neimean, stat%sample%quantile%prob, stat%sfc%sampleLogFuncState, 2_IK, stat%sfc%sampleWeight, stat%sfc%sumw(stat%sfc%nref))
    1057             : 
    1058          13 :                     call spec%disp%show("stats.chain.refined.quantile")
    1059         120 :                     call spec%disp%show(css_type([character(len(spec%domainAxisName%val),SKC) :: "quantile", spec%domainAxisName%val]), format = spec%reportFile%format%fixform, bmsize = 0_IK)
    1060          13 :                     call spec%disp%skip(count = spec%disp%tmsize)
    1061         130 :                     do iq = 1, size(stat%sample%quantile%prob, 1, IK)
    1062         373 :                         write(spec%reportFile%unit, spec%reportFile%format%allreal) stat%sample%quantile%prob(iq), (stat%sample%quantile%quan(iq, idim), idim = 1, ndim)
    1063             :                     end do
    1064          13 :                     call spec%disp%skip(count = spec%disp%bmsize)
    1065          13 :                     call spec%disp%note%show("This is the quantiles table of the variables of the final output refined sample.")
    1066             : 
    1067             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1068             :                     ! Begin inter-chain convergence test in multiChain parallelization mode
    1069             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1070             : 
    1071             : #if                 CAF_ENABLED || MPI_ENABLED || OMP_ENABLED
    1072             :                     blockInterChainConvergence: if (spec%parallelism%is%multiChain .and. spec%image%count > 1_IK) then
    1073             : 
    1074             :                         call spec%disp%note%show("Computing the inter-chain convergence probabilities...")
    1075             :                         if (spec%image%is%first .and. .not. spec%outputSplashMode%is%silent) then
    1076             :                             call spec%disp%note%show("Computing the inter-chain convergence probabilities...", unit = output_unit, bmsize = 0_IK)
    1077             :                         end if
    1078             :                         call spec%image%sync()
    1079             : 
    1080             :                         ! compute and report the KS convergence probabilities for all images.
    1081             : 
    1082             :                         multiChainConvergenceTest: block
    1083             : 
    1084             :                             real(RKC), allocatable :: sampleLogFuncState1(:,:)
    1085             :                             real(RKC), allocatable :: sampleLogFuncState2(:,:)
    1086             :                             integer(IK) :: imageID, idimMinProbKS, pidMinProbKS
    1087             :                             character(:, SK), allocatable :: sampleFilePath
    1088             :                             real(RKC), allocatable :: probKS(:)
    1089             :                             real(RKC) :: minProbKS
    1090             : 
    1091             :                             minProbKS = 2._RKC !huge(minProbKS)
    1092             :                             call setResized(probKS, ndim + 1_IK)
    1093             :                             !call setRebound(probKS, 0_IK, ndim)
    1094             : 
    1095             :                             ! sort the refined chain on the current image.
    1096             : 
    1097             :                             err%stat = getErrTableRead(spec%sampleFile%file, sampleLogFuncState1, trans, sep = spec%outputSeparator%val, roff = 1_IK)
    1098             :                             err%occurred = err%stat /= 0_IK
    1099             :                             if (err%occurred) then
    1100             :                                 err%msg = PROCEDURE_NAME//SKC_": "//err%msg ! LCOV_EXCL_LINE
    1101             :                                 exit blockLeaderPostProcessing ! LCOV_EXCL_LINE
    1102             :                             end if
    1103             :                             do idim = 1, ndim + 1
    1104             :                                 call setSorted(sampleLogFuncState1(:, idim))
    1105             :                             end do
    1106             : 
    1107             :                             !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1108             : 
    1109             :                             call spec%disp%show("stats.chain.refined.kstest.prob")
    1110             :                             call spec%disp%show([css_type("processID"), stat%sfc%colname], format = spec%reportFile%format%fixform, bmsize = 0_IK)
    1111             : 
    1112             :                             do imageID = 1, spec%image%count
    1113             : 
    1114             :                                 if (spec%image%id /= imageID) then
    1115             : 
    1116             :                                     ! read the refined chain on the other image.
    1117             :                                     sampleFilePath = getReplaced(spec%sampleFile%file, spec%sampleFile%suffix, getReplaced(spec%sampleFile%suffix, SKC_"_pid"//getStr(spec%image%id), SKC_"_pid"//getStr(imageID)))
    1118             :                                     err%stat = getErrTableRead(sampleFilePath, sampleLogFuncState2, trans, sep = spec%outputSeparator%val, roff = 1_IK)
    1119             :                                     err%occurred = err%stat /= 0_IK
    1120             :                                     if (err%occurred) then
    1121             :                                         err%msg = PROCEDURE_NAME//SKC_": "//err%msg ! LCOV_EXCL_LINE
    1122             :                                         exit blockLeaderPostProcessing ! LCOV_EXCL_LINE
    1123             :                                     end if
    1124             : 
    1125             :                                     do idim = 1, ndim + 1
    1126             :                                         ! sort the refined chain on the other image.
    1127             :                                         call setSorted(sampleLogFuncState2(:, idim))
    1128             :                                         ! compute the inter-chain KS probability table.
    1129             :                                         probKS(idim) = getProbKS(getDisKolm(sampleLogFuncState1(:, idim), sampleLogFuncState2(:, idim), ascending), size(sampleLogFuncState1, 1, IK), size(sampleLogFuncState2, 1, IK))
    1130             :                                         if (minProbKS <= probKS(idim)) cycle
    1131             :                                         minProbKS = probKS(idim)
    1132             :                                         pidMinProbKS = imageID
    1133             :                                         idimMinProbKS = idim
    1134             :                                     end do
    1135             : 
    1136             :                                     ! write the inter-chain KS probability table row
    1137             : 
    1138             :                                     write(spec%reportFile%unit, spec%reportFile%format%intreal) imageID, probKS
    1139             : 
    1140             :                                 end if
    1141             : 
    1142             :                             end do
    1143             : 
    1144             :                             call spec%disp%skip(count = spec%disp%bmsize)
    1145             :                             spec%msg = SKC_"This is the table of pairwise inter-chain Kolmogorov-Smirnov (KS) convergence (similarity) probabilities. &
    1146             :                             &Higher KS probabilities are better, presenting less evidence for a lack of convergence of all chains to the same target density function."
    1147             :                             call spec%disp%note%show(spec%msg)
    1148             : 
    1149             :                             ! write the smallest KS probabilities
    1150             : 
    1151             :                             !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1152             : 
    1153             :                             call spec%disp%show("stats.chain.refined.kstest.prob.min")
    1154             :                             call spec%disp%show(minProbKS, format = format)
    1155             :                             spec%msg = SKC_"This is the smallest KS-test probability for the inter-chain sampling convergence, which has happened between "//&
    1156             :                             stat%sfc%colname(idimMinProbKS)%val//SKC_" on the chains generated by processes "//getStr(spec%image%id)//SKC_" and "//getStr(pidMinProbKS)//SKC_"."
    1157             :                             call spec%disp%note%show(spec%msg)
    1158             : 
    1159             :                             ! Report the smallest KS probabilities on stdout.
    1160             : 
    1161             :                             if (.not. spec%outputSplashMode%is%silent) then
    1162             :                                 if (spec%image%is%first) then
    1163             :                                     call spec%disp%note%show("The smallest KS probabilities for the inter-chain sampling convergence (higher is better):", unit = output_unit, bmsize = 0_IK)!, tmsize = 2_IK
    1164             :                                 end if
    1165             :                                 do imageID = 1, spec%image%count
    1166             :                                     if (spec%image%id == imageID) then
    1167             :                                         spec%msg = getStr(minProbKS)//SKC_" for "//stat%sfc%colname(idimMinProbKS)%val//&
    1168             :                                         SKC_" on the chains generated by processes "//getStr(spec%image%id)//SKC_" and "//getStr(pidMinProbKS)//SKC_"."
    1169             :                                         call spec%disp%note%show(spec%msg, unit = output_unit, tmsize = 0_IK, bmsize = 0_IK)
    1170             :                                     end if
    1171             :                                     flush(output_unit)
    1172             :                                     call spec%image%sync()
    1173             :                                 end do
    1174             :                                 if (spec%image%is%first) then
    1175             :                                     call execute_command_line("", cmdstat = err%stat)
    1176             :                                     if (1 < spec%disp%bmsize) call spec%disp%skip(unit = output_unit, count = spec%disp%bmsize - 1)
    1177             :                                 end if
    1178             :                             end if
    1179             : 
    1180             :                         end block multiChainConvergenceTest
    1181             : 
    1182             :                         call spec%image%sync()
    1183             : 
    1184             :                     end if blockInterChainConvergence
    1185             : #endif
    1186             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1187             :                     ! End inter-chain convergence test in multiChain parallelization mode
    1188             :                     !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1189             : 
    1190             :                 end if blockSampleFileGeneration
    1191             : 
    1192             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1193             :                 ! End of generating the i.i.d. sample statistics and output file (if requested)
    1194             :                 !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    1195             : 
    1196             :                 ! Mission accomplished.
    1197             : 
    1198          13 :                 call spec%disp%note%show("Mission Accomplished.", tmsize = 2_IK * spec%disp%note%tmsize)!, tmsize = 3_IK, bmsize = 1_IK
    1199          13 :                 if (spec%reportFile%unit /= output_unit .and. spec%image%is%first .and. .not. spec%outputSplashMode%is%silent) then
    1200          13 :                     flush(output_unit)
    1201          13 :                     call execute_command_line("", cmdstat = err%stat)
    1202          13 :                     call spec%disp%note%show("Mission Accomplished.", unit = output_unit, tmsize = 1_IK)!, tmsize = 1_IK, bmsize = 3_IK)
    1203             :                 end if
    1204          13 :                 close(spec%progressFile%unit)
    1205          13 :                 close(spec%reportFile%unit)
    1206          39 :                 err%msg = SK_""
    1207             : 
    1208             :             end associate
    1209             : 
    1210             :         end if blockLeaderPostProcessing
    1211             : 
    1212             :         ! A global sync is essential for parallel applications.
    1213             : 
    1214             :         SET_CAFMPI(call spec%image%sync())
    1215             :         SET_CAFMPI(if (spec%parallelismMpiFinalizeEnabled%val) call spec%image%finalize())
    1216             : #else
    1217             :         !%%%%%%%%%%%%%%%%%%%%%%%%
    1218             : #error  "Unrecognized interface."
    1219             :         !%%%%%%%%%%%%%%%%%%%%%%%%
    1220             : #endif
    1221             : #undef  RETURN_IF_FAILED
    1222             : #undef  SET_DRAMDISE
    1223             : #undef  SET_ParaNest
    1224             : #undef  SET_CAFMPI
    1225             : #undef  SET_SERIAL
    1226             : #undef  SET_DEBUG
    1227             : #undef  SET_CAF
    1228             : #undef  SET_MPI
    1229             : #undef  SET_OMP
    1230             : #undef  COINDEX
    1231             : #undef  TRACE

ParaMonte: Parallel Monte Carlo and Machine Learning Library 
The Computational Data Science Lab
© Copyright 2012 - 2024