ug4
element_angles.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2018: G-CSC, Goethe University Frankfurt
3  * Author: Martin Stepniewski
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 #ifndef __H__UG_ELEMENT_ANGLES
34 #define __H__UG_ELEMENT_ANGLES
35 
36 #ifdef UG_PARALLEL
38 #endif
39 
40 /* system includes */
41 #include <stddef.h>
42 #include <cmath>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <fstream>
47 #include <vector>
48 #include <string>
49 #include <algorithm>
50 
51 #include "lib_grid/lib_grid.h"
52 
53 
54 using namespace std;
55 
56 
57 namespace ug {
58 
59 
60 
62 // CollectAssociatedSides
64 
66 
67 UG_API
68 inline void CollectAssociatedSides(Edge* sidesOut[2], Grid& grid, Face* f, Vertex* vrt)
69 {
70  //PROFILE_BEGIN(CollectAssociatedSides_VERTEX);
71  sidesOut[0] = NULL;
72  sidesOut[1] = NULL;
73 
74  grid.begin_marking();
75  for(size_t i = 0; i < f->num_vertices(); ++i){
76  grid.mark(f->vertex(i));
77  }
78 
79  //vector<Edge*> vNeighbourEdgesToVertex;
80  //CollectAssociated(vNeighbourEdgesToVertex, grid, vrt, true);
81 
83  //Grid::AssociatedEdgeIterator iterEnd = vNeighbourEdgesToVertex.end();
84  for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(vrt); iter != iterEnd; ++iter)
85  //for(Grid::AssociatedEdgeIterator iter = vNeighbourEdgesToVertex.begin(); iter != iterEnd; ++iter)
86  {
87  Edge* e = *iter;
88  if(grid.is_marked(e->vertex(0)) && grid.is_marked(e->vertex(1))){
89  UG_ASSERT( sidesOut[1] == NULL,
90  "Only two edges may be adjacent to a vertex in a face element.");
91 
92  if(sidesOut[0] == NULL)
93  sidesOut[0] = e;
94  else
95  sidesOut[1] = e;
96  }
97  }
98 
99  grid.end_marking();
100  UG_ASSERT( sidesOut[1] != NULL,
101  "Exactly two edges should be adjacent to a vertex in a face element.")
102 }
103 
105 
106 UG_API
107 inline void CollectAssociatedSides(Face* sidesOut[2], Grid& grid, Volume* v, Edge* e)
108 {
109  //PROFILE_BEGIN(CollectAssociatedSides_EDGE);
110  sidesOut[0] = NULL;
111  sidesOut[1] = NULL;
112 
113  grid.begin_marking();
114 
115  for(size_t i = 0; i < v->num_vertices(); ++i)
116  grid.mark(v->vertex(i));
117 
118  vector<Face*> vNeighbourFacesToEdge;
119  CollectAssociated(vNeighbourFacesToEdge, grid, e, true);
120 
121  //Grid::AssociatedFaceIterator iterEnd = grid.associated_faces_end(e);
122  Grid::AssociatedFaceIterator iterEnd = vNeighbourFacesToEdge.end();
123  //for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(e); iter != iterEnd; ++iter)
124  for(Grid::AssociatedFaceIterator iter = vNeighbourFacesToEdge.begin(); iter != iterEnd; ++iter)
125  {
126  Face* f = *iter;
127 
128  // check whether all vertices of f are marked
129  bool allMarked = true;
130  for(size_t i = 0; i < f->num_vertices(); ++i){
131  if(!grid.is_marked(f->vertex(i))){
132  allMarked = false;
133  break;
134  }
135  }
136 
137  if(allMarked){
138  if(FaceContains(f, e)){
139  UG_ASSERT( sidesOut[1] == NULL,
140  "Only two faces may be adjacent to an edge in a volume element.")
141 
142  if(sidesOut[0] == NULL)
143  sidesOut[0] = f;
144  else
145  sidesOut[1] = f;
146  }
147  }
148  }
149 
150  grid.end_marking();
151 
152  UG_ASSERT( sidesOut[1] != NULL,
153  "Exactly two faces should be adjacent to an edge in a volume element.")
154 }
155 
156 
158 // CalculateMinAngle
160 
162 template <class TElem, class TAAPosVRT>
163 number CalculateMinAngle(Grid& grid, TElem* elem, TAAPosVRT& aaPos);
164 
166 template <class TAAPosVRT>
167 number CalculateMinAngle(Grid& grid, Face* f, TAAPosVRT& aaPos)
168 {
169  //PROFILE_FUNC();
170 
178  {
179  LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
181  }
182 
183 // Get type of vertex attachment in aaPos and define it as ValueType
184  typedef typename TAAPosVRT::ValueType ValueType;
185 
186 // Initialization
187  uint numFaceVrts = f->num_vertices();
188  ValueType vNorm1, vNorm2;
189  ValueType vDir1, vDir2;
190  number minAngle = 180.0;
191  number tmpAngle;
192  Edge* vNeighbourEdgesToVertex[2];
193  Vertex* adjacentVrt1;
194  Vertex* adjacentVrt2;
195 
196 // Iterate over all face vertices
197  for(uint vrtIter = 0; vrtIter < numFaceVrts; ++vrtIter)
198  {
199  Vertex* vrt = f->vertex(vrtIter);
200 
201  // Get adjacent edges at the current vertex and calculate the angle between their normals
202  CollectAssociatedSides(vNeighbourEdgesToVertex, grid, f, vrt);
203 
204  // Calculate vDir vectors of the current two adjacent edges
205  // !!! Beware of the correct order of the vertices to get correct angle value !!!
206  if(vrt != vNeighbourEdgesToVertex[0]->vertex(0))
207  adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(0);
208  else
209  adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(1);
210 
211  if(vrt != vNeighbourEdgesToVertex[1]->vertex(0))
212  adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(0);
213  else
214  adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(1);
215 
216  VecSubtract(vDir1, aaPos[adjacentVrt1], aaPos[vrt]);
217  VecSubtract(vDir2, aaPos[adjacentVrt2], aaPos[vrt]);
218 
219  // Normalize
220  VecNormalize(vDir1, vDir1);
221  VecNormalize(vDir2, vDir2);
222 
223  // Calculate current angle
224  tmpAngle = acos(VecDot(vDir1, vDir2));
225 
226  // Check for minimality
227  if(tmpAngle < minAngle)
228  {
229  minAngle = tmpAngle;
230  }
231  }
232 
233 // Transform minAngle from RAD to DEG
234  minAngle = 180/PI * minAngle;
235 
236  return minAngle;
237 }
238 
240 // INFO: For volume elements the minimal angle corresponds to the smallest dihedral
242 
244 template <class TAAPosVRT>
245 number CalculateMinAngle(Grid& grid, Tetrahedron* tet, TAAPosVRT& aaPos)
246 {
247  return CalculateMinDihedral(grid, static_cast<Volume*>(tet), aaPos);
248 }
249 
251 template <class TAAPosVRT>
252 number CalculateMinAngle(Grid& grid, Prism* prism, TAAPosVRT& aaPos)
253 {
254  return CalculateMinDihedral(grid, static_cast<Volume*>(prism), aaPos);
255 }
256 
258 template <class TAAPosVRT>
259 number CalculateMinAngle(Grid& grid, Pyramid* pyr, TAAPosVRT& aaPos)
260 {
261  return CalculateMinDihedral(grid, static_cast<Volume*>(pyr), aaPos);
262 }
263 
265 template <class TAAPosVRT>
266 number CalculateMinAngle(Grid& grid, Hexahedron* hex, TAAPosVRT& aaPos)
267 {
268  return CalculateMinDihedral(grid, static_cast<Volume*>(hex), aaPos);
269 }
270 
272 template <class TAAPosVRT>
273 number CalculateMinAngle(Grid& grid, Volume* vol, TAAPosVRT& aaPos)
274 {
275  return CalculateMinDihedral(grid, vol, aaPos);
276 }
277 
278 
280 // CalculateMinDihedral
282 
284 template <class TElem, class TAAPosVRT>
285 number CalculateMinDihedral(Grid& grid, TElem* elem, TAAPosVRT& aaPos);
286 
288 template <class TAAPosVRT>
289 number CalculateMinDihedral(Grid& grid, Tetrahedron* tet, TAAPosVRT& aaPos)
290 {
291  return CalculateMinDihedral(grid, static_cast<Volume*>(tet), aaPos);
292 }
293 
295 template <class TAAPosVRT>
296 number CalculateMinDihedral(Grid& grid, Prism* prism, TAAPosVRT& aaPos)
297 {
298  return CalculateMinDihedral(grid, static_cast<Volume*>(prism), aaPos);
299 }
300 
302 template <class TAAPosVRT>
303 number CalculateMinDihedral(Grid& grid, Pyramid* pyr, TAAPosVRT& aaPos)
304 {
305  return CalculateMinDihedral(grid, static_cast<Volume*>(pyr), aaPos);
306 }
307 
309 template <class TAAPosVRT>
310 number CalculateMinDihedral(Grid& grid, Hexahedron* hex, TAAPosVRT& aaPos)
311 {
312  return CalculateMinDihedral(grid, static_cast<Volume*>(hex), aaPos);
313 }
314 
316 template <class TAAPosVRT>
317 number CalculateMinDihedral(Grid& grid, Volume* v, TAAPosVRT& aaPos)
318 {
319  //PROFILE_FUNC();
320 
328  {
329  LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
331  }
332 
333 // Initialization
334  uint numElementEdges = v->num_edges();
335  vector3 vNorm1, vNorm2;
336  number minDihedral = 360.0;
337  number tmpAngle;
338  Face* vNeighbourFacesToEdge[2];
339 
340 // Iterate over all element edges
341  for(uint eIter = 0; eIter < numElementEdges; ++eIter)
342  {
343  Edge* e = grid.get_edge(v, eIter);
344 
345  // Get adjacent faces at the current edge and calculate the angle between their normals
346  // !!! Beware of the correct vExtrDir normals to get correct angle value !!!
347  CollectAssociatedSides(vNeighbourFacesToEdge, grid, v, e);
348 
349  Vertex* adjacentVrt1;
350  Vertex* adjacentVrt2;
351  vector3 vDir1;
352  vector3 vDir2;
353  vector3 vDir3;
354 
355  // Get vertex of each associated face, which is not part of the given edge
356  for(size_t i = 0; i < vNeighbourFacesToEdge[0]->num_vertices(); ++i)
357  {
358  if(vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(1))
359  adjacentVrt1 = vNeighbourFacesToEdge[0]->vertex(i);
360  }
361 
362  for(size_t i = 0; i < vNeighbourFacesToEdge[1]->num_vertices(); ++i)
363  {
364  if(vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(1))
365  adjacentVrt2 = vNeighbourFacesToEdge[1]->vertex(i);
366  }
367 
368  VecSubtract(vDir1, aaPos[e->vertex(1)], aaPos[e->vertex(0)]);
369  VecSubtract(vDir2, aaPos[adjacentVrt1], aaPos[e->vertex(0)]);
370  VecSubtract(vDir3, aaPos[e->vertex(0)], aaPos[adjacentVrt2]);
371 
372  VecCross(vNorm1, vDir1, vDir2);
373  VecCross(vNorm2, vDir1, vDir3);
374 
375  VecNormalize(vNorm1, vNorm1);
376  VecNormalize(vNorm2, vNorm2);
377 
378  tmpAngle = acos(VecDot(vNorm1, vNorm2));
379  tmpAngle = PI - tmpAngle;
380 
381  // Check for minimality
382  if(tmpAngle < minDihedral)
383  {
384  minDihedral = tmpAngle;
385  }
386  }
387 
388 // Transform minAngle from RAD to DEG
389  minDihedral = 180/PI * minDihedral;
390 
391  return minDihedral;
392 }
393 
394 
396 // CalculateMaxAngle
398 
400 template <class TElem, class TAAPosVRT>
401 number CalculateMaxAngle(Grid& grid, TElem* elem, TAAPosVRT& aaPos);
402 
404 template <class TAAPosVRT>
405 number CalculateMaxAngle(Grid& grid, Face* f, TAAPosVRT& aaPos)
406 {
407  //PROFILE_FUNC();
408 
416  {
417  LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
419  }
420 
421 // Get type of vertex attachment in aaPos and define it as ValueType
422  typedef typename TAAPosVRT::ValueType ValueType;
423 
424 // Initialization
425  uint numFaceVrts = f->num_vertices();
426  ValueType vNorm1, vNorm2;
427  ValueType vDir1, vDir2;
428  number maxAngle = 0;
429  number tmpAngle;
430  Edge* vNeighbourEdgesToVertex[2];
431  Vertex* adjacentVrt1;
432  Vertex* adjacentVrt2;
433 
434 // Iterate over all face vertices
435  for(uint vrtIter = 0; vrtIter < numFaceVrts; ++vrtIter)
436  {
437  Vertex* vrt = f->vertex(vrtIter);
438 
439  // Get adjacent edges at the current vertex and calculate the angle between their normals
440  CollectAssociatedSides(vNeighbourEdgesToVertex, grid, f, vrt);
441 
442  // Calculate vExtrDir vectors of the current two adjacent edges
443  // !!! Beware of the correct order of the vertices to get correct angle value !!!
444  if(vrt != vNeighbourEdgesToVertex[0]->vertex(0))
445  adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(0);
446  else
447  adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(1);
448 
449  if(vrt != vNeighbourEdgesToVertex[1]->vertex(0))
450  adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(0);
451  else
452  adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(1);
453 
454  VecSubtract(vDir1, aaPos[adjacentVrt1], aaPos[vrt]);
455  VecSubtract(vDir2, aaPos[adjacentVrt2], aaPos[vrt]);
456 
457  // Normalize
458  VecNormalize(vDir1, vDir1);
459  VecNormalize(vDir2, vDir2);
460 
461  // Calculate current angle
462  tmpAngle = acos(VecDot(vDir1, vDir2));
463 
464  // Check for maximality
465  if(tmpAngle > maxAngle)
466  {
467  maxAngle = tmpAngle;
468  }
469  }
470 
471 // Transform maxAngle from RAD to DEG
472  maxAngle = 180/PI * maxAngle;
473 
474  return maxAngle;
475 }
476 
478 // INFO: For volume elements the maxAngle corresponds to the largest dihedral
480 
482 template <class TAAPosVRT>
483 number CalculateMaxAngle(Grid& grid, Tetrahedron* tet, TAAPosVRT& aaPos)
484 {
485  return CalculateMaxDihedral(grid, static_cast<Volume*>(tet), aaPos);
486 }
487 
489 template <class TAAPosVRT>
490 number CalculateMaxAngle(Grid& grid, Prism* prism, TAAPosVRT& aaPos)
491 {
492  return CalculateMaxDihedral(grid, static_cast<Volume*>(prism), aaPos);
493 }
494 
496 template <class TAAPosVRT>
497 number CalculateMaxAngle(Grid& grid, Pyramid* pyr, TAAPosVRT& aaPos)
498 {
499  return CalculateMaxDihedral(grid, static_cast<Volume*>(pyr), aaPos);
500 }
501 
503 template <class TAAPosVRT>
504 number CalculateMaxAngle(Grid& grid, Volume* vol, TAAPosVRT& aaPos)
505 {
506  return CalculateMaxDihedral(grid, vol, aaPos);
507 }
508 
509 
511 // CalculateMaxDihedral
513 
515 template <class TElem, class TAAPosVRT>
516 number CalculateMaxDihedral(Grid& grid, TElem* elem, TAAPosVRT& aaPos);
517 
519 template <class TAAPosVRT>
520 number CalculateMaxDihedral(Grid& grid, Tetrahedron* tet, TAAPosVRT& aaPos)
521 {
522  return CalculateMaxDihedral(grid, static_cast<Volume*>(tet), aaPos);
523 }
524 
526 template <class TAAPosVRT>
527 number CalculateMaxDihedral(Grid& grid, Prism* prism, TAAPosVRT& aaPos)
528 {
529  return CalculateMaxDihedral(grid, static_cast<Volume*>(prism), aaPos);
530 }
531 
533 template <class TAAPosVRT>
534 number CalculateMaxDihedral(Grid& grid, Pyramid* pyr, TAAPosVRT& aaPos)
535 {
536  return CalculateMaxDihedral(grid, static_cast<Volume*>(pyr), aaPos);
537 }
538 
540 template <class TAAPosVRT>
541 number CalculateMaxDihedral(Grid& grid, Volume* v, TAAPosVRT& aaPos)
542 {
543  //PROFILE_FUNC();
544 
552  {
553  LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
555  }
556 
557 // Initialization
558  uint numElementEdges = v->num_edges();
559  vector3 vNorm1, vNorm2;
560  number maxDihedral = 0;
561  number tmpAngle;
562  Face* vNeighbourFacesToEdge[2];
563 
564 // Iterate over all element edges
565  for(uint eIter = 0; eIter < numElementEdges; ++eIter)
566  {
567  Edge* e = grid.get_edge(v, eIter);
568 
569  // Get adjacent faces at the current edge and calculate the angle between their normals
570  // !!! Beware of the correct vExtrDir normals to get correct angle value !!!
571  CollectAssociatedSides(vNeighbourFacesToEdge, grid, v, e);
572 
573  Vertex* adjacentVrt1;
574  Vertex* adjacentVrt2;
575  vector3 vDir1;
576  vector3 vDir2;
577  vector3 vDir3;
578 
579  for(size_t i = 0; i < vNeighbourFacesToEdge[0]->num_vertices(); ++i)
580  {
581  if(vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(1))
582  adjacentVrt1 = vNeighbourFacesToEdge[0]->vertex(i);
583  }
584 
585  for(size_t i = 0; i < vNeighbourFacesToEdge[1]->num_vertices(); ++i)
586  {
587  if(vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(1))
588  adjacentVrt2 = vNeighbourFacesToEdge[1]->vertex(i);
589  }
590 
591  VecSubtract(vDir1, aaPos[e->vertex(1)], aaPos[e->vertex(0)]);
592  VecSubtract(vDir2, aaPos[adjacentVrt1], aaPos[e->vertex(0)]);
593  VecSubtract(vDir3, aaPos[e->vertex(0)], aaPos[adjacentVrt2]);
594 
595  VecCross(vNorm1, vDir1, vDir2);
596  VecCross(vNorm2, vDir1, vDir3);
597 
598  VecNormalize(vNorm1, vNorm1);
599  VecNormalize(vNorm2, vNorm2);
600 
601  tmpAngle = acos(VecDot(vNorm1, vNorm2));
602  tmpAngle = PI - tmpAngle;
603 
604  // Check for maximality
605  if(tmpAngle > maxDihedral)
606  {
607  maxDihedral = tmpAngle;
608  }
609  }
610 
611 // Transform maxDihedral from RAD to DEG
612  maxDihedral = 180/PI * maxDihedral;
613 
614  return maxDihedral;
615 }
616 
617 
619 // CalculateAngles
621 
623 template <class TElem, class TAAPosVRT>
624 number CalculateAngles(vector<number>& vAnglesOut, Grid& grid, TElem* elem, TAAPosVRT& aaPos);
625 
627 template <class TAAPosVRT>
628 void CalculateAngles(vector<number>& vAnglesOut, Grid& grid, Face* f, TAAPosVRT& aaPos)
629 {
630  //PROFILE_FUNC();
631 
639  {
640  LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
642  }
643 
644 // Get type of vertex attachment in aaPos and define it as ValueType
645  typedef typename TAAPosVRT::ValueType ValueType;
646 
647 // Initialization
648  uint numFaceVrts = f->num_vertices();
649  ValueType vNorm1, vNorm2;
650  ValueType vDir1, vDir2;
651  number tmpAngle;
652  Edge* vNeighbourEdgesToVertex[2];
653  Vertex* adjacentVrt1;
654  Vertex* adjacentVrt2;
655 
656 // Iterate over all face vertices
657  for(uint vrtIter = 0; vrtIter < numFaceVrts; ++vrtIter)
658  {
659  Vertex* vrt = f->vertex(vrtIter);
660 
661  // Get adjacent edges at the current vertex and calculate the angle between their normals
662  CollectAssociatedSides(vNeighbourEdgesToVertex, grid, f, vrt);
663 
664  // Calculate vDir vectors of the current two adjacent edges
665  // !!! Beware of the correct order of the vertices to get correct angle value !!!
666  if(vrt != vNeighbourEdgesToVertex[0]->vertex(0))
667  adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(0);
668  else
669  adjacentVrt1 = vNeighbourEdgesToVertex[0]->vertex(1);
670 
671  if(vrt != vNeighbourEdgesToVertex[1]->vertex(0))
672  adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(0);
673  else
674  adjacentVrt2 = vNeighbourEdgesToVertex[1]->vertex(1);
675 
676  VecSubtract(vDir1, aaPos[adjacentVrt1], aaPos[vrt]);
677  VecSubtract(vDir2, aaPos[adjacentVrt2], aaPos[vrt]);
678 
679  // Normalize
680  VecNormalize(vDir1, vDir1);
681  VecNormalize(vDir2, vDir2);
682 
683  // Calculate current angle
684  tmpAngle = acos(VecDot(vDir1, vDir2));
685 
686  // Transform minAngle from RAD to DEG
687  tmpAngle = 180/PI * tmpAngle;
688 
689  vAnglesOut.push_back(tmpAngle);
690  }
691 }
692 
694 template <class TAAPosVRT>
695 void CalculateAngles(vector<number>& vAnglesOut, Grid& grid, Volume* v, TAAPosVRT& aaPos)
696 {
697  //PROFILE_FUNC();
698 
706  {
707  LOG("WARNING: autoenabling GRIDOPT_AUTOGENERATE_SIDES in GetNeighbours(Face).\n");
709  }
710 
711 // Initialization
712  uint numElementEdges = v->num_edges();
713  vector3 vNorm1, vNorm2;
714  number tmpAngle;
715  Face* vNeighbourFacesToEdge[2];
716 
717 // Iterate over all element edges
718  for(uint eIter = 0; eIter < numElementEdges; ++eIter)
719  {
720  Edge* e = grid.get_edge(v, eIter);
721 
722  // Get adjacent faces at the current edge and calculate the angle between their normals
723  // !!! Beware of the correct vExtrDir normals to get correct angle value !!!
724  CollectAssociatedSides(vNeighbourFacesToEdge, grid, v, e);
725 
726  Vertex* adjacentVrt1;
727  Vertex* adjacentVrt2;
728  vector3 vDir1;
729  vector3 vDir2;
730  vector3 vDir3;
731 
732  for(size_t i = 0; i < vNeighbourFacesToEdge[0]->num_vertices(); ++i)
733  {
734  if(vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[0]->vertex(i) != e->vertex(1))
735  adjacentVrt1 = vNeighbourFacesToEdge[0]->vertex(i);
736  }
737 
738  for(size_t i = 0; i < vNeighbourFacesToEdge[1]->num_vertices(); ++i)
739  {
740  if(vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(0) && vNeighbourFacesToEdge[1]->vertex(i) != e->vertex(1))
741  adjacentVrt2 = vNeighbourFacesToEdge[1]->vertex(i);
742  }
743 
744  VecSubtract(vDir1, aaPos[e->vertex(1)], aaPos[e->vertex(0)]);
745  VecSubtract(vDir2, aaPos[adjacentVrt1], aaPos[e->vertex(0)]);
746  VecSubtract(vDir3, aaPos[e->vertex(0)], aaPos[adjacentVrt2]);
747 
748  VecCross(vNorm1, vDir1, vDir2);
749  VecCross(vNorm2, vDir1, vDir3);
750 
751  VecNormalize(vNorm1, vNorm1);
752  VecNormalize(vNorm2, vNorm2);
753 
754  tmpAngle = acos(VecDot(vNorm1, vNorm2));
755  tmpAngle = PI - tmpAngle;
756 
757  // Transform maxDihedral from RAD to DEG
758  tmpAngle = 180.0/PI * tmpAngle;
759 
760  vAnglesOut.push_back(tmpAngle);
761  }
762 }
763 
764 
766 // FindElementWithSmallestMinAngle
767 template <class TIterator, class TAAPosVRT>
768 typename TIterator::value_type
769 FindElementWithSmallestMinAngle(Grid& grid, TIterator elementsBegin, TIterator elementsEnd, TAAPosVRT& aaPos)
770 {
771  //PROFILE_FUNC();
772 // if volumesBegin equals volumesBegin, then the list is empty and we can
773 // immediately return NULL
774  if(elementsBegin == elementsEnd)
775  return NULL;
776 
777 // Initializations
778  typename TIterator::value_type elementWithSmallestMinAngle = *elementsBegin;
779  number smallestMinAngle = CalculateMinAngle(grid, elementWithSmallestMinAngle, aaPos);
780  ++elementsBegin;
781 
782 // compare all volumes and find that one with smallest minAngle
783  for(; elementsBegin != elementsEnd; ++elementsBegin)
784  {
785  typename TIterator::value_type curElement = *elementsBegin;
786  number curSmallestMinAngle = CalculateMinAngle(grid, curElement, aaPos);
787 
788  if(curSmallestMinAngle < smallestMinAngle)
789  {
790  elementWithSmallestMinAngle = curElement;
791  smallestMinAngle = curSmallestMinAngle;
792  }
793  }
794 
795  return elementWithSmallestMinAngle;
796 }
797 
798 
800 // FindElementWithLargestMaxAngle
801 template <class TIterator, class TAAPosVRT>
802 typename TIterator::value_type
803 FindElementWithLargestMaxAngle(Grid& grid, TIterator elementsBegin, TIterator elementsEnd, TAAPosVRT& aaPos)
804 {
805  //PROFILE_FUNC();
806 // if volumesBegin equals volumesBegin, then the list is empty and we can
807 // immediately return NULL
808  if(elementsBegin == elementsEnd)
809  return NULL;
810 
811 // Initializations
812  typename TIterator::value_type elementWithLargestMaxAngle = *elementsBegin;
813  number largestMaxAngle = CalculateMaxAngle(grid, elementWithLargestMaxAngle, aaPos);
814  ++elementsBegin;
815 
816 // compare all volumes and find that one with largest maxAngle
817  for(; elementsBegin != elementsEnd; ++elementsBegin)
818  {
819  typename TIterator::value_type curElement = *elementsBegin;
820  number curLargestMaxAngle = CalculateMaxAngle(grid, curElement, aaPos);
821 
822  if(curLargestMaxAngle > largestMaxAngle)
823  {
824  elementWithLargestMaxAngle = curElement;
825  largestMaxAngle = curLargestMaxAngle;
826  }
827  }
828 
829  return elementWithLargestMaxAngle;
830 }
831 
832 
833 }
834 #endif
Base-class for edges.
Definition: grid_base_objects.h:397
virtual Vertex * vertex(size_t index) const
Definition: grid_base_objects.h:366
Faces are 2-dimensional objects.
Definition: grid_base_objects.h:510
virtual Vertex * vertex(size_t index) const
Definition: grid_base_objects.h:486
virtual size_t num_vertices() const
Definition: grid_base_objects.h:488
Manages the elements of a grid and their interconnection.
Definition: grid.h:132
EdgeContainer::iterator AssociatedEdgeIterator
used to iterate over associated edges of vertices, faces and volumes
Definition: grid.h:249
void end_marking()
ends a marking sequence. Call this method when you're done with marking.
Definition: grid.cpp:1285
AssociatedEdgeIterator associated_edges_begin(Vertex *vrt)
DO NOT INVOKE! Subject to change.
Definition: grid.cpp:882
bool option_is_enabled(uint option) const
see set_options for a description of valid parameters.
Definition: grid.cpp:721
bool is_marked(GridObject *obj) const
returns true if the object is marked, false if not.
Definition: grid_impl.hpp:843
AssociatedEdgeIterator associated_edges_end(Vertex *vrt)
DO NOT INVOKE! Subject to change.
Definition: grid.cpp:892
Edge * get_edge(Vertex *v1, Vertex *v2)
returns the edge between v1 and v2, if it exists. Returns NULL if not.
Definition: grid.cpp:1069
void mark(GridObject *obj)
marks the object. Calls are only valid between calls to Grid::begin_marking and Grid::end_marking.
Definition: grid_impl.hpp:773
void begin_marking()
begin marking.
Definition: grid.cpp:1262
FaceContainer::iterator AssociatedFaceIterator
used to iterate over associated faces of vertices, edges and volumes
Definition: grid.h:251
void enable_options(uint options)
see set_options for a description of valid parameters.
Definition: grid.cpp:711
A volume element with 6 quadrilateral sides.
Definition: grid_objects_3d.h:227
A volume element with 2 triangle and 3 quadrilateral sides.
Definition: grid_objects_3d.h:360
A volume element with 4 triangle and 1 quadrilateral sides.
Definition: grid_objects_3d.h:493
the most simple volume-element.
Definition: grid_objects_3d.h:91
Base-class for all vertex-types.
Definition: grid_base_objects.h:231
Volumes are 3-dimensional objects.
Definition: grid_base_objects.h:754
virtual uint num_edges() const
Definition: grid_base_objects.h:782
virtual Vertex * vertex(size_t index) const
Definition: grid_base_objects.h:727
virtual size_t num_vertices() const
Definition: grid_base_objects.h:729
bool FaceContains(Face *f, EdgeVertices *ev)
returns true if the given face contains the two given vertices
Definition: grid_util.cpp:561
UG_API void CollectAssociated(std::vector< Vertex * > &vVertexOut, Grid &grid, GridObject *obj, bool clearContainer=true)
Definition: grid_util_impl.hpp:169
@ GRIDOPT_AUTOGENERATE_SIDES
sides are automatically created
Definition: grid_constants.h:102
#define UG_ASSERT(expr, msg)
Definition: assert.h:70
#define LOG(msg)
Definition: common.h:60
#define UG_API
Definition: ug_config.h:65
unsigned int uint
Definition: types.h:114
double number
Definition: types.h:124
void VecNormalize(vector_t &vOut, const vector_t &v)
scales a vector_t to unit length
Definition: math_vector_functions_common_impl.hpp:501
void VecSubtract(vector_t &vOut, const vector_t &v1, const vector_t &v2)
subtracts v2 from v1 and stores the result in a vOut
Definition: math_vector_functions_common_impl.hpp:226
void VecCross(vector_t &vOut, const vector_t &v1, const vector_t &v2)
calculates the cross product of two Vectors of dimension 3. It makes no sense to use VecCross for vec...
Definition: math_vector_functions_common_impl.hpp:437
vector_t::value_type VecDot(const vector_t &v1, const vector_t &v2)
returns the dot-product of two vector_ts
Definition: math_vector_functions_common_impl.hpp:385
Definition: smart_pointer.h:814
the ug namespace
void CalculateAngles(vector< number > &vAnglesOut, Grid &grid, Volume *v, TAAPosVRT &aaPos)
Volume.
Definition: element_angles.h:695
UG_API void CollectAssociatedSides(Face *sidesOut[2], Grid &grid, Volume *v, Edge *e)
Collects all faces (= 2) which exist in the given volume and which share the given edge.
Definition: element_angles.h:107
const number PI
Definition: math_constants.h:45
TIterator::value_type FindElementWithSmallestMinAngle(Grid &grid, TIterator elementsBegin, TIterator elementsEnd, TAAPosVRT &aaPos)
Definition: element_angles.h:769
number CalculateMinDihedral(Grid &grid, Volume *v, TAAPosVRT &aaPos)
Volume.
Definition: element_angles.h:317
number CalculateMaxAngle(Grid &grid, Volume *vol, TAAPosVRT &aaPos)
Volume.
Definition: element_angles.h:504
number CalculateMaxDihedral(Grid &grid, Volume *v, TAAPosVRT &aaPos)
Volume.
Definition: element_angles.h:541
TIterator::value_type FindElementWithLargestMaxAngle(Grid &grid, TIterator elementsBegin, TIterator elementsEnd, TAAPosVRT &aaPos)
Definition: element_angles.h:803
number CalculateMinAngle(Grid &grid, Volume *vol, TAAPosVRT &aaPos)
Volume.
Definition: element_angles.h:273
T value_type
Definition: sparsematrix_interface.h:2