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