/[escript]/trunk/escript/py_src/modelframe.py
ViewVC logotype

Contents of /trunk/escript/py_src/modelframe.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 266 - (show annotations)
Wed Nov 30 00:21:51 2005 UTC (13 years, 10 months ago) by elspeth
File MIME type: text/x-python
File size: 28399 byte(s)
Added handling for NoneType

1 # $Id$
2
3 from types import StringType,IntType,FloatType,BooleanType,ListType,DictType
4 from sys import stdout
5 import itertools
6 # import modellib temporarily removed!!!
7
8 # import the 'set' module if it's not defined (python2.3/2.4 difference)
9 try:
10 set
11 except NameError:
12 from sets import Set as set
13
14 from xml.dom import minidom
15
16 def dataNode(document, tagName, data):
17 """
18 C{dataNode}s are the building blocks of the xml documents constructed in
19 this module.
20
21 @param document: the current xml document
22 @param tagName: the associated xml tag
23 @param data: the values in the tag
24 """
25 t = document.createTextNode(str(data))
26 n = document.createElement(tagName)
27 n.appendChild(t)
28 return n
29
30 def esysDoc():
31 """
32 Global method for creating an instance of an EsysXML document.
33 """
34 doc = minidom.Document()
35 esys = doc.createElement('ESys')
36 doc.appendChild(esys)
37 return doc, esys
38
39 def all(seq):
40 for x in seq:
41 if not x:
42 return False
43 return True
44
45 def any(seq):
46 for x in seq:
47 if x:
48 return True
49 return False
50
51 LinkableObjectRegistry = {}
52
53 def registerLinkableObject(obj_id, o):
54 LinkableObjectRegistry[obj_id] = o
55
56 LinkRegistry = []
57
58 def registerLink(obj_id, l):
59 LinkRegistry.append((obj_id,l))
60
61 def parse(xml):
62 """
63 Generic parse method for EsysXML. Without this, Links don't work.
64 """
65 global LinkRegistry, LinkableObjectRegistry
66 LinkRegistry = []
67 LinkableObjectRegistry = {}
68
69 doc = minidom.parseString(xml)
70 sim = getComponent(doc.firstChild)
71 for obj_id, link in LinkRegistry:
72 link.target = LinkableObjectRegistry[obj_id]
73
74 return sim
75
76 def importName(modulename, name):
77 """ Import a named object from a module in the context of this function,
78 which means you should use fully qualified module paths.
79
80 Return None on failure.
81
82 This function from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52241
83 """
84 module = __import__(modulename, globals(), locals(), [name])
85
86 try:
87 return vars(module)[name]
88 except KeyError:
89 raise ImportError("Could not import %s from %s" % (name, modulename))
90
91 def getComponent(doc):
92 """
93 Used to get components of Simualtions, Models.
94 """
95 for node in doc.childNodes:
96
97 if isinstance(node, minidom.Element):
98 if node.tagName == 'Simulation':
99 if node.getAttribute("type") == 'Simulation':
100 return Simulation.fromDom(node)
101 if node.tagName == 'Model':
102 if (node.getAttribute("module")):
103 model_module = node.getAttribute("module")
104 model_type = node.getAttribute("type")
105 return importName(model_module, model_type).fromDom(node)
106 else:
107 model_type = node.getAttribute("type")
108 model_subclasses = Model.__subclasses__()
109 for model in model_subclasses:
110 if model_type == model.__name__:
111 return Model.fromDom(node)
112 if node.tagName == 'ParameterSet':
113 parameter_type = node.getAttribute("type")
114 return ParameterSet.fromDom(node)
115 raise "Invalid simulation type, %r" % node.getAttribute("type")
116
117
118 raise ValueError("No Simulation Found")
119
120
121 class Link:
122 """
123 A Link makes an attribute of an object callable::
124
125 o.object()
126 o.a=8
127 l=Link(o,"a")
128 assert l()==8
129 """
130
131 def __init__(self,target,attribute=None):
132 """
133 Creates a link to the object target. If attribute is given, the link is
134 establised to this attribute of the target. Otherwise the attribute is
135 undefined.
136 """
137 self.target = target
138 self.attribute = None
139 self.setAttributeName(attribute)
140
141 def setAttributeName(self,attribute):
142 """
143 Set a new attribute name to be collected from the target object. The
144 target object must have the attribute with name attribute.
145 """
146 if attribute and self.target:
147 if isinstance(self.target,LinkableObject):
148 if not self.target.hasAttribute(attribute):
149 raise AttributeError("%s: target %s has no attribute %s."%(self, self.target, attribute))
150 else:
151 if not hasattr(self.target,attribute):
152 raise AttributeError("%s: target %s has no attribute %s."%(self, self.target, attribute))
153 self.attribute = attribute
154
155 def hasDefinedAttributeName(self):
156 """
157 Returns true if an attribute name is set.
158 """
159 return self.attribute != None
160
161 def __repr__(self):
162 """
163 Returns a string representation of the link.
164 """
165 if self.hasDefinedAttributeName():
166 return "<Link to attribute %s of %s>" % (self.attribute, self.target)
167 else:
168 return "<Link to target %s>" % self.target
169
170 def __call__(self,name=None):
171 """
172 Returns the value of the attribute of the target object. If the
173 atrribute is callable then the return value of the call is returned.
174 """
175 if name:
176 out=getattr(self.target, name)
177 else:
178 out=getattr(self.target, self.attribute)
179
180 if callable(out):
181 return out()
182 else:
183 return out
184
185 def toDom(self, document, node):
186 """
187 C{toDom} method of Link. Creates a Link node and appends it to the
188 current XML document.
189 """
190 link = document.createElement('Link')
191 assert (self.target != None), ("Target was none, name was %r" % self.attribute)
192 link.appendChild(dataNode(document, 'Target', self.target.id))
193 # this use of id will not work for purposes of being able to retrieve the intended
194 # target from the xml later. I need a better unique identifier.
195 assert self.attribute, "You can't xmlify a Link without a target attribute"
196 link.appendChild(dataNode(document, 'Attribute', self.attribute))
197 node.appendChild(link)
198
199 def fromDom(cls, doc):
200 targetid = doc.getElementsByTagName("Target")[0].firstChild.nodeValue.strip()
201 attribute = doc.getElementsByTagName("Attribute")[0].firstChild.nodeValue.strip()
202 l = cls(None, attribute)
203 registerLink(targetid, l)
204 return l
205
206 fromDom = classmethod(fromDom)
207
208 def writeXML(self,ostream=stdout):
209 """
210 Writes an XML representation of self to the output stream ostream.
211 If ostream is nor present the standart output stream is used. If
212 esysheader==True the esys XML header is written
213 """
214 print 'I got to the Link writeXML method'
215 document, rootnode = esysDoc()
216 self.toDom(document, rootnode)
217
218 ostream.write(document.toprettyxml())
219
220 class LinkableObject(object):
221 """
222 An object that allows to link its attributes to attributes of other objects
223 via a Link object. For instance::
224
225 p = LinkableObject()
226 p.x = Link(o,"name")
227 print p.x
228
229 links attribute C{x} of C{p} to the attribute name of object C{o}.
230
231 C{p.x} will contain the current value of attribute C{name} of object
232 C{o}.
233
234 If the value of C{getattr(o, "name")} is callable, C{p.x} will return
235 the return value of the call.
236 """
237
238 number_sequence = itertools.count(100)
239
240 def __init__(self, debug=False):
241 """
242 Initializes LinkableObject so that we can operate on Links
243 """
244 self.debug = debug
245 self.__linked_attributes={}
246 self.id = self.number_sequence.next()
247 registerLinkableObject(self.id, self)
248
249 def trace(self, msg):
250 """
251 If debugging is on, print the message, otherwise do nothing
252 """
253 if self.debug:
254 print "%s: %s"%(str(self),msg)
255
256 def __getattr__(self,name):
257 """
258 Returns the value of attribute name. If the value is a Link object the
259 object is called and the return value is returned.
260 """
261 out = self.getAttributeObject(name)
262 if isinstance(out,Link):
263 return out()
264 else:
265 return out
266
267 def getAttributeObject(self,name):
268 """
269 Return the object stored for attribute name.
270 """
271
272 if self.__dict__.has_key(name):
273 return self.__dict__[name]
274
275 if self.__linked_attributes.has_key(name):
276 return self.__linked_attributes[name]
277
278 if self.__class__.__dict__.has_key(name):
279 return self.__class.__dict__[name]
280
281 raise AttributeError,"No attribute %s."%name
282
283 def hasAttribute(self,name):
284 """
285 Returns True if self as attribute name.
286 """
287 return self.__dict__.has_key(name) or self.__linked_attributes.has_key(name) or self.__class__.__dict__.has_key(name)
288
289 def __setattr__(self,name,value):
290 """
291 Sets the value for attribute name. If value is a Link the target
292 attribute is set to name if no attribute has been specified.
293 """
294
295 if self.__dict__.has_key(name):
296 del self.__dict__[name]
297
298 if isinstance(value,Link):
299 if not value.hasDefinedAttributeName():
300 value.setAttributeName(name)
301 self.__linked_attributes[name] = value
302
303 self.trace("attribute %s is now linked by %s."%(name,value))
304 else:
305 self.__dict__[name] = value
306
307 def __delattr__(self,name):
308 """
309 Removes the attribute name.
310 """
311
312 if self.__linked_attributes.has_key[name]:
313 del self.__linked_attributes[name]
314 elif self.__dict__.has_key(name):
315 del self.__dict__[name]
316 else:
317 raise AttributeError,"No attribute %s."%name
318
319 class _ParameterIterator:
320 def __init__(self,parameterset):
321
322 self.__set=parameterset
323 self.__iter=iter(parameterset.parameters)
324
325 def next(self):
326 o=self.__iter.next()
327 return (o,self.__set.getAttributeObject(o))
328
329 def __iter__(self):
330 return self
331
332 class ParameterSet(LinkableObject):
333 """
334 A class which allows to emphazise attributes to be written and read to XML
335
336 Leaves of an ESySParameters object can be:
337
338 - a real number
339 - a integer number
340 - a string
341 - a boolean value
342 - a ParameterSet object
343 - a Simulation object
344 - a Model object
345 - any other object (not considered by writeESySXML and writeXML)
346
347 Example how to create an ESySParameters object::
348
349 p11=ParameterSet(gamma1=1.,gamma2=2.,gamma3=3.)
350 p1=ParameterSet(dim=2,tol_v=0.001,output_file="/tmp/u.%3.3d.dx",runFlag=True,parm11=p11)
351 parm=ParameterSet(parm1=p1,parm2=ParameterSet(alpha=Link(p11,"gamma1")))
352
353 This can be accessed as::
354
355 parm.parm1.gamma=0.
356 parm.parm1.dim=2
357 parm.parm1.tol_v=0.001
358 parm.parm1.output_file="/tmp/u.%3.3d.dx"
359 parm.parm1.runFlag=True
360 parm.parm1.parm11.gamma1=1.
361 parm.parm1.parm11.gamma2=2.
362 parm.parm1.parm11.gamma3=3.
363 parm.parm2.alpha=1. (value of parm.parm1.parm11.gamma1)
364 """
365 def __init__(self, parameters=[], **kwargs):
366 """
367 Creates a ParameterSet with parameters parameters.
368 """
369 LinkableObject.__init__(self, **kwargs)
370 self.parameters = set()
371 self.declareParameters(parameters)
372
373 def __repr__(self):
374 return "<%s %r>" % (self.__class__.__name__,
375 [(p, getattr(self, p, None)) for p in self.parameters])
376
377 def declareParameter(self,**parameters):
378 """
379 Declares a new parameter(s) and its (their) initial value.
380 """
381 self.declareParameters(parameters)
382
383 def declareParameters(self,parameters):
384 """
385 Declares a set of parameters. parameters can be a list, a dictionary
386 or a ParameterSet.
387 """
388 if isinstance(parameters,ListType):
389 parameters = zip(parameters, itertools.repeat(None))
390 if isinstance(parameters,DictType):
391 parameters = parameters.iteritems()
392
393 for prm, value in parameters:
394 setattr(self,prm,value)
395 self.parameters.add(prm)
396
397 self.trace("parameter %s has been declared."%prm)
398
399 def releaseParameters(self,name):
400 """
401 Removes parameter name from the paramameters.
402 """
403 if self.isParameter(name):
404 self.parameters.remove(name)
405 self.trace("parameter %s has been removed."%name)
406
407 def __iter__(self):
408 """
409 Creates an iterator over the parameter and their values.
410 """
411 return _ParameterIterator(self)
412
413 def showParameters(self):
414 """
415 Returns a descrition of the parameters.
416 """
417 out="{"
418 notfirst=False
419 for i,v in self:
420 if notfirst: out=out+","
421 notfirst=True
422 if isinstance(v,ParameterSet):
423 out="%s\"%s\" : %s"%(out,i,v.showParameters())
424 else:
425 out="%s\"%s\" : %s"%(out,i,v)
426 return out+"}"
427
428 def __delattr__(self,name):
429 """
430 Removes the attribute name.
431 """
432 LinkableObject.__delattr__(self,name)
433 try:
434 self.releaseParameter(name)
435 except:
436 pass
437
438 def toDom(self, document, node):
439 """
440 C{toDom} method of ParameterSet class.
441 """
442 pset = document.createElement('ParameterSet')
443 node.appendChild(pset)
444 self._parametersToDom(document, pset)
445
446 def _parametersToDom(self, document, node):
447 node.setAttribute ('id', str(self.id))
448 for name,value in self:
449 param = document.createElement('Parameter')
450 param.setAttribute('type', value.__class__.__name__)
451
452 param.appendChild(dataNode(document, 'Name', name))
453
454 val = document.createElement('Value')
455
456 if isinstance(value,ParameterSet):
457 value.toDom(document, val)
458 param.appendChild(val)
459 elif isinstance(value, Link):
460 value.toDom(document, val)
461 param.appendChild(val)
462 elif isinstance(value,StringType):
463 param.appendChild(dataNode(document, 'Value', value))
464 else:
465 param.appendChild(dataNode(document, 'Value', str(value)))
466
467 node.appendChild(param)
468
469 def fromDom(cls, doc):
470
471 # Define a host of helper functions to assist us.
472 def _children(node):
473 """
474 Remove the empty nodes from the children of this node.
475 """
476 return [x for x in node.childNodes
477 if not isinstance(x, minidom.Text) or x.nodeValue.strip()]
478
479 def _floatfromValue(doc):
480 return float(doc.nodeValue.strip())
481
482 def _stringfromValue(doc):
483 return str(doc.nodeValue.strip())
484
485 def _intfromValue(doc):
486 return int(doc.nodeValue.strip())
487
488 def _boolfromValue(doc):
489 return bool(doc.nodeValue.strip())
490
491 def _nonefromValue(doc):
492 return None
493
494 # Mapping from text types in the xml to methods used to process trees of that type
495 ptypemap = {"Simulation": Simulation.fromDom,
496 "Model":Model.fromDom,
497 "ParameterSet":ParameterSet.fromDom,
498 "Link":Link.fromDom,
499 "float":_floatfromValue,
500 "int":_intfromValue,
501 "str":_stringfromValue,
502 "bool":_boolfromValue
503 "NoneType":_nonefromValue,
504 }
505
506 # print doc.toxml()
507
508 parameters = {}
509 for node in _children(doc):
510 ptype = node.getAttribute("type")
511
512 pname = pvalue = None
513 for childnode in _children(node):
514
515 if childnode.tagName == "Name":
516 pname = childnode.firstChild.nodeValue.strip()
517
518 if childnode.tagName == "Value":
519 nodes = _children(childnode)
520 pvalue = ptypemap[ptype](nodes[0])
521
522 parameters[pname] = pvalue
523
524 # Create the instance of ParameterSet
525 o = cls()
526 o.declareParameters(parameters)
527 registerLinkableObject(doc.getAttribute("id"), o)
528 return o
529
530 fromDom = classmethod(fromDom)
531
532 def writeXML(self,ostream=stdout):
533 """
534 Writes the object as an XML object into an output stream.
535 """
536 # ParameterSet(d) with d[Name]=Value
537 document, node = esysDoc()
538 self.toDom(document, node)
539 ostream.write(document.toprettyxml())
540
541 class Model(ParameterSet):
542 """
543 A Model object represents a processess marching over time until a
544 finalizing condition is fullfilled. At each time step an iterative
545 process can be performed and the time step size can be controlled. A
546 Model has the following work flow::
547
548 doInitialization()
549 while not finalize():
550 dt=getSafeTimeStepSize(dt)
551 doStepPreprocessing(dt)
552 while not terminateIteration(): doStep(dt)
553 doStepPostprocessing(dt)
554 doFinalization()
555
556 where C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
557 C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
558 C{doFinalization} are methods of the particular instance of a Model. The
559 default implementations of these methods have to be overwritten by the
560 subclass implementing a Model.
561 """
562
563 UNDEF_DT=1.e300
564
565 def __init__(self,parameters=[],**kwarg):
566 """
567 Creates a model.
568
569 Just calls the parent constructor.
570 """
571 ParameterSet.__init__(self, parameters=parameters,**kwarg)
572
573 def __str__(self):
574 return "<%s %d>"%(self.__class__,id(self))
575
576 def toDom(self, document, node):
577 """
578 C{toDom} method of Model class
579 """
580 pset = document.createElement('Model')
581 pset.setAttribute('type', self.__class__.__name__)
582 if not self.__class__.__module__.startswith('esys.escript'):
583 pset.setAttribute('module', self.__class__.__module__)
584 node.appendChild(pset)
585 self._parametersToDom(document, pset)
586
587 def doInitialization(self):
588 """
589 Initializes the time stepping scheme.
590
591 This function may be overwritten.
592 """
593 pass
594
595 def getSafeTimeStepSize(self,dt):
596 """
597 Returns a time step size which can safely be used.
598
599 C{dt} gives the previously used step size.
600
601 This function may be overwritten.
602 """
603 return self.UNDEF_DT
604
605 def finalize(self):
606 """
607 Returns False if the time stepping is finalized.
608
609 This function may be overwritten.
610 """
611 return False
612
613 def doFinalization(self):
614 """
615 Finalizes the time stepping.
616
617 This function may be overwritten.
618 """
619 pass
620
621 def doStepPreprocessing(self,dt):
622 """
623 Sets up a time step of step size dt.
624
625 This function may be overwritten.
626 """
627 pass
628
629 def doStep(self,dt):
630 """
631 Executes an iteration step at a time step.
632
633 C{dt} is the currently used time step size.
634
635 This function may be overwritten.
636 """
637 pass
638
639 def terminateIteration(self):
640 """
641 Returns True if iteration on a time step is terminated.
642 """
643 return True
644
645 def doStepPostprocessing(self,dt):
646 """
647 Finalalizes the time step.
648
649 dt is the currently used time step size.
650
651 This function may be overwritten.
652 """
653 pass
654
655 def writeXML(self, ostream=stdout):
656 document, node = esysDoc()
657 self.toDom(document, node)
658 ostream.write(document.toprettyxml())
659
660
661 class Simulation(Model):
662 """
663 A Simulation object is special Model which runs a sequence of Models.
664
665 The methods C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
666 C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
667 C{doFinalization} are executing the corresponding methods of the models in
668 the simulation.
669 """
670
671 FAILED_TIME_STEPS_MAX=20
672 MAX_ITER_STEPS=50
673
674 def __init__(self, models=[], **kwargs):
675 """
676 Initiates a simulation from a list of models.
677 """
678 Model.__init__(self, **kwargs)
679 self.__models=[]
680
681 for i in range(len(models)):
682 self[i] = models[i]
683
684
685 def __repr__(self):
686 """
687 Returns a string representation of the Simulation.
688 """
689 return "<Simulation %r>" % self.__models
690
691 def __str__(self):
692 """
693 Returning Simulation as a string.
694 """
695 return "<Simulation %d>"%id(self)
696
697 def iterModels(self):
698 """
699 Returns an iterator over the models.
700 """
701 return self.__models
702
703 def __getitem__(self,i):
704 """
705 Returns the i-th model.
706 """
707 return self.__models[i]
708
709 def __setitem__(self,i,value):
710 """
711 Sets the i-th model.
712 """
713 if not isinstance(value,Model):
714 raise ValueError("assigned value is not a Model")
715 for j in range(max(i-len(self.__models)+1,0)):
716 self.__models.append(None)
717 self.__models[i]=value
718
719 def __len__(self):
720 """
721 Returns the number of models.
722 """
723 return len(self.__models)
724
725 def toDom(self, document, node):
726 """
727 C{toDom} method of Simulation class.
728 """
729 simulation = document.createElement('Simulation')
730 simulation.setAttribute('type', self.__class__.__name__)
731
732 for rank, sim in enumerate(self.iterModels()):
733 component = document.createElement('Component')
734 component.setAttribute('rank', str(rank))
735
736 sim.toDom(document, component)
737
738 simulation.appendChild(component)
739
740 node.appendChild(simulation)
741
742 def writeXML(self,ostream=stdout):
743 """
744 Writes the object as an XML object into an output stream.
745 """
746 document, rootnode = esysDoc()
747 self.toDom(document, rootnode)
748 targetsList = document.getElementsByTagName('Target')
749 for i in targetsList:
750 targetId = int(i.firstChild.nodeValue.strip())
751 targetObj = LinkableObjectRegistry[targetId]
752 targetObj.toDom(document, rootnode)
753 ostream.write(document.toprettyxml())
754
755 def getSafeTimeStepSize(self,dt):
756 """
757 Returns a time step size which can safely be used by all models.
758
759 This is the minimum over the time step sizes of all models.
760 """
761 out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])
762 #print "%s: safe step size is %e."%(str(self),out)
763 return out
764
765 def doInitialization(self):
766 """
767 Initializes all models.
768 """
769 self.n=0
770 self.tn=0.
771 for o in self.iterModels():
772 o.doInitialization()
773
774 def finalize(self):
775 """
776 Returns True if any of the models is to be finalized.
777 """
778 return any([o.finalize() for o in self.iterModels()])
779
780 def doFinalization(self):
781 """
782 Finalalizes the time stepping for all models.
783 """
784 for i in self.iterModels(): i.doFinalization()
785 self.trace("end of time integation.")
786
787 def doStepPreprocessing(self,dt):
788 """
789 Initializes the time step for all models.
790 """
791 for o in self.iterModels():
792 o.doStepPreprocessing(dt)
793
794 def terminateIteration(self):
795 """
796 Returns True if all iterations for all models are terminated.
797 """
798 out=all([o.terminateIteration() for o in self.iterModels()])
799 return out
800
801 def doStepPostprocessing(self,dt):
802 """
803 Finalalizes the iteration process for all models.
804 """
805 for o in self.iterModels():
806 o.doStepPostprocessing(dt)
807 self.n+=1
808 self.tn+=dt
809
810 def doStep(self,dt):
811 """
812 Executes the iteration step at a time step for all model::
813
814 self.doStepPreprocessing(dt)
815 while not self.terminateIteration():
816 for all models:
817 self.doStep(dt)
818 self.doStepPostprocessing(dt)
819 """
820 self.iter=0
821 while not self.terminateIteration():
822 if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.n+1,self.tn+dt))
823 self.iter+=1
824 self.trace("iteration step %d"%(self.iter))
825 for o in self.iterModels():
826 o.doStep(dt)
827 if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.n+1,self.tn+dt))
828
829 def run(self,check_point=None):
830 """
831 Run the simulation by performing essentially::
832
833 self.doInitialization()
834 while not self.finalize():
835 dt=self.getSafeTimeStepSize()
836 self.doStep(dt)
837 if n%check_point==0:
838 self.writeXML()
839 self.doFinalization()
840
841 If one of the models in throws a C{FailedTimeStepError} exception a
842 new time step size is computed through getSafeTimeStepSize() and the
843 time step is repeated.
844
845 If one of the models in throws a C{IterationDivergenceError}
846 exception the time step size is halved and the time step is repeated.
847
848 In both cases the time integration is given up after
849 C{Simulation.FAILED_TIME_STEPS_MAX} attempts.
850 """
851 dt=self.UNDEF_DT
852 self.doInitialization()
853 while not self.finalize():
854 step_fail_counter=0
855 iteration_fail_counter=0
856 dt_new=self.getSafeTimeStepSize(dt)
857 self.trace("%d. time step %e (step size %e.)" % (self.n+1,self.tn+dt_new,dt_new))
858 end_of_step=False
859 while not end_of_step:
860 end_of_step=True
861 if not dt_new>0:
862 raise NonPositiveStepSizeError("non-positive step size in step %d",self.n+1)
863 try:
864 self.doStepPreprocessing(dt_new)
865 self.doStep(dt_new)
866 self.doStepPostprocessing(dt_new)
867 except IterationDivergenceError:
868 dt_new*=0.5
869 end_of_step=False
870 iteration_fail_counter+=1
871 if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:
872 raise SimulationBreakDownError("reduction of time step to achieve convergence failed.")
873 self.trace("iteration fails. time step is repeated with new step size.")
874 except FailedTimeStepError:
875 dt_new=self.getSafeTimeStepSize(dt)
876 end_of_step=False
877 step_fail_counter+=1
878 self.trace("time step is repeated.")
879 if step_fail_counter>self.FAILED_TIME_STEPS_MAX:
880 raise SimulationBreakDownError("time integration is given up after %d attempts."%step_fail_counter)
881 dt=dt_new
882 if not check_point==None:
883 if n%check_point==0:
884 self.trace("check point is created.")
885 self.writeXML()
886 self.doFinalization()
887
888 def fromDom(cls, doc):
889 sims = []
890 for node in doc.childNodes:
891 if isinstance(node, minidom.Text):
892 continue
893
894 sims.append(getComponent(node))
895
896 return cls(sims)
897
898 fromDom = classmethod(fromDom)
899
900
901 class IterationDivergenceError(Exception):
902 """
903 Exception which is thrown if there is no convergence of the iteration
904 process at a time step.
905
906 But there is a chance that a smaller step could help to reach convergence.
907 """
908 pass
909
910 class FailedTimeStepError(Exception):
911 """
912 Exception which is thrown if the time step fails because of a step
913 size that have been choosen to be too large.
914 """
915 pass
916
917 class SimulationBreakDownError(Exception):
918 """
919 Exception which is thrown if the simulation does not manage to
920 progress in time.
921 """
922 pass
923
924 class NonPositiveStepSizeError(Exception):
925 """
926 Exception which is thrown if the step size is not positive.
927 """
928 pass
929
930 # vim: expandtab shiftwidth=4:

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26