/[escript]/trunk/pycad/py_src/design.py
ViewVC logotype

Annotation of /trunk/pycad/py_src/design.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6939 - (hide annotations)
Mon Jan 20 03:37:18 2020 UTC (3 years, 2 months ago) by uqaeller
File MIME type: text/x-python
File size: 13905 byte(s)
Updated the copyright header.


1 ksteube 1809
2 jfenwick 3981 ##############################################################################
3 ksteube 1312 #
4 uqaeller 6939 # Copyright (c) 2003-2020 by The University of Queensland
5 jfenwick 3981 # http://www.uq.edu.au
6 ksteube 1312 #
7 ksteube 1809 # Primary Business: Queensland, Australia
8 jfenwick 6112 # Licensed under the Apache License, version 2.0
9     # http://www.apache.org/licenses/LICENSE-2.0
10 ksteube 1312 #
11 jfenwick 3981 # Development until 2012 by Earth Systems Science Computational Center (ESSCC)
12 jfenwick 4657 # Development 2012-2013 by School of Earth Sciences
13     # Development from 2014 by Centre for Geoscience Computing (GeoComp)
14 uqaeller 6939 # Development from 2019 by School of Earth and Environmental Sciences
15 jfenwick 3981 #
16     ##############################################################################
17 gross 899
18 sshaw 5706 from __future__ import print_function, division
19 sshaw 5571
20 uqaeller 6939 __copyright__="""Copyright (c) 2003-2020 by The University of Queensland
21 jfenwick 3981 http://www.uq.edu.au
22 ksteube 1809 Primary Business: Queensland, Australia"""
23 jfenwick 6112 __license__="""Licensed under the Apache License, version 2.0
24     http://www.apache.org/licenses/LICENSE-2.0"""
25 jfenwick 2344 __url__="https://launchpad.net/escript-finley"
26 ksteube 1809
27 gross 899 """
28 caltinay 2180 Template for the Design which defines regions and features
29 gross 932 for a mesh generator.
30 gross 899
31 jfenwick 2625 :var __author__: name of author
32     :var __copyright__: copyrights
33     :var __license__: licence agreement
34     :var __url__: url entry point on documentation
35     :var __version__: version
36     :var __date__: date of the version
37 gross 899 """
38    
39     __author__="Lutz Gross, l.gross@uq.edu.au"
40    
41 jfenwick 3774 from .primitives import Primitive, ReversePrimitive, PropertySet, Point, Manifold1D, Manifold2D, Manifold3D
42 gross 944 from xml.dom import minidom
43 gross 2720 import tempfile, os
44 gross 931
45 gross 944 class TagMap(object):
46     """
47 caltinay 2180 A class that allows to map tags to names.
48 gross 944
49 caltinay 2180 Example::
50    
51     tm=TagMap({5 : x })
52     tm.setMap(a=1,x=4)
53     assert tm.getTags("a") == [ 1 ]
54     assert tm.getTags("x") == [ 5, 4 ]
55     assert tm.map(x=10., a=20.) == { 5 : 10, 4: 10, 1 : 20 }
56    
57 gross 944 """
58 gross 1052 def __init__(self, mapping={}):
59 gross 944 """
60 jfenwick 2625 Initializes the mapping. ``mapping`` defines an initial mapping from tag
61 caltinay 2180 to a name.
62 gross 944 """
63 gross 1052 self.__mapping={}
64 sshaw 5641 for tag, name in sorted(mapping.items(), key=lambda x: x[1]):
65 gross 944 if not isinstance(tag, int):
66 caltinay 2180 raise TypeError("tag needs to be an int")
67 gross 944 if not isinstance(name, str):
68     raise TypeError("name needs to be a str.")
69 gross 1052 self.__mapping[tag]=name
70 caltinay 2180
71 gross 944 def setMap(self,**kwargs):
72     """
73 caltinay 2180 Sets a new map where <name>=<tag> assigns the tag <tag> to name <name>.
74     <tag> has to be an integer. If <tag> has been assigned to a name before
75     the mapping will be overwritten. Otherwise a new mapping <tag> -> <name>
76     is set. Notice that a single name can be assigned to different tags.
77 gross 944 """
78 sshaw 5641 for name, tag in sorted(kwargs.items(), key=lambda x: x[0]):
79 gross 944 if not isinstance(tag, int):
80 caltinay 2180 raise TypeError("tag needs to be an int")
81 gross 1052 self.__mapping[tag]=name
82 caltinay 2180
83 gross 944 def getTags(self,name=None):
84     """
85 jfenwick 2625 Returns a list of the tags assigned to ``name``. If name is not present
86 caltinay 2180 a list of all tags is returned.
87 gross 944 """
88     if name == None:
89 sshaw 5641 out=sorted(self.__mapping.keys())
90 gross 944 else:
91     out=[]
92 sshaw 5641 for tag, arg in sorted(self.__mapping.items(), key=lambda x: x[0]):
93 gross 944 if arg == name: out.append(tag)
94     return out
95 caltinay 2180
96 gross 999 def getName(self,tag=None):
97 gross 944 """
98 jfenwick 2625 Returns the name of a tag. If ``tag`` is not present a list of all names
99 caltinay 2180 is returned.
100 gross 944 """
101 gross 999 if tag == None:
102 sshaw 5641 return sorted(list(set(self.__mapping.values())))
103 gross 999 else:
104 gross 1052 return self.__mapping[tag]
105 gross 997
106 gross 944 def getMapping(self):
107     """
108 caltinay 2180 Returns a dictionary where the tags define the keys and the values the
109     corresponding names.
110 gross 944 """
111 gross 1052 return self.__mapping
112 gross 997
113 gross 944 def map(self,default=0,**kwargs):
114     """
115 caltinay 2180 Returns a dictionary where the tags define the keys and the values give
116     the values assigned to the tag via name and kwargs::
117 gross 944
118 caltinay 2180 tm=TagMap(x=5)
119     tm.setMap(a=1,x=4)
120     print tm.map(x=10., a=20.)
121     { 5 : 10, 4: 10, 1 : 20 }
122    
123     The default is used for tags which map onto name with unspecified
124     values.
125 gross 944 """
126     out={}
127 gross 1052 for tag in self.__mapping:
128 jfenwick 3774 if self.__mapping[tag] in kwargs:
129 gross 1052 out[tag]=kwargs[self.__mapping[tag]]
130 gross 944 else:
131     out[tag]=default
132     return out
133    
134     def insert(self,data,default=0,**kwargs):
135     """
136 jfenwick 2625 Inserts values into the `esys.escript.Data` object according to the
137 caltinay 2180 given values assigned to the keywords. The default is used for tags
138     which map onto name with unspecified values.
139 gross 944 """
140     d=self.map(default=default,**kwargs)
141 sshaw 5641 for t,v in sorted(d.items(), key=lambda x: x[0]):
142 gross 944 data.setTaggedValue(t,v)
143 caltinay 2180
144 gross 1044 def passToDomain(self,domain):
145     """
146 jfenwick 2625 Passes the tag map to the `esys.escript.Domain` ``domain``.
147 gross 1044 """
148 sshaw 5641 for tag, name in sorted(self.__mapping.items(), key=lambda x: x[1]):
149 jfenwick 3774 print("Tag",name, "is mapped to id ", tag)
150 gross 1044 domain.setTagMap(name,tag)
151 caltinay 2180
152 gross 944 def toDOM(self,dom):
153     """
154 jfenwick 2625 Adds object to ``dom``.
155 gross 944 """
156     tm=dom.createElement("TagMap")
157     dom.appendChild(tm)
158 sshaw 5641 for tag,name in sorted(self.getMapping().items(), key=lambda x: x[1]):
159 gross 944 item_dom=dom.createElement("map")
160     tag_dom=dom.createElement("tag")
161     name_dom=dom.createElement("name")
162     tag_dom.appendChild(dom.createTextNode(str(tag)))
163     name_dom.appendChild(dom.createTextNode(str(name)))
164     item_dom.appendChild(tag_dom)
165     item_dom.appendChild(name_dom)
166     tm.appendChild(item_dom)
167     return tm
168 caltinay 2180
169 gross 944 def fromDom(self,node):
170     """
171 jfenwick 2625 Fills names and tags from dom ``node``.
172 gross 944 """
173     for node in node.childNodes:
174     if isinstance(node, minidom.Element):
175     if node.tagName == 'map':
176     tag=int(node.getElementsByTagName("tag")[0].firstChild.nodeValue.strip())
177     name=str(node.getElementsByTagName("name")[0].firstChild.nodeValue.strip())
178     self.setMap(**{ name : tag })
179     return
180    
181 gross 999 def fillFromXML(self,iostream):
182 gross 944 """
183 caltinay 2180 Uses the XML file or string to set the mapping.
184 gross 944 """
185 gross 999 if isinstance(iostream,str):
186     dom=minidom.parseString(iostream)
187 gross 944 else:
188 gross 999 dom=minidom.parse(iostream)
189 gross 944 root=dom.getElementsByTagName('ESys')[0]
190     for node in root.childNodes:
191     if isinstance(node, minidom.Element):
192     if node.tagName == 'TagMap':
193     self.fromDom(node)
194     return
195    
196     def writeXML(self,iostream=None):
197     """
198 jfenwick 2625 Serializes self as XML into ``iostream`` or if not present returns the
199 caltinay 2180 XML as string.
200 gross 944 """
201     dom=minidom.Document()
202     esys=dom.createElement('ESys')
203     esys.appendChild(self.toDOM(dom))
204     dom.appendChild(esys)
205     if iostream == None:
206     return dom.toprettyxml()
207     else:
208     iostream.write(dom.toprettyxml())
209 caltinay 2180
210 sshaw 4559 class AbstractDesign(object):
211 gross 899 """
212 caltinay 2180 Template for a design which defines the input for a mesh generator.
213 gross 2717
214 jfenwick 6647 :note: class variable GMSH - `gmsh <http://www.geuz.org/gmsh/>`_ file format
215     :note: class variable IDEAS - `I_DEAS <http://www.plm.automation.siemens.com/en_us/products/nx/>`_ universal file format
216     :note: class variable VRML - `VRML <http://www.w3.org/MarkUp/VRML/>`_ file format
217     :note: class variable STL - `STL <http://en.wikipedia.org/wiki/STL_(file_format)>`_ file format
218     :note: class variable NASTRAN - `Nastran <http://simcompanion.mscsoftware.com/infocenter/index?page=content&channel=DOCUMENTATION>`_ bulk data format
219     :note: class variable MEDIT - `Medit <http://www-rocq.inria.fr/OpenFEM/Doc/>`_ file format
220     :note: class variable CGNS - `CGNS <http://cgns.sourceforge.net/>`_ file format
221     :note: class variable PLOT3D - `Plot3D <http://www.plot3d.net/>`_ file format
222     :note: class variable DIFFPACK- `Diffpack <http://www.diffpack.com/>`_ file format
223 gross 899 """
224 gross 2717 GMSH="msh"
225     IDEAS="unv"
226     VRML="vrml"
227     STL="stl"
228     NASTRAN="bdf"
229     MEDIT="mesh"
230     CGNS="cgns"
231     PLOT3D="p3d"
232     DIFFPACK="diff"
233 gross 932 def __init__(self,dim=3,element_size=1.,order=1,keep_files=False):
234 gross 899 """
235 caltinay 2180 Initializes a design.
236 gross 932
237 jfenwick 2625 :param dim: spatial dimension
238     :param element_size: global element size
239     :param order: element order
240     :param keep_files: flag to keep work files
241 caltinay 2180 """
242 gross 932 self.clearItems()
243     self.setElementSize(element_size)
244 gross 899 self.setDim(dim)
245 gross 932 self.setElementOrder(order)
246 gross 2717 self.setFileFormat()
247 gross 932 if keep_files:
248     self.setKeepFilesOn()
249     else:
250     self.setKeepFilesOff()
251 caltinay 3734 self.__mshname=""
252     self.setMeshFileName()
253 caltinay 2180
254 gross 899 def setDim(self,dim=3):
255 gross 932 """
256 caltinay 2180 Sets the spatial dimension.
257 gross 932 """
258 caltinay 2180 if not dim in [1,2,3]:
259 gross 932 raise ValueError("only dimension 1, 2, 3 are supported.")
260 gross 899 self.__dim=dim
261 caltinay 2180
262 gross 899 def getDim(self,dim=3):
263 gross 932 """
264 caltinay 2180 Returns the spatial dimension.
265 gross 932 """
266 gross 899 return self.__dim
267 caltinay 2180
268 gross 899 def setElementOrder(self,order=1):
269 gross 932 """
270 caltinay 2180 Sets the element order.
271 gross 932 """
272     if not order in [1,2]:
273 caltinay 2180 raise ValueError("only element order 1 or 2 is supported.")
274 gross 899 self.__order=order
275 caltinay 2180
276 gross 999 def getElementOrder(self):
277 gross 932 """
278 caltinay 2180 Returns the element order.
279 gross 932 """
280 gross 899 return self.__order
281 caltinay 2180
282 gross 999 def setElementSize(self,element_size=1.):
283 gross 932 """
284 caltinay 2180 Sets the global element size.
285 gross 932 """
286     if element_size<=0.:
287 gross 999 raise ValueError("element size needs to be positive.")
288 gross 932 self.__element_size=element_size
289 caltinay 2180
290 gross 999 def getElementSize(self):
291 gross 932 """
292 caltinay 2180 Returns the global element size.
293 gross 932 """
294     return self.__element_size
295 caltinay 2180
296 gross 932 def setKeepFilesOn(self):
297     """
298 caltinay 2180 Work files are kept at the end of the generation.
299 gross 932 """
300     self.__keep_files=True
301 caltinay 2180
302 gross 932 def setKeepFilesOff(self):
303     """
304 caltinay 2180 Work files are deleted at the end of the generation
305 gross 932 """
306     self.__keep_files=False
307 caltinay 2180
308 gross 932 def keepFiles(self):
309     """
310 caltinay 2180 Returns True if work files are kept, False otherwise.
311 gross 932 """
312     return self.__keep_files
313 caltinay 2180
314 gross 932 def addItems(self,*items):
315     """
316 caltinay 2180 Adds items to the design.
317 gross 932 """
318 gross 2683 new_items=[]
319 gross 932 for i in range(len(items)):
320     if not isinstance(items[i],(Primitive, ReversePrimitive)):
321     raise TypeError("%s-th argument is not a Primitive object"%i)
322 gross 2560 if isinstance(items[i],PropertySet):
323 gross 2683 q=items[i]
324     else:
325     q=PropertySet("__%s__"%(items[i].getID()), items[i])
326     for p in self.getAllPrimitives():
327     if isinstance(p, PropertySet):
328     if q.getName() == p.getName():
329     raise ValueError("Property set name %s is allready in use."%q.getName())
330     new_items.append(q)
331     for q in new_items: self.__items.append(q)
332 caltinay 2180
333 gross 932 def getItems(self):
334     """
335 caltinay 2180 Returns a list of the items used in the design.
336 gross 932 """
337 gross 899 return self.__items
338 caltinay 2180
339 gross 932 def clearItems(self):
340     """
341 caltinay 2180 Removes all items from the design.
342 gross 932 """
343     self.__items=[]
344 caltinay 2180
345 gross 932 def getAllPrimitives(self):
346     """
347 caltinay 2180 Returns a list of all primitives used to create the design.
348     Each primitive appears once. The primitives are ordered by their
349     order of generation.
350 gross 932 """
351 gross 1021 prims=[]
352 caltinay 2180 for i in self.getItems():
353 gross 1021 for p in i.getPrimitives():
354     if not p in prims: prims.append(p)
355 gross 932 prims.sort()
356     return prims
357 gross 901
358 gross 932 def setOptions(self,**kwargs):
359     """
360 caltinay 2180 Sets options of the mesh generator.
361 gross 932
362 jfenwick 2625 :note: this method is typically overwritten by a particular design
363 caltinay 2180 implementation.
364 gross 932 """
365     pass
366 gross 2717 def generate(self):
367     """
368     generate output file
369    
370     :note: this method may be overwritten by a particular design
371     implementation.
372     """
373     self.getMeshHandler()
374 caltinay 2180
375 gross 932 def getMeshHandler(self):
376     """
377 caltinay 2180 Returns a handle to a mesh meshing the design.
378 gross 932
379 jfenwick 2625 :note: this method has to be overwritten by a particular design
380 caltinay 2180 implementation.
381 gross 932 """
382     raise NotImplementedError()
383    
384 gross 997 def getTagMap(self):
385 gross 944 """
386 jfenwick 2625 Returns a `TagMap` to map the names of `PropertySet` s to tags.
387 gross 944 """
388     m={}
389     for p in self.getAllPrimitives():
390 gross 997 if isinstance(p, PropertySet): m[ p.getTag() ] = p.getName()
391 gross 944 return TagMap(m)
392 caltinay 2180
393 gross 2717 def setFileFormat(self,format='msh'):
394     """
395     Sets the file format to be used.
396    
397     :param format: format to be used. needs to be one of
398    
399     """
400     if not format in [ self.GMSH, self.IDEAS, self.VRML, self.STL, self.NASTRAN, self.MEDIT, self.CGNS, self.PLOT3D, self.DIFFPACK] :
401 jfenwick 3774 raise ValueError("unknown file format %s."%format)
402 gross 2717 self.__fileformat=format
403    
404     def getFileFormat(self):
405     """
406     Returns the file format
407     """
408     return self.__fileformat
409    
410     def setMeshFileName(self, name=None):
411     """
412     Sets the name for the mesh file. If no name is given a name is generated.
413     """
414 caltinay 3734 if self.__mshname:
415     os.unlink(self.__mshname)
416 gross 2717 if name == None:
417 caltinay 3782 self.__mshname_set=False
418 gross 2717 tmp_f_id=tempfile.mkstemp(suffix="."+self.getFileFormat())
419     self.__mshname=tmp_f_id[1]
420     os.close(tmp_f_id[0])
421     else:
422     self.__mshname=name
423 caltinay 3782 self.__mshname_set=True
424 gross 2717
425     def getMeshFileName(self):
426     """
427     Returns the name of the mesh file.
428     """
429     return self.__mshname
430    
431    
432    

  ViewVC Help
Powered by ViewVC 1.1.26