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