15 |
|
|
16 |
def dataNode(document, tagName, data): |
def dataNode(document, tagName, data): |
17 |
""" |
""" |
18 |
dataNodes are the building blocks of the xml documents constructed in |
C{dataNode}s are the building blocks of the xml documents constructed in |
19 |
this module. document is the current xml document, tagName is the |
this module. |
20 |
associated xml tag, and data is the values in the tag. |
|
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)) |
t = document.createTextNode(str(data)) |
26 |
n = document.createElement(tagName) |
n = document.createElement(tagName) |
60 |
|
|
61 |
def parse(xml): |
def parse(xml): |
62 |
""" |
""" |
63 |
Generic parse method for EsysXML. Without this, Links don't work. |
Generic parse method for EsysXML. Without this, Links don't work. |
64 |
""" |
""" |
65 |
global LinkRegistry, LinkableObjectRegistry |
global LinkRegistry, LinkableObjectRegistry |
66 |
LinkRegistry = [] |
LinkRegistry = [] |
73 |
|
|
74 |
return sim |
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): |
def getComponent(doc): |
92 |
""" |
""" |
93 |
Used to get components of Simualtions, Models. |
Used to get components of Simualtions, Models. |
99 |
if node.getAttribute("type") == 'Simulation': |
if node.getAttribute("type") == 'Simulation': |
100 |
return Simulation.fromDom(node) |
return Simulation.fromDom(node) |
101 |
if node.tagName == 'Model': |
if node.tagName == 'Model': |
102 |
model_type = node.getAttribute("type") |
if (node.getAttribute("module")): |
103 |
model_subclasses = Model.__subclasses__() |
model_module = node.getAttribute("module") |
104 |
for model in model_subclasses: |
model_type = node.getAttribute("type") |
105 |
if model_type == model.__name__: |
return importName(model_module, model_type).fromDom(node) |
106 |
return Model.fromDom(node) |
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': |
if node.tagName == 'ParameterSet': |
113 |
parameter_type = node.getAttribute("type") |
parameter_type = node.getAttribute("type") |
114 |
return ParameterSet.fromDom(node) |
return ParameterSet.fromDom(node) |
120 |
|
|
121 |
class Link: |
class Link: |
122 |
""" |
""" |
123 |
a Link makes an attribute of an object callable: |
A Link makes an attribute of an object callable:: |
124 |
|
|
125 |
o.object() |
o.object() |
126 |
o.a=8 |
o.a=8 |
127 |
l=Link(o,"a") |
l=Link(o,"a") |
130 |
|
|
131 |
def __init__(self,target,attribute=None): |
def __init__(self,target,attribute=None): |
132 |
""" |
""" |
133 |
creates a link to the object target. If attribute is given, the link is |
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 |
establised to this attribute of the target. Otherwise the attribute is |
135 |
undefined. |
undefined. |
136 |
""" |
""" |
140 |
|
|
141 |
def setAttributeName(self,attribute): |
def setAttributeName(self,attribute): |
142 |
""" |
""" |
143 |
set a new attribute name to be collected from the target object. The |
Set a new attribute name to be collected from the target object. The |
144 |
target object must have the attribute with name attribute. |
target object must have the attribute with name attribute. |
145 |
""" |
""" |
146 |
if attribute and self.target: |
if attribute and self.target: |
154 |
|
|
155 |
def hasDefinedAttributeName(self): |
def hasDefinedAttributeName(self): |
156 |
""" |
""" |
157 |
returns true if an attribute name is set |
Returns true if an attribute name is set. |
158 |
""" |
""" |
159 |
return self.attribute != None |
return self.attribute != None |
160 |
|
|
161 |
def __repr__(self): |
def __repr__(self): |
162 |
""" |
""" |
163 |
returns a string representation of the link |
Returns a string representation of the link. |
164 |
""" |
""" |
165 |
if self.hasDefinedAttributeName(): |
if self.hasDefinedAttributeName(): |
166 |
return "<Link to attribute %s of %s>" % (self.attribute, self.target) |
return "<Link to attribute %s of %s>" % (self.attribute, self.target) |
169 |
|
|
170 |
def __call__(self,name=None): |
def __call__(self,name=None): |
171 |
""" |
""" |
172 |
returns the value of the attribute of the target object. If the |
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. |
atrribute is callable then the return value of the call is returned. |
174 |
""" |
""" |
175 |
if name: |
if name: |
184 |
|
|
185 |
def toDom(self, document, node): |
def toDom(self, document, node): |
186 |
""" |
""" |
187 |
toDom method of Link. Creates a Link node and appends it to the current XML |
C{toDom} method of Link. Creates a Link node and appends it to the |
188 |
document |
current XML document. |
189 |
""" |
""" |
190 |
link = document.createElement('Link') |
link = document.createElement('Link') |
191 |
assert (self.target != None), ("Target was none, name was %r" % self.attribute) |
assert (self.target != None), ("Target was none, name was %r" % self.attribute) |
207 |
|
|
208 |
def writeXML(self,ostream=stdout): |
def writeXML(self,ostream=stdout): |
209 |
""" |
""" |
210 |
writes an XML representation of self to the output stream ostream. |
Writes an XML representation of self to the output stream ostream. |
211 |
If ostream is nor present the standart output stream is used. If |
If ostream is nor present the standart output stream is used. If |
212 |
esysheader==True the esys XML header is written |
esysheader==True the esys XML header is written |
213 |
""" |
""" |
220 |
class LinkableObject(object): |
class LinkableObject(object): |
221 |
""" |
""" |
222 |
An object that allows to link its attributes to attributes of other objects |
An object that allows to link its attributes to attributes of other objects |
223 |
via a Link object. For instance |
via a Link object. For instance:: |
224 |
|
|
225 |
p = LinkableObject() |
p = LinkableObject() |
226 |
p.x = Link(o,"name") |
p.x = Link(o,"name") |
227 |
print p.x |
print p.x |
228 |
|
|
229 |
links attribute x of p to the attribute name of object o. |
links attribute C{x} of C{p} to the attribute name of object C{o}. |
230 |
|
|
231 |
p.x will contain the current value of attribute name of object o. |
C{p.x} will contain the current value of attribute C{name} of object |
232 |
|
C{o}. |
233 |
|
|
234 |
If the value of getattr(o, "name") is callable, p.x will rturn the return |
If the value of C{getattr(o, "name")} is callable, C{p.x} will return |
235 |
value of the call. |
the return value of the call. |
236 |
""" |
""" |
237 |
|
|
238 |
number_sequence = itertools.count(100) |
number_sequence = itertools.count(100) |
239 |
|
|
240 |
def __init__(self, debug=False): |
def __init__(self, debug=False): |
241 |
""" initializes LinkableObject so that we can operate on Links """ |
""" |
242 |
|
Initializes LinkableObject so that we can operate on Links |
243 |
|
""" |
244 |
self.debug = debug |
self.debug = debug |
245 |
self.__linked_attributes={} |
self.__linked_attributes={} |
246 |
self.id = self.number_sequence.next() |
self.id = self.number_sequence.next() |
247 |
|
registerLinkableObject(self.id, self) |
248 |
|
|
249 |
def trace(self, msg): |
def trace(self, msg): |
250 |
""" If debugging is on, print the message, otherwise do nothing |
""" |
251 |
|
If debugging is on, print the message, otherwise do nothing |
252 |
""" |
""" |
253 |
if self.debug: |
if self.debug: |
254 |
print "%s: %s"%(str(self),msg) |
print "%s: %s"%(str(self),msg) |
255 |
|
|
256 |
def __getattr__(self,name): |
def __getattr__(self,name): |
257 |
"""returns the value of attribute name. If the value is a Link object the |
""" |
258 |
object is called and the return value is returned.""" |
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) |
out = self.getAttributeObject(name) |
262 |
if isinstance(out,Link): |
if isinstance(out,Link): |
263 |
return out() |
return out() |
265 |
return out |
return out |
266 |
|
|
267 |
def getAttributeObject(self,name): |
def getAttributeObject(self,name): |
268 |
"""return the object stored for attribute name.""" |
""" |
269 |
|
Return the object stored for attribute name. |
270 |
|
""" |
271 |
|
|
272 |
if self.__dict__.has_key(name): |
if self.__dict__.has_key(name): |
273 |
return self.__dict__[name] |
return self.__dict__[name] |
281 |
raise AttributeError,"No attribute %s."%name |
raise AttributeError,"No attribute %s."%name |
282 |
|
|
283 |
def hasAttribute(self,name): |
def hasAttribute(self,name): |
284 |
"""returns True if self as attribute name""" |
""" |
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) |
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): |
def __setattr__(self,name,value): |
290 |
"""sets the value for attribute name. If value is a Link the target |
""" |
291 |
attribute is set to name if no attribute has been specified.""" |
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): |
if self.__dict__.has_key(name): |
296 |
del self.__dict__[name] |
del self.__dict__[name] |
305 |
self.__dict__[name] = value |
self.__dict__[name] = value |
306 |
|
|
307 |
def __delattr__(self,name): |
def __delattr__(self,name): |
308 |
"""removes the attribute name.""" |
""" |
309 |
|
Removes the attribute name. |
310 |
|
""" |
311 |
|
|
312 |
if self.__linked_attributes.has_key[name]: |
if self.__linked_attributes.has_key[name]: |
313 |
del self.__linked_attributes[name] |
del self.__linked_attributes[name] |
330 |
return self |
return self |
331 |
|
|
332 |
class ParameterSet(LinkableObject): |
class ParameterSet(LinkableObject): |
333 |
"""a class which allows to emphazise attributes to be written and read to XML |
""" |
334 |
|
A class which allows to emphazise attributes to be written and read to XML |
335 |
|
|
336 |
Leaves of an ESySParameters objects can be |
Leaves of an ESySParameters object can be: |
337 |
|
|
338 |
a real number |
- a real number |
339 |
a integer number |
- a integer number |
340 |
a string |
- a string |
341 |
a boolean value |
- a boolean value |
342 |
a ParameterSet object |
- a ParameterSet object |
343 |
a Simulation object |
- a Simulation object |
344 |
a Model object |
- a Model object |
345 |
any other object (not considered by writeESySXML and writeXML) |
- any other object (not considered by writeESySXML and writeXML) |
346 |
|
|
347 |
Example how to create an ESySParameters object: |
Example how to create an ESySParameters object:: |
348 |
|
|
349 |
p11=ParameterSet(gamma1=1.,gamma2=2.,gamma3=3.) |
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) |
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"))) |
parm=ParameterSet(parm1=p1,parm2=ParameterSet(alpha=Link(p11,"gamma1"))) |
352 |
|
|
353 |
This can be accessed as |
This can be accessed as:: |
354 |
|
|
355 |
parm.parm1.gamma=0. |
parm.parm1.gamma=0. |
356 |
parm.parm1.dim=2 |
parm.parm1.dim=2 |
357 |
parm.parm1.tol_v=0.001 |
parm.parm1.tol_v=0.001 |
358 |
parm.parm1.output_file="/tmp/u.%3.3d.dx" |
parm.parm1.output_file="/tmp/u.%3.3d.dx" |
359 |
parm.parm1.runFlag=True |
parm.parm1.runFlag=True |
360 |
parm.parm1.parm11.gamma1=1. |
parm.parm1.parm11.gamma1=1. |
361 |
parm.parm1.parm11.gamma2=2. |
parm.parm1.parm11.gamma2=2. |
362 |
parm.parm1.parm11.gamma3=3. |
parm.parm1.parm11.gamma3=3. |
363 |
parm.parm2.alpha=1. (value of parm.parm1.parm11.gamma1) |
parm.parm2.alpha=1. (value of parm.parm1.parm11.gamma1) |
|
|
|
364 |
""" |
""" |
365 |
def __init__(self, parameters=[], **kwargs): |
def __init__(self, parameters=[], **kwargs): |
366 |
"""creates a ParameterSet with parameters parameters""" |
""" |
367 |
|
Creates a ParameterSet with parameters parameters. |
368 |
|
""" |
369 |
LinkableObject.__init__(self, **kwargs) |
LinkableObject.__init__(self, **kwargs) |
370 |
self.parameters = set() |
self.parameters = set() |
371 |
self.declareParameters(parameters) |
self.declareParameters(parameters) |
375 |
[(p, getattr(self, p, None)) for p in self.parameters]) |
[(p, getattr(self, p, None)) for p in self.parameters]) |
376 |
|
|
377 |
def declareParameter(self,**parameters): |
def declareParameter(self,**parameters): |
378 |
"""declares a new parameter(s) and its (their) inital value.""" |
""" |
379 |
|
Declares a new parameter(s) and its (their) initial value. |
380 |
|
""" |
381 |
self.declareParameters(parameters) |
self.declareParameters(parameters) |
382 |
|
|
383 |
def declareParameters(self,parameters): |
def declareParameters(self,parameters): |
384 |
"""declares a set of parameters. parameters can be a list, a dictonary or a ParameterSet.""" |
""" |
385 |
|
Declares a set of parameters. parameters can be a list, a dictionary |
386 |
|
or a ParameterSet. |
387 |
|
""" |
388 |
if isinstance(parameters,ListType): |
if isinstance(parameters,ListType): |
389 |
parameters = zip(parameters, itertools.repeat(None)) |
parameters = zip(parameters, itertools.repeat(None)) |
390 |
if isinstance(parameters,DictType): |
if isinstance(parameters,DictType): |
397 |
self.trace("parameter %s has been declared."%prm) |
self.trace("parameter %s has been declared."%prm) |
398 |
|
|
399 |
def releaseParameters(self,name): |
def releaseParameters(self,name): |
400 |
"""removes parameter name from the paramameters""" |
""" |
401 |
|
Removes parameter name from the paramameters. |
402 |
|
""" |
403 |
if self.isParameter(name): |
if self.isParameter(name): |
404 |
self.parameters.remove(name) |
self.parameters.remove(name) |
405 |
self.trace("parameter %s has been removed."%name) |
self.trace("parameter %s has been removed."%name) |
406 |
|
|
407 |
def __iter__(self): |
def __iter__(self): |
408 |
"""creates an iterator over the parameter and their values""" |
""" |
409 |
|
Creates an iterator over the parameter and their values. |
410 |
|
""" |
411 |
return _ParameterIterator(self) |
return _ParameterIterator(self) |
412 |
|
|
413 |
def showParameters(self): |
def showParameters(self): |
414 |
"""returns a descrition of the parameters""" |
""" |
415 |
|
Returns a descrition of the parameters. |
416 |
|
""" |
417 |
out="{" |
out="{" |
418 |
notfirst=False |
notfirst=False |
419 |
for i,v in self: |
for i,v in self: |
426 |
return out+"}" |
return out+"}" |
427 |
|
|
428 |
def __delattr__(self,name): |
def __delattr__(self,name): |
429 |
"""removes the attribute name.""" |
""" |
430 |
|
Removes the attribute name. |
431 |
|
""" |
432 |
LinkableObject.__delattr__(self,name) |
LinkableObject.__delattr__(self,name) |
433 |
try: |
try: |
434 |
self.releaseParameter(name) |
self.releaseParameter(name) |
436 |
pass |
pass |
437 |
|
|
438 |
def toDom(self, document, node): |
def toDom(self, document, node): |
439 |
""" toDom method of ParameterSet class """ |
""" |
440 |
|
C{toDom} method of ParameterSet class. |
441 |
|
""" |
442 |
pset = document.createElement('ParameterSet') |
pset = document.createElement('ParameterSet') |
443 |
node.appendChild(pset) |
node.appendChild(pset) |
444 |
self._parametersToDom(document, pset) |
self._parametersToDom(document, pset) |
471 |
# Define a host of helper functions to assist us. |
# Define a host of helper functions to assist us. |
472 |
def _children(node): |
def _children(node): |
473 |
""" |
""" |
474 |
Remove the empty nodes from the children of this node |
Remove the empty nodes from the children of this node. |
475 |
""" |
""" |
476 |
return [x for x in node.childNodes |
return [x for x in node.childNodes |
477 |
if not isinstance(x, minidom.Text) or x.nodeValue.strip()] |
if not isinstance(x, minidom.Text) or x.nodeValue.strip()] |
526 |
fromDom = classmethod(fromDom) |
fromDom = classmethod(fromDom) |
527 |
|
|
528 |
def writeXML(self,ostream=stdout): |
def writeXML(self,ostream=stdout): |
529 |
"""writes the object as an XML object into an output stream""" |
""" |
530 |
|
Writes the object as an XML object into an output stream. |
531 |
|
""" |
532 |
# ParameterSet(d) with d[Name]=Value |
# ParameterSet(d) with d[Name]=Value |
533 |
document, node = esysDoc() |
document, node = esysDoc() |
534 |
self.toDom(document, node) |
self.toDom(document, node) |
536 |
|
|
537 |
class Model(ParameterSet): |
class Model(ParameterSet): |
538 |
""" |
""" |
539 |
|
A Model object represents a processess marching over time until a |
540 |
A Model object represents a processess marching over time |
finalizing condition is fullfilled. At each time step an iterative |
541 |
until a finalizing condition is fullfilled. At each time step an iterative |
process can be performed and the time step size can be controlled. A |
542 |
process can be performed and the time step size can be controlled. A Model has |
Model has the following work flow:: |
|
the following work flow: |
|
543 |
|
|
544 |
doInitialization() |
doInitialization() |
545 |
while not finalize(): |
while not finalize(): |
549 |
doStepPostprocessing(dt) |
doStepPostprocessing(dt) |
550 |
doFinalization() |
doFinalization() |
551 |
|
|
552 |
where doInitialization,finalize, getSafeTimeStepSize, doStepPreprocessing, terminateIteration, doStepPostprocessing, doFinalization |
where C{doInitialization}, C{finalize}, C{getSafeTimeStepSize}, |
553 |
are methods of the particular instance of a Model. The default implementations of these methods have to be overwritten by |
C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing}, |
554 |
the subclass implementinf a Model. |
C{doFinalization} are methods of the particular instance of a Model. The |
555 |
|
default implementations of these methods have to be overwritten by the |
556 |
|
subclass implementing a Model. |
557 |
""" |
""" |
558 |
|
|
559 |
UNDEF_DT=1.e300 |
UNDEF_DT=1.e300 |
560 |
|
|
561 |
def __init__(self,parameters=[],**kwarg): |
def __init__(self,parameters=[],**kwarg): |
562 |
"""creates a model |
""" |
563 |
|
Creates a model. |
564 |
|
|
565 |
Just calls the parent constructor. |
Just calls the parent constructor. |
566 |
""" |
""" |
567 |
ParameterSet.__init__(self, parameters=parameters,**kwarg) |
ParameterSet.__init__(self, parameters=parameters,**kwarg) |
568 |
|
|
570 |
return "<%s %d>"%(self.__class__,id(self)) |
return "<%s %d>"%(self.__class__,id(self)) |
571 |
|
|
572 |
def toDom(self, document, node): |
def toDom(self, document, node): |
573 |
""" toDom method of Model class """ |
""" |
574 |
|
C{toDom} method of Model class |
575 |
|
""" |
576 |
pset = document.createElement('Model') |
pset = document.createElement('Model') |
577 |
pset.setAttribute('type', self.__class__.__name__) |
pset.setAttribute('type', self.__class__.__name__) |
578 |
|
if not self.__class__.__module__.startswith('esys.escript'): |
579 |
|
pset.setAttribute('module', self.__class__.__module__) |
580 |
node.appendChild(pset) |
node.appendChild(pset) |
581 |
self._parametersToDom(document, pset) |
self._parametersToDom(document, pset) |
582 |
|
|
583 |
def doInitialization(self): |
def doInitialization(self): |
584 |
"""initializes the time stepping scheme. This function may be overwritten.""" |
""" |
585 |
|
Initializes the time stepping scheme. |
586 |
|
|
587 |
|
This function may be overwritten. |
588 |
|
""" |
589 |
pass |
pass |
590 |
|
|
591 |
def getSafeTimeStepSize(self,dt): |
def getSafeTimeStepSize(self,dt): |
592 |
"""returns a time step size which can safely be used. |
""" |
593 |
dt gives the previously used step size. |
Returns a time step size which can safely be used. |
594 |
This function may be overwritten.""" |
|
595 |
|
C{dt} gives the previously used step size. |
596 |
|
|
597 |
|
This function may be overwritten. |
598 |
|
""" |
599 |
return self.UNDEF_DT |
return self.UNDEF_DT |
600 |
|
|
601 |
def finalize(self): |
def finalize(self): |
602 |
"""returns False if the time stepping is finalized. This function may be |
""" |
603 |
overwritten.""" |
Returns False if the time stepping is finalized. |
604 |
|
|
605 |
|
This function may be overwritten. |
606 |
|
""" |
607 |
return False |
return False |
608 |
|
|
609 |
def doFinalization(self): |
def doFinalization(self): |
610 |
"""finalizes the time stepping. This function may be overwritten.""" |
""" |
611 |
|
Finalizes the time stepping. |
612 |
|
|
613 |
|
This function may be overwritten. |
614 |
|
""" |
615 |
pass |
pass |
616 |
|
|
617 |
def doStepPreprocessing(self,dt): |
def doStepPreprocessing(self,dt): |
618 |
"""sets up a time step of step size dt. This function may be overwritten.""" |
""" |
619 |
|
Sets up a time step of step size dt. |
620 |
|
|
621 |
|
This function may be overwritten. |
622 |
|
""" |
623 |
pass |
pass |
624 |
|
|
625 |
def doStep(self,dt): |
def doStep(self,dt): |
626 |
"""executes an iteration step at a time step. |
""" |
627 |
dt is the currently used time step size. |
Executes an iteration step at a time step. |
628 |
This function may be overwritten.""" |
|
629 |
|
C{dt} is the currently used time step size. |
630 |
|
|
631 |
|
This function may be overwritten. |
632 |
|
""" |
633 |
pass |
pass |
634 |
|
|
635 |
def terminateIteration(self): |
def terminateIteration(self): |
636 |
"""returns True if iteration on a time step is terminated.""" |
""" |
637 |
|
Returns True if iteration on a time step is terminated. |
638 |
|
""" |
639 |
return True |
return True |
640 |
|
|
641 |
def doStepPostprocessing(self,dt): |
def doStepPostprocessing(self,dt): |
642 |
"""finalalizes the time step. |
""" |
643 |
dt is the currently used time step size. |
Finalalizes the time step. |
644 |
This function may be overwritten.""" |
|
645 |
|
dt is the currently used time step size. |
646 |
|
|
647 |
|
This function may be overwritten. |
648 |
|
""" |
649 |
pass |
pass |
650 |
|
|
651 |
def writeXML(self, ostream=stdout): |
def writeXML(self, ostream=stdout): |
653 |
self.toDom(document, node) |
self.toDom(document, node) |
654 |
ostream.write(document.toprettyxml()) |
ostream.write(document.toprettyxml()) |
655 |
|
|
|
|
|
656 |
|
|
657 |
class Simulation(Model): |
class Simulation(Model): |
658 |
""" |
""" |
659 |
A Simulation object is special Model which runs a sequence of Models. |
A Simulation object is special Model which runs a sequence of Models. |
660 |
|
|
661 |
The methods doInitialization,finalize, getSafeTimeStepSize, doStepPreprocessing, |
The methods C{doInitialization}, C{finalize}, C{getSafeTimeStepSize}, |
662 |
terminateIteration, doStepPostprocessing, doFinalization |
C{doStepPreprocessing}, C{terminateIteration}, C{doStepPostprocessing}, |
663 |
are executing the corresponding methods of the models in the simulation. |
C{doFinalization} are executing the corresponding methods of the models in |
664 |
|
the simulation. |
665 |
""" |
""" |
666 |
|
|
667 |
FAILED_TIME_STEPS_MAX=20 |
FAILED_TIME_STEPS_MAX=20 |
668 |
MAX_ITER_STEPS=50 |
MAX_ITER_STEPS=50 |
669 |
|
|
670 |
def __init__(self, models=[], **kwargs): |
def __init__(self, models=[], **kwargs): |
671 |
"""initiates a simulation from a list of models. """ |
""" |
672 |
|
Initiates a simulation from a list of models. |
673 |
|
""" |
674 |
Model.__init__(self, **kwargs) |
Model.__init__(self, **kwargs) |
675 |
self.__models=[] |
self.__models=[] |
676 |
|
|
677 |
for i in range(len(models)): |
for i in range(len(models)): |
678 |
self[i] = models[i] |
self[i] = models[i] |
679 |
|
|
680 |
|
|
681 |
def __repr__(self): |
def __repr__(self): |
682 |
""" |
""" |
683 |
returns a string representation of the Simulation |
Returns a string representation of the Simulation. |
684 |
""" |
""" |
685 |
return "<Simulation %r>" % self.__models |
return "<Simulation %r>" % self.__models |
686 |
|
|
687 |
def __str__(self): |
def __str__(self): |
688 |
""" |
""" |
689 |
returning Simulation as a string |
Returning Simulation as a string. |
690 |
""" |
""" |
691 |
return "<Simulation %d>"%id(self) |
return "<Simulation %d>"%id(self) |
692 |
|
|
693 |
def iterModels(self): |
def iterModels(self): |
694 |
"""returns an iterator over the models""" |
""" |
695 |
|
Returns an iterator over the models. |
696 |
|
""" |
697 |
return self.__models |
return self.__models |
698 |
|
|
699 |
def __getitem__(self,i): |
def __getitem__(self,i): |
700 |
"""returns the i-th model""" |
""" |
701 |
|
Returns the i-th model. |
702 |
|
""" |
703 |
return self.__models[i] |
return self.__models[i] |
704 |
|
|
705 |
def __setitem__(self,i,value): |
def __setitem__(self,i,value): |
706 |
"""sets the i-th model""" |
""" |
707 |
|
Sets the i-th model. |
708 |
|
""" |
709 |
if not isinstance(value,Model): |
if not isinstance(value,Model): |
710 |
raise ValueError("assigned value is not a Model") |
raise ValueError("assigned value is not a Model") |
711 |
for j in range(max(i-len(self.__models)+1,0)): self.__models.append(None) |
for j in range(max(i-len(self.__models)+1,0)): |
712 |
|
self.__models.append(None) |
713 |
self.__models[i]=value |
self.__models[i]=value |
714 |
|
|
715 |
def __len__(self): |
def __len__(self): |
716 |
"""returns the number of models""" |
""" |
717 |
|
Returns the number of models. |
718 |
|
""" |
719 |
return len(self.__models) |
return len(self.__models) |
720 |
|
|
721 |
def toDom(self, document, node): |
def toDom(self, document, node): |
722 |
""" toDom method of Simulation class """ |
""" |
723 |
|
C{toDom} method of Simulation class. |
724 |
|
""" |
725 |
simulation = document.createElement('Simulation') |
simulation = document.createElement('Simulation') |
726 |
simulation.setAttribute('type', self.__class__.__name__) |
simulation.setAttribute('type', self.__class__.__name__) |
727 |
|
|
736 |
node.appendChild(simulation) |
node.appendChild(simulation) |
737 |
|
|
738 |
def writeXML(self,ostream=stdout): |
def writeXML(self,ostream=stdout): |
739 |
"""writes the object as an XML object into an output stream""" |
""" |
740 |
|
Writes the object as an XML object into an output stream. |
741 |
|
""" |
742 |
document, rootnode = esysDoc() |
document, rootnode = esysDoc() |
743 |
self.toDom(document, rootnode) |
self.toDom(document, rootnode) |
744 |
|
targetsList = document.getElementsByTagName('Target') |
745 |
|
for i in targetsList: |
746 |
|
targetId = int(i.firstChild.nodeValue.strip()) |
747 |
|
targetObj = LinkableObjectRegistry[targetId] |
748 |
|
targetObj.toDom(document, rootnode) |
749 |
ostream.write(document.toprettyxml()) |
ostream.write(document.toprettyxml()) |
750 |
|
|
751 |
def getSafeTimeStepSize(self,dt): |
def getSafeTimeStepSize(self,dt): |
752 |
"""returns a time step size which can safely be used by all models. |
""" |
753 |
This is the minimum over the time step sizes of all models.""" |
Returns a time step size which can safely be used by all models. |
754 |
|
|
755 |
|
This is the minimum over the time step sizes of all models. |
756 |
|
""" |
757 |
out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()]) |
out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()]) |
758 |
print "%s: safe step size is %e."%(str(self),out) |
#print "%s: safe step size is %e."%(str(self),out) |
759 |
return out |
return out |
760 |
|
|
761 |
def doInitialization(self): |
def doInitialization(self): |
762 |
"""initializes all models """ |
""" |
763 |
|
Initializes all models. |
764 |
|
""" |
765 |
self.n=0 |
self.n=0 |
766 |
self.tn=0. |
self.tn=0. |
767 |
for o in self.iterModels(): |
for o in self.iterModels(): |
768 |
o.doInitialization() |
o.doInitialization() |
769 |
|
|
770 |
def finalize(self): |
def finalize(self): |
771 |
"""returns True if any of the models is to be finalized""" |
""" |
772 |
|
Returns True if any of the models is to be finalized. |
773 |
|
""" |
774 |
return any([o.finalize() for o in self.iterModels()]) |
return any([o.finalize() for o in self.iterModels()]) |
775 |
|
|
776 |
def doFinalization(self): |
def doFinalization(self): |
777 |
"""finalalizes the time stepping for all models.""" |
""" |
778 |
|
Finalalizes the time stepping for all models. |
779 |
|
""" |
780 |
for i in self.iterModels(): i.doFinalization() |
for i in self.iterModels(): i.doFinalization() |
781 |
self.trace("end of time integation.") |
self.trace("end of time integation.") |
782 |
|
|
783 |
def doStepPreprocessing(self,dt): |
def doStepPreprocessing(self,dt): |
784 |
"""initializes the time step for all models.""" |
""" |
785 |
|
Initializes the time step for all models. |
786 |
|
""" |
787 |
for o in self.iterModels(): |
for o in self.iterModels(): |
788 |
o.doStepPreprocessing(dt) |
o.doStepPreprocessing(dt) |
789 |
|
|
790 |
def terminateIteration(self): |
def terminateIteration(self): |
791 |
"""returns True if all iterations for all models are terminated.""" |
""" |
792 |
|
Returns True if all iterations for all models are terminated. |
793 |
|
""" |
794 |
out=all([o.terminateIteration() for o in self.iterModels()]) |
out=all([o.terminateIteration() for o in self.iterModels()]) |
795 |
return out |
return out |
796 |
|
|
797 |
def doStepPostprocessing(self,dt): |
def doStepPostprocessing(self,dt): |
798 |
"""finalalizes the iteration process for all models.""" |
""" |
799 |
|
Finalalizes the iteration process for all models. |
800 |
|
""" |
801 |
for o in self.iterModels(): |
for o in self.iterModels(): |
802 |
o.doStepPostprocessing(dt) |
o.doStepPostprocessing(dt) |
803 |
self.n+=1 |
self.n+=1 |
805 |
|
|
806 |
def doStep(self,dt): |
def doStep(self,dt): |
807 |
""" |
""" |
808 |
executes the iteration step at a time step for all model: |
Executes the iteration step at a time step for all model:: |
809 |
|
|
810 |
self.doStepPreprocessing(dt) |
self.doStepPreprocessing(dt) |
811 |
while not self.terminateIteration(): for all models: self.doStep(dt) |
while not self.terminateIteration(): |
812 |
self.doStepPostprocessing(dt) |
for all models: |
813 |
|
self.doStep(dt) |
814 |
|
self.doStepPostprocessing(dt) |
815 |
""" |
""" |
816 |
self.iter=0 |
self.iter=0 |
817 |
while not self.terminateIteration(): |
while not self.terminateIteration(): |
824 |
|
|
825 |
def run(self,check_point=None): |
def run(self,check_point=None): |
826 |
""" |
""" |
827 |
|
Run the simulation by performing essentially:: |
|
run the simulation by performing essentially |
|
828 |
|
|
829 |
self.doInitialization() |
self.doInitialization() |
830 |
while not self.finalize(): |
while not self.finalize(): |
831 |
dt=self.getSafeTimeStepSize() |
dt=self.getSafeTimeStepSize() |
832 |
self.doStep(dt) |
self.doStep(dt) |
833 |
if n%check_point==0: self.writeXML() |
if n%check_point==0: |
834 |
self.doFinalization() |
self.writeXML() |
835 |
|
self.doFinalization() |
836 |
If one of the models in throws a FailedTimeStepError exception a new time step size is |
|
837 |
computed through getSafeTimeStepSize() and the time step is repeated. |
If one of the models in throws a C{FailedTimeStepError} exception a |
838 |
|
new time step size is computed through getSafeTimeStepSize() and the |
839 |
|
time step is repeated. |
840 |
|
|
841 |
If one of the models in throws a IterationDivergenceError exception the time step size |
If one of the models in throws a C{IterationDivergenceError} |
842 |
is halved and the time step is repeated. |
exception the time step size is halved and the time step is repeated. |
843 |
|
|
844 |
In both cases the time integration is given up after Simulation.FAILED_TIME_STEPS_MAX |
In both cases the time integration is given up after |
845 |
attempts. |
C{Simulation.FAILED_TIME_STEPS_MAX} attempts. |
|
|
|
|
|
|
846 |
""" |
""" |
847 |
dt=self.UNDEF_DT |
dt=self.UNDEF_DT |
848 |
self.doInitialization() |
self.doInitialization() |
896 |
|
|
897 |
class IterationDivergenceError(Exception): |
class IterationDivergenceError(Exception): |
898 |
""" |
""" |
899 |
excpetion which is thrown if there is no convergence of the iteration process at a time step |
Exception which is thrown if there is no convergence of the iteration |
900 |
but there is a chance taht a smaller step could help to reach convergence. |
process at a time step. |
901 |
|
|
902 |
|
But there is a chance that a smaller step could help to reach convergence. |
903 |
""" |
""" |
904 |
pass |
pass |
905 |
|
|
906 |
class FailedTimeStepError(Exception): |
class FailedTimeStepError(Exception): |
907 |
"""excpetion which is thrown if the time step fails because of a step size that have been choosen to be too large""" |
""" |
908 |
|
Exception which is thrown if the time step fails because of a step |
909 |
|
size that have been choosen to be too large. |
910 |
|
""" |
911 |
pass |
pass |
912 |
|
|
913 |
class SimulationBreakDownError(Exception): |
class SimulationBreakDownError(Exception): |
914 |
"""excpetion which is thrown if the simulation does not manage to progress in time.""" |
""" |
915 |
|
Exception which is thrown if the simulation does not manage to |
916 |
|
progress in time. |
917 |
|
""" |
918 |
pass |
pass |
919 |
|
|
920 |
class NonPositiveStepSizeError(Exception): |
class NonPositiveStepSizeError(Exception): |
921 |
"""excpetion which is thrown if the step size is not positive""" |
""" |
922 |
|
Exception which is thrown if the step size is not positive. |
923 |
|
""" |
924 |
pass |
pass |
925 |
|
|
926 |
|
# vim: expandtab shiftwidth=4: |