27 |
import numarray |
import numarray |
28 |
import operator |
import operator |
29 |
import itertools |
import itertools |
30 |
# import modellib temporarily removed!!! |
import time |
31 |
|
import os |
32 |
|
|
33 |
# import the 'set' module if it's not defined (python2.3/2.4 difference) |
# import the 'set' module if it's not defined (python2.3/2.4 difference) |
34 |
try: |
try: |
38 |
|
|
39 |
from xml.dom import minidom |
from xml.dom import minidom |
40 |
|
|
|
def dataNode(document, tagName, data): |
|
|
""" |
|
|
C{dataNode}s are the building blocks of the xml documents constructed in |
|
|
this module. |
|
|
|
|
|
@param document: the current xml document |
|
|
@param tagName: the associated xml tag |
|
|
@param data: the values in the tag |
|
|
""" |
|
|
t = document.createTextNode(str(data)) |
|
|
n = document.createElement(tagName) |
|
|
n.appendChild(t) |
|
|
return n |
|
|
|
|
|
def esysDoc(): |
|
|
""" |
|
|
Global method for creating an instance of an EsysXML document. |
|
|
""" |
|
|
doc = minidom.Document() |
|
|
esys = doc.createElement('ESys') |
|
|
doc.appendChild(esys) |
|
|
return doc, esys |
|
41 |
|
|
42 |
def all(seq): |
def all(seq): |
43 |
for x in seq: |
for x in seq: |
51 |
return True |
return True |
52 |
return False |
return False |
53 |
|
|
|
LinkableObjectRegistry = {} |
|
|
|
|
|
def registerLinkableObject(obj_id, o): |
|
|
LinkableObjectRegistry[obj_id] = o |
|
|
|
|
|
LinkRegistry = [] |
|
|
|
|
|
def registerLink(obj_id, l): |
|
|
LinkRegistry.append((obj_id,l)) |
|
|
|
|
|
def parse(xml): |
|
|
""" |
|
|
Generic parse method for EsysXML. Without this, Links don't work. |
|
|
""" |
|
|
global LinkRegistry, LinkableObjectRegistry |
|
|
LinkRegistry = [] |
|
|
LinkableObjectRegistry = {} |
|
|
|
|
|
doc = minidom.parseString(xml) |
|
|
sim = getComponent(doc.firstChild) |
|
|
for obj_id, link in LinkRegistry: |
|
|
link.target = LinkableObjectRegistry[obj_id] |
|
|
|
|
|
return sim |
|
|
|
|
54 |
def importName(modulename, name): |
def importName(modulename, name): |
55 |
""" Import a named object from a module in the context of this function, |
""" Import a named object from a module in the context of this function, |
56 |
which means you should use fully qualified module paths. |
which means you should use fully qualified module paths. |
|
|
|
57 |
Return None on failure. |
Return None on failure. |
58 |
|
|
59 |
This function from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52241 |
This function from: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52241 |
65 |
except KeyError: |
except KeyError: |
66 |
raise ImportError("Could not import %s from %s" % (name, modulename)) |
raise ImportError("Could not import %s from %s" % (name, modulename)) |
67 |
|
|
68 |
def getComponent(doc): |
class ESySXMLParser(object): |
|
""" |
|
|
Used to get components of Simualtions, Models. |
|
69 |
""" |
""" |
70 |
for node in doc.childNodes: |
parser for ESysXML file |
71 |
|
""" |
72 |
if isinstance(node, minidom.Element): |
def __init__(self,xml, debug=False): |
73 |
if node.tagName == 'Simulation': |
self.__dom = minidom.parseString(xml) |
74 |
if node.getAttribute("type") == 'Simulation': |
self.__linkable_object_registry= {} |
75 |
return Simulation.fromDom(node) |
self.__link_registry= [] |
76 |
if node.tagName == 'Model': |
self.__esys=self.__dom.getElementsByTagName('ESys')[0] |
77 |
if (node.getAttribute("module")): |
self.debug=debug |
78 |
model_module = node.getAttribute("module") |
|
79 |
model_type = node.getAttribute("type") |
def getClassPath(self, node): |
80 |
return importName(model_module, model_type).fromDom(node) |
type = node.getAttribute("type") |
81 |
else: |
if (node.getAttribute("module")): |
82 |
model_type = node.getAttribute("type") |
module = node.getAttribute("module") |
83 |
model_subclasses = Model.__subclasses__() |
return importName(module, type) |
84 |
for model in model_subclasses: |
else: |
85 |
if model_type == model.__name__: |
return importName("__main__", type) |
|
return Model.fromDom(node) |
|
|
if node.tagName == 'ParameterSet': |
|
|
parameter_type = node.getAttribute("type") |
|
|
return ParameterSet.fromDom(node) |
|
|
raise "Invalid simulation type, %r" % node.getAttribute("type") |
|
|
|
|
86 |
|
|
87 |
raise ValueError("No Simulation Found") |
def setLinks(self): |
88 |
|
for obj_id, link in self.__link_registry: |
89 |
|
link.target = self.__linkable_object_registry[obj_id] |
90 |
|
|
91 |
|
def parse(self): |
92 |
|
""" |
93 |
|
parser method for EsysXML and returns the list of generating ParameterSets |
94 |
|
""" |
95 |
|
found=[] |
96 |
|
for node in self.__esys.childNodes: |
97 |
|
if isinstance(node, minidom.Element): |
98 |
|
if node.tagName == 'Simulation': |
99 |
|
found.append(Simulation.fromDom(self, node)) |
100 |
|
elif node.tagName == 'Model': |
101 |
|
found.append(self.getClassPath(node).fromDom(self, node)) |
102 |
|
elif node.tagName == 'ParameterSet': |
103 |
|
found.append(self.getClassPath(node).fromDom(self, node)) |
104 |
|
else: |
105 |
|
raise "Invalid type, %r" % node.getAttribute("type") |
106 |
|
self.setLinks() |
107 |
|
return found |
108 |
|
|
109 |
|
def registerLink(self,obj_id, link): |
110 |
|
self.__link_registry.append((int(obj_id),link)) |
111 |
|
|
112 |
|
def registerLinkableObject(self,obj, node): |
113 |
|
id_str=node.getAttribute('id').strip() |
114 |
|
if len(id_str)>0: |
115 |
|
id=int(id_str) |
116 |
|
if self.__linkable_object_registry.has_key(id): |
117 |
|
raise ValueError("Object id %s already exists."%id) |
118 |
|
else: |
119 |
|
self.__linkable_object_registry[id]=obj |
120 |
|
|
121 |
|
def getComponent(self, node): |
122 |
|
""" |
123 |
|
returns a single component + rank from a simulation |
124 |
|
parser method for EsysXML and returns the list of generating ParameterSets |
125 |
|
""" |
126 |
|
rank = int(node.getAttribute("rank")) |
127 |
|
for n in node.childNodes: |
128 |
|
if isinstance(n, minidom.Element): |
129 |
|
if n.tagName == 'Simulation': |
130 |
|
return (rank, Simulation.fromDom(self, n)) |
131 |
|
elif n.tagName == 'Model': |
132 |
|
return (rank, self.getClassPath(n).fromDom(self, n)) |
133 |
|
elif n.tagName == 'ParameterSet': |
134 |
|
return (rank, self.getClassPath(n).fromDom(self, n)) |
135 |
|
else: |
136 |
|
raise ValueError("illegal component type %s"%n.tagName) |
137 |
|
raise ValueError("cannot resolve Component") |
138 |
|
|
139 |
|
class ESySXMLCreator(object): |
140 |
|
""" |
141 |
|
creates an XML Dom representation |
142 |
|
""" |
143 |
|
def __init__(self): |
144 |
|
self.__dom=minidom.Document() |
145 |
|
self.__esys =self.__dom.createElement('ESys') |
146 |
|
self.__dom.appendChild(self.__esys) |
147 |
|
self.__linkable_object_registry={} |
148 |
|
self.__number_sequence = itertools.count(100) |
149 |
|
def getRoot(self): |
150 |
|
return self.__esys |
151 |
|
def createElement(self,name): |
152 |
|
return self.__dom.createElement(name) |
153 |
|
def createTextNode(self,name): |
154 |
|
return self.__dom.createTextNode(name) |
155 |
|
def getElementById(self,name): |
156 |
|
return self.__dom.getElementById(name) |
157 |
|
def createDataNode(self, tagName, data): |
158 |
|
""" |
159 |
|
C{createDataNode}s are the building blocks of the xml documents constructed in |
160 |
|
this module. |
161 |
|
|
162 |
|
@param tagName: the associated xml tag |
163 |
|
@param data: the values in the tag |
164 |
|
""" |
165 |
|
n = self.createElement(tagName) |
166 |
|
n.appendChild(self.createTextNode(str(data))) |
167 |
|
return n |
168 |
|
def getLinkableObjectId(self, obj): |
169 |
|
for id, o in self.__linkable_object_registry.items(): |
170 |
|
if o == obj: return id |
171 |
|
id =self.__number_sequence.next() |
172 |
|
self.__linkable_object_registry[id]=obj |
173 |
|
return id |
174 |
|
|
175 |
|
def registerLinkableObject(self, obj, node): |
176 |
|
""" |
177 |
|
returns a unique object id for object obj |
178 |
|
""" |
179 |
|
id=self.getLinkableObjectId(obj) |
180 |
|
node.setAttribute('id',str(id)) |
181 |
|
node.setIdAttribute("id") |
182 |
|
|
183 |
|
def includeTargets(self): |
184 |
|
target_written=True |
185 |
|
while target_written: |
186 |
|
targetsList =self.__dom.getElementsByTagName('Target') |
187 |
|
target_written=False |
188 |
|
for element in targetsList: |
189 |
|
targetId = int(element.firstChild.nodeValue.strip()) |
190 |
|
if self.getElementById(str(targetId)): continue |
191 |
|
targetObj = self.__linkable_object_registry[targetId] |
192 |
|
targetObj.toDom(self, self.__esys) |
193 |
|
target_written=True |
194 |
|
|
195 |
|
def toprettyxml(self): |
196 |
|
self.includeTargets() |
197 |
|
return self.__dom.toprettyxml() |
198 |
|
|
199 |
class Link: |
class Link: |
200 |
""" |
""" |
201 |
A Link makes an attribute of an object callable:: |
A Link makes an attribute of an object callable:: |
215 |
self.target = target |
self.target = target |
216 |
self.attribute = None |
self.attribute = None |
217 |
self.setAttributeName(attribute) |
self.setAttributeName(attribute) |
218 |
|
|
219 |
|
def getTarget(self): |
220 |
|
""" |
221 |
|
returns the target |
222 |
|
""" |
223 |
|
return self.target |
224 |
|
def getAttributeName(self): |
225 |
|
""" |
226 |
|
returns the name of the attribute the link is pointing to |
227 |
|
""" |
228 |
|
return self.attribute |
229 |
|
|
230 |
def setAttributeName(self,attribute): |
def setAttributeName(self,attribute): |
231 |
""" |
""" |
271 |
else: |
else: |
272 |
return out |
return out |
273 |
|
|
274 |
def toDom(self, document, node): |
def toDom(self, esysxml, node): |
275 |
""" |
""" |
276 |
C{toDom} method of Link. Creates a Link node and appends it to the |
C{toDom} method of Link. Creates a Link node and appends it to the |
277 |
current XML document. |
current XML esysxml. |
278 |
""" |
""" |
279 |
link = document.createElement('Link') |
link = esysxml.createElement('Link') |
280 |
assert (self.target != None), ("Target was none, name was %r" % self.attribute) |
assert (self.target != None), ("Target was none, name was %r" % self.attribute) |
281 |
link.appendChild(dataNode(document, 'Target', self.target.id)) |
link.appendChild(esysxml.createDataNode('Target', esysxml.getLinkableObjectId(self.target))) |
282 |
# this use of id will not work for purposes of being able to retrieve the intended |
# this use of id will not work for purposes of being able to retrieve the intended |
283 |
# target from the xml later. I need a better unique identifier. |
# target from the xml later. I need a better unique identifier. |
284 |
assert self.attribute, "You can't xmlify a Link without a target attribute" |
assert self.attribute, "You can't xmlify a Link without a target attribute" |
285 |
link.appendChild(dataNode(document, 'Attribute', self.attribute)) |
link.appendChild(esysxml.createDataNode('Attribute', self.attribute)) |
286 |
node.appendChild(link) |
node.appendChild(link) |
287 |
|
|
288 |
def fromDom(cls, doc): |
def fromDom(cls, esysxml, node): |
289 |
targetid = doc.getElementsByTagName("Target")[0].firstChild.nodeValue.strip() |
targetid = int(node.getElementsByTagName("Target")[0].firstChild.nodeValue.strip()) |
290 |
attribute = doc.getElementsByTagName("Attribute")[0].firstChild.nodeValue.strip() |
attribute =str(node.getElementsByTagName("Attribute")[0].firstChild.nodeValue.strip()) |
291 |
l = cls(None, attribute) |
l = cls(None, attribute) |
292 |
registerLink(targetid, l) |
esysxml.registerLink(targetid, l) |
293 |
return l |
return l |
294 |
|
|
295 |
fromDom = classmethod(fromDom) |
fromDom = classmethod(fromDom) |
296 |
|
|
|
def writeXML(self,ostream=stdout): |
|
|
""" |
|
|
Writes an XML representation of self to the output stream ostream. |
|
|
If ostream is nor present the standart output stream is used. If |
|
|
esysheader==True the esys XML header is written |
|
|
""" |
|
|
print 'I got to the Link writeXML method' |
|
|
document, rootnode = esysDoc() |
|
|
self.toDom(document, rootnode) |
|
|
|
|
|
ostream.write(document.toprettyxml()) |
|
|
|
|
297 |
class LinkableObject(object): |
class LinkableObject(object): |
298 |
""" |
""" |
299 |
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 |
312 |
the return value of the call. |
the return value of the call. |
313 |
""" |
""" |
314 |
|
|
|
number_sequence = itertools.count(100) |
|
315 |
|
|
316 |
def __init__(self, debug=False): |
def __init__(self, id = None, debug=False): |
317 |
""" |
""" |
318 |
Initializes LinkableObject so that we can operate on Links |
Initializes LinkableObject so that we can operate on Links |
319 |
""" |
""" |
320 |
self.debug = debug |
self.debug = debug |
321 |
self.__linked_attributes={} |
self.__linked_attributes={} |
322 |
self.id = self.number_sequence.next() |
|
|
registerLinkableObject(self.id, self) |
|
|
|
|
323 |
def trace(self, msg): |
def trace(self, msg): |
324 |
""" |
""" |
325 |
If debugging is on, print the message, otherwise do nothing |
If debugging is on, print the message, otherwise do nothing |
447 |
self.declareParameters(parameters) |
self.declareParameters(parameters) |
448 |
|
|
449 |
def __repr__(self): |
def __repr__(self): |
450 |
return "<%s %r>" % (self.__class__.__name__, |
return "<%s %d>"%(self.__class__.__name__,id(self)) |
|
[(p, getattr(self, p, None)) for p in self.parameters]) |
|
451 |
|
|
452 |
def declareParameter(self,**parameters): |
def declareParameter(self,**parameters): |
453 |
""" |
""" |
469 |
setattr(self,prm,value) |
setattr(self,prm,value) |
470 |
self.parameters.add(prm) |
self.parameters.add(prm) |
471 |
|
|
|
self.trace("parameter %s has been declared."%prm) |
|
|
|
|
472 |
def releaseParameters(self,name): |
def releaseParameters(self,name): |
473 |
""" |
""" |
474 |
Removes parameter name from the paramameters. |
Removes parameter name from the paramameters. |
476 |
if self.isParameter(name): |
if self.isParameter(name): |
477 |
self.parameters.remove(name) |
self.parameters.remove(name) |
478 |
self.trace("parameter %s has been removed."%name) |
self.trace("parameter %s has been removed."%name) |
479 |
|
|
480 |
|
def checkLinkTargets(self, models, hash): |
481 |
|
""" |
482 |
|
returns a set of tuples ("<self>(<name>)", <target model>) if the parameter <name> is linked to model <target model> |
483 |
|
but <target model> is not in the list models. If the a parameter is linked to another parameter set which is not in the hash list |
484 |
|
the parameter set is checked for its models. hash gives the call history. |
485 |
|
""" |
486 |
|
out=set() |
487 |
|
for name, value in self: |
488 |
|
if isinstance(value, Link): |
489 |
|
m=value.getTarget() |
490 |
|
if isinstance(m, Model): |
491 |
|
if not m in models: out.add( (str(self)+"("+name+")",m) ) |
492 |
|
elif isinstance(m, ParameterSet) and not m in hash: |
493 |
|
out|=set( [ (str(self)+"("+name+")."+f[0],f[1]) for f in m.checkLinkTargets(models, hash+[ self ] ) ] ) |
494 |
|
return out |
495 |
|
|
496 |
def __iter__(self): |
def __iter__(self): |
497 |
""" |
""" |
524 |
except: |
except: |
525 |
pass |
pass |
526 |
|
|
527 |
def toDom(self, document, node): |
def toDom(self, esysxml, node): |
528 |
""" |
""" |
529 |
C{toDom} method of ParameterSet class. |
C{toDom} method of Model class |
530 |
""" |
""" |
531 |
pset = document.createElement('ParameterSet') |
pset = esysxml.createElement('ParameterSet') |
532 |
|
pset.setAttribute('type', self.__class__.__name__) |
533 |
|
pset.setAttribute('module', self.__class__.__module__) |
534 |
|
esysxml.registerLinkableObject(self, pset) |
535 |
|
self._parametersToDom(esysxml, pset) |
536 |
node.appendChild(pset) |
node.appendChild(pset) |
|
self._parametersToDom(document, pset) |
|
537 |
|
|
538 |
def _parametersToDom(self, document, node): |
def _parametersToDom(self, esysxml, node): |
|
node.setAttribute('id', str(self.id)) |
|
|
node.setIdAttribute("id") |
|
539 |
for name,value in self: |
for name,value in self: |
540 |
param = document.createElement('Parameter') |
# convert list to numarray when possible: |
541 |
param.setAttribute('type', value.__class__.__name__) |
if isinstance (value, list): |
542 |
|
elem_type=-1 |
543 |
|
for i in value: |
544 |
|
if isinstance(i, bool): |
545 |
|
elem_type = max(elem_type,0) |
546 |
|
elif isinstance(i, int): |
547 |
|
elem_type = max(elem_type,1) |
548 |
|
elif isinstance(i, float): |
549 |
|
elem_type = max(elem_type,2) |
550 |
|
if elem_type == 0: value = numarray.array(value,numarray.Bool) |
551 |
|
if elem_type == 1: value = numarray.array(value,numarray.Int) |
552 |
|
if elem_type == 2: value = numarray.array(value,numarray.Float) |
553 |
|
|
554 |
param.appendChild(dataNode(document, 'Name', name)) |
param = esysxml.createElement('Parameter') |
555 |
|
param.setAttribute('type', value.__class__.__name__) |
556 |
|
|
557 |
val = document.createElement('Value') |
param.appendChild(esysxml.createDataNode('Name', name)) |
558 |
|
|
559 |
|
val = esysxml.createElement('Value') |
560 |
if isinstance(value,(ParameterSet,Link,DataSource)): |
if isinstance(value,(ParameterSet,Link,DataSource)): |
561 |
value.toDom(document, val) |
value.toDom(esysxml, val) |
562 |
param.appendChild(val) |
param.appendChild(val) |
563 |
elif isinstance(value, numarray.NumArray): |
elif isinstance(value, numarray.NumArray): |
564 |
shape = value.getshape() |
shape = value.getshape() |
570 |
shape = str(shape) |
shape = str(shape) |
571 |
|
|
572 |
arraytype = value.type() |
arraytype = value.type() |
573 |
numarrayElement = document.createElement('NumArray') |
if isinstance(arraytype, numarray.BooleanType): |
574 |
numarrayElement.appendChild(dataNode(document, 'ArrayType', str(arraytype))) |
arraytype_str="Bool" |
575 |
numarrayElement.appendChild(dataNode(document, 'Shape', shape)) |
elif isinstance(arraytype, numarray.IntegralType): |
576 |
numarrayElement.appendChild(dataNode(document, 'Data', ' '.join( |
arraytype_str="Int" |
577 |
|
elif isinstance(arraytype, numarray.FloatingType): |
578 |
|
arraytype_str="Float" |
579 |
|
elif isinstance(arraytype, numarray.ComplexType): |
580 |
|
arraytype_str="Complex" |
581 |
|
else: |
582 |
|
arraytype_str=str(arraytype) |
583 |
|
numarrayElement = esysxml.createElement('NumArray') |
584 |
|
numarrayElement.appendChild(esysxml.createDataNode('ArrayType', arraytype_str)) |
585 |
|
numarrayElement.appendChild(esysxml.createDataNode('Shape', shape)) |
586 |
|
numarrayElement.appendChild(esysxml.createDataNode('Data', ' '.join( |
587 |
[str(x) for x in numarray.reshape(value, size)]))) |
[str(x) for x in numarray.reshape(value, size)]))) |
588 |
val.appendChild(numarrayElement) |
val.appendChild(numarrayElement) |
589 |
param.appendChild(val) |
param.appendChild(val) |
590 |
elif isinstance (value, list): |
elif isinstance(value, list): |
591 |
param.appendChild(dataNode(document, 'Value', ' '.join( |
param.appendChild(esysxml.createDataNode('Value', ' '.join([str(x) for x in value]) )) |
592 |
[str(x) for x in value]) |
elif isinstance(value, (str, bool, int, float, type(None))): |
593 |
)) |
param.appendChild(esysxml.createDataNode('Value', str(value))) |
594 |
|
elif isinstance(value, dict): |
595 |
|
dic = esysxml.createElement('dictionary') |
596 |
|
if len(value.keys())>0: |
597 |
|
dic.setAttribute('key_type', value.keys()[0].__class__.__name__) |
598 |
|
dic.setAttribute('value_type', value[value.keys()[0]].__class__.__name__) |
599 |
|
for k,v in value.items(): |
600 |
|
i=esysxml.createElement('item') |
601 |
|
i.appendChild(esysxml.createDataNode('key', k)) |
602 |
|
i.appendChild(esysxml.createDataNode('value', v)) |
603 |
|
dic.appendChild(i) |
604 |
|
param.appendChild(dic) |
605 |
else: |
else: |
606 |
param.appendChild(dataNode(document, 'Value', str(value))) |
raise ValueError("cannot serialize %s type to XML."%str(value.__class__)) |
607 |
|
|
608 |
node.appendChild(param) |
node.appendChild(param) |
609 |
|
|
610 |
def fromDom(cls, doc): |
def fromDom(cls, esysxml, node): |
|
|
|
611 |
# Define a host of helper functions to assist us. |
# Define a host of helper functions to assist us. |
612 |
def _children(node): |
def _children(node): |
613 |
""" |
""" |
622 |
ret.append(x) |
ret.append(x) |
623 |
return ret |
return ret |
624 |
|
|
625 |
def _floatfromValue(doc): |
def _floatfromValue(esysxml, node): |
626 |
return float(doc.nodeValue.strip()) |
return float(node.nodeValue.strip()) |
627 |
|
|
628 |
def _stringfromValue(doc): |
def _stringfromValue(esysxml, node): |
629 |
return str(doc.nodeValue.strip()) |
return str(node.nodeValue.strip()) |
630 |
|
|
631 |
def _intfromValue(doc): |
def _intfromValue(esysxml, node): |
632 |
return int(doc.nodeValue.strip()) |
return int(node.nodeValue.strip()) |
633 |
|
|
634 |
def _boolfromValue(doc): |
def _boolfromValue(esysxml, node): |
635 |
return _boolfromstring(doc.nodeValue.strip()) |
return _boolfromstring(node.nodeValue.strip()) |
636 |
|
|
637 |
def _nonefromValue(doc): |
def _nonefromValue(esysxml, node): |
638 |
return None |
return None |
639 |
|
|
640 |
def _numarrayfromValue(doc): |
def _numarrayfromValue(esysxml, node): |
641 |
for node in _children(doc): |
for node in _children(node): |
642 |
if node.tagName == 'ArrayType': |
if node.tagName == 'ArrayType': |
643 |
arraytype = node.firstChild.nodeValue.strip() |
arraytype = node.firstChild.nodeValue.strip() |
644 |
if node.tagName == 'Shape': |
if node.tagName == 'Shape': |
650 |
return numarray.reshape(numarray.array(data, type=getattr(numarray, arraytype)), |
return numarray.reshape(numarray.array(data, type=getattr(numarray, arraytype)), |
651 |
shape) |
shape) |
652 |
|
|
653 |
def _listfromValue(doc): |
def _listfromValue(esysxml, node): |
654 |
return [_boolfromstring(x) for x in doc.nodeValue.split()] |
return [x for x in node.nodeValue.split()] |
|
|
|
655 |
|
|
656 |
def _boolfromstring(s): |
def _boolfromstring(s): |
657 |
if s == 'True': |
if s == 'True': |
673 |
"NoneType":_nonefromValue, |
"NoneType":_nonefromValue, |
674 |
} |
} |
675 |
|
|
|
# print doc.toxml() |
|
|
|
|
676 |
parameters = {} |
parameters = {} |
677 |
for node in _children(doc): |
for n in _children(node): |
678 |
ptype = node.getAttribute("type") |
ptype = n.getAttribute("type") |
679 |
|
if not ptypemap.has_key(ptype): |
680 |
|
raise KeyError("cannot handle parameter type %s."%ptype) |
681 |
|
|
682 |
pname = pvalue = None |
pname = pvalue = None |
683 |
for childnode in _children(node): |
for childnode in _children(n): |
|
|
|
684 |
if childnode.tagName == "Name": |
if childnode.tagName == "Name": |
685 |
pname = childnode.firstChild.nodeValue.strip() |
pname = childnode.firstChild.nodeValue.strip() |
686 |
|
|
687 |
if childnode.tagName == "Value": |
if childnode.tagName == "Value": |
688 |
nodes = _children(childnode) |
nodes = _children(childnode) |
689 |
# if ptype == 'NumArray': |
pvalue = ptypemap[ptype](esysxml, nodes[0]) |
|
# pvalue = _numarrayfromValue(nodes) |
|
|
# else: |
|
|
pvalue = ptypemap[ptype](nodes[0]) |
|
690 |
|
|
691 |
parameters[pname] = pvalue |
parameters[pname] = pvalue |
692 |
|
|
693 |
# Create the instance of ParameterSet |
# Create the instance of ParameterSet |
694 |
o = cls() |
o = cls(debug=esysxml.debug) |
695 |
o.declareParameters(parameters) |
o.declareParameters(parameters) |
696 |
registerLinkableObject(doc.getAttribute("id"), o) |
esysxml.registerLinkableObject(o, node) |
697 |
return o |
return o |
698 |
|
|
699 |
fromDom = classmethod(fromDom) |
fromDom = classmethod(fromDom) |
700 |
|
|
701 |
def writeXML(self,ostream=stdout): |
def writeXML(self,ostream=stdout): |
702 |
""" |
""" |
703 |
Writes the object as an XML object into an output stream. |
Writes the object as an XML object into an output stream. |
704 |
""" |
""" |
705 |
# ParameterSet(d) with d[Name]=Value |
esysxml=ESySXMLCreator() |
706 |
document, node = esysDoc() |
self.toDom(esysxml, esysxml.getRoot()) |
707 |
self.toDom(document, node) |
ostream.write(esysxml.toprettyxml()) |
708 |
ostream.write(document.toprettyxml()) |
|
|
|
|
709 |
class Model(ParameterSet): |
class Model(ParameterSet): |
710 |
""" |
""" |
711 |
A Model object represents a processess marching over time until a |
A Model object represents a processess marching over time until a |
712 |
finalizing condition is fullfilled. At each time step an iterative |
finalizing condition is fullfilled. At each time step an iterative |
713 |
process can be performed and the time step size can be controlled. A |
process can be performed and the time step size can be controlled. A |
714 |
Model has the following work flow:: |
Model has the following work flow:: |
715 |
|
|
716 |
doInitialization() |
doInitialization() |
717 |
|
while not terminateInitialIteration(): doInitializationiStep() |
718 |
|
doInitialPostprocessing() |
719 |
while not finalize(): |
while not finalize(): |
720 |
dt=getSafeTimeStepSize(dt) |
dt=getSafeTimeStepSize(dt) |
721 |
doStepPreprocessing(dt) |
doStepPreprocessing(dt) |
732 |
|
|
733 |
UNDEF_DT=1.e300 |
UNDEF_DT=1.e300 |
734 |
|
|
735 |
def __init__(self,parameters=[],**kwarg): |
def __init__(self,parameters=[],**kwargs): |
736 |
""" |
""" |
737 |
Creates a model. |
Creates a model. |
738 |
|
|
739 |
Just calls the parent constructor. |
Just calls the parent constructor. |
740 |
""" |
""" |
741 |
ParameterSet.__init__(self, parameters=parameters,**kwarg) |
ParameterSet.__init__(self, parameters=parameters,**kwargs) |
742 |
|
|
743 |
def __str__(self): |
def __str__(self): |
744 |
return "<%s %d>"%(self.__class__,id(self)) |
return "<%s %d>"%(self.__class__.__name__,id(self)) |
745 |
|
|
746 |
def toDom(self, document, node): |
|
747 |
|
def setUp(self): |
748 |
""" |
""" |
749 |
C{toDom} method of Model class |
Sets up the model. |
750 |
""" |
|
751 |
pset = document.createElement('Model') |
This function may be overwritten. |
752 |
pset.setAttribute('type', self.__class__.__name__) |
""" |
753 |
if not self.__class__.__module__.startswith('esys.escript'): |
pass |
|
pset.setAttribute('module', self.__class__.__module__) |
|
|
node.appendChild(pset) |
|
|
self._parametersToDom(document, pset) |
|
754 |
|
|
755 |
def doInitialization(self): |
def doInitialization(self): |
756 |
""" |
""" |
757 |
Initializes the time stepping scheme. |
Initializes the time stepping scheme. This method is not called in case of a restart. |
758 |
|
|
759 |
This function may be overwritten. |
This function may be overwritten. |
760 |
""" |
""" |
761 |
pass |
pass |
762 |
|
def doInitialStep(self): |
763 |
|
""" |
764 |
|
performs an iteration step in the initialization phase. This method is not called in case of a restart. |
765 |
|
|
766 |
|
This function may be overwritten. |
767 |
|
""" |
768 |
|
pass |
769 |
|
|
770 |
|
def terminateInitialIteration(self): |
771 |
|
""" |
772 |
|
Returns True if iteration at the inital phase is terminated. |
773 |
|
""" |
774 |
|
return True |
775 |
|
|
776 |
|
def doInitialPostprocessing(self): |
777 |
|
""" |
778 |
|
finalises the initialization iteration process. This method is not called in case of a restart. |
779 |
|
|
780 |
|
This function may be overwritten. |
781 |
|
""" |
782 |
|
pass |
783 |
|
|
784 |
def getSafeTimeStepSize(self,dt): |
def getSafeTimeStepSize(self,dt): |
785 |
""" |
""" |
830 |
Returns True if iteration on a time step is terminated. |
Returns True if iteration on a time step is terminated. |
831 |
""" |
""" |
832 |
return True |
return True |
833 |
|
|
834 |
|
|
835 |
def doStepPostprocessing(self,dt): |
def doStepPostprocessing(self,dt): |
836 |
""" |
""" |
837 |
Finalalizes the time step. |
finalises the time step. |
838 |
|
|
839 |
dt is the currently used time step size. |
dt is the currently used time step size. |
840 |
|
|
841 |
This function may be overwritten. |
This function may be overwritten. |
842 |
""" |
""" |
843 |
pass |
pass |
|
|
|
|
def writeXML(self, ostream=stdout): |
|
|
document, node = esysDoc() |
|
|
self.toDom(document, node) |
|
|
ostream.write(document.toprettyxml()) |
|
|
|
|
844 |
|
|
845 |
|
def toDom(self, esysxml, node): |
846 |
|
""" |
847 |
|
C{toDom} method of Model class |
848 |
|
""" |
849 |
|
pset = esysxml.createElement('Model') |
850 |
|
pset.setAttribute('type', self.__class__.__name__) |
851 |
|
pset.setAttribute('module', self.__class__.__module__) |
852 |
|
esysxml.registerLinkableObject(self, pset) |
853 |
|
node.appendChild(pset) |
854 |
|
self._parametersToDom(esysxml, pset) |
855 |
|
|
856 |
class Simulation(Model): |
class Simulation(Model): |
857 |
""" |
""" |
858 |
A Simulation object is special Model which runs a sequence of Models. |
A Simulation object is special Model which runs a sequence of Models. |
871 |
""" |
""" |
872 |
Initiates a simulation from a list of models. |
Initiates a simulation from a list of models. |
873 |
""" |
""" |
874 |
Model.__init__(self, **kwargs) |
super(Simulation, self).__init__(**kwargs) |
875 |
|
self.declareParameter(time=0., |
876 |
|
time_step=0, |
877 |
|
dt = self.UNDEF_DT) |
878 |
|
for m in models: |
879 |
|
if not isinstance(m, Model): |
880 |
|
raise TypeError("%s is not a subclass of Model."%m) |
881 |
self.__models=[] |
self.__models=[] |
|
|
|
882 |
for i in range(len(models)): |
for i in range(len(models)): |
883 |
self[i] = models[i] |
self[i] = models[i] |
884 |
|
|
923 |
""" |
""" |
924 |
return len(self.__models) |
return len(self.__models) |
925 |
|
|
926 |
def toDom(self, document, node): |
def getAllModels(self): |
927 |
""" |
""" |
928 |
C{toDom} method of Simulation class. |
returns a list of all models used in the Simulation including subsimulations |
929 |
""" |
""" |
930 |
simulation = document.createElement('Simulation') |
out=[] |
931 |
simulation.setAttribute('type', self.__class__.__name__) |
for m in self.iterModels(): |
932 |
|
if isinstance(m, Simulation): |
933 |
for rank, sim in enumerate(self.iterModels()): |
out+=m.getAllModels() |
934 |
component = document.createElement('Component') |
else: |
935 |
component.setAttribute('rank', str(rank)) |
out.append(m) |
936 |
|
return list(set(out)) |
|
sim.toDom(document, component) |
|
|
|
|
|
simulation.appendChild(component) |
|
|
|
|
|
node.appendChild(simulation) |
|
937 |
|
|
938 |
def writeXML(self,ostream=stdout): |
def checkModels(self, models, hash): |
939 |
""" |
""" |
940 |
Writes the object as an XML object into an output stream. |
returns a list of (model,parameter, target model ) if the the parameter of model |
941 |
""" |
is linking to the target_model which is not in list of models. |
942 |
document, rootnode = esysDoc() |
""" |
943 |
self.toDom(document, rootnode) |
out=self.checkLinkTargets(models, hash + [self]) |
944 |
targetsList = document.getElementsByTagName('Target') |
for m in self.iterModels(): |
945 |
|
if isinstance(m, Simulation): |
946 |
for element in targetsList: |
out|=m.checkModels(models, hash) |
947 |
targetId = int(element.firstChild.nodeValue.strip()) |
else: |
948 |
if document.getElementById(str(targetId)): |
out|=m.checkLinkTargets(models, hash + [self]) |
949 |
continue |
return set( [ (str(self)+"."+f[0],f[1]) for f in out ] ) |
950 |
targetObj = LinkableObjectRegistry[targetId] |
|
|
targetObj.toDom(document, rootnode) |
|
|
ostream.write(document.toprettyxml()) |
|
951 |
|
|
952 |
def getSafeTimeStepSize(self,dt): |
def getSafeTimeStepSize(self,dt): |
953 |
""" |
""" |
956 |
This is the minimum over the time step sizes of all models. |
This is the minimum over the time step sizes of all models. |
957 |
""" |
""" |
958 |
out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()]) |
out=min([o.getSafeTimeStepSize(dt) for o in self.iterModels()]) |
|
#print "%s: safe step size is %e."%(str(self),out) |
|
959 |
return out |
return out |
960 |
|
|
961 |
|
def setUp(self): |
962 |
|
""" |
963 |
|
performs the setup for all models |
964 |
|
""" |
965 |
|
for o in self.iterModels(): |
966 |
|
o.setUp() |
967 |
|
|
968 |
def doInitialization(self): |
def doInitialization(self): |
969 |
""" |
""" |
970 |
Initializes all models. |
Initializes all models. |
971 |
""" |
""" |
|
self.n=0 |
|
|
self.tn=0. |
|
972 |
for o in self.iterModels(): |
for o in self.iterModels(): |
973 |
o.doInitialization() |
o.doInitialization() |
974 |
|
def doInitialStep(self): |
975 |
|
""" |
976 |
|
performs an iteration step in the initialization step for all models |
977 |
|
""" |
978 |
|
iter=0 |
979 |
|
while not self.terminateInitialIteration(): |
980 |
|
if iter==0: self.trace("iteration for initialization starts") |
981 |
|
iter+=1 |
982 |
|
self.trace("iteration step %d"%(iter)) |
983 |
|
for o in self.iterModels(): |
984 |
|
o.doInitialStep() |
985 |
|
if iter>self.MAX_ITER_STEPS: |
986 |
|
raise IterationDivergenceError("initial iteration did not converge after %s steps."%iter) |
987 |
|
self.trace("Initialization finalized after %s iteration steps."%iter) |
988 |
|
|
989 |
|
def doInitialPostprocessing(self): |
990 |
|
""" |
991 |
|
finalises the initialization iteration process for all models. |
992 |
|
""" |
993 |
|
for o in self.iterModels(): |
994 |
|
o.doInitialPostprocessing() |
995 |
def finalize(self): |
def finalize(self): |
996 |
""" |
""" |
997 |
Returns True if any of the models is to be finalized. |
Returns True if any of the models is to be finalized. |
1000 |
|
|
1001 |
def doFinalization(self): |
def doFinalization(self): |
1002 |
""" |
""" |
1003 |
Finalalizes the time stepping for all models. |
finalises the time stepping for all models. |
1004 |
""" |
""" |
1005 |
for i in self.iterModels(): i.doFinalization() |
for i in self.iterModels(): i.doFinalization() |
1006 |
self.trace("end of time integation.") |
self.trace("end of time integation.") |
1018 |
""" |
""" |
1019 |
out=all([o.terminateIteration() for o in self.iterModels()]) |
out=all([o.terminateIteration() for o in self.iterModels()]) |
1020 |
return out |
return out |
1021 |
|
|
1022 |
|
def terminateInitialIteration(self): |
1023 |
|
""" |
1024 |
|
Returns True if all initial iterations for all models are terminated. |
1025 |
|
""" |
1026 |
|
out=all([o.terminateInitialIteration() for o in self.iterModels()]) |
1027 |
|
return out |
1028 |
|
|
1029 |
def doStepPostprocessing(self,dt): |
def doStepPostprocessing(self,dt): |
1030 |
""" |
""" |
1031 |
Finalalizes the iteration process for all models. |
finalises the iteration process for all models. |
1032 |
""" |
""" |
1033 |
for o in self.iterModels(): |
for o in self.iterModels(): |
1034 |
o.doStepPostprocessing(dt) |
o.doStepPostprocessing(dt) |
1035 |
self.n+=1 |
self.time_step+=1 |
1036 |
self.tn+=dt |
self.time+=dt |
1037 |
|
self.dt=dt |
1038 |
|
|
1039 |
def doStep(self,dt): |
def doStep(self,dt): |
1040 |
""" |
""" |
1048 |
""" |
""" |
1049 |
self.iter=0 |
self.iter=0 |
1050 |
while not self.terminateIteration(): |
while not self.terminateIteration(): |
1051 |
if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.n+1,self.tn+dt)) |
if self.iter==0: self.trace("iteration at %d-th time step %e starts"%(self.time_step+1,self.time+dt)) |
1052 |
self.iter+=1 |
self.iter+=1 |
1053 |
self.trace("iteration step %d"%(self.iter)) |
self.trace("iteration step %d"%(self.iter)) |
1054 |
for o in self.iterModels(): |
for o in self.iterModels(): |
1055 |
o.doStep(dt) |
o.doStep(dt) |
1056 |
if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.n+1,self.tn+dt)) |
if self.iter>0: self.trace("iteration at %d-th time step %e finalized."%(self.time_step+1,self.time+dt)) |
1057 |
|
|
1058 |
def run(self,check_point=None): |
def run(self,check_pointing=None): |
1059 |
""" |
""" |
1060 |
Run the simulation by performing essentially:: |
Run the simulation by performing essentially:: |
1061 |
|
|
1062 |
self.doInitialization() |
self.setUp() |
1063 |
|
if not restart: |
1064 |
|
self.doInitialization() |
1065 |
|
while not self.terminateInitialIteration(): self.doInitialStep() |
1066 |
|
self.doInitialPostprocessing() |
1067 |
while not self.finalize(): |
while not self.finalize(): |
1068 |
dt=self.getSafeTimeStepSize() |
dt=self.getSafeTimeStepSize() |
1069 |
self.doStep(dt) |
self.doStepPreprocessing(dt_new) |
1070 |
if n%check_point==0: |
self.doStep(dt_new) |
1071 |
self.writeXML() |
self.doStepPostprocessing(dt_new) |
1072 |
self.doFinalization() |
self.doFinalization() |
1073 |
|
|
1074 |
If one of the models in throws a C{FailedTimeStepError} exception a |
If one of the models in throws a C{FailedTimeStepError} exception a |
1081 |
In both cases the time integration is given up after |
In both cases the time integration is given up after |
1082 |
C{Simulation.FAILED_TIME_STEPS_MAX} attempts. |
C{Simulation.FAILED_TIME_STEPS_MAX} attempts. |
1083 |
""" |
""" |
1084 |
dt=self.UNDEF_DT |
# check the completness of the models: |
1085 |
self.doInitialization() |
# first a list of all the models involved in the simulation including subsimulations: |
1086 |
|
# |
1087 |
|
missing=self.checkModels(self.getAllModels(), []) |
1088 |
|
if len(missing)>0: |
1089 |
|
msg="" |
1090 |
|
for l in missing: |
1091 |
|
msg+="\n\t"+str(l[1])+" at "+l[0] |
1092 |
|
raise MissingLink("link targets missing in the Simulation: %s"%msg) |
1093 |
|
#============================== |
1094 |
|
self.setUp() |
1095 |
|
if self.time_step < 1: |
1096 |
|
self.doInitialization() |
1097 |
|
self.doInitialStep() |
1098 |
|
self.doInitialPostprocessing() |
1099 |
while not self.finalize(): |
while not self.finalize(): |
1100 |
step_fail_counter=0 |
step_fail_counter=0 |
1101 |
iteration_fail_counter=0 |
iteration_fail_counter=0 |
1102 |
if self.n==0: |
if self.time_step==0: |
1103 |
dt_new=self.getSafeTimeStepSize(dt) |
dt_new=self.getSafeTimeStepSize(self.dt) |
1104 |
else: |
else: |
1105 |
dt_new=min(max(self.getSafeTimeStepSize(dt),dt/self.MAX_CHANGE_OF_DT),dt*self.MAX_CHANGE_OF_DT) |
dt_new=min(max(self.getSafeTimeStepSize(self.dt),self.dt/self.MAX_CHANGE_OF_DT),self.dt*self.MAX_CHANGE_OF_DT) |
1106 |
self.trace("%d. time step %e (step size %e.)" % (self.n+1,self.tn+dt_new,dt_new)) |
self.trace("%d. time step %e (step size %e.)" % (self.time_step+1,self.time+dt_new,dt_new)) |
1107 |
end_of_step=False |
end_of_step=False |
1108 |
while not end_of_step: |
while not end_of_step: |
1109 |
end_of_step=True |
end_of_step=True |
1110 |
if not dt_new>0: |
if not dt_new>0: |
1111 |
raise NonPositiveStepSizeError("non-positive step size in step %d"%(self.n+1)) |
raise NonPositiveStepSizeError("non-positive step size in step %d"%(self.time_step+1)) |
1112 |
try: |
try: |
1113 |
self.doStepPreprocessing(dt_new) |
self.doStepPreprocessing(dt_new) |
1114 |
self.doStep(dt_new) |
self.doStep(dt_new) |
1121 |
raise SimulationBreakDownError("reduction of time step to achieve convergence failed after %s steps."%self.FAILED_TIME_STEPS_MAX) |
raise SimulationBreakDownError("reduction of time step to achieve convergence failed after %s steps."%self.FAILED_TIME_STEPS_MAX) |
1122 |
self.trace("Iteration failed. Time step is repeated with new step size %s."%dt_new) |
self.trace("Iteration failed. Time step is repeated with new step size %s."%dt_new) |
1123 |
except FailedTimeStepError: |
except FailedTimeStepError: |
1124 |
dt_new=self.getSafeTimeStepSize(dt) |
dt_new=self.getSafeTimeStepSize(self.dt) |
1125 |
end_of_step=False |
end_of_step=False |
1126 |
step_fail_counter+=1 |
step_fail_counter+=1 |
1127 |
self.trace("Time step is repeated with new time step size %s."%dt_new) |
self.trace("Time step is repeated with new time step size %s."%dt_new) |
1128 |
if step_fail_counter>self.FAILED_TIME_STEPS_MAX: |
if step_fail_counter>self.FAILED_TIME_STEPS_MAX: |
1129 |
raise SimulationBreakDownError("Time integration is given up after %d attempts."%step_fail_counter) |
raise SimulationBreakDownError("Time integration is given up after %d attempts."%step_fail_counter) |
1130 |
dt=dt_new |
if not check_pointing==None: |
1131 |
if not check_point==None: |
if check_pointing.doDump(): |
|
if n%check_point==0: |
|
1132 |
self.trace("check point is created.") |
self.trace("check point is created.") |
1133 |
self.writeXML() |
self.writeXML() |
1134 |
self.doFinalization() |
self.doFinalization() |
1135 |
|
|
|
def fromDom(cls, doc): |
|
|
sims = [] |
|
|
for node in doc.childNodes: |
|
|
if isinstance(node, minidom.Text): |
|
|
continue |
|
1136 |
|
|
1137 |
sims.append(getComponent(node)) |
def toDom(self, esysxml, node): |
1138 |
|
""" |
1139 |
|
C{toDom} method of Simulation class. |
1140 |
|
""" |
1141 |
|
simulation = esysxml.createElement('Simulation') |
1142 |
|
esysxml.registerLinkableObject(self, simulation) |
1143 |
|
for rank, sim in enumerate(self.iterModels()): |
1144 |
|
component = esysxml.createElement('Component') |
1145 |
|
component.setAttribute('rank', str(rank)) |
1146 |
|
sim.toDom(esysxml, component) |
1147 |
|
simulation.appendChild(component) |
1148 |
|
node.appendChild(simulation) |
1149 |
|
|
1150 |
|
|
1151 |
return cls(sims) |
def fromDom(cls, esysxml, node): |
1152 |
|
sims = [] |
1153 |
|
for n in node.childNodes: |
1154 |
|
if isinstance(n, minidom.Text): |
1155 |
|
continue |
1156 |
|
sims.append(esysxml.getComponent(n)) |
1157 |
|
sims.sort(_comp) |
1158 |
|
sim=cls([s[1] for s in sims], debug=esysxml.debug) |
1159 |
|
esysxml.registerLinkableObject(sim, node) |
1160 |
|
return sim |
1161 |
|
|
1162 |
fromDom = classmethod(fromDom) |
fromDom = classmethod(fromDom) |
1163 |
|
|
1164 |
|
def _comp(a,b): |
1165 |
|
if a[0]<a[1]: |
1166 |
|
return 1 |
1167 |
|
elif a[0]>a[1]: |
1168 |
|
return -1 |
1169 |
|
else: |
1170 |
|
return 0 |
1171 |
|
|
1172 |
class IterationDivergenceError(Exception): |
class IterationDivergenceError(Exception): |
1173 |
""" |
""" |
1198 |
""" |
""" |
1199 |
pass |
pass |
1200 |
|
|
1201 |
|
class MissingLink(Exception): |
1202 |
|
""" |
1203 |
|
Exception thrown when a link is missing |
1204 |
|
""" |
1205 |
|
pass |
1206 |
|
|
1207 |
class DataSource(object): |
class DataSource(object): |
1208 |
""" |
""" |
1209 |
Class for handling data sources, including local and remote files. This class is under development. |
Class for handling data sources, including local and remote files. This class is under development. |
1213 |
self.uri = uri |
self.uri = uri |
1214 |
self.fileformat = fileformat |
self.fileformat = fileformat |
1215 |
|
|
1216 |
def toDom(self, document, node): |
def toDom(self, esysxml, node): |
1217 |
""" |
""" |
1218 |
C{toDom} method of DataSource. Creates a DataSource node and appends it to the |
C{toDom} method of DataSource. Creates a DataSource node and appends it to the |
1219 |
current XML document. |
current XML esysxml. |
1220 |
""" |
""" |
1221 |
ds = document.createElement('DataSource') |
ds = esysxml.createElement('DataSource') |
1222 |
ds.appendChild(dataNode(document, 'URI', self.uri)) |
ds.appendChild(esysxml.createDataNode('URI', self.uri)) |
1223 |
ds.appendChild(dataNode(document, 'FileFormat', self.fileformat)) |
ds.appendChild(esysxml.createDataNode('FileFormat', self.fileformat)) |
1224 |
node.appendChild(ds) |
node.appendChild(ds) |
1225 |
|
|
1226 |
def fromDom(cls, doc): |
def fromDom(cls, esysxml, node): |
1227 |
uri= doc.getElementsByTagName("URI")[0].firstChild.nodeValue.strip() |
uri= str(node.getElementsByTagName("URI")[0].firstChild.nodeValue.strip()) |
1228 |
fileformat= doc.getElementsByTagName("FileFormat")[0].firstChild.nodeValue.strip() |
fileformat= str(node.getElementsByTagName("FileFormat")[0].firstChild.nodeValue.strip()) |
1229 |
ds = cls(uri, fileformat) |
ds = cls(uri, fileformat) |
1230 |
return ds |
return ds |
1231 |
|
|
1233 |
return self.uri |
return self.uri |
1234 |
|
|
1235 |
fromDom = classmethod(fromDom) |
fromDom = classmethod(fromDom) |
1236 |
|
|
1237 |
|
class RestartManager(object): |
1238 |
|
""" |
1239 |
|
A restart manager which does two things: it decides when restart files have created (when doDump returns true) and |
1240 |
|
manages directories for restart files. The method getNewDumper creates a new directory and returns its name. |
1241 |
|
|
1242 |
|
This restart manager will decide to dump restart files if every dump_step calls of doDump or |
1243 |
|
if more than dump_time since the last dump has elapsed. The restart manager controls two directories for dumping restart data, namely |
1244 |
|
for the current and previous dump. This way the previous dump can be used for restart in the case the current dump failed. |
1245 |
|
|
1246 |
|
@cvar SEC: unit of seconds, for instance for 5*RestartManager.SEC to define 5 seconds. |
1247 |
|
@cvar MIN: unit of minutes, for instance for 5*RestartManager.MIN to define 5 minutes. |
1248 |
|
@cvar H: unit of hours, for instance for 5*RestartManager.H to define 5 hours. |
1249 |
|
@cvar D: unit of days, for instance for 5*RestartManager.D to define 5 days. |
1250 |
|
""" |
1251 |
|
SEC=1. |
1252 |
|
MIN=60. |
1253 |
|
H=360. |
1254 |
|
D=8640. |
1255 |
|
def __init__(self,dump_time=1080., dump_step=None, dumper=None): |
1256 |
|
""" |
1257 |
|
initializes the RestartManager. |
1258 |
|
|
1259 |
|
@param dump_time: defines the minimum time interval in SEC between to dumps. If None, time is not used as criterion. |
1260 |
|
@param dump_step: defines the number of calls of doDump between to dump events. If None, the call counter is not used as criterion. |
1261 |
|
@param dumper: defines the directory for dumping restart files. Additionally the directories dumper+"_bkp" and dumper+"_bkp2" are used. |
1262 |
|
if the directory does not exist it is created. If dumper is not present a unique directory within the current |
1263 |
|
working directory is used. |
1264 |
|
""" |
1265 |
|
self.__dump_step=dump_time |
1266 |
|
self.__dump_time=dump_step |
1267 |
|
self.__counter=0 |
1268 |
|
self.__saveMarker() |
1269 |
|
if dumper == None: |
1270 |
|
self.__dumper="restart"+str(os.getpid()) |
1271 |
|
else: |
1272 |
|
self.__dumper=dumper |
1273 |
|
self.__dumper_bkp=self.__dumper+"_bkp" |
1274 |
|
self.__dumper_bkp2=self.__dumper+"_bkp2" |
1275 |
|
self.__current_dumper=None |
1276 |
|
def __saveMarker(self): |
1277 |
|
self.__last_restart_time=time.time() |
1278 |
|
self.__last_restart_counter=self.__counter |
1279 |
|
def getCurrentDumper(self): |
1280 |
|
""" |
1281 |
|
returns the name of the currently used dumper |
1282 |
|
""" |
1283 |
|
return self.__current_dumper |
1284 |
|
def doDump(self): |
1285 |
|
""" |
1286 |
|
returns true the restart should be dumped. use C{getNewDumper} to get the directory name to be used. |
1287 |
|
""" |
1288 |
|
if self.__dump_step == None: |
1289 |
|
if self.__dump_step == None: |
1290 |
|
out = False |
1291 |
|
else: |
1292 |
|
out = (self.__dump_step + self.__last_restart_counter) <= self.__counter |
1293 |
|
else: |
1294 |
|
if dump_step == None: |
1295 |
|
out = (self.__last_restart_time + self.__dump_time) <= time.time() |
1296 |
|
else: |
1297 |
|
out = ( (self.__dump_step + self.__last_restart_counter) <= self.__counter) \ |
1298 |
|
or ( (self.__last_restart_time + self.__dump_time) <= time.time() ) |
1299 |
|
if out: self.__saveMarker() |
1300 |
|
self__counter+=1 |
1301 |
|
def getNewDumper(self): |
1302 |
|
""" |
1303 |
|
creates a new directory to be used for dumping and returns its name. |
1304 |
|
""" |
1305 |
|
if os.access(self.__dumper_bkp,os.F_OK): |
1306 |
|
if os.access(self.__dumper_bkp2, os.F_OK): |
1307 |
|
raise RunTimeError("please remove %s."%self.__dumper_bkp2) |
1308 |
|
try: |
1309 |
|
os.rename(self.__dumper_bkp, self.__dumper_bkp2) |
1310 |
|
except: |
1311 |
|
self.__current_dumper=self.__dumper |
1312 |
|
raise RunTimeError("renaming back-up directory %s failed. Use %s for restart."%(self.__dumper_bkp,self.__dumper)) |
1313 |
|
if os.access(self.__dumper,os.F_OK): |
1314 |
|
if os.access(self.__dumper_bkp, os.F_OK): |
1315 |
|
raise RunTimeError("please remove %s."%self.__dumper_bkp) |
1316 |
|
try: |
1317 |
|
os.rename(self.__dumper, self.__dumper_bkp) |
1318 |
|
except: |
1319 |
|
self.__current_dumper=self.__dumper_bkp2 |
1320 |
|
raise RunTimeError("moving directory %s to back-up failed. Use %s for restart."%(self.__dumper,self.__dumper_bkp2)) |
1321 |
|
try: |
1322 |
|
os.mkdir(self.__dumper) |
1323 |
|
except: |
1324 |
|
self.__current_dumper=self.__dumper_bkp |
1325 |
|
raise RunTimeError("creating a new restart directory %s failed. Use %s for restart."%(self.__dumper,self.__dumper_bkp)) |
1326 |
|
if os.access(self.__dumper_bkp2, os.F_OK): os.rmdir(self.__dumper_bkp2) |
1327 |
|
return self.getCurrentDumper() |
1328 |
|
|
1329 |
|
|
1330 |
# vim: expandtab shiftwidth=4: |
# vim: expandtab shiftwidth=4: |