/
mesh.py
181 lines (144 loc) · 6.68 KB
/
mesh.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# $Id$
##
## This file is part of pyFormex 0.7.3 Release Tue Dec 30 20:45:35 2008
## pyFormex is a tool for generating, manipulating and transforming 3D
## geometrical models by sequences of mathematical operations.
## Website: http://pyformex.berlios.de/
## Copyright (C) Benedict Verhegghe (bverheg@users.berlios.de)
## Distributed under the GNU General Public License version 3 or later.
##
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
##
"""Mesh representation of geometrical data.
A Mesh representation describes geometrical entities by a tuple of
(coords,elems), where coords is an array with coordinates of points
and elems is an array describing the geometrical entities by a list of
point numbers.
On large data sets, this model can be more efficient then the Formex model,
both in memory and cpu usage, but it does not allow the simple geometry
creation functions of the Formex.
"""
from coords import *
######################## Mesh geometry model ##########################
class Mesh(Dict):
"""A class representing (discrete) geometrical entities.
The Mesh representation describes geometrical entities by a tuple of
(coords,elems), where coords is an array with coordinates of points
and elems is an array describing the geometrical entities by a list of
point numbers.
coords is a (npoints,3) array of float values, each line of which
represents a single point in space, addresses by its row index.
elems is a (nelems,nplex) array of integer values, such that each row
describes a single geometrical entity, defined by the nplex points
defined by rows of coords with indices equal to to values in elems.
By default all geometrical entities are of the same plexitude.
It is possible to relax this requirement and allow the inclusion of
elements with a lower plexitude by setting some vertex indices to a
negative value.
Besides the geometrical data, the object can also hold an array of
node and element property numbers. These could e.g. be used to give
the nodes/elements another numbering scheme than the internal one.
"""
def __init__(self,coords,elems,nprop=None,eprop=None,strict=True):
"""Create new mesh geometry from given coords and elems arrays.
This will check that coords and elems arrays have proper shape
and data type, and that the numbers in elems are within the row
range of the coords array.
The model can have node and element property numbers.
"""
self.coords = checkArray(coords,shape=(-1,3),kind='f')
self.elems = checkArray(elems,shape=(-1,-1),kind='i')
def nnodes(self):
return self.nodes.shape[0]
def splitElems(self,set):
"""Splits a set of element numbers over the element groups.
Returns two lists of element sets, the first in global numbering,
the second in group numbering.
Each item contains the element numbers from the given set that
belong to the corresponding group.
"""
set = unique1d(set)
split = []
n = 0
for e in self.celems[1:]:
i = set.searchsorted(e)
split.append(set[n:i])
n = i
return split,[ asarray(s) - ofs for s,ofs in zip(split,self.celems) ]
def elemNrs(group,set):
"""Return the global element numbers for elements set in group"""
return self.celems[group] + set
def getElems(self,sets):
"""Return the definitions of the elements in sets.
sets should be a list of element sets with length equal to the
number of element groups. Each set contains element numbers local
to that group.
As the elements can be grouped according to plexitude,
this function returns a list of element arrays matching
the element groups in self.elems. Some of these arrays may
be empty.
It also provide the global and group element numbers, since they
had to be calculated anyway.
"""
return [ e[s] for e,s in zip(self.elems,sets) ]
def renumber(self,old=None,new=None):
"""Renumber a set of nodes.
old and new are equally sized lists with unique node numbers, each
smaller that the number of nodes in the model.
The old numbers will be renumbered to the new numbers.
If one of the lists is None, a range with the length of the
other is used.
If the lists are shorter than the number of nodes, the remaining
nodes will be numbered in an unspecified order.
If both lists are None, the nodes are renumbered randomly.
This function returns a tuple (old,new) with the full renumbering
vectors used. The first gives the old node numbers of the current
numbers, the second gives the new numbers cooresponding with the
old ones.
"""
nnodes = self.nnodes()
if old is None and new is None:
old = unique1d(random.randint(0,nnodes-1,nnodes))
new = unique1d(random.randint(0,nnodes-1,nnodes))
nn = max(old.size,new.size)
old = old[:nn]
new = new[:nn]
elif old is None:
new = asarray(new).reshape(-1)
checkUniqueNumbers(new,0,nnodes)
old = arange(new.size)
elif new is None:
old = asarray(old).reshape(-1)
checkUniqueNumbers(old,0,nnodes)
new = arange(old.size)
all = arange(nnodes)
old = concatenate([old,setdiff1d(all,old)])
new = concatenate([new,setdiff1d(all,new)])
print "old:\n",old
print "new:\n",new
oldnew = old[new]
newold = argsort(oldnew)
print "oldnew:\n",oldnew
print "newold:\n",newold
self.nodes = self.nodes[oldnew]
self.elems = [ newold[e] for e in self.elems ]
return oldnew,newold
def mergedModel(*args):
"""Returns the fe Model obtained from merging individual models.
The input arguments are (nodes,elems) tuples.
The return value is a merged fe Model.
"""
return Model(*mergeModels(args))
# End