/[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 269 - (show annotations)
Wed Nov 30 01:59:55 2005 UTC (13 years, 11 months ago) by elspeth
File MIME type: text/x-python
File size: 28509 byte(s)
Fixed typos and import problems

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 print "The model we got up to: ", i
683 self[i] = models[i]
684
685
686 def __repr__(self):
687 """
688 Returns a string representation of the Simulation.
689 """
690 return "<Simulation %r>" % self.__models
691
692 def __str__(self):
693 """
694 Returning Simulation as a string.
695 """
696 return "<Simulation %d>"%id(self)
697
698 def iterModels(self):
699 """
700 Returns an iterator over the models.
701 """
702 return self.__models
703
704 def __getitem__(self,i):
705 """
706 Returns the i-th model.
707 """
708 return self.__models[i]
709
710 def __setitem__(self,i,value):
711 """
712 Sets the i-th model.
713 """
714 if not isinstance(value,Model):
715 raise ValueError("assigned value is not a Model, Model was:", i, " an instance of: ", value.__class__.__name__)
716 for j in range(max(i-len(self.__models)+1,0)):
717 self.__models.append(None)
718 self.__models[i]=value
719
720 def __len__(self):
721 """
722 Returns the number of models.
723 """
724 return len(self.__models)
725
726 def toDom(self, document, node):
727 """
728 C{toDom} method of Simulation class.
729 """
730 simulation = document.createElement('Simulation')
731 simulation.setAttribute('type', self.__class__.__name__)
732
733 for rank, sim in enumerate(self.iterModels()):
734 component = document.createElement('Component')
735 component.setAttribute('rank', str(rank))
736
737 sim.toDom(document, component)
738
739 simulation.appendChild(component)
740
741 node.appendChild(simulation)
742
743 def writeXML(self,ostream=stdout):
744 """
745 Writes the object as an XML object into an output stream.
746 """
747 document, rootnode = esysDoc()
748 self.toDom(document, rootnode)
749 targetsList = document.getElementsByTagName('Target')
750 for i in targetsList:
751 targetId = int(i.firstChild.nodeValue.strip())
752 targetObj = LinkableObjectRegistry[targetId]
753 targetObj.toDom(document, rootnode)
754 ostream.write(document.toprettyxml())
755
756 def getSafeTimeStepSize(self,dt):
757 """
758 Returns a time step size which can safely be used by all models.
759
760 This is the minimum over the time step sizes of all models.
761 """
762 out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])
763 #print "%s: safe step size is %e."%(str(self),out)
764 return out
765
766 def doInitialization(self):
767 """
768 Initializes all models.
769 """
770 self.n=0
771 self.tn=0.
772 for o in self.iterModels():
773 o.doInitialization()
774
775 def finalize(self):
776 """
777 Returns True if any of the models is to be finalized.
778 """
779 return any([o.finalize() for o in self.iterModels()])
780
781 def doFinalization(self):
782 """
783 Finalalizes the time stepping for all models.
784 """
785 for i in self.iterModels(): i.doFinalization()
786 self.trace("end of time integation.")
787
788 def doStepPreprocessing(self,dt):
789 """
790 Initializes the time step for all models.
791 """
792 for o in self.iterModels():
793 o.doStepPreprocessing(dt)
794
795 def terminateIteration(self):
796 """
797 Returns True if all iterations for all models are terminated.
798 """
799 out=all([o.terminateIteration() for o in self.iterModels()])
800 return out
801
802 def doStepPostprocessing(self,dt):
803 """
804 Finalalizes the iteration process for all models.
805 """
806 for o in self.iterModels():
807 o.doStepPostprocessing(dt)
808 self.n+=1
809 self.tn+=dt
810
811 def doStep(self,dt):
812 """
813 Executes the iteration step at a time step for all model::
814
815 self.doStepPreprocessing(dt)
816 while not self.terminateIteration():
817 for all models:
818 self.doStep(dt)
819 self.doStepPostprocessing(dt)
820 """
821 self.iter=0
822 while not self.terminateIteration():
823 if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.n+1,self.tn+dt))
824 self.iter+=1
825 self.trace("iteration step %d"%(self.iter))
826 for o in self.iterModels():
827 o.doStep(dt)
828 if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.n+1,self.tn+dt))
829
830 def run(self,check_point=None):
831 """
832 Run the simulation by performing essentially::
833
834 self.doInitialization()
835 while not self.finalize():
836 dt=self.getSafeTimeStepSize()
837 self.doStep(dt)
838 if n%check_point==0:
839 self.writeXML()
840 self.doFinalization()
841
842 If one of the models in throws a C{FailedTimeStepError} exception a
843 new time step size is computed through getSafeTimeStepSize() and the
844 time step is repeated.
845
846 If one of the models in throws a C{IterationDivergenceError}
847 exception the time step size is halved and the time step is repeated.
848
849 In both cases the time integration is given up after
850 C{Simulation.FAILED_TIME_STEPS_MAX} attempts.
851 """
852 dt=self.UNDEF_DT
853 self.doInitialization()
854 while not self.finalize():
855 step_fail_counter=0
856 iteration_fail_counter=0
857 dt_new=self.getSafeTimeStepSize(dt)
858 self.trace("%d. time step %e (step size %e.)" % (self.n+1,self.tn+dt_new,dt_new))
859 end_of_step=False
860 while not end_of_step:
861 end_of_step=True
862 if not dt_new>0:
863 raise NonPositiveStepSizeError("non-positive step size in step %d",self.n+1)
864 try:
865 self.doStepPreprocessing(dt_new)
866 self.doStep(dt_new)
867 self.doStepPostprocessing(dt_new)
868 except IterationDivergenceError:
869 dt_new*=0.5
870 end_of_step=False
871 iteration_fail_counter+=1
872 if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:
873 raise SimulationBreakDownError("reduction of time step to achieve convergence failed.")
874 self.trace("iteration fails. time step is repeated with new step size.")
875 except FailedTimeStepError:
876 dt_new=self.getSafeTimeStepSize(dt)
877 end_of_step=False
878 step_fail_counter+=1
879 self.trace("time step is repeated.")
880 if step_fail_counter>self.FAILED_TIME_STEPS_MAX:
881 raise SimulationBreakDownError("time integration is given up after %d attempts."%step_fail_counter)
882 dt=dt_new
883 if not check_point==None:
884 if n%check_point==0:
885 self.trace("check point is created.")
886 self.writeXML()
887 self.doFinalization()
888
889 def fromDom(cls, doc):
890 sims = []
891 for node in doc.childNodes:
892 if isinstance(node, minidom.Text):
893 continue
894
895 sims.append(getComponent(node))
896
897 return cls(sims)
898
899 fromDom = classmethod(fromDom)
900
901
902 class IterationDivergenceError(Exception):
903 """
904 Exception which is thrown if there is no convergence of the iteration
905 process at a time step.
906
907 But there is a chance that a smaller step could help to reach convergence.
908 """
909 pass
910
911 class FailedTimeStepError(Exception):
912 """
913 Exception which is thrown if the time step fails because of a step
914 size that have been choosen to be too large.
915 """
916 pass
917
918 class SimulationBreakDownError(Exception):
919 """
920 Exception which is thrown if the simulation does not manage to
921 progress in time.
922 """
923 pass
924
925 class NonPositiveStepSizeError(Exception):
926 """
927 Exception which is thrown if the step size is not positive.
928 """
929 pass
930
931 # 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