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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 149 - (hide annotations)
Thu Sep 1 03:31:39 2005 UTC (14 years, 2 months ago) by jgs
Original Path: trunk/esys2/escript/py_src/modelframe.py
File MIME type: text/x-python
File size: 27332 byte(s)
Merge of development branch dev-02 back to main trunk on 2005-09-01

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