diff --git a/developer_tools/XSDSchemas/Samplers.xsd b/developer_tools/XSDSchemas/Samplers.xsd
index 884fadcaa9..e495471746 100644
--- a/developer_tools/XSDSchemas/Samplers.xsd
+++ b/developer_tools/XSDSchemas/Samplers.xsd
@@ -398,6 +398,7 @@
+
diff --git a/framework/JobHandler.py b/framework/JobHandler.py
index 6ff806bc96..b82e62b245 100644
--- a/framework/JobHandler.py
+++ b/framework/JobHandler.py
@@ -377,6 +377,18 @@ def addClientJob(self, args, functionToRun, identifier, metadata=None, uniqueHan
forceUseThreads = True, uniqueHandler = uniqueHandler,
clientQueue = True)
+ def addFinishedJob(self, data):
+ """
+ Takes an already-finished job (for example, a restart realization) and adds it to the finished queue.
+ @ In, data, dict, completed realization
+ @ Out, None
+ """
+ # create a placeholder runner
+ run = Runners.PassthroughRunner(self.messageHandler, data)
+ # place it on the finished queue
+ with self.__queueLock:
+ self.__finished.append(run)
+
def isFinished(self):
"""
Method to check if all the runs in the queue are finished
diff --git a/framework/Runners/PassthroughRunner.py b/framework/Runners/PassthroughRunner.py
new file mode 100644
index 0000000000..9c6da2e44d
--- /dev/null
+++ b/framework/Runners/PassthroughRunner.py
@@ -0,0 +1,86 @@
+# Copyright 2017 Battelle Energy Alliance, LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+ Module for Passthrough Runner class, which skips evaluation. Used particularly
+ for restarting Samplers from existing data currently.
+"""
+import numpy as np
+from .Runner import Runner
+
+class PassthroughRunner(Runner):
+ """
+ A runner for when we already have the answer, but need to go through the mechanics.
+ """
+ def __init__(self, messageHandler, data, metadata=None, uniqueHandler="any", profile=False):
+ """
+ Init method
+ @ In, messageHandler, MessageHandler object, the global RAVEN message
+ handler object
+ @ In, data, dict, fully-evaluated realization
+ @ In, metadata, dict, optional, dictionary of metadata associated with
+ this run
+ @ In, uniqueHandler, string, optional, it is a special keyword attached to
+ this runner. For example, if present, to retrieve this runner using the
+ method jobHandler.getFinished, the uniqueHandler needs to be provided.
+ If uniqueHandler == 'any', every "client" can get this runner
+ @ In, profile, bool, optional, if True then at deconstruction timing statements will be printed
+ @ Out, None
+ """
+ super(PassthroughRunner, self).__init__(messageHandler, metadata=metadata, uniqueHandler=uniqueHandler, profile=profile)
+ self._data = data # realization with completed data
+ self.returnCode = 0 # passthrough was born successful
+
+ def isDone(self):
+ """
+ Method to check if the calculation associated with this Runner is finished
+ @ In, None
+ @ Out, isDone, bool, is it finished?
+ """
+ return True # passthrough was born done
+
+ def getReturnCode(self):
+ """
+ Returns the return code from "running the code."
+ @ In, None
+ @ Out, returnCode, int, the return code of this evaluation
+ """
+ return self.returnCode
+
+ def getEvaluation(self):
+ """
+ Return solution.
+ @ In, None
+ @ Out, result, dict, results
+ """
+ result = {}
+ result.update(dict((key, np.atleast_1d(value)) for key, value in self._data['inputs'].items()))
+ result.update(dict((key, np.atleast_1d(value)) for key, value in self._data['outputs'].items()))
+ result.update(dict((key, np.atleast_1d(value)) for key, value in self._data['metadata'].items()))
+ return result
+
+ def start(self):
+ """
+ Method to start the job associated to this Runner
+ @ In, None
+ @ Out, None
+ """
+ pass # passthrough was born done
+
+ def kill(self):
+ """
+ Method to kill the job associated to this Runner
+ @ In, None
+ @ Out, None
+ """
+ pass # passthrough was born done; you can't kill it
\ No newline at end of file
diff --git a/framework/Runners/Runner.py b/framework/Runners/Runner.py
index 5a9d989038..2a8c7d50e3 100644
--- a/framework/Runners/Runner.py
+++ b/framework/Runners/Runner.py
@@ -38,7 +38,7 @@ class Runner(MessageHandler.MessageUser):
Generic base class for running codes and models in parallel environments
both internally (shared data) and externally.
"""
- def __init__(self, messageHandler, identifier = None, metadata = None, uniqueHandler = "any", profile = False):
+ def __init__(self, messageHandler, identifier=None, metadata=None, uniqueHandler="any", profile=False):
"""
Initialize command variable
@ In, messageHandler, MessageHandler instance, the global RAVEN message handler instance
diff --git a/framework/Runners/__init__.py b/framework/Runners/__init__.py
index da0a470f45..d95a77cc71 100644
--- a/framework/Runners/__init__.py
+++ b/framework/Runners/__init__.py
@@ -28,6 +28,7 @@
from .InternalRunner import InternalRunner
from .SharedMemoryRunner import SharedMemoryRunner
from .DistributedMemoryRunner import DistributedMemoryRunner
+from .PassthroughRunner import PassthroughRunner
from .Error import Error
# from .Factory import knownTypes
diff --git a/framework/Steps.py b/framework/Steps.py
index 0ac9ecb56d..05bc3263ae 100644
--- a/framework/Steps.py
+++ b/framework/Steps.py
@@ -626,9 +626,10 @@ def _localInitializeStep(self,inDictionary):
for inputIndex in range(inDictionary['jobHandler'].runInfoDict['batchSize']):
if inDictionary[self.samplerType].amIreadyToProvideAnInput():
try:
- newInput = self._findANewInputToRun(inDictionary[self.samplerType], inDictionary['Model'], inDictionary['Input'], inDictionary['Output'])
- inDictionary["Model"].submit(newInput, inDictionary[self.samplerType].type, inDictionary['jobHandler'], **copy.deepcopy(inDictionary[self.samplerType].inputInfo))
- self.raiseADebug('Submitted input '+str(inputIndex+1))
+ newInput = self._findANewInputToRun(inDictionary[self.samplerType], inDictionary['Model'], inDictionary['Input'], inDictionary['Output'], inDictionary['jobHandler'])
+ if newInput is not None:
+ inDictionary["Model"].submit(newInput, inDictionary[self.samplerType].type, inDictionary['jobHandler'], **copy.deepcopy(inDictionary[self.samplerType].inputInfo))
+ self.raiseADebug('Submitted input '+str(inputIndex+1))
except utils.NoMoreSamplesNeeded:
self.raiseAMessage('Sampler returned "NoMoreSamplesNeeded". Continuing...')
@@ -710,8 +711,9 @@ def _localTakeAstepRun(self,inDictionary):
if sampler.amIreadyToProvideAnInput():
try:
- newInput = self._findANewInputToRun(sampler, model, inputs, outputs)
- model.submit(newInput, inDictionary[self.samplerType].type, jobHandler, **copy.deepcopy(sampler.inputInfo))
+ newInput = self._findANewInputToRun(sampler, model, inputs, outputs, jobHandler)
+ if newInput is not None:
+ model.submit(newInput, inDictionary[self.samplerType].type, jobHandler, **copy.deepcopy(sampler.inputInfo))
except utils.NoMoreSamplesNeeded:
self.raiseAMessage(' ... Sampler returned "NoMoreSamplesNeeded". Continuing...')
break
@@ -728,7 +730,7 @@ def _localTakeAstepRun(self,inDictionary):
# if any collected runs failed, let the sampler treat them appropriately, and any other closing-out actions
sampler.finalizeSampler(self.failedRuns)
- def _findANewInputToRun(self, sampler, model, inputs, outputs):
+ def _findANewInputToRun(self, sampler, model, inputs, outputs, jobHandler):
"""
Repeatedly calls Sampler until a new run is found or "NoMoreSamplesNeeded" is raised.
@ In, sampler, Sampler, the sampler in charge of generating the sample
@@ -741,18 +743,20 @@ def _findANewInputToRun(self, sampler, model, inputs, outputs):
(i.e., a DataObject, File, or HDF5, I guess? Maybe these should all
inherit from some base "Data" so that we can ensure a consistent
interface for these?)
- @ Out, newInp, list, list containing the new inputs
+ @ In, jobHandler, object, the raven object used to handle jobs
+ @ Out, newInp, list, list containing the new inputs (or None if a restart)
"""
#The value of "found" determines what the Sampler is ready to provide.
# case 0: a new sample has been discovered and can be run, and newInp is a new input list.
# case 1: found the input in restart, and newInp is a realization dicitonary of data to use
- found = None
- while found != 0:
- found, newInp = sampler.generateInput(model,inputs)
- if found == 1:
- # loop over the outputs for this step and collect the data for each
- for collector, outIndex in self._outputDictCollectionLambda:
- collector([newInp,outputs[outIndex]])
+ found, newInp = sampler.generateInput(model,inputs)
+ if found == 1:
+ # "submit" the finished run
+ jobHandler.addFinishedJob(newInp)
+ return None
+ # NOTE: we return None here only because the Sampler's "counter" is not correctly passed
+ # through if we add several samples at once through the restart. If we actually returned
+ # a Realization object from the Sampler, this would not be a problem. - talbpaul
return newInp
#
#
diff --git a/tests/framework/Samplers/Restart/adaptive_mc.xml b/tests/framework/Samplers/Restart/adaptive_mc.xml
new file mode 100644
index 0000000000..d4a23c21c8
--- /dev/null
+++ b/tests/framework/Samplers/Restart/adaptive_mc.xml
@@ -0,0 +1,197 @@
+
+
+
+ framework/Samplers/Restart.AMC
+ talbpaul
+ 2020-07-16
+ Samplers.AdaptiveMonteCarlo
+
+ Tests restarting an Adaptive Monte Carlo sampling from restart. \texttt{makeCoarse} samples initial data, then \texttt{makeRestart}
+ makes additional samples, restarting from the first set of samples. \texttt{makeFine} does all the samples without restart
+ for comparison. The model for \texttt{coarse} always returns a value of 1, while the model for \texttt{restart} returns a value of 2, so
+ you can tell which samples came from which sampling strategy. Further, the solution export for
+ the restart should contain all the sample points, not merely the newly-sampled points.
+
+
+
+
+ AMC
+ makeCoarse,makeRestart,makeFine,print
+
+
+
+
+ dummyIN
+ coarsemod
+ coarse
+ exportCoarse
+
+
+
+ dummyIN
+ finemod
+ fine
+ exportFine
+
+
+
+ solns
+ finemod
+ restart
+ exportRestart
+
+
+
+ solns
+ solnsFine
+ solnsRestart
+ exportCoarse
+ exportFine
+ exportRestart
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 2
+
+
+ 2
+ 3
+
+
+
+
+
+ solns
+
+ 50
+ 5
+ False
+ x1
+
+ 42
+
+ u1
+
+
+ u2
+
+
+
+ solnsRestart
+
+ 50
+ 5
+ False
+ x1
+
+ 42
+
+ u1
+
+
+ u2
+
+ solns
+
+
+ solnsFine
+
+ 50
+ 5
+ False
+ x1
+
+ 42
+
+ u1
+
+
+ u2
+
+
+
+
+
+
+
+ x1,x2,ans
+
+
+ x1,x2,ans
+
+
+
+
+
+ x1,x2
+
+
+
+ x1,x2
+
+
+
+ x1,x2
+
+
+
+ x1,x2
+
+
+
+ solutionUpdate
+
+
+
+ solutionUpdate
+
+
+
+ solutionUpdate
+
+
+
+
+
+
+ csv
+ solns
+ input,output
+
+
+ csv
+ solnsFine
+ input,output
+
+
+ csv
+ solnsRestart
+ input,output
+
+
+ csv
+ exportCoarse
+ input,output
+
+
+ csv
+ exportFine
+ input,output
+
+
+ csv
+ exportRestart
+ input,output
+
+
+
+
diff --git a/tests/framework/Samplers/Restart/gold/AMC/coarse.csv b/tests/framework/Samplers/Restart/gold/AMC/coarse.csv
new file mode 100644
index 0000000000..d59b9318c6
--- /dev/null
+++ b/tests/framework/Samplers/Restart/gold/AMC/coarse.csv
@@ -0,0 +1,7 @@
+x1,x2,ans
+1.3745401144,2.79654298439,1.0
+1.95071431178,2.18343478771,1.0
+1.7319939385,2.77969099762,1.0
+1.59865848641,2.59685016158,1.0
+1.15601863855,2.44583275762,1.0
+1.15599452382,2.09997492053,1.0
diff --git a/tests/framework/Samplers/Restart/gold/AMC/exp_coarse.csv b/tests/framework/Samplers/Restart/gold/AMC/exp_coarse.csv
new file mode 100644
index 0000000000..9547170773
--- /dev/null
+++ b/tests/framework/Samplers/Restart/gold/AMC/exp_coarse.csv
@@ -0,0 +1,6 @@
+solutionUpdate,mean_x1,mean_ste_x1
+1,1.66262721309,0.288087098693
+2,1.68574945489,0.167926661206
+3,1.66397671277,0.120721721622
+4,1.56238509793,0.138076415978
+5,1.49465333558,0.131520553771
diff --git a/tests/framework/Samplers/Restart/gold/AMC/exp_fine.csv b/tests/framework/Samplers/Restart/gold/AMC/exp_fine.csv
new file mode 100644
index 0000000000..176ceb43db
--- /dev/null
+++ b/tests/framework/Samplers/Restart/gold/AMC/exp_fine.csv
@@ -0,0 +1,16 @@
+solutionUpdate,mean_x1,mean_ste_x1
+1,1.66262721309,0.288087098693
+2,1.68574945489,0.167926661206
+3,1.66397671277,0.120721721622
+4,1.56238509793,0.138076415978
+5,1.49465333558,0.131520553771
+6,1.43228623208,0.127456362007
+7,1.48652247167,0.122985417215
+8,1.4992549761,0.109207722536
+9,1.52013673634,0.0998854806255
+10,1.47472289656,0.101121245154
+11,1.51598847578,0.101114307658
+12,1.54033110353,0.0961443070765
+13,1.51690310413,0.092043828684
+14,1.49456456166,0.0885520639248
+15,1.47511705843,0.0850851920379
diff --git a/tests/framework/Samplers/Restart/gold/AMC/exp_restart.csv b/tests/framework/Samplers/Restart/gold/AMC/exp_restart.csv
new file mode 100644
index 0000000000..176ceb43db
--- /dev/null
+++ b/tests/framework/Samplers/Restart/gold/AMC/exp_restart.csv
@@ -0,0 +1,16 @@
+solutionUpdate,mean_x1,mean_ste_x1
+1,1.66262721309,0.288087098693
+2,1.68574945489,0.167926661206
+3,1.66397671277,0.120721721622
+4,1.56238509793,0.138076415978
+5,1.49465333558,0.131520553771
+6,1.43228623208,0.127456362007
+7,1.48652247167,0.122985417215
+8,1.4992549761,0.109207722536
+9,1.52013673634,0.0998854806255
+10,1.47472289656,0.101121245154
+11,1.51598847578,0.101114307658
+12,1.54033110353,0.0961443070765
+13,1.51690310413,0.092043828684
+14,1.49456456166,0.0885520639248
+15,1.47511705843,0.0850851920379
diff --git a/tests/framework/Samplers/Restart/gold/AMC/fine.csv b/tests/framework/Samplers/Restart/gold/AMC/fine.csv
new file mode 100644
index 0000000000..8d17e9e9cd
--- /dev/null
+++ b/tests/framework/Samplers/Restart/gold/AMC/fine.csv
@@ -0,0 +1,17 @@
+x1,x2,ans
+1.3745401144,2.79654298439,2.0
+1.95071431178,2.18343478771,2.0
+1.7319939385,2.77969099762,2.0
+1.59865848641,2.59685016158,2.0
+1.15601863855,2.44583275762,2.0
+1.15599452382,2.09997492053,2.0
+1.05808361109,2.45924888795,2.0
+1.86617614885,2.33370861139,2.0
+1.60111501152,2.14286681431,2.0
+1.70807257847,2.65088847341,2.0
+1.02058449877,2.05641157647,2.0
+1.96990984724,2.72199877159,2.0
+1.83244263656,2.9385527144,2.0
+1.21233911189,2.00077876472,2.0
+1.18182496707,2.99221156444,2.0
+1.18340450995,2.6174815075,2.0
diff --git a/tests/framework/Samplers/Restart/gold/AMC/restart.csv b/tests/framework/Samplers/Restart/gold/AMC/restart.csv
new file mode 100644
index 0000000000..533255eabd
--- /dev/null
+++ b/tests/framework/Samplers/Restart/gold/AMC/restart.csv
@@ -0,0 +1,17 @@
+x1,x2,ans
+1.3745401144,2.79654298439,1.0
+1.95071431178,2.18343478771,1.0
+1.7319939385,2.77969099762,1.0
+1.59865848641,2.59685016158,1.0
+1.15601863855,2.44583275762,1.0
+1.15599452382,2.09997492053,1.0
+1.05808361109,2.45924888795,2.0
+1.86617614885,2.33370861139,2.0
+1.60111501152,2.14286681431,2.0
+1.70807257847,2.65088847341,2.0
+1.02058449877,2.05641157647,2.0
+1.96990984724,2.72199877159,2.0
+1.83244263656,2.9385527144,2.0
+1.21233911189,2.00077876472,2.0
+1.18182496707,2.99221156444,2.0
+1.18340450995,2.6174815075,2.0
diff --git a/tests/framework/Samplers/Restart/tests b/tests/framework/Samplers/Restart/tests
index 8503749034..e8564edfda 100644
--- a/tests/framework/Samplers/Restart/tests
+++ b/tests/framework/Samplers/Restart/tests
@@ -7,6 +7,12 @@
UnorderedCsv = 'mc/coarse.csv mc/restart.csv mc/fine.csv'
[../]
+ [./AMC]
+ type = 'RavenFramework'
+ input = 'adaptive_mc.xml'
+ UnorderedCsv = 'AMC/coarse.csv AMC/restart.csv AMC/fine.csv AMC/exp_coarse.csv AMC/exp_restart.csv AMC/exp_fine.csv'
+ [../]
+
[./StochPoly]
type = 'RavenFramework'
input = 'test_restart_stochpoly.xml'
@@ -40,7 +46,7 @@
output = 'large/large_restart.xml'
UnorderedCsv = 'large/large_restart.csv'
[../]
-
+
[./Constant]
type = 'RavenFramework'
input = 'test_restart_constant.xml'