Hermes2D  2.0
mesh.cpp
1 // This file is part of Hermes2D.
2 //
3 // Hermes2D is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // Hermes2D is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Hermes2D. If not, see <http://www.gnu.org/licenses/>.
15 
16 #include "mesh.h"
17 #include "refmap.h"
18 #include <algorithm>
19 #include "global.h"
20 #include "api2d.h"
21 #include "mesh_reader_h2d.h"
22 
23 namespace Hermes
24 {
25  namespace Hermes2D
26  {
27 
28  static const int H2D_DG_INNER_EDGE_INT = -1234567;
29  static const std::string H2D_DG_INNER_EDGE = "-1234567";
30 
32  {
33  assert(type == HERMES_TYPE_VERTEX);
34  return ref <= 3 && !bnd;
35  }
36 
37  void Node::ref_element(Element* e)
38  {
39  if(type == HERMES_TYPE_EDGE)
40  {
41  // store the element pointer in a free slot of 'elem'
42  if(elem[0] == NULL) elem[0] = e;
43  else
44  {
45  if(elem[1] == NULL)
46  elem[1] = e;
47  else
48  throw Hermes::Exceptions::Exception(false, "No free slot 'elem'");
49  }
50  }
51  ref++;
52  }
53 
54  void Node::unref_element(HashTable* ht, Element* e)
55  {
56  if(type == HERMES_TYPE_VERTEX)
57  {
58  if(!--ref) ht->remove_vertex_node(id);
59  }
60  else
61  {
62  // remove the element from the array 'elem'
63  if(elem[0] == e) elem[0] = NULL;
64  else if(elem[1] == e) elem[1] = NULL;
65 
66  if(!--ref) ht->remove_edge_node(id);
67  }
68  }
69 
71  {
72  for (unsigned int i = 0; i < nvert; i++)
73  {
74  vn[i]->ref_element();
75  en[i]->ref_element(this);
76  }
77  this->areaCalculated = false;
78  this->diameterCalculated = false;
79  }
80 
81  int Element::get_edge_orientation(int ie) const
82  {
83  return (this->vn[ie]->id < this->vn[this->next_vert(ie)]->id) ? 0 : 1;
84  }
85 
87  {
88  for (unsigned int i = 0; i < nvert; i++)
89  {
90  vn[i]->unref_element(ht);
91  en[i]->unref_element(ht, this);
92  }
93  this->areaCalculated = false;
94  this->diameterCalculated = false;
95  }
96 
97  Element::Element() : visited(false), area(0.0), diameter(0.0)
98  {
99  };
100 
101  bool Element::is_triangle() const
102  {
103  return nvert == 3;
104  }
105 
106  bool Element::is_quad() const
107  {
108  return nvert == 4;
109  }
110 
111  bool Element::is_curved() const
112  {
113  return cm != NULL;
114  }
115 
116  int Element::get_nvert() const
117  {
118  return this->nvert;
119  }
120 
121  ElementMode2D Element::get_mode() const
122  {
123  return (nvert == 3) ? HERMES_MODE_TRIANGLE : HERMES_MODE_QUAD;
124  }
125 
126  int Element::next_vert(int i) const
127  {
128  return (i < (int)nvert-1) ? i + 1 : 0;
129  }
130 
131  int Element::prev_vert(int i) const
132  {
133  return (i > 0) ? i-1 : nvert-1;
134  }
135 
136  bool Element::hsplit() const
137  {
138  if(active)
139  return false;
140  return sons[0] != NULL;
141  }
142 
143  bool Element::vsplit() const
144  {
145  if(active)
146  return false;
147  return sons[2] != NULL;
148  }
149 
150  bool Element::bsplit() const
151  {
152  if(active)
153  return false;
154  return sons[0] != NULL && sons[2] != NULL;
155  }
156 
158  {
159  Element** elem = en[ie]->elem;
160  if(elem[0] == this)
161  return elem[1];
162  if(elem[1] == this)
163  return elem[0];
164  assert(0);
165  return NULL;
166  }
167 
169  {
170  if(!this->areaCalculated)
171  {
172  double ax, ay, bx, by;
173  ax = vn[1]->x - vn[0]->x;
174  ay = vn[1]->y - vn[0]->y;
175  bx = vn[2]->x - vn[0]->x;
176  by = vn[2]->y - vn[0]->y;
177 
178  this->area = 0.5*(ax*by - ay*bx);
179  if(is_quad())
180  {
181  ax = bx; ay = by;
182  bx = vn[3]->x - vn[0]->x;
183  by = vn[3]->y - vn[0]->y;
184 
185  this->area = area + 0.5*(ax*by - ay*bx);
186  }
187  this->areaCalculated = true;
188  }
189  return this->area;
190  }
191 
192  void Element::get_center(double& x, double& y)
193  {
194  // x - coordinate
195  x = this->vn[0]->x + this->vn[1]->x + this->vn[2]->x;
196  if(this->is_quad())
197  {
198  x += this->vn[3]->x;
199  x = x / 4.0;
200  }
201  else
202  x = x / 3.0;
203 
204  // y - coordinate
205  y = this->vn[0]->y + this->vn[1]->y + this->vn[2]->y;
206  if(this->is_quad())
207  {
208  y += this->vn[3]->y;
209  y = y / 4.0;
210  }
211  else
212  y = y / 3.0;
213  }
214 
216  {
217  if(!this->diameterCalculated)
218  {
219  double max, l;
220  if(is_triangle())
221  {
222  max = 0.0;
223  for (int i = 0; i < 3; i++)
224  {
225  int j = next_vert(i);
226  l = sqr(vn[i]->x - vn[j]->x) + sqr(vn[i]->y - vn[j]->y);
227  if(l > max)
228  max = l;
229  }
230  }
231  else
232  {
233  max = sqr(vn[0]->x - vn[2]->x) + sqr(vn[0]->y - vn[2]->y);
234  l = sqr(vn[1]->x - vn[3]->x) + sqr(vn[1]->y - vn[3]->y);
235  if(l > max)
236  max = l;
237  }
238  diameter = sqrt(max);
239  this->diameterCalculated = true;
240  }
241  return this->diameter;
242  }
243 
244  unsigned g_mesh_seq = 0;
245 
246  Mesh::Mesh() : HashTable()
247  {
248  nbase = nactive = ntopvert = ninitial = 0;
249  seq = g_mesh_seq++;
250  }
251 
252  Mesh::~Mesh()
253  {
254  free();
255  }
256 
257  bool Mesh::isOkay() const
258  {
259  bool okay = true;
260 
261  if(this->elements.get_size() < 1)
262  okay = false;
263  if(this->nodes.get_size() < 1)
264  okay = false;
265  if(seq < 0)
266  okay = false;
267  return okay;
268  }
269 
270  Mesh::ReferenceMeshCreator::ReferenceMeshCreator(Mesh* coarse_mesh, int refinement) : coarse_mesh(coarse_mesh), refinement(refinement)
271  {
272  }
273 
275  {
276  Mesh* ref_mesh = new Mesh;
277  ref_mesh->copy(this->coarse_mesh);
278  ref_mesh->refine_all_elements(refinement, false);
279  return ref_mesh;
280  }
281 
282  void Mesh::initial_single_check()
283  {
284  RefMap r;
285  Element* e;
286  Quad2D* quad = &g_quad_2d_std;
287  for_all_active_elements(e, this)
288  {
289  r.set_active_element(e);
290 
291  int i, o, mo = quad->get_max_order(e->get_mode());
292 
293  int k = e->is_triangle() ? 2 : 3;
294 
295  double const_m[2][2] =
296  {
297  { e->vn[1]->x - e->vn[0]->x, e->vn[k]->x - e->vn[0]->x },
298  { e->vn[1]->y - e->vn[0]->y, e->vn[k]->y - e->vn[0]->y }
299  };
300 
301  double const_jacobian = 0.25 * (const_m[0][0] * const_m[1][1] - const_m[0][1] * const_m[1][0]);
302  double2x2 const_inv_ref_map;
303  if(const_jacobian <= 0.0)
304  throw Hermes::Exceptions::MeshLoadFailureException("Element #%d is concave or badly oriented in initial_single_check().", e->id);
305 
306  // check first the positivity of the jacobian
307  double3* pt = quad->get_points(mo, e->get_mode());
308  double2x2* m = r.get_inv_ref_map(mo);
309  double* jac = r.get_jacobian(mo);
310  for (i = 0; i < quad->get_num_points(mo, e->get_mode()); i++)
311  if(jac[i] <= 0.0)
312  throw Hermes::Exceptions::MeshLoadFailureException("Element #%d is concave or badly oriented in initial_single_check().", e->id);
313  }
314  }
315 
316  void Mesh::initial_multimesh_check(Hermes::vector<Mesh*> meshes)
317  {
318  }
319 
320  void Mesh::create(int nv, double2* verts, int nt, int3* tris, std::string* tri_markers,
321  int nq, int4* quads, std::string* quad_markers, int nm, int2* mark, std::string* boundary_markers)
322  {
323  free();
324 
325  // initialize hash table
326  int size = 16;
327  while (size < 2*nv) size *= 2;
328  init(size);
329 
330  // create vertex nodes
331  for (int i = 0; i < nv; i++)
332  {
333  Node* node = nodes.add();
334  assert(node->id == i);
335  node->ref = TOP_LEVEL_REF;
336  node->type = HERMES_TYPE_VERTEX;
337  node->bnd = 0;
338  node->p1 = node->p2 = -1;
339  node->next_hash = NULL;
340  node->x = verts[i][0];
341  node->y = verts[i][1];
342  }
343  ntopvert = nv;
344 
345  // create triangles
346  Element* e;
347  for (int i = 0; i < nt; i++)
348  {
349  this->element_markers_conversion.insert_marker(this->element_markers_conversion.min_marker_unused, tri_markers[i]);
350 
351  e = create_triangle(this->element_markers_conversion.get_internal_marker(tri_markers[i]).marker, &nodes[tris[i][0]], &nodes[tris[i][1]],
352  &nodes[tris[i][2]], NULL);
353  }
354 
355  // create quads
356  for (int i = 0; i < nq; i++)
357  {
358  this->element_markers_conversion.insert_marker(this->element_markers_conversion.min_marker_unused, quad_markers[i]);
359 
360  e = create_quad(this->element_markers_conversion.get_internal_marker(quad_markers[i]).marker, &nodes[quads[i][0]], &nodes[quads[i][1]],
361  &nodes[quads[i][2]], &nodes[quads[i][3]], NULL);
362  }
363 
364  // set boundary markers
365  for (int i = 0; i < nm; i++)
366  {
367  Node* en = peek_edge_node(mark[i][0], mark[i][1]);
368  if(en == NULL)
369  throw Hermes::Exceptions::Exception("Boundary data error (edge does not exist)");
370 
371  this->boundary_markers_conversion.insert_marker(this->boundary_markers_conversion.min_marker_unused, boundary_markers[i]);
372 
373  en->marker = this->boundary_markers_conversion.get_internal_marker(boundary_markers[i]).marker;
374 
375  nodes[mark[i][0]].bnd = 1;
376  nodes[mark[i][1]].bnd = 1;
377  en->bnd = 1;
378  }
379 
380  nbase = nactive = ninitial = nt + nq;
381  seq = g_mesh_seq++;
382  }
383 
385  {
386  if(this == NULL) throw Hermes::Exceptions::Exception("this == NULL in Mesh::get_num_elements().");
387  if(this->seq < 0)
388  return -1;
389  else
390  return elements.get_num_items();
391  }
392 
395  {
396  if(this == NULL) throw Hermes::Exceptions::Exception("this == NULL in Mesh::get_num_base_elements().");
397 
398  if(this->seq < 0)
399  return -1;
400  else
401  return nbase;
402  }
403 
406  {
407  int toReturn = 0;
408  if(this == NULL)
409  throw Hermes::Exceptions::Exception("this == NULL in Mesh::get_num_base_elements().");
410 
411  if(this->seq < 0)
412  return -1;
413  else
414  {
415  Element* e;
416  for_all_base_elements(e, this)
417  toReturn++;
418  }
419  return toReturn;
420  }
421 
424  {
425  if(this == NULL)
426  throw Hermes::Exceptions::Exception("this == NULL in Mesh::get_num_active_elements().");
427  if(this->seq < 0)
428  return -1;
429  else
430  return nactive;
431  }
432 
435  {
436  if(this == NULL)
437  throw Hermes::Exceptions::Exception("this == NULL in Mesh::get_max_element_id().");
438  if(this->seq < 0)
439  return -1;
440  else
441  return elements.get_size();
442  }
443 
445  {
446  if(this == NULL)
447  throw Hermes::Exceptions::Exception("this == NULL in Mesh::get_num_vertex_nodes().");
448  if(this->seq < 0)
449  return -1;
450  else
451  {
452  int to_return = 0;
453  for (int i = 0; i < this->get_num_nodes(); i++)
454  {
455  if(get_node(i)->used && !get_node(i)->type)
456  to_return++;
457  }
458  return to_return;
459  }
460  }
461 
463  {
464  if(this == NULL)
465  throw Hermes::Exceptions::Exception("this == NULL in Mesh::get_num_vertex_nodes().");
466  if(this->seq < 0)
467  return -1;
468  else
469  {
470  int to_return = 0;
471  for (int i = 0; i < this->get_num_nodes(); i++)
472  {
473  if(get_node(i)->used && get_node(i)->type)
474  to_return++;
475  }
476  return to_return;
477  }
478  }
479 
480  Element* Mesh::get_element(int id) const
481  {
482  if(id < 0 || id >= elements.get_size())
483  throw Hermes::Exceptions::Exception("Invalid element ID %d, current range:[0; %d]", id, elements.get_size());
484  return &(elements[id]);
485  }
486 
487  unsigned Mesh::get_seq() const
488  {
489  return seq;
490  }
491 
492  void Mesh::set_seq(unsigned seq)
493  {
494  this->seq = seq;
495  }
496 
498  {
499  return &(elements[id]);
500  }
501 
502  int Mesh::get_edge_sons(Element* e, int edge, int& son1, int& son2) const
503  {
504  assert(!e->active);
505 
506  if(!e->is_triangle())
507  {
508  if(e->sons[2] == NULL) // horz quad
509  {
510  if(edge == 0 || edge == 2) { son1 = edge >> 1; return 1; }
511  else if(edge == 1) { son1 = 0; son2 = 1; return 2; }
512  else { son1 = 1; son2 = 0; return 2; }
513  }
514  else if(e->sons[0] == NULL) // vert quad
515  {
516  if(edge == 1 || edge == 3) { son1 = (edge == 1) ? 3 : 2; return 1; }
517  else if(edge == 0) { son1 = 2; son2 = 3; return 2; }
518  else { son1 = 3; son2 = 2; return 2; }
519  }
520  }
521 
522  // triangle or 4-son quad
523  son1 = edge;
524  son2 = e->next_vert(edge);
525  return 2;
526  }
527 
528  Element* Mesh::create_triangle(int marker, Node* v0, Node* v1, Node* v2, CurvMap* cm, int id)
529  {
530  // create a new element
531  Element* e = elements.add();
532 
533  if(id != -1)
534  e->id = id;
535 
536  // initialize the new element
537  e->active = 1;
538  e->marker = marker;
539  e->nvert = 3;
540  e->iro_cache = -1;
541  e->cm = cm;
542  e->parent = NULL;
543  e->visited = false;
544 
545  // set vertex and edge node pointers
546  if(v0 == v1 || v1 == v2 || v2 == v0)
547  throw Hermes::Exceptions::MeshLoadFailureException("Some of the vertices of element #%d are identical which is impossible.", e->id);
548  e->vn[0] = v0;
549  e->vn[1] = v1;
550  e->vn[2] = v2;
551 
552  e->en[0] = get_edge_node(v0->id, v1->id);
553  e->en[1] = get_edge_node(v1->id, v2->id);
554  e->en[2] = get_edge_node(v2->id, v0->id);
555 
556  // register in the nodes
557  e->ref_all_nodes();
558 
559  return e;
560  }
561 
562  Element* Mesh::create_quad(int marker, Node* v0, Node* v1, Node* v2, Node* v3,
563  CurvMap* cm, int id)
564  {
565  // create a new element
566  Element* e = elements.add();
567 
568  if(id != -1)
569  e->id = id;
570 
571  // initialize the new element
572  e->active = 1;
573  e->marker = marker;
574  e->nvert = 4;
575  e->iro_cache = -1;
576  e->cm = cm;
577  e->parent = NULL;
578  e->visited = false;
579 
580  // set vertex and edge node pointers
581  if(v0 == v1 || v1 == v2 || v2 == v3 || v3 == v0 || v2 == v0 || v3 == v1)
582  throw Hermes::Exceptions::MeshLoadFailureException("Some of the vertices of element #%d are identical which is impossible.", e->id);
583  e->vn[0] = v0;
584  e->vn[1] = v1;
585  e->vn[2] = v2;
586  e->vn[3] = v3;
587 
588  e->en[0] = get_edge_node(v0->id, v1->id);
589  e->en[1] = get_edge_node(v1->id, v2->id);
590  e->en[2] = get_edge_node(v2->id, v3->id);
591  e->en[3] = get_edge_node(v3->id, v0->id);
592 
593  // register in the nodes
594  e->ref_all_nodes();
595 
596  return e;
597  }
598 
599  CurvMap* create_son_curv_map(Element* e, int son)
600  {
601  // if the top three bits of part are nonzero, we would overflow
602  // -- make the element non-curvilinear
603  if(e->cm->part & 0xe000000000000000ULL)
604  return NULL;
605 
606  // if the parent element is already almost straight-edged,
607  // the son will be even more straight-edged
608  if(e->iro_cache == 0)
609  return NULL;
610 
611  CurvMap* cm = new CurvMap;
612  if(e->cm->toplevel == false)
613  {
614  cm->parent = e->cm->parent;
615  cm->part = (e->cm->part << 3) + son + 1;
616  }
617  else
618  {
619  cm->parent = e;
620  cm->part = (son + 1);
621  }
622  cm->toplevel = false;
623  cm->order = 4;
624 
625  return cm;
626  }
627 
628  void Mesh::refine_triangle_to_triangles(Element* e, Element** sons_out)
629  {
630  // remember the markers of the edge nodes
631  int bnd[3] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd };
632  int mrk[3] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker };
633 
634  // obtain three mid-edge vertex nodes
635  Node* x0, *x1, *x2;
636  x0 = get_vertex_node(e->vn[0]->id, e->vn[1]->id);
637  x1 = get_vertex_node(e->vn[1]->id, e->vn[2]->id);
638  x2 = get_vertex_node(e->vn[2]->id, e->vn[0]->id);
639 
640  CurvMap* cm[H2D_MAX_NUMBER_EDGES];
641  memset(cm, 0, sizeof(cm));
642 
643  // adjust mid-edge coordinates if this is a curved element
644  if(e->is_curved())
645  {
646  double2 pt[3] = { { 0.0, -1.0 }, { 0.0, 0.0 }, { -1.0, 0.0 } };
647  e->cm->get_mid_edge_points(e, pt, 3);
648  x0->x = pt[0][0]; x0->y = pt[0][1];
649  x1->x = pt[1][0]; x1->y = pt[1][1];
650  x2->x = pt[2][0]; x2->y = pt[2][1];
651 
652  // create CurvMaps for sons (pointer to parent element, part)
653  for (int i = 0; i < 4; i++)
654  cm[i] = create_son_curv_map(e, i);
655  }
656 
657  // create the four sons
658  Element* sons[H2D_MAX_ELEMENT_SONS];
659  sons[0] = create_triangle(e->marker, e->vn[0], x0, x2, cm[0]);
660  sons[1] = create_triangle(e->marker, x0, e->vn[1], x1, cm[1]);
661  sons[2] = create_triangle(e->marker, x2, x1, e->vn[2], cm[2]);
662  sons[3] = create_triangle(e->marker, x1, x2, x0, cm[3]);
663 
664  // update coefficients of curved reference mapping
665  for (int i = 0; i < 4; i++)
666  if(sons[i]->is_curved())
667  sons[i]->cm->update_refmap_coeffs(sons[i]);
668 
669  // deactivate this element and unregister from its nodes
670  e->active = 0;
671  this->nactive += 3;
672  e->unref_all_nodes(this);
673 
674  // now the original edge nodes may no longer exist...
675  // set correct boundary status and markers for the new nodes
676  sons[0]->en[0]->bnd = bnd[0]; sons[0]->en[0]->marker = mrk[0];
677  sons[0]->en[2]->bnd = bnd[2]; sons[0]->en[2]->marker = mrk[2];
678  sons[1]->en[0]->bnd = bnd[0]; sons[1]->en[0]->marker = mrk[0];
679  sons[1]->en[1]->bnd = bnd[1]; sons[1]->en[1]->marker = mrk[1];
680  sons[2]->en[1]->bnd = bnd[1]; sons[2]->en[1]->marker = mrk[1];
681  sons[2]->en[2]->bnd = bnd[2]; sons[2]->en[2]->marker = mrk[2];
682  sons[3]->vn[0]->bnd = bnd[1];
683  sons[3]->vn[1]->bnd = bnd[2];
684  sons[3]->vn[2]->bnd = bnd[0];
685 
686  //set pointers to parent element for sons
687  for(int i = 0; i < 4; i++)
688  {
689  if(sons[i] != NULL) sons[i]->parent = e;
690  }
691 
692  // copy son pointers (could not have been done earlier because of the union)
693  memcpy(e->sons, sons, 4 * sizeof(Element*));
694 
695  // If sons_out != NULL, copy son pointers there.
696  if(sons_out != NULL)
697  {
698  for(int i = 0; i < 3; i++) sons_out[i] = sons[i];
699  }
700  }
701 
702  Node* get_vertex_node(Node* v1, Node* v2)
703  {
704  // initialize the new Node
705  Node* newnode = new Node();
706  newnode->type = HERMES_TYPE_VERTEX;
707  newnode->ref = 0;
708  newnode->bnd = 0;
709  newnode->p1 = -9999;
710  newnode->p2 = -9999;
711  newnode->x = (v1->x + v2->x) * 0.5;
712  newnode->y = (v1->y + v2->y) * 0.5;
713 
714  return newnode;
715  }
716 
717  Node* get_edge_node()
718  {
719  // initialize the new Node
720  Node* newnode = new Node();
721  newnode->type = HERMES_TYPE_EDGE;
722  newnode->ref = 0;
723  newnode->bnd = 0;
724  newnode->p1 = -9999;
725  newnode->p2 = -9999;
726  newnode->marker = 0;
727  newnode->elem[0] = newnode->elem[1] = NULL;
728 
729  return newnode;
730  }
731 
732  void Mesh::refine_quad(Element* e, int refinement, Element** sons_out)
733  {
734  int i, j;
735  Element* sons[H2D_MAX_ELEMENT_SONS] = {NULL, NULL, NULL, NULL};
736 
737  // remember the markers of the edge nodes
738  int bnd[H2D_MAX_NUMBER_EDGES] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd, e->en[3]->bnd };
739  int mrk[H2D_MAX_NUMBER_EDGES] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker, e->en[3]->marker };
740 
741  // deactivate this element and unregister from its nodes
742  e->active = false;
743  nactive--;
744  e->unref_all_nodes(this);
745 
746  // now the original edge nodes may no longer exist...
748  memset(cm, 0, sizeof(cm));
749 
750  // default refinement: one quad to four quads
751  if(refinement == 0)
752  {
753  // obtain four mid-edge vertex nodes and one mid-element vertex node
754  Node* x0, *x1, *x2, *x3, *mid;
755  x0 = get_vertex_node(e->vn[0]->id, e->vn[1]->id);
756  x1 = get_vertex_node(e->vn[1]->id, e->vn[2]->id);
757  x2 = get_vertex_node(e->vn[2]->id, e->vn[3]->id);
758  x3 = get_vertex_node(e->vn[3]->id, e->vn[0]->id);
759  mid = get_vertex_node(x0->id, x2->id);
760 
761  // adjust mid-edge coordinates if this is a curved element
762  if(e->is_curved())
763  {
764  double2 pt[5] = { { 0.0, -1.0 }, { 1.0, 0.0 }, { 0.0, 1.0 }, { -1.0, 0.0 }, { 0.0, 0.0 } };
765  e->cm->get_mid_edge_points(e, pt, 5);
766  x0->x = pt[0][0]; x0->y = pt[0][1];
767  x1->x = pt[1][0]; x1->y = pt[1][1];
768  x2->x = pt[2][0]; x2->y = pt[2][1];
769  x3->x = pt[3][0]; x3->y = pt[3][1];
770  mid->x = pt[4][0]; mid->y = pt[4][1];
771 
772  // create CurvMaps for sons (pointer to parent element, part)
773  for (i = 0; i < H2D_MAX_ELEMENT_SONS; i++)
774  cm[i] = create_son_curv_map(e, i);
775  }
776 
777  // create the four sons
778  sons[0] = create_quad(e->marker, e->vn[0], x0, mid, x3, cm[0]);
779  sons[1] = create_quad(e->marker, x0, e->vn[1], x1, mid, cm[1]);
780  sons[2] = create_quad(e->marker, mid, x1, e->vn[2], x2, cm[2]);
781  sons[3] = create_quad(e->marker, x3, mid, x2, e->vn[3], cm[3]);
782 
783  // Increase the number of active elements by 4.
784  this->nactive += H2D_MAX_ELEMENT_SONS;
785 
786  // set correct boundary markers for the new edge nodes
787  for (i = 0; i < H2D_MAX_NUMBER_EDGES; i++)
788  {
789  j = (i > 0) ? i-1 : 3;
790  sons[i]->en[j]->bnd = bnd[j]; sons[i]->en[j]->marker = mrk[j];
791  sons[i]->en[i]->bnd = bnd[i]; sons[i]->en[i]->marker = mrk[i];
792  sons[i]->vn[j]->bnd = bnd[j];
793  }
794  }
795 
796  // refinement '1': one quad to two 'horizontal' quads
797  else if(refinement == 1)
798  {
799  Node* x1, *x3;
800  x1 = get_vertex_node(e->vn[1]->id, e->vn[2]->id);
801  x3 = get_vertex_node(e->vn[3]->id, e->vn[0]->id);
802 
803  // adjust mid-edge coordinates if this is a curved element
804  if(e->is_curved())
805  {
806  double2 pt[2] = { { 1.0, 0.0 }, { -1.0, 0.0 } };
807  e->cm->get_mid_edge_points(e, pt, 2);
808  x1->x = pt[0][0]; x1->y = pt[0][1];
809  x3->x = pt[1][0]; x3->y = pt[1][1];
810 
811  // create CurvMaps for sons (pointer to parent element, part)
812  for (i = 0; i < 2; i++)
813  cm[i] = create_son_curv_map(e, i + 4);
814  }
815 
816  sons[0] = create_quad(e->marker, e->vn[0], e->vn[1], x1, x3, cm[0]);
817  sons[1] = create_quad(e->marker, x3, x1, e->vn[2], e->vn[3], cm[1]);
818  sons[2] = sons[3] = NULL;
819 
820  this->nactive += 2;
821 
822  sons[0]->en[0]->bnd = bnd[0]; sons[0]->en[0]->marker = mrk[0];
823  sons[0]->en[1]->bnd = bnd[1]; sons[0]->en[1]->marker = mrk[1];
824  sons[0]->en[3]->bnd = bnd[3]; sons[0]->en[3]->marker = mrk[3];
825  sons[1]->en[1]->bnd = bnd[1]; sons[1]->en[1]->marker = mrk[1];
826  sons[1]->en[2]->bnd = bnd[2]; sons[1]->en[2]->marker = mrk[2];
827  sons[1]->en[3]->bnd = bnd[3]; sons[1]->en[3]->marker = mrk[3];
828  sons[0]->vn[2]->bnd = bnd[1];
829  sons[0]->vn[3]->bnd = bnd[3];
830  }
831 
832  // refinement '2': one quad to two 'vertical' quads
833  else if(refinement == 2)
834  {
835  Node* x0, *x2;
836  x0 = get_vertex_node(e->vn[0]->id, e->vn[1]->id);
837  x2 = get_vertex_node(e->vn[2]->id, e->vn[3]->id);
838 
839  // adjust mid-edge coordinates if this is a curved element
840  if(e->is_curved())
841  {
842  double2 pt[2] = { { 0.0, -1.0 }, { 0.0, 1.0 } };
843  e->cm->get_mid_edge_points(e, pt, 2);
844  x0->x = pt[0][0]; x0->y = pt[0][1];
845  x2->x = pt[1][0]; x2->y = pt[1][1];
846 
847  // create CurvMaps for sons (pointer to parent element, part)
848  for (i = 0; i < 2; i++)
849  cm[i] = create_son_curv_map(e, i + 6);
850  }
851 
852  sons[0] = sons[1] = NULL;
853  sons[2] = create_quad(e->marker, e->vn[0], x0, x2, e->vn[3], cm[0]);
854  sons[3] = create_quad(e->marker, x0, e->vn[1], e->vn[2], x2, cm[1]);
855 
856  this->nactive += 2;
857 
858  sons[2]->en[0]->bnd = bnd[0]; sons[2]->en[0]->marker = mrk[0];
859  sons[2]->en[2]->bnd = bnd[2]; sons[2]->en[2]->marker = mrk[2];
860  sons[2]->en[3]->bnd = bnd[3]; sons[2]->en[3]->marker = mrk[3];
861  sons[3]->en[0]->bnd = bnd[0]; sons[3]->en[0]->marker = mrk[0];
862  sons[3]->en[1]->bnd = bnd[1]; sons[3]->en[1]->marker = mrk[1];
863  sons[3]->en[2]->bnd = bnd[2]; sons[3]->en[2]->marker = mrk[2];
864  sons[2]->vn[1]->bnd = bnd[0];
865  sons[2]->vn[2]->bnd = bnd[2];
866  }
867  else assert(0);
868 
869  // update coefficients of curved reference mapping
870  for (i = 0; i < 4; i++)
871  if(sons[i] != NULL && sons[i]->cm != NULL)
872  sons[i]->cm->update_refmap_coeffs(sons[i]);
873 
874  // optimization: iro never gets worse
875  if(e->iro_cache == 0)
876  for (i = 0; i < 4; i++)
877  if(sons[i] != NULL)
878  sons[i]->iro_cache = 0;
879 
880  // set pointers to parent element for sons
881  for(int i = 0; i < 4; i++)
882  if(sons[i] != NULL) sons[i]->parent = e;
883 
884  // copy son pointers (could not have been done earlier because of the union)
885  memcpy(e->sons, sons, sizeof(sons));
886 
887  // If sons_out != NULL, copy son pointers there.
888  if(sons_out != NULL)
889  {
890  for(int i = 0; i < 4; i++) sons_out[i] = sons[i];
891  }
892  }
893 
894  void Mesh::unrefine_element_internal(Element* e)
895  {
896  this->refinements.push_back(std::pair<unsigned int, int>(e->id, -1));
897  assert(!e->active);
898  unsigned int i;
899  int s1, s2;
900 
901  // obtain markers and bnds from son elements
903  for (unsigned i = 0; i < e->get_nvert(); i++)
904  {
905  get_edge_sons(e, i, s1, s2);
906  assert(e->sons[s1]->active);
907  mrk[i] = e->sons[s1]->en[i]->marker;
908  bnd[i] = e->sons[s1]->en[i]->bnd;
909  }
910 
911  // remove all sons
912  for (i = 0; i < H2D_MAX_ELEMENT_SONS; i++)
913  {
914  Element* son = e->sons[i];
915  if(son != NULL)
916  {
917  son->unref_all_nodes(this);
918  if(son->cm != NULL) delete son->cm;
919  elements.remove(son->id);
920  this->nactive--;
921  }
922  }
923 
924  // recreate edge nodes
925  for (i = 0; i < e->get_nvert(); i++)
926  e->en[i] = this->get_edge_node(e->vn[i]->id, e->vn[e->next_vert(i)]->id);
927 
928  e->ref_all_nodes();
929  e->active = 1;
930  nactive++;
931 
932  // restore edge node markers and bnds
933  for (i = 0; i < e->get_nvert(); i++)
934  {
935  e->en[i]->marker = mrk[i];
936  e->en[i]->bnd = bnd[i];
937  }
938  }
939 
940  void Mesh::refine_element(Element* e, int refinement)
941  {
942  this->refinements.push_back(std::pair<unsigned int, int>(e->id, refinement));
943 
944  if(e->is_triangle())
945  {
946  if(refinement == 3)
947  {
948  refine_triangle_to_quads(this, e);
949  }
950  else
951  {
952  this->refine_triangle_to_triangles(e);
953  }
954  }
955  else refine_quad(e, refinement);
956 
957  this->seq = g_mesh_seq++;
958  }
959 
960  void Mesh::refine_element_id(int id, int refinement)
961  {
962  if(refinement == -1)
963  return;
964  Element* e = this->get_element(id);
965  if(!e->used) throw Hermes::Exceptions::Exception("Invalid element id number.");
966  if(!e->active) throw Hermes::Exceptions::Exception("Attempt to refine element #%d which has been refined already.", e->id);
967  this->refine_element(e, refinement);
968  }
969 
970  void Mesh::refine_all_elements(int refinement, bool mark_as_initial)
971  {
972  Element* e;
973 
974  ninitial = this->get_max_element_id();
975 
976  if(refinement == -1)
977  return;
978 
979  elements.set_append_only(true);
980 
981  for_all_active_elements(e, this)
982  refine_element_id(e->id, refinement);
983 
984  elements.set_append_only(false);
985 
986  if(mark_as_initial)
987  ninitial = this->get_max_element_id();
988  }
989 
990  static int rtb_marker;
991  static bool rtb_aniso;
992  static char* rtb_vert;
993 
994  void Mesh::refine_by_criterion(int (*criterion)(Element*), int depth, bool mark_as_initial)
995  {
996  Element* e;
997  elements.set_append_only(true);
998  for (int r, i = 0; i < depth; i++)
999  {
1000  for_all_active_elements(e, this)
1001  {
1002  if((r = criterion(e)) >= 0)
1003  refine_element_id(e->id, r);
1004  }
1005  }
1006  elements.set_append_only(false);
1007 
1008  if(mark_as_initial)
1009  ninitial = this->get_max_element_id();
1010  }
1011 
1012  static int rtv_id;
1013 
1014  static int rtv_criterion(Element* e)
1015  {
1016  for (unsigned int i = 0; i < e->get_nvert(); i++)
1017  if(e->vn[i]->id == rtv_id)
1018  return 0;
1019  return -1;
1020  }
1021 
1022  void Mesh::refine_towards_vertex(int vertex_id, int depth, bool mark_as_initial)
1023  {
1024  rtv_id = vertex_id;
1025  refine_by_criterion(rtv_criterion, depth);
1026  if(mark_as_initial)
1027  ninitial = this->get_max_element_id();
1028  }
1029 
1030  int rtb_criterion(Element* e)
1031  {
1032  unsigned int i;
1033  for (i = 0; i < e->get_nvert(); i++)
1034  {
1035  if(e->en[i]->marker == rtb_marker || rtb_vert[e->vn[i]->id])
1036  {
1037  break;
1038  }
1039  }
1040 
1041  if(i >= e->get_nvert()) return -1;
1042  // triangle should be split into 3 quads
1043  // if(e->is_triangle() && rtb_tria_to_quad) return 3;
1044  // triangle should be split into 4 triangles or quad should
1045  // be split into 4 quads
1046  if(e->is_triangle() || !rtb_aniso) return 0;
1047 
1048  // quads - anisotropic case 1
1049  if((e->en[0]->marker == rtb_marker && !rtb_vert[e->vn[2]->id] && !rtb_vert[e->vn[3]->id]) ||
1050  (e->en[2]->marker == rtb_marker && !rtb_vert[e->vn[0]->id] && !rtb_vert[e->vn[1]->id]) ||
1051  (e->en[0]->marker == rtb_marker && e->en[2]->marker == rtb_marker &&
1052  e->en[1]->marker != rtb_marker && e->en[3]->marker != rtb_marker)) return 1;
1053 
1054  // quads - anisotropic case 2
1055  if((e->en[1]->marker == rtb_marker && !rtb_vert[e->vn[3]->id] && !rtb_vert[e->vn[0]->id]) ||
1056  (e->en[3]->marker == rtb_marker && !rtb_vert[e->vn[1]->id] && !rtb_vert[e->vn[2]->id]) ||
1057  (e->en[1]->marker == rtb_marker && e->en[3]->marker == rtb_marker &&
1058  e->en[0]->marker != rtb_marker && e->en[2]->marker != rtb_marker)) return 2;
1059 
1060  return 0;
1061  }
1062 
1063  void Mesh::refine_towards_boundary(Hermes::vector<std::string> markers, int depth, bool aniso, bool mark_as_initial)
1064  {
1065  rtb_aniso = aniso;
1066  bool refined = true;
1067 
1068  // refinement: refine all elements to quad elements.
1069  for (int i = 0; i < depth; i++)
1070  {
1071  refined = false;
1072  int size = get_max_node_id() + 1;
1073  rtb_vert = new char[size];
1074  memset(rtb_vert, 0, sizeof(char) * size);
1075 
1076  Element* e;
1077  for_all_active_elements(e, this)
1078  for (unsigned int j = 0; j < e->get_nvert(); j++)
1079  {
1080  bool marker_matched = false;
1081  for(unsigned int marker_i = 0; marker_i < markers.size(); marker_i++)
1082  if(e->en[j]->marker == this->boundary_markers_conversion.get_internal_marker(markers[marker_i]).marker)
1083  marker_matched = true;
1084  if(marker_matched)
1085  {
1086  rtb_vert[e->vn[j]->id] = rtb_vert[e->vn[e->next_vert(j)]->id] = 1;
1087  refined = true;
1088  }
1089  }
1090 
1091  refine_by_criterion(rtb_criterion, 1);
1092  delete [] rtb_vert;
1093  }
1094 
1095  if(mark_as_initial)
1096  ninitial = this->get_max_element_id();
1097  if(!refined)
1098  throw Hermes::Exceptions::Exception("None of the markers in Mesh::refine_towards_boundary found in the Mesh.");
1099  }
1100 
1101  void Mesh::refine_towards_boundary(std::string marker, int depth, bool aniso, bool mark_as_initial)
1102  {
1103  if(marker == HERMES_ANY)
1104  for(std::map<int, std::string>::iterator it = this->boundary_markers_conversion.conversion_table.begin(); it != this->boundary_markers_conversion.conversion_table.end(); ++it)
1105  refine_towards_boundary(it->second, depth, aniso, mark_as_initial);
1106 
1107  else
1108  {
1109  bool refined = true;
1110  rtb_marker = this->boundary_markers_conversion.get_internal_marker(marker).marker;
1111  rtb_aniso = aniso;
1112 
1113  // refinement: refine all elements to quad elements.
1114  for (int i = 0; i < depth; i++)
1115  {
1116  refined = false;
1117  int size = get_max_node_id() + 1;
1118  rtb_vert = new char[size];
1119  memset(rtb_vert, 0, sizeof(char) * size);
1120 
1121  Element* e;
1122  for_all_active_elements(e, this)
1123  for (unsigned int j = 0; j < e->get_nvert(); j++)
1124  {
1125  if(e->en[j]->marker == this->boundary_markers_conversion.get_internal_marker(marker).marker)
1126  {
1127  rtb_vert[e->vn[j]->id] = rtb_vert[e->vn[e->next_vert(j)]->id] = 1;
1128  refined = true;
1129  }
1130  }
1131 
1132  refine_by_criterion(rtb_criterion, 1);
1133  delete [] rtb_vert;
1134  }
1135 
1136  if(mark_as_initial)
1137  ninitial = this->get_max_element_id();
1138  if(!refined)
1139  throw Hermes::Exceptions::Exception("None of the markers in Mesh::refine_towards_boundary found in the Mesh.");
1140  }
1141  }
1142 
1143  void Mesh::refine_in_area(std::string marker, int depth, bool mark_as_initial)
1144  {
1145  Hermes::vector<std::string> markers;
1146  markers.push_back(marker);
1147  this->refine_in_areas(markers, depth, mark_as_initial);
1148  }
1149 
1150  void Mesh::refine_in_areas(Hermes::vector<std::string> markers, int depth, bool mark_as_initial)
1151  {
1152  bool refined = true;
1153  for (int i = 0; i < depth; i++)
1154  {
1155  refined = false;
1156  Element* e;
1157  for_all_active_elements(e, this)
1158  {
1159  for(unsigned int marker_i = 0; marker_i < markers.size(); marker_i++)
1160  if(e->marker == this->element_markers_conversion.get_internal_marker(markers[marker_i]).marker || markers[marker_i] == HERMES_ANY)
1161  {
1162  this->refine_element(e, 0);
1163  refined = true;
1164  }
1165  }
1166  }
1167 
1168  if(mark_as_initial)
1169  ninitial = this->get_max_element_id();
1170  if(!refined)
1171  throw Hermes::Exceptions::Exception("None of the markers in Mesh::refine_in_areas found in the Mesh.");
1172  }
1173 
1175  {
1176  Element* e = get_element(id);
1177  if(!e->used) throw Hermes::Exceptions::Exception("Invalid element id number.");
1178  if(e->active) return;
1179 
1180  for (int i = 0; i < 4; i++)
1181  if(e->sons[i] != NULL)
1182  unrefine_element_id(e->sons[i]->id);
1183 
1184  unrefine_element_internal(e);
1185  seq = g_mesh_seq++;
1186  }
1187 
1188  void Mesh::unrefine_all_elements(bool keep_initial_refinements)
1189  {
1190  // find inactive elements with active sons
1191  Hermes::vector<int> list;
1192  Element* e;
1193  for_all_inactive_elements(e, this)
1194  {
1195  bool found = true;
1196  for (unsigned int i = 0; i < 4; i++)
1197  if(e->sons[i] != NULL &&
1198  (!e->sons[i]->active || (keep_initial_refinements && e->sons[i]->id < ninitial))
1199  )
1200  { found = false; break; }
1201 
1202  if(found) list.push_back(e->id);
1203  }
1204 
1205  // unrefine the found elements
1206  for (unsigned int i = 0; i < list.size(); i++)
1207  unrefine_element_id(list[i]);
1208  }
1209 
1210  Nurbs* Mesh::reverse_nurbs(Nurbs* nurbs)
1211  {
1212  Nurbs* rev = new Nurbs;
1213  *rev = *nurbs;
1214  rev->twin = true;
1215 
1216  rev->pt = new double3[nurbs->np];
1217  for (int i = 0; i < nurbs->np; i++)
1218  {
1219  rev->pt[nurbs->np-1 - i][0] = nurbs->pt[i][0];
1220  rev->pt[nurbs->np-1 - i][1] = nurbs->pt[i][1];
1221  rev->pt[nurbs->np-1 - i][2] = nurbs->pt[i][2];
1222  }
1223 
1224  rev->kv = new double[nurbs->nk];
1225  for (int i = 0; i < nurbs->nk; i++)
1226  rev->kv[i] = nurbs->kv[i];
1227  for (int i = nurbs->degree + 1; i < nurbs->nk - nurbs->degree - 1; i++)
1228  rev->kv[nurbs->nk-1 - i] = 1.0 - nurbs->kv[i];
1229 
1230  rev->arc = nurbs->arc;
1231  rev->angle = -nurbs->angle;
1232  return rev;
1233  }
1234 
1235  double Mesh::vector_length(double a_1, double a_2)
1236  {
1237  return sqrt(sqr(a_1) + sqr(a_2));
1238  }
1239 
1240  bool Mesh::same_line(double p_1, double p_2, double q_1, double q_2, double r_1, double r_2)
1241  {
1242  double pq_1 = q_1 - p_1, pq_2 = q_2 - p_2, pr_1 = r_1 - p_1, pr_2 = r_2 - p_2;
1243  double length_pq = vector_length(pq_1, pq_2);
1244  double length_pr = vector_length(pr_1, pr_2);
1245  double sin_angle = (pq_1*pr_2 - pq_2*pr_1)/(length_pq*length_pr);
1246  if(fabs(sin_angle) < 1e-8) return true;
1247  else return false;
1248  }
1249 
1250  bool Mesh::is_convex(double a_1, double a_2, double b_1, double b_2)
1251  {
1252  if(a_1*b_2 - a_2*b_1 > 0) return true;
1253  else return false;
1254  }
1255 
1256  void Mesh::check_triangle(int i, Node *&v0, Node *&v1, Node *&v2)
1257  {
1258  // checking that all edges have nonzero length
1259  double
1260  length_1 = vector_length(v1->x - v0->x, v1->y - v0->y),
1261  length_2 = vector_length(v2->x - v1->x, v2->y - v1->y),
1262  length_3 = vector_length(v0->x - v2->x, v0->y - v2->y);
1263  if(length_1 < 1e-14 || length_2 < 1e-14 || length_3 < 1e-14)
1264  throw Hermes::Exceptions::Exception("Edge of triangular element #%d has length less than 1e-14.", i);
1265 
1266  // checking that vertices do not lie on the same line
1267  if(same_line(v0->x, v0->y, v1->x, v1->y, v2->x, v2->y))
1268  throw Hermes::Exceptions::Exception("Triangular element #%d: all vertices lie on the same line.", i);
1269 
1270  // checking positive orientation. If not positive, swapping vertices
1271  if(!is_convex(v1->x - v0->x, v1->y - v0->y, v2->x - v0->x, v2->y - v0->y))
1272  {
1273  std::swap(v1, v2);
1274  }
1275  }
1276 
1277  void Mesh::check_quad(int i, Node *&v0, Node *&v1, Node *&v2, Node *&v3)
1278  {
1279  // checking that all edges have nonzero length
1280  double
1281  length_1 = vector_length(v1->x - v0->x, v1->y - v0->y),
1282  length_2 = vector_length(v2->x - v1->x, v2->y - v1->y),
1283  length_3 = vector_length(v3->x - v2->x, v3->y - v2->y),
1284  length_4 = vector_length(v0->x - v3->x, v0->y - v3->y);
1285  if(length_1 < 1e-14 || length_2 < 1e-14 || length_3 < 1e-14 || length_4 < 1e-14)
1286  throw Hermes::Exceptions::Exception("Edge of quad element #%d has length less than 1e-14.", i);
1287 
1288  // checking that both diagonals have nonzero length
1289  double
1290  diag_1 = vector_length(v2->x - v0->x, v2->y - v0->y),
1291  diag_2 = vector_length(v3->x - v1->x, v3->y - v1->y);
1292  if(diag_1 < 1e-14 || diag_2 < 1e-14)
1293  throw Hermes::Exceptions::Exception("Diagonal of quad element #%d has length less than 1e-14.", i);
1294 
1295  // checking that vertices v0, v1, v2 do not lie on the same line
1296  if(same_line(v0->x, v0->y, v1->x, v1->y, v2->x, v2->y))
1297  throw Hermes::Exceptions::Exception("Quad element #%d: vertices v0, v1, v2 lie on the same line.", i);
1298  // checking that vertices v0, v1, v3 do not lie on the same line
1299  if(same_line(v0->x, v0->y, v1->x, v1->y, v3->x, v3->y))
1300  throw Hermes::Exceptions::Exception("Quad element #%d: vertices v0, v1, v3 lie on the same line.", i);
1301  // checking that vertices v0, v2, v3 do not lie on the same line
1302  if(same_line(v0->x, v0->y, v2->x, v2->y, v3->x, v3->y))
1303  throw Hermes::Exceptions::Exception("Quad element #%d: vertices v0, v2, v3 lie on the same line.", i);
1304  // checking that vertices v1, v2, v3 do not lie on the same line
1305  if(same_line(v1->x, v1->y, v2->x, v2->y, v3->x, v3->y))
1306  throw Hermes::Exceptions::Exception("Quad element #%d: vertices v1, v2, v3 lie on the same line.", i);
1307 
1308  // checking that vertex v1 lies on the right of the diagonal v2-v0
1309  int vertex_1_ok = is_convex(v1->x - v0->x, v1->y - v0->y, v2->x - v0->x, v2->y - v0->y);
1310  if(!vertex_1_ok) throw Hermes::Exceptions::Exception("Vertex v1 of quad element #%d does not lie on the right of the diagonal v2-v0.", i);
1311  // checking that vertex v3 lies on the left of the diagonal v2-v0
1312  int vertex_3_ok = is_convex(v2->x - v0->x, v2->y - v0->y, v3->x - v0->x, v3->y - v0->y);
1313  if(!vertex_3_ok) throw Hermes::Exceptions::Exception("Vertex v3 of quad element #%d does not lie on the left of the diagonal v2-v0.", i);
1314  // checking that vertex v2 lies on the right of the diagonal v3-v1
1315  int vertex_2_ok = is_convex(v2->x - v1->x, v2->y - v1->y, v3->x - v1->x, v3->y - v1->y);
1316  if(!vertex_2_ok) throw Hermes::Exceptions::Exception("Vertex v2 of quad element #%d does not lie on the right of the diagonal v3-v1.", i);
1317  // checking that vertex v0 lies on the left of the diagonal v3-v1
1318  int vertex_0_ok = is_convex(v3->x - v1->x, v3->y - v1->y, v0->x - v1->x, v0->y - v1->y);
1319  if(!vertex_0_ok) throw Hermes::Exceptions::Exception("Vertex v0 of quad element #%d does not lie on the left of the diagonal v2-v1.", i);
1320  }
1321 
1322  bool Mesh::rescale(double x_ref, double y_ref)
1323  {
1324  // Go through all vertices and rescale coordinates.
1325  Node* n;
1326  for_all_vertex_nodes(n, this) {
1327  n->x /= x_ref;
1328  n->y /= y_ref;
1329  }
1330 
1331  // If curvilinear, throw an exception.
1332  Element* e;
1333  for_all_elements(e, this)
1334  if(e->cm != NULL)
1335  {
1336  throw CurvedException(e->id);
1337  return false;
1338  }
1339  return true;
1340  }
1341 
1342  void Mesh::copy(const Mesh* mesh)
1343  {
1344  unsigned int i;
1345 
1346  free();
1347  // Serves as a Mesh::init() for purposes of pointer calculation.
1348 
1349  // copy nodes and elements
1350  HashTable::copy(mesh);
1351  elements.copy(mesh->elements);
1352 
1353  this->refinements = mesh->refinements;
1354 
1355  Element* e;
1356  for_all_elements(e, this)
1357  {
1358  // update vertex node pointers
1359  for (i = 0; i < e->get_nvert(); i++)
1360  e->vn[i] = &nodes[e->vn[i]->id];
1361 
1362  if(e->active)
1363  {
1364  // update edge node pointers
1365  for (i = 0; i < e->get_nvert(); i++)
1366  e->en[i] = &nodes[e->en[i]->id];
1367  }
1368  else
1369  {
1370  // update son pointers
1371  for (i = 0; i < 4; i++)
1372  if(e->sons[i] != NULL)
1373  e->sons[i] = &elements[e->sons[i]->id];
1374  }
1375 
1376  // copy CurvMap, update its parent
1377  if(e->cm != NULL)
1378  {
1379  e->cm = new CurvMap(e->cm);
1380  if(!e->cm->toplevel)
1381  e->cm->parent = &elements[e->cm->parent->id];
1382  }
1383 
1384  //update parent pointer
1385  if(e->parent != NULL)
1386  e->parent = &elements[e->parent->id];
1387  }
1388 
1389  // update element pointers in edge nodes
1390  Node* node;
1391  for_all_edge_nodes(node, this)
1392  for (i = 0; i < 2; i++)
1393  if(node->elem[i] != NULL)
1394  node->elem[i] = &elements[node->elem[i]->id];
1395 
1396  nbase = mesh->nbase;
1397  nactive = mesh->nactive;
1398  ntopvert = mesh->ntopvert;
1399  ninitial = mesh->ninitial;
1400  seq = mesh->seq;
1401  boundary_markers_conversion = mesh->boundary_markers_conversion;
1402  element_markers_conversion = mesh->element_markers_conversion;
1403  }
1404 
1405  Node* Mesh::get_base_edge_node(Element* base, int edge)
1406  {
1407  while (!base->active) // we need to go down to an active element
1408  {
1409  int son1, son2;
1410  get_edge_sons(base, edge, son1, son2);
1411  base = base->sons[son1];
1412  }
1413  return base->en[edge];
1414  }
1415 
1416  void Mesh::init(int size)
1417  {
1418  HashTable::init(size);
1419  }
1420 
1421  void Mesh::copy_base(Mesh* mesh)
1422  {
1423  //printf("Calling Mesh::free() in Mesh::copy_base().\n");
1424  free();
1425  init();
1426 
1427  // copy top-level vertex nodes
1428  for (int i = 0; i < mesh->get_max_node_id(); i++)
1429  {
1430  Node* node = &(mesh->nodes[i]);
1431  if(node->ref < TOP_LEVEL_REF) break;
1432  Node* newnode = nodes.add();
1433  assert(newnode->id == i && node->type == HERMES_TYPE_VERTEX);
1434  memcpy(newnode, node, sizeof(Node));
1435  newnode->ref = TOP_LEVEL_REF;
1436  }
1437 
1438  // copy base elements
1439  Element* e;
1440  for_all_base_elements(e, mesh)
1441  {
1442  Element* enew;
1443  Node *v0 = &nodes[e->vn[0]->id], *v1 = &nodes[e->vn[1]->id], *v2 = &nodes[e->vn[2]->id];
1444  if(e->is_triangle())
1445  enew = this->create_triangle(e->marker, v0, v1, v2, NULL);
1446  else
1447  enew = this->create_quad(e->marker, v0, v1, v2, &nodes[e->vn[3]->id], NULL);
1448 
1449  // copy edge markers
1450  for (unsigned int j = 0; j < e->get_nvert(); j++)
1451  {
1452  Node* en = get_base_edge_node(e, j);
1453  enew->en[j]->bnd = en->bnd; // copy bnd data from the active el.
1454  enew->en[j]->marker = en->marker;
1455  }
1456 
1457  if(e->is_curved())
1458  enew->cm = new CurvMap(e->cm);
1459  }
1460 
1461  this->boundary_markers_conversion = mesh->boundary_markers_conversion;
1462  this->element_markers_conversion = mesh->element_markers_conversion;
1463 
1464  nbase = nactive = ninitial = mesh->nbase;
1465  ntopvert = mesh->ntopvert;
1466  seq = g_mesh_seq++;
1467  }
1468 
1469  void Mesh::free()
1470  {
1471  Element* e;
1472  for_all_elements(e, this)
1473  {
1474  if(e->cm != NULL)
1475  {
1476  delete e->cm;
1477  e->cm = NULL; // fixme!!!
1478  }
1479  }
1480  elements.free();
1481  HashTable::free();
1482  this->boundary_markers_conversion.conversion_table.clear();
1483  this->boundary_markers_conversion.conversion_table_inverse.clear();
1484  this->element_markers_conversion.conversion_table.clear();
1485  this->element_markers_conversion.conversion_table_inverse.clear();
1486  this->refinements.clear();
1487  this->seq = -1;
1488  }
1489 
1491  {
1492  free();
1493  HashTable::copy(mesh);
1494  this->boundary_markers_conversion = mesh->boundary_markers_conversion;
1495  this->element_markers_conversion = mesh->element_markers_conversion;
1496 
1497  // clear reference for all nodes
1498  for(int i = 0; i < nodes.get_size(); i++)
1499  {
1500  Node& node = nodes[i];
1501  if(node.type == HERMES_TYPE_EDGE) { //process only edge nodes
1502  for(int k = 0; k < 2; k++)
1503  node.elem[k] = NULL;
1504  }
1505  }
1506 
1507  // copy active elements
1508  Element* e;
1509 
1510  for_all_active_elements(e, mesh)
1511  {
1512  Element* enew;
1513  Node *v0 = &nodes[e->vn[0]->id], *v1 = &nodes[e->vn[1]->id], *v2 = &nodes[e->vn[2]->id];
1514  Node *e0 = &nodes[e->en[0]->id], *e1 = &nodes[e->en[1]->id], *e2 = &nodes[e->en[2]->id];
1515  if(e->is_triangle())
1516  {
1517  // create a new element
1518  enew = elements.add();
1519  enew->active = 1;
1520  enew->marker = e->marker;
1521  enew->nvert = 3;
1522  enew->iro_cache = -1;
1523  enew->cm = e->cm;
1524 
1525  // set vertex and edge node pointers
1526  enew->vn[0] = v0;
1527  enew->vn[1] = v1;
1528  enew->vn[2] = v2;
1529  enew->en[0] = e0;
1530  enew->en[1] = e1;
1531  enew->en[2] = e2;
1532  }
1533  else
1534  {
1535  // create a new element
1536  Node *v3 = &nodes[e->vn[3]->id];
1537  Node *e3 = &nodes[e->en[3]->id];
1538  enew = elements.add();
1539  enew->active = 1;
1540  enew->marker = e->marker;
1541  enew->nvert = 4;
1542  enew->iro_cache = -1;
1543  enew->cm = e->cm;
1544  enew->parent = NULL;
1545  enew->visited = false;
1546 
1547  // set vertex and edge node pointers
1548  enew->vn[0] = v0;
1549  enew->vn[1] = v1;
1550  enew->vn[2] = v2;
1551  enew->vn[3] = v3;
1552  enew->en[0] = e0;
1553  enew->en[1] = e1;
1554  enew->en[2] = e2;
1555  enew->en[3] = e3;
1556  }
1557 
1558  // copy edge markers
1559  for (unsigned int j = 0; j < e->get_nvert(); j++)
1560  {
1561  Node* en = get_base_edge_node(e, j);
1562  enew->en[j]->bnd = en->bnd;
1563  enew->en[j]->marker = en->marker;
1564  }
1565 
1566  if(e->is_curved())
1567  enew->cm = new CurvMap(e->cm);
1568  }
1569 
1570  nbase = nactive = ninitial = mesh->nactive;
1571  ntopvert = mesh->ntopvert = get_num_nodes();
1572  seq = g_mesh_seq++;
1573  }
1574 
1575  void Mesh::convert_quads_to_triangles()
1576  {
1577  Element* e;
1578 
1579  elements.set_append_only(true);
1580  for_all_active_elements(e, this)
1581  refine_element_to_triangles_id(e->id);
1582  elements.set_append_only(false);
1583 
1584  Mesh mesh_tmp_for_convert;
1585  mesh_tmp_for_convert.copy_converted(this);
1586  for (int i = 0; i < mesh_tmp_for_convert.ntopvert; i++)
1587  {
1588  if(mesh_tmp_for_convert.nodes[i].type == 1)
1589  {
1590  mesh_tmp_for_convert.nodes[i].y = 0.0;
1591  }
1592  }
1593  MeshReaderH2D loader_mesh_tmp_for_convert;
1594  char* mesh_file_tmp = NULL;
1595  mesh_file_tmp = tmpnam(NULL);
1596  loader_mesh_tmp_for_convert.save(mesh_file_tmp, &mesh_tmp_for_convert);
1597  loader_mesh_tmp_for_convert.load(mesh_file_tmp, &mesh_tmp_for_convert);
1598  remove(mesh_file_tmp);
1599  copy(&mesh_tmp_for_convert);
1600  }
1601 
1602  void Mesh::convert_to_base()
1603  {
1604  Element* e;
1605 
1606  elements.set_append_only(true);
1607  for_all_active_elements(e, this)
1608  convert_element_to_base_id(e->id);
1609  elements.set_append_only(false);
1610 
1611  Mesh mesh_tmp_for_convert;
1612  mesh_tmp_for_convert.copy_converted(this);
1613  for (int i = 0; i < mesh_tmp_for_convert.ntopvert; i++)
1614  {
1615  if(mesh_tmp_for_convert.nodes[i].type == 1)
1616  {
1617  mesh_tmp_for_convert.nodes[i].y = 0.0;
1618  }
1619  }
1620  MeshReaderH2D loader_mesh_tmp_for_convert;
1621  char* mesh_file_tmp = NULL;
1622  mesh_file_tmp = tmpnam(NULL);
1623  loader_mesh_tmp_for_convert.save(mesh_file_tmp, &mesh_tmp_for_convert);
1624  loader_mesh_tmp_for_convert.load(mesh_file_tmp, &mesh_tmp_for_convert);
1625  remove(mesh_file_tmp);
1626  copy(&mesh_tmp_for_convert);
1627  }
1628 
1629  void Mesh::refine_triangle_to_quads(Mesh* mesh, Element* e, Element** sons_out)
1630  {
1631  // remember the markers of the edge nodes
1632  int bnd[3] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd };
1633  int mrk[3] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker };
1634 
1635  // obtain three mid-edge and one gravity vertex nodes
1636  Node* x0 = this->get_vertex_node(e->vn[0]->id, e->vn[1]->id);
1637  Node* x1 = this->get_vertex_node(e->vn[1]->id, e->vn[2]->id);
1638  Node* x2 = this->get_vertex_node(e->vn[2]->id, e->vn[0]->id);
1639  Node* mid = this->get_vertex_node(x0->id, e->vn[1]->id);
1640 
1641  mid->x = (x0->x + x1->x + x2->x)/3;
1642  mid->y = (x0->y + x1->y + x2->y)/3;
1643 
1644  // check if element e is a internal element.
1645  bool e_inter = true;
1646  for (unsigned int n = 0; n < e->get_nvert(); n++)
1647  {
1648  if(bnd[n] == 1)
1649  e_inter = false;
1650  }
1651 
1652  CurvMap* cm[4];
1653  memset(cm, 0, sizeof(cm));
1654 
1655  // adjust mid-edge and gravity coordinates if this is a curved element
1656  if(e->is_curved())
1657  {
1658  if(!e_inter)
1659  {
1660  double2 pt[4] = { { 0.0, -1.0 }, { 0.0, 0.0 }, { -1.0, 0.0 }, { -0.33333333, -0.33333333 } };
1661  e->cm->get_mid_edge_points(e, pt, 4);
1662  x0->x = pt[0][0]; x0->y = pt[0][1];
1663  x1->x = pt[1][0]; x1->y = pt[1][1];
1664  x2->x = pt[2][0]; x2->y = pt[2][1];
1665  mid->x = pt[3][0]; mid->y = pt[3][1];
1666  }
1667  }
1668 
1669  // get the boundary edge angle.
1670  double refinement_angle[3] = {0.0, 0.0, 0.0};
1671  if(e->is_curved() && (!e_inter))
1672  {
1673  // for base element.
1674  if(e->cm->toplevel == true)
1675  {
1676  for (unsigned int n = 0; n < e->get_nvert(); n++)
1677  {
1678  if(e->cm->nurbs[n] != NULL)
1679  {
1680  //this->info("angle = %f", e->cm->nurbs[n]->angle);
1681  refinement_angle[n] = e->cm->nurbs[n]->angle;
1682  }
1683  }
1684  }
1685  else
1686  // one level refinement.
1687  if(e->parent->cm->toplevel == true)
1688  {
1689  for (unsigned int n = 0; n < e->get_nvert(); n++)
1690  {
1691  if(e->parent->cm->nurbs[n] != NULL)
1692  {
1693  //this->info("angle = %f", e->parent->cm->nurbs[n]->angle);
1694  refinement_angle[n] = e->parent->cm->nurbs[n]->angle / 2;
1695  }
1696  }
1697  }
1698  else
1699  // two level refinements.
1700  if(e->parent->parent->cm->toplevel == true)
1701  {
1702  for (unsigned int n = 0; n < e->get_nvert(); n++)
1703  {
1704  if(e->parent->parent->cm->nurbs[n] != NULL)
1705  {
1706  //this->info("angle = %f", e->parent->parent->cm->nurbs[n]->angle);
1707  refinement_angle[n] = e->parent->parent->cm->nurbs[n]->angle / 4;
1708  }
1709  }
1710  }
1711  else
1712  // three level refinements.
1713  if(e->parent->parent->parent->cm->toplevel == true)
1714  {
1715  for (unsigned int n = 0; n < e->get_nvert(); n++)
1716  {
1717  if(e->parent->parent->parent->cm->nurbs[n] != NULL)
1718  {
1719  //this->info("angle = %f", e->parent->parent->parent->cm->nurbs[n]->angle);
1720  refinement_angle[n] = e->parent->parent->parent->cm->nurbs[n]->angle / 8;
1721  }
1722  }
1723  }
1724  else
1725  // four level refinements.
1726  if(e->parent->parent->parent->parent->cm->toplevel == true)
1727  {
1728  for (unsigned int n = 0; n < e->get_nvert(); n++)
1729  {
1730  if(e->parent->parent->parent->parent->cm->nurbs[n] != NULL)
1731  {
1732  //this->info("angle = %f", e->parent->parent->parent->parent->cm->nurbs[n]->angle);
1733  refinement_angle[n] = e->parent->parent->parent->parent->cm->nurbs[n]->angle / 16;
1734  }
1735  }
1736  }
1737  }
1738 
1739  double angle2 = 0.0;
1740  int idx = 0;
1741  // create CurvMaps for sons if this is a curved element
1742  if((e->is_curved()) && (!e_inter))
1743  {
1744  for (idx = 0; idx < 2; idx++)
1745  {
1746  if(e->cm->nurbs[idx] != NULL)
1747  {
1748  cm[idx] = new CurvMap;
1749  memset(cm[idx], 0, sizeof(CurvMap));
1750  cm[idx + 1] = new CurvMap;
1751  memset(cm[idx + 1], 0, sizeof(CurvMap));
1752  }
1753  }
1754 
1755  idx = 0;
1756  if(e->cm->nurbs[idx] != NULL)
1757  {
1758  angle2 = refinement_angle[0] / 2;
1759  Node* node_temp = this->get_vertex_node(e->vn[idx%3]->id, e->vn[(idx + 1)%3]->id);
1760 
1761  for (int k = 0; k < 2; k++)
1762  {
1763  int p1, p2;
1764  int idx2 = 0;
1765 
1766  if(k == 0)
1767  {
1768  p1 = e->vn[(idx)%3]->id;
1769  p2 = node_temp->id;
1770  if(idx == 0) idx2 = 0;
1771  if(idx == 1) idx2 = 1;
1772  if(idx == 2) continue;
1773  }
1774  else
1775  {
1776  p1 = node_temp->id;
1777  p2 = e->vn[(idx + 1)%3]->id;
1778  idx = (idx + 1)%3;
1779  if(idx == 0) continue;
1780  if(idx == 1) idx2 = 0;
1781  if(idx == 2) idx2 = 0;
1782  }
1783 
1784  Nurbs* nurbs = new Nurbs;
1785  bool cricle = true;
1786 
1787  nurbs->arc = cricle;
1788  nurbs->degree = 2;
1789 
1790  int inner = 1, outer = 0;
1791  nurbs->np = inner + 2;
1792  nurbs->pt = new double3[nurbs->np];
1793 
1794  nurbs->pt[0][0] = nodes[p1].x;
1795  nurbs->pt[0][1] = nodes[p1].y;
1796  nurbs->pt[0][2] = 1.0;
1797 
1798  nurbs->pt[inner + 1][0] = nodes[p2].x;
1799  nurbs->pt[inner + 1][1] = nodes[p2].y;
1800  nurbs->pt[inner + 1][2] = 1.0;
1801 
1802  double angle = angle2;
1803  double a = (180.0 - angle) / 180.0 * M_PI;
1804  nurbs->angle = angle;
1805 
1806  // generate one control point
1807  double x = 1.0 / tan(a * 0.5);
1808  nurbs->pt[1][0] = 0.5*((nurbs->pt[2][0] + nurbs->pt[0][0]) + (nurbs->pt[2][1] - nurbs->pt[0][1]) * x);
1809  nurbs->pt[1][1] = 0.5*((nurbs->pt[2][1] + nurbs->pt[0][1]) - (nurbs->pt[2][0] - nurbs->pt[0][0]) * x);
1810  nurbs->pt[1][2] = cos((M_PI - a) * 0.5);
1811 
1812  int i = 0;
1813  inner = 0;
1814  nurbs->nk = nurbs->degree + nurbs->np + 1;
1815  outer = nurbs->nk - inner;
1816 
1817  // knot vector is completed by 0.0 on the left and by 1.0 on the right
1818  nurbs->kv = new double[nurbs->nk];
1819 
1820  for (i = 0; i < outer/2; i++)
1821  nurbs->kv[i] = 0.0;
1822  for (i = outer/2 + inner; i < nurbs->nk; i++)
1823  nurbs->kv[i] = 1.0;
1824  nurbs->ref = 0;
1825 
1826  cm[idx]->toplevel = 1;
1827  cm[idx]->order = 4;
1828  cm[idx]->nurbs[idx2] = nurbs;
1829  nurbs->ref++;
1830  }
1831  }
1832 
1833  idx = 1;
1834  if(e->cm->nurbs[idx] != NULL)
1835  {
1836  angle2 = refinement_angle[1] / 2;
1837  Node* node_temp = this->get_vertex_node(e->vn[idx%3]->id, e->vn[(idx + 1)%3]->id);
1838  for (int k = 0; k < 2; k++)
1839  {
1840  int p1, p2;
1841  int idx2 = 0;
1842  if(k == 0)
1843  {
1844  p1 = e->vn[(idx)%3]->id;
1845  p2 = node_temp->id;
1846  if(idx == 0) idx2 = 0;
1847  if(idx == 1) idx2 = 1;
1848  if(idx == 2) continue;
1849  }
1850  else
1851  {
1852  p1 = node_temp->id;
1853  p2 = e->vn[(idx + 1)%3]->id;
1854  idx = (idx + 1)%3;
1855  if(idx == 0) continue;
1856  if(idx == 1) idx2 = 0;
1857  if(idx == 2) idx2 = 0;
1858  }
1859 
1860  Nurbs* nurbs = new Nurbs;
1861  bool cricle = true;
1862 
1863  nurbs->arc = cricle;
1864  nurbs->degree = 2;
1865  int inner = 1, outer = 0;
1866  nurbs->np = inner + 2;
1867  nurbs->pt = new double3[nurbs->np];
1868 
1869  nurbs->pt[0][0] = nodes[p1].x;
1870  nurbs->pt[0][1] = nodes[p1].y;
1871  nurbs->pt[0][2] = 1.0;
1872 
1873  nurbs->pt[inner + 1][0] = nodes[p2].x;
1874  nurbs->pt[inner + 1][1] = nodes[p2].y;
1875  nurbs->pt[inner + 1][2] = 1.0;
1876 
1877  double angle = angle2;
1878  double a = (180.0 - angle) / 180.0 * M_PI;
1879  nurbs->angle = angle;
1880 
1881  // generate one control point
1882  double x = 1.0 / tan(a * 0.5);
1883  nurbs->pt[1][0] = 0.5*((nurbs->pt[2][0] + nurbs->pt[0][0]) + (nurbs->pt[2][1] - nurbs->pt[0][1]) * x);
1884  nurbs->pt[1][1] = 0.5*((nurbs->pt[2][1] + nurbs->pt[0][1]) - (nurbs->pt[2][0] - nurbs->pt[0][0]) * x);
1885  nurbs->pt[1][2] = cos((M_PI - a) * 0.5);
1886 
1887  int i = 0;
1888  inner = 0;
1889  nurbs->nk = nurbs->degree + nurbs->np + 1;
1890  outer = nurbs->nk - inner;
1891 
1892  // knot vector is completed by 0.0 on the left and by 1.0 on the right
1893  nurbs->kv = new double[nurbs->nk];
1894  for (i = 0; i < outer/2; i++)
1895  nurbs->kv[i] = 0.0;
1896  for (i = outer/2 + inner; i < nurbs->nk; i++)
1897  nurbs->kv[i] = 1.0;
1898  nurbs->ref = 0;
1899 
1900  cm[idx]->toplevel = 1;
1901  cm[idx]->order = 4;
1902  cm[idx]->nurbs[idx2] = nurbs;
1903  nurbs->ref++;
1904  }
1905  }
1906  }
1907 
1908  // create the four sons
1909  Element* sons[3];
1910  sons[0] = mesh->create_quad(e->marker, e->vn[0], x0, mid, x2, cm[0]);
1911  sons[1] = mesh->create_quad(e->marker, x0, e->vn[1], x1, mid, cm[1]);
1912  sons[2] = mesh->create_quad(e->marker, x1, e->vn[2], x2, mid, cm[2]);
1913 
1914  // update coefficients of curved reference mapping
1915  for (int i = 0; i < 3; i++)
1916  if(sons[i]->is_curved())
1917  sons[i]->cm->update_refmap_coeffs(sons[i]);
1918 
1919  // deactivate this element and unregister from its nodes
1920  e->active = 0;
1921  if(mesh != NULL)
1922  {
1923  mesh->nactive += 2;
1924  e->unref_all_nodes(mesh);
1925  }
1926  // now the original edge nodes may no longer exist...
1927 
1928  // set correct boundary status and markers for the new nodes
1929  sons[0]->en[0]->bnd = bnd[0]; sons[0]->en[0]->marker = mrk[0];
1930  sons[0]->en[3]->bnd = bnd[2]; sons[0]->en[3]->marker = mrk[2];
1931  sons[1]->en[0]->bnd = bnd[0]; sons[1]->en[0]->marker = mrk[0];
1932  sons[1]->en[1]->bnd = bnd[1]; sons[1]->en[1]->marker = mrk[1];
1933  sons[2]->en[0]->bnd = bnd[1]; sons[2]->en[0]->marker = mrk[1];
1934  sons[2]->en[1]->bnd = bnd[2]; sons[2]->en[1]->marker = mrk[2];
1935 
1936  //set pointers to parent element for sons
1937  for(int i = 0; i < 3; i++)
1938  {
1939  if(sons[i] != NULL) sons[i]->parent = e;
1940  }
1941 
1942  // copy son pointers (could not have been done earlier because of the union)
1943  memcpy(e->sons, sons, 3 * sizeof(Element*));
1944 
1945  // If sons_out != NULL, copy son pointers there.
1946  if(sons_out != NULL)
1947  {
1948  for(int i = 0; i < 3; i++) sons_out[i] = sons[i];
1949  }
1950  }
1951 
1952  void Mesh::refine_element_to_quads_id(int id)
1953  {
1954  Element* e = get_element(id);
1955  if(!e->used) throw Hermes::Exceptions::Exception("Invalid element id number.");
1956  if(!e->active) throw Hermes::Exceptions::Exception("Attempt to refine element #%d which has been refined already.", e->id);
1957 
1958  if(e->is_triangle())
1959  refine_triangle_to_quads(this, e);
1960  else
1961  refine_quad_to_quads(e);
1962 
1963  seq = g_mesh_seq++;
1964  }
1965 
1966  void Mesh::refine_quad_to_triangles(Element* e)
1967  {
1968  // remember the markers of the edge nodes
1969  int bnd[H2D_MAX_NUMBER_EDGES] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd, e->en[3]->bnd };
1970  int mrk[H2D_MAX_NUMBER_EDGES] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker, e->en[3]->marker };
1971 
1972  // deactivate this element and unregister from its nodes
1973  e->active = false;
1974  nactive--;
1975  e->unref_all_nodes(this);
1976 
1977  bool bcheck = true;
1978 
1979  double length_x_0_2 = (e->vn[0]->x - e->vn[2]->x)*(e->vn[0]->x - e->vn[2]->x);
1980  double length_x_1_3 = (e->vn[1]->x - e->vn[3]->x)*(e->vn[1]->x - e->vn[3]->x);
1981 
1982  double length_y_0_2 = (e->vn[0]->y - e->vn[2]->y)*(e->vn[0]->y - e->vn[2]->y);
1983  double length_y_1_3 = (e->vn[1]->y - e->vn[3]->y)*(e->vn[1]->y - e->vn[3]->y);
1984 
1985  if((length_x_0_2 + length_y_0_2) > (length_x_1_3 + length_y_1_3))
1986  {
1987  bcheck = false;
1988  }
1989 
1990  double angle2;
1991  unsigned int idx;
1992  CurvMap* cm[2];
1993  memset(cm, 0, sizeof(cm));
1994 
1995  // create CurvMaps for sons if this is a curved element
1996  if(e->is_curved())
1997  {
1998  int i_case2 = 0;
1999  if(bcheck == true)
2000  {
2001  if((e->cm->nurbs[0] != NULL) || (e->cm->nurbs[1] != NULL))
2002  {
2003  cm[0] = new CurvMap;
2004  memset(cm[0], 0, sizeof(CurvMap));
2005  }
2006  if((e->cm->nurbs[2] != NULL) || (e->cm->nurbs[3] != NULL))
2007  {
2008  cm[1] = new CurvMap;
2009  memset(cm[1], 0, sizeof(CurvMap));
2010  }
2011  }
2012  else if(bcheck == false)
2013  {
2014  if((e->cm->nurbs[1] != NULL) || (e->cm->nurbs[2] != NULL))
2015  {
2016  cm[0] = new CurvMap;
2017  memset(cm[0], 0, sizeof(CurvMap));
2018  }
2019  if((e->cm->nurbs[3] != NULL) || (e->cm->nurbs[0] != NULL))
2020  {
2021  cm[1] = new CurvMap;
2022  memset(cm[1], 0, sizeof(CurvMap));
2023  }
2024  i_case2 = 1; //switch to the shorter diagonal
2025  }
2026 
2027  for (unsigned int k = 0; k < 2; k++)
2028  {
2029  for (idx = 0 + 2*k; idx < 2 + 2*k; idx++)
2030  {
2031  if(e->cm->nurbs[(idx + i_case2)%4] != NULL)
2032  {
2033  angle2 = e->cm->nurbs[(idx + i_case2)%4]->angle;
2034 
2035  int p1, p2;
2036 
2037  p1 = e->vn[(idx + i_case2)%4]->id;
2038  p2 = e->vn[(idx + i_case2 + 1)%4]->id; //node_temp->id;
2039 
2040  Nurbs* nurbs = new Nurbs;
2041  bool cricle = true;
2042 
2043  nurbs->arc = cricle;
2044  nurbs->degree = 2;
2045 
2046  int inner = 1, outer;
2047  inner = 1;
2048  nurbs->np = inner + 2;
2049  nurbs->pt = new double3[nurbs->np];
2050 
2051  nurbs->pt[0][0] = nodes[p1].x;
2052  nurbs->pt[0][1] = nodes[p1].y;
2053  nurbs->pt[0][2] = 1.0;
2054 
2055  nurbs->pt[inner + 1][0] = nodes[p2].x;
2056  nurbs->pt[inner + 1][1] = nodes[p2].y;
2057  nurbs->pt[inner + 1][2] = 1.0;
2058 
2059  double angle = angle2;
2060  double a = (180.0 - angle) / 180.0 * M_PI;
2061  nurbs->angle = angle;
2062 
2063  // generate one control point
2064  double x = 1.0 / tan(a * 0.5);
2065  nurbs->pt[1][0] = 0.5*((nurbs->pt[2][0] + nurbs->pt[0][0]) + (nurbs->pt[2][1] - nurbs->pt[0][1]) * x);
2066  nurbs->pt[1][1] = 0.5*((nurbs->pt[2][1] + nurbs->pt[0][1]) - (nurbs->pt[2][0] - nurbs->pt[0][0]) * x);
2067  nurbs->pt[1][2] = cos((M_PI - a) * 0.5);
2068 
2069  int i;
2070  inner = 0;
2071  nurbs->nk = nurbs->degree + nurbs->np + 1;
2072  outer = nurbs->nk - inner;
2073 
2074  // knot vector is completed by 0.0 on the left and by 1.0 on the right
2075  nurbs->kv = new double[nurbs->nk];
2076 
2077  for (i = 0; i < outer/2; i++)
2078  nurbs->kv[i] = 0.0;
2079  for (i = outer/2 + inner; i < nurbs->nk; i++)
2080  nurbs->kv[i] = 1.0;
2081  nurbs->ref = 0;
2082 
2083  cm[k]->toplevel = 1;
2084  cm[k]->order = 4;
2085  cm[k]->nurbs[idx%2] = nurbs;
2086  nurbs->ref++;
2087  }
2088  }
2089  }
2090  }
2091 
2092  // create the four sons
2093  Element* sons[H2D_MAX_ELEMENT_SONS];
2094  if(bcheck == true)
2095  {
2096  sons[0] = this->create_triangle(e->marker, e->vn[0], e->vn[1], e->vn[2], cm[0]);
2097  sons[1] = this->create_triangle(e->marker, e->vn[2], e->vn[3], e->vn[0], cm[1]);
2098  sons[2] = NULL;
2099  sons[3] = NULL;
2100  }
2101  else
2102  {
2103  sons[0] = this->create_triangle(e->marker, e->vn[1], e->vn[2], e->vn[3], cm[0]);
2104  sons[1] = this->create_triangle(e->marker, e->vn[3], e->vn[0], e->vn[1], cm[1]);
2105  sons[2] = NULL;
2106  sons[3] = NULL;
2107  }
2108 
2109  // update coefficients of curved reference mapping
2110  for (int i = 0; i < 2; i++)
2111  {
2112  if(sons[i]->is_curved())
2113  {
2114  sons[i]->cm->update_refmap_coeffs(sons[i]);
2115  }
2116  }
2117  nactive += 2;
2118  // now the original edge nodes may no longer exist...
2119  // set correct boundary status and markers for the new nodes
2120  if(bcheck == true)
2121  {
2122  sons[0]->en[0]->bnd = bnd[0]; sons[0]->en[0]->marker = mrk[0];
2123  sons[0]->en[1]->bnd = bnd[1]; sons[0]->en[1]->marker = mrk[1];
2124  sons[0]->vn[1]->bnd = bnd[0];
2125 
2126  sons[1]->en[0]->bnd = bnd[2]; sons[1]->en[0]->marker = mrk[2];
2127  sons[1]->en[1]->bnd = bnd[3]; sons[1]->en[1]->marker = mrk[3];
2128  sons[1]->vn[2]->bnd = bnd[1];
2129  }
2130  else
2131  {
2132  sons[0]->en[0]->bnd = bnd[1]; sons[0]->en[0]->marker = mrk[1];
2133  sons[0]->en[1]->bnd = bnd[2]; sons[0]->en[1]->marker = mrk[2];
2134  sons[0]->vn[1]->bnd = bnd[1];
2135 
2136  sons[1]->en[0]->bnd = bnd[3]; sons[1]->en[0]->marker = mrk[3];
2137  sons[1]->en[1]->bnd = bnd[0]; sons[1]->en[1]->marker = mrk[0];
2138  sons[1]->vn[2]->bnd = bnd[0];
2139  }
2140 
2141  //set pointers to parent element for sons
2142  for(int i = 0; i < H2D_MAX_ELEMENT_SONS; i++)
2143  if(sons[i] != NULL)
2144  sons[i]->parent = e;
2145 
2146  // copy son pointers (could not have been done earlier because of the union)
2147  memcpy(e->sons, sons, H2D_MAX_ELEMENT_SONS * sizeof(Element*));
2148  }
2149 
2150  void Mesh::refine_element_to_triangles_id(int id)
2151  {
2152  Element* e = get_element(id);
2153  if(!e->used) throw Hermes::Exceptions::Exception("Invalid element id number.");
2154  if(!e->active) throw Hermes::Exceptions::Exception("Attempt to refine element #%d which has been refined already.", e->id);
2155 
2156  if(e->is_triangle())
2157  return;
2158  else
2159  refine_quad_to_triangles(e);
2160 
2161  seq = g_mesh_seq++;
2162  }
2163 
2164  void Mesh::convert_element_to_base_id(int id)
2165  {
2166  Element* e = get_element(id);
2167  if(!e->used) throw Hermes::Exceptions::Exception("Invalid element id number.");
2168  if(!e->active) throw Hermes::Exceptions::Exception("Attempt to refine element #%d which has been refined already.", e->id);
2169 
2170  if(e->is_triangle())
2171  convert_triangles_to_base(e);
2172  else
2173  convert_quads_to_base(e);// FIXME:
2174 
2175  seq = g_mesh_seq++;
2176  }
2177 
2178  Mesh::MarkersConversion::MarkersConversion() : min_marker_unused(1)
2179  {
2180  }
2181 
2182  Mesh::MarkersConversion::StringValid::StringValid()
2183  {
2184  }
2185 
2186  Mesh::MarkersConversion::StringValid::StringValid(std::string marker, bool valid) : marker(marker), valid(valid)
2187  {
2188  }
2189 
2190  Mesh::MarkersConversion::IntValid::IntValid()
2191  {
2192  }
2193 
2194  Mesh::MarkersConversion::IntValid::IntValid(int marker, bool valid) : marker(marker), valid(valid)
2195  {
2196  }
2197 
2198  Mesh::ElementMarkersConversion::ElementMarkersConversion()
2199  {
2200  }
2201 
2202  Mesh::MarkersConversion::MarkersConversionType Mesh::ElementMarkersConversion::get_type() const
2203  {
2204  return HERMES_ELEMENT_MARKERS_CONVERSION;
2205  }
2206 
2207  Mesh::BoundaryMarkersConversion::BoundaryMarkersConversion()
2208  {
2209  }
2210 
2211  Mesh::MarkersConversion::MarkersConversionType Mesh::BoundaryMarkersConversion::get_type() const
2212  {
2213  return HERMES_BOUNDARY_MARKERS_CONVERSION;
2214  }
2215 
2216  Mesh::ElementMarkersConversion &Mesh::get_element_markers_conversion()
2217  {
2218  return element_markers_conversion;
2219  }
2220 
2221  Mesh::BoundaryMarkersConversion &Mesh::get_boundary_markers_conversion()
2222  {
2223  return boundary_markers_conversion;
2224  }
2225 
2226  void Mesh::MarkersConversion::insert_marker(int internal_marker, std::string user_marker)
2227  {
2228  // First a check that the string value is not already present.
2229  if(user_marker != "")
2230  if(conversion_table_inverse.find(user_marker) != conversion_table_inverse.end())
2231  return;
2232  if(conversion_table.size() == 0 || conversion_table.find(internal_marker) == conversion_table.end())
2233  {
2234  conversion_table.insert(std::pair<int, std::string>(internal_marker, user_marker));
2235  conversion_table_inverse.insert(std::pair<std::string, int>(user_marker, internal_marker));
2236  if(user_marker != "")
2237  this->min_marker_unused++;
2238  }
2239  return;
2240  }
2241 
2242  Mesh::MarkersConversion::StringValid Mesh::MarkersConversion::get_user_marker(int internal_marker) const
2243  {
2244  if(internal_marker == H2D_DG_INNER_EDGE_INT)
2245  return StringValid(H2D_DG_INNER_EDGE, true);
2246 
2247  if(conversion_table.find(internal_marker) == conversion_table.end())
2248  return StringValid("-999", false);
2249 
2250  return StringValid(conversion_table.find(internal_marker)->second, true);
2251  }
2252 
2253  Mesh::MarkersConversion::IntValid Mesh::MarkersConversion::get_internal_marker(std::string user_marker) const
2254  {
2255  if(user_marker == H2D_DG_INNER_EDGE)
2256  return IntValid(H2D_DG_INNER_EDGE_INT, true);
2257 
2258  if(conversion_table_inverse.find(user_marker) == conversion_table_inverse.end())
2259  return IntValid(-999, false);
2260 
2261  return IntValid(conversion_table_inverse.find(user_marker)->second, true);
2262  }
2263 
2264  Mesh::CurvedException::CurvedException(int elementId) : elementId(elementId)
2265  {
2266  char * msg = new char[150];
2267  sprintf(msg, "Element id %i is curved, this is not supported in this method.", elementId);
2268  message = msg;
2269  }
2270 
2271  Mesh::CurvedException::CurvedException(const CurvedException & e)
2272  {
2273  char * msg = new char[strlen(e.what())+1];
2274  strcpy(msg, e.what());
2275  message = msg;
2276  elementId = e.elementId;
2277  }
2278 
2279  int Mesh::CurvedException::getElementId() const
2280  {
2281  return this->elementId;
2282  }
2283 
2284  void Mesh::convert_triangles_to_base(Element *e)
2285  {
2286  // remember the markers of the edge nodes
2287  int bnd[3] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd };
2288  int mrk[3] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker };
2289 
2290  // check if element e is a internal element.
2291  bool e_inter = true;
2292  for (unsigned int n = 0; n < e->get_nvert(); n++)
2293  {
2294  if(bnd[n] == 1)
2295  e_inter = false;
2296  }
2297 
2298  // get the boundary edge angle.
2299  double refinement_angle[3] = {0.0, 0.0, 0.0};
2300  if(e->is_curved() && (!e_inter))
2301  {
2302  // for base element.
2303  if(e->cm->toplevel == true)
2304  {
2305  for (unsigned int n = 0; n < e->get_nvert(); n++)
2306  {
2307  if(e->cm->nurbs[n] != NULL)
2308  {
2309  //this->info("angle = %f", e->cm->nurbs[n]->angle);
2310  refinement_angle[n] = e->cm->nurbs[n]->angle;
2311  }
2312  }
2313  }
2314  else
2315  // one level refinement.
2316  if(e->parent->cm->toplevel == true)
2317  {
2318  for (unsigned int n = 0; n < e->get_nvert(); n++)
2319  {
2320  if(e->parent->cm->nurbs[n] != NULL)
2321  {
2322  //this->info("angle = %f", e->parent->cm->nurbs[n]->angle);
2323  refinement_angle[n] = e->parent->cm->nurbs[n]->angle / 2;
2324  }
2325  }
2326  }
2327  else
2328  // two level refinements.
2329  if(e->parent->parent->cm->toplevel == true)
2330  {
2331  for (unsigned int n = 0; n < e->get_nvert(); n++)
2332  {
2333  if(e->parent->parent->cm->nurbs[n] != NULL)
2334  {
2335  //this->info("angle = %f", e->parent->parent->cm->nurbs[n]->angle);
2336  refinement_angle[n] = e->parent->parent->cm->nurbs[n]->angle / 4;
2337  }
2338  }
2339  }
2340  else
2341  // three level refinements.
2342  if(e->parent->parent->parent->cm->toplevel == true)
2343  {
2344  for (unsigned int n = 0; n < e->get_nvert(); n++)
2345  {
2346  if(e->parent->parent->parent->cm->nurbs[n] != NULL)
2347  {
2348  //this->info("angle = %f", e->parent->parent->parent->cm->nurbs[n]->angle);
2349  refinement_angle[n] = e->parent->parent->parent->cm->nurbs[n]->angle / 8;
2350  }
2351  }
2352  }
2353  else
2354  // four level refinements.
2355  if(e->parent->parent->parent->parent->cm->toplevel == true)
2356  {
2357  for (unsigned int n = 0; n < e->get_nvert(); n++)
2358  {
2359  if(e->parent->parent->parent->parent->cm->nurbs[n] != NULL)
2360  {
2361  //this->info("angle = %f", e->parent->parent->parent->parent->cm->nurbs[n]->angle);
2362  refinement_angle[n] = e->parent->parent->parent->parent->cm->nurbs[n]->angle / 16;
2363  }
2364  }
2365  }
2366  }
2367 
2368  // deactivate this element and unregister from its nodes
2369  e->active = false;
2370  e->unref_all_nodes(this);
2371 
2372  double angle2 = 0.0;
2373  int idx = 0;
2374  CurvMap* cm;
2375  memset(&cm, 0, sizeof(cm));
2376 
2377  // create CurvMaps for sons if this is a curved element
2378  if((e->is_curved()) && (!e_inter))
2379  {
2380  cm = new CurvMap;
2381  memset(cm, 0, sizeof(CurvMap));
2382 
2383  for (idx = 0; idx < 3; idx++)
2384  if((e->cm->nurbs[idx] != NULL) && (bnd[idx] == 1))
2385  {
2386  angle2 = refinement_angle[idx];
2387  int p1, p2;
2388  p1 = e->en[idx]->p1;
2389  p2 = e->en[idx]->p2;
2390  if(p1 > p2) std::swap(p1, p2);
2391 
2392  Nurbs* nurbs = new Nurbs;
2393  bool cricle = true;
2394 
2395  nurbs->arc = cricle;
2396  nurbs->degree = 2;
2397 
2398  int inner = 1, outer = 0;
2399  nurbs->np = inner + 2;
2400  nurbs->pt = new double3[nurbs->np];
2401 
2402  nurbs->pt[0][0] = nodes[p1].x;
2403  nurbs->pt[0][1] = nodes[p1].y;
2404  nurbs->pt[0][2] = 1.0;
2405 
2406  nurbs->pt[inner + 1][0] = nodes[p2].x;
2407  nurbs->pt[inner + 1][1] = nodes[p2].y;
2408  nurbs->pt[inner + 1][2] = 1.0;
2409 
2410  double angle = angle2;
2411  double a = (180.0 - angle) / 180.0 * M_PI;
2412  nurbs->angle = angle;
2413 
2414  // generate one control point
2415  double x = 1.0 / tan(a * 0.5);
2416  nurbs->pt[1][0] = 0.5*((nurbs->pt[2][0] + nurbs->pt[0][0]) + (nurbs->pt[2][1] - nurbs->pt[0][1]) * x);
2417  nurbs->pt[1][1] = 0.5*((nurbs->pt[2][1] + nurbs->pt[0][1]) - (nurbs->pt[2][0] - nurbs->pt[0][0]) * x);
2418  nurbs->pt[1][2] = cos((M_PI - a) * 0.5);
2419 
2420  int i = 0;
2421  inner = 0;
2422  nurbs->nk = nurbs->degree + nurbs->np + 1;
2423  outer = nurbs->nk - inner;
2424 
2425  // knot vector is completed by 0.0 on the left and by 1.0 on the right
2426  nurbs->kv = new double[nurbs->nk];
2427 
2428  for (i = 0; i < outer/2; i++)
2429  nurbs->kv[i] = 0.0;
2430  for (i = outer/2 + inner; i < nurbs->nk; i++)
2431  nurbs->kv[i] = 1.0;
2432  nurbs->ref = 0;
2433 
2434  cm->toplevel = 1;
2435  cm->order = 4;
2436  cm->nurbs[idx] = nurbs;
2437  nurbs->ref++;
2438  }
2439  }
2440 
2441  // create a new element.
2442  Element* enew;
2443  Node *v0 = &nodes[e->vn[0]->id], *v1 = &nodes[e->vn[1]->id], *v2 = &nodes[e->vn[2]->id];
2444  enew = this->create_triangle(e->marker, v0, v1, v2, cm);
2445 
2446  if(enew->is_curved())
2447  {
2448  enew->cm->update_refmap_coeffs(enew);
2449  }
2450 
2451  // now the original edge nodes may no longer exist...
2452  // set correct boundary status and markers for the new nodes
2453  enew->en[0]->bnd = bnd[0];
2454  enew->en[1]->bnd = bnd[1];
2455  enew->en[2]->bnd = bnd[2];
2456  enew->en[0]->marker = mrk[0];
2457  enew->en[1]->marker = mrk[1];
2458  enew->en[2]->marker = mrk[2];
2459  enew->parent = e;
2460  }
2461 
2462  void Mesh::convert_quads_to_base(Element *e)
2463  {
2464  // remember the markers of the edge nodes
2465  int bnd[H2D_MAX_NUMBER_EDGES] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd, e->en[3]->bnd };
2466  int mrk[H2D_MAX_NUMBER_EDGES] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker, e->en[3]->marker };
2467 
2468  // check if element e is a internal element.
2469  bool e_inter = true;
2470  for (unsigned int n = 0; n < e->get_nvert(); n++)
2471  {
2472  if(bnd[n] == 1)
2473  e_inter = false;
2474  }
2475 
2476  // get the boundary edge angle.
2477  double refinement_angle[H2D_MAX_NUMBER_EDGES] = {0.0, 0.0, 0.0, 0.0};
2478  if(e->is_curved() && (!e_inter))
2479  {
2480  // for base element.
2481  if(e->cm->toplevel == true)
2482  {
2483  for (unsigned int n = 0; n < e->get_nvert(); n++)
2484  {
2485  if((e->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2486  {
2487  //this->info("angle = %f", e->cm->nurbs[n]->angle);
2488  refinement_angle[n] = e->cm->nurbs[n]->angle;
2489  }
2490  }
2491  }
2492  else
2493  // one level refinement.
2494  if(e->parent->cm->toplevel == true)
2495  {
2496  for (unsigned int n = 0; n < e->get_nvert(); n++)
2497  {
2498  if((e->parent->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2499  {
2500  //this->info("angle = %f", e->parent->cm->nurbs[n]->angle);
2501  refinement_angle[n] = e->parent->cm->nurbs[n]->angle / 2;
2502  }
2503  }
2504  }
2505  else
2506  // two level refinements.
2507  if(e->parent->parent->cm->toplevel == true)
2508  {
2509  for (unsigned int n = 0; n < e->get_nvert(); n++)
2510  {
2511  if((e->parent->parent->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2512  {
2513  //this->info("angle = %f", e->parent->parent->cm->nurbs[n]->angle);
2514  refinement_angle[n] = e->parent->parent->cm->nurbs[n]->angle / 4;
2515  }
2516  }
2517  }
2518  else
2519  // three level refinements.
2520  if(e->parent->parent->parent->cm->toplevel == true)
2521  {
2522  for (unsigned int n = 0; n < e->get_nvert(); n++)
2523  {
2524  if((e->parent->parent->parent->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2525  {
2526  //this->info("angle = %f", e->parent->parent->parent->cm->nurbs[n]->angle);
2527  refinement_angle[n] = e->parent->parent->parent->cm->nurbs[n]->angle / 8;
2528  }
2529  }
2530  }
2531  else
2532  // four level refinements.
2533  if(e->parent->parent->parent->parent->cm->toplevel == true)
2534  {
2535  for (unsigned int n = 0; n < e->get_nvert(); n++)
2536  {
2537  if((e->parent->parent->parent->parent->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2538  {
2539  //this->info("angle = %f", e->parent->parent->parent->parent->cm->nurbs[n]->angle);
2540  refinement_angle[n] = e->parent->parent->parent->parent->cm->nurbs[n]->angle / 16;
2541  }
2542  }
2543  }
2544  }
2545 
2546  // FIXME:
2547  if(rtb_aniso)
2548  for (unsigned int i = 0; i < e->get_nvert(); i++)
2549  refinement_angle[i] = refinement_angle[i]*2;
2550 
2551  // deactivate this element and unregister from its nodes
2552  e->active = false;
2553  e->unref_all_nodes(this);
2554 
2555  double angle2 = 0.0;
2556  int idx = 0;
2557  CurvMap* cm;
2558  memset(&cm, 0, sizeof(cm));
2559 
2560  // create CurvMaps for sons if this is a curved element
2561  if((e->is_curved()) && (!e_inter))
2562  {
2563  bool create_new = false;
2564  for (unsigned int i = 0; i < e->get_nvert(); i++)
2565  {
2566  if(fabs(refinement_angle[i] - 0.0) > 1e-4)
2567  {
2568  create_new = true;
2569  }
2570  }
2571 
2572  if(create_new)
2573 
2574  {
2575  cm = new CurvMap;
2576  memset(cm, 0, sizeof(CurvMap));
2577  }
2578 
2579  for (idx = 0; idx < 4; idx++)
2580  if(fabs(refinement_angle[idx] - 0.0) > 1e-4)
2581  {
2582  angle2 = refinement_angle[idx];
2583  int p1, p2;
2584  p1 = e->en[idx]->p1;
2585  p2 = e->en[idx]->p2;
2586  if(p1 > p2) std::swap(p1, p2);
2587 
2588  Nurbs* nurbs = new Nurbs;
2589  bool cricle = true;
2590 
2591  nurbs->arc = cricle;
2592  nurbs->degree = 2;
2593 
2594  int inner = 1, outer = 0;
2595  nurbs->np = inner + 2;
2596  nurbs->pt = new double3[nurbs->np];
2597 
2598  nurbs->pt[0][0] = nodes[p1].x;
2599  nurbs->pt[0][1] = nodes[p1].y;
2600  nurbs->pt[0][2] = 1.0;
2601 
2602  nurbs->pt[inner + 1][0] = nodes[p2].x;
2603  nurbs->pt[inner + 1][1] = nodes[p2].y;
2604  nurbs->pt[inner + 1][2] = 1.0;
2605 
2606  double angle = angle2;
2607  double a = (180.0 - angle) / 180.0 * M_PI;
2608  nurbs->angle = angle;
2609 
2610  // generate one control point
2611  double x = 1.0 / tan(a * 0.5);
2612  nurbs->pt[1][0] = 0.5*((nurbs->pt[2][0] + nurbs->pt[0][0]) + (nurbs->pt[2][1] - nurbs->pt[0][1]) * x);
2613  nurbs->pt[1][1] = 0.5*((nurbs->pt[2][1] + nurbs->pt[0][1]) - (nurbs->pt[2][0] - nurbs->pt[0][0]) * x);
2614  nurbs->pt[1][2] = cos((M_PI - a) * 0.5);
2615 
2616  int i = 0;
2617  inner = 0;
2618  nurbs->nk = nurbs->degree + nurbs->np + 1;
2619  outer = nurbs->nk - inner;
2620 
2621  // knot vector is completed by 0.0 on the left and by 1.0 on the right
2622  nurbs->kv = new double[nurbs->nk];
2623 
2624  for (i = 0; i < outer/2; i++)
2625  nurbs->kv[i] = 0.0;
2626  for (i = outer/2 + inner; i < nurbs->nk; i++)
2627  nurbs->kv[i] = 1.0;
2628  nurbs->ref = 0;
2629 
2630  cm->toplevel = 1;
2631  cm->order = 4;
2632  cm->nurbs[idx] = nurbs;
2633  nurbs->ref++;
2634  }
2635  }
2636 
2637  // create a new element.
2638  Element* enew;
2639  Node *v0 = &nodes[e->vn[0]->id], *v1 = &nodes[e->vn[1]->id], *v2 = &nodes[e->vn[2]->id], *v3 = &nodes[e->vn[3]->id];
2640  enew = this->create_quad(e->marker, v0, v1, v2, v3, cm);
2641 
2642  if(enew->is_curved())
2643  {
2644  enew->cm->update_refmap_coeffs(enew);
2645  }
2646 
2647  // now the original edge nodes may no longer exist...
2648  // set correct boundary status and markers for the new nodes
2649  enew->en[0]->bnd = bnd[0];
2650  enew->en[1]->bnd = bnd[1];
2651  enew->en[2]->bnd = bnd[2];
2652  enew->en[3]->bnd = bnd[3];
2653  enew->en[0]->marker = mrk[0];
2654  enew->en[1]->marker = mrk[1];
2655  enew->en[2]->marker = mrk[2];
2656  enew->en[3]->marker = mrk[3];
2657  enew->parent = e;
2658  }
2659 
2660  void Mesh::refine_quad_to_quads(Element* e, int refinement)
2661  {
2662  // remember the markers of the edge nodes
2663  int bnd[H2D_MAX_NUMBER_EDGES] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd, e->en[3]->bnd };
2664  int mrk[H2D_MAX_NUMBER_EDGES] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker, e->en[3]->marker };
2665 
2666  // check if element e is a internal element.
2667  bool e_inter = true;
2668  for (unsigned int n = 0; n < e->get_nvert(); n++)
2669  {
2670  if(bnd[n] == 1)
2671  e_inter = false;
2672  }
2673 
2674  // get the boundary edge angle.
2675  double refinement_angle[H2D_MAX_NUMBER_EDGES] = {0.0, 0.0, 0.0, 0.0};
2676  if(e->is_curved() && (!e_inter))
2677  {
2678  // for base element.
2679  if(e->cm->toplevel == true)
2680  {
2681  for (unsigned int n = 0; n < e->get_nvert(); n++)
2682  {
2683  if((e->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2684  {
2685  //this->info("angle = %f", e->cm->nurbs[n]->angle);
2686  refinement_angle[n] = e->cm->nurbs[n]->angle;
2687  }
2688  }
2689  }
2690  else
2691  // one level refinement.
2692  if(e->parent->cm->toplevel == true)
2693  {
2694  for (unsigned int n = 0; n < e->get_nvert(); n++)
2695  {
2696  if((e->parent->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2697  {
2698  //this->info("angle = %f", e->parent->cm->nurbs[n]->angle);
2699  refinement_angle[n] = e->parent->cm->nurbs[n]->angle / 2;
2700  }
2701  }
2702  }
2703  else
2704  // two level refinements.
2705  if(e->parent->parent->cm->toplevel == true)
2706  {
2707  for (unsigned int n = 0; n < e->get_nvert(); n++)
2708  {
2709  if((e->parent->parent->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2710  {
2711  //this->info("angle = %f", e->parent->parent->cm->nurbs[n]->angle);
2712  refinement_angle[n] = e->parent->parent->cm->nurbs[n]->angle / 4;
2713  }
2714  }
2715  }
2716  else
2717  // three level refinements.
2718  if(e->parent->parent->parent->cm->toplevel == true)
2719  {
2720  for (unsigned int n = 0; n < e->get_nvert(); n++)
2721  {
2722  if((e->parent->parent->parent->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2723  {
2724  //this->info("angle = %f", e->parent->parent->parent->cm->nurbs[n]->angle);
2725  refinement_angle[n] = e->parent->parent->parent->cm->nurbs[n]->angle / 8;
2726  }
2727  }
2728  }
2729  else
2730  // four level refinements.
2731  if(e->parent->parent->parent->parent->cm->toplevel == true)
2732  {
2733  for (unsigned int n = 0; n < e->get_nvert(); n++)
2734  {
2735  if((e->parent->parent->parent->parent->cm->nurbs[n] != NULL) && (bnd[n] == 1))
2736  {
2737  //this->info("angle = %f", e->parent->parent->parent->parent->cm->nurbs[n]->angle);
2738  refinement_angle[n] = e->parent->parent->parent->parent->cm->nurbs[n]->angle / 16;
2739  }
2740  }
2741  }
2742  }
2743 
2744  // deactivate this element and unregister from its nodes
2745  e->active = false;
2746  this->nactive--;
2747  e->unref_all_nodes(this);
2748 
2749  double angle2 = 0.0;
2750  int i, j;
2751  int idx = 0;
2752  Element* sons[H2D_MAX_ELEMENT_SONS] = {NULL, NULL, NULL, NULL};
2753  CurvMap* cm[H2D_MAX_ELEMENT_SONS];
2754  memset(cm, 0, sizeof(cm));
2755 
2756  // default refinement: one quad to four quads
2757  if(refinement == 0)
2758  {
2759  // obtain four mid-edge vertex nodes and one mid-element vetex node
2760  Node* x0 = get_vertex_node(e->vn[0]->id, e->vn[1]->id);
2761  Node* x1 = get_vertex_node(e->vn[1]->id, e->vn[2]->id);
2762  Node* x2 = get_vertex_node(e->vn[2]->id, e->vn[3]->id);
2763  Node* x3 = get_vertex_node(e->vn[3]->id, e->vn[0]->id);
2764  Node* mid = get_vertex_node(x0->id, x2->id);
2765 
2766  // adjust mid-edge coordinates if this is a curved element
2767  if(e->is_curved())
2768  {
2769  double2 pt[5] = { { 0.0, -1.0 }, { 1.0, 0.0 }, { 0.0, 1.0 }, { -1.0, 0.0 }, { 0.0, 0.0 } };
2770  e->cm->get_mid_edge_points(e, pt, 5);
2771  x0->x = pt[0][0]; x0->y = pt[0][1];
2772  x1->x = pt[1][0]; x1->y = pt[1][1];
2773  x2->x = pt[2][0]; x2->y = pt[2][1];
2774  x3->x = pt[3][0]; x3->y = pt[3][1];
2775  mid->x = pt[4][0]; mid->y = pt[4][1];
2776  }
2777 
2778  // create CurvMaps for sons.
2779  if((e->is_curved()) && (!e_inter))
2780  {
2781  //bool create_new = false;
2782  for (unsigned int i = 0; i < e->get_nvert(); i++)
2783  {
2784  if(fabs(refinement_angle[i] - 0.0) > 1e-4)
2785  {
2786  cm[i%4] = new CurvMap;
2787  memset(cm[i%4], 0, sizeof(CurvMap));
2788  cm[(i + 1)%4] = new CurvMap;
2789  memset(cm[(i + 1)%4], 0, sizeof(CurvMap));
2790  }
2791  }
2792 
2793  for (idx = 0; idx < 4; idx++)
2794  if(cm[idx] != NULL)
2795  {
2796  if((fabs(refinement_angle[idx%4] - 0.0) > 1e-4))
2797  {
2798  angle2 = refinement_angle[idx%4] / 2;
2799  Node* node_temp = this->get_vertex_node(e->vn[idx%4]->id, e->vn[(idx + 1)%4]->id);
2800 
2801  int p1, p2;
2802  p1 = e->vn[(idx)%4]->id;
2803  p2 = node_temp->id;
2804 
2805  Nurbs* nurbs = new Nurbs;
2806  bool cricle = true;
2807 
2808  nurbs->arc = cricle;
2809  nurbs->degree = 2;
2810 
2811  int inner = 1, outer = 0;
2812  nurbs->np = inner + 2;
2813  nurbs->pt = new double3[nurbs->np];
2814 
2815  nurbs->pt[0][0] = nodes[p1].x;
2816  nurbs->pt[0][1] = nodes[p1].y;
2817  nurbs->pt[0][2] = 1.0;
2818 
2819  nurbs->pt[inner + 1][0] = nodes[p2].x;
2820  nurbs->pt[inner + 1][1] = nodes[p2].y;
2821  nurbs->pt[inner + 1][2] = 1.0;
2822 
2823  double angle = angle2;
2824  double a = (180.0 - angle) / 180.0 * M_PI;
2825  nurbs->angle = angle;
2826 
2827  // generate one control point
2828  double x = 1.0 / tan(a * 0.5);
2829  nurbs->pt[1][0] = 0.5*((nurbs->pt[2][0] + nurbs->pt[0][0]) + (nurbs->pt[2][1] - nurbs->pt[0][1]) * x);
2830  nurbs->pt[1][1] = 0.5*((nurbs->pt[2][1] + nurbs->pt[0][1]) - (nurbs->pt[2][0] - nurbs->pt[0][0]) * x);
2831  nurbs->pt[1][2] = cos((M_PI - a) * 0.5);
2832 
2833  int i = 0;
2834  inner = 0;
2835  nurbs->nk = nurbs->degree + nurbs->np + 1;
2836  outer = nurbs->nk - inner;
2837 
2838  // knot vector is completed by 0.0 on the left and by 1.0 on the right
2839  nurbs->kv = new double[nurbs->nk];
2840 
2841  for (i = 0; i < outer/2; i++)
2842  nurbs->kv[i] = 0.0;
2843  for (i = outer/2 + inner; i < nurbs->nk; i++)
2844  nurbs->kv[i] = 1.0;
2845  nurbs->ref = 0;
2846 
2847  cm[idx]->toplevel = 1;
2848  cm[idx]->order = 4;
2849  cm[idx]->nurbs[idx%4] = nurbs;
2850  nurbs->ref++;
2851  }
2852 
2853  if((fabs(refinement_angle[(idx + 3)%4] - 0.0) > 1e-4))
2854  {
2855  angle2 = refinement_angle[(idx + 3)%4]/2;
2856  Node* node_temp = this->get_vertex_node(e->vn[idx%4]->id, e->vn[(idx + 1)%4]->id);
2857 
2858  int p1, p2;
2859  p1 = e->vn[(idx)%4]->id;
2860  p2 = node_temp->id;
2861 
2862  Nurbs* nurbs = new Nurbs;
2863  bool cricle = true;
2864 
2865  nurbs->arc = cricle;
2866  nurbs->degree = 2;
2867 
2868  int inner = 1, outer = 0;
2869  nurbs->np = inner + 2;
2870  nurbs->pt = new double3[nurbs->np];
2871 
2872  nurbs->pt[0][0] = nodes[p1].x;
2873  nurbs->pt[0][1] = nodes[p1].y;
2874  nurbs->pt[0][2] = 1.0;
2875 
2876  nurbs->pt[inner + 1][0] = nodes[p2].x;
2877  nurbs->pt[inner + 1][1] = nodes[p2].y;
2878  nurbs->pt[inner + 1][2] = 1.0;
2879 
2880  double angle = angle2;
2881  double a = (180.0 - angle) / 180.0 * M_PI;
2882  nurbs->angle = angle;
2883 
2884  // generate one control point
2885  double x = 1.0 / tan(a * 0.5);
2886  nurbs->pt[1][0] = 0.5*((nurbs->pt[2][0] + nurbs->pt[0][0]) + (nurbs->pt[2][1] - nurbs->pt[0][1]) * x);
2887  nurbs->pt[1][1] = 0.5*((nurbs->pt[2][1] + nurbs->pt[0][1]) - (nurbs->pt[2][0] - nurbs->pt[0][0]) * x);
2888  nurbs->pt[1][2] = cos((M_PI - a) * 0.5);
2889 
2890  int i = 0;
2891  inner = 0;
2892  nurbs->nk = nurbs->degree + nurbs->np + 1;
2893  outer = nurbs->nk - inner;
2894 
2895  // knot vector is completed by 0.0 on the left and by 1.0 on the right
2896  nurbs->kv = new double[nurbs->nk];
2897 
2898  for (i = 0; i < outer/2; i++)
2899  nurbs->kv[i] = 0.0;
2900  for (i = outer/2 + inner; i < nurbs->nk; i++)
2901  nurbs->kv[i] = 1.0;
2902  nurbs->ref = 0;
2903 
2904  cm[idx]->toplevel = 1;
2905  cm[idx]->order = 4;
2906  cm[idx]->nurbs[(idx + 3)%4] = nurbs;
2907  nurbs->ref++;
2908  }
2909  }
2910  }
2911 
2912  // create the four sons
2913  sons[0] = this->create_quad(e->marker, e->vn[0], x0, mid, x3, cm[0]);
2914  sons[1] = this->create_quad(e->marker, x0, e->vn[1], x1, mid, cm[1]);
2915  sons[2] = this->create_quad(e->marker, mid, x1, e->vn[2], x2, cm[2]);
2916  sons[3] = this->create_quad(e->marker, x3, mid, x2, e->vn[3], cm[3]);
2917 
2918  // Increase the number of active elements by 4.
2919  this->nactive += 4;
2920 
2921  // set correct boundary markers for the new edge nodes
2922  for (i = 0; i < 4; i++)
2923  {
2924  j = (i > 0) ? i-1 : 3;
2925  sons[i]->en[j]->bnd = bnd[j]; sons[i]->en[j]->marker = mrk[j];
2926  sons[i]->en[i]->bnd = bnd[i]; sons[i]->en[i]->marker = mrk[i];
2927  sons[i]->vn[j]->bnd = bnd[j];
2928  }
2929  }
2930  else assert(0);
2931 
2932  // update coefficients of curved reference mapping
2933  for (i = 0; i < 4; i++)
2934  if(sons[i] != NULL && sons[i]->cm != NULL)
2935  sons[i]->cm->update_refmap_coeffs(sons[i]);
2936 
2937  //set pointers to parent element for sons
2938  for(int i = 0; i < 4; i++)
2939  if(sons[i] != NULL)
2940  sons[i]->parent = e;
2941 
2942  // copy son pointers (could not have been done earlier because of the union)
2943  memcpy(e->sons, sons, sizeof(sons));
2944  }
2945 
2946  int Mesh::get_edge_degree(Node* v1, Node* v2)
2947  {
2948  int degree = 0;
2949  Node* v3 = peek_vertex_node(v1->id, v2->id);
2950  if(v3 != NULL)
2951  {
2952  degree = 1 + std::max(get_edge_degree(v1, v3), get_edge_degree(v3, v2));
2953  }
2954  return degree;
2955  }
2956 
2957  void Mesh::regularize_triangle(Element* e)
2958  {
2959  int i, k, k1, k2;
2960 
2961  Element* t[3];
2962 
2963  int eo[3] = { get_edge_degree(e->vn[0], e->vn[1]),
2964  get_edge_degree(e->vn[1], e->vn[2]),
2965  get_edge_degree(e->vn[2], e->vn[0]) };
2966 
2967  int sum = eo[0] + eo[1] + eo[2];
2968  if(sum == 3)
2969  {
2970  refine_element_id(e->id);
2971  }
2972  else if(sum > 0)
2973  {
2974  // remember the markers of the edge nodes
2975  int bnd[3] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd };
2976  int mrk[3] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker };
2977 
2978  if(sum == 1)
2979  {
2980  Node* v4;
2981  for(i = 0; i < 3; i++)
2982  if(eo[i] == 1) k = i;
2983  k1 = e->next_vert(k);
2984  k2 = e->prev_vert(k);
2985  v4 = peek_vertex_node(e->vn[k]->id, e->vn[k1]->id);
2986 
2987  e->active = 0;
2988  nactive += 1;
2989  e->unref_all_nodes(this);
2990 
2991  t[0] = this->create_triangle(e->marker, e->vn[k], v4, e->vn[k2], NULL);
2992  t[1] = this->create_triangle(e->marker, v4, e->vn[k1], e->vn[k2], NULL);
2993 
2994  // set correct boundary status and markers for the new nodes
2995  t[0]->en[2]->bnd = bnd[k2];
2996  t[1]->en[1]->bnd = bnd[k1];
2997  t[0]->en[2]->marker = mrk[k2];
2998  t[1]->en[1]->marker = mrk[k1];
2999 
3000  e->sons[0] = t[0];
3001  e->sons[1] = t[1];
3002  e->sons[2] = NULL;
3003  e->sons[3] = NULL;
3004  }
3005  else if(sum == 2)
3006  {
3007  Node *v4, *v5;
3008  for(i = 0; i < 3; i++)
3009  if(eo[i] == 0) k = i;
3010  k1 = e->next_vert(k);
3011  k2 = e->prev_vert(k);
3012  v4 = peek_vertex_node(e->vn[k1]->id, e->vn[k2]->id);
3013  v5 = peek_vertex_node(e->vn[k2]->id, e->vn[k]->id);
3014 
3015  e->active = 0;
3016  nactive += 2;
3017  e->unref_all_nodes(this);
3018 
3019  t[0] = this->create_triangle(e->marker, e->vn[k], e->vn[k1], v4, NULL);
3020  t[1] = this->create_triangle(e->marker, v4, v5, e->vn[k], NULL);
3021  t[2] = this->create_triangle(e->marker, v4, e->vn[k2], v5, NULL);
3022 
3023  // set correct boundary status and markers for the new nodes
3024  t[0]->en[0]->bnd = bnd[k];
3025  t[0]->en[0]->marker = mrk[k];
3026 
3027  e->sons[0] = t[0];
3028  e->sons[1] = t[1];
3029  e->sons[2] = t[2];
3030  e->sons[3] = NULL;
3031  }
3032  }
3033 
3034  // store id of parent
3035  if(!e->active)
3036  {
3037  for (i = 0; i < 4; i++)
3038  assign_parent(e, i);
3039  }
3040  }
3041 
3042  void Mesh::regularize_quad(Element* e)
3043  {
3044  int i, k = 0, k1, k2, k3, n = 0, m = 0;
3045  Node *v4, *v5;
3046  Element* t[4];
3047 
3048  int eo[4] = { get_edge_degree(e->vn[0], e->vn[1]),
3049  get_edge_degree(e->vn[1], e->vn[2]),
3050  get_edge_degree(e->vn[2], e->vn[3]),
3051  get_edge_degree(e->vn[3], e->vn[0]) };
3052 
3053  int sum = eo[0] + eo[1] + eo[2] + eo[3];
3054  if(sum == 4)
3055  {
3056  refine_element_id(e->id);
3057  }
3058  else if(sum > 0)
3059  {
3060  // remember the markers of the edge nodes
3061  int bnd[H2D_MAX_NUMBER_EDGES] = { e->en[0]->bnd, e->en[1]->bnd, e->en[2]->bnd , e->en[3]->bnd };
3062  int mrk[H2D_MAX_NUMBER_EDGES] = { e->en[0]->marker, e->en[1]->marker, e->en[2]->marker, e->en[3]->marker };
3063 
3064  if(sum == 1)
3065  {
3066  for(i = 0; i < 4; i++)
3067  if(eo[i] == 1) k = i;
3068  k1 = e->next_vert(k);
3069  k2 = e->next_vert(k1);
3070  k3 = e->prev_vert(k);
3071  v4 = peek_vertex_node(e->vn[k]->id, e->vn[k1]->id);
3072 
3073  e->active = 0;
3074  nactive += 2;
3075  e->unref_all_nodes(this);
3076 
3077  t[0] = this->create_triangle(e->marker, e->vn[k], v4, e->vn[k3], NULL);
3078  t[1] = this->create_triangle(e->marker, v4, e->vn[k1], e->vn[k2], NULL);
3079  t[2] = this->create_triangle(e->marker, v4, e->vn[k2], e->vn[k3], NULL);
3080 
3081  // set correct boundary status and markers for the new nodes
3082  t[0]->en[2]->bnd = bnd[k3];
3083  t[1]->en[1]->bnd = bnd[k1];
3084  t[2]->en[1]->bnd = bnd[k2];
3085  t[0]->en[2]->marker = mrk[k3];
3086  t[1]->en[1]->marker = mrk[k1];
3087  t[2]->en[1]->marker = mrk[k2];
3088 
3089  e->sons[0] = t[0];
3090  e->sons[1] = t[1];
3091  e->sons[2] = t[2];
3092  e->sons[3] = NULL;
3093  }
3094  else if(sum == 2)
3095  {
3096  // two hanging nodes opposite to each other
3097  if(eo[0] == 1 && eo[2] == 1) refine_element_id(e->id, 2);
3098  else if(eo[1] == 1 && eo[3] == 1) refine_element_id(e->id, 1);
3099  else // two hanging nodes next to each other
3100  {
3101  for(i = 0; i < 4; i++)
3102  if(eo[i] == 1 && eo[e->next_vert(i)] == 1) k = i;
3103  k1 = e->next_vert(k);
3104  k2 = e->next_vert(k1);
3105  k3 = e->prev_vert(k);
3106  v4 = peek_vertex_node(e->vn[k]->id, e->vn[k1]->id);
3107  v5 = peek_vertex_node(e->vn[k1]->id, e->vn[k2]->id);
3108 
3109  e->active = 0;
3110  nactive += 3;
3111  e->unref_all_nodes(this);
3112 
3113  t[0] = this->create_triangle(e->marker, e->vn[k1], v5, v4, NULL);
3114  t[1] = this->create_triangle(e->marker, v5, e->vn[k2], e->vn[k3], NULL);
3115  t[2] = this->create_triangle(e->marker, v4, v5, e->vn[k3], NULL);
3116  t[3] = this->create_triangle(e->marker, v4, e->vn[k3], e->vn[k], NULL);
3117 
3118  t[1]->en[1]->bnd = bnd[k2];
3119  t[3]->en[1]->bnd = bnd[k3];
3120  t[1]->en[1]->marker = mrk[k2];
3121  t[3]->en[1]->marker = mrk[k3];
3122 
3123  e->sons[0] = t[0];
3124  e->sons[1] = t[1];
3125  e->sons[2] = t[2];
3126  e->sons[3] = t[3];
3127  }
3128  }
3129  else //sum = 3
3130  {
3131  if(eo[0] == 1 && eo[2] == 1)
3132  {
3133  refine_element_id(e->id, 2);
3134  for (i = 0; i < 4; i++)
3135  assign_parent(e, i);
3136  n = 2; m = 3;
3137  }
3138  else if(eo[1] == 1 && eo[3] == 1)
3139  {
3140  refine_element_id(e->id, 1);
3141  for (i = 0; i < 4; i++)
3142  assign_parent(e, i);
3143  n = 0; m = 1;
3144  }
3145 
3146  regularize_quad(e->sons[n]);
3147  regularize_quad(e->sons[m]);
3148  }
3149  }
3150 
3151  // store id of parent
3152  if(!e->active)
3153  {
3154  for (i = 0; i < 4; i++)
3155  assign_parent(e, i);
3156  }
3157  }
3158 
3159  void Mesh::flatten()
3160  {
3161  Node* node;
3162  for_all_edge_nodes(node, this)
3163  {
3164  if(node->elem[0] != NULL) node->elem[0] = (Element*) (node->elem[0]->id + 1);
3165  if(node->elem[1] != NULL) node->elem[1] = (Element*) (node->elem[1]->id + 1);
3166  }
3167 
3168  int* idx = new int[elements.get_size() + 1];
3169  Array<Element> new_elements;
3170  Element* e;
3171  for_all_active_elements(e, this)
3172  {
3173  Element* ee = new_elements.add();
3174  int temp = ee->id;
3175  *ee = *e;
3176  ee->id = temp;
3177  idx[e->id] = temp;
3178  parents[ee->id] = parents[e->id];
3179  }
3180 
3181  elements.copy(new_elements);
3182  nbase = nactive = elements.get_num_items();
3183 
3184  for_all_edge_nodes(node, this)
3185  {
3186  if(node->elem[0] != NULL) node->elem[0] = &(elements[idx[((int) (long) node->elem[0]) - 1]]);
3187  if(node->elem[1] != NULL) node->elem[1] = &(elements[idx[((int) (long) node->elem[1]) - 1]]);
3188  }
3189  }
3190 
3191  void Mesh::assign_parent(Element* e, int i)
3192  {
3193  if(e->sons[i] != NULL)
3194  {
3195  if(e->sons[i]->id >= parents_size)
3196  {
3197  parents_size = 2 * parents_size;
3198  parents = (int*) realloc(parents, sizeof(int) * parents_size);
3199  }
3200 
3201  parents[e->sons[i]->id] = parents[e->id];
3202  }
3203  }
3204 
3205  int* Mesh::regularize(int n)
3206  {
3207  int j;
3208  bool ok;
3209  bool reg = false;
3210  Element* e;
3211 
3212  if(n < 1)
3213  {
3214  n = 1;
3215  reg = true;
3216  }
3217 
3218  parents_size = 2*get_max_element_id();
3219  parents = (int*) malloc(sizeof(int) * parents_size);
3220  for_all_active_elements(e, this)
3221  parents[e->id] = e->id;
3222 
3223  do
3224  {
3225  ok = true;
3226  for_all_active_elements(e, this)
3227  {
3228  int iso = -1;
3229  if(e->is_triangle())
3230  {
3231  for(unsigned int i = 0; i < e->get_nvert(); i++)
3232  {
3233  j = e->next_vert(i);
3234  if(get_edge_degree(e->vn[i], e->vn[j]) > n)
3235  { iso = 0; ok = false; break; }
3236  }
3237  }
3238  else
3239  {
3240  if( ((get_edge_degree(e->vn[0], e->vn[1]) > n) || (get_edge_degree(e->vn[2], e->vn[3]) > n))
3241  && (get_edge_degree(e->vn[1], e->vn[2]) <= n) && (get_edge_degree(e->vn[3], e->vn[0]) <= n) )
3242  { iso = 2; ok = false; }
3243  else if( (get_edge_degree(e->vn[0], e->vn[1]) <= n) && (get_edge_degree(e->vn[2], e->vn[3]) <= n)
3244  && ((get_edge_degree(e->vn[1], e->vn[2]) > n) || (get_edge_degree(e->vn[3], e->vn[0]) > n)) )
3245  { iso = 1; ok = false; }
3246  else
3247  {
3248  for(unsigned int i = 0; i < e->get_nvert(); i++)
3249  {
3250  j = e->next_vert(i);
3251  if(get_edge_degree(e->vn[i], e->vn[j]) > n)
3252  { iso = 0; ok = false; break; }
3253  }
3254  }
3255  }
3256 
3257  if(iso >= 0)
3258  {
3259  refine_element_id(e->id, iso);
3260  for (int i = 0; i < 4; i++)
3261  assign_parent(e, i);
3262  }
3263  }
3264  }
3265  while (!ok);
3266 
3267  if(reg)
3268  {
3269  for_all_active_elements(e, this)
3270  {
3271  if(e->is_curved()) throw Hermes::Exceptions::Exception("Regularization of curved elements is not supported.");
3272 
3273  if(e->is_triangle())
3274  regularize_triangle(e);
3275  else
3276  regularize_quad(e);
3277  }
3278  flatten();
3279  }
3280 
3281  return parents;
3282  }
3283  }
3284 }