Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
includeLinks/ShapeQualityMetric.hpp
Go to the documentation of this file.
1 /* *****************************************************************
2  MESQUITE -- The Mesh Quality Improvement Toolkit
3 
4  Copyright 2004 Sandia Corporation and Argonne National
5  Laboratory. Under the terms of Contract DE-AC04-94AL85000
6  with Sandia Corporation, the U.S. Government retains certain
7  rights in this software.
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  (lgpl.txt) along with this library; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 
23  diachin2@llnl.gov, djmelan@sandia.gov, mbrewer@sandia.gov,
24  pknupp@sandia.gov, tleurent@mcs.anl.gov, tmunson@mcs.anl.gov
25 
26  ***************************************************************** */
27 // -*- Mode : c++; tab-width: 3; c-tab-always-indent: t; indent-tabs-mode: nil; c-basic-offset: 3 -*-
28 
38 #ifndef ShapeQualityMetric_hpp
39 #define ShapeQualityMetric_hpp
40 
41 #include "Mesquite.hpp"
42 #include "MsqError.hpp"
43 #include "QualityMetric.hpp"
44 #include "PatchData.hpp"
45 
46 namespace Mesquite
47 {
49  {
54  public:
55 
58  {};
59 
60  protected:
61 
62  //void compute_scalar_weights(int num_scalar_weights, double scalar_weights[], MsqError &err);
63 
65  bool condition_number_2d(Vector3D temp_vec[],size_t v_ind, PatchData &pd,
66  double &fval, MsqError &err);
68  bool condition_number_3d(Vector3D temp_vec[], PatchData &pd, double &fval, MsqError &err);
69 
70  private:
71 
72 
73  };
74 
75  /*
76  //BEGIN INLINE FUNCITONS
77 #undef __FUNC__
78 #define __FUNC__ "ShapeQualityMetric::condition_number_2d"
79  inline bool ShapeQualityMetric::condition_number_2d(Vector3D temp_vec[],
80  size_t v_ind,
81  PatchData &pd,
82  double &fval,
83  MsqError &err)
84  {
85  Vector3D cross_vec=(temp_vec[0]*temp_vec[1]);
86  //If the domain is not set, we assume all elements are valid.
87  //Otherwise, we ensure the surface normal and the cross
88  //vector have generally the same direction.
89  if ( pd.domain_set() ) {
90  Vector3D unit_surf_norm;
91  pd.get_domain_normal_at_vertex(v_ind,true,unit_surf_norm,err);MSQ_CHKERR(err);
92  //if invalid
93  if(unit_surf_norm%cross_vec < 0.0){
94  return false;
95  }
96  }
97 
98  double temp_val=cross_vec.length()*2.0;
99  fval=MSQ_MAX_CAP;
100  if(temp_val>MSQ_MIN){
101  fval=(temp_vec[0].length_squared()+temp_vec[1].length_squared())/
102  temp_val;
103  }
104  //returning true always until surf_normal is avail.
105  return true;
106  }
107  */
108 
110  size_t v_ind,
111  PatchData &pd,
112  double &fval,
113  MsqError &err)
114  {
115  //norm squared of J
116  double term1=temp_vec[0]%temp_vec[0]+temp_vec[1]%temp_vec[1];
117 
118  Vector3D unit_surf_norm;
119  if ( pd.domain_set() ) {
120  pd.get_domain_normal_at_vertex(v_ind,true,unit_surf_norm,err);MSQ_ERRZERO(err);
121  }
122  else {
123  return false;
124  }
125 
126  // det J
127  double temp_var=unit_surf_norm%(temp_vec[0]*temp_vec[1]);
128 
129  double h;
130  double delta=pd.get_barrier_delta(err); MSQ_ERRZERO(err);
131 
132  // Note: technically, we want delta=eta*tau-max
133  // whereas the function above gives delta=eta*alpha-max
134  //
135  // Because the only requirement on eta is eta << 1,
136  // and because tau-max = alpha-max/0.707 we can
137  // ignore the discrepancy
138 
139  if (delta==0) {
140  if (temp_var < MSQ_DBL_MIN ) {
141  return false;
142  }
143  else {
144  h=temp_var;
145  }
146 
147  // Note: when delta=0, the vertex_barrier_function
148  // formally gives h=temp_var as well.
149  // We just do it this way to avoid any
150  // roundoff issues.
151  // Also: when delta=0, this metric is identical
152  // to the original condition number with
153  // the barrier at temp_var=0
154  }
155  else {
156  h = vertex_barrier_function(temp_var,delta);
157 
158  if (h<MSQ_DBL_MIN && fabs(temp_var) > MSQ_DBL_MIN ) {
159  h = delta*delta/fabs(temp_var); }
160  // Note: Analytically, h is strictly positive, but
161  // it can be zero numerically if temp_var
162  // is a large negative number
163  // In the case h=0, we use a different analytic
164  // approximation to compute h.
165  }
166 
167  if (h<MSQ_DBL_MIN) {
168  MSQ_SETERR(err)( "Barrier function is zero due to excessively large "
169  "negative area compared to delta. /n Try to untangle "
170  "mesh another way. ", MsqError::INVALID_MESH);
171  return false;
172  }
173 
174  fval=term1/(2*h);
175 
176  if (fval>MSQ_MAX_CAP) {
177  fval=MSQ_MAX_CAP;
178  }
179  return true;
180 
181  }
182 
183 
184  //} //namespace
185 
187  PatchData &pd,
188  double &fval,
189  MsqError &err)
190  {
191  //norm squared of J
192  double term1=temp_vec[0]%temp_vec[0]+
193  temp_vec[1]%temp_vec[1]+
194  temp_vec[2]%temp_vec[2];
195  //norm squared of adjoint of J
196  double term2=(temp_vec[0]*temp_vec[1])%
197  (temp_vec[0]*temp_vec[1])+
198  (temp_vec[1]*temp_vec[2])%
199  (temp_vec[1]*temp_vec[2])+
200  (temp_vec[2]*temp_vec[0])%
201  (temp_vec[2]*temp_vec[0]);
202  //det of J
203  double temp_var=temp_vec[0]%(temp_vec[1]*temp_vec[2]);
204 
205  double h;
206  double delta=pd.get_barrier_delta(err); MSQ_ERRZERO(err);
207 
208  // Note: technically, we want delta=eta*tau-max
209  // whereas the function above gives delta=eta*alpha-max
210  //
211  // Because the only requirement on eta is eta << 1,
212  // and because tau-max = alpha-max/0.707 we can
213  // ignore the discrepancy
214 
215  if (delta==0) {
216  if (temp_var < MSQ_DBL_MIN ) {
217  return false;
218  }
219  else {
220  h=temp_var;
221  }
222 
223  // Note: when delta=0, the vertex_barrier_function
224  // formally gives h=temp_var as well.
225  // We just do it this way to avoid any
226  // roundoff issues.
227  // Also: when delta=0, this metric is identical
228  // to the original condition number with
229  // the barrier at temp_var=0
230 
231  }
232  else {
233  h = vertex_barrier_function(temp_var,delta);
234 
235  if (h<MSQ_DBL_MIN && fabs(temp_var) > MSQ_DBL_MIN ) {
236  h = delta*delta/fabs(temp_var); }
237 
238  // Note: Analytically, h is strictly positive, but
239  // it can be zero numerically if temp_var
240  // is a large negative number
241  // In the h=0, we use a different analytic
242  // approximation to compute h.
243  }
244  if (h<MSQ_DBL_MIN) {
245  MSQ_SETERR(err)("Barrier function is zero due to excessively large "
246  "negative area compared to delta. /n Try to untangle "
247  "mesh another way. ", MsqError::INVALID_MESH);
248  return false;
249  }
250 
251  fval=sqrt(term1*term2)/(3*h);
252 
253  if (fval>MSQ_MAX_CAP) {
254  fval=MSQ_MAX_CAP;
255  }
256  return true;
257 
258  }
259 
260 
261 } //namespace
262 
263 
264 #endif // ShapeQualityMetric_hpp
bool condition_number_3d(Vector3D temp_vec[], PatchData &pd, double &fval, MsqError &err)
Given the 3-d jacobian matrix, compute the condition number, fval.
#define MSQ_ERRZERO(err)
Return zero/NULL on error.
const double MSQ_DBL_MIN
Definition: Mesquite.hpp:158
const double MSQ_MAX_CAP
Definition: Mesquite.hpp:173
double vertex_barrier_function(double det, double delta)
Escobar Barrier Function for Shape and Other Metrics.
Used to hold the error state and return it to the application.
Base class for concrete quality metrics.
Vector3D is the object that effeciently stores information about about three-deminsional vectors...
double sqrt(double d)
Definition: double.h:73
virtual ~ShapeQualityMetric()
virtual destructor ensures use of polymorphism during destruction
double get_barrier_delta(MsqError &err)
Returns delta based on the minimum and maximum corner determinant over all elements in the patch This...
bool condition_number_2d(Vector3D temp_vec[], size_t v_ind, PatchData &pd, double &fval, MsqError &err)
Given the 2-d jacobian matrix, compute the condition number, fval.
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
void get_domain_normal_at_vertex(size_t vertex_index, bool normalize, Vector3D &surf_norm, MsqError &err)