-
Notifications
You must be signed in to change notification settings - Fork 2
/
micromesh.py
110 lines (90 loc) · 3.4 KB
/
micromesh.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
# Copyright 2017 Chris Richardson ([email protected])
""" A super simple library for low volume two-dimensional unstructured meshes.
Meshes are stored as python dicts containing 'geometry', 'topology',
'data', and can be read from a URL pointing to a text-based XDMF file """
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy
def get(url):
""" Read a mesh in XDMF XML format (not HDF5) from a URL"""
try:
import requests
import xml.etree.ElementTree as ET
except ImportError:
raise("Missing required library")
r = requests.get(url)
if r.status_code != 200:
raise IOError("Cannot read from URL")
et = ET.fromstring(r.text)
assert(et.tag == 'Xdmf')
assert(et[0].tag == 'Domain')
assert(et[0][0].tag == 'Grid')
grid = et[0][0]
# Get topology array
topology = grid.find('Topology')
assert(topology.attrib['TopologyType'] == 'Triangle')
tdims = numpy.fromstring(topology[0].attrib['Dimensions'], sep=' ', dtype='int')
nptopo = numpy.fromstring(topology[0].text, sep=' ', dtype='int').reshape(tdims)
# Get geometry array
geometry = grid.find('Geometry')
assert(geometry.attrib['GeometryType'] == 'XY')
gdims = numpy.fromstring(geometry[0].attrib['Dimensions'], sep=' ', dtype='int')
npgeom = numpy.fromstring(geometry[0].text, sep=' ', dtype='float').reshape(gdims)
# Find all attributes and put them in a list
attrlist = grid.findall('Attribute')
data_all = []
for attr in attrlist:
adims = numpy.fromstring(attr[0].attrib['Dimensions'], sep=' ', dtype='int')
npattr = attr.attrib
npattr['value'] = numpy.fromstring(attr[0].text, sep=' ', dtype='int')
data_all.append(npattr)
mesh = {'geometry':npgeom, 'topology':nptopo, 'data':data_all}
return mesh
def rectangle_mesh(nx, ny):
"""Make a rectangular mesh of triangles, nx by ny."""
assert(isinstance(nx, int))
assert(isinstance(ny, int))
c = 0
geometry = zeros((nx*ny, 2), dtype='float')
for i in range(nx):
for j in range(ny):
geometry[c] = [float(i/(nx-1)), float(j/(ny-1))]
c += 1
ntri = (nx - 1)*(ny - 1)*2
topology = zeros((ntri, 3), dtype='int')
c = 0
for i in range(nx - 1):
for j in range(ny - 1):
ij = j + i*ny
topology[c] = [ij, ij+ny, ij+ny+1]
topology[c + 1] = [ij+1, ij, ij+ny+1]
c += 2
mesh = {'geometry':geometry, 'topology':topology}
return mesh
def plot(mesh, *args, **kwargs):
""" Plot a mesh with matplotlib, possibly with associated data,
which may be associated with points or triangles """
# FIXME: check keys of mesh contain geometry and topology
geom, topo = mesh['geometry'], mesh['topology']
x = geom[:,0]
y = geom[:,1]
plt.gca(aspect='equal')
if args:
data = args[0]
if len(data)==len(geom):
plt.tricontourf(x, y, topo, data, 40, **kwargs)
elif len(data)==len(topo):
tr = tri.Triangulation(x, y, topo)
plt.tripcolor(tr, data, **kwargs)
else:
raise RuntimeError("Data is wrong length")
plt.triplot(x, y, topo, color='k', alpha=0.5)
xmax = x.max()
xmin = x.min()
ymax = y.max()
ymin = y.min()
dx = 0.1*(xmax - xmin)
dy = 0.1*(ymax - ymin)
plt.xlim(xmin-dx, xmax+dx)
plt.ylim(ymin-dy, ymax+dy)
return