1 |
# $Id:$ |
2 |
|
3 |
""" |
4 |
template for the Design which defines a regions and features |
5 |
for a mesh generator. |
6 |
|
7 |
@var __author__: name of author |
8 |
@var __copyright__: copyrights |
9 |
@var __license__: licence agreement |
10 |
@var __url__: url entry point on documentation |
11 |
@var __version__: version |
12 |
@var __date__: date of the version |
13 |
""" |
14 |
|
15 |
|
16 |
__author__="Lutz Gross, l.gross@uq.edu.au" |
17 |
__copyright__=""" Copyright (c) 2007 by ACcESS MNRF |
18 |
http://www.access.edu.au |
19 |
Primary Business: Queensland, Australia""" |
20 |
__license__="""Licensed under the Open Software License version 3.0 |
21 |
http://www.opensource.org/licenses/osl-3.0.php""" |
22 |
__url__="http://www.iservo.edu.au/esys/escript" |
23 |
__version__="$Revision:$" |
24 |
__date__="$Date:$" |
25 |
|
26 |
|
27 |
from primitives import Primitive, ReversePrimitive, PropertySet, Point, Manifold1D, Manifold2D, Manifold3D |
28 |
from xml.dom import minidom |
29 |
|
30 |
class TagMap(object): |
31 |
""" |
32 |
a class that allows to map tags to names |
33 |
|
34 |
tm=TagMap({5 : x }) |
35 |
tm.setMap(a=1,x=4) |
36 |
assert tm.getTags("a") == [ 1 ] |
37 |
assert tm.getTags("x") == [ 5, 4 ] |
38 |
assert tm.map(x=10., a=20.) == { 5 : 10, 4: 10, 1 : 20 } |
39 |
|
40 |
""" |
41 |
def __init__(self, map={}): |
42 |
""" |
43 |
initizlizes the mapping. map defines an initial mapping from tag to a name. |
44 |
""" |
45 |
for tag, name in map.items(): |
46 |
if not isinstance(tag, int): |
47 |
raise TypeError("tag needs to be int") |
48 |
if not isinstance(name, str): |
49 |
raise TypeError("name needs to be a str.") |
50 |
self.__map=map |
51 |
def setMap(self,**kwargs): |
52 |
""" |
53 |
set a new map where <name>=<tag> assigns the tag <tag> to name <name>. <tag> has to be integer. |
54 |
If <tag> has been assigned to a name before the mapping will be overwritten. Otherwise a new |
55 |
mapping <tag> -> <name> is set. Notice that a single name can be assigned to different tags. |
56 |
""" |
57 |
for name, tag in kwargs.items(): |
58 |
if not isinstance(tag, int): |
59 |
raise TypeError("tag needs to be int") |
60 |
self.__map[tag]=name |
61 |
def getTags(self,name=None): |
62 |
""" |
63 |
returns a list of the tags assigned to name. If name is not present a list of tags is returned. |
64 |
""" |
65 |
if name == None: |
66 |
out=self.__map.keys() |
67 |
else: |
68 |
out=[] |
69 |
for tag, arg in self.__map.items(): |
70 |
if arg == name: out.append(tag) |
71 |
return out |
72 |
def getName(self,tag=None): |
73 |
""" |
74 |
returns the name of a tag. If tag is not present a list of names is returned. |
75 |
""" |
76 |
if tag == None: |
77 |
return list(set(self.__map.values())) |
78 |
else: |
79 |
return self.__map[tag] |
80 |
|
81 |
def getMapping(self): |
82 |
""" |
83 |
returns a dictionary where the tags define the keys and the values the corresposnding names. |
84 |
""" |
85 |
return self.__map |
86 |
|
87 |
def map(self,default=0,**kwargs): |
88 |
""" |
89 |
returns a dictionary where the tags define the keys and the values give the values assigned to the tag via name |
90 |
and kwargs: |
91 |
|
92 |
tm=TagMap(x=5) |
93 |
tm.setMap(a=1,x=4) |
94 |
print tm.map(x=10., a=20.) |
95 |
{ 5 : 10, 4: 10, 1 : 20 } |
96 |
|
97 |
the default is used for tags which map onto name with unspecified values |
98 |
""" |
99 |
out={} |
100 |
for tag in self.__map: |
101 |
if kwargs.has_key(self.__map[tag]): |
102 |
out[tag]=kwargs[self.__map[tag]] |
103 |
else: |
104 |
out[tag]=default |
105 |
return out |
106 |
|
107 |
def insert(self,data,default=0,**kwargs): |
108 |
""" |
109 |
inserts values into the L{esys.escript.Data} object according to the given values assigned to the keywords. |
110 |
the default is used for tags which map onto name with unspecified values |
111 |
""" |
112 |
d=self.map(default=default,**kwargs) |
113 |
for t,v in d.items(): |
114 |
data.setTaggedValue(t,v) |
115 |
def toDOM(self,dom): |
116 |
""" |
117 |
adds object to dom |
118 |
""" |
119 |
tm=dom.createElement("TagMap") |
120 |
dom.appendChild(tm) |
121 |
for tag,name in self.getMapping().items(): |
122 |
item_dom=dom.createElement("map") |
123 |
tag_dom=dom.createElement("tag") |
124 |
name_dom=dom.createElement("name") |
125 |
tag_dom.appendChild(dom.createTextNode(str(tag))) |
126 |
name_dom.appendChild(dom.createTextNode(str(name))) |
127 |
item_dom.appendChild(tag_dom) |
128 |
item_dom.appendChild(name_dom) |
129 |
tm.appendChild(item_dom) |
130 |
return tm |
131 |
def fromDom(self,node): |
132 |
""" |
133 |
fills from dom node |
134 |
""" |
135 |
for node in node.childNodes: |
136 |
if isinstance(node, minidom.Element): |
137 |
if node.tagName == 'map': |
138 |
tag=int(node.getElementsByTagName("tag")[0].firstChild.nodeValue.strip()) |
139 |
name=str(node.getElementsByTagName("name")[0].firstChild.nodeValue.strip()) |
140 |
self.setMap(**{ name : tag }) |
141 |
return |
142 |
|
143 |
def fillFromXML(self,iostream): |
144 |
""" |
145 |
uses the xml file or string to set the mapping |
146 |
""" |
147 |
if isinstance(iostream,str): |
148 |
dom=minidom.parseString(iostream) |
149 |
else: |
150 |
dom=minidom.parse(iostream) |
151 |
root=dom.getElementsByTagName('ESys')[0] |
152 |
for node in root.childNodes: |
153 |
if isinstance(node, minidom.Element): |
154 |
if node.tagName == 'TagMap': |
155 |
self.fromDom(node) |
156 |
return |
157 |
|
158 |
|
159 |
|
160 |
def writeXML(self,iostream=None): |
161 |
""" |
162 |
writes XML serialization into the iostream or if not present returns the XML as string |
163 |
""" |
164 |
dom=minidom.Document() |
165 |
esys=dom.createElement('ESys') |
166 |
esys.appendChild(self.toDOM(dom)) |
167 |
dom.appendChild(esys) |
168 |
if iostream == None: |
169 |
return dom.toprettyxml() |
170 |
else: |
171 |
iostream.write(dom.toprettyxml()) |
172 |
|
173 |
class Design(object): |
174 |
""" |
175 |
template for a design which defines the input for a mesh generator |
176 |
""" |
177 |
def __init__(self,dim=3,element_size=1.,order=1,keep_files=False): |
178 |
""" |
179 |
initializes a design |
180 |
|
181 |
@param dim: patial dimension |
182 |
@param element_size: global element size |
183 |
@param order: element order |
184 |
@param keep_files: flag to keep work files. |
185 |
""" |
186 |
self.clearItems() |
187 |
self.setElementSize(element_size) |
188 |
self.setDim(dim) |
189 |
self.setElementOrder(order) |
190 |
if keep_files: |
191 |
self.setKeepFilesOn() |
192 |
else: |
193 |
self.setKeepFilesOff() |
194 |
def setDim(self,dim=3): |
195 |
""" |
196 |
sets the spatial dimension |
197 |
""" |
198 |
if not dim in [1,2,3]: |
199 |
raise ValueError("only dimension 1, 2, 3 are supported.") |
200 |
self.__dim=dim |
201 |
def getDim(self,dim=3): |
202 |
""" |
203 |
returns the spatial dimension |
204 |
""" |
205 |
return self.__dim |
206 |
def setElementOrder(self,order=1): |
207 |
""" |
208 |
sets the element order |
209 |
""" |
210 |
if not order in [1,2]: |
211 |
raise ValueError("only element orser 1 or 2 is supported.") |
212 |
self.__order=order |
213 |
|
214 |
def getElementOrder(self): |
215 |
""" |
216 |
returns the element order |
217 |
""" |
218 |
return self.__order |
219 |
|
220 |
def setElementSize(self,element_size=1.): |
221 |
""" |
222 |
set the global element size. |
223 |
""" |
224 |
if element_size<=0.: |
225 |
raise ValueError("element size needs to be positive.") |
226 |
self.__element_size=element_size |
227 |
|
228 |
def getElementSize(self): |
229 |
""" |
230 |
returns the global element size. |
231 |
""" |
232 |
return self.__element_size |
233 |
|
234 |
def setKeepFilesOn(self): |
235 |
""" |
236 |
work files are kept at the end of the generation |
237 |
""" |
238 |
self.__keep_files=True |
239 |
def setKeepFilesOff(self): |
240 |
""" |
241 |
work files are deleted at the end of the generation |
242 |
""" |
243 |
self.__keep_files=False |
244 |
def keepFiles(self): |
245 |
""" |
246 |
returns True if work files are kept |
247 |
""" |
248 |
return self.__keep_files |
249 |
def addItems(self,*items): |
250 |
""" |
251 |
adds items to the design |
252 |
""" |
253 |
for i in range(len(items)): |
254 |
if not isinstance(items[i],(Primitive, ReversePrimitive)): |
255 |
raise TypeError("%s-th argument is not a Primitive object"%i) |
256 |
for i in items: |
257 |
self.__items.append(i) |
258 |
def getItems(self): |
259 |
""" |
260 |
returns a list of the items used in the design |
261 |
""" |
262 |
return self.__items |
263 |
def clearItems(self): |
264 |
""" |
265 |
resets the items in design |
266 |
""" |
267 |
self.__items=[] |
268 |
def getAllPrimitives(self): |
269 |
""" |
270 |
returns a list of all primitives used to create the design. |
271 |
each primitve appears once. The primitives are ordered by their |
272 |
order of generation |
273 |
""" |
274 |
prims=[] |
275 |
for i in self.getItems(): |
276 |
for p in i.getPrimitives(): |
277 |
if not p in prims: prims.append(p) |
278 |
prims.sort() |
279 |
return prims |
280 |
|
281 |
def setOptions(self,**kwargs): |
282 |
""" |
283 |
sets options of the mesh generator |
284 |
|
285 |
@note: this method is typically overwritten by a particular Design implementation |
286 |
""" |
287 |
pass |
288 |
def getMeshHandler(self): |
289 |
""" |
290 |
returns a handle to a mesh meshing the design |
291 |
|
292 |
@note: this method has to be overwritten by a particular Design implementation |
293 |
""" |
294 |
raise NotImplementedError() |
295 |
|
296 |
def getTagMap(self): |
297 |
""" |
298 |
returns a L{TagMap} to map the names of L{PropertySet}s to tags |
299 |
""" |
300 |
m={} |
301 |
for p in self.getAllPrimitives(): |
302 |
if isinstance(p, PropertySet): m[ p.getTag() ] = p.getName() |
303 |
return TagMap(m) |