jacobi.template
Loading...
Searching...
No Matches
geom.cpp
Go to the documentation of this file.
1#undef CUTHILL_MCKEE
2// see: http://llvm.org/docs/CodingStandards.html#include-style
3#include "vdop.h"
4#ifdef CUTHILL_MCKEE
6#endif
7#include "geom.h"
8
9#include <algorithm>
10#include <array>
11#include <cassert>
12#include <ctime> // contains clock()
13#include <fstream>
14#include <iostream>
15#include <list>
16#include <string>
17#include <vector>
18
19using namespace std;
20
21Mesh::Mesh(int ndim, int nvert_e, int ndof_e, int nedge_e)
22 : _nelem(0), _nvert_e(nvert_e), _ndof_e(ndof_e), _nnode(0), _ndim(ndim), _ia(0), _xc(0),
23 _bedges(0), _sdedges(0),
24 _nedge(0), _nedge_e(nedge_e), _edges(0), _ea(), _ebedges(),
25 _dummy(0)
26{
27}
28
31
32void Mesh::SetValues(std::vector<double> &v, const function<double(double, double)> &func) const
33{
34 int const nnode = Nnodes(); // number of vertices in mesh
35 assert( nnode == static_cast<int>(v.size()) );
36 for (int k = 0; k < nnode; ++k)
37 {
38 v[k] = func( _xc[2 * k], _xc[2 * k + 1] );
39 }
40}
41
42void Mesh::SetBoundaryValues(vector<double> &v, const function<double(double, double)> &func) const
43{
44 auto const idx = Index_BoundaryNodes();
45 for (size_t ik = 0; ik < idx.size(); ++ik)
46 {
47 const int k = idx[ik];
48 v[k] = func( _xc[2 * k], _xc[2 * k + 1] );
49 }
50}
51
52void Mesh::SetDirchletValues(vector<double> &v, const function<double(double, double)> &func) const
53{
54 auto const idx = Index_DirichletNodes();
55 for (size_t ik = 0; ik < idx.size(); ++ik)
56 {
57 const int k = idx[ik];
58 v[k] = func( _xc[2 * k], _xc[2 * k + 1] );
59 }
60}
61
62
63
64void Mesh::Debug() const
65{
66 cout << "\n ############### Debug M E S H ###################\n";
67 cout << "\n ............... Coordinates ...................\n";
68 for (int k = 0; k < _nnode; ++k)
69 {
70 cout << k << " : " ;
71 for (int i = 0; i < _ndof_e; ++i )
72 {
73 cout << _xc[2*k+i] << " ";
74 }
75 cout << endl;
76 }
77 cout << "\n ............... Elements ...................\n";
78 for (int k = 0; k < _nelem; ++k)
79 {
80 cout << k << " : ";
81 for (int i = 0; i < _ndof_e; ++i )
82 cout << _ia[_ndof_e * k + i] << " ";
83 cout << endl;
84 }
85 cout << "\n ............... Boundary (vertices) .................\n";
86 cout << " _bedges : " << _bedges << endl;
87 return;
88}
89
91{
92 cout << "\n ############### Debug M E S H (edge based) ###################\n";
93 cout << "\n ............... Coordinates ...................\n";
94 for (int k = 0; k < _nnode; ++k)
95 {
96 cout << k << " : " << _xc[2 * k] << " " << _xc[2 * k + 1] << endl;
97 }
98
99 cout << "\n ............... edges ...................\n";
100 for (int k = 0; k < _nedge; ++k)
101 {
102 cout << k << " : ";
103 for (int i = 0; i < 2; ++i )
104 cout << _edges[2 * k + i] << " ";
105 cout << endl;
106 }
107
108 cout << "\n ............... Elements (edges) .................\n";
109 assert(_nedge_e * _nelem == static_cast<int>(_ea.size()) );
110 for (int k = 0; k < _nelem; ++k)
111 {
112 cout << k << " : ";
113 for (int i = 0; i < _nedge_e; ++i )
114 cout << _ea[_nedge_e * k + i] << " ";
115 cout << endl;
116 }
117 cout << "\n ............... Boundary (edges) .................\n";
118 cout << " _ebedges : " << _ebedges << endl;
119
120 return;
121}
122
123void Mesh::Write_ascii_matlab(std::string const &fname, std::vector<double> const &v) const
124{
125 assert(Nnodes() == static_cast<int>(v.size())); // fits vector length to mesh information?
126
127 ofstream fout(fname); // open file ASCII mode
128 if ( !fout.is_open() )
129 {
130 cout << "\nFile " << fname << " has not been opened.\n\n" ;
131 assert( fout.is_open() && "File not opened." );
132 }
133
134 string const DELIMETER(" "); // define the same delimiter as in matlab/ascii_read*.m
135 int const OFFSET(1); // convert C-indexing to matlab
136
137 // Write data: #nodes, #space dimensions, #elements, #vertices per element
138 fout << Nnodes() << DELIMETER << Ndims() << DELIMETER << Nelems() << DELIMETER << NverticesElements() << endl;
139
140 // Write coordinates: x_k, y_k in separate lines
141 assert( Nnodes()*Ndims() == static_cast<int>(_xc.size()));
142 for (int k = 0, kj = 0; k < Nnodes(); ++k)
143 {
144 for (int j = 0; j < Ndims(); ++j, ++kj)
145 {
146 fout << _xc[kj] << DELIMETER;
147 }
148 fout << endl;
149 }
150
151 // Write connectivity: ia_k,0, ia_k,1 etc in separate lines
152 assert( Nelems()*NverticesElements() == static_cast<int>(_ia.size()));
153 for (int k = 0, kj = 0; k < Nelems(); ++k)
154 {
155 for (int j = 0; j < NverticesElements(); ++j, ++kj)
156 {
157 fout << _ia[kj] + OFFSET << DELIMETER; // C to matlab
158 }
159 fout << endl;
160 }
161
162 // Write vector
163 for (int k = 0; k < Nnodes(); ++k)
164 {
165 fout << v[k] << endl;
166 }
167
168 fout.close();
169 return;
170}
171
172
173void Mesh::Export_scicomp(std::string const &basename) const
174{
175 //assert(Nnodes() == static_cast<int>(v.size())); // fits vector length to mesh information?
176 string const DELIMETER(" "); // define the same delimiter as in matlab/ascii_read*.m
177 int const OFFSET(0);
178 {
179 // Write coordinates into scicomp-file
180 string fname(basename + "_coords.txt");
181 ofstream fout(fname); // open file ASCII mode
182 if ( !fout.is_open() )
183 {
184 cout << "\nFile " << fname << " has not been opened.\n\n" ;
185 assert( fout.is_open() && "File not opened." );
186 }
187
188 fout << Nnodes() << endl;
189 // Write coordinates: x_k, y_k in separate lines
190 assert( Nnodes()*Ndims() == static_cast<int>(_xc.size()));
191 for (int k = 0, kj = 0; k < Nnodes(); ++k)
192 {
193 for (int j = 0; j < Ndims(); ++j, ++kj)
194 {
195 fout << _xc[kj] << DELIMETER;
196 }
197 fout << endl;
198 }
199 fout.close();
200
201 }
202
203 {
204 // Write elements into scicomp-file
205 string fname(basename + "_elements.txt");
206 ofstream fout(fname); // open file ASCII mode
207 if ( !fout.is_open() )
208 {
209 cout << "\nFile " << fname << " has not been opened.\n\n" ;
210 assert( fout.is_open() && "File not opened." );
211 }
212
213 fout << Nelems() << endl;
214
215 // Write connectivity: ia_k,0, ia_k,1 etc in separate lines
216 assert( Nelems()*NverticesElements() == static_cast<int>(_ia.size()));
217 for (int k = 0, kj = 0; k < Nelems(); ++k)
218 {
219 for (int j = 0; j < NverticesElements(); ++j, ++kj)
220 {
221 fout << _ia[kj] + OFFSET << DELIMETER; // C to matlab
222 }
223 fout << endl;
224 }
225 fout.close();
226 }
227
228 return;
229}
230
231/*
232 manjaro> matlab
233 MATLAB is selecting SOFTWARE OPENGL rendering.
234 /usr/local/MATLAB/R2019a/bin/glnxa64/MATLAB: error while loading shared libraries: libcrypt.so.1: cannot open shared object file: No such file or directory
235
236 SOLUTION: sudo pacman -S libxcrypt-compat + reboot
237*/
238
239void Mesh::Visualize(vector<double> const &v) const
240{
241 // define external command
242 const string exec_m("matlab -nosplash < visualize_results.m"); // Matlab
243 //const string exec_m("octave --no-window-system --no-gui visualize_results.m"); // Octave until version 6.3
244 //const string exec_m("octave --no-gui --eval visualize_results.m"); // Octave since version 6.4
245 //const string exec_m("flatpak run org.octave.Octave visualize_results.m"); // Octave (flatpak): desktop GH
246
247 const string fname("uv.txt");
249
250 int ierror = system(exec_m.c_str()); // call external command
251
252 if (ierror != 0)
253 {
254 cout << endl << "Check path to Matlab/octave on your system" << endl;
255 }
256 cout << endl;
257 return;
258}
259
260std::vector<int> Mesh::Index_DirichletNodes() const
261{
262 //vector<int> idx(_bedges); // copy
263 // 2020-01-08
264 // copy only the Dirichlet boundary nodes, not all boundary nodes.
265 vector<int> idx(_bedges.size());
266 size_t cnt=0;
267 for (size_t kb = 0; kb < _bedges.size(); kb+=2 )
268 {
269 if (_sdedges.at(kb) <0 || _sdedges.at(kb+1) <0) // one neighboring subdomain is negativ
270 {
271 idx[cnt] = _bedges[kb];
272 ++cnt;
273 idx[cnt] = _bedges[kb+1];
274 ++cnt;
275 }
276 }
277 idx.resize(cnt);
278
279 sort(idx.begin(), idx.end()); // sort
280 idx.erase( unique(idx.begin(), idx.end()), idx.end() ); // remove duplicate data
281
282 return idx;
283}
284
285// 2020-01-08
286std::vector<int> Mesh::Index_BoundaryNodes() const
287{
288 vector<int> idx(_bedges); // copy
289
290 sort(idx.begin(), idx.end()); // sort
291 idx.erase( unique(idx.begin(), idx.end()), idx.end() ); // remove duplicate data
292
293 return idx;
294}
295
296// GH
297// only correct for simplices
299{
300 assert(NedgesElements() == 3);
301 assert(NverticesElements() == 3); // 3 vertices, 3 edges per element are assumed
302
303 // Store indices of all elements connected to a vertex
304 vector<vector<int>> vertex2elems(_nnode, vector<int>(0));
305 for (int k = 0; k < Nelems(); ++k)
306 {
307 for (int i = 0; i < 3; ++i)
308 {
309 vertex2elems[_ia[3 * k + i]].push_back(k);
310 }
311 }
312 size_t max_neigh = 0; // maximal number of elements per vertex
313 for (auto const &v : vertex2elems)
314 {
315 max_neigh = max(max_neigh, v.size());
316 }
317 //cout << endl << vertex2elems << endl;
318
319 // assign edges to elements
320 _ea.clear(); // old data still in _ea without clear()
321 _ea.resize(NedgesElements()*Nelems(), -1);
322 // Derive the edges
323 _edges.clear();
324 _nedge = 0;
325
326 // convert also boundary edges
327 unsigned int mbc(_bedges.size() / 2); // number of boundary edges
328 _ebedges.clear();
329 _ebedges.resize(mbc, -1);
330 vector<bool> bdir(_nnode, false); // vector indicating boundary nodes
331 //for (size_t kb = 0; kb < _bedges.size(); ++kb )
332 //{
333 //bdir.at(_bedges[kb]) = true;
334 //}
335 // 2020-01-08
336 // GH ToDo: Selection of Dirichlet edges/nodes is still wrong
337 // Problem: _bedges is used externally instead of the local correct bdir.
338 for (size_t kb = 0; kb < _bedges.size(); kb+=2 )
339 {
340 bool const booldir = _sdedges.at(kb) <0 || _sdedges.at(kb+1) <0; // one neighboring subdomain is negativ
341 bdir.at(_bedges[kb]) = booldir;
342 bdir.at(_bedges[kb+1]) = booldir;
343 }
344
345 vector<int> vert_visited; // already visisted neighboring vertices of k
346 vert_visited.reserve(max_neigh); // avoids multiple (re-)allocations
347 for (int k = 0; k < _nnode; ++k) // vertex k
348 {
349 vert_visited.clear();
350 auto const &elems = vertex2elems[k]; // element neighborhood
351 int kedges = static_cast<int>(_edges.size()) / 2; // #edges before vertex k is investigated
352 //cout << elems << endl;
353// GH: problem, shared edges appear twice.
354 int nneigh = elems.size();
355 for (int ne = 0; ne < nneigh; ++ne) // iterate through neighborhood
356 {
357 int e = elems[ne]; // neighboring element e
358 //cout << "e = " << e << endl;
359 for (int i = 3 * e + 0; i < 3 * e + _nvert_e; ++i) // vertices of element e
360 {
361 int const vert = _ia[i];
362 //cout << "vert: " << vert << " "<< k << endl;
363 if ( vert > k )
364 {
365 int ke = -1;
366 auto const iv = find(vert_visited.cbegin(), vert_visited.cend(), vert);
367 if (iv == vert_visited.cend()) // vertex not yet visited
368 {
369 vert_visited.push_back(vert); // now, vertex vert is visited
370 _edges.push_back(k); // add the new edge k->vert
371 _edges.push_back(vert);
372
373 ke = _nedge;
374 ++_nedge;
375 // Is edge ke also a boundary edge?
376 if (bdir[k] && bdir[vert])
377 {
378 size_t kb = 0;
379 while (kb < _bedges.size() && (!( (_bedges[kb] == k && _bedges[kb + 1] == vert) || (_bedges[kb] == vert && _bedges[kb + 1] == k) )) )
380 {
381 kb += 2;
382 }
383 if (kb < _bedges.size())
384 {
385 _ebedges[kb / 2] = ke;
386 }
387 }
388 }
389 else
390 {
391 int offset = iv - vert_visited.cbegin();
392 ke = kedges + offset;
393 }
394 // assign that edge to the edges based connectivity of element e
395 auto ip = find_if(_ea.begin() + 3 * e, _ea.begin() + 3 * (e + 1),
396 [] (int v) -> bool {return v < 0;} );
397 //cout << ip-_ea.begin()+3*e << " " << *ip << endl;
398 assert(ip != _ea.cbegin() + 3 * (e + 1)); // data error !
399 *ip = ke;
400 }
401 }
402 }
403 }
404
406 return;
407}
408// HG
409
410// GH
411// only correct for simplices
413{
414 assert(NedgesElements() == 3);
415 assert(NverticesElements() == 3); // 3 vertices, 3 edges per element are assumed
416
417 // Store indices of all elements connected to a vertex
418 vector<vector<int>> vertex2elems(_nnode, vector<int>(0));
419 for (int k = 0; k < Nelems(); ++k)
420 {
421 for (int i = 0; i < 3; ++i)
422 {
423 vertex2elems[_ia[3 * k + i]].push_back(k);
424 }
425 }
426 size_t max_neigh = 0; // maximal number of elements per vertex
427 for (auto const &v : vertex2elems)
428 {
429 max_neigh = max(max_neigh, v.size());
430 }
431 //cout << endl << vertex2elems << endl;
432
433 // assign edges to elements
434 _ea.clear(); // old data still in _ea without clear()
435 _ea.resize(NedgesElements()*Nelems(), -1);
436 // Derive the edges
437 _edges.clear();
438 _nedge = 0;
439 vector<int> vert_visited; // already visisted neighboring vertices of k
440 vert_visited.reserve(max_neigh); // avoids multiple (re-)allocations
441 for (int k = 0; k < _nnode; ++k) // vertex k
442 {
443 vert_visited.clear();
444 auto const &elems = vertex2elems[k]; // element neighborhood
445 int kedges = static_cast<int>(_edges.size()) / 2; // #edges before vertex k is investigated
446 //cout << elems << endl;
447// GH: problem, shared edges appear twice.
448 int nneigh = elems.size();
449 for (int ne = 0; ne < nneigh; ++ne) // iterate through neighborhood
450 {
451 int e = elems[ne]; // neighboring element e
452 //cout << "e = " << e << endl;
453 for (int i = 3 * e + 0; i < 3 * e + _nvert_e; ++i) // vertices of element e
454 {
455 int const vert = _ia[i];
456 //cout << "vert: " << vert << " "<< k << endl;
457 if ( vert > k )
458 {
459 int ke = -1;
460 auto const iv = find(vert_visited.cbegin(), vert_visited.cend(), vert);
461 if (iv == vert_visited.cend()) // vertex not yet visited
462 {
463 vert_visited.push_back(vert); // now, vertex vert is visited
464 _edges.push_back(k); // add the new edge k->vert
465 _edges.push_back(vert);
466
467 ke = _nedge;
468 ++_nedge;
469 }
470 else
471 {
472 int offset = iv - vert_visited.cbegin();
473 ke = kedges + offset;
474 }
475 // assign that edge to the edges based connectivity of element e
476 auto ip = find_if(_ea.begin() + 3 * e, _ea.begin() + 3 * (e + 1),
477 [] (int v) -> bool {return v < 0;} );
478 //cout << ip-_ea.begin()+3*e << " " << *ip << endl;
479 assert(ip != _ea.cbegin() + 3 * (e + 1)); // data error !
480 *ip = ke;
481 }
482 }
483 }
484 }
485
486 // convert also boundary edges
487 unsigned int mbc(_bedges.size() / 2); // number of boundary edges
488 _ebedges.clear();
489 _ebedges.resize(mbc, -1);
490 for (unsigned int kb = 0; kb < mbc; ++kb)
491 {
492 int const v1 = min(_bedges[2 * kb], _bedges[2 * kb + 1]); // vertices
493 int const v2 = max(_bedges[2 * kb], _bedges[2 * kb + 1]);
494
495 size_t e = 0;
496 // ascending vertex indices for each edge e in _edges
497 while (e < _edges.size() && (_edges[e] != v1 || _edges[e + 1] != v2) )
498 {
499 e += 2; // next edge
500 }
501 assert(e < _edges.size()); // error: no edge found
502 _ebedges[kb] = e / 2; // index of edge
503 }
504
505
507 return;
508}
509// HG
510
511
512#include <utility> // pair
513
515{
516 assert(NedgesElements() == 3);
517 assert(NverticesElements() == 3); // 3 vertices, 3 edges per element are assumed
518
519 _ea.resize(NedgesElements()*Nelems());
520 vector< pair<int, int> > edges(0);
521 int nedges = 0;
522
523 for (int k = 0; k < Nelems(); ++k)
524 {
525 array < int, 3 + 1 > ivert{{ _ia[3 * k], _ia[3 * k + 1], _ia[3 * k + 2], _ia[3 * k] }};
526
527 for (int i = 0; i < 3; ++i)
528 {
529 pair<int, int> e2; // this edge
530 if (ivert[i] < ivert[i + 1]) // guarantee ascending order
531 {
532 e2 = make_pair(ivert[i], ivert[i + 1]);
533 }
534 else
535 {
536 e2 = make_pair(ivert[i + 1], ivert[i]);
537 }
538
539 int eki(-1); // global index of this edge
540 auto ip = find(edges.cbegin(), edges.cend(), e2);
541 if ( ip == edges.cend() ) // edge not found ==> add that edge
542 {
543 //cout << "found edge\n";
544 edges.push_back(e2); // add the new edge
545 eki = nedges; // index of this new edge
546 ++nedges;
547
548 }
549 else
550 {
551 eki = ip - edges.cbegin(); // index of the edge found
552 }
553 _ea[3 * k + i] = eki; // set edge index in edge based connectivity
554 }
555 }
556
557 assert( nedges == static_cast<int>(edges.size()) );
558 _nedge = nedges; // set the member variable for number of edges
559 _edges.resize(2 * nedges); // allocate memory for edge storage
560 for (int k = 0; k < nedges; ++k)
561 {
562 _edges[2 * k ] = edges[k].first;
563 _edges[2 * k + 1] = edges[k].second;
564 }
565
566 // convert also boundary edges
567 unsigned int mbc(_bedges.size() / 2); // number of boundary edges
568 //cout << "AA " << mbc << endl;
569 _ebedges.resize(mbc);
570 for (unsigned int kb = 0; kb < mbc; ++kb)
571 {
572 const auto vv1 = make_pair(_bedges[2 * kb ], _bedges[2 * kb + 1]); // both
573 const auto vv2 = make_pair(_bedges[2 * kb + 1], _bedges[2 * kb ]); // directions of edge
574 auto ip1 = find(edges.cbegin(), edges.cend(), vv1);
575 if (ip1 == edges.cend())
576 {
577 ip1 = find(edges.cbegin(), edges.cend(), vv2);
578 assert(ip1 != edges.cend()); // stop because inconsistency (boundary edge has to be included in edges)
579 }
580 _ebedges[kb] = ip1 - edges.cbegin(); // index of edge
581 }
582
584 return;
585}
586
588{
589 assert(NedgesElements() == 3);
590 assert(NverticesElements() == 3); // 3 vertices, 3 edges per element are assumed
591
592 _ia.resize(NedgesElements()*Nelems()); // NN
593
594 for (int k = 0; k < Nelems(); ++k)
595 {
596 //vector<int> ivert(6); // indices of vertices
597 array<int, 6> ivert; // indices of vertices
598 for (int j = 0; j < 3; ++j) // local edges
599 {
600 int const iedg = _ea[3 * k + j]; // index of one edge in triangle
601 ivert[2 * j ] = _edges[2 * iedg ]; // first vertex of edge
602 ivert[2 * j + 1] = _edges[2 * iedg + 1]; // second vertex of edge
603 }
604 sort(ivert.begin(), ivert.end()); // unique indices are needed
605 auto const ip = unique(ivert.begin(), ivert.end());
606 assert( ip - ivert.begin() == 3 );
607 for (int i = 0; i < 3; ++i) // vertex based element connectivity
608 {
609 _ia[3 * k + i] = ivert[i];
610 }
611 }
612
613 // convert also boundary edges
614 unsigned int mbc(_ebedges.size()); // number of boundary edges
615 _bedges.resize(2 * mbc);
616 for (unsigned int k = 0; k < mbc; ++k)
617 {
618 const auto ke = _ebedges[k]; // edge index
619 _bedges[2 * k ] = _edges[2 * ke ];
620 _bedges[2 * k + 1] = _edges[2 * ke + 1];
621 }
622
623
624 return;
625}
626
627// Member Input: vertices of each element : _ia[_nelem*_nvert_e] stores as 1D array
628// number of vertices per element : _nvert_e
629// global number of elements: _nelem
630// global number of vertices: _nnode
631vector<vector<int>> Mesh::Node2NodeGraph_2() const
632{
633 vector<vector<int>> v2v(_nnode, vector<int>(0)); // stores the vertex to vertex connections
634
636 vector<int> cnt(_nnode,0);
637 for (size_t i = 0; i < _ia.size(); ++i) ++cnt[_ia[i]]; // determine number of entries per vertex
638 for (size_t k = 0; k < v2v.size(); ++k)
639 {
640 v2v[k].resize(_nvert_e * cnt[k]); // and allocate the memory for that vertex
641 cnt[k] = 0;
642 }
644
645 for (int e = 0; e < _nelem; ++e)
646 {
647 int const basis = e * _nvert_e; // start of vertex connectivity of element e
648 for (int k = 0; k < _nvert_e; ++k)
649 {
650 int const v = _ia[basis + k];
651 for (int l = 0; l < _nvert_e; ++l)
652 {
653 v2v[v][cnt[v]] = _ia[basis + l];
654 ++cnt[v];
655 }
656 }
657 }
658 // finally cnt[v]==v2v[v].size() has to hold for all v!
659
660 // guarantee unique, ascending sorted entries per vertex
661 for (size_t v = 0; v < v2v.size(); ++v)
662 {
663 sort(v2v[v].begin(), v2v[v].end());
664 auto ip = unique(v2v[v].begin(), v2v[v].end());
665 v2v[v].erase(ip, v2v[v].end());
666 //v2v[v].shrink_to_fit(); // automatically done when copied at return
667 }
668
669 return v2v;
670}
671
672vector<vector<int>> Mesh::Node2NodeGraph_1() const
673{
674 vector<vector<int>> v2v(_nnode, vector<int>(0)); // stores the vertex to vertex connections
675
676 for (int e = 0; e < _nelem; ++e)
677 {
678 int const basis = e * _nvert_e; // start of vertex connectivity of element e
679 for (int k = 0; k < _nvert_e; ++k)
680 {
681 int const v = _ia[basis + k];
682 for (int l = 0; l < _nvert_e; ++l)
683 {
684 v2v[v].push_back(_ia[basis + l]);
685 }
686 }
687 }
688 // guarantee unique, ascending sorted entries per vertex
689 for (size_t v = 0; v < v2v.size(); ++v)
690 {
691 sort(v2v[v].begin(), v2v[v].end());
692 auto ip = unique(v2v[v].begin(), v2v[v].end());
693 v2v[v].erase(ip, v2v[v].end());
694 //v2v[v].shrink_to_fit(); // automatically done when copied at return
695 }
696
697 return v2v;
698}
699
700
701Mesh::Mesh(std::string const &fname)
702 : Mesh(2, 3, 3, 3) // two dimensions, 3 vertices, 3 dofs, 3 edges per element
703{
705 DeriveEdgeFromVertexBased(); // Generate also the edge based information
706 //cout << " JJJJJJJJJ\n";
707 //DeriveEdgeFromVertexBased();
708 //cout << " KKKKKKKKKKK\n";
710}
711
712void Mesh::ReadVertexBasedMesh(std::string const &fname)
713{
714 ifstream ifs(fname);
715 if (!(ifs.is_open() && ifs.good()))
716 {
717 cerr << "Mesh::ReadVertexBasedMesh: Error cannot open file " << fname << endl;
718 assert(ifs.is_open());
719 }
720
721 int const OFFSET(1); // Matlab to C indexing
722 cout << "ASCI file " << fname << " opened" << endl;
723
724 // Read some mesh constants
725 int nnode, ndim, nelem, nvert_e;
726 ifs >> nnode >> ndim >> nelem >> nvert_e;
727 cout << nnode << " " << ndim << " " << nelem << " " << nvert_e << endl;
728 assert(ndim == 2 && nvert_e == 3);
729
730 // Allocate memory
731 Resize_Coords(nnode, ndim); // coordinates in 2D [nnode][ndim]
732 Resize_Connectivity(nelem, nvert_e); // connectivity matrix [nelem][nvert]
733
734 // Read coordinates
735 auto &xc = GetCoords();
736 for (int k = 0; k < nnode * ndim; ++k)
737 {
738 ifs >> xc[k];
739 }
740
741 // Read connectivity
742 auto &ia = GetConnectivity();
743 for (int k = 0; k < nelem * nvert_e; ++k)
744 {
745 ifs >> ia[k];
746 ia[k] -= OFFSET; // Matlab to C indexing
747 }
748
749 // additional read of boundary information (only start/end point)
750 int nbedges;
751 ifs >> nbedges;
752
753 _bedges.resize(nbedges * 2);
754 for (int k = 0; k < nbedges * 2; ++k)
755 {
756 ifs >> _bedges[k];
757 _bedges[k] -= OFFSET; // Matlab to C indexing
758 }
759// 2020-01-08 Check
760 int const DUMMY{-9876};
761 _sdedges.resize(nbedges * 2,DUMMY);
762 if (!ifs.eof())
763 {
764 cout << nbedges << endl; // change to while-loop
765 for (int k = 0; k < nbedges * 2; ++k)
766 {
767 ifs >> _sdedges.at(k);
768 _sdedges[k] -= OFFSET; // Matlab to C indexing
769 }
770 //assert(ifs.eof());
771 assert(count(_sdedges.cbegin(),_sdedges.cend(),DUMMY)==0);
772 }
773 else
774 {
775 cout << "\n ####### no subdomain info of edges available! #########\n";
776 }
777 cout << "\n End of File read " << _sdedges.at(2*nbedges-2) << " " << _sdedges.at(2*nbedges-1) << "\n" << endl;
778
779 return;
780}
781
783{
784 bool b_ia = static_cast<int>(_ia.size() / _nvert_e) == _nelem;
785 if (!b_ia) cerr << "misfit: _nelem vs. _ia" << endl;
786
787 bool b_xc = static_cast<int>(_xc.size() / _ndim) == _nnode;
788 if (!b_xc) cerr << "misfit: _nnode vs. _xc" << endl;
789
790 bool b_ea = static_cast<int>(_ea.size() / _nedge_e) == _nelem;
791 if (!b_ea) cerr << "misfit: _nelem vs. _ea" << endl;
792
793 bool b_ed = static_cast<int>(_edges.size() / 2) == _nedge;
794 if (!b_ed) cerr << "misfit: _nedge vs. _edges" << endl;
795
796
797 return b_ia && b_xc && b_ea && b_ed;
798}
799
801{
802 _nedge = 0;
803 _edges.resize(0);
804 _edges.shrink_to_fit();
805 _ea.resize(0);
806 _ea.shrink_to_fit();
807 _ebedges.resize(0);
808 _ebedges.shrink_to_fit();
809 return;
810}
811
812
813
814// ####################################################################
815
816RefinedMesh::RefinedMesh(Mesh const &cmesh, std::vector<bool> const &ibref)
817//: Mesh(cmesh), _cmesh(cmesh), _ibref(ibref), _nref(0), _vfathers(0)
818 : Mesh(cmesh), _ibref(ibref), _nref(0), _vfathers(0)
819{
820 if (_ibref.size() == 0) // refine all elements
821 {
822 //
824 }
825 else
826 {
827 cout << endl << " Adaptive Refinement not implemented yet." << endl;
828 assert(_ibref.size() != 0);
829 }
830}
831
834
835Mesh RefinedMesh::RefineElements(std::vector<bool> const & /*ibref*/)
836{
837 Mesh new_mesh(_ndim, _nvert_e, _ndof_e, _nedge_e);
838 cout << " NOT IMPLEMENTED: Mesh::RefineElements" << endl;
839
841 //auto new_coords = new_mesh.GetCoords();
842 //new_coords = _xc; // copy coordinates from old mesh
843
845 //auto new_ia = new_mesh.GetConnectivity();
846 //auto new_ea = new_mesh.GetEdgeConnectivity();
847 //auto new_edges = new_mesh.GetEdges();
848
850
851
852 //assert( new_ia.size()== new_ea.size() );
853 //new_mesh.SetNnode( new_coords.size() );
854 //new_mesh.SetNelem( new_ia.size()/3 );
855 //new_mesh._nedge = new_edges.size()/2;
856
857 return new_mesh;
858}
859
860//JF
862{
863 cout << "\n############ Refine Mesh " << nref << " times ";
864 double tstart = clock();
865 DeriveEdgeFromVertexBased(); // ensure that edge information is available
866
867 for (int kr = 0; kr < nref; ++kr)
868 {
869 //DeriveEdgeFromVertexBased(); // ensure that edge information is available // GH: not needed in each loop
870
871 auto old_ea(_ea); // save old edge connectivity
872 auto old_edges(_edges); // save old edges
873 auto old_nedges(Nedges());
874 auto old_nnodes(Nnodes());
875 auto old_nelems(Nelems());
876
877 // the new vertices will be appended to the coordinates in _xc
878
879 vector<int> edge_sons(2 * old_nedges); // 2 sons for each edge
880
881 // -- Derive the fine edges ---
882 int new_nedge = 2 * old_nedges + 3 * old_nelems; // #edges in new mesh
883 int new_nelem = 4 * old_nelems; // #elements in new mesh
884 int new_nnode = old_nnodes + old_nedges; // #nodes in new mesh
885
886 _xc.reserve(2 * new_nnode);
887 // store the 2 fathers of each vertex (equal fathers denote original coarse vertex)
888 _vfathers.resize(2 * old_nnodes);
889 for (int vc = 0; vc < old_nnodes; ++vc)
890 {
891 _vfathers[2 * vc ] = vc; // equal fathers denote original coarse vertex
892 _vfathers[2 * vc + 1] = vc;
893 }
894
895 _ia.clear();
896 _ea.clear();
897 _ea.resize(new_nelem * 3);
898 _edges.clear();
899 _edges.resize(2 * new_nedge); // vertices of edges [v_0, v_1;v_0, v_1; ...]
900 vector<int> e_son(2 * old_nedges); // sons of coarse edges [s_0, s_1; s_0, s_1; ...]
901
902 // split all coarse edges and append the new nodes
903 int kf = 0; // index of edges in fine mesh
904 int vf = old_nnodes; // index of new vertex in fine grid
905 for (int kc = 0; kc < old_nedges; ++kc) // index of edges in coarse mesh
906 {
907 //
908 int v1 = old_edges[2 * kc]; // vertices of old edge
909 int v2 = old_edges[2 * kc + 1];
910 // append coordinates of new vertex
911 double xf = 0.5 * ( _xc[2 * v1 ] + _xc[2 * v2 ] );
912 double yf = 0.5 * ( _xc[2 * v1 + 1] + _xc[2 * v2 + 1] );
913 _xc.push_back(xf);
914 _xc.push_back(yf);
915 // fathers of vertex vf
916 _vfathers.push_back(v1);
917 _vfathers.push_back(v2);
918
919 // split old edge into two edges
920 _edges[2 * kf ] = v1; // coarse vertex 1
921 _edges[2 * kf + 1] = vf; // to new fine vertex
922 e_son[2 * kc ] = kf; // son edge
923 ++kf;
924 _edges[2 * kf ] = vf; // new fine vertex
925 _edges[2 * kf + 1] = v2; // to coarse vertex 2
926 e_son[2 * kc + 1] = kf; // son edge
927
928 ++vf;
929 ++kf;
930 }
931 _xc.shrink_to_fit();
932 _vfathers.shrink_to_fit();
933
934 // -- derive the fine mesh elements --
935 // creates additional fine edges
936
937 for (int kc = 0; kc < old_nelems; ++kc) // index of elements in coarse mesh
938 {
939 array<array<int, 3>, 3 * 2> boundary; // fine scale vertices and edges as boundary of old element
940 //boundary[ ][0], boundary[ ][1] ..vertices boundary[ ][2] edge
941
942 for (int j = 0; j < 3; ++j) // each edge in element
943 {
944 int ce = old_ea[3 * kc + j]; // coarse edge number
945
946 int s1 = e_son[2 * ce ]; // son edges of that coarse edge
947 int s2 = e_son[2 * ce + 1];
948 boundary[2 * j][2] = s1; //add boundary edge
949 boundary[2 * j][0] = _edges[2 * s1 + 0];
950 boundary[2 * j][1] = _edges[2 * s1 + 1];
951 if (boundary[2 * j][0] > boundary[2 * j][1]) swap(boundary[2 * j][0], boundary[2 * j][1]); // fine vertices always in 2nd entry
952 boundary[2 * j + 1][2] = s2; //add boundary edge
953 boundary[2 * j + 1][0] = _edges[2 * s2 + 0];
954 boundary[2 * j + 1][1] = _edges[2 * s2 + 1];
955 if (boundary[2 * j + 1][0] > boundary[2 * j + 1][1]) swap(boundary[2 * j + 1][0], boundary[2 * j + 1][1]);
956 }
957
958 sort(boundary.begin(), boundary.end()); // sort -> edges with same coarse vertex will be neighbors
959
960 int interior_1 = 2 * old_nedges + kc * 3; // add interior edges
961 int interior_2 = 2 * old_nedges + kc * 3 + 1;
962 int interior_3 = 2 * old_nedges + kc * 3 + 2;
963
964 _edges[interior_1 * 2 ] = boundary[0][1]; // add interior edges
965 _edges[interior_1 * 2 + 1] = boundary[1][1];
966
967 _edges[interior_2 * 2 ] = boundary[2][1];
968 _edges[interior_2 * 2 + 1] = boundary[3][1];
969
970 _edges[interior_3 * 2 ] = boundary[4][1];
971 _edges[interior_3 * 2 + 1] = boundary[5][1];
972
973 _ea[kc * 3 * 4 ] = boundary[0][2]; // add 4 new elements with 3 edges for every old element
974 _ea[kc * 3 * 4 + 1] = boundary[1][2];
975 _ea[kc * 3 * 4 + 2] = interior_1;
976
977 _ea[kc * 3 * 4 + 3] = boundary[2][2];
978 _ea[kc * 3 * 4 + 4] = boundary[3][2];
979 _ea[kc * 3 * 4 + 5] = interior_2;
980
981 _ea[kc * 3 * 4 + 6] = boundary[4][2];
982 _ea[kc * 3 * 4 + 7] = boundary[5][2];
983 _ea[kc * 3 * 4 + 8] = interior_3;
984
985 _ea[kc * 3 * 4 + 9] = interior_1;
986 _ea[kc * 3 * 4 + 10] = interior_2;
987 _ea[kc * 3 * 4 + 11] = interior_3;
988 }
989
990// GH: ToDo: _bedges has to updated for the new mesh //!< boundary edges [nbedges][2] storing start/end vertex
991// Pass the refinement information to the boundary edges (edge based)
992 auto old_ebedges(_ebedges); // save original boundary edges [nbedges] (edge based storage)
993 unsigned int old_nbedges(old_ebedges.size());
994
995 _ebedges.resize(2 * old_nbedges); // each old boundary edge will be bisected
996 unsigned int kn = 0; // index of new boundary edges
997 for (unsigned int ke = 0; ke < old_nbedges; ++ke) // index of old boundary edges
998 {
999 const auto kc = old_ebedges[ke];
1000 _ebedges[kn] = e_son[2 * kc ];
1001 ++kn;
1002 _ebedges[kn] = e_son[2 * kc + 1];
1003 ++kn;
1004 }
1005// HG
1006 // set new mesh parameters
1007 SetNelem(new_nelem);
1008 SetNnode(new_nnode);
1009 SetNedge(new_nedge);
1010
1011#ifdef CUTHILL_MCKEE
1012 {
1013// Cuthill-McKee reordering
1014// Increases mesh generation time by factor 5 - but solver is faster.
1015 auto const perm = cuthill_mckee_reordering(_edges);
1017 }
1018#endif
1019
1022
1023 ++_nref; // track the number of refinements
1024 }
1025
1026 double duration = (clock() - tstart) / CLOCKS_PER_SEC;
1027 cout << "finished in " << duration << " sec. ########\n";
1028
1029 return;
1030}
1031
1032
1033void Mesh::PermuteVertices_EdgeBased(vector<int> const &old2new)
1034{
1035// permute vertices _edges
1036 auto const edges_old(_edges);
1037 for (size_t k = 0; k < _edges.size(); k += 2)
1038 {
1039 _edges[k ] = old2new[edges_old[k ]];
1040 _edges[k + 1] = old2new[edges_old[k + 1]];
1041 if (_edges[k] > _edges[k + 1])
1042 swap(_edges[k], _edges[k + 1]);
1043 }
1044// permute coordinates
1045 auto const coord_old(_xc);
1046 for (size_t k = 0; k < _xc.size() / 2; ++k)
1047 {
1048 _xc[2 * old2new[k] ] = coord_old[2 * k ];
1049 _xc[2 * old2new[k] + 1] = coord_old[2 * k + 1];
1050 }
1051 return;
1052}
1053
1054
1055void RefinedMesh::PermuteVertices_EdgeBased(vector<int> const &old2new)
1056{
1058// permute fathers of a vertex
1059 auto const old_fathers(_vfathers);
1060 for (size_t k = 0; k < _vfathers.size() / 2; ++k)
1061 {
1062 _vfathers[2 * old2new[k] ] = old_fathers[2 * k ];
1063 _vfathers[2 * old2new[k] + 1] = old_fathers[2 * k + 1];
1064 }
1065 return;
1066}
1067
1068
1070{
1071 const bool bp = Mesh::Check_array_dimensions();
1072
1073 const bool bvf = (static_cast<int>(_vfathers.size()) / 2 == Nnodes());
1074
1075 return bp && bvf;
1076
1077}
1078// #####################################################################
1079
1080
1081gMesh_Hierarchy::gMesh_Hierarchy(Mesh const &cmesh, int const nlevel)
1082 : _gmesh(max(1, nlevel))
1083{
1084 _gmesh[0] = make_shared<Mesh>(cmesh);
1085 for (int lev = 1; lev < nlevel; ++lev)
1086 {
1087 _gmesh.at(lev) = make_shared<RefinedMesh>( *_gmesh.at(lev - 1) );
1088 //auto vv=_gmesh[lev]->GetFathersOfVertices();
1089 //cout << " :: "<< vv.size() <<endl;
1090 }
1091 for (size_t lev = 0; lev < _gmesh.size(); ++lev)
1092 {
1093 _gmesh[lev]->Del_EdgeConnectivity();
1094 }
1095}
1096
1097
1098// #####################################################################
1099Mesh_2d_3_square::Mesh_2d_3_square(int nx, int ny, int myid, int procx, int procy)
1100 : Mesh(2, 3, 3, 3), // two dimensions, 3 vertices, 3 dofs, 3 edges per element
1101 _myid(myid), _procx(procx), _procy(procy), _neigh{{ -1, -1, -1, -1}}, _color(0),
1102_xl(0.0), _xr(1.0), _yb(0.0), _yt(1.0), _nx(nx), _ny(ny)
1103{
1104 //void IniGeom(int const myid, int const procx, int const procy, int neigh[], int &color)
1105 int const ky = _myid / _procx;
1106 int const kx = _myid % _procy; // MOD(myid,procx)
1107 // Determine the neighbors of domain/rank myid
1108 _neigh[0] = (ky == 0) ? -1 : _myid - _procx; // South
1109 _neigh[1] = (kx == _procx - 1) ? -1 : _myid + 1; // East
1110 _neigh[2] = (ky == _procy - 1) ? -1 : _myid + _procx; // North
1111 _neigh[3] = (kx == 0) ? -1 : _myid - 1; // West
1112
1113 _color = (kx + ky) & 1 ;
1114
1115 // subdomain is part of unit square
1116 double const hx = 1. / _procx;
1117 double const hy = 1. / _procy;
1118 _xl = kx * hx; // left
1119 _xr = (kx + 1) * hx; // right
1120 _yb = ky * hy; // bottom
1121 _yt = (ky + 1) * hy; // top
1122
1123 // Calculate coordinates
1124 int const nnode = (_nx + 1) * (_ny + 1); // number of nodes
1125 Resize_Coords(nnode, 2); // coordinates in 2D [nnode][ndim]
1126 GetCoordsInRectangle(_nx, _ny, _xl, _xr, _yb, _yt, GetCoords().data());
1127
1128 // Calculate element connectivity (linear triangles)
1129 int const nelem = 2 * _nx * _ny; // number of elements
1130 Resize_Connectivity(nelem, 3); // connectivity matrix [nelem][3]
1131 GetConnectivityInRectangle(_nx, _ny, GetConnectivity().data());
1132
1133 return;
1134}
1135
1138
1139
1140void Mesh_2d_3_square::SetU(std::vector<double> &u) const
1141{
1142 int dx = _nx + 1;
1143 for (int j = 0; j <= _ny; ++j)
1144 {
1145 int k = j * dx;
1146 for (int i = 0; i <= _nx; ++i, ++k)
1147 {
1148 u[k] = 0.0;
1149 }
1150 }
1151
1152}
1153
1154void Mesh_2d_3_square::SetF(std::vector<double> &f) const
1155{
1156 int dx = _nx + 1;
1157 for (int j = 0; j <= _ny; ++j)
1158 {
1159 int k = j * dx;
1160 for (int i = 0; i <= _nx; ++i, ++k)
1161 {
1162 f[k] = 1.0;
1163 }
1164 }
1165
1166}
1167
1168
1170{
1171 int const dx = 1,
1172 dy = _nx + 1,
1173 bl = 0,
1174 br = _nx,
1175 tl = _ny * (_nx + 1),
1176 tr = (_ny + 1) * (_nx + 1) - 1;
1177 int const start[4] = { bl, br, tl, bl};
1178 int const end[4] = { br, tr, tr, tl};
1179 int const step[4] = { dx, dy, dx, dy};
1180
1181 vector<int> idx(0);
1182 for (int j = 0; j < 4; j++)
1183 {
1184 if (_neigh[j] < 0)
1185 {
1186 for (int i = start[j]; i <= end[j]; i += step[j])
1187 {
1188 idx.push_back(i); // node i is Dirichlet node
1189 }
1190 }
1191 }
1192 // remove multiple elements
1193 sort(idx.begin(), idx.end()); // sort
1194 idx.erase( unique(idx.begin(), idx.end()), idx.end() ); // remove duplicate data
1195
1196 return idx;
1197}
1198
1200{
1201 cerr << "Warning: Funktion not implemented. " << __FILE__ << "." << __LINE__ << endl;
1202 return Index_BoundaryNodes();
1203}
1204
1205
1206
1207
1208void Mesh_2d_3_square::SaveVectorP(std::string const &name, vector<double> const &u) const
1209{
1210// construct the file name for subdomain myid
1211 const string tmp( std::to_string(_myid / 100) + to_string((_myid % 100) / 10) + to_string(_myid % 10) );
1212
1213 const string namep = name + "." + tmp;
1214 ofstream ff(namep.c_str());
1215 ff.precision(6);
1216 ff.setf(ios::fixed, ios::floatfield);
1217
1218 // assumes tensor product grid in unit square; rowise numbered (as generated in class constructor)
1219 // output is provided for tensor product grid visualization ( similar to Matlab-surf() )
1220 auto const &xc = GetCoords();
1221 int k = 0;
1222 for (int j = 0; j <= _ny; ++j)
1223 {
1224 for (int i = 0; i <= _nx; ++i, ++k)
1225 ff << xc[2 * k + 0] << " " << xc[2 * k + 1] << " " << u[k] << endl;
1226 ff << endl;
1227 }
1228
1229 ff.close();
1230 return;
1231}
1232
1233void Mesh_2d_3_square::GetCoordsInRectangle(int const nx, int const ny,
1234 double const xl, double const xr, double const yb, double const yt,
1235 double xc[])
1236{
1237 const double hx = (xr - xl) / nx,
1238 hy = (yt - yb) / ny;
1239
1240 int k = 0;
1241 for (int j = 0; j <= ny; ++j)
1242 {
1243 const double y0 = yb + j * hy;
1244 for (int i = 0; i <= nx; ++i, k += 2)
1245 {
1246 xc[k ] = xl + i * hx;
1247 xc[k + 1] = y0;
1248 }
1249 }
1250
1251 return;
1252}
1253
1254void Mesh_2d_3_square::GetConnectivityInRectangle(int const nx, int const ny, int ia[])
1255{
1256 const int dx = nx + 1;
1257 int k = 0;
1258 int l = 0;
1259 for (int j = 0; j < ny; ++j, ++k)
1260 {
1261 for (int i = 0; i < nx; ++i, ++k)
1262 {
1263 ia[l ] = k;
1264 ia[l + 1] = k + 1;
1265 ia[l + 2] = k + dx + 1;
1266 l += 3;
1267 ia[l ] = k;
1268 ia[l + 1] = k + dx;
1269 ia[l + 2] = k + dx + 1;
1270 l += 3;
1271 }
1272 }
1273 return;
1274}
1275
1276// ####################################################################
1277
function[xc, ia, v]
function vertex minimal boundary edge info in an ASCII file Matlab indexing is stored(starts with 1). % % The output file format is compatible with Mesh_2d_3_matlab nnode
tmp(:,:).'
void SetU(std::vector< double > &u) const
Definition geom.cpp:1140
~Mesh_2d_3_square() override
Definition geom.cpp:1136
std::array< int, 4 > _neigh
MPI ranks of neighbors (negative: no neighbor but b.c.)
Definition geom.h:696
void GetCoordsInRectangle(int nx, int ny, double xl, double xr, double yb, double yt, double xc[])
Definition geom.cpp:1233
std::vector< int > Index_DirichletNodes() const override
Definition geom.cpp:1169
void SaveVectorP(std::string const &name, std::vector< double > const &u) const
Definition geom.cpp:1208
int _myid
my MPI rank
Definition geom.h:693
void SetF(std::vector< double > &f) const
Definition geom.cpp:1154
std::vector< int > Index_BoundaryNodes() const override
Definition geom.cpp:1199
void GetConnectivityInRectangle(int nx, int ny, int ia[])
Definition geom.cpp:1254
int _nx
number of intervals in x-direction
Definition geom.h:703
int _ny
number of intervals in y-direction
Definition geom.h:704
Mesh_2d_3_square(int nx, int ny, int myid=0, int procx=1, int procy=1)
Definition geom.cpp:1099
Definition geom.h:14
const std::vector< double > & GetCoords() const
Definition geom.h:151
void DeriveEdgeFromVertexBased_fast()
Definition geom.cpp:412
void Resize_Connectivity(int nelem, int nvert_e)
Definition geom.h:109
void Debug() const
Definition geom.cpp:64
std::vector< int > _ea
edge based element connectivity
Definition geom.h:442
int _nedge_e
number of edges per element
Definition geom.h:440
void Resize_Coords(int nnodes, int ndim)
Definition geom.h:140
std::vector< int > _sdedges
boundary edges [nbedges][2] with left/right subdomain number
Definition geom.h:434
std::vector< int > _ia
element connectivity
Definition geom.h:427
void DeriveEdgeFromVertexBased()
Definition geom.h:362
int _ndof_e
degrees of freedom (d.o.f.) per element
Definition geom.h:424
void Export_scicomp(std::string const &basename) const
Definition geom.cpp:173
std::vector< double > _xc
coordinates
Definition geom.h:428
void SetNedge(int nedge)
Definition geom.h:343
int Ndims() const
Definition geom.h:98
std::vector< std::vector< int > > Node2NodeGraph_2() const
Definition geom.cpp:631
int _nelem
number elements
Definition geom.h:422
virtual std::vector< int > Index_DirichletNodes() const
Definition geom.cpp:260
virtual ~Mesh()
Definition geom.cpp:29
virtual bool Check_array_dimensions() const
Definition geom.cpp:782
Mesh(int ndim, int nvert_e=0, int ndof_e=0, int nedge_e=0)
Definition geom.cpp:21
int _ndim
space dimension of the problem (1, 2, or 3)
Definition geom.h:426
std::vector< int > _ebedges
boundary edges [nbedges]
Definition geom.h:444
int _nnode
number nodes/vertices
Definition geom.h:425
int Nelems() const
Definition geom.h:62
void DeriveVertexFromEdgeBased()
Definition geom.cpp:587
void Write_ascii_matlab(std::string const &fname, std::vector< double > const &v) const
Definition geom.cpp:123
int Nnodes() const
Definition geom.h:89
int _nedge
number of edges in mesh
Definition geom.h:439
std::vector< int > _bedges
boundary edges [nbedges][2] storing start/end vertex
Definition geom.h:432
void DeriveEdgeFromVertexBased_fast_2()
Definition geom.cpp:298
int NverticesElements() const
Definition geom.h:71
int NedgesElements() const
Definition geom.h:236
void PermuteVertices_EdgeBased(std::vector< int > const &old2new)
Definition geom.cpp:1033
void SetNnode(int nnode)
Definition geom.h:333
void Del_EdgeConnectivity()
Definition geom.cpp:800
void ReadVertexBasedMesh(std::string const &fname)
Definition geom.cpp:712
void DeriveEdgeFromVertexBased_slow()
Definition geom.cpp:514
void DebugEdgeBased() const
Definition geom.cpp:90
int Nedges() const
Definition geom.h:227
void SetDirchletValues(std::vector< double > &v, const std::function< double(double, double)> &func) const
Definition geom.cpp:52
void SetNelem(int nelem)
Definition geom.h:318
void SetBoundaryValues(std::vector< double > &v, const std::function< double(double, double)> &func) const
Definition geom.cpp:42
std::vector< int > _edges
edges of mesh (vertices ordered ascending)
Definition geom.h:441
virtual std::vector< int > Index_BoundaryNodes() const
Definition geom.cpp:286
const std::vector< int > & GetConnectivity() const
Definition geom.h:120
std::vector< std::vector< int > > Node2NodeGraph_1() const
Definition geom.cpp:672
void SetValues(std::vector< double > &v, const std::function< double(double, double)> &func) const
Definition geom.cpp:32
virtual void Visualize(std::vector< double > const &v) const
Definition geom.cpp:239
int _nvert_e
number of vertices per element
Definition geom.h:423
bool Check_array_dimensions() const override
Definition geom.cpp:1069
virtual ~RefinedMesh() override
Definition geom.cpp:832
std::vector< bool > const _ibref
refinement info
Definition geom.h:538
void PermuteVertices_EdgeBased(std::vector< int > const &old2new)
Definition geom.cpp:1055
Mesh RefineElements(std::vector< bool > const &ibref)
Definition geom.cpp:835
std::vector< int > _vfathers
stores the 2 fathers of each vertex (equal fathers denote original coarse vertex)
Definition geom.h:540
void RefineAllElements(int nref=1)
Definition geom.cpp:861
int _nref
number of regular refinements performed
Definition geom.h:539
RefinedMesh(Mesh const &cmesh, std::vector< bool > const &ibref)
Definition geom.cpp:816
std::vector< std::shared_ptr< Mesh > > _gmesh
mesh hierarchy from coarse ([0]) to fine.
Definition geom.h:599
gMesh_Hierarchy(Mesh const &cmesh, int nlevel)
Definition geom.cpp:1081
vector< int > cuthill_mckee_reordering(vector< int > const &_edges)
u
Definition laplacian.m:3
angle in trangle e
Definition square_bb_4.m:62