MoDeNa  1.0
Software framework facilitating sequential multi-scale modelling
Strategy.py
Go to the documentation of this file.
1 
31 
32 
42 
43 import six
44 import abc
45 import sys
46 import copy
47 import modena
48 from fireworks import Firework, Workflow, FWAction, FireTaskBase, ScriptTask
49 from fireworks.utilities.fw_serializers import FWSerializable, \
50  recursive_serialize, recursive_deserialize, serialize_fw
51 import fireworks.utilities.fw_serializers as fw_serializers
52 from fireworks.utilities.fw_utilities import explicit_serialize
53 from fireworks.utilities.fw_serializers import load_object
54 from collections import defaultdict
55 from rpy2.robjects.packages import importr
56 import rpy2.robjects as robjects
57 import rpy2.rinterface as rinterface
58 from rpy2.robjects.vectors import FloatVector
59 from numpy import array
60 from numpy.random import choice, seed
61 from blessings import Terminal
62 
63 # Import R libraries
64 rinterface.initr()
65 nlmrt = importr('nlmrt')
66 lhs = importr('lhs')
67 
68 # Create terminal for colour output
69 term = Terminal()
70 
71 
74 
75 
76 
84 class InitialisationStrategy(defaultdict, FWSerializable):
85 
87  def __init__(self, *args, **kwargs):
88  dict.__init__(self, *args, **kwargs)
89 
90 
91  @abc.abstractmethod
92 
94  def newPoints(self):
95  raise NotImplementedError('newPoints not implemented!')
96 
97 
98 
108  def workflow(self, model):
109  p = self.newPoints()
110  if len(p):
111  wf = model.exactTasks(p)
112  wf.append_wf(
113  model.parameterFittingStrategy().workflow(model),
114  wf.leaf_fw_ids
115  )
116  return wf
117 
118  elif not len(p) and len(model.substituteModels):
119  wf = Workflow([])
120  for sm in model.substituteModels:
121  wf.append_wf(
122  sm.initialisationStrategy().workflow(sm),
123  []
124  )
125  return wf
126 
127  else:
128  return Workflow([])
129 
130 
131  @serialize_fw
132  @recursive_serialize
133 
135  def to_dict(self):
136  return dict(self)
137 
138 
139  @classmethod
140  @recursive_deserialize
141 
143  def from_dict(cls, m_dict):
144  return cls(m_dict)
145 
146 
147  def __repr__(self):
148  return '<{}>:{}'.format(self.fw_name, dict(self))
149 
150 
151 
159 class OutOfBoundsStrategy(defaultdict, FWSerializable):
160 
162  def __init__(self, *args, **kwargs):
163  dict.__init__(self, *args, **kwargs)
164 
165 
166  @abc.abstractmethod
167  def newPoints(self):
168  raise NotImplementedError('newPoints not implemented!')
169 
170 
171 
176  def workflow(self, model, **kwargs):
177  wf = model.exactTasks(self.newPoints(model, **kwargs))
178  wf.append_wf(
179  model.parameterFittingStrategy().workflow(model),
180  wf.leaf_fw_ids
181  )
182  return wf
183 
184 
185  @serialize_fw
186  @recursive_serialize
187  def to_dict(self):
188  return dict(self)
189 
190 
191  @classmethod
192  @recursive_deserialize
193  def from_dict(cls, m_dict):
194  return cls(m_dict)
195 
196 
197  def __repr__(self):
198  return '<{}>:{}'.format(self.fw_name, dict(self))
199 
200 
201 
203 class ImproveErrorStrategy(defaultdict, FWSerializable):
204  def __init__(self, *args, **kwargs):
205  dict.__init__(self, *args, **kwargs)
206 
207 
208  def workflow(self, model, **kwargs):
209  wf = model.exactTasks(self.newPoints(model))
210  wf.append_wf(
211  model.parameterFittingStrategy().workflow(model),
212  wf.leaf_fw_ids
213  )
214  return wf
215 
216 
217  @serialize_fw
218  @recursive_serialize
219  def to_dict(self):
220  return dict(self)
221 
222 
223  @classmethod
224  @recursive_deserialize
225  def from_dict(cls, m_dict):
226  return cls(m_dict)
227 
228 
229  def __repr__(self):
230  return '<{}>:{}'.format(self.fw_name, dict(self))
231 
232 
233 
235 class ParameterFittingStrategy(dict, FWSerializable):
236  def __init__(self, *args, **kwargs):
237  dict.__init__(self, *args, **kwargs)
238 
239 
240  @abc.abstractmethod
241  def newPointsFWAction(self, model, **kwargs):
242  raise NotImplementedError('newPointsFWAction not implemented!')
243 
244  def workflow(self, model):
245  return Workflow(
246  [
247  Firework(
248  ParameterFitting(surrogateModelId=model._id),
249  name='parameter fitting'
250  )
251  ]
252  )
253 
254 
255  def errorTest(model, parameters, testIndices):
256 
257  def fitData(testIndices):
258  for i in testPoint:
259  yield i
260 
261  # Instantiate the surrogate model
262  cModel = modena.libmodena.modena_model_t(
263  model,
264  parameters=list(parameters)
265  )
266 
267  return max(
268  abs(i) for i in model.error(
269  cModel,
270  idxGenerator=fitData(testPoint),
271  checkBounds=False
272  )
273  )
274 
275 
276  # errorFit function can only take a single arguemnt (parameters) when it
277  # is called from R. Using wrapper class instead!
278  class errorFit:
279 
280  def __init__(self, *args, **kwargs):
281  self.model = args[0]
282  self.testPoint = args[1]
283 
284  def function(parameters):
285 
286  def fitData(n, testPoint):
287  for i in xrange(n):
288  if i not in testPoint:
289  yield i
290 
291  # Instantiate the surrogate model
292  cModel = modena.libmodena.modena_model_t(
293  model=model,
294  parameters=list(parameters)
295  )
296 
297  return FloatVector(
298  list(
299  model.error(
300  cModel,
301  idxGenerator=fitData(model.nSamples, self.testPoint),
302  checkBounds=False
303  )
304  )
305  )
306 
307 
308  @serialize_fw
309  @recursive_serialize
310  def to_dict(self):
311  return dict(self)
312 
313 
314  @classmethod
315  @recursive_deserialize
316  def from_dict(cls, m_dict):
317  return cls(m_dict)
318 
319 
320  def __repr__(self):
321  return '<{}>:{}'.format(self.fw_name, dict(self))
322 
323 
324 
326 class SamplingStrategy():
327 
328  def newPoints(self):
329  raise NotImplementedError('newPoints not implemented!')
330 
331 
332  def samplePoints(self, model, sampleRange, nPoints):
333 
334  points = array(lhs.randomLHS(nPoints, len(sampleRange))).tolist()
335 
336  sr = sampleRange
337 
338  return {
339  key: [
340  sr[key]['min'] +
341  (sr[key]['max'] - sr[key]['min']) * points[i][j]
342  for i in xrange(nPoints)
343  ] for j, key in enumerate(sr)
344  }
345 
346 
347 @explicit_serialize
348 
353  def __init__(self, *args, **kwargs):
354  InitialisationStrategy.__init__(self, *args, **kwargs)
355 
356 
357  def newPoints(self):
358  return self['initialPoints']
359 
360 
361 @explicit_serialize
362 
367  def __init__(self, *args, **kwargs):
368  InitialisationStrategy.__init__(self, *args, **kwargs)
369 
370 
371  def newPoints(self):
372  return self['initialData']
373 
374 
375  def workflow(self, model):
376 
377  et = load_object({'_fw_name': '{{modena.Strategy.InitialDataPoints}}'})
378 
379  points = self.newPoints()
380 
381  e = six.next(six.itervalues(points))
382  p = { k:[0]*len(points[k]) for k in points }
383  for i in xrange(len(e)):
384  for k in points:
385  p[k][i] = points[k][i]
386 
387  t = et
388  t['point'] = p
389  t['indices'] = indices
390  t['modelId'] = self._id
391  fw = Firework(t)
392  wf = Workflow( [fw], name='initialising to dataset')
393 
394  wf.append_wf(
395  model.parameterFittingStrategy().workflow(model),
396  wf.leaf_fw_ids
397  )
398 
399  return wf
400 
401 
402 @explicit_serialize
403 
406  def newPoints(self):
407  return []
408 
409 
410 @explicit_serialize
411 
414  def __init__(self, *args, **kwargs):
415  OutOfBoundsStrategy.__init__(self, *args, **kwargs)
416 
417 
418  def newPoints(self, model, **kwargs):
419  # Get a sampling range around the outside point and create points
420  sampleRange, limitPoint = model.extendedRange(kwargs['outsidePoint'])
421  sp = self.samplePoints(model, sampleRange, self['nNewPoints']-1)
422  return { k: v + [limitPoint[k]] for k, v in sp.iteritems() }
423 
424 
425 @explicit_serialize
426 
429  def __init__(self, *args, **kwargs):
430  ImproveErrorStrategy.__init__(self, *args, **kwargs)
431 
432 
433 
438  def newPoints(self, model):
439  # Get a sampling range from fitData. Note: Cannot use MinMax must not
440  # be updated, yet
441  sampleRange = {
442  k: {
443  'min': min(model.fitData[k]),
444  'max': max(model.fitData[k])
445  } for k in model.inputs.keys()
446  }
447 
448  return self.samplePoints(model, sampleRange, self['nNewPoints'])
449 
450 
451 @explicit_serialize
452 
455 
459  def __init__(self, *args, **kwargs):
460  #if '_fw_name' in args[0]:
461  # ParameterFittingStrategy.__init__(self, *args, **kwargs)
462 
463  #if not kwargs.has_key('improveErrorStrategy'):
464  # raise Exception('Need improveErrorStrategy')
465  #if not isinstance(
466  # kwargs['improveErrorStrategy'], ImproveErrorStrategy
467  #):
468  # raise TypeError('Need improveErrorStrategy')
469 
470  ParameterFittingStrategy.__init__(self, *args, **kwargs)
471 
472 
473  def newPointsFWAction(self, model, **kwargs):
474  # Make sure we get new samples in deterministic manner
475  seed(model.nSamples)
476 
477  # TODO: The rest of this function should become a method in model (or /
478  # strategy class)
479 
480  # Create indices a subset (~20% of samples) for testing
481  testIndices = set(
482  choice(
483  model.nSamples,
484  size=max(1, self['testDataPercentage']*model.nSamples),
485  replace=False
486  )
487  )
488 
489  # ------------------------------ Function ----------------------------#
490  def errorFit(parameters):
491 
492  def fitData(n, testIndices):
493  for i in xrange(n):
494  if i not in testIndices:
495  yield i
496 
497  # Instantiate the surrogate model
498  cModel = modena.libmodena.modena_model_t(
499  model=model,
500  parameters=list(parameters)
501  )
502 
503  return FloatVector(
504  list(
505  model.error(
506  cModel,
507  idxGenerator=fitData(model.nSamples, testIndices),
508  checkBounds=False
509  )
510  )
511  )
512 
513  # ------------------------------------------------------------------- #
514 
515  # ------------------------------ Function --------------------------- #
516  def errorTest(parameters):
517 
518  def fitData(testIndices):
519  for i in testIndices:
520  yield i
521 
522  # Instantiate the surrogate model
523  cModel = modena.libmodena.modena_model_t(
524  model,
525  parameters=list(parameters)
526  )
527 
528  return max(
529  abs(i) for i in model.error(
530  cModel,
531  idxGenerator=fitData(testIndices),
532  checkBounds=False
533  )
534  )
535 
536  # ------------------------------------------------------------------- #
537 
538  new_parameters = model.parameters
539  if not len(new_parameters):
540  new_parameters = [None] * len(model.surrogateFunction.parameters)
541  for k, v in model.surrogateFunction.parameters.iteritems():
542  new_parameters[v.argPos] = (v.min + v.max)/2
543 
544  # make objects usable in R
545  R_par = FloatVector(new_parameters)
546  R_res = rinterface.rternalize(errorFit)
547 
548  max_parameters = [None]*len(new_parameters)
549  min_parameters = [None]*len(new_parameters)
550  for k, v in model.surrogateFunction.parameters.iteritems():
551  min_parameters[v.argPos] = v.min
552  max_parameters[v.argPos] = v.max
553 
554  # perform fitting (nonlinear MSSQ)
555  nlfb = nlmrt.nlfb(
556  start=R_par,
557  resfn=R_res,
558  jacfn=rinterface.NULL,
559  trace=rinterface.FALSE,
560  lower=FloatVector(min_parameters),
561  upper=FloatVector(max_parameters),
562  maskidx=rinterface.NULL
563  )
564  del max_parameters
565  del min_parameters
566 
567  # optimised coefficients and sum of squares
568  nlfb_coeffs = nlfb[nlfb.names.index('coefficients')]
569  nlfb_ssqres = nlfb[nlfb.names.index('ssquares')]
570  new_parameters = list(nlfb_coeffs)
571 
572  # The following code block will check the error and call the ImproveEr-
573  # rorStrategy to add more points to the design of experiments if the m-
574  # odel is not validated
575 
576  maxError = errorTest(new_parameters)
577 
578  print 'Maximum Error = %s' % maxError
579  if maxError > self['maxError']:
580  print(
581  'Parameters ' + term.red + 'not' + term.normal
582  + ' valid, adding samples.'
583  )
584  print(
585  'current parameters = [%s]' % ', '.join(
586  '%g' % k for k in new_parameters
587  )
588  )
589 
590  # Update database
591  model.save()
592 
593  return FWAction(
594  detours=self['improveErrorStrategy'].workflow(model)
595  )
596 
597  else:
598  print(
599  'old parameters = [%s]' % ', '.join(
600  '%g' % k for k in model.parameters
601  )
602  )
603  print(
604  'new parameters = [%s]' % ', '.join(
605  '%g' % k for k in new_parameters
606  )
607  )
608 
609  # Update database
610  # TODO: This is not save if the model is updated by another fitting
611  # task running concurrently
612  model.parameters = new_parameters
613  model.updateMinMax()
614  model.save()
615 
616  # return nothing to restart normal operation
617  return FWAction()
618 
619 
620 @explicit_serialize
621 
630 
631  def __init__(self, *args, **kwargs):
632 
633  # TODO: access tuple correctly
634  #if '_fw_name' in args[0]:
635  # ParameterFittingStrategy.__init__(self, *args, **kwargs)
636 
637  #if not kwargs.has_key('improveErrorStrategy'):
638  # raise Exception('Need improveErrorStrategy')
639  #if not isinstance(
640  # kwargs['improveErrorStrategy'], ImproveErrorStrategy
641  #):
642  # raise TypeError('Need improveErrorStrategy')
643 
644  ParameterFittingStrategy.__init__(self, *args, **kwargs)
645 
646 
647  def newPointsFWAction(self, model, **kwargs):
648 
649  new_parameters = model.parameters
650  if not len(new_parameters):
651  new_parameters = [None] * len(model.surrogateFunction.parameters)
652  for k, v in model.surrogateFunction.parameters.iteritems():
653  new_parameters[v.argPos] = (v.min + v.max)/2
654 
655  max_parameters = [None]*len(new_parameters)
656  min_parameters = [None]*len(new_parameters)
657  for k, v in model.surrogateFunction.parameters.iteritems():
658  min_parameters[v.argPos] = v.min
659  max_parameters[v.argPos] = v.max
660 
661  maxError = 1000
662  coeffs = None
663  for i in xrange(model.nSamples):
664  testPoint = [i]
665 
666  # ------------------------------ Function --------------------------- #
667  def errorTest(parameters):
668 
669  def fitData(testIndices):
670  for i in testPoint:
671  yield i
672 
673  # Instantiate the surrogate model
674  cModel = modena.libmodena.modena_model_t(
675  model,
676  parameters=list(parameters)
677  )
678 
679  return max(
680  abs(i) for i in model.error(
681  cModel,
682  idxGenerator=fitData(testPoint),
683  checkBounds=False
684  )
685  )
686  # ------------------------------------------------------------------- #
687 
688  # ------------------------------ Function ----------------------------#
689  def errorFit(parameters):
690 
691  def fitData(n, testPoint):
692  for i in xrange(n):
693  if i not in testPoint:
694  yield i
695 
696  # Instantiate the surrogate model
697  cModel = modena.libmodena.modena_model_t(
698  model=model,
699  parameters=list(parameters)
700  )
701 
702  return FloatVector(
703  list(
704  model.error(
705  cModel,
706  idxGenerator=fitData(model.nSamples, testPoint),
707  checkBounds=False
708  )
709  )
710  )
711  # ------------------------------------------------------------------- #
712 
713  # make objects usable in R
714  R_res = rinterface.rternalize(errorFit)
715  R_par = FloatVector(new_parameters)
716 
717  # perform fitting (nonlinear MSSQ)
718  nlfb = nlmrt.nlfb(
719  start=R_par,
720  resfn=R_res,
721  jacfn=rinterface.NULL,
722  trace=rinterface.FALSE,
723  lower=FloatVector(min_parameters),
724  upper=FloatVector(max_parameters),
725  maskidx=rinterface.NULL
726  )
727 
728  parameterError = errorTest(nlfb[nlfb.names.index('coefficients')])
729  if parameterError < maxError:
730  maxError = parameterError
731  new_parameters = list(nlfb[nlfb.names.index('coefficients')])
732  coeffs = nlfb
733 
734 
735  # optimised coefficients and sum of squares
736  nlfb_coeffs = coeffs[nlfb.names.index('coefficients')]
737  nlfb_ssqres = coeffs[nlfb.names.index('ssquares')]
738 
739  print 'Maximum Error = %s' % maxError
740  print(
741  'old parameters = [%s]' % ', '.join(
742  '%g' % k for k in model.parameters
743  )
744  )
745  print(
746  'new parameters = [%s]' % ', '.join(
747  '%g' % k for k in new_parameters
748  )
749  )
750 
751  # Update database
752  # TODO: This is not save if the model is updated by another fitting
753  # task running concurrently
754  model.parameters = new_parameters
755  model.updateMinMax()
756  model.save()
757 
758  del parameterError
759  del max_parameters
760  del min_parameters
761  del coeffs
762 
763  # return nothing to restart normal operation
764  return FWAction()
765 
766 
767 @explicit_serialize
768 
774 class Initialisation(FireTaskBase):
775 
776  def __init__(self, *args, **kwargs):
777  FireTaskBase.__init__(self, *args, **kwargs)
778 
779  if kwargs.has_key('surrogateModel'):
780  if isinstance(kwargs['surrogateModel'], modena.SurrogateModel):
781  self['surrogateModelId'] = kwargs['surrogateModel']['_id']
782  del self['surrogateModel']
783 
784 
785  def run_task(self, fw_spec):
786  try:
787  print term.cyan + 'Performing initialisation' + term.normal
788  model = modena.SurrogateModel.load(self['surrogateModelId'])
789  return FWAction(
790  detours=model.initialisationStrategy().workflow(model)
791  )
792  except:
793  import traceback
794  traceback.print_exc()
795  return FWAction(defuse_workflow=True)
796 
797 
798 @explicit_serialize
799 
805 class ParameterFitting(FireTaskBase):
806 
807  def __init__(self, *args, **kwargs):
808  FireTaskBase.__init__(self, *args, **kwargs)
809 
810  if kwargs.has_key('surrogateModel'):
811  if isinstance(kwargs['surrogateModel'], modena.SurrogateModel):
812  self['surrogateModelId'] = kwargs['surrogateModel']['_id']
813  del self['surrogateModel']
814 
815 
816  def run_task(self, fw_spec):
817  try:
818  model = modena.SurrogateModel.load(self['surrogateModelId'])
819  print(
820  term.cyan
821  + 'Performing parameter fitting for model %s' % model._id
822  + term.normal
823  );
824  model.updateFitDataFromFwSpec(fw_spec)
825  return model.parameterFittingStrategy().newPointsFWAction(model)
826  except Exception as e:
827  import traceback
828  traceback.print_exc()
829  return FWAction(defuse_workflow=True)
830 
831 
832 @explicit_serialize
833 
846 class InitialDataPoints(FireTaskBase):
847 
848  def run_task(self, fw_spec):
849  return FWAction(mod_spec=[{'_push': self['point']}])
850 
852 class OutOfBounds(Exception):
853  pass
854 
856 class ParametersNotValid(Exception):
857  pass
858 
860 class TerminateWorkflow(Exception):
861  pass
862 
864 class ModifyWorkflow(Exception):
865  pass
866 
867 
868 @explicit_serialize
869 
872 class ModenaFireTask(FireTaskBase):
873 
874  def executeAndCatchExceptions(self, op, text):
875  try:
876  op()
877 
878  except OutOfBounds as e:
879  model = e.args[1]
880  print(
881  term.cyan
882  + '%s out-of-bounds, executing outOfBoundsStrategy for model %s'
883  % (text, model._id)
884  + term.normal
885  )
886 
887  # Continue with exact tasks, parameter estimation and (finally) this
888  # task in order to resume normal operation
889  wf = model.outOfBoundsStrategy().workflow(
890  model,
891  outsidePoint=model.outsidePoint
892  )
893  wf.append_wf(
894  Workflow([Firework(self)], name='original task'),
895  wf.leaf_fw_ids
896  )
897  raise ModifyWorkflow(FWAction(detours=wf))
898 
899  except ParametersNotValid as e:
900  model = e.args[1]
901  print(
902  term.cyan
903  + '%s is not initialised, ' % text
904  + 'executing initialisationStrategy for model %s' % model._id
905  + term.normal
906  )
907 
908  # Continue with exact tasks, parameter estimation and (finally) this
909  # task in order to resume normal operation
910  wf = model.initialisationStrategy().workflow(model)
911  wf.append_wf(
912  Workflow([Firework(self)], name='original task'),
913  wf.leaf_fw_ids
914  )
915  raise ModifyWorkflow(FWAction(detours=wf))
916 
917 
918 
921  def run_task(self, fw_spec):
922  try:
923  print(
924  term.yellow
925  + 'Performing exact simulation (microscopic code recipe) for model '
926  + self['modelId']
927  + term.normal
928  )
929 
930  p = self['point']
931 
932  print(
933  term.yellow
934  + 'point = {%s}' % ', '.join(
935  '%s: %g' % (k, v) for (k, v) in p.iteritems()
936  )
937  + term.normal
938  )
939 
940  model = modena.SurrogateModel.load(self['modelId'])
941  oldP = copy.copy(p)
942  for m in model.substituteModels:
943  self.executeAndCatchExceptions(
944  lambda: p.update(m.callModel(p)),
945  'Substituted Model'
946  )
947 
948  if not len(p) == len(oldP):
949  print(
950  term.yellow
951  + 'values added by substitution = {%s}' % ', '.join(
952  '%s: %g' % (k, v) for (k, v) in p.iteritems()
953  if k not in oldP
954  )
955  + term.normal
956  )
957 
958  self.executeAndCatchExceptions(
959  lambda: self.task(fw_spec),
960  'Model'
961  )
962  return FWAction(mod_spec=[{'_push': self['point']}])
963 
964  except ModifyWorkflow as e:
965  return e.args[0]
966 
967  except Exception as e:
968  print(term.red + e.args[0] + term.normal)
969  import traceback
970  traceback.print_exc()
971  return FWAction(defuse_workflow=True)
972 
973  return FWAction()
974 
975 
976  def handleReturnCode(self, returnCode):
977 
978  # Analyse return code and raise appropriate exception
979  if returnCode > 0:
980  print(term.red + 'return code = %i' % returnCode + term.normal)
981 
982  if returnCode == 200:
983  try:
984  # TODO
985  # Finding the 'failing' model using the outsidePoint will fail
986  # eventually fail when running in parallel. Need to pass id of
987  # calling FireTask. However, this requires additional code in the
988  # library as well as cooperation of the recipie
989 
990  model = modena.SurrogateModel.loadFailing()
991  except:
992  raise TerminateWorkflow(
993  'Exact task raised OutOfBounds signal, '
994  + 'but failing model could not be determined',
995  returnCode
996  )
997  raise OutOfBounds(
998  'Exact task raised OutOfBounds signal',
999  model,
1000  returnCode
1001  )
1002 
1003  elif returnCode == 201:
1004  try:
1005  model = modena.SurrogateModel.loadFromModule()
1006  except:
1007  raise TerminateWorkflow(
1008  'Exact task raised LoadFromModule signal, '
1009  + 'but failing model could not be determined',
1010  returnCode
1011  )
1012  raise ParametersNotValid(
1013  'Exact task raised LoadFromModule signal',
1014  model,
1015  returnCode
1016  )
1017 
1018  elif returnCode == 202:
1019  try:
1020  model = modena.SurrogateModel.loadParametersNotValid()
1021  except:
1022  raise TerminateWorkflow(
1023  'Exact task raised ParametersNotValid, '
1024  + 'but failing model could not be determined',
1025  returnCode
1026  )
1027  raise ParametersNotValid(
1028  'Exact task raised ParametersNotValid',
1029  model,
1030  returnCode
1031  )
1032 
1033  elif returnCode > 0:
1034  raise TerminateWorkflow(
1035  'An unknow error occurred calling exact simulation',
1036  returnCode
1037  )
1038 
1039 
1040 @explicit_serialize
1041 
1046 class BackwardMappingScriptTask(ModenaFireTask, ScriptTask):
1047  required_params = ['script']
1048 
1049 
1052  def run_task(self, fw_spec):
1053  try:
1054  print(
1055  term.yellow
1056  + 'Performing backward mapping simulation '
1057  + '(macroscopic code recipe)'
1058  + term.normal
1059  )
1060  self.executeAndCatchExceptions(
1061  lambda: self.task(fw_spec),
1062  'Model'
1063  )
1064  print(term.green + 'Success - We are done' + term.normal)
1065 
1066  except ModifyWorkflow as e:
1067  return e.args[0]
1068 
1069  except Exception as e:
1070  print(term.red + e.args[0] + term.normal)
1071  import traceback
1072  traceback.print_exc()
1073  return FWAction(defuse_workflow=True)
1074 
1075  return FWAction()
1076 
1077 
1078  def task(self, fw_spec):
1079 
1080  self['defuse_bad_rc'] = True
1081 
1082  # Execute the macroscopic code by calling function in base class
1083  ret = ScriptTask.run_task(self, fw_spec)
1084  self.handleReturnCode(ret.stored_data['returncode'])
1085 
1086 
1088 
Performs parameter fitting of a set of samples and returns the parameters that yield the smallest err...
Definition: Strategy.py:628
Parent class for the initialisation strategies.
Definition: Strategy.py:83
Class for extending the design space using stochastic sampling.
Definition: Strategy.py:412
Class for initialisation of a surrogate model by fitting it to user-specified points.
Definition: Strategy.py:351
A FireTask that performs parameter fitting.
Definition: Strategy.py:804
Parameter fitting class, non-linear least squares regression.
Definition: Strategy.py:453
Base class for strategies &#39;fixing&#39; the error of a surrogate model.
Definition: Strategy.py:202
A FireTask that starts a macroscopic code and catches its return code.
Definition: Strategy.py:1045
Parent class for the out of bounds strategies.
Definition: Strategy.py:158
Empty initialisation strategy, used by Forward Mapping Models.
Definition: Strategy.py:404
Base class for Sampling strategies (DoE).
Definition: Strategy.py:325
A FireTask that performs the initialisation.
Definition: Strategy.py:773
Design of experiments class, Monte Carlo sampling.
Definition: Strategy.py:427
Pushes all "points" to the next firework.
Definition: Strategy.py:845
Class initialising a SurrogateModel given a dataset of input-output relations.
Definition: Strategy.py:365
Base Class for creating parameter fitting strategies.
Definition: Strategy.py:234