Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Geometric_Metrics_3.C
Go to the documentation of this file.
1 /* *******************************************************************
2  * Rocstar Simulation Suite *
3  * Copyright@2015, Illinois Rocstar LLC. All rights reserved. *
4  * *
5  * Illinois Rocstar LLC *
6  * Champaign, IL *
7  * www.illinoisrocstar.com *
8  * sales@illinoisrocstar.com *
9  * *
10  * License: See LICENSE file in top level of distribution package or *
11  * http://opensource.org/licenses/NCSA *
12  *********************************************************************/
13 /* *******************************************************************
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
16  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
21  * USE OR OTHER DEALINGS WITH THE SOFTWARE. *
22  *********************************************************************/
23 // $Id: Geometric_Metrics_3.C,v 1.6 2008/12/06 08:45:24 mtcampbe Exp $
24 
35 #include "geometry.h"
36 #include "Geometric_Metrics_3.h"
37 #include <cmath>
38 #include <vector>
39 #include <cassert>
40 #include <iostream>
41 #include <algorithm>
42 
44 
45 using namespace std;
46 
48  _type = type;
49  if (_type == COM::Connectivity::TET4){
50  v.resize(7);
51  v[0]= n[2]-n[1]; v[1]= n[1]-n[2]; v[2]= n[2]-n[0];
52  v[3]= n[1]-n[0]; v[4]= n[3]-n[1]; v[5]= n[3]-n[0];
53  v[6]= n[3]-n[2];
54  }
55  else if (_type == COM::Connectivity::HEX8){
56  v.resize(8);
57  v[0]= n[1]-n[0]; v[1]= n[3]-n[0]; v[2]= n[1]-n[2]; v[3]= n[3]-n[2];
58  v[4]= n[5]-n[1]; v[5]= n[7]-n[3]; v[6]= n[5]-n[4]; v[7]= n[7]-n[4];
59  }
60 }
61 
62 void Geo_Metric_Base_3::initialize(Element_node_enumerator &ene){
63  _type = ene.type();
64  if(ene.type() == COM::Connectivity::TET4){
65  v.resize(7);
66  const std::string nc("nc");
67  Element_node_vectors_k_const<double> n;
68  n.set(ene.pane()->attribute(nc),ene);
69  v[0][0]=n(2,0)-n(1,0); v[0][1]=n(2,1)-n(1,1); v[0][2]=n(2,2)-n(1,2);
70  v[1][0]=n(1,0)-n(2,0); v[1][1]=n(1,1)-n(2,1); v[1][2]=n(1,2)-n(2,2);
71  v[2][0]=n(2,0)-n(0,0); v[2][1]=n(2,1)-n(0,1); v[2][2]=n(2,2)-n(0,2);
72  v[3][0]=n(1,0)-n(0,0); v[3][1]=n(1,1)-n(0,1); v[3][2]=n(1,2)-n(0,2);
73  v[4][0]=n(3,0)-n(1,0); v[4][1]=n(3,1)-n(1,1); v[4][2]=n(3,2)-n(1,2);
74  v[5][0]=n(3,0)-n(0,0); v[5][1]=n(3,1)-n(0,1); v[5][2]=n(3,2)-n(0,2);
75  v[6][0]=n(3,0)-n(2,0); v[6][1]=n(3,1)-n(2,1); v[6][2]=n(3,2)-n(2,2);
76  }
77  else if (ene.type() == COM::Connectivity::HEX8){
78  v.resize(8);
79  const std::string nc("nc");
80  Element_node_vectors_k_const<double> n;
81  n.set(ene.pane()->attribute(nc),ene);
82  v[0][0]=n(1,0)-n(0,0); v[0][1]=n(1,1)-n(0,1); v[0][2]=n(1,2)-n(0,2);
83  v[1][0]=n(3,0)-n(0,0); v[1][1]=n(3,1)-n(0,1); v[1][2]=n(3,2)-n(0,2);
84  v[2][0]=n(1,0)-n(2,0); v[2][1]=n(1,1)-n(2,1); v[2][2]=n(1,2)-n(2,2);
85  v[3][0]=n(3,0)-n(2,0); v[3][1]=n(3,1)-n(2,1); v[3][2]=n(3,2)-n(2,2);
86  v[4][0]=n(5,0)-n(1,0); v[4][1]=n(5,1)-n(1,1); v[4][2]=n(5,2)-n(1,2);
87  v[5][0]=n(7,0)-n(3,0); v[5][1]=n(7,1)-n(3,1); v[5][2]=n(7,2)-n(3,2);
88  v[6][0]=n(5,0)-n(4,0); v[6][1]=n(5,1)-n(4,1); v[6][2]=n(5,2)-n(4,2);
89  v[7][0]=n(7,0)-n(4,0); v[7][1]=n(7,1)-n(4,1); v[7][2]=n(7,2)-n(4,2);
90  }
91  else if (ene.type() == COM::Connectivity::PYRIMID5 ||
92  ene.type() == COM::Connectivity::PRISM6){
93  _type = ene.type();
94  _ene_pane = ene.pane();
95  _ene_i = ene.id();
96  }
97  else COM_assertion_msg(0,"Element type not supported for 3D geometric metrics");
98 }
99 
100 void Geo_Metric_Base_3::compute_angles(double& min, double& max) const{
101  if (_type == COM::Connectivity::TET4){
102  double a12,a13,a14,a23,a24,a34;
103  Vector_3<double> n1,n2,n3,n4;
104  unit_normal(v[2],v[3],n1); unit_normal(v[5],v[2],n2);
105  unit_normal(v[3],v[5],n3); unit_normal(v[0],v[4],n4);
106  a12=f_angle(n1,n2); a13=f_angle(n1,n3); a14=f_angle(n1,n4);
107  a23=f_angle(n2,n3); a24=f_angle(n2,n4); a34=f_angle(n3,n4);
108  min_max6(a12,a13,a14,a23,a24,a34,min,max);
109  }
110  else if (_type == COM::Connectivity::HEX8){
111  double a12,a14,a25,a34,a26,a46,a13,a15,a23,a45,a36,a56;
112  Vector_3<double> n1,n2,n3,n4,n5,n6;
113 
114  unit_normal(v[1],v[0],n1); unit_normal(v[0],v[4],n2);
115  unit_normal(v[4],v[2],n3); unit_normal(v[3],v[5],n4);
116  unit_normal(v[5],v[1],n5); unit_normal(v[6],v[7],n6);
117 
118  a12= f_angle(n1,n2); a13= f_angle(n1,n3); a14= f_angle(n1,n4);
119  a15= f_angle(n1,n5); a25= f_angle(n2,n5); a23= f_angle(n2,n3);
120  a34= f_angle(n3,n4); a45= f_angle(n4,n5); a26= f_angle(n2,n6);
121  a36= f_angle(n3,n6); a46= f_angle(n4,n6); a56= f_angle(n5,n6);
122 
123  min_max12(a12,a15,a34,a36,a13,a25,a45,a46,a14,a23,a26,a56,min,max);
124  }
125  else {
126 
127  const int face_node_lists_pyra[5][8] =
128  { {0,3,2,1,8,7,6,5}, {0,1,4,5,10,9,-1,-1}, {1,2,4,6,11,10,-1,-1},
129  {2,3,4,7,12,11,-1,-1}, {3,0,4,8,9,12,-1,-1}};
130 
131  const int face_node_lists_pris[5][9] =
132  { {0,1,4,3,6,10,12,9,15}, {1,2,5,4,7,11,13,10,16}, {2,0,3,5,8,9,14,11,17},
133  {0,2,1,8,7,6,-1,-1,-1}, {3,4,5,12,13,14,-1,-1,-1}};
134 
135  // Create an element node enumerator for handling this element
136  Element_node_enumerator ene(_ene_pane,
137  _ene_i);
138  // Loop over faces,
139  // a) determining which share an edge and
140  // b) face normals
141 
142  std::vector<Vector_3<double> > fnormals(ene.size_of_faces());
143  Element_node_vectors_k_const<double> n;
144  n.set(ene.pane()->attribute("nc"),ene);
145  // map from edges to faces
146  std::map<std::pair<int,int>,int> e2f;
147  std::map<std::pair<int,int>,int>::iterator e2f_it;
148  // set of adjacent faces
149  std::set<std::pair<int,int> > afs;
150  std::set<std::pair<int,int> >::iterator afs_it;
151  for(int i=0, ni = ene.size_of_faces(); i<ni; ++i){
152 
153  Facet_node_enumerator fne( &ene, i);
154 
155  const int *fn_list = (_type == COM::Connectivity::PYRIMID5) ?
156  face_node_lists_pyra[i] : face_node_lists_pris[i];
157 
158  int i0 = fn_list[0];
159  int i1 = fn_list[1];
160  int i2 = fn_list[2];
161 
162  // Find face normal
163  Vector_3<double> e1,e2;
164  e1[0] = n(i1,0)-n(i0,0);
165  e1[1] = n(i1,1)-n(i0,1);
166  e1[2] = n(i1,2)-n(i0,2);
167  e2[0] = n(i2,0)-n(i1,0);
168  e2[1] = n(i2,1)-n(i1,1);
169  e2[2] = n(i2,2)-n(i1,2);
170  unit_normal(e1,e2,fnormals[i]);
171 
172  for(int j=0, nj = fne.size_of_edges();j<nj;++j){
173 
174  // Loop over the edges of this face.
175  // If we there is a matching edge, store the adjacent
176  // faces.
177  int node_id1 = fne[j],node_id2 = fne[(j+1)%nj];
178  if(node_id1>node_id2)
179  std::swap(node_id1, node_id2);
180  e2f_it = e2f.find(std::make_pair<int,int>(node_id1,node_id2));
181  if(e2f_it != e2f.end()){
182  afs.insert(std::make_pair<int,int>(e2f_it->second,i));
183  e2f.erase(e2f_it);
184  }
185  else{
186  e2f.insert(std::make_pair<std::pair<int,int>,int>(
187  std::make_pair<int,int>(node_id1,node_id2)
188  ,i));
189  }
190  }
191  min = 180.0; max = 0.0;
192  for(afs_it = afs.begin(); afs_it != afs.end(); ++afs_it){
193  int ind1 = afs_it->first;
194  int ind2 = afs_it->second;
195  double angle = f_angle(fnormals[ind1],
196  fnormals[ind2]);
197  min = (angle < min) ? angle : min;
198  max = (angle > max) ? angle : max;
199  }
200  }
201  }
202 }
203 
204 void Geo_Metric_Base_3::compute_aspects(double& R, double& r, double& l) const {
205 
206  // This metric is only defined for tetrahedrons
207  if (_type == COM::Connectivity::TET4){
208 
209  // Use formulas from mathworld to find circumradius (R),
210  // inradius (r), and shortest edge length (l)
211 
212  double a1 = tri_area(v[0],v[2],v[3]);
213  double a2 = tri_area(v[0],v[4],v[6]);
214  double a3 = tri_area(v[2],v[5],v[6]);
215  double a4 = tri_area(v[3],v[4],v[5]);
216  double a_sum = a1+a2+a3+a4;
217 
218 
219  double len_a = edge_length(v[0]);
220  double len_b = edge_length(v[2]);
221  double len_c = edge_length(v[3]);
222  double len_ap = edge_length(v[5]);
223  double len_bp = edge_length(v[4]);
224  double len_cp = edge_length(v[6]);
225 
226  double p1 = len_a * len_ap;
227  double p2 = len_b * len_bp;
228  double p3 = len_c * len_cp;
229  double p_prod = sqrt((p1+p2+p3)*(p1+p2-p3)*(p1-p2+p3)*(p2+p3-p1));
230 
231  double vol = tet_vol(v[5],v[4],v[6]);
232 
233  R= p_prod/(24.0*vol);
234  r = (3.0*vol)/a_sum;
235  l = len_a;
236  if( len_b < l ){ l = len_b;}
237  if( len_c < l ){ l = len_c;}
238  if( len_ap < l ){ l = len_ap;}
239  if( len_bp < l ){ l = len_bp;}
240  if( len_cp < l ){ l = len_cp;}
241  }
242  else{
243  R = 1.0;
244  r = 1.0;
245  l = 1.0;
246  }
247 }
248 
249 void Angle_Metric_3::compute(double atts[]) const {
250  compute_angles(atts[0],atts[1]);
251 }
252 
253 double Angle_Metric_3::maxValue() const {
254 return 180.0;
255 }
256 
257 double Angle_Metric_3::minValue() const {
258 return 0.0;
259 }
260 
261 void Aspect_Metric_3::compute(double atts[]) const {
262  if (_type == COM::Connectivity::HEX8) {
263  atts[0] = -1;
264  atts[1] = -1;
265  }
266  else{
267  double R, r, l;
268  compute_aspects(R,r,l);
269  atts[0] = (r/R)*3.0;
270  atts[1] = (l/R)*.61237243569579447;
271  if(atts[0] > 1.0)
272  atts[0] = 1.0;
273  if(atts[1] > 1.0)
274  atts[0] = 1.0;
275  }
276 }
277 
278 double Aspect_Metric_3::maxValue() const {
279  if (_type == COM::Connectivity::TET4) {
280  return 1.0;
281  }
282  else { return -1.0; }
283 }
284 
285 double Aspect_Metric_3::minValue() const {
286  if (_type == COM::Connectivity::TET4) {
287  return 0.0;
288  }
289  else { return -1.0; }
290 }
291 
293 
294 
295 
296 
297 
298 
void swap(int &a, int &b)
Definition: buildface.cpp:88
void compute_angles(double &min, double &max) const
Compute min and max dihedral angles.
virtual void compute(double atts[]) const
Calculate the metric value on this element.
double maxValue() const
Get the maximum value for this metric.
double minValue() const
Get the minimum value for this metric.
#define COM_assertion_msg(EX, msg)
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
NT p1
3D geometric quality Metric declarations.
double minValue() const
Get the minimum value for this metric.
void compute_aspects(double &R, double &r, double &l) const
Compute circumradius, inradius, and shortest edge length.
double sqrt(double d)
Definition: double.h:73
*********************************************************************Illinois Open Source License ****University of Illinois NCSA **Open Source License University of Illinois All rights reserved ****Developed free of to any person **obtaining a copy of this software and associated documentation to deal with the Software without including without limitation the rights to and or **sell copies of the and to permit persons to whom the **Software is furnished to do subject to the following this list of conditions and the following disclaimers ****Redistributions in binary form must reproduce the above **copyright this list of conditions and the following **disclaimers in the documentation and or other materials **provided with the distribution ****Neither the names of the Center for Simulation of Advanced the University of nor the names of its **contributors may be used to endorse or promote products derived **from this Software without specific prior written permission ****THE SOFTWARE IS PROVIDED AS WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE v
Definition: roccomf90.h:20
double f_angle(Vector_3< double > v1, Vector_3< double >v2)
Compute the angle between two faces.
Definition: geometry.C:72
double maxValue() const
Get the maximum value for this metric.
virtual void compute(double atts[]) const
Calculate the metric value on this element.
blockLoc i
Definition: read.cpp:79
double angle(Vector_3< double > v1, Vector_3< double > v2)
Compute the angle between two vectors.
Definition: geometry.C:61
const NT & n
#define MOP_END_NAMESPACE
Definition: mopbasic.h:29
virtual void initialize(Vector_3< double > n[], int type)
Initialize a 3D Geometric Metric by nodal coords and element type.
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
j indices j
Definition: Indexing.h:6
double tet_vol(const Vector_3< double > &a, const Vector_3< double > &b, const Vector_3< double > &c)
Compute the volume of a tetrahedron given three edges from a point as vectors.
Definition: geometry.C:103
double tri_area(const Vector_3< double > &v1, const Vector_3< double > &v2, const Vector_3< double > &v3)
Compute the area of a triangle defined by its three sides as vectors.
Definition: geometry.C:93
#define MOP_BEGIN_NAMESPACE
Definition: mopbasic.h:28
void min_max12(double a1, double a2, double a3, double a4, double a5, double a6, double a7, double a8, double a9, double a10, double a11, double a12, double &min, double &max)
Find minimum and maximum of 12 numbers.
Definition: geometry.C:53
void int int REAL REAL REAL *z blockDim dim * ni
Definition: read.cpp:77
void unit_normal(const Vector_3< double > &v1, const Vector_3< double > &v2, Vector_3< double > &v3)
Compute the unit vector normal to two input vectors.
Definition: geometry.C:80
void int * nj
Definition: read.cpp:74
double edge_length(const Vector_3< double > &v)
Compute the edge length of a vector.
Definition: geometry.C:89
Geometric helper function header file.
void min_max6(double a1, double a2, double a3, double a4, double a5, double a6, double &min, double &max)
Find minimum and maximum of 6 numbers.
Definition: geometry.C:46