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 : #if CHECK_ENABLED
18 : use pm_err, only: setAsserted
19 : #define CHECK_ASSERTION(LINE,ASSERTION,MSG) \
20 : call setAsserted(ASSERTION,getFine(__FILE__,LINE)//MODULE_NAME//MSG);
21 : #else
22 : #define CHECK_ASSERTION(LINE,ASSERTION,MSG) continue;
23 : #endif
24 : use pm_kind, only: SKC => SK, SK, IK, LK
25 : use pm_matrixClass, only: isMatClass, posdefmat
26 : use pm_sampling_base, only: specbase_type, astatbase_type, sfcbase_type, NL2, NL1
27 : use pm_arrayRemove, only: getRemoved
28 : use pm_arrayResize, only: setResized
29 : use pm_strASCII, only: getStrLower
30 : use pm_val2str, only: getStr
31 : use pm_except, only: setNAN
32 : use pm_except, only: isNAN
33 : use pm_strASCII, only: SUB
34 : use pm_err, only: err_type
35 : use pm_err, only: getFine
36 :
37 : implicit none
38 :
39 : character(*,SKC) , parameter :: MODULE_NAME = SK_"@pm_sampling_mcmc"
40 :
41 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 : ! simulation declarations.
43 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
44 :
45 : type :: burninLoc_type
46 : integer(IK) :: compact
47 : integer(IK) :: verbose
48 : end type
49 :
50 : ! type for chain refinements
51 : type, extends(sfcbase_type) :: sfcmcmc_type
52 : real(RKC) , allocatable :: act(:,:) !< \public The array of shape `(1:ndim, 0:nref)` containing he Integrated AutoCorrelation Time at each refinement stage.
53 : contains
54 : procedure , pass :: getErrRefinement
55 : end type
56 :
57 : type, abstract, extends(astatbase_type) :: astatmcmc_type
58 : type(burninLoc_type) :: burninLocMCMC
59 : type(sfcmcmc_type) :: sfc
60 : end type
61 :
62 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63 : ! specification declarations.
64 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65 :
66 : !integer(IK) :: outputChainSize ! namelist input
67 : type :: outputChainSize_type
68 : integer(IK) :: val
69 : integer(IK) :: def
70 : integer(IK) :: null
71 : character(:,SKC) , allocatable :: desc
72 : end type
73 :
74 : !integer(IK) :: outputSampleRefinementCount ! namelist input
75 : type :: outputSampleRefinementCount_type
76 : character(:,SKC) , allocatable :: str
77 : integer(IK) :: val
78 : integer(IK) :: def
79 : integer(IK) :: null
80 : character(:,SKC) , allocatable :: desc
81 : end type
82 :
83 : !character(63,SKC) :: outputSampleRefinementMethod ! namelist input
84 : type :: outputSampleRefinementMethod_type
85 : logical(LK) :: isBatchMeansCompact = .false._LK
86 : logical(LK) :: isBatchMeansVerbose = .false._LK
87 : logical(LK) :: isMaxCumSumACF = .false._LK
88 : logical(LK) :: isBatchMeans = .false._LK
89 : character(12,SKC) :: maxCumSumACF = "maxCumSumACF"
90 : character(10,SKC) :: batchMeans = "BatchMeans"
91 : character(9,SKC) :: cutoffACF = "cutoffACF"
92 : character(:,SKC) , allocatable :: def
93 : character(:,SKC) , allocatable :: val
94 : character(:,SKC) , allocatable :: null
95 : character(:,SKC) , allocatable :: desc
96 : end type
97 :
98 : !character(63,SKC) :: proposal ! namelist input
99 : type :: proposalis_type
100 : logical(LK) :: normal = .false._LK
101 : logical(LK) :: uniform = .false._LK
102 : end type
103 : type :: proposal_type
104 : type(proposalis_type) :: is
105 : character(7,SKC) :: uniform
106 : character(6,SKC) :: normal
107 : character(:,SKC) , allocatable :: val
108 : character(:,SKC) , allocatable :: def
109 : character(:,SKC) , allocatable :: null
110 : character(:,SKC) , allocatable :: desc
111 : end type
112 :
113 : !real(RKC) , allocatable :: proposalCorMat(:,:) ! namelist input
114 : type :: proposalCorMat_type
115 : real(RKC) , allocatable :: val(:,:)
116 : real(RKC) , allocatable :: def(:,:)
117 : character(:,SKC) , allocatable :: desc
118 : end type
119 :
120 : !real(RKC) , allocatable :: proposalCovMat(:,:) ! namelist input
121 : type :: proposalCovMat_type
122 : logical(LK) :: isUserSet
123 : real(RKC) , allocatable :: def(:,:)
124 : real(RKC) , allocatable :: val(:,:)
125 : character(:,SKC) , allocatable :: desc
126 : end type
127 :
128 : !character(127,SKC) :: proposalScaleFactor
129 : type :: proposalScaleFactor_type
130 : real(RKC) :: val, valdef
131 : character(:,SKC) , allocatable :: str, strdef, null, desc
132 : end type
133 :
134 : !real(RKC) , allocatable :: proposalStart(:) ! namelist input
135 : type :: proposalStart_type
136 : real(RKC) , allocatable :: val(:)
137 : character(:,SKC) , allocatable :: desc
138 : end type
139 :
140 : !real(RKC) , allocatable :: proposalStartDomainCubeLimitLower(:) ! namelist input
141 : type :: proposalStartDomainCubeLimitLower_type
142 : real(RKC) :: null
143 : real(RKC) :: def
144 : real(RKC) , allocatable :: val(:)
145 : character(:,SKC) , allocatable :: desc
146 : end type
147 :
148 : !real(RKC) , allocatable :: proposalStartDomainCubeLimitUpper(:) ! namelist input
149 : type :: proposalStartDomainCubeLimitUpper_type
150 : real(RKC) :: def
151 : real(RKC) , allocatable :: val(:)
152 : character(:,SKC) , allocatable :: desc
153 : end type
154 :
155 : !logical(LK) :: proposalStartRandomized ! namelist input
156 : type :: proposalStartRandomized_type
157 : logical(LK) :: val
158 : logical(LK) :: def
159 : character(:,SKC) , allocatable :: desc
160 : end type
161 :
162 : !real(RKC) , allocatable :: proposalStdVec(:) ! namelist input
163 : type :: proposalStdVec_type
164 : real(RKC) , allocatable :: val(:)
165 : real(RKC) , allocatable :: def(:)
166 : character(:,SKC) , allocatable :: desc
167 : end type
168 :
169 : type, extends(specbase_type) :: specmcmc_type
170 : type(outputChainSize_type) :: outputChainSize
171 : type(proposal_type) :: proposal
172 : type(ProposalScaleFactor_type) :: ProposalScaleFactor
173 : type(proposalStart_type) :: proposalStart
174 : type(proposalStdVec_type) :: proposalStdVec
175 : type(proposalCorMat_type) :: proposalCorMat
176 : type(proposalCovMat_type) :: proposalCovMat
177 : type(outputSampleRefinementCount_type) :: outputSampleRefinementCount
178 : type(outputSampleRefinementMethod_type) :: outputSampleRefinementMethod
179 : type(proposalStartRandomized_type) :: proposalStartRandomized
180 : type(proposalStartDomainCubeLimitLower_type) :: proposalStartDomainCubeLimitLower
181 : type(proposalStartDomainCubeLimitUpper_type) :: proposalStartDomainCubeLimitUpper
182 : contains
183 : procedure, pass, private :: sanitize
184 : procedure, pass, private :: report
185 : procedure, pass, public :: set
186 : end type
187 :
188 : interface specmcmc_type
189 : module procedure :: construct
190 : end interface
191 :
192 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193 :
194 : type, private :: method_type
195 : logical(LK) :: isMax = .false._LK
196 : logical(LK) :: isMed = .false._LK
197 : logical(LK) :: isMin = .false._LK
198 : logical(LK) :: isAvg = .false._LK
199 : logical(LK) :: isCumSum = .false._LK
200 : logical(LK) :: isCumSumMax = .false._LK
201 : logical(LK) :: isBatchMeans = .false._LK
202 : logical(LK) :: isBatchMeansMax = .false._LK
203 : logical(LK) :: isViaCompactChain = .true._LK
204 : logical(LK) :: isViaVerboseChain = .true._LK
205 : end type
206 :
207 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208 :
209 : contains
210 :
211 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212 :
213 0 : subroutine killMeAlreadyCMake1_RK5(); use pm_sampling_scio_RK5, only: RKC; end subroutine
214 0 : subroutine killMeAlreadyCMake1_RK4(); use pm_sampling_scio_RK4, only: RKC; end subroutine
215 0 : subroutine killMeAlreadyCMake1_RK3(); use pm_sampling_scio_RK3, only: RKC; end subroutine
216 0 : subroutine killMeAlreadyCMake1_RK2(); use pm_sampling_scio_RK2, only: RKC; end subroutine
217 0 : subroutine killMeAlreadyCMake1_RK1(); use pm_sampling_scio_RK1, only: RKC; end subroutine
218 :
219 0 : subroutine killMeAlreadyCMake2_RK5(); use pm_sampling_base_RK5, only: RKC; end subroutine
220 0 : subroutine killMeAlreadyCMake2_RK4(); use pm_sampling_base_RK4, only: RKC; end subroutine
221 0 : subroutine killMeAlreadyCMake2_RK3(); use pm_sampling_base_RK3, only: RKC; end subroutine
222 0 : subroutine killMeAlreadyCMake2_RK2(); use pm_sampling_base_RK2, only: RKC; end subroutine
223 0 : subroutine killMeAlreadyCMake2_RK1(); use pm_sampling_base_RK1, only: RKC; end subroutine
224 :
225 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226 :
227 14 : function construct(modelr, method, ndim) result(spec)
228 : #if __INTEL_COMPILER && DLL_ENABLED && (_WIN32 || _WIN64)
229 : !DEC$ ATTRIBUTES DLLEXPORT :: construct
230 : #endif
231 : use pm_kind, only: modelr_type
232 : type(modelr_type), intent(in) :: modelr
233 : character(*,SKC), intent(in) :: method
234 : integer(IK), intent(in) :: ndim
235 : type(specmcmc_type) :: spec
236 :
237 14 : spec%specbase_type = specbase_type(modelr, method, ndim)
238 :
239 : outputChainSize_block: block
240 : use pm_sampling_scio, only: outputChainSize
241 14 : spec%outputChainSize%null = -huge(0_IK)
242 14 : spec%outputChainSize%def = 100000_IK
243 : spec%outputChainSize%desc = &
244 : SKC_"The simulation specification `outputChainSize` is a positive scalar of type `integer` whose value determines the number &
245 : &of non-refined, potentially auto-correlated, but unique samples drawn by the MCMC sampler before stopping the sampling. &
246 : &For example, if `outputChainSize = 10000`, then `10000` unique sample points (with no duplicates) will be drawn from the &
247 : &target objective function that the user has provided. &
248 : &The input value for `outputChainSize` must be a positive integer of a minimum value `ndim + 1` or larger, &
249 : &where `ndim` is the number of dimensions of the domain of the objective function to be sampled. &
250 : &Note that `outputChainSize` is different from and always smaller than the length of the constructed MCMC chain. &
251 14 : &The default value for `outputChainSize` is `"//getStr(spec%outputChainSize%def)//SKC_"`."
252 : !!$omp master
253 14 : outputChainSize = spec%outputChainSize%null
254 : !!$omp end master
255 : end block outputChainSize_block
256 :
257 : outputSampleRefinementCount_block: block
258 : use pm_sampling_scio, only: outputSampleRefinementCount
259 14 : spec%outputSampleRefinementCount%null = -huge(0_IK)
260 14 : spec%outputSampleRefinementCount%def = huge(0_IK)
261 : spec%outputSampleRefinementCount%desc = &
262 : SKC_"The simulation specification `outputSampleRefinementCount` is a positive-valued scalar of type `integer`. &
263 : &When `outputSampleSize < 0`, the value of `outputSampleRefinementCount` dictates the maximum number of times &
264 : &the MCMC chain will be refined to remove the autocorrelation within the output MCMC sample. For example,"//NL2//&
265 : SKC_"+ if `outputSampleRefinementCount = 0`,"//NL2//&
266 : SKC_" no refinement of the output MCMC chain will be performed. The resulting MCMC sample will correspond &
267 : &to the full MCMC chain in verbose format (i.e., each sampled state has a weight of one)."//NL2//&
268 : SKC_"+ if `outputSampleRefinementCount = 1`,"//NL2//&
269 : SKC_" the refinement of the output MCMC chain will be done only once if needed, and no more, &
270 : &even though some residual autocorrelation in the output MCMC sample may still exist. &
271 : &In practice, only one refinement of the final output MCMC chain should be enough to remove &
272 : &the existing autocorrelations in the final output sample. Exceptions occur when the integrated &
273 : &Autocorrelation (ACT) of the output MCMC chain is comparable to or larger than the length of the chain. &
274 : &In such cases, neither the BatchMeans method nor any other method of ACT computation will be able to &
275 : &accurately compute the ACT. Consequently, the samples generated based on the computed ACT values will &
276 : &likely not be i.i.d. and will still be significantly autocorrelated. In such scenarios, more than &
277 : &one refinement of the MCMC chain will be necessary. Very small sample size resulting from multiple &
278 : &refinements of the sample could be a strong indication of the bad mixing of the MCMC chain and &
279 : &the lack of convergence to the target objective function."//NL2//&
280 : SKC_"+ if `outputSampleRefinementCount > 1`,"//NL2//&
281 : SKC_" the refinement of the output MCMC chain will be done for a maximum `outputSampleRefinementCount` number of &
282 : ×, even though some residual autocorrelation in the final output MCMC sample may still exist."//NL2//&
283 : SKC_"+ if `outputSampleRefinementCount >> 1` (e.g., comparable to or larger than the length of the MCMC chain),"//NL2//&
284 : SKC_" the refinement of the output MCMC chain will continue until the integrated autocorrelation of the resulting &
285 : &final sample is less than 2, virtually implying that an independent identically-distributed (i.i.d.) sample &
286 : &from the target objective function has finally been obtained."//NL2//&
287 : SKC_"Note that to obtain i.i.d. samples from a multidimensional chain, the sampler will, by default, use the maximum of &
288 : &integrated Autocorrelation (ACT) among all chain dimensions to refine the chain. &
289 : &Note that the value specified for `outputSampleRefinementCount` is used only when the variable `outputSampleSize < 0`, &
290 14 : &otherwise, it will be ignored. The default value for `outputSampleRefinementCount` is `"//getStr(spec%outputSampleRefinementCount%def)//SKC_"`."
291 : !!$omp master
292 14 : outputSampleRefinementCount = spec%outputSampleRefinementCount%null
293 : !!$omp end master
294 : end block outputSampleRefinementCount_block
295 :
296 : outputSampleRefinementMethod_block: block
297 : use pm_sampling_scio, only: outputSampleRefinementMethod
298 14 : spec%outputSampleRefinementMethod%def = spec%outputSampleRefinementMethod%batchMeans
299 14 : spec%outputSampleRefinementMethod%null = repeat(SUB, len(outputSampleRefinementMethod, IK))
300 : spec%outputSampleRefinementMethod%desc = &
301 : SKC_"The simulation specification `outputSampleRefinementMethod` is a scalar string of maximum length `"//getStr(len(outputSampleRefinementMethod, IK))//&
302 : SKC_"` representing the method of computing the (integrated) AutoCorrelation Time (ACT) to be used in the simulation for refining &
303 : &the final output MCMC chain and sample. If specified within an external input file, it must be either singly or doubly quoted. &
304 : &Methods that are currently supported include:"//NL2//&
305 : SKC_"+ `outputSampleRefinementMethod = '"//spec%outputSampleRefinementMethod%batchMeans//SKC_"'`"//NL2//&
306 : SKC_" This method of computing the integrated Autocorrelation Time is based on the approach described in"//NL2//&
307 : SKC_" SCHMEISER, B., 1982, Batch size effects in the analysis of simulation output, Oper. Res. 30 556-568."//NL2//&
308 : SKC_" The batch sizes in the BatchMeans method are chosen to be `int(N^(2/3))`, where `N` is the length of the MCMC chain. &
309 : &As long as the batch size is larger than the ACT of the chain and there are significantly more than `10` batches, &
310 : &the BatchMeans method will provide reliable estimates of the ACT. &
311 : &Note that the refinement strategy involves two separate phases of sample decorrelation. At the first stage, &
312 : &the Markov chain is decorrelated recursively (for as long as needed) based on the ACT of its compact format, &
313 : &where only the uniquely visited states are kept in the (compact) chain. Once the Markov chain is refined &
314 : &such that its compact format is fully decorrelated, the second phase of the decorrelation begins, during which &
315 : &the Markov chain is decorrelated based on the ACT of the chain in its verbose (Markov) format. This process &
316 : &is repeated recursively for as long as residual autocorrelation exists in the refined sample."//NL2//&
317 : SKC_"+ `outputSampleRefinementMethod = '"//spec%outputSampleRefinementMethod%batchMeans//SKC_"-compact'`"//NL2//&
318 : SKC_" This is the same as the first case in the above, except that only the first phase of the sample refinement &
319 : &described in the above will be performed; that is, the (verbose) Markov chain is refined only based on the &
320 : &ACT computed from the compact format of the Markov chain. This will lead to a larger, final, refined sample. &
321 : &However, the final sample will likely not be fully decorrelated."//NL2//&
322 : SKC_"+ `outputSampleRefinementMethod = '"//spec%outputSampleRefinementMethod%batchMeans//SKC_"-verbose'`"//NL2//&
323 : SKC_" This is the same as the first case in the above, except that only the second phase of the sample refinement &
324 : &described in the above will be performed; that is, the (verbose) Markov chain is refined only based on the ACT &
325 : &computed from the verbose format of the Markov chain. While the resulting refined sample will be fully decorrelated, &
326 : &the size of the refined sample may be smaller than the default choice in the first case in the above."//NL2//&
327 : SKC_"Note that to obtain i.i.d. samples from a multidimensional chain, the sampler will use the average of the &
328 : &ACT among all dimensions of the chain to refine the chain. If the maximum, minimum, or the median of IACs is preferred &
329 : &add `'-max'` (or `'-maximum'`), `'-min'` (or `'-minimum'`), `'-med'` (or `'-median'`), respectively, to the value of &
330 : &`outputSampleRefinementMethod`. For example, "//NL2//&
331 : SKC_"+ `outputSampleRefinementMethod = '"//spec%outputSampleRefinementMethod%batchMeans//SKC_"-max'`"//NL2//&
332 : SKC_"or, "//NL2//&
333 : SKC_"+ `outputSampleRefinementMethod = '"//spec%outputSampleRefinementMethod%batchMeans//SKC_"-compact-max'`"//NL2//&
334 : SKC_"or, "//NL2//&
335 : SKC_"+ `outputSampleRefinementMethod = '"//spec%outputSampleRefinementMethod%batchMeans//SKC_"-max-compact'`"//NL2//&
336 : SKC_"Note that the specified `outputSampleRefinementCount` is used only when the condition `outputSampleSize < 0` holds. &
337 : &Otherwise, it is ignored. The default value for `outputSampleRefinementMethod` is `'"//spec%outputSampleRefinementMethod%def//SKC_"'`. &
338 14 : &Note that the input values are case-INsensitive and white-space characters are ignored."
339 : !!$omp master
340 14 : outputSampleRefinementMethod = spec%outputSampleRefinementMethod%null
341 : !!$omp end master
342 : end block outputSampleRefinementMethod_block
343 :
344 : proposal_block: block
345 : use pm_sampling_scio, only: proposal
346 14 : spec%proposal%is%uniform = .false._LK
347 14 : spec%proposal%is%normal = .false._LK
348 14 : spec%proposal%uniform = "uniform"
349 14 : spec%proposal%normal = "normal"
350 14 : spec%proposal%def = spec%proposal%normal
351 14 : spec%proposal%null = repeat(SUB, len(proposal, IK))
352 : spec%proposal%desc = &
353 : SKC_"The simulation specification `proposal` is a scalar string of maximum length `"//getStr(len(proposal, IK))//SKC_"` containing &
354 : &the name of the proposal distribution for the MCMC sampler. When specified from within an external input file, it must &
355 : &be singly or doubly quoted. Options that are currently supported include:"//NL2//&
356 : SKC_"+ `proposal = '"//spec%proposal%normal//SKC_"'`"//NL2//&
357 : SKC_" This is equivalent to the multivariate normal distribution, &
358 : &which is the most widely-used proposal model along with MCMC samplers."//NL2//&
359 : SKC_"+ `proposal = '"//spec%proposal%uniform//SKC_"'`"//NL2//&
360 : SKC_" The proposals will be drawn uniformly from within a ndim-dimensional ellipsoid whose covariance matrix &
361 : &and scale are initialized by the user and optionally adaptively updated throughout the simulation."//NL2//&
362 14 : SKC_"The default value for `proposal` is `'"//spec%proposal%def//SKC_"'`."
363 : !!$omp master
364 14 : proposal = spec%proposal%null
365 : !!$omp end master
366 : end block proposal_block
367 :
368 : proposalCorMat_block: block
369 : use pm_except, only: setNAN
370 : use pm_sampling_scio, only: proposalCorMat
371 : use pm_matrixInit, only: getMatInit, uppLowDia
372 272 : spec%proposalCorMat%def = getMatInit([ndim, ndim], uppLowDia, 0._RKC, 0._RKC, 1._RKC)
373 : spec%proposalCorMat%desc = &
374 : SKC_"The simulation specification `proposalCorMat` is a positive-definite square matrix of type `real` of the highest precision &
375 : &available within the ParaMonte library matrix of size `(ndim, ndim)`, where `ndim` is the dimension of the sampling space. &
376 : &It serves as the best-guess starting correlation matrix of the proposal distribution used by the sampler. &
377 : &It is used (along with the input vector `proposalStdVec`) to construct the covariance matrix of the proposal &
378 : &distribution when the input covariance matrix is missing in the input list of variables. &
379 : &If the covariance matrix is specified as input to the sampler, any input values for `proposalCorMat`, &
380 : &and `proposalStdVec` will be automatically ignored. Specifying `proposalCorMat` along with `proposalStdVec` is especially &
381 : &useful when obtaining the best-guess covariance matrix is not trivial. &
382 14 : &The default value for `proposalCorMat` is a square Identity matrix of rank `ndim`."
383 : !!$omp master
384 14 : if (allocated(proposalCorMat)) deallocate(proposalCorMat)
385 27 : allocate(proposalCorMat(ndim, ndim))
386 122 : call setNAN(proposalCorMat)
387 : !!$omp end master
388 : end block proposalCorMat_block
389 :
390 : proposalCovMat_block: block
391 : use pm_except, only: setNAN
392 : use pm_sampling_scio, only: proposalCovMat
393 : use pm_matrixInit, only: getMatInit, uppLowDia
394 272 : spec%proposalCovMat%def = getMatInit([ndim, ndim], uppLowDia, 0._RKC, 0._RKC, 1._RKC)
395 : ! This must be set here. It is important for the proper setting from inputFile and inputArg.
396 14 : spec%proposalCovMat%isUserSet = .false._LK
397 : spec%proposalCovMat%desc = &
398 : SKC_"The simulation specification `proposalCovMat` is a square positive-definite matrix of type `real` of the highest precision &
399 : &available within the ParaMonte library, of shape `(ndim, ndim)`, where `ndim` is the number of dimensions of the sampling space. &
400 : &It serves as the best-guess starting covariance matrix of the proposal distribution. &
401 : &To bring the sampling efficiency of the sampler to within the desired requested range, the covariance matrix will &
402 : &be adaptively updated throughout the simulation, according to the user-specified schedule. If `proposalCovMat` &
403 : &is not provided by the user or it is completely missing from the input file, its value will be automatically &
404 : &computed via the input variables `proposalCorMat` and `proposalStdVec` (or via their default values, if not provided). &
405 : &If the simulation specification `outputStatus` is set to ""extend"" and a successful prior simulation run exists, &
406 : &then `proposalCovMat` will be set to the covariance matrix of the output sample from the most recent simulation run. &
407 : &In this case, the computed `proposalCovMat` will override any user-specified value. &
408 14 : &Otherwise, the default value for `proposalCovMat` is a square Identity matrix of rank `ndim`."
409 : !!$omp master
410 14 : if (allocated(proposalCovMat)) deallocate(proposalCovMat)
411 27 : allocate(proposalCovMat(ndim, ndim))
412 122 : call setNAN(proposalCovMat)
413 : !!$omp end master
414 : end block proposalCovMat_block
415 :
416 : proposalScaleFactor_block: block
417 : use pm_sampling_scio, only: proposalScaleFactor
418 14 : spec%proposalScaleFactor%strdef = SKC_"gelman"
419 14 : spec%proposalScaleFactor%valdef = 2.38_RKC / sqrt(real(ndim, RKC)) ! Gelman, Roberts, Gilks (1996): Efficient Metropolis Jumping Rules.
420 14 : spec%proposalScaleFactor%null = repeat(SUB, len(proposalScaleFactor, IK))
421 : spec%proposalScaleFactor%desc = &
422 : SKC_"The simulation specification `proposalScaleFactor` is a scalar string of maximum length `"//getStr(len(proposalScaleFactor, IK))//SKC_"` &
423 : &containing a positive real-valued number whose square will be multiplied with the covariance matrix of the proposal distribution &
424 : &of the MCMC sampler to shrink or enlarge it. In other words, the proposal distribution will be scaled in every direction &
425 : &by the specified numeric value of `proposalScaleFactor`. It can also be given in units of the string keyword `'gelman'` &
426 : &(which is case-INsensitive) after the paper:"//NL2//&
427 : SKC_" Gelman, Roberts, and Gilks (1996), Efficient Metropolis Jumping Rules."//NL2//&
428 : SKC_"The paper finds that the optimal scaling factor for a Multivariate Gaussian proposal distribution for the Metropolis-Hastings &
429 : &Markov Chain Monte Carlo sampling of a target Multivariate Normal Distribution of dimension `ndim` is given by:"//NL2//&
430 : SKC_" proposalScaleFactor = 2.38 / sqrt(ndim) , in the limit of ndim -> Infinity."//NL2//&
431 : SKC_"Multiples of the Gelman scale factors are also acceptable as input and can be specified like the following examples:"//NL2//&
432 : SKC_"+ `proposalScaleFactor = '1'`"//NL2//&
433 : SKC_" multiplies the ndim-dimensional proposal covariance matrix by 1, &
434 : &essentially no change occurs to the covariance matrix."//NL2//&
435 : SKC_"+ `proposalScaleFactor = ""1""`"//NL2//&
436 : SKC_" same as the previous example. The double-quotation marks act the same way as single-quotation marks."//NL2//&
437 : SKC_"+ `proposalScaleFactor = '2.5'`"//NL2//&
438 : SKC_" multiplies the ndim-dimensional proposal covariance matrix by 2.5."//NL2//&
439 : SKC_"+ `proposalScaleFactor = '2.5*Gelman'`"//NL2//&
440 : SKC_" multiplies the `ndim`-dimensional proposal covariance matrix by 2.5 * 2.38/sqrt(ndim)."//NL2//&
441 : SKC_"+ `proposalScaleFactor = ""2.5 * gelman""`"//NL2//&
442 : SKC_" same as the previous example but with double-quotation marks. space characters are ignored."//NL2//&
443 : SKC_"+ `proposalScaleFactor = ""2.5 * gelman*gelman*2""`"//NL2//&
444 : SKC_" equivalent to gelmanFactor-squared multiplied by `5`."//NL2//&
445 : SKC_"Note, however, that the result of Gelman et al. paper applies only to multivariate normal proposal distributions, in the limit &
446 : &of infinite dimensions. Therefore, care must be taken when using Gelman's scaling factor with non-Gaussian proposals and target &
447 : &objective functions. Only the product symbol `*` can be parsed in the string value of `proposalScaleFactor`. &
448 : &The presence of other mathematical symbols or multiple appearances of the product symbol will lead to a simulation crash. &
449 : &Also, note that the prescription of an acceptance range specified by the input variable `targetAcceptanceRate` will lead &
450 : &to dynamic modification of the initial input value of `proposalScaleFactor` throughout sampling for `proposalAdaptationCount` times. &
451 : &The default string value for `proposalScaleFactor` is `""gelman""` (for all proposal distributions), &
452 14 : &which is subsequently converted to `2.38 / sqrt(ndim)`."
453 : !!$omp master
454 14 : proposalScaleFactor = spec%proposalScaleFactor%null
455 : !!$omp end master
456 : end block proposalScaleFactor_block
457 :
458 : proposalStart_block: block
459 : use pm_sampling_scio, only: proposalStart
460 : spec%proposalStart%desc = &
461 : SKC_"The simulation specification `proposalStart` is a vector type of `real` of the highest precision available &
462 : &within the ParaMonte library of length `ndim` where `ndim` is the dimension of the domain of the objective function. &
463 : &For every element of `proposalStart` that is not provided as input, the default value will be the center of the sampling domain &
464 : &as determined by `domainCubeLimitLower` and `domainCubeLimitUpper` input specifications. &
465 : &If the condition `proposalStartRandomized` is set to the logical/Boolean true value, then the missing &
466 : &elements of `proposalStart` will be initialized to values drawn randomly from within the corresponding &
467 : &ranges specified by the input variables `proposalStartDomainCubeLimitLower` and `proposalStartDomainCubeLimitUpper`. &
468 : &If the simulation specification `outputStatus` is set to ""extend"" and a prior successful simulation run exists, &
469 : &then `proposalStart` will be set to the average of the sampled states of the most recent successful run. &
470 14 : &In this case, any user-specified value will be overridden by the computed `proposalStart`."
471 : !!$omp master
472 14 : if (allocated(proposalStart)) deallocate(proposalStart)
473 14 : allocate(proposalStart(ndim))
474 42 : call setNAN(proposalStart)
475 : !!$omp end master
476 : end block proposalStart_block
477 :
478 : proposalStartDomainCubeLimitLower_block: block
479 : use pm_sampling_scio, only: proposalStartDomainCubeLimitLower
480 14 : spec%proposalStartDomainCubeLimitLower%def = spec%domainCubeLimitLower%def
481 : spec%proposalStartDomainCubeLimitLower%desc = &
482 : SKC_"The simulation specification `proposalStartDomainCubeLimitLower` is a vector of type `real` of the highest precision available &
483 : &in the ParaMonet library of size `ndim` is the number of dimensions of the domain of the objective function. It contains the &
484 : &lower boundaries of the cubical domain from which the starting point(s) of the MCMC chain(s) will be initialized randomly &
485 : &(only if requested via the input variable `proposalStartRandomized`). &
486 : &This happens only when some or all of the input specification `proposalStart` elements are missing. &
487 : &In such cases, every missing value of the input `proposalStart` will be set to the center point between &
488 : &`proposalStartDomainCubeLimitLower` and `proposalStartDomainCubeLimitUpper` in the corresponding dimension. &
489 : &If `proposalStartRandomized` is set to the logical/Boolean true value, then the missing elements of &
490 : &`proposalStart` will be initialized to values drawn randomly from within the corresponding ranges &
491 : &whose lower limits are specified by the input `proposalStartDomainCubeLimitLower`. &
492 : &When specified from within an external input file to the sampler, it is also possible to assign only select &
493 : &values of `proposalStartDomainCubeLimitLower` and leave the rest of the components to be assigned the default value. &
494 : &For example, having the following inside the input file, "//NL2//&
495 : SKC_"+ `proposalStartDomainCubeLimitLower(3:5) = -100`"//NL2//&
496 : SKC_" will only set the lower limits of the third, fourth, and the fifth dimensions to -100, or,"//NL2//&
497 : SKC_"+ `proposalStartDomainCubeLimitLower(1) = -100, proposalStartDomainCubeLimitLower(2) = -1.e6`"//NL2//&
498 : SKC_" will set the lower limit on the first dimension to -100, and 1.e6 on the second dimension, or,"//NL2//&
499 : SKC_"+ `proposalStartDomainCubeLimitLower = 3*-2.5e100`"//NL2//&
500 : SKC_" will only set the lower limits on the first, second, and the third dimensions to `-2.5*10^100`, &
501 : &while the rest of the lower limits for the missing dimensions will be automatically set to the default value."//NL2//&
502 14 : SKC_"The default for all `proposalStartDomainCubeLimitLower` elements are taken from the corresponding elements of `domainCubeLimitLower`."
503 : !!$omp master
504 14 : call setResized(proposalStartDomainCubeLimitLower, ndim)
505 42 : call setNAN(proposalStartDomainCubeLimitLower)
506 : !!$omp end master
507 : end block proposalStartDomainCubeLimitLower_block
508 :
509 : proposalStartDomainCubeLimitUpper_block: block
510 : use pm_sampling_scio, only: proposalStartDomainCubeLimitUpper
511 14 : spec%proposalStartDomainCubeLimitUpper%def = spec%domainCubeLimitUpper%def
512 : spec%proposalStartDomainCubeLimitUpper%desc = &
513 : SKC_"The simulation specification `proposalStartDomainCubeLimitUpper` is a vector of type `real` of the highest precision available &
514 : &in the ParaMonet library of size `ndim` is the number of dimensions of the domain of the objective function. It contains the &
515 : &upper boundaries of the cubical domain from which the starting point(s) of the MCMC chain(s) will be initialized randomly &
516 : &(only if requested via the input variable `proposalStartRandomized`). &
517 : &This happens only when some or all of the input specification `proposalStart` elements are missing. &
518 : &In such cases, every missing value of the input `proposalStart` will be set to the center point between &
519 : &`proposalStartDomainCubeLimitLower` and `proposalStartDomainCubeLimitUpper` in the corresponding dimension. &
520 : &If `proposalStartRandomized` is set to the logical/Boolean true value, then the missing elements of &
521 : &`proposalStart` will be initialized to values drawn randomly from within the corresponding ranges &
522 : &whose upper limits are specified by the input `proposalStartDomainCubeLimitUpper`. &
523 : &When specified from within an external input file to the sampler, it is also possible to assign only select &
524 : &values of `proposalStartDomainCubeLimitUpper` and leave the rest of the components to be assigned the default value. &
525 : &For example, having the following inside the input file, "//NL2//&
526 : SKC_"+ `proposalStartDomainCubeLimitUpper(3:5) = -100`"//NL2//&
527 : SKC_" will only set the upper limits of the third, fourth, and the fifth dimensions to `-100`, or,"//NL2//&
528 : SKC_"+ `proposalStartDomainCubeLimitUpper(1) = -100, proposalStartDomainCubeLimitUpper(2) = -1.e6`"//NL2//&
529 : SKC_" will set the upper limit on the first dimension to -100, and 1.e6 on the second dimension, or,"//NL2//&
530 : SKC_"+ `proposalStartDomainCubeLimitUpper = 3*-2.5e100`"//NL2//&
531 : SKC_" will only set the upper limits on the first, second, and the third dimensions to `-2.5*10**100`, while &
532 : &the rest of the upper limits for the missing dimensions will be automatically set to the default value."//NL2//&
533 : SKC_"The default values for all elements of `proposalStartDomainCubeLimitUpper` are &
534 14 : &taken from the corresponding values in the input variable `domainCubeLimitUpper`."
535 : !!$omp master
536 14 : call setResized(proposalStartDomainCubeLimitUpper, ndim)
537 42 : call setNAN(proposalStartDomainCubeLimitUpper)
538 : !!$omp end master
539 : end block proposalStartDomainCubeLimitUpper_block
540 :
541 : proposalStartRandomized_block: block
542 : use pm_sampling_scio, only: proposalStartRandomized
543 14 : spec%proposalStartRandomized%def = .false._LK
544 : spec%proposalStartRandomized%desc = &
545 : SKC_"The simulation specification `proposalStartRandomized` is scalar of type `logical` (Boolean). &
546 : &If `true` (or `.true.` or `TRUE` or `.t.` from within an external input file), then the variable `proposalStart` &
547 : &will be initialized randomly for each MCMC chain that is to be generated by the sampler. The random values will be &
548 : &drawn from the specified or the default domain of `proposalStart`, given by `proposalStartDomainCubeLimitLower` and &
549 : &`proposalStartDomainCubeLimitUpper` variable. Note that the value of `proposalStart`, if provided, has precedence over &
550 : &random initialization. In other words, only uninitialized elements of `proposalStart` will be randomly initialized only &
551 : &if `proposalStartRandomized` is set to the logical true value. Note that even if `proposalStart` is randomly initialized, &
552 : &its random value will be deterministic between different independent simulation runs if the input variable `randomSeed` &
553 14 : &is specified by the user. The default value is `"//getStr(spec%proposalStartRandomized%def)//SKC_"`."
554 : !!$omp master
555 14 : proposalStartRandomized = spec%proposalStartRandomized%def
556 : !!$omp end master
557 : end block proposalStartRandomized_block
558 :
559 : proposalStdVec_block: block
560 : use pm_arrayFill, only: getFilled
561 : use pm_sampling_scio, only: proposalStdVec
562 56 : spec%proposalStdVec%def = getFilled(1._RKC, ndim)
563 : spec%proposalStdVec%desc = &
564 : SKC_"The simulation specification `proposalStdVec` is a positive-valued vector of type `real` of the highest precision available &
565 : &within the ParaMonte library, of size `ndim`, where `ndim` is the dimension of the domain of the objective function. &
566 : &It serves as the best-guess starting standard deviation for each component of the proposal distribution. &
567 : &If the initial covariance matrix (`proposalCovMat`) is missing as an input specification to the sampler, &
568 : &then `proposalStdVec` (along with the specified `proposalCorMat`) will be used to construct &
569 : &the initial covariance matrix of the proposal distribution of the MCMC sampler. &
570 : &However, if `proposalCovMat` is specified for the sampler, then the input `proposalStdVec` and `proposalCorMat` will &
571 : &be completely ignored, and the input value for `proposalCovMat` will be used to construct the initial covariance matrix &
572 14 : &of the proposal distribution. The default value of `proposalStdVec` is a vector of size `ndim` of unit values (i.e., ones)."
573 : !!$omp master
574 14 : call setResized(proposalStdVec, ndim)
575 42 : call setNAN(proposalStdVec)
576 : !!$omp end master
577 : end block proposalStdVec_block
578 :
579 : !!$omp barrier
580 :
581 70 : end function
582 :
583 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
584 :
585 13 : function set(spec, sampler) result(err)
586 : #if __INTEL_COMPILER && DLL_ENABLED && (_WIN32 || _WIN64)
587 : !DEC$ ATTRIBUTES DLLEXPORT :: set
588 : #endif
589 : use pm_err, only: err_type
590 : use pm_sampling, only: paramcmc_type
591 : use pm_sampling, only: sampler_type
592 : class(specmcmc_type), intent(inout) :: spec
593 : class(sampler_type), intent(in), optional :: sampler
594 : type(err_type) :: err
595 :
596 : character(*, SK), parameter :: PROCEDURE_NAME = MODULE_NAME//"@set()"
597 :
598 : select type(sampler)
599 : type is (paramcmc_type)
600 :
601 13 : err = spec%specbase_type%set(sampler%sampler_type)
602 13 : if (err%occurred) return
603 :
604 : outputChainSize_block: block
605 : use pm_sampling_scio, only: outputChainSize
606 13 : if (spec%overridable .and. allocated(sampler%outputChainSize)) then
607 9 : spec%outputChainSize%val = sampler%outputChainSize
608 : else
609 4 : spec%outputChainSize%val = outputChainSize
610 : end if
611 13 : if (spec%outputChainSize%val == spec%outputChainSize%null) spec%outputChainSize%val = spec%outputChainSize%def
612 : end block outputChainSize_block
613 :
614 : outputSampleRefinementCount_block: block
615 : use pm_sampling_scio, only: outputSampleRefinementCount
616 13 : if (spec%overridable .and. allocated(sampler%outputSampleRefinementCount)) then
617 0 : spec%outputSampleRefinementCount%val = sampler%outputSampleRefinementCount
618 : else
619 13 : spec%outputSampleRefinementCount%val = outputSampleRefinementCount
620 : end if
621 13 : if (spec%outputSampleRefinementCount%val == spec%outputSampleRefinementCount%null) spec%outputSampleRefinementCount%val = spec%outputSampleRefinementCount%def
622 13 : spec%outputSampleRefinementCount%str = getStr(spec%outputSampleRefinementCount%val)
623 : end block outputSampleRefinementCount_block
624 :
625 13 : outputSampleRefinementMethod_block: block
626 : use pm_sampling_scio, only: outputSampleRefinementMethod
627 : character(:,SKC), allocatable :: lowval
628 13 : if (spec%overridable .and. allocated(sampler%outputSampleRefinementMethod)) then
629 0 : spec%outputSampleRefinementMethod%val = trim(adjustl(getRemoved(sampler%outputSampleRefinementMethod, SKC_" ")))
630 : else
631 13 : spec%outputSampleRefinementMethod%val = trim(adjustl(getRemoved(outputSampleRefinementMethod, SKC_" ")))
632 : end if
633 13 : if (spec%outputSampleRefinementMethod%val == trim(adjustl(spec%outputSampleRefinementMethod%null))) spec%outputSampleRefinementMethod%val = spec%outputSampleRefinementMethod%def
634 13 : lowval = getStrLower(spec%outputSampleRefinementMethod%val)
635 13 : spec%outputSampleRefinementMethod%isMaxCumSumACF = logical(lowval == SKC_"maxcumsumacf", LK)
636 13 : spec%outputSampleRefinementMethod%isBatchMeans = logical(0 < index(lowval, SKC_"batchmeans"), LK)
637 13 : spec%outputSampleRefinementMethod%isBatchMeansCompact = spec%outputSampleRefinementMethod%isBatchMeans .and. logical(0 < index(lowval, SKC_"compact"), LK)
638 39 : spec%outputSampleRefinementMethod%isBatchMeansVerbose = spec%outputSampleRefinementMethod%isBatchMeans .and. logical(0 < index(lowval, SKC_"verbose"), LK)
639 : end block outputSampleRefinementMethod_block
640 :
641 : proposal_block: block
642 : use pm_sampling_scio, only: proposal
643 13 : if (spec%overridable .and. allocated(sampler%proposal)) then
644 0 : spec%proposal%val = getStrLower(trim(adjustl(sampler%proposal)))
645 : else
646 13 : spec%proposal%val = getStrLower(trim(adjustl(proposal)))
647 : end if
648 13 : if (spec%proposal%val == spec%proposal%null) spec%proposal%val = spec%proposal%def
649 13 : spec%proposal%is%uniform = spec%proposal%val == spec%proposal%uniform
650 13 : spec%proposal%is%normal = spec%proposal%val == spec%proposal%normal
651 : end block proposal_block
652 :
653 : proposalCorMat_block: block
654 : use pm_sampling_scio, only: proposalCorMat
655 13 : if (spec%overridable .and. allocated(sampler%proposalCorMat)) then
656 0 : spec%proposalCorMat%val = real(sampler%proposalCorMat, RKC)
657 : else
658 158 : spec%proposalCorMat%val = proposalCorMat
659 : end if
660 119 : where (isNAN(spec%proposalCorMat%val))
661 : spec%proposalCorMat%val = spec%proposalCorMat%def
662 : end where
663 : end block proposalCorMat_block
664 :
665 : proposalCovMat_block: block
666 : use pm_sampling_scio, only: proposalCovMat
667 : integer(IK) :: idim, jdim
668 13 : if (spec%overridable .and. allocated(sampler%proposalCovMat)) then
669 0 : spec%proposalCovMat%val = real(sampler%proposalCovMat, RKC)
670 : else
671 158 : spec%proposalCovMat%val = proposalCovMat
672 : end if
673 40 : do jdim = 1, spec%ndim%val
674 119 : do idim = 1, spec%ndim%val
675 106 : if (isNAN(spec%proposalCovMat%val(idim, jdim))) then
676 59 : spec%proposalCovMat%val(idim, jdim) = spec%proposalCovMat%def(idim, jdim)
677 : else
678 20 : spec%proposalCovMat%isUserSet = .true._LK
679 : end if
680 : end do
681 : end do
682 : end block proposalCovMat_block
683 :
684 : proposalScaleFactor_block: block
685 : use pm_sampling_scio, only: proposalScaleFactor
686 13 : if (spec%overridable .and. allocated(sampler%proposalScaleFactor)) then
687 1 : spec%proposalScaleFactor%str = trim(adjustl(sampler%proposalScaleFactor))
688 : else
689 12 : spec%proposalScaleFactor%str = trim(adjustl(proposalScaleFactor))
690 : end if
691 13 : if (spec%proposalScaleFactor%str == spec%proposalScaleFactor%null) then
692 10 : spec%proposalScaleFactor%val = spec%proposalScaleFactor%valdef
693 10 : spec%proposalScaleFactor%str = spec%proposalScaleFactor%strdef
694 : end if
695 : end block proposalScaleFactor_block
696 :
697 : proposalStart_block: block
698 : use pm_sampling_scio, only: proposalStart
699 13 : if (spec%overridable .and. allocated(sampler%proposalStart)) then
700 21 : spec%proposalStart%val = real(sampler%proposalStart, RKC)
701 : else
702 38 : spec%proposalStart%val = proposalStart
703 : end if
704 : end block proposalStart_block
705 :
706 : proposalStartDomainCubeLimitLower_block: block
707 : use pm_sampling_scio, only: proposalStartDomainCubeLimitLower
708 13 : if (spec%overridable .and. allocated(sampler%proposalStartDomainCubeLimitLower)) then
709 0 : spec%proposalStartDomainCubeLimitLower%val = real(sampler%proposalStartDomainCubeLimitLower, RKC)
710 : else
711 66 : spec%proposalStartDomainCubeLimitLower%val = proposalStartDomainCubeLimitLower
712 : end if
713 40 : where(isNAN(spec%proposalStartDomainCubeLimitLower%val))
714 : spec%proposalStartDomainCubeLimitLower%val = spec%domainCubeLimitLower%val
715 : end where
716 : end block proposalStartDomainCubeLimitLower_block
717 :
718 : proposalStartDomainCubeLimitUpper_block: block
719 : use pm_sampling_scio, only: proposalStartDomainCubeLimitUpper
720 13 : if (spec%overridable .and. allocated(sampler%proposalStartDomainCubeLimitUpper)) then
721 0 : spec%proposalStartDomainCubeLimitUpper%val = real(sampler%proposalStartDomainCubeLimitUpper, RKC)
722 : else
723 66 : spec%proposalStartDomainCubeLimitUpper%val = proposalStartDomainCubeLimitUpper
724 : end if
725 40 : where(isNAN(spec%proposalStartDomainCubeLimitUpper%val))
726 : spec%proposalStartDomainCubeLimitUpper%val = spec%domainCubeLimitUpper%val
727 : end where
728 : end block proposalStartDomainCubeLimitUpper_block
729 :
730 : proposalStartRandomized_block: block
731 : use pm_sampling_scio, only: proposalStartRandomized
732 13 : if (spec%overridable .and. allocated(sampler%proposalStartRandomized)) then
733 0 : spec%proposalStartRandomized%val = sampler%proposalStartRandomized
734 : else
735 13 : spec%proposalStartRandomized%val = proposalStartRandomized
736 : end if
737 : end block proposalStartRandomized_block
738 :
739 : proposalStdVec_block: block
740 : use pm_sampling_scio, only: proposalStdVec
741 13 : if (spec%overridable .and. allocated(sampler%proposalStdVec)) then
742 0 : spec%proposalStdVec%val = real(sampler%proposalStdVec, RKC)
743 : else
744 66 : spec%proposalStdVec%val = proposalStdVec
745 : end if
746 40 : where (isNAN(spec%proposalStdVec%val))
747 : spec%proposalStdVec%val = spec%proposalStdVec%def
748 : end where
749 : end block proposalStdVec_block
750 :
751 : ! Resolve the conflicting cases.
752 :
753 13 : if (spec%outputStatus%is%extend .and. 1 < spec%run%id) then
754 1 : block
755 : use pm_sampleMean, only: setMean
756 : use pm_sampleCov, only: setCov, uppDia
757 : use pm_io, only: getErrTableRead, LEN_IOMSG
758 : use pm_matrixCopy, only: setMatCopy, rdpack, upp, transHerm
759 : real(RKC), allocatable :: logFuncState(:,:)
760 1 : call setResized(err%msg, LEN_IOMSG)
761 1 : err%stat = getErrTableRead(spec%sampleFile%list(spec%run%id - 1)%val, logFuncState, sep = spec%outputSeparator%val, roff = 1_IK, iomsg = err%msg)
762 1 : err%occurred = err%stat /= 0
763 1 : if (err%occurred) then
764 : err%msg = PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SK_": Failed to read the sample file """//spec%sampleFile%list(spec%run%id - 1)%val//& ! LCOV_EXCL_LINE
765 : SK_""" contents from the previous simulation run. "//trim(err%msg) ! LCOV_EXCL_LINE
766 : return ! LCOV_EXCL_LINE
767 : end if
768 1 : call setMean(spec%proposalStart%val, logFuncState(:, 2 : spec%ndim%val + 1), dim = 1_IK)
769 1 : call setCov(spec%proposalCovMat%val, uppDia, logFuncState(:, 2 : spec%ndim%val + 1), dim = 1_IK)
770 1 : call setMatCopy(spec%proposalCovMat%val, rdpack, spec%proposalCovMat%val, rdpack, upp, transHerm)
771 : end block
772 : else
773 : block
774 : use pm_sampleCov, only: getCov, uppDia
775 : use pm_distUnif, only: setUnifRand
776 : integer(IK) :: idim
777 183 : if (.not. spec%proposalCovMat%isUserSet) spec%proposalCovMat%val = getCov(spec%proposalCorMat%val, uppDia, spec%proposalStdVec%val)
778 37 : do idim = 1, size(spec%proposalStart%val, 1, IK)
779 37 : if (isNAN(spec%proposalStart%val(idim))) then
780 18 : if (spec%proposalStartRandomized%val) then
781 0 : call setUnifRand(spec%rng, spec%proposalStart%val(idim), spec%proposalStartDomainCubeLimitLower%val(idim), spec%proposalStartDomainCubeLimitUpper%val(idim))
782 : else
783 18 : spec%proposalStart%val(idim) = 0.5_RKC * spec%proposalStartDomainCubeLimitLower%val(idim) + 0.5_RKC * spec%proposalStartDomainCubeLimitUpper%val(idim)
784 : end if
785 : end if
786 : end do
787 : end block
788 : end if
789 :
790 : ! open output files, report and sanitize.
791 :
792 13 : if (spec%image%is%leader) call spec%report() ! if (spec%run%is%new)
793 26 : call spec%sanitize(err)
794 :
795 : class default
796 : error stop "The input `sampler` must be of type `paramcmc_type`." ! LCOV_EXCL_LINE
797 : end select
798 :
799 26 : end function
800 :
801 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
802 :
803 13 : subroutine report(spec)
804 : #if __INTEL_COMPILER && DLL_ENABLED && (_WIN32 || _WIN64)
805 : !DEC$ ATTRIBUTES DLLEXPORT :: report
806 : #endif
807 : class(specmcmc_type), intent(inout) :: spec
808 :
809 13 : call spec%disp%text%wrap(NL1//spec%method%val//SKC_".simulation.specifications.mcmc"//NL1)
810 :
811 : associate(ndim => spec%ndim%val, format => spec%reportFile%format%generic)
812 :
813 13 : call spec%disp%show("outputChainSize")
814 13 : call spec%disp%show(spec%outputChainSize%val, format = format)
815 13 : call spec%disp%note%show(spec%outputChainSize%desc)
816 :
817 13 : call spec%disp%show("outputSampleRefinementCount")
818 13 : call spec%disp%show(spec%outputSampleRefinementCount%val, format = format)
819 13 : call spec%disp%note%show(spec%outputSampleRefinementCount%desc)
820 :
821 13 : call spec%disp%show("outputSampleRefinementMethod")
822 13 : call spec%disp%show(spec%outputSampleRefinementMethod%val, format = format)
823 13 : call spec%disp%note%show(spec%outputSampleRefinementMethod%desc)
824 :
825 13 : call spec%disp%show("proposal")
826 13 : call spec%disp%show(spec%proposal%val, format = format)
827 13 : call spec%disp%note%show(spec%proposal%desc)
828 :
829 13 : call spec%disp%show("proposalCorMat")
830 13 : call spec%disp%show(spec%proposalCorMat%val, format = format)
831 13 : call spec%disp%note%show(spec%proposalCorMat%desc)
832 :
833 13 : call spec%disp%show("proposalCovMat")
834 13 : call spec%disp%show(spec%proposalCovMat%val, format = format)
835 13 : call spec%disp%note%show(spec%proposalCovMat%desc)
836 :
837 13 : call spec%disp%show("proposalScaleFactor")
838 13 : call spec%disp%show(spec%proposalScaleFactor%str//SKC_" (gelman(ndim = "//getStr(spec%ndim%val)//SKC_") = "//getStr(spec%proposalScaleFactor%valdef)//SKC_")", format = format)
839 13 : call spec%disp%note%show(spec%proposalScaleFactor%desc)
840 :
841 13 : call spec%disp%show("proposalStart")
842 39 : call spec%disp%show(reshape(spec%proposalStart%val, [ndim, 1_IK]), format = format)
843 13 : call spec%disp%note%show(spec%proposalStart%desc)
844 :
845 13 : call spec%disp%show("proposalStartDomainCubeLimitLower")
846 39 : call spec%disp%show(reshape(spec%proposalStartDomainCubeLimitLower%val, [ndim, 1_IK]), format = format)
847 13 : call spec%disp%note%show(spec%proposalStartDomainCubeLimitLower%desc)
848 :
849 13 : call spec%disp%show("proposalStartDomainCubeLimitUpper")
850 39 : call spec%disp%show(reshape(spec%proposalStartDomainCubeLimitUpper%val, [ndim, 1_IK]), format = format)
851 13 : call spec%disp%note%show(spec%proposalStartDomainCubeLimitUpper%desc)
852 :
853 13 : call spec%disp%show("proposalStartRandomized")
854 13 : call spec%disp%show(spec%proposalStartRandomized%val, format = format)
855 13 : call spec%disp%note%show(spec%proposalStartRandomized%desc)
856 :
857 13 : call spec%disp%show("proposalStdVec")
858 39 : call spec%disp%show(reshape(spec%proposalStdVec%val, [ndim, 1_IK]), format = format)
859 26 : call spec%disp%note%show(spec%proposalStdVec%desc)
860 :
861 : end associate
862 :
863 13 : end subroutine
864 :
865 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866 :
867 13 : subroutine sanitize(spec, err)
868 : #if __INTEL_COMPILER && DLL_ENABLED && (_WIN32 || _WIN64)
869 : !DEC$ ATTRIBUTES DLLEXPORT :: sanitize
870 : #endif
871 : use pm_err, only: err_type
872 : type(err_type), intent(inout) :: err
873 : class(specmcmc_type), intent(inout) :: spec
874 : character(*,SKC), parameter :: PROCEDURE_NAME = MODULE_NAME//SKC_"@sanitize()"
875 :
876 : outputChainSize_block: block
877 13 : if (spec%outputChainSize%val < spec%ndim%val + 1_IK) then
878 0 : err%occurred = .true._LK
879 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. The input requested value for `outputChainSize` ("//getStr(spec%outputChainSize%val)//&
880 : SKC_") can neither be negative nor smaller than `ndim + 1`, where `ndim` represents the dimension of the domain of the objective &
881 : &function, here `ndim = "//getStr(spec%ndim%val)//SKC_". If you do not know an appropriate value for `outputChainSize`, &
882 0 : &drop it from the input list. The MCMC sampler will automatically assign an appropriate value to it."
883 : end if
884 : end block outputChainSize_block
885 :
886 : outputSampleRefinementCount_block: block
887 13 : if (spec%outputSampleRefinementCount%val < 0_IK) then
888 0 : err%occurred = .true._LK
889 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. &
890 : &The input value for variable `outputSampleRefinementCount` must be a non-negative integer. &
891 : &If you are unsure about the appropriate value for this variable, simply drop it from the input. &
892 0 : &The sampler will automatically assign an appropriate value to it."
893 : end if
894 : end block outputSampleRefinementCount_block
895 :
896 13 : outputSampleRefinementMethod_block: block
897 : character(:,SKC), allocatable :: lowerCaseVal
898 13 : lowerCaseVal = getStrLower(spec%outputSampleRefinementMethod%val)
899 : if (& ! LCOV_EXCL_LINE
900 : index(lowerCaseVal, getStrLower(spec%outputSampleRefinementMethod%maxCumSumACF)) == 0_IK & ! LCOV_EXCL_LINE
901 : .and. & ! LCOV_EXCL_LINE
902 : index(lowerCaseVal, getStrLower(spec%outputSampleRefinementMethod%batchMeans)) == 0_IK & ! LCOV_EXCL_LINE
903 : .and. & ! LCOV_EXCL_LINE
904 : index(lowerCaseVal, getStrLower(spec%outputSampleRefinementMethod%cutoffACF)) == 0_IK & ! LCOV_EXCL_LINE
905 26 : ) then
906 0 : err%occurred = .true._LK
907 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. &
908 : &The input requested method for the computation of the integrated AutoCorrelation Time ("//spec%outputSampleRefinementMethod%val//&
909 : SKC_") assigned to the variable `outputSampleRefinementMethod` cannot be anything other than "//spec%outputSampleRefinementMethod%batchMeans//SKC_". "//&
910 : ! " or "//spec%maxCumSumACF//". &
911 : SKC_"If you are unsure of the appropriate value for `outputSampleRefinementMethod`, &
912 13 : &drop it from the input list. The sampler will automatically assign an appropriate value to it."
913 : end if
914 : end block outputSampleRefinementMethod_block
915 :
916 : proposal_block: block
917 13 : if (.not. (spec%proposal%is%normal .or. spec%proposal%is%uniform)) then
918 0 : err%occurred = .true._LK
919 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. &
920 : &The input requested proposal model ("//spec%proposal%val//") is not supported. &
921 : &The variable proposal cannot be set to anything other than '"//&
922 : spec%proposal%normal//SKC_"', or '"//&
923 0 : spec%proposal%uniform//SKC_"'."
924 : end if
925 : end block proposal_block
926 :
927 : proposalCorMat_block: block
928 13 : if (.not. isMatClass(spec%proposalCorMat%val, posdefmat)) then
929 0 : err%occurred = .true._LK
930 0 : err%msg = err%msg//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. The specified `proposalCorMat` is not positive-definite: "//getStr(spec%proposalCorMat%val)//SKC_""
931 : end if
932 : end block proposalCorMat_block
933 :
934 : proposalCovMat_block: block
935 13 : if (.not. isMatClass(spec%proposalCovMat%val, posdefmat)) then
936 0 : err%occurred = .true._LK
937 0 : err%msg = err%msg//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. The specified `proposalCovMat` is not positive-definite: "//getStr(spec%proposalCovMat%val)//SKC_""
938 : end if
939 : end block proposalCovMat_block
940 :
941 13 : proposalScaleFactor_block: block
942 : use pm_val2real, only: setReal
943 : use pm_arraySplit, only: setSplit
944 : integer(IK), allocatable :: sindex(:,:)
945 : character(:,SKC), allocatable :: str
946 : real(RKC) :: conversion
947 : integer(IK) :: ipart
948 : ! First convert the proposalScaleFactor string to real value:
949 13 : str = getRemoved(spec%proposalScaleFactor%str, SKC_" ") ! remove the white spaces.
950 13 : if (len_trim(adjustl(str)) == 0_IK) then
951 0 : err%occurred = .true._LK
952 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. &
953 : &The input string value ("//spec%proposalScaleFactor%str//SKC_") for the variable `proposalScaleFactor` is empty. &
954 : &Ensure the specified string follows the syntax rules of the sampler for this variable. Otherwise drop &
955 0 : &it from the input list. The sampler will automatically assign an appropriate value to it."
956 : end if
957 : ! Now split the string by "*" to real coefficient and character (gelman) parts for further evaluations.
958 13 : call setSplit(sindex, str, sep = SKC_"*")
959 13 : spec%proposalScaleFactor%val = 1._RKC
960 31 : do ipart = 1, size(sindex, 2, IK)
961 31 : if (getStrLower(str(sindex(1, ipart) : sindex(2, ipart))) == SKC_"gelman") then
962 13 : spec%proposalScaleFactor%val = spec%proposalScaleFactor%val * spec%proposalScaleFactor%valdef
963 : else
964 5 : call setReal(conversion, str(sindex(1, ipart) : sindex(2, ipart)), iostat = err%stat)
965 23 : if (err%stat /= 0_IK) then
966 0 : err%occurred = .true._LK
967 : err%msg = err%msg//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred while reading real number. &
968 : &The input string value for the variable `proposalScaleFactor` ("//spec%proposalScaleFactor%str//SKC_") does not appear to follow &
969 : &the standard syntax rules of the sampler for this variable. The slice `"//str(sindex(1, ipart) : sindex(1, ipart))//& ! LCOV_EXCL_LINE
970 : SKC_"` cannot be parsed into any meaningful token. Please correct the input value, or drop it from the input list &
971 0 : &in which case, the sampler will automatically assign an appropriate value to it."
972 : else
973 5 : spec%proposalScaleFactor%val = spec%proposalScaleFactor%val * conversion
974 : end if
975 : end if
976 : end do
977 : ! Now check if the real value is positive
978 26 : if (spec%proposalScaleFactor%val <= 0_IK) then
979 0 : err%occurred = .true._LK
980 : err%msg = err%msg//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. &
981 : &The input string value ("""//spec%proposalScaleFactor%str//""") translates to a non-positive real value: "//getStr(spec%proposalScaleFactor%val)//SKC_". &
982 : &Make sure the input string follows the syntax rules of the sampler for this variable. &
983 0 : &Otherwise drop it from the input list. The sampler will automatically assign an appropriate value to it."
984 : end if
985 : end block proposalScaleFactor_block
986 :
987 : proposalStart_block: block
988 : use pm_sampling_scio, only: proposalStart
989 : !!$omp barrier
990 : !!$omp master
991 13 : if (allocated(proposalStart)) deallocate(proposalStart)
992 : !!$omp end master
993 : end block proposalStart_block
994 :
995 : proposalStartDomainCubeLimitLower_block: block
996 : use pm_sampling_scio, only: proposalStartDomainCubeLimitLower
997 : !!$omp barrier
998 : !!$omp master
999 13 : if (allocated(proposalStartDomainCubeLimitLower)) deallocate(proposalStartDomainCubeLimitLower)
1000 : !!$omp end master
1001 : end block proposalStartDomainCubeLimitLower_block
1002 :
1003 : proposalStartDomainCubeLimitUpper_block: block
1004 : use pm_sampling_scio, only: proposalStartDomainCubeLimitUpper
1005 : integer(IK) :: idim
1006 40 : do idim = 1, size(spec%proposalStartDomainCubeLimitUpper%val, kind = IK)
1007 : ! Check if the domain is set when random start point is requested.
1008 27 : if (spec%proposalStartRandomized%val .and. spec%proposalStartDomainCubeLimitUpper%val(idim) == spec%domainCubeLimitUpper%def) then
1009 0 : err%occurred = .true._LK
1010 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. &
1011 : &You have requested a random start point by setting `proposalStartRandomized` to TRUE while the &
1012 : &element #"//getStr(idim)//SKC_" of `proposalStartDomainCubeLimitLower` has not been preset to a finite value. &
1013 0 : &This information is essential otherwise, how could the sampler draw points randomly from within an unspecified domain?"
1014 : end if
1015 : ! The upper boundary of the domain of random-start-point must be smaller than the upper boundary of the target's domain.
1016 27 : if (spec%domainCubeLimitUpper%val(idim) < spec%proposalStartDomainCubeLimitUpper%val(idim)) then
1017 0 : err%occurred = .true._LK
1018 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. The component "//getStr(idim)//& ! LCOV_EXCL_LINE
1019 : SKC_" of the variable `proposalStartDomainCubeLimitUpper` ("//getStr(spec%proposalStartDomainCubeLimitUpper%val(idim))//SKC_") cannot be "//& ! LCOV_EXCL_LINE
1020 : SKC_"larger than the corresponding component of the variable domainCubeLimitUpper ("//& ! LCOV_EXCL_LINE
1021 : getStr(spec%domainCubeLimitUpper%val(idim))//SKC_"). If you do not know an appropriate &
1022 : &value to set for `proposalStartDomainCubeLimitUpper`, drop it from the input list. &
1023 0 : &The sampler will automatically assign an appropriate value to it."
1024 : end if
1025 : ! The upper boundary of the domain of random-start-point must be smaller than the corresponding lower boundary.
1026 40 : if (spec%proposalStartDomainCubeLimitUpper%val(idim) <= spec%proposalStartDomainCubeLimitLower%val(idim)) then
1027 0 : err%occurred = .true._LK
1028 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. The input upper limit value in the component "//getStr(idim)//&
1029 : SKC_" of the variable `proposalStartDomainCubeLimitUpper` cannot be smaller than or equal to the corresponding input &
1030 : &lower limit value in `proposalStartDomainCubeLimitLower`:"//NL1//&
1031 : SKC_" proposalStartDomainCubeLimitLower("//getStr(idim)//SKC_") = "//getStr(spec%proposalStartDomainCubeLimitLower%val(idim))//NL1//&
1032 0 : SKC_" proposalStartDomainCubeLimitUpper("//getStr(idim)//SKC_") = "//getStr(spec%proposalStartDomainCubeLimitUpper%val(idim))//SKC_""
1033 : end if
1034 :
1035 : end do
1036 : !!$omp barrier
1037 : !!$omp master
1038 13 : if (allocated(proposalStartDomainCubeLimitUpper)) deallocate(proposalStartDomainCubeLimitUpper)
1039 : !!$omp end master
1040 : end block proposalStartDomainCubeLimitUpper_block
1041 :
1042 : proposalStartRandomized_block: block
1043 : end block proposalStartRandomized_block
1044 :
1045 : proposalStdVec_block: block
1046 : integer(IK) :: idim
1047 40 : do idim = 1, spec%ndim%val
1048 40 : if (spec%proposalStdVec%val(idim) <= 0._RKC) then
1049 0 : err%occurred = .true._LK
1050 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. &
1051 : &The input requested value ("//getStr(spec%proposalStdVec%val(idim))//SKC_") for the component "//getStr(idim)//&
1052 0 : SKC_" of the variable proposalStdVec for the proposal distribution of the sampler must be a positive real number."
1053 : end if
1054 : end do
1055 : end block proposalStdVec_block
1056 :
1057 : ! Resolve conflicts.
1058 :
1059 : block
1060 : ! proposalStart must be within the domain.
1061 : integer(IK) :: idim
1062 40 : do idim = 1, size(spec%proposalStart%val, 1, IK)
1063 40 : if (spec%proposalStart%val(idim) < spec%domainCubeLimitLower%val(idim) .or. spec%domainCubeLimitUpper%val(idim) < spec%proposalStart%val(idim)) then
1064 0 : err%occurred = .true._LK
1065 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. &
1066 : &The input requested value for the component "//getStr(idim)//SKC_" of the vector `proposalStart` ("//& ! LCOV_EXCL_LINE
1067 : getStr(spec%proposalStart%val(idim))//SKC_") must be within the range of the sampling domain defined in the program: ["//& ! LCOV_EXCL_LINE
1068 : getStr([spec%domainCubeLimitLower%val(idim), spec%domainCubeLimitUpper%val(idim)])//SKC_"]. &
1069 : &If you do not know an appropriate value for proposalStart, drop it from the input list. &
1070 27 : &The sampler will automatically assign an appropriate value to it."
1071 : end if
1072 : end do
1073 : end block
1074 :
1075 : block
1076 : ! `proposalStartDomainCubeLimitLower` must be larger than `domainCubeLimitLower` when start point is randomized.
1077 : integer(IK) :: idim
1078 40 : do idim = 1, size(spec%proposalStartDomainCubeLimitLower%val, kind = IK)
1079 : ! check if the domain is set when random start point is requested.
1080 27 : if (spec%proposalStartRandomized%val .and. spec%proposalStartDomainCubeLimitLower%val(idim) == spec%domainCubeLimitLower%def) then
1081 0 : err%occurred = .true._LK
1082 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. &
1083 : &You have requested a random start point by setting `proposalStartRandomized` to the logical/Boolean true value &
1084 : &while the element #"//getStr(idim)//SKC_" of `proposalStartDomainCubeLimitLower` has not been preset to a finite value. &
1085 0 : &This information is essential otherwise, how could the sampler draw points randomly from within an unspecified domain?"
1086 : end if
1087 : ! check if the random start point domain is within the boundaries of the domain of the target.
1088 40 : if (spec%proposalStartDomainCubeLimitLower%val(idim) < spec%domainCubeLimitLower%val(idim)) then
1089 0 : err%occurred = .true._LK
1090 : err%msg = err%msg//NL2//PROCEDURE_NAME//getFine(__FILE__, __LINE__)//SKC_": Error occurred. The component "//getStr(idim)//& ! LCOV_EXCL_LINE
1091 : SKC_" of the variable `proposalStartDomainCubeLimitLower` ("//getStr(spec%proposalStartDomainCubeLimitLower%val(idim))//& ! LCOV_EXCL_LINE
1092 : SKC_") cannot be smaller than the corresponding component of the variable `domainCubeLimitLower` ("//& ! LCOV_EXCL_LINE
1093 : getStr(spec%domainCubeLimitLower%val(idim))//"). If you do not know &an appropriate value to &
1094 : &set for `proposalStartDomainCubeLimitLower`, drop it from the input list. The sampler will &
1095 0 : &automatically assign an appropriate value to it."
1096 : end if
1097 :
1098 : end do
1099 : end block
1100 :
1101 13 : end subroutine
1102 :
1103 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1104 :
1105 : !> Return the refined Markov chain, given the input Markov chain and its specifications.
1106 : !> This procedure is a method of the [sfc_type](@ref sfc_type) class.
1107 : !>
1108 : !> \param[inout] sfc : An object of class [sfc_type](@ref sfc_type).
1109 : !> \param[in] outputSampleSize : The requested refined sample size (**optional**). If the size of the refined sample is given as input,
1110 : !! then the requested sample is directly generated based on the input size.
1111 : !> \param[in] outputSampleRefinementCount : The maximum number of times the sample can be refined (**optional**, default = `Infinity`).
1112 : !! : For example, if set to 1, then only one round of refinement will be performed on the Markov chain.
1113 : !> \param[in] outputSampleRefinementMethod : The requested method of refining the sample (**optional**, default = "BatchMeans").
1114 13 : function getErrRefinement(sfc, sampleWeight, sampleLogFunc, sampleState, outputSampleRefinementCount, outputSampleRefinementMethod) result(err)
1115 : #if __INTEL_COMPILER && DLL_ENABLED && (_WIN32 || _WIN64)
1116 : !DEC$ ATTRIBUTES DLLEXPORT :: getErrRefinement
1117 : #endif
1118 : use, intrinsic :: iso_fortran_env, only: output_unit
1119 : use pm_arrayRefine, only: setRefined
1120 : use pm_arrayRebind, only: setRebound
1121 : use pm_arrayResize, only: setResized
1122 : use pm_sampleACT, only: getACT, batchMeans, batchMeansMax, cumSum, cumSumMax
1123 : use pm_sampleQuan, only: getQuan, piwilin
1124 :
1125 : type(err_type) :: err
1126 : class(sfcmcmc_type) , intent(inout) :: sfc
1127 : integer(IK) , intent(in) , contiguous :: sampleWeight(:)
1128 : real(RKC) , intent(in) , contiguous :: sampleLogFunc(:), sampleState(:,:)
1129 : integer(IK) , intent(in) , optional :: outputSampleRefinementCount
1130 : character(*, SK) , intent(in) , optional :: outputSampleRefinementMethod
1131 : real(RKC) , allocatable :: logFuncStateAxis(:) ! ensures contiguity.
1132 : character(*, SK) , parameter :: PROCEDURE_NAME = SK_"@getErrRefinement()"
1133 : integer(IK) :: idim, ndim, nsam, ndimp1, nrefAlloc, outputSampleRefinementCount_def
1134 : real(RKC) :: act, ndimp1inv
1135 : type(method_type) :: method
1136 :
1137 13 : CHECK_ASSERTION(__LINE__, 0_IK < size(sampleState, 1, IK), SK_"The condition `0 < size(sampleState, 1)` must hold. shape(sampleState) = "//getStr(shape(sampleState, IK)))
1138 78 : CHECK_ASSERTION(__LINE__, size(sampleWeight, 1, IK) == size(sampleState, 2, IK), SK_"The condition `size(sampleWeight) == size(sampleState, 2)` must hold. size(sampleWeight), shape(sampleState) = "//getStr([size(sampleWeight, 1, IK), shape(sampleState, IK)]))
1139 39 : CHECK_ASSERTION(__LINE__, size(sampleWeight, 1, IK) == size(sampleLogFunc, 1, IK), SK_"The condition `size(sampleWeight) == size(sampleLogFunc)` must hold. size(sampleWeight), size(sampleLogFunc) = "//getStr([size(sampleWeight, 1, IK), size(sampleLogFunc, 1, IK)]))
1140 13 : err = getErrRefinementMethod(method, outputSampleRefinementMethod)
1141 : ndim = size(sampleState, 1, IK)
1142 : nsam = size(sampleState, 2, IK)
1143 13 : ndimp1 = ndim + 1_IK
1144 :
1145 : ! This is to avoid memory overflow due to extremely large `outputSampleRefinementCount` requested by the user.
1146 :
1147 13 : ndimp1inv = 1._RKC / ndimp1
1148 : outputSampleRefinementCount_def = 20_IK ! this is a temporary maximum value, to be increased later if needed
1149 13 : if (present(outputSampleRefinementCount)) outputSampleRefinementCount_def = outputSampleRefinementCount
1150 13 : nrefAlloc = min(2_IK, outputSampleRefinementCount_def)
1151 :
1152 : ! Allocate components.
1153 :
1154 39 : call setRebound(sfc%act, [0_IK, 0_IK], [ndim, nrefAlloc])
1155 13 : call setRebound(sfc%nsam, 0_IK, nrefAlloc)
1156 13 : call setRebound(sfc%sumw, 0_IK, nrefAlloc)
1157 :
1158 13 : sfc%nref = 0_IK
1159 13 : sfc%nsam(sfc%nref) = size(sampleWeight, 1, IK)
1160 13 : call setResized(logFuncStateAxis, sfc%nsam(sfc%nref))
1161 39 : call setRebound(sfc%sampleLogFuncState, [0_IK, 1_IK], [ndim, nsam])
1162 1300003 : sfc%sampleLogFuncState(1 : ndim, :) = sampleState
1163 285031 : sfc%sampleLogFuncState(0, :) = sampleLogFunc
1164 285044 : sfc%sampleWeight = sampleWeight
1165 :
1166 : ! Perform chain refinement.
1167 :
1168 13 : blockSufficientChainSize: if (ndim < nsam) then
1169 :
1170 : loopRefinement: do
1171 :
1172 593466 : sfc%sumw(sfc%nref) = sum(sfc%sampleWeight(1 : sfc%nsam(sfc%nref)))
1173 :
1174 : ! Obtain the ACT for each individual axes.
1175 : block
1176 216 : do idim = 0, ndim
1177 2773783 : logFuncStateAxis(1 : sfc%nsam(sfc%nref)) = sfc%sampleLogFuncState(idim, 1 : sfc%nsam(sfc%nref))
1178 216 : if (method%isViaCompactChain) then
1179 112 : if (method%isBatchMeansMax) then
1180 0 : sfc%act(idim, sfc%nref) = getACT(logFuncStateAxis(1 : sfc%nsam(sfc%nref)), batchMeansMax)
1181 112 : elseif (method%isBatchMeans) then
1182 112 : sfc%act(idim, sfc%nref) = getACT(logFuncStateAxis(1 : sfc%nsam(sfc%nref)), batchMeans)
1183 0 : elseif (method%isCumSumMax) then
1184 0 : sfc%act(idim, sfc%nref) = getACT(logFuncStateAxis(1 : sfc%nsam(sfc%nref)), cumSumMax)
1185 0 : elseif (method%isCumSum) then
1186 0 : sfc%act(idim, sfc%nref) = getACT(logFuncStateAxis(1 : sfc%nsam(sfc%nref)), cumSum)
1187 : else
1188 : error stop PROCEDURE_NAME//SK_"Internal Error: Unrecognized ACT computation method." ! LCOV_EXCL_LINE
1189 : end if
1190 52 : elseif (method%isViaVerboseChain) then
1191 52 : if (method%isBatchMeansMax) then
1192 0 : sfc%act(idim, sfc%nref) = getACT(logFuncStateAxis(1 : sfc%nsam(sfc%nref)), sfc%sampleWeight(1 : sfc%nsam(sfc%nref)), batchMeansMax)
1193 52 : elseif (method%isBatchMeans) then
1194 52 : sfc%act(idim, sfc%nref) = getACT(logFuncStateAxis(1 : sfc%nsam(sfc%nref)), sfc%sampleWeight(1 : sfc%nsam(sfc%nref)), batchMeans)
1195 0 : elseif (method%isCumSumMax) then
1196 0 : sfc%act(idim, sfc%nref) = getACT(logFuncStateAxis(1 : sfc%nsam(sfc%nref)), sfc%sampleWeight(1 : sfc%nsam(sfc%nref)), cumSumMax)
1197 0 : elseif (method%isCumSum) then
1198 0 : sfc%act(idim, sfc%nref) = getACT(logFuncStateAxis(1 : sfc%nsam(sfc%nref)), sfc%sampleWeight(1 : sfc%nsam(sfc%nref)), cumSum)
1199 : else
1200 : error stop PROCEDURE_NAME//SK_"Internal Error: Unrecognized ACT computation method." ! LCOV_EXCL_LINE
1201 : end if
1202 : else
1203 : error stop PROCEDURE_NAME//SK_": Internal error: Unrecognized chain format." ! LCOV_EXCL_LINE
1204 : endif
1205 : end do
1206 : end block
1207 :
1208 : ! act is guaranteed to be larger than `1` by definition.
1209 :
1210 52 : if (method%isAvg) then
1211 216 : act = sum(sfc%act(0 : ndim, sfc%nref)) * ndimp1inv
1212 0 : elseif (method%isMed) then
1213 0 : act = getQuan(piwilin, .5_RKC, sfc%act(0 : ndim, sfc%nref))
1214 0 : elseif (method%isMax) then
1215 0 : act = maxval(sfc%act(0 : ndim, sfc%nref))
1216 0 : elseif (method%isMin) then
1217 0 : act = minval(sfc%act(0 : ndim, sfc%nref))
1218 : else
1219 : error stop PROCEDURE_NAME//SK_": Internal error: Unrecognized refinement method." ! LCOV_EXCL_LINE
1220 : end if
1221 :
1222 : ! So far, we have computed the max ACT of the sample, but no refinement. Refine the sample only if needed.
1223 : ! The output sample size can be less than the requested outputSampleSize if nsam < outputSampleSize.
1224 : ! This is the right place to quit if needed, as all components for the current stage of the refinement are set.
1225 :
1226 52 : if (sfc%nref == outputSampleRefinementCount_def) exit loopRefinement
1227 52 : if (act < 2._RKC) then
1228 26 : if (method%isViaCompactChain .and. method%isViaVerboseChain) then
1229 13 : method%isViaCompactChain = .false._LK
1230 13 : cycle loopRefinement
1231 : else
1232 : exit loopRefinement
1233 : end if
1234 : end if
1235 :
1236 : ! Generate the refined sample, then put it back into sfc to start over again.
1237 :
1238 26 : sfc%nref = sfc%nref + 1_IK
1239 :
1240 : ! Reallocate to bigger array if needed.
1241 :
1242 26 : if (nrefAlloc < sfc%nref) then
1243 3 : nrefAlloc = min(nrefAlloc * 2, outputSampleRefinementCount_def)
1244 9 : call setRebound(sfc%act, [0_IK, 0_IK], [ndim, nrefAlloc])
1245 3 : call setRebound(sfc%nsam, 0_IK, nrefAlloc)
1246 3 : call setRebound(sfc%sumw, 0_IK, nrefAlloc)
1247 : end if
1248 : !block
1249 : ! use pm_io
1250 : ! call disp%show("act")
1251 : ! call disp%show( act )
1252 : ! print *, sfc%nref
1253 : ! print *, sfc%nsam(0 : sfc%nref - 1)
1254 : ! !call disp%show("sfc%nref")
1255 : ! !call disp%show( sfc%nref )
1256 : ! call disp%show("sfc%nsam(0 : sfc%nref - 1)")
1257 : ! call disp%show( sfc%nsam(0 : sfc%nref - 1) )
1258 : !end block
1259 0 : if (act < 2._RKC) cycle loopRefinement ! no need for refinement. should happen only when transitioning from compact to verbose.
1260 39 : call setRefined(sfc%sampleLogFuncState(:, 1 : sfc%nsam(sfc%nref - 1)), 2_IK, sfc%sampleWeight(1 : sfc%nsam(sfc%nref - 1)), skip = int(act, IK), rsize = sfc%nsam(sfc%nref))
1261 :
1262 : end do loopRefinement
1263 :
1264 0 : elseif (0_IK < nsam) then blockSufficientChainSize
1265 :
1266 : ! Return only the last sampled state if the input sample is too small.
1267 :
1268 0 : sfc%nsam(sfc%nref) = size(sampleWeight, 1, IK)
1269 0 : call setResized(logFuncStateAxis, sfc%nsam(sfc%nref))
1270 0 : call setRebound(sfc%sampleLogFuncState, [0_IK, 1_IK], [ndim, nsam])
1271 0 : sfc%sampleLogFuncState(1 : ndim, :) = sampleState
1272 0 : sfc%sampleLogFuncState(0, :) = sampleLogFunc
1273 0 : sfc%sampleWeight = sampleWeight
1274 :
1275 : end if blockSufficientChainSize
1276 :
1277 39 : call setRebound(sfc%sampleLogFuncState, [0_IK, 1_IK], [ndim, sfc%nsam(sfc%nref)])
1278 13 : call setResized(sfc%sampleWeight, sfc%nsam(sfc%nref))
1279 :
1280 13 : end function getErrRefinement
1281 :
1282 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1283 :
1284 13 : function getErrRefinementMethod(method, outputSampleRefinementMethod) result(err)
1285 :
1286 : use pm_val2int, only: getInt
1287 : use pm_strASCII, only: getStrLower
1288 : use pm_arrayReplace, only: getReplaced
1289 : type(method_type), intent(inout) :: method
1290 : character(*, SK), parameter :: PROCEDURE_NAME = SK_"@getErrRefinementMethod()"
1291 : character(*, SK), intent(in), optional :: outputSampleRefinementMethod
1292 : character(:, SK), allocatable :: outputSampleRefinementMethod_def
1293 : type(err_type) :: err
1294 : integer(IK) :: idim
1295 :
1296 13 : err%msg = ""
1297 : err%occurred = .false._LK
1298 :
1299 : ! Define the ACT computation method.
1300 :
1301 13 : if (present(outputSampleRefinementMethod)) then
1302 13 : outputSampleRefinementMethod_def = getStrLower(outputSampleRefinementMethod)
1303 13 : if (0 < index(outputSampleRefinementMethod_def, SK_"batchmeansmax")) then
1304 0 : method%isBatchMeansMax = .true._LK
1305 13 : elseif (0 < index(outputSampleRefinementMethod_def, SK_"batchmeans")) then
1306 13 : method%isBatchMeans = .true._LK
1307 0 : elseif (0 < index(outputSampleRefinementMethod_def, SK_"cumsummax")) then
1308 0 : method%isCumSumMax = .true._LK
1309 0 : elseif (0 < index(outputSampleRefinementMethod_def, SK_"cumsum")) then
1310 0 : method%isCumSum = .true._LK
1311 : else
1312 : err%occurred = .true._LK ! LCOV_EXCL_LINE
1313 : err%msg = getFine(__FILE__, __LINE__)//PROCEDURE_NAME//SK_": Unknown unsupported ACT computation method name: "//outputSampleRefinementMethod_def ! LCOV_EXCL_LINE
1314 : return ! LCOV_EXCL_LINE
1315 : end if
1316 13 : method%isViaCompactChain = 0 < index(outputSampleRefinementMethod_def, SK_"compact")
1317 13 : method%isViaVerboseChain = 0 < index(outputSampleRefinementMethod_def, SK_"verbose")
1318 : else
1319 0 : outputSampleRefinementMethod_def = SK_"batchmeans"
1320 0 : method%isBatchMeans = .true._LK
1321 : end if
1322 :
1323 : ! Define the chain types to use for the ACT computation.
1324 :
1325 13 : if (.not. (method%isViaCompactChain .or. method%isViaVerboseChain)) then
1326 13 : method%isViaCompactChain = .true._LK
1327 13 : method%isViaVerboseChain = .true._LK
1328 : end if
1329 :
1330 : ! Define the statistic to use for the collective ACT computation.
1331 :
1332 13 : outputSampleRefinementMethod_def = getReplaced(outputSampleRefinementMethod_def, SK_" ", SK_"-")
1333 13 : method%isMed = index(outputSampleRefinementMethod_def, SK_"-med") > 0 .or. index(outputSampleRefinementMethod_def, SK_"-median") > 0
1334 13 : method%isAvg = index(outputSampleRefinementMethod_def, SK_"-avg") > 0 .or. index(outputSampleRefinementMethod_def, SK_"-average") > 0
1335 13 : method%isMin = index(outputSampleRefinementMethod_def, SK_"-min") > 0 .or. index(outputSampleRefinementMethod_def, SK_"-minimum") > 0
1336 13 : method%isMax = index(outputSampleRefinementMethod_def, SK_"-max") > 0 .or. index(outputSampleRefinementMethod_def, SK_"-maximum") > 0
1337 65 : idim = sum(getInt([method%isAvg, method%isMed, method%isMax, method%isMin]))
1338 13 : err%occurred = 1_IK < idim
1339 13 : if (err%occurred) then
1340 : err%msg = getFine(__FILE__, __LINE__)//PROCEDURE_NAME//SK_": avg, med, min, max cannot be simultaneously specified in outputSampleRefinementMethod: "//outputSampleRefinementMethod_def ! LCOV_EXCL_LINE
1341 : return ! LCOV_EXCL_LINE
1342 : end if
1343 13 : if (idim == 0_IK) method%isAvg = .true._LK ! default method of ACT summarization.
1344 :
1345 26 : end function getErrRefinementMethod
1346 :
1347 : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|