GooseFEM 1.4.1.dev2+g78f16df
Loading...
Searching...
No Matches
MeshTri3.h
Go to the documentation of this file.
1
9#ifndef GOOSEFEM_MESHTRI3_H
10#define GOOSEFEM_MESHTRI3_H
11
12#include "Mesh.h"
13#include "config.h"
14
15namespace GooseFEM {
16namespace Mesh {
17
21namespace Tri3 {
22
26class Regular : public RegularBase2d<Regular> {
27public:
35 Regular(size_t nelx, size_t nely, double h = 1.0)
36 {
37 m_h = h;
38 m_nelx = nelx;
39 m_nely = nely;
40 m_ndim = 2;
41 m_nne = 3;
42
43 GOOSEFEM_ASSERT(m_nelx >= 1);
44 GOOSEFEM_ASSERT(m_nely >= 1);
45
46 m_nnode = (m_nelx + 1) * (m_nely + 1);
47 m_nelem = m_nelx * m_nely * 2;
48 }
49
50private:
51 friend class RegularBase<Regular>;
52 friend class RegularBase2d<Regular>;
53
54 size_t nelx_impl() const
55 {
56 return m_nelx;
57 }
58
59 size_t nely_impl() const
60 {
61 return m_nely;
62 }
63
64 ElementType elementType_impl() const
65 {
66 return ElementType::Tri3;
67 }
68
69 array_type::tensor<double, 2> coor_impl() const
70 {
71 array_type::tensor<double, 2> ret = xt::empty<double>({m_nnode, m_ndim});
72
73 array_type::tensor<double, 1> x =
74 xt::linspace<double>(0.0, m_h * static_cast<double>(m_nelx), m_nelx + 1);
75 array_type::tensor<double, 1> y =
76 xt::linspace<double>(0.0, m_h * static_cast<double>(m_nely), m_nely + 1);
77
78 size_t inode = 0;
79
80 for (size_t iy = 0; iy < m_nely + 1; ++iy) {
81 for (size_t ix = 0; ix < m_nelx + 1; ++ix) {
82 ret(inode, 0) = x(ix);
83 ret(inode, 1) = y(iy);
84 ++inode;
85 }
86 }
87
88 return ret;
89 }
90
91 array_type::tensor<size_t, 2> conn_impl() const
92 {
93 array_type::tensor<size_t, 2> ret = xt::empty<size_t>({m_nelem, m_nne});
94
95 size_t ielem = 0;
96
97 for (size_t iy = 0; iy < m_nely; ++iy) {
98 for (size_t ix = 0; ix < m_nelx; ++ix) {
99 ret(ielem, 0) = (iy) * (m_nelx + 1) + (ix);
100 ret(ielem, 1) = (iy) * (m_nelx + 1) + (ix + 1);
101 ret(ielem, 2) = (iy + 1) * (m_nelx + 1) + (ix);
102 ++ielem;
103 ret(ielem, 0) = (iy) * (m_nelx + 1) + (ix + 1);
104 ret(ielem, 1) = (iy + 1) * (m_nelx + 1) + (ix + 1);
105 ret(ielem, 2) = (iy + 1) * (m_nelx + 1) + (ix);
106 ++ielem;
107 }
108 }
109
110 return ret;
111 }
112
113 array_type::tensor<size_t, 1> nodesBottomEdge_impl() const
114 {
115 array_type::tensor<size_t, 1> ret = xt::empty<size_t>({m_nelx + 1});
116
117 for (size_t ix = 0; ix < m_nelx + 1; ++ix) {
118 ret(ix) = ix;
119 }
120
121 return ret;
122 }
123
124 array_type::tensor<size_t, 1> nodesTopEdge_impl() const
125 {
126 array_type::tensor<size_t, 1> ret = xt::empty<size_t>({m_nelx + 1});
127
128 for (size_t ix = 0; ix < m_nelx + 1; ++ix) {
129 ret(ix) = ix + m_nely * (m_nelx + 1);
130 }
131
132 return ret;
133 }
134
135 array_type::tensor<size_t, 1> nodesLeftEdge_impl() const
136 {
137 array_type::tensor<size_t, 1> ret = xt::empty<size_t>({m_nely + 1});
138
139 for (size_t iy = 0; iy < m_nely + 1; ++iy) {
140 ret(iy) = iy * (m_nelx + 1);
141 }
142
143 return ret;
144 }
145
146 array_type::tensor<size_t, 1> nodesRightEdge_impl() const
147 {
148 array_type::tensor<size_t, 1> ret = xt::empty<size_t>({m_nely + 1});
149
150 for (size_t iy = 0; iy < m_nely + 1; ++iy) {
151 ret(iy) = iy * (m_nelx + 1) + m_nelx;
152 }
153
154 return ret;
155 }
156
157 array_type::tensor<size_t, 1> nodesBottomOpenEdge_impl() const
158 {
159 array_type::tensor<size_t, 1> ret = xt::empty<size_t>({m_nelx - 1});
160
161 for (size_t ix = 1; ix < m_nelx; ++ix) {
162 ret(ix - 1) = ix;
163 }
164
165 return ret;
166 }
167
168 array_type::tensor<size_t, 1> nodesTopOpenEdge_impl() const
169 {
170 array_type::tensor<size_t, 1> ret = xt::empty<size_t>({m_nelx - 1});
171
172 for (size_t ix = 1; ix < m_nelx; ++ix) {
173 ret(ix - 1) = ix + m_nely * (m_nelx + 1);
174 }
175
176 return ret;
177 }
178
179 array_type::tensor<size_t, 1> nodesLeftOpenEdge_impl() const
180 {
181 array_type::tensor<size_t, 1> ret = xt::empty<size_t>({m_nely - 1});
182
183 for (size_t iy = 1; iy < m_nely; ++iy) {
184 ret(iy - 1) = iy * (m_nelx + 1);
185 }
186
187 return ret;
188 }
189
190 array_type::tensor<size_t, 1> nodesRightOpenEdge_impl() const
191 {
192 array_type::tensor<size_t, 1> ret = xt::empty<size_t>({m_nely - 1});
193
194 for (size_t iy = 1; iy < m_nely; ++iy) {
195 ret(iy - 1) = iy * (m_nelx + 1) + m_nelx;
196 }
197
198 return ret;
199 }
200
201 size_t nodesBottomLeftCorner_impl() const
202 {
203 return 0;
204 }
205
206 size_t nodesBottomRightCorner_impl() const
207 {
208 return m_nelx;
209 }
210
211 size_t nodesTopLeftCorner_impl() const
212 {
213 return m_nely * (m_nelx + 1);
214 }
215
216 size_t nodesTopRightCorner_impl() const
217 {
218 return m_nely * (m_nelx + 1) + m_nelx;
219 }
220
221 double m_h;
222 size_t m_nelx;
223 size_t m_nely;
224 size_t m_nelem;
225 size_t m_nnode;
226 size_t m_nne;
227 size_t m_ndim;
228};
229
230// read / set the orientation (-1/+1) of all triangles
231
239inline array_type::tensor<int, 1>
241{
242 GOOSEFEM_ASSERT(conn.shape(1) == 3ul);
243 GOOSEFEM_ASSERT(coor.shape(1) == 2ul);
244
245 double k;
246 size_t nelem = conn.shape(0);
247
248 array_type::tensor<int, 1> ret = xt::empty<int>({nelem});
249
250 for (size_t ielem = 0; ielem < nelem; ++ielem) {
251 auto v1 =
252 xt::view(coor, conn(ielem, 0), xt::all()) - xt::view(coor, conn(ielem, 1), xt::all());
253 auto v2 =
254 xt::view(coor, conn(ielem, 2), xt::all()) - xt::view(coor, conn(ielem, 1), xt::all());
255
256 k = v1(0) * v2(1) - v2(0) * v1(1);
257
258 if (k < 0) {
259 ret(ielem) = -1;
260 }
261 else {
262 ret(ielem) = +1;
263 }
264 }
265
266 return ret;
267}
268
283 int orientation = -1
284)
285{
286 GOOSEFEM_ASSERT(conn.shape(1) == 3ul);
287 GOOSEFEM_ASSERT(coor.shape(1) == 2ul);
288 GOOSEFEM_ASSERT(conn.shape(0) == val.size());
290
291 UNUSED(coor);
292
293 size_t nelem = conn.shape(0);
295
296 for (size_t ielem = 0; ielem < nelem; ++ielem) {
297 if ((orientation == -1 && val(ielem) > 0) || (orientation == +1 && val(ielem) < 0)) {
298 std::swap(ret(ielem, 2), ret(ielem, 1));
299 }
300 }
301
302 return ret;
303}
304
316 int orientation = -1
317)
318{
319 GOOSEFEM_ASSERT(conn.shape(1) == 3ul);
320 GOOSEFEM_ASSERT(coor.shape(1) == 2ul);
322
324
325 return setOrientation(coor, conn, val, orientation);
326}
327
328} // namespace Tri3
329} // namespace Mesh
330} // namespace GooseFEM
331
332#endif
Generic mesh operations.
CRTP base class for regular meshes in 2d.
Definition Mesh.h:339
CRTP base class for regular meshes.
Definition Mesh.h:181
auto nely() const
Number of elements in y-direction == height of the mesh, in units of h,.
Definition Mesh.h:237
auto h() const
Linear edge size of one 'block'.
Definition Mesh.h:246
auto nelx() const
Number of elements in x-direction == width of the mesh in units of h.
Definition Mesh.h:228
Regular grid of squares, with each square cut into two triangular elements.
Definition MeshTri3.h:26
Regular(size_t nelx, size_t nely, double h=1.0)
Constructor.
Definition MeshTri3.h:35
Basic configuration:
#define GOOSEFEM_ASSERT(expr)
All assertions are implementation as::
Definition config.h:97
array_type::tensor< size_t, 2 > setOrientation(const array_type::tensor< double, 2 > &coor, const array_type::tensor< size_t, 2 > &conn, const array_type::tensor< int, 1 > &val, int orientation=-1)
Set the orientation of a mesh of triangular elements of type ElementType::Tri3.
Definition MeshTri3.h:279
array_type::tensor< int, 1 > getOrientation(const array_type::tensor< double, 2 > &coor, const array_type::tensor< size_t, 2 > &conn)
Read the orientation of a mesh of triangular elements of type ElementType::Tri3.
Definition MeshTri3.h:240
ElementType
Enumerator for element-types.
Definition Mesh.h:31
@ Tri3
Triangle: 3-noded element in 2-d.
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Definition config.h:177
Toolbox to perform finite element computations.
Definition Allocate.h:14
auto AsTensor(const T &arg, const S &shape)
"Broadcast" a scalar stored in an array (e.g.
Definition Allocate.h:167