/[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 282 - (show annotations)
Wed Nov 30 09:18:38 2005 UTC (13 years, 11 months ago) by elspeth
File MIME type: text/x-python
File size: 28595 byte(s)
Fixed XML duplication in output bug.

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 node.setIdAttribute("id")
449 for name,value in self:
450 param = document.createElement('Parameter')
451 param.setAttribute('type', value.__class__.__name__)
452
453 param.appendChild(dataNode(document, 'Name', name))
454
455 val = document.createElement('Value')
456
457 if isinstance(value,ParameterSet):
458 value.toDom(document, val)
459 param.appendChild(val)
460 elif isinstance(value, Link):
461 value.toDom(document, val)
462 param.appendChild(val)
463 elif isinstance(value,StringType):
464 param.appendChild(dataNode(document, 'Value', value))
465 else:
466 param.appendChild(dataNode(document, 'Value', str(value)))
467
468 node.appendChild(param)
469
470 def fromDom(cls, doc):
471
472 # Define a host of helper functions to assist us.
473 def _children(node):
474 """
475 Remove the empty nodes from the children of this node.
476 """
477 return [x for x in node.childNodes
478 if not isinstance(x, minidom.Text) or x.nodeValue.strip()]
479
480 def _floatfromValue(doc):
481 return float(doc.nodeValue.strip())
482
483 def _stringfromValue(doc):
484 return str(doc.nodeValue.strip())
485
486 def _intfromValue(doc):
487 return int(doc.nodeValue.strip())
488
489 def _boolfromValue(doc):
490 return bool(doc.nodeValue.strip())
491
492 def _nonefromValue(doc):
493 return None
494
495 # Mapping from text types in the xml to methods used to process trees of that type
496 ptypemap = {"Simulation": Simulation.fromDom,
497 "Model":Model.fromDom,
498 "ParameterSet":ParameterSet.fromDom,
499 "Link":Link.fromDom,
500 "float":_floatfromValue,
501 "int":_intfromValue,
502 "str":_stringfromValue,
503 "bool":_boolfromValue,
504 "NoneType":_nonefromValue
505 }
506
507 # print doc.toxml()
508
509 parameters = {}
510 for node in _children(doc):
511 ptype = node.getAttribute("type")
512
513 pname = pvalue = None
514 for childnode in _children(node):
515
516 if childnode.tagName == "Name":
517 pname = childnode.firstChild.nodeValue.strip()
518
519 if childnode.tagName == "Value":
520 nodes = _children(childnode)
521 pvalue = ptypemap[ptype](nodes[0])
522
523 parameters[pname] = pvalue
524
525 # Create the instance of ParameterSet
526 o = cls()
527 o.declareParameters(parameters)
528 registerLinkableObject(doc.getAttribute("id"), o)
529 return o
530
531 fromDom = classmethod(fromDom)
532
533 def writeXML(self,ostream=stdout):
534 """
535 Writes the object as an XML object into an output stream.
536 """
537 # ParameterSet(d) with d[Name]=Value
538 document, node = esysDoc()
539 self.toDom(document, node)
540 ostream.write(document.toprettyxml())
541
542 class Model(ParameterSet):
543 """
544 A Model object represents a processess marching over time until a
545 finalizing condition is fullfilled. At each time step an iterative
546 process can be performed and the time step size can be controlled. A
547 Model has the following work flow::
548
549 doInitialization()
550 while not finalize():
551 dt=getSafeTimeStepSize(dt)
552 doStepPreprocessing(dt)
553 while not terminateIteration(): doStep(dt)
554 doStepPostprocessing(dt)
555 doFinalization()
556
557 where C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
558 C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
559 C{doFinalization} are methods of the particular instance of a Model. The
560 default implementations of these methods have to be overwritten by the
561 subclass implementing a Model.
562 """
563
564 UNDEF_DT=1.e300
565
566 def __init__(self,parameters=[],**kwarg):
567 """
568 Creates a model.
569
570 Just calls the parent constructor.
571 """
572 ParameterSet.__init__(self, parameters=parameters,**kwarg)
573
574 def __str__(self):
575 return "<%s %d>"%(self.__class__,id(self))
576
577 def toDom(self, document, node):
578 """
579 C{toDom} method of Model class
580 """
581 pset = document.createElement('Model')
582 pset.setAttribute('type', self.__class__.__name__)
583 if not self.__class__.__module__.startswith('esys.escript'):
584 pset.setAttribute('module', self.__class__.__module__)
585 node.appendChild(pset)
586 self._parametersToDom(document, pset)
587
588 def doInitialization(self):
589 """
590 Initializes the time stepping scheme.
591
592 This function may be overwritten.
593 """
594 pass
595
596 def getSafeTimeStepSize(self,dt):
597 """
598 Returns a time step size which can safely be used.
599
600 C{dt} gives the previously used step size.
601
602 This function may be overwritten.
603 """
604 return self.UNDEF_DT
605
606 def finalize(self):
607 """
608 Returns False if the time stepping is finalized.
609
610 This function may be overwritten.
611 """
612 return False
613
614 def doFinalization(self):
615 """
616 Finalizes the time stepping.
617
618 This function may be overwritten.
619 """
620 pass
621
622 def doStepPreprocessing(self,dt):
623 """
624 Sets up a time step of step size dt.
625
626 This function may be overwritten.
627 """
628 pass
629
630 def doStep(self,dt):
631 """
632 Executes an iteration step at a time step.
633
634 C{dt} is the currently used time step size.
635
636 This function may be overwritten.
637 """
638 pass
639
640 def terminateIteration(self):
641 """
642 Returns True if iteration on a time step is terminated.
643 """
644 return True
645
646 def doStepPostprocessing(self,dt):
647 """
648 Finalalizes the time step.
649
650 dt is the currently used time step size.
651
652 This function may be overwritten.
653 """
654 pass
655
656 def writeXML(self, ostream=stdout):
657 document, node = esysDoc()
658 self.toDom(document, node)
659 ostream.write(document.toprettyxml())
660
661
662 class Simulation(Model):
663 """
664 A Simulation object is special Model which runs a sequence of Models.
665
666 The methods C{doInitialization}, C{finalize}, C{getSafeTimeStepSize},
667 C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing},
668 C{doFinalization} are executing the corresponding methods of the models in
669 the simulation.
670 """
671
672 FAILED_TIME_STEPS_MAX=20
673 MAX_ITER_STEPS=50
674
675 def __init__(self, models=[], **kwargs):
676 """
677 Initiates a simulation from a list of models.
678 """
679 Model.__init__(self, **kwargs)
680 self.__models=[]
681
682 for i in range(len(models)):
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
751 for element in targetsList:
752 targetId = int(element.firstChild.nodeValue.strip())
753 if document.getElementById(str(targetId)):
754 continue
755 targetObj = LinkableObjectRegistry[targetId]
756 targetObj.toDom(document, rootnode)
757 ostream.write(document.toprettyxml())
758
759 def getSafeTimeStepSize(self,dt):
760 """
761 Returns a time step size which can safely be used by all models.
762
763 This is the minimum over the time step sizes of all models.
764 """
765 out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()])
766 #print "%s: safe step size is %e."%(str(self),out)
767 return out
768
769 def doInitialization(self):
770 """
771 Initializes all models.
772 """
773 self.n=0
774 self.tn=0.
775 for o in self.iterModels():
776 o.doInitialization()
777
778 def finalize(self):
779 """
780 Returns True if any of the models is to be finalized.
781 """
782 return any([o.finalize() for o in self.iterModels()])
783
784 def doFinalization(self):
785 """
786 Finalalizes the time stepping for all models.
787 """
788 for i in self.iterModels(): i.doFinalization()
789 self.trace("end of time integation.")
790
791 def doStepPreprocessing(self,dt):
792 """
793 Initializes the time step for all models.
794 """
795 for o in self.iterModels():
796 o.doStepPreprocessing(dt)
797
798 def terminateIteration(self):
799 """
800 Returns True if all iterations for all models are terminated.
801 """
802 out=all([o.terminateIteration() for o in self.iterModels()])
803 return out
804
805 def doStepPostprocessing(self,dt):
806 """
807 Finalalizes the iteration process for all models.
808 """
809 for o in self.iterModels():
810 o.doStepPostprocessing(dt)
811 self.n+=1
812 self.tn+=dt
813
814 def doStep(self,dt):
815 """
816 Executes the iteration step at a time step for all model::
817
818 self.doStepPreprocessing(dt)
819 while not self.terminateIteration():
820 for all models:
821 self.doStep(dt)
822 self.doStepPostprocessing(dt)
823 """
824 self.iter=0
825 while not self.terminateIteration():
826 if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.n+1,self.tn+dt))
827 self.iter+=1
828 self.trace("iteration step %d"%(self.iter))
829 for o in self.iterModels():
830 o.doStep(dt)
831 if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.n+1,self.tn+dt))
832
833 def run(self,check_point=None):
834 """
835 Run the simulation by performing essentially::
836
837 self.doInitialization()
838 while not self.finalize():
839 dt=self.getSafeTimeStepSize()
840 self.doStep(dt)
841 if n%check_point==0:
842 self.writeXML()
843 self.doFinalization()
844
845 If one of the models in throws a C{FailedTimeStepError} exception a
846 new time step size is computed through getSafeTimeStepSize() and the
847 time step is repeated.
848
849 If one of the models in throws a C{IterationDivergenceError}
850 exception the time step size is halved and the time step is repeated.
851
852 In both cases the time integration is given up after
853 C{Simulation.FAILED_TIME_STEPS_MAX} attempts.
854 """
855 dt=self.UNDEF_DT
856 self.doInitialization()
857 while not self.finalize():
858 step_fail_counter=0
859 iteration_fail_counter=0
860 dt_new=self.getSafeTimeStepSize(dt)
861 self.trace("%d. time step %e (step size %e.)" % (self.n+1,self.tn+dt_new,dt_new))
862 end_of_step=False
863 while not end_of_step:
864 end_of_step=True
865 if not dt_new>0:
866 raise NonPositiveStepSizeError("non-positive step size in step %d",self.n+1)
867 try:
868 self.doStepPreprocessing(dt_new)
869 self.doStep(dt_new)
870 self.doStepPostprocessing(dt_new)
871 except IterationDivergenceError:
872 dt_new*=0.5
873 end_of_step=False
874 iteration_fail_counter+=1
875 if iteration_fail_counter>self.FAILED_TIME_STEPS_MAX:
876 raise SimulationBreakDownError("reduction of time step to achieve convergence failed.")
877 self.trace("iteration fails. time step is repeated with new step size.")
878 except FailedTimeStepError:
879 dt_new=self.getSafeTimeStepSize(dt)
880 end_of_step=False
881 step_fail_counter+=1
882 self.trace("time step is repeated.")
883 if step_fail_counter>self.FAILED_TIME_STEPS_MAX:
884 raise SimulationBreakDownError("time integration is given up after %d attempts."%step_fail_counter)
885 dt=dt_new
886 if not check_point==None:
887 if n%check_point==0:
888 self.trace("check point is created.")
889 self.writeXML()
890 self.doFinalization()
891
892 def fromDom(cls, doc):
893 sims = []
894 for node in doc.childNodes:
895 if isinstance(node, minidom.Text):
896 continue
897
898 sims.append(getComponent(node))
899
900 return cls(sims)
901
902 fromDom = classmethod(fromDom)
903
904
905 class IterationDivergenceError(Exception):
906 """
907 Exception which is thrown if there is no convergence of the iteration
908 process at a time step.
909
910 But there is a chance that a smaller step could help to reach convergence.
911 """
912 pass
913
914 class FailedTimeStepError(Exception):
915 """
916 Exception which is thrown if the time step fails because of a step
917 size that have been choosen to be too large.
918 """
919 pass
920
921 class SimulationBreakDownError(Exception):
922 """
923 Exception which is thrown if the simulation does not manage to
924 progress in time.
925 """
926 pass
927
928 class NonPositiveStepSizeError(Exception):
929 """
930 Exception which is thrown if the step size is not positive.
931 """
932 pass
933
934 # 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