jacobi.template
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 
19 using namespace std;
20 
21 Mesh::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 
30 {}
31 
32 void 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 
42 void 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 
52 void 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 
64 void 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 
123 void 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 
173 void 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 
239 void 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 
260 std::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
286 std::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 
405  assert( Mesh::Check_array_dimensions() );
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 
506  assert( Mesh::Check_array_dimensions() );
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 
583  assert( Mesh::Check_array_dimensions() );
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
631 vector<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 
672 vector<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 
701 Mesh::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 
712 void 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 
816 RefinedMesh::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 
833 {}
834 
835 Mesh 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 
1033 void 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 
1055 void 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 
1081 gMesh_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 // #####################################################################
1099 Mesh_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 
1137 {}
1138 
1139 
1140 void 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 
1154 void 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 
1208 void 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 
1233 void 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 
1254 void 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 
Mesh::Write_ascii_matlab
void Write_ascii_matlab(std::string const &fname, std::vector< double > const &v) const
Definition: geom.cpp:123
Mesh::Export_scicomp
void Export_scicomp(std::string const &basename) const
Definition: geom.cpp:173
Mesh::DeriveVertexFromEdgeBased
void DeriveVertexFromEdgeBased()
Definition: geom.cpp:587
Mesh::NedgesElements
int NedgesElements() const
Definition: geom.h:236
Mesh::SetNelem
void SetNelem(int nelem)
Definition: geom.h:318
Mesh::_nedge
int _nedge
number of edges in mesh
Definition: geom.h:439
Mesh::SetBoundaryValues
void SetBoundaryValues(std::vector< double > &v, const std::function< double(double, double)> &func) const
Definition: geom.cpp:42
xc
xc
Definition: ascii_read_meshvector.m:30
Mesh::_ea
std::vector< int > _ea
edge based element connectivity
Definition: geom.h:442
Mesh::_edges
std::vector< int > _edges
edges of mesh (vertices ordered ascending)
Definition: geom.h:441
end
end
Definition: visualize_par_results.m:9
tmp
tmp(:,:).'
Mesh::Node2NodeGraph_2
std::vector< std::vector< int > > Node2NodeGraph_2() const
Definition: geom.cpp:631
Mesh::Ndims
int Ndims() const
Definition: geom.h:98
e
angle in trangle e
Definition: square_bb_4.m:62
Mesh::DeriveEdgeFromVertexBased
void DeriveEdgeFromVertexBased()
Definition: geom.h:362
Mesh::_bedges
std::vector< int > _bedges
boundary edges [nbedges][2] storing start/end vertex
Definition: geom.h:432
Mesh::Resize_Coords
void Resize_Coords(int nnodes, int ndim)
Definition: geom.h:140
Mesh::Index_BoundaryNodes
virtual std::vector< int > Index_BoundaryNodes() const
Definition: geom.cpp:286
Mesh::Resize_Connectivity
void Resize_Connectivity(int nelem, int nvert_e)
Definition: geom.h:109
Mesh::ReadVertexBasedMesh
void ReadVertexBasedMesh(std::string const &fname)
Definition: geom.cpp:712
Mesh::_ebedges
std::vector< int > _ebedges
boundary edges [nbedges]
Definition: geom.h:444
Mesh::PermuteVertices_EdgeBased
void PermuteVertices_EdgeBased(std::vector< int > const &old2new)
Definition: geom.cpp:1033
RefinedMesh::_nref
int _nref
number of regular refinements performed
Definition: geom.h:539
Mesh::GetConnectivity
const std::vector< int > & GetConnectivity() const
Definition: geom.h:120
fname
end fname
Definition: visualize_par_results.m:44
Mesh::Del_EdgeConnectivity
void Del_EdgeConnectivity()
Definition: geom.cpp:800
Mesh::_sdedges
std::vector< int > _sdedges
boundary edges [nbedges][2] with left/right subdomain number
Definition: geom.h:434
RefinedMesh::_ibref
const std::vector< bool > _ibref
refinement info
Definition: geom.h:538
RefinedMesh::RefineAllElements
void RefineAllElements(int nref=1)
Definition: geom.cpp:861
Mesh::Nedges
int Nedges() const
Definition: geom.h:227
Mesh
Definition: geom.h:13
Mesh::_nedge_e
int _nedge_e
number of edges per element
Definition: geom.h:440
Mesh::SetValues
void SetValues(std::vector< double > &v, const std::function< double(double, double)> &func) const
Definition: geom.cpp:32
Mesh::_ia
std::vector< int > _ia
element connectivity
Definition: geom.h:427
cuthill_mckee_reordering
vector< int > cuthill_mckee_reordering(vector< int > const &_edges)
Definition: cuthill_mckee_ordering.cpp:168
Mesh::Node2NodeGraph_1
std::vector< std::vector< int > > Node2NodeGraph_1() const
Definition: geom.cpp:672
Mesh::DeriveEdgeFromVertexBased_slow
void DeriveEdgeFromVertexBased_slow()
Definition: geom.cpp:514
Mesh_2d_3_square::Mesh_2d_3_square
Mesh_2d_3_square(int nx, int ny, int myid=0, int procx=1, int procy=1)
Definition: geom.cpp:1099
Mesh_2d_3_square::_neigh
std::array< int, 4 > _neigh
MPI ranks of neighbors (negative: no neighbor but b.c.)
Definition: geom.h:696
Mesh_2d_3_square::Index_BoundaryNodes
std::vector< int > Index_BoundaryNodes() const override
Definition: geom.cpp:1199
Mesh::SetDirchletValues
void SetDirchletValues(std::vector< double > &v, const std::function< double(double, double)> &func) const
Definition: geom.cpp:52
Mesh::Mesh
Mesh(int ndim, int nvert_e=0, int ndof_e=0, int nedge_e=0)
Definition: geom.cpp:21
Mesh::Nnodes
int Nnodes() const
Definition: geom.h:89
u
u
Definition: laplacian.m:3
v
v
Definition: ascii_read_meshvector.m:40
Mesh::_ndim
int _ndim
space dimension of the problem (1, 2, or 3)
Definition: geom.h:426
Mesh_2d_3_square::~Mesh_2d_3_square
~Mesh_2d_3_square() override
Definition: geom.cpp:1136
Mesh_2d_3_square::_nx
int _nx
number of intervals in x-direction
Definition: geom.h:703
Mesh_2d_3_square::SetU
void SetU(std::vector< double > &u) const
Definition: geom.cpp:1140
RefinedMesh::RefineElements
Mesh RefineElements(std::vector< bool > const &ibref)
Definition: geom.cpp:835
Mesh_2d_3_square::SetF
void SetF(std::vector< double > &f) const
Definition: geom.cpp:1154
Mesh::_nvert_e
int _nvert_e
number of vertices per element
Definition: geom.h:423
Mesh_2d_3_square::GetConnectivityInRectangle
void GetConnectivityInRectangle(int nx, int ny, int ia[])
Definition: geom.cpp:1254
Mesh::Visualize
virtual void Visualize(std::vector< double > const &v) const
Definition: geom.cpp:239
Mesh::SetNedge
void SetNedge(int nedge)
Definition: geom.h:343
Mesh_2d_3_square::_myid
int _myid
my MPI rank
Definition: geom.h:693
Mesh::~Mesh
virtual ~Mesh()
Definition: geom.cpp:29
gMesh_Hierarchy::gMesh_Hierarchy
gMesh_Hierarchy(Mesh const &cmesh, int nlevel)
Definition: geom.cpp:1081
vdop.h
Mesh_2d_3_square::SaveVectorP
void SaveVectorP(std::string const &name, std::vector< double > const &u) const
Definition: geom.cpp:1208
ndim
ndim
Definition: ascii_read_meshvector.m:23
Mesh::_ndof_e
int _ndof_e
degrees of freedom (d.o.f.) per element
Definition: geom.h:424
geom.h
cuthill_mckee_ordering.h
ia
ia
Definition: ascii_read_meshvector.m:35
Mesh::DeriveEdgeFromVertexBased_fast
void DeriveEdgeFromVertexBased_fast()
Definition: geom.cpp:412
RefinedMesh::~RefinedMesh
virtual ~RefinedMesh() override
Definition: geom.cpp:832
RefinedMesh::Check_array_dimensions
bool Check_array_dimensions() const override
Definition: geom.cpp:1069
nnode
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
Definition: ascii_write_mesh.m:23
Mesh::_nelem
int _nelem
number elements
Definition: geom.h:422
Mesh_2d_3_square::Index_DirichletNodes
std::vector< int > Index_DirichletNodes() const override
Definition: geom.cpp:1169
RefinedMesh::_vfathers
std::vector< int > _vfathers
stores the 2 fathers of each vertex (equal fathers denote original coarse vertex)
Definition: geom.h:540
Mesh_2d_3_square::GetCoordsInRectangle
void GetCoordsInRectangle(int nx, int ny, double xl, double xr, double yb, double yt, double xc[])
Definition: geom.cpp:1233
Mesh::SetNnode
void SetNnode(int nnode)
Definition: geom.h:333
Mesh::Check_array_dimensions
virtual bool Check_array_dimensions() const
Definition: geom.cpp:782
Mesh::NverticesElements
int NverticesElements() const
Definition: geom.h:71
gMesh_Hierarchy::_gmesh
std::vector< std::shared_ptr< Mesh > > _gmesh
mesh hierarchy from coarse ([0]) to fine.
Definition: geom.h:599
Mesh_2d_3_square::_ny
int _ny
number of intervals in y-direction
Definition: geom.h:704
nelem
nelem
Definition: ascii_read_meshvector.m:24
Mesh::DeriveEdgeFromVertexBased_fast_2
void DeriveEdgeFromVertexBased_fast_2()
Definition: geom.cpp:298
Mesh::Debug
void Debug() const
Definition: geom.cpp:64
Mesh::Index_DirichletNodes
virtual std::vector< int > Index_DirichletNodes() const
Definition: geom.cpp:260
Mesh::DebugEdgeBased
void DebugEdgeBased() const
Definition: geom.cpp:90
nvert_e
nvert_e
Definition: ascii_write_mesh.m:26
Mesh::_nnode
int _nnode
number nodes/vertices
Definition: geom.h:425
Mesh::_xc
std::vector< double > _xc
coordinates
Definition: geom.h:428
RefinedMesh::RefinedMesh
RefinedMesh(Mesh const &cmesh, std::vector< bool > const &ibref)
Definition: geom.cpp:816
Mesh::GetCoords
const std::vector< double > & GetCoords() const
Definition: geom.h:151
RefinedMesh::PermuteVertices_EdgeBased
void PermuteVertices_EdgeBased(std::vector< int > const &old2new)
Definition: geom.cpp:1055
Mesh::Nelems
int Nelems() const
Definition: geom.h:62